modelfusion 0.35.0 → 0.35.1
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/model-function/generate-structure/fixJson.cjs +168 -56
- package/model-function/generate-structure/fixJson.js +168 -56
- package/model-function/generate-structure/fixJson.test.cjs +59 -3
- package/model-function/generate-structure/fixJson.test.js +59 -3
- package/model-function/generate-structure/streamStructure.d.ts +1 -2
- package/package.json +1 -1
@@ -4,69 +4,121 @@ exports.fixJson = void 0;
|
|
4
4
|
// Implemented as a scanner with additional fixing
|
5
5
|
// that performs a single linear time scan pass over the partial JSON:
|
6
6
|
function fixJson(input) {
|
7
|
-
const stack = ["
|
7
|
+
const stack = ["ROOT"];
|
8
8
|
let lastValidIndex = -1;
|
9
9
|
let literalStart = null;
|
10
|
+
function processValueStart(char, i, swapState) {
|
11
|
+
{
|
12
|
+
switch (char) {
|
13
|
+
case '"': {
|
14
|
+
lastValidIndex = i;
|
15
|
+
stack.pop();
|
16
|
+
stack.push(swapState);
|
17
|
+
stack.push("INSIDE_STRING");
|
18
|
+
break;
|
19
|
+
}
|
20
|
+
case "f":
|
21
|
+
case "t":
|
22
|
+
case "n": {
|
23
|
+
lastValidIndex = i;
|
24
|
+
literalStart = i;
|
25
|
+
stack.pop();
|
26
|
+
stack.push(swapState);
|
27
|
+
stack.push("INSIDE_LITERAL");
|
28
|
+
break;
|
29
|
+
}
|
30
|
+
case "-": {
|
31
|
+
stack.pop();
|
32
|
+
stack.push(swapState);
|
33
|
+
stack.push("INSIDE_NUMBER");
|
34
|
+
break;
|
35
|
+
}
|
36
|
+
case "0":
|
37
|
+
case "1":
|
38
|
+
case "2":
|
39
|
+
case "3":
|
40
|
+
case "4":
|
41
|
+
case "5":
|
42
|
+
case "6":
|
43
|
+
case "7":
|
44
|
+
case "8":
|
45
|
+
case "9": {
|
46
|
+
lastValidIndex = i;
|
47
|
+
stack.pop();
|
48
|
+
stack.push(swapState);
|
49
|
+
stack.push("INSIDE_NUMBER");
|
50
|
+
break;
|
51
|
+
}
|
52
|
+
case "{": {
|
53
|
+
lastValidIndex = i;
|
54
|
+
stack.pop();
|
55
|
+
stack.push(swapState);
|
56
|
+
stack.push("INSIDE_OBJECT_START");
|
57
|
+
break;
|
58
|
+
}
|
59
|
+
case "[": {
|
60
|
+
lastValidIndex = i;
|
61
|
+
stack.pop();
|
62
|
+
stack.push(swapState);
|
63
|
+
stack.push("INSIDE_ARRAY_START");
|
64
|
+
break;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
69
|
+
function processAfterObjectValue(char, i) {
|
70
|
+
switch (char) {
|
71
|
+
case ",": {
|
72
|
+
stack.pop();
|
73
|
+
stack.push("INSIDE_OBJECT_AFTER_COMMA");
|
74
|
+
break;
|
75
|
+
}
|
76
|
+
case "}": {
|
77
|
+
lastValidIndex = i;
|
78
|
+
stack.pop();
|
79
|
+
break;
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
function processAfterArrayValue(char, i) {
|
84
|
+
switch (char) {
|
85
|
+
case ",": {
|
86
|
+
stack.pop();
|
87
|
+
stack.push("INSIDE_ARRAY_AFTER_COMMA");
|
88
|
+
break;
|
89
|
+
}
|
90
|
+
case "]": {
|
91
|
+
lastValidIndex = i;
|
92
|
+
stack.pop();
|
93
|
+
break;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
10
97
|
for (let i = 0; i < input.length; i++) {
|
11
98
|
const char = input[i];
|
12
99
|
const currentState = stack[stack.length - 1];
|
13
100
|
switch (currentState) {
|
14
|
-
case "
|
101
|
+
case "ROOT":
|
102
|
+
processValueStart(char, i, "FINISH");
|
103
|
+
break;
|
104
|
+
case "INSIDE_OBJECT_START": {
|
15
105
|
switch (char) {
|
16
106
|
case '"': {
|
17
|
-
lastValidIndex = i;
|
18
|
-
stack.pop();
|
19
|
-
stack.push("INSIDE_STRING");
|
20
|
-
break;
|
21
|
-
}
|
22
|
-
case "f":
|
23
|
-
case "t":
|
24
|
-
case "n": {
|
25
|
-
lastValidIndex = i;
|
26
|
-
literalStart = i;
|
27
|
-
stack.pop();
|
28
|
-
stack.push("INSIDE_LITERAL");
|
29
|
-
break;
|
30
|
-
}
|
31
|
-
case "-": {
|
32
107
|
stack.pop();
|
33
|
-
stack.push("
|
34
|
-
break;
|
35
|
-
}
|
36
|
-
case "0":
|
37
|
-
case "1":
|
38
|
-
case "2":
|
39
|
-
case "3":
|
40
|
-
case "4":
|
41
|
-
case "5":
|
42
|
-
case "6":
|
43
|
-
case "7":
|
44
|
-
case "8":
|
45
|
-
case "9": {
|
46
|
-
lastValidIndex = i;
|
47
|
-
stack.pop();
|
48
|
-
stack.push("INSIDE_NUMBER");
|
49
|
-
break;
|
50
|
-
}
|
51
|
-
case "{": {
|
52
|
-
lastValidIndex = i;
|
53
|
-
stack.pop();
|
54
|
-
stack.push("INSIDE_OBJECT");
|
108
|
+
stack.push("INSIDE_OBJECT_KEY");
|
55
109
|
break;
|
56
110
|
}
|
57
|
-
case "
|
58
|
-
lastValidIndex = i;
|
111
|
+
case "}": {
|
59
112
|
stack.pop();
|
60
|
-
stack.push("INSIDE_ARRAY");
|
61
|
-
stack.push("BEFORE_VALUE");
|
62
113
|
break;
|
63
114
|
}
|
64
115
|
}
|
65
116
|
break;
|
66
117
|
}
|
67
|
-
case "
|
118
|
+
case "INSIDE_OBJECT_AFTER_COMMA": {
|
68
119
|
switch (char) {
|
69
120
|
case '"': {
|
121
|
+
stack.pop();
|
70
122
|
stack.push("INSIDE_OBJECT_KEY");
|
71
123
|
break;
|
72
124
|
}
|
@@ -77,22 +129,30 @@ function fixJson(input) {
|
|
77
129
|
switch (char) {
|
78
130
|
case '"': {
|
79
131
|
stack.pop();
|
80
|
-
stack.push("
|
132
|
+
stack.push("INSIDE_OBJECT_AFTER_KEY");
|
81
133
|
break;
|
82
134
|
}
|
83
135
|
}
|
84
136
|
break;
|
85
137
|
}
|
86
|
-
case "
|
138
|
+
case "INSIDE_OBJECT_AFTER_KEY": {
|
87
139
|
switch (char) {
|
88
140
|
case ":": {
|
89
141
|
stack.pop();
|
90
|
-
stack.push("
|
142
|
+
stack.push("INSIDE_OBJECT_BEFORE_VALUE");
|
91
143
|
break;
|
92
144
|
}
|
93
145
|
}
|
94
146
|
break;
|
95
147
|
}
|
148
|
+
case "INSIDE_OBJECT_BEFORE_VALUE": {
|
149
|
+
processValueStart(char, i, "INSIDE_OBJECT_AFTER_VALUE");
|
150
|
+
break;
|
151
|
+
}
|
152
|
+
case "INSIDE_OBJECT_AFTER_VALUE": {
|
153
|
+
processAfterObjectValue(char, i);
|
154
|
+
break;
|
155
|
+
}
|
96
156
|
case "INSIDE_STRING": {
|
97
157
|
switch (char) {
|
98
158
|
case '"': {
|
@@ -110,10 +170,31 @@ function fixJson(input) {
|
|
110
170
|
}
|
111
171
|
break;
|
112
172
|
}
|
113
|
-
case "
|
173
|
+
case "INSIDE_ARRAY_START": {
|
174
|
+
switch (char) {
|
175
|
+
case "]": {
|
176
|
+
lastValidIndex = i;
|
177
|
+
stack.pop();
|
178
|
+
break;
|
179
|
+
}
|
180
|
+
default: {
|
181
|
+
lastValidIndex = i;
|
182
|
+
processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
|
183
|
+
break;
|
184
|
+
}
|
185
|
+
}
|
186
|
+
break;
|
187
|
+
}
|
188
|
+
case "INSIDE_ARRAY_AFTER_VALUE": {
|
114
189
|
switch (char) {
|
115
190
|
case ",": {
|
116
|
-
stack.
|
191
|
+
stack.pop();
|
192
|
+
stack.push("INSIDE_ARRAY_AFTER_COMMA");
|
193
|
+
break;
|
194
|
+
}
|
195
|
+
case "]": {
|
196
|
+
lastValidIndex = i;
|
197
|
+
stack.pop();
|
117
198
|
break;
|
118
199
|
}
|
119
200
|
default: {
|
@@ -123,6 +204,10 @@ function fixJson(input) {
|
|
123
204
|
}
|
124
205
|
break;
|
125
206
|
}
|
207
|
+
case "INSIDE_ARRAY_AFTER_COMMA": {
|
208
|
+
processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
|
209
|
+
break;
|
210
|
+
}
|
126
211
|
case "INSIDE_STRING_ESCAPE": {
|
127
212
|
stack.pop();
|
128
213
|
lastValidIndex = i;
|
@@ -151,8 +236,25 @@ function fixJson(input) {
|
|
151
236
|
}
|
152
237
|
case ",": {
|
153
238
|
stack.pop();
|
154
|
-
if (stack[stack.length - 1] === "
|
155
|
-
|
239
|
+
if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
240
|
+
processAfterArrayValue(char, i);
|
241
|
+
}
|
242
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
243
|
+
processAfterObjectValue(char, i);
|
244
|
+
}
|
245
|
+
break;
|
246
|
+
}
|
247
|
+
case "}": {
|
248
|
+
stack.pop();
|
249
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
250
|
+
processAfterObjectValue(char, i);
|
251
|
+
}
|
252
|
+
break;
|
253
|
+
}
|
254
|
+
case "]": {
|
255
|
+
stack.pop();
|
256
|
+
if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
257
|
+
processAfterArrayValue(char, i);
|
156
258
|
}
|
157
259
|
break;
|
158
260
|
}
|
@@ -164,13 +266,16 @@ function fixJson(input) {
|
|
164
266
|
break;
|
165
267
|
}
|
166
268
|
case "INSIDE_LITERAL": {
|
167
|
-
const partialLiteral = input.substring(literalStart, i);
|
269
|
+
const partialLiteral = input.substring(literalStart, i + 1);
|
168
270
|
if (!"false".startsWith(partialLiteral) &&
|
169
271
|
!"true".startsWith(partialLiteral) &&
|
170
272
|
!"null".startsWith(partialLiteral)) {
|
171
273
|
stack.pop();
|
172
|
-
if (stack[stack.length - 1] === "
|
173
|
-
|
274
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
275
|
+
processAfterObjectValue(char, i);
|
276
|
+
}
|
277
|
+
else if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
278
|
+
processAfterArrayValue(char, i);
|
174
279
|
}
|
175
280
|
}
|
176
281
|
else {
|
@@ -188,11 +293,18 @@ function fixJson(input) {
|
|
188
293
|
result += '"';
|
189
294
|
break;
|
190
295
|
}
|
191
|
-
case "
|
296
|
+
case "INSIDE_OBJECT_KEY":
|
297
|
+
case "INSIDE_OBJECT_AFTER_KEY":
|
298
|
+
case "INSIDE_OBJECT_AFTER_COMMA":
|
299
|
+
case "INSIDE_OBJECT_START":
|
300
|
+
case "INSIDE_OBJECT_BEFORE_VALUE":
|
301
|
+
case "INSIDE_OBJECT_AFTER_VALUE": {
|
192
302
|
result += "}";
|
193
303
|
break;
|
194
304
|
}
|
195
|
-
case "
|
305
|
+
case "INSIDE_ARRAY_START":
|
306
|
+
case "INSIDE_ARRAY_AFTER_COMMA":
|
307
|
+
case "INSIDE_ARRAY_AFTER_VALUE": {
|
196
308
|
result += "]";
|
197
309
|
break;
|
198
310
|
}
|
@@ -1,69 +1,121 @@
|
|
1
1
|
// Implemented as a scanner with additional fixing
|
2
2
|
// that performs a single linear time scan pass over the partial JSON:
|
3
3
|
export function fixJson(input) {
|
4
|
-
const stack = ["
|
4
|
+
const stack = ["ROOT"];
|
5
5
|
let lastValidIndex = -1;
|
6
6
|
let literalStart = null;
|
7
|
+
function processValueStart(char, i, swapState) {
|
8
|
+
{
|
9
|
+
switch (char) {
|
10
|
+
case '"': {
|
11
|
+
lastValidIndex = i;
|
12
|
+
stack.pop();
|
13
|
+
stack.push(swapState);
|
14
|
+
stack.push("INSIDE_STRING");
|
15
|
+
break;
|
16
|
+
}
|
17
|
+
case "f":
|
18
|
+
case "t":
|
19
|
+
case "n": {
|
20
|
+
lastValidIndex = i;
|
21
|
+
literalStart = i;
|
22
|
+
stack.pop();
|
23
|
+
stack.push(swapState);
|
24
|
+
stack.push("INSIDE_LITERAL");
|
25
|
+
break;
|
26
|
+
}
|
27
|
+
case "-": {
|
28
|
+
stack.pop();
|
29
|
+
stack.push(swapState);
|
30
|
+
stack.push("INSIDE_NUMBER");
|
31
|
+
break;
|
32
|
+
}
|
33
|
+
case "0":
|
34
|
+
case "1":
|
35
|
+
case "2":
|
36
|
+
case "3":
|
37
|
+
case "4":
|
38
|
+
case "5":
|
39
|
+
case "6":
|
40
|
+
case "7":
|
41
|
+
case "8":
|
42
|
+
case "9": {
|
43
|
+
lastValidIndex = i;
|
44
|
+
stack.pop();
|
45
|
+
stack.push(swapState);
|
46
|
+
stack.push("INSIDE_NUMBER");
|
47
|
+
break;
|
48
|
+
}
|
49
|
+
case "{": {
|
50
|
+
lastValidIndex = i;
|
51
|
+
stack.pop();
|
52
|
+
stack.push(swapState);
|
53
|
+
stack.push("INSIDE_OBJECT_START");
|
54
|
+
break;
|
55
|
+
}
|
56
|
+
case "[": {
|
57
|
+
lastValidIndex = i;
|
58
|
+
stack.pop();
|
59
|
+
stack.push(swapState);
|
60
|
+
stack.push("INSIDE_ARRAY_START");
|
61
|
+
break;
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
function processAfterObjectValue(char, i) {
|
67
|
+
switch (char) {
|
68
|
+
case ",": {
|
69
|
+
stack.pop();
|
70
|
+
stack.push("INSIDE_OBJECT_AFTER_COMMA");
|
71
|
+
break;
|
72
|
+
}
|
73
|
+
case "}": {
|
74
|
+
lastValidIndex = i;
|
75
|
+
stack.pop();
|
76
|
+
break;
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
function processAfterArrayValue(char, i) {
|
81
|
+
switch (char) {
|
82
|
+
case ",": {
|
83
|
+
stack.pop();
|
84
|
+
stack.push("INSIDE_ARRAY_AFTER_COMMA");
|
85
|
+
break;
|
86
|
+
}
|
87
|
+
case "]": {
|
88
|
+
lastValidIndex = i;
|
89
|
+
stack.pop();
|
90
|
+
break;
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
7
94
|
for (let i = 0; i < input.length; i++) {
|
8
95
|
const char = input[i];
|
9
96
|
const currentState = stack[stack.length - 1];
|
10
97
|
switch (currentState) {
|
11
|
-
case "
|
98
|
+
case "ROOT":
|
99
|
+
processValueStart(char, i, "FINISH");
|
100
|
+
break;
|
101
|
+
case "INSIDE_OBJECT_START": {
|
12
102
|
switch (char) {
|
13
103
|
case '"': {
|
14
|
-
lastValidIndex = i;
|
15
|
-
stack.pop();
|
16
|
-
stack.push("INSIDE_STRING");
|
17
|
-
break;
|
18
|
-
}
|
19
|
-
case "f":
|
20
|
-
case "t":
|
21
|
-
case "n": {
|
22
|
-
lastValidIndex = i;
|
23
|
-
literalStart = i;
|
24
|
-
stack.pop();
|
25
|
-
stack.push("INSIDE_LITERAL");
|
26
|
-
break;
|
27
|
-
}
|
28
|
-
case "-": {
|
29
104
|
stack.pop();
|
30
|
-
stack.push("
|
31
|
-
break;
|
32
|
-
}
|
33
|
-
case "0":
|
34
|
-
case "1":
|
35
|
-
case "2":
|
36
|
-
case "3":
|
37
|
-
case "4":
|
38
|
-
case "5":
|
39
|
-
case "6":
|
40
|
-
case "7":
|
41
|
-
case "8":
|
42
|
-
case "9": {
|
43
|
-
lastValidIndex = i;
|
44
|
-
stack.pop();
|
45
|
-
stack.push("INSIDE_NUMBER");
|
46
|
-
break;
|
47
|
-
}
|
48
|
-
case "{": {
|
49
|
-
lastValidIndex = i;
|
50
|
-
stack.pop();
|
51
|
-
stack.push("INSIDE_OBJECT");
|
105
|
+
stack.push("INSIDE_OBJECT_KEY");
|
52
106
|
break;
|
53
107
|
}
|
54
|
-
case "
|
55
|
-
lastValidIndex = i;
|
108
|
+
case "}": {
|
56
109
|
stack.pop();
|
57
|
-
stack.push("INSIDE_ARRAY");
|
58
|
-
stack.push("BEFORE_VALUE");
|
59
110
|
break;
|
60
111
|
}
|
61
112
|
}
|
62
113
|
break;
|
63
114
|
}
|
64
|
-
case "
|
115
|
+
case "INSIDE_OBJECT_AFTER_COMMA": {
|
65
116
|
switch (char) {
|
66
117
|
case '"': {
|
118
|
+
stack.pop();
|
67
119
|
stack.push("INSIDE_OBJECT_KEY");
|
68
120
|
break;
|
69
121
|
}
|
@@ -74,22 +126,30 @@ export function fixJson(input) {
|
|
74
126
|
switch (char) {
|
75
127
|
case '"': {
|
76
128
|
stack.pop();
|
77
|
-
stack.push("
|
129
|
+
stack.push("INSIDE_OBJECT_AFTER_KEY");
|
78
130
|
break;
|
79
131
|
}
|
80
132
|
}
|
81
133
|
break;
|
82
134
|
}
|
83
|
-
case "
|
135
|
+
case "INSIDE_OBJECT_AFTER_KEY": {
|
84
136
|
switch (char) {
|
85
137
|
case ":": {
|
86
138
|
stack.pop();
|
87
|
-
stack.push("
|
139
|
+
stack.push("INSIDE_OBJECT_BEFORE_VALUE");
|
88
140
|
break;
|
89
141
|
}
|
90
142
|
}
|
91
143
|
break;
|
92
144
|
}
|
145
|
+
case "INSIDE_OBJECT_BEFORE_VALUE": {
|
146
|
+
processValueStart(char, i, "INSIDE_OBJECT_AFTER_VALUE");
|
147
|
+
break;
|
148
|
+
}
|
149
|
+
case "INSIDE_OBJECT_AFTER_VALUE": {
|
150
|
+
processAfterObjectValue(char, i);
|
151
|
+
break;
|
152
|
+
}
|
93
153
|
case "INSIDE_STRING": {
|
94
154
|
switch (char) {
|
95
155
|
case '"': {
|
@@ -107,10 +167,31 @@ export function fixJson(input) {
|
|
107
167
|
}
|
108
168
|
break;
|
109
169
|
}
|
110
|
-
case "
|
170
|
+
case "INSIDE_ARRAY_START": {
|
171
|
+
switch (char) {
|
172
|
+
case "]": {
|
173
|
+
lastValidIndex = i;
|
174
|
+
stack.pop();
|
175
|
+
break;
|
176
|
+
}
|
177
|
+
default: {
|
178
|
+
lastValidIndex = i;
|
179
|
+
processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
|
180
|
+
break;
|
181
|
+
}
|
182
|
+
}
|
183
|
+
break;
|
184
|
+
}
|
185
|
+
case "INSIDE_ARRAY_AFTER_VALUE": {
|
111
186
|
switch (char) {
|
112
187
|
case ",": {
|
113
|
-
stack.
|
188
|
+
stack.pop();
|
189
|
+
stack.push("INSIDE_ARRAY_AFTER_COMMA");
|
190
|
+
break;
|
191
|
+
}
|
192
|
+
case "]": {
|
193
|
+
lastValidIndex = i;
|
194
|
+
stack.pop();
|
114
195
|
break;
|
115
196
|
}
|
116
197
|
default: {
|
@@ -120,6 +201,10 @@ export function fixJson(input) {
|
|
120
201
|
}
|
121
202
|
break;
|
122
203
|
}
|
204
|
+
case "INSIDE_ARRAY_AFTER_COMMA": {
|
205
|
+
processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
|
206
|
+
break;
|
207
|
+
}
|
123
208
|
case "INSIDE_STRING_ESCAPE": {
|
124
209
|
stack.pop();
|
125
210
|
lastValidIndex = i;
|
@@ -148,8 +233,25 @@ export function fixJson(input) {
|
|
148
233
|
}
|
149
234
|
case ",": {
|
150
235
|
stack.pop();
|
151
|
-
if (stack[stack.length - 1] === "
|
152
|
-
|
236
|
+
if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
237
|
+
processAfterArrayValue(char, i);
|
238
|
+
}
|
239
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
240
|
+
processAfterObjectValue(char, i);
|
241
|
+
}
|
242
|
+
break;
|
243
|
+
}
|
244
|
+
case "}": {
|
245
|
+
stack.pop();
|
246
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
247
|
+
processAfterObjectValue(char, i);
|
248
|
+
}
|
249
|
+
break;
|
250
|
+
}
|
251
|
+
case "]": {
|
252
|
+
stack.pop();
|
253
|
+
if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
254
|
+
processAfterArrayValue(char, i);
|
153
255
|
}
|
154
256
|
break;
|
155
257
|
}
|
@@ -161,13 +263,16 @@ export function fixJson(input) {
|
|
161
263
|
break;
|
162
264
|
}
|
163
265
|
case "INSIDE_LITERAL": {
|
164
|
-
const partialLiteral = input.substring(literalStart, i);
|
266
|
+
const partialLiteral = input.substring(literalStart, i + 1);
|
165
267
|
if (!"false".startsWith(partialLiteral) &&
|
166
268
|
!"true".startsWith(partialLiteral) &&
|
167
269
|
!"null".startsWith(partialLiteral)) {
|
168
270
|
stack.pop();
|
169
|
-
if (stack[stack.length - 1] === "
|
170
|
-
|
271
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
272
|
+
processAfterObjectValue(char, i);
|
273
|
+
}
|
274
|
+
else if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
275
|
+
processAfterArrayValue(char, i);
|
171
276
|
}
|
172
277
|
}
|
173
278
|
else {
|
@@ -185,11 +290,18 @@ export function fixJson(input) {
|
|
185
290
|
result += '"';
|
186
291
|
break;
|
187
292
|
}
|
188
|
-
case "
|
293
|
+
case "INSIDE_OBJECT_KEY":
|
294
|
+
case "INSIDE_OBJECT_AFTER_KEY":
|
295
|
+
case "INSIDE_OBJECT_AFTER_COMMA":
|
296
|
+
case "INSIDE_OBJECT_START":
|
297
|
+
case "INSIDE_OBJECT_BEFORE_VALUE":
|
298
|
+
case "INSIDE_OBJECT_AFTER_VALUE": {
|
189
299
|
result += "}";
|
190
300
|
break;
|
191
301
|
}
|
192
|
-
case "
|
302
|
+
case "INSIDE_ARRAY_START":
|
303
|
+
case "INSIDE_ARRAY_AFTER_COMMA":
|
304
|
+
case "INSIDE_ARRAY_AFTER_VALUE": {
|
193
305
|
result += "]";
|
194
306
|
break;
|
195
307
|
}
|
@@ -66,19 +66,46 @@ const fixJson_1 = require("./fixJson");
|
|
66
66
|
(0, vitest_1.test)("should handle incomplete array", () => {
|
67
67
|
(0, vitest_1.expect)((0, fixJson_1.fixJson)("[")).toBe("[]");
|
68
68
|
});
|
69
|
+
(0, vitest_1.test)("should handle closing bracket after number in array", () => {
|
70
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)("[[1], [2")).toBe("[[1], [2]]");
|
71
|
+
});
|
72
|
+
(0, vitest_1.test)("should handle closing bracket after string in array", () => {
|
73
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)(`[["1"], ["2`)).toBe(`[["1"], ["2"]]`);
|
74
|
+
});
|
75
|
+
(0, vitest_1.test)("should handle closing bracket after literal in array", () => {
|
76
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)("[[false], [nu")).toBe("[[false], [null]]");
|
77
|
+
});
|
78
|
+
(0, vitest_1.test)("should handle closing bracket after array in array", () => {
|
79
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)("[[[]], [[]")).toBe("[[[]], [[]]]");
|
80
|
+
});
|
81
|
+
(0, vitest_1.test)("should handle closing bracket after object in array", () => {
|
82
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)("[[{}], [{")).toBe("[[{}], [{}]]");
|
83
|
+
});
|
69
84
|
(0, vitest_1.test)("should handle trailing comma", () => {
|
70
85
|
(0, vitest_1.expect)((0, fixJson_1.fixJson)("[1, ")).toBe("[1]");
|
71
86
|
});
|
72
87
|
(0, vitest_1.test)("should handle closing array", () => {
|
73
|
-
(0, vitest_1.expect)((0, fixJson_1.fixJson)(
|
88
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)("[[], 123")).toBe("[[], 123]");
|
74
89
|
});
|
75
90
|
});
|
76
91
|
(0, vitest_1.describe)("object", () => {
|
77
92
|
(0, vitest_1.test)("should handle keys without values", () => {
|
78
93
|
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"key":')).toBe("{}");
|
79
94
|
});
|
80
|
-
(0, vitest_1.test)("should handle closing brace in object", () => {
|
81
|
-
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"a": {"b": 1}')).toBe('{"a": {"b": 1}}');
|
95
|
+
(0, vitest_1.test)("should handle closing brace after number in object", () => {
|
96
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"a": {"b": 1}, "c": {"d": 2')).toBe('{"a": {"b": 1}, "c": {"d": 2}}');
|
97
|
+
});
|
98
|
+
(0, vitest_1.test)("should handle closing brace after string in object", () => {
|
99
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"a": {"b": "1"}, "c": {"d": 2')).toBe('{"a": {"b": "1"}, "c": {"d": 2}}');
|
100
|
+
});
|
101
|
+
(0, vitest_1.test)("should handle closing brace after literal in object", () => {
|
102
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"a": {"b": false}, "c": {"d": 2')).toBe('{"a": {"b": false}, "c": {"d": 2}}');
|
103
|
+
});
|
104
|
+
(0, vitest_1.test)("should handle closing brace after array in object", () => {
|
105
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"a": {"b": []}, "c": {"d": 2')).toBe('{"a": {"b": []}, "c": {"d": 2}}');
|
106
|
+
});
|
107
|
+
(0, vitest_1.test)("should handle closing brace after object in object", () => {
|
108
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"a": {"b": {}}, "c": {"d": 2')).toBe('{"a": {"b": {}}, "c": {"d": 2}}');
|
82
109
|
});
|
83
110
|
(0, vitest_1.test)("should handle partial keys (first key)", () => {
|
84
111
|
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"ke')).toBe("{}");
|
@@ -127,4 +154,33 @@ const fixJson_1 = require("./fixJson");
|
|
127
154
|
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"a": 1, "b": "')).toBe('{"a": 1, "b": ""}');
|
128
155
|
});
|
129
156
|
});
|
157
|
+
(0, vitest_1.describe)("regression", () => {
|
158
|
+
(0, vitest_1.test)("should handle complex nesting 1", () => {
|
159
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)([
|
160
|
+
"{",
|
161
|
+
' "a": [',
|
162
|
+
" {",
|
163
|
+
' "a1": "v1",',
|
164
|
+
' "a2": "v2",',
|
165
|
+
` "a3": "v3"`,
|
166
|
+
" }",
|
167
|
+
" ],",
|
168
|
+
' "b": [',
|
169
|
+
" {",
|
170
|
+
' "b1": "n',
|
171
|
+
].join("\n"))).toBe([
|
172
|
+
"{",
|
173
|
+
' "a": [',
|
174
|
+
" {",
|
175
|
+
' "a1": "v1",',
|
176
|
+
' "a2": "v2",',
|
177
|
+
` "a3": "v3"`,
|
178
|
+
" }",
|
179
|
+
" ],",
|
180
|
+
' "b": [',
|
181
|
+
" {",
|
182
|
+
' "b1": "n"}]}',
|
183
|
+
].join("\n"));
|
184
|
+
});
|
185
|
+
});
|
130
186
|
});
|
@@ -64,19 +64,46 @@ describe("fixJson", () => {
|
|
64
64
|
test("should handle incomplete array", () => {
|
65
65
|
expect(fixJson("[")).toBe("[]");
|
66
66
|
});
|
67
|
+
test("should handle closing bracket after number in array", () => {
|
68
|
+
expect(fixJson("[[1], [2")).toBe("[[1], [2]]");
|
69
|
+
});
|
70
|
+
test("should handle closing bracket after string in array", () => {
|
71
|
+
expect(fixJson(`[["1"], ["2`)).toBe(`[["1"], ["2"]]`);
|
72
|
+
});
|
73
|
+
test("should handle closing bracket after literal in array", () => {
|
74
|
+
expect(fixJson("[[false], [nu")).toBe("[[false], [null]]");
|
75
|
+
});
|
76
|
+
test("should handle closing bracket after array in array", () => {
|
77
|
+
expect(fixJson("[[[]], [[]")).toBe("[[[]], [[]]]");
|
78
|
+
});
|
79
|
+
test("should handle closing bracket after object in array", () => {
|
80
|
+
expect(fixJson("[[{}], [{")).toBe("[[{}], [{}]]");
|
81
|
+
});
|
67
82
|
test("should handle trailing comma", () => {
|
68
83
|
expect(fixJson("[1, ")).toBe("[1]");
|
69
84
|
});
|
70
85
|
test("should handle closing array", () => {
|
71
|
-
expect(fixJson(
|
86
|
+
expect(fixJson("[[], 123")).toBe("[[], 123]");
|
72
87
|
});
|
73
88
|
});
|
74
89
|
describe("object", () => {
|
75
90
|
test("should handle keys without values", () => {
|
76
91
|
expect(fixJson('{"key":')).toBe("{}");
|
77
92
|
});
|
78
|
-
test("should handle closing brace in object", () => {
|
79
|
-
expect(fixJson('{"a": {"b": 1}')).toBe('{"a": {"b": 1}}');
|
93
|
+
test("should handle closing brace after number in object", () => {
|
94
|
+
expect(fixJson('{"a": {"b": 1}, "c": {"d": 2')).toBe('{"a": {"b": 1}, "c": {"d": 2}}');
|
95
|
+
});
|
96
|
+
test("should handle closing brace after string in object", () => {
|
97
|
+
expect(fixJson('{"a": {"b": "1"}, "c": {"d": 2')).toBe('{"a": {"b": "1"}, "c": {"d": 2}}');
|
98
|
+
});
|
99
|
+
test("should handle closing brace after literal in object", () => {
|
100
|
+
expect(fixJson('{"a": {"b": false}, "c": {"d": 2')).toBe('{"a": {"b": false}, "c": {"d": 2}}');
|
101
|
+
});
|
102
|
+
test("should handle closing brace after array in object", () => {
|
103
|
+
expect(fixJson('{"a": {"b": []}, "c": {"d": 2')).toBe('{"a": {"b": []}, "c": {"d": 2}}');
|
104
|
+
});
|
105
|
+
test("should handle closing brace after object in object", () => {
|
106
|
+
expect(fixJson('{"a": {"b": {}}, "c": {"d": 2')).toBe('{"a": {"b": {}}, "c": {"d": 2}}');
|
80
107
|
});
|
81
108
|
test("should handle partial keys (first key)", () => {
|
82
109
|
expect(fixJson('{"ke')).toBe("{}");
|
@@ -125,4 +152,33 @@ describe("fixJson", () => {
|
|
125
152
|
expect(fixJson('{"a": 1, "b": "')).toBe('{"a": 1, "b": ""}');
|
126
153
|
});
|
127
154
|
});
|
155
|
+
describe("regression", () => {
|
156
|
+
test("should handle complex nesting 1", () => {
|
157
|
+
expect(fixJson([
|
158
|
+
"{",
|
159
|
+
' "a": [',
|
160
|
+
" {",
|
161
|
+
' "a1": "v1",',
|
162
|
+
' "a2": "v2",',
|
163
|
+
` "a3": "v3"`,
|
164
|
+
" }",
|
165
|
+
" ],",
|
166
|
+
' "b": [',
|
167
|
+
" {",
|
168
|
+
' "b1": "n',
|
169
|
+
].join("\n"))).toBe([
|
170
|
+
"{",
|
171
|
+
' "a": [',
|
172
|
+
" {",
|
173
|
+
' "a1": "v1",',
|
174
|
+
' "a2": "v2",',
|
175
|
+
` "a3": "v3"`,
|
176
|
+
" }",
|
177
|
+
" ],",
|
178
|
+
' "b": [',
|
179
|
+
" {",
|
180
|
+
' "b1": "n"}]}',
|
181
|
+
].join("\n"));
|
182
|
+
});
|
183
|
+
});
|
128
184
|
});
|
@@ -3,7 +3,7 @@ import { AsyncIterableResultPromise } from "../AsyncIterableResultPromise.js";
|
|
3
3
|
import { DeltaEvent } from "../DeltaEvent.js";
|
4
4
|
import { ModelFunctionOptions } from "../ModelFunctionOptions.js";
|
5
5
|
import { StructureGenerationModel, StructureGenerationModelSettings } from "./StructureGenerationModel.js";
|
6
|
-
type StructureStreamPart<STRUCTURE> = {
|
6
|
+
export type StructureStreamPart<STRUCTURE> = {
|
7
7
|
isComplete: false;
|
8
8
|
value: unknown;
|
9
9
|
} | {
|
@@ -14,4 +14,3 @@ export declare function streamStructure<STRUCTURE, PROMPT, FULL_DELTA, NAME exte
|
|
14
14
|
generateStructureStreamResponse: (structureDefinition: StructureDefinition<NAME, STRUCTURE>, prompt: PROMPT, options: ModelFunctionOptions<SETTINGS>) => PromiseLike<AsyncIterable<DeltaEvent<FULL_DELTA>>>;
|
15
15
|
extractPartialStructure: (fullDelta: FULL_DELTA) => unknown | undefined;
|
16
16
|
}, structureDefinition: StructureDefinition<NAME, STRUCTURE>, prompt: PROMPT, options?: ModelFunctionOptions<SETTINGS>): AsyncIterableResultPromise<StructureStreamPart<STRUCTURE>>;
|
17
|
-
export {};
|
package/package.json
CHANGED