@ag-ui/encoder 0.0.27 → 0.0.28-alpha.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/package.json +3 -3
- package/.turbo/turbo-build.log +0 -23
- package/jest.config.js +0 -6
- package/src/__tests__/encoder.test.ts +0 -101
- package/src/encoder.ts +0 -69
- package/src/index.ts +0 -2
- package/src/media-type.ts +0 -305
- package/tsconfig.json +0 -23
- package/tsup.config.ts +0 -10
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ag-ui/encoder",
|
|
3
3
|
"author": "Markus Ecker <markus.ecker@gmail.com>",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.28-alpha.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"module": "./dist/index.mjs",
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@ag-ui/core": "0.0.
|
|
14
|
-
"@ag-ui/proto": "0.0.
|
|
13
|
+
"@ag-ui/core": "0.0.28-alpha.0",
|
|
14
|
+
"@ag-ui/proto": "0.0.28-alpha.0"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"@types/jest": "^29.5.12",
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
> @ag-ui/encoder@0.0.27 build /Users/mme/Code/ag-ui-protocol/typescript-sdk/packages/encoder
|
|
4
|
-
> tsup
|
|
5
|
-
|
|
6
|
-
[34mCLI[39m Building entry: src/index.ts
|
|
7
|
-
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
8
|
-
[34mCLI[39m tsup v8.4.0
|
|
9
|
-
[34mCLI[39m Using tsup config: /Users/mme/Code/ag-ui-protocol/typescript-sdk/packages/encoder/tsup.config.ts
|
|
10
|
-
[34mCLI[39m Target: es2017
|
|
11
|
-
[34mCLI[39m Cleaning output folder
|
|
12
|
-
[34mCJS[39m Build start
|
|
13
|
-
[34mESM[39m Build start
|
|
14
|
-
[32mCJS[39m [1mdist/index.js [22m[32m7.09 KB[39m
|
|
15
|
-
[32mCJS[39m [1mdist/index.js.map [22m[32m13.37 KB[39m
|
|
16
|
-
[32mCJS[39m ⚡️ Build success in 8ms
|
|
17
|
-
[32mESM[39m [1mdist/index.mjs [22m[32m5.49 KB[39m
|
|
18
|
-
[32mESM[39m [1mdist/index.mjs.map [22m[32m13.34 KB[39m
|
|
19
|
-
[32mESM[39m ⚡️ Build success in 8ms
|
|
20
|
-
DTS Build start
|
|
21
|
-
DTS ⚡️ Build success in 652ms
|
|
22
|
-
DTS dist/index.d.ts 540.00 B
|
|
23
|
-
DTS dist/index.d.mts 540.00 B
|
package/jest.config.js
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { EventEncoder } from "../encoder";
|
|
2
|
-
import { BaseEvent, EventType, TextMessageStartEvent } from "@ag-ui/core";
|
|
3
|
-
import * as proto from "@ag-ui/proto";
|
|
4
|
-
|
|
5
|
-
describe("Encoder Tests", () => {
|
|
6
|
-
// Create a valid TextMessageStartEvent event
|
|
7
|
-
const testEvent: TextMessageStartEvent = {
|
|
8
|
-
type: EventType.TEXT_MESSAGE_START,
|
|
9
|
-
timestamp: 123456789,
|
|
10
|
-
messageId: "msg123",
|
|
11
|
-
role: "assistant",
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
describe("encodeBinary method", () => {
|
|
15
|
-
it("should return protobuf encoded data when accept header includes protobuf media type", () => {
|
|
16
|
-
// Setup an encoder with protobuf accepted
|
|
17
|
-
const encoder = new EventEncoder({
|
|
18
|
-
accept: `text/event-stream, ${proto.AGUI_MEDIA_TYPE}`,
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
// Get the binary encoding
|
|
22
|
-
const result = encoder.encodeBinary(testEvent);
|
|
23
|
-
|
|
24
|
-
// Verify it's a Uint8Array
|
|
25
|
-
expect(result).toBeInstanceOf(Uint8Array);
|
|
26
|
-
|
|
27
|
-
// A protobuf message should start with 4 bytes for length followed by the message
|
|
28
|
-
// So the length should be greater than 4 at minimum
|
|
29
|
-
expect(result.length).toBeGreaterThan(4);
|
|
30
|
-
|
|
31
|
-
// The first 4 bytes should be a uint32 representing the message length
|
|
32
|
-
const dataView = new DataView(result.buffer);
|
|
33
|
-
const messageLength = dataView.getUint32(0, false); // false for big-endian
|
|
34
|
-
|
|
35
|
-
// The actual message should match the length specified in the header
|
|
36
|
-
expect(result.length - 4).toBe(messageLength);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it("should return SSE encoded data when accept header doesn't include protobuf media type", () => {
|
|
40
|
-
// Setup an encoder without protobuf accepted
|
|
41
|
-
const encoder = new EventEncoder({
|
|
42
|
-
accept: "text/event-stream",
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// Get the binary encoding
|
|
46
|
-
const result = encoder.encodeBinary(testEvent);
|
|
47
|
-
|
|
48
|
-
// Verify it's a Uint8Array
|
|
49
|
-
expect(result).toBeInstanceOf(Uint8Array);
|
|
50
|
-
|
|
51
|
-
// Convert back to string to verify it's SSE format
|
|
52
|
-
const decoder = new TextDecoder();
|
|
53
|
-
const resultString = decoder.decode(result);
|
|
54
|
-
|
|
55
|
-
// Should match the SSE format with the expected JSON
|
|
56
|
-
expect(resultString).toBe(`data: ${JSON.stringify(testEvent)}\n\n`);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("should return SSE encoded data when no accept header is provided", () => {
|
|
60
|
-
// Setup an encoder without any accept header
|
|
61
|
-
const encoder = new EventEncoder();
|
|
62
|
-
|
|
63
|
-
// Get the binary encoding
|
|
64
|
-
const result = encoder.encodeBinary(testEvent);
|
|
65
|
-
|
|
66
|
-
// Verify it's a Uint8Array
|
|
67
|
-
expect(result).toBeInstanceOf(Uint8Array);
|
|
68
|
-
|
|
69
|
-
// Convert back to string to verify it's SSE format
|
|
70
|
-
const decoder = new TextDecoder();
|
|
71
|
-
const resultString = decoder.decode(result);
|
|
72
|
-
|
|
73
|
-
// Should match the SSE format with the expected JSON
|
|
74
|
-
expect(resultString).toBe(`data: ${JSON.stringify(testEvent)}\n\n`);
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
describe("encodeProtobuf method", () => {
|
|
79
|
-
it("should encode event as protobuf with length prefix", () => {
|
|
80
|
-
const encoder = new EventEncoder();
|
|
81
|
-
|
|
82
|
-
const result = encoder.encodeProtobuf(testEvent);
|
|
83
|
-
|
|
84
|
-
// Verify it's a Uint8Array
|
|
85
|
-
expect(result).toBeInstanceOf(Uint8Array);
|
|
86
|
-
|
|
87
|
-
// A protobuf message should start with 4 bytes for length followed by the message
|
|
88
|
-
expect(result.length).toBeGreaterThan(4);
|
|
89
|
-
|
|
90
|
-
// The first 4 bytes should be a uint32 representing the message length
|
|
91
|
-
const dataView = new DataView(result.buffer);
|
|
92
|
-
const messageLength = dataView.getUint32(0, false); // false for big-endian
|
|
93
|
-
|
|
94
|
-
// The actual message should match the length specified in the header
|
|
95
|
-
expect(result.length - 4).toBe(messageLength);
|
|
96
|
-
|
|
97
|
-
// The message length should be greater than zero
|
|
98
|
-
expect(messageLength).toBeGreaterThan(0);
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
});
|
package/src/encoder.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { BaseEvent } from "@ag-ui/core";
|
|
2
|
-
import * as proto from "@ag-ui/proto";
|
|
3
|
-
import { preferredMediaTypes } from "./media-type";
|
|
4
|
-
|
|
5
|
-
export interface EventEncoderParams {
|
|
6
|
-
accept?: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export class EventEncoder {
|
|
10
|
-
private acceptsProtobuf: boolean;
|
|
11
|
-
|
|
12
|
-
constructor(params?: EventEncoderParams) {
|
|
13
|
-
this.acceptsProtobuf = params?.accept ? this.isProtobufAccepted(params.accept) : false;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
getContentType(): string {
|
|
17
|
-
if (this.acceptsProtobuf) {
|
|
18
|
-
return proto.AGUI_MEDIA_TYPE;
|
|
19
|
-
} else {
|
|
20
|
-
return "text/event-stream";
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
encode(event: BaseEvent): string {
|
|
25
|
-
return this.encodeSSE(event);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
encodeSSE(event: BaseEvent): string {
|
|
29
|
-
return `data: ${JSON.stringify(event)}\n\n`;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
encodeBinary(event: BaseEvent): Uint8Array {
|
|
33
|
-
if (this.acceptsProtobuf) {
|
|
34
|
-
return this.encodeProtobuf(event);
|
|
35
|
-
} else {
|
|
36
|
-
const sseString = this.encodeSSE(event);
|
|
37
|
-
// Convert string to Uint8Array using TextEncoder
|
|
38
|
-
const encoder = new TextEncoder();
|
|
39
|
-
return encoder.encode(sseString);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
encodeProtobuf(event: BaseEvent): Uint8Array {
|
|
44
|
-
const messageBytes = proto.encode(event);
|
|
45
|
-
const length = messageBytes.length;
|
|
46
|
-
|
|
47
|
-
// Create a buffer for 4 bytes (for the uint32 length) plus the message bytes
|
|
48
|
-
const buffer = new ArrayBuffer(4 + length);
|
|
49
|
-
const dataView = new DataView(buffer);
|
|
50
|
-
|
|
51
|
-
// Write the length as a uint32
|
|
52
|
-
// Set the third parameter to `false` for big-endian or `true` for little-endian
|
|
53
|
-
dataView.setUint32(0, length, false);
|
|
54
|
-
|
|
55
|
-
// Create a Uint8Array view and copy in the message bytes after the 4-byte header
|
|
56
|
-
const result = new Uint8Array(buffer);
|
|
57
|
-
result.set(messageBytes, 4);
|
|
58
|
-
|
|
59
|
-
return result;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
private isProtobufAccepted(acceptHeader: string): boolean {
|
|
63
|
-
// Pass the Accept header and an array with your media type
|
|
64
|
-
const preferred = preferredMediaTypes(acceptHeader, [proto.AGUI_MEDIA_TYPE]);
|
|
65
|
-
|
|
66
|
-
// If the returned array includes your media type, it's acceptable
|
|
67
|
-
return preferred.includes(proto.AGUI_MEDIA_TYPE);
|
|
68
|
-
}
|
|
69
|
-
}
|
package/src/index.ts
DELETED
package/src/media-type.ts
DELETED
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* negotiator
|
|
3
|
-
* Copyright(c) 2012 Isaac Z. Schlueter
|
|
4
|
-
* Copyright(c) 2014 Federico Romero
|
|
5
|
-
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
|
6
|
-
* MIT Licensed
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
// modified from https://github.com/jshttp/negotiator/blob/master/lib/mediaType.js
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Module exports.
|
|
13
|
-
* @public
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
export function preferredMediaTypes(accept?: string, provided?: string[]): string[] {
|
|
17
|
-
// RFC 2616 sec 14.2: no header = */*
|
|
18
|
-
const accepts = parseAccept(accept === undefined ? "*/*" : accept || "");
|
|
19
|
-
|
|
20
|
-
if (!provided) {
|
|
21
|
-
// sorted list of all types
|
|
22
|
-
return accepts
|
|
23
|
-
.filter((spec): spec is MediaType => spec.q > 0)
|
|
24
|
-
.sort((a, b) => {
|
|
25
|
-
return b.q - a.q || b.i - a.i || 0;
|
|
26
|
-
})
|
|
27
|
-
.map(getFullType);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const priorities = provided.map(function getPriority(type: string, index: number) {
|
|
31
|
-
return getMediaTypePriority(type, accepts, index);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
// sorted list of accepted types
|
|
35
|
-
return priorities
|
|
36
|
-
.filter((spec): spec is Priority => spec.q > 0)
|
|
37
|
-
.sort(compareSpecs)
|
|
38
|
-
.map(function getType(priority: Priority) {
|
|
39
|
-
return provided[priorities.indexOf(priority)];
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Module variables.
|
|
45
|
-
* @private
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
|
-
const simpleMediaTypeRegExp = /^\s*([^\s\/;]+)\/([^;\s]+)\s*(?:;(.*))?$/;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Media type interface
|
|
52
|
-
* @private
|
|
53
|
-
*/
|
|
54
|
-
interface MediaType {
|
|
55
|
-
type: string;
|
|
56
|
-
subtype: string;
|
|
57
|
-
params: Record<string, string>;
|
|
58
|
-
q: number;
|
|
59
|
-
i: number;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Priority interface
|
|
64
|
-
* @private
|
|
65
|
-
*/
|
|
66
|
-
interface Priority {
|
|
67
|
-
o: number;
|
|
68
|
-
q: number;
|
|
69
|
-
s: number;
|
|
70
|
-
i?: number;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Parse the Accept header.
|
|
75
|
-
* @private
|
|
76
|
-
*/
|
|
77
|
-
function parseAccept(accept: string): MediaType[] {
|
|
78
|
-
const accepts = splitMediaTypes(accept);
|
|
79
|
-
const result: MediaType[] = [];
|
|
80
|
-
|
|
81
|
-
for (let i = 0, j = 0; i < accepts.length; i++) {
|
|
82
|
-
const mediaType = parseMediaType(accepts[i].trim(), i);
|
|
83
|
-
|
|
84
|
-
if (mediaType) {
|
|
85
|
-
result[j++] = mediaType;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return result;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Parse a media type from the Accept header.
|
|
94
|
-
* @private
|
|
95
|
-
*/
|
|
96
|
-
function parseMediaType(str: string, i: number): MediaType | null {
|
|
97
|
-
const match = simpleMediaTypeRegExp.exec(str);
|
|
98
|
-
if (!match) return null;
|
|
99
|
-
|
|
100
|
-
const params: Record<string, string> = Object.create(null);
|
|
101
|
-
let q = 1;
|
|
102
|
-
const subtype = match[2];
|
|
103
|
-
const type = match[1];
|
|
104
|
-
|
|
105
|
-
if (match[3]) {
|
|
106
|
-
const kvps = splitParameters(match[3]).map(splitKeyValuePair);
|
|
107
|
-
|
|
108
|
-
for (let j = 0; j < kvps.length; j++) {
|
|
109
|
-
const pair = kvps[j];
|
|
110
|
-
const key = pair[0].toLowerCase();
|
|
111
|
-
const val = pair[1];
|
|
112
|
-
|
|
113
|
-
// get the value, unwrapping quotes
|
|
114
|
-
const value = val && val[0] === '"' && val[val.length - 1] === '"' ? val.slice(1, -1) : val;
|
|
115
|
-
|
|
116
|
-
if (key === "q") {
|
|
117
|
-
q = parseFloat(value);
|
|
118
|
-
break;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// store parameter
|
|
122
|
-
params[key] = value;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return {
|
|
127
|
-
type: type,
|
|
128
|
-
subtype: subtype,
|
|
129
|
-
params: params,
|
|
130
|
-
q: q,
|
|
131
|
-
i: i,
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Get the priority of a media type.
|
|
137
|
-
* @private
|
|
138
|
-
*/
|
|
139
|
-
function getMediaTypePriority(type: string, accepted: MediaType[], index: number): Priority {
|
|
140
|
-
const priority: Priority = { o: -1, q: 0, s: 0 };
|
|
141
|
-
|
|
142
|
-
for (let i = 0; i < accepted.length; i++) {
|
|
143
|
-
const spec = specify(type, accepted[i], index);
|
|
144
|
-
|
|
145
|
-
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
|
146
|
-
priority.o = spec.o;
|
|
147
|
-
priority.q = spec.q;
|
|
148
|
-
priority.s = spec.s;
|
|
149
|
-
priority.i = spec.i;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return priority;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Get the specificity of the media type.
|
|
158
|
-
* @private
|
|
159
|
-
*/
|
|
160
|
-
function specify(type: string, spec: MediaType, index: number): Priority | null {
|
|
161
|
-
const p = parseMediaType(type, 0);
|
|
162
|
-
let s = 0;
|
|
163
|
-
|
|
164
|
-
if (!p) {
|
|
165
|
-
return null;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (spec.type.toLowerCase() == p.type.toLowerCase()) {
|
|
169
|
-
s |= 4;
|
|
170
|
-
} else if (spec.type != "*") {
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (spec.subtype.toLowerCase() == p.subtype.toLowerCase()) {
|
|
175
|
-
s |= 2;
|
|
176
|
-
} else if (spec.subtype != "*") {
|
|
177
|
-
return null;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const keys = Object.keys(spec.params);
|
|
181
|
-
if (keys.length > 0) {
|
|
182
|
-
if (
|
|
183
|
-
keys.every(function (k) {
|
|
184
|
-
return (
|
|
185
|
-
spec.params[k] == "*" ||
|
|
186
|
-
(spec.params[k] || "").toLowerCase() == (p.params[k] || "").toLowerCase()
|
|
187
|
-
);
|
|
188
|
-
})
|
|
189
|
-
) {
|
|
190
|
-
s |= 1;
|
|
191
|
-
} else {
|
|
192
|
-
return null;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return {
|
|
197
|
-
i: index,
|
|
198
|
-
o: spec.i,
|
|
199
|
-
q: spec.q,
|
|
200
|
-
s: s,
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Compare two specs.
|
|
206
|
-
* @private
|
|
207
|
-
*/
|
|
208
|
-
function compareSpecs(a: Priority, b: Priority): number {
|
|
209
|
-
return b.q - a.q || b.s - a.s || (a.o || 0) - (b.o || 0) || (a.i || 0) - (b.i || 0) || 0;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Get full type string.
|
|
214
|
-
* @private
|
|
215
|
-
*/
|
|
216
|
-
function getFullType(spec: MediaType): string {
|
|
217
|
-
return spec.type + "/" + spec.subtype;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Check if a spec has any quality.
|
|
222
|
-
* @private
|
|
223
|
-
*/
|
|
224
|
-
function isQuality(spec: Priority | MediaType): boolean {
|
|
225
|
-
return spec.q > 0;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Count the number of quotes in a string.
|
|
230
|
-
* @private
|
|
231
|
-
*/
|
|
232
|
-
function quoteCount(string: string): number {
|
|
233
|
-
let count = 0;
|
|
234
|
-
let index = 0;
|
|
235
|
-
|
|
236
|
-
while ((index = string.indexOf('"', index)) !== -1) {
|
|
237
|
-
count++;
|
|
238
|
-
index++;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
return count;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Split a key value pair.
|
|
246
|
-
* @private
|
|
247
|
-
*/
|
|
248
|
-
function splitKeyValuePair(str: string): [string, string] {
|
|
249
|
-
const index = str.indexOf("=");
|
|
250
|
-
let key: string;
|
|
251
|
-
let val: string = "";
|
|
252
|
-
|
|
253
|
-
if (index === -1) {
|
|
254
|
-
key = str;
|
|
255
|
-
} else {
|
|
256
|
-
key = str.slice(0, index);
|
|
257
|
-
val = str.slice(index + 1);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
return [key, val];
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Split an Accept header into media types.
|
|
265
|
-
* @private
|
|
266
|
-
*/
|
|
267
|
-
function splitMediaTypes(accept: string): string[] {
|
|
268
|
-
const accepts = accept.split(",");
|
|
269
|
-
const result: string[] = [accepts[0]];
|
|
270
|
-
|
|
271
|
-
for (let i = 1, j = 0; i < accepts.length; i++) {
|
|
272
|
-
if (quoteCount(result[j]) % 2 == 0) {
|
|
273
|
-
result[++j] = accepts[i];
|
|
274
|
-
} else {
|
|
275
|
-
result[j] += "," + accepts[i];
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// trim result
|
|
280
|
-
return result;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Split a string of parameters.
|
|
285
|
-
* @private
|
|
286
|
-
*/
|
|
287
|
-
function splitParameters(str: string): string[] {
|
|
288
|
-
const parameters = str.split(";");
|
|
289
|
-
const result: string[] = [parameters[0]];
|
|
290
|
-
|
|
291
|
-
for (let i = 1, j = 0; i < parameters.length; i++) {
|
|
292
|
-
if (quoteCount(result[j]) % 2 == 0) {
|
|
293
|
-
result[++j] = parameters[i];
|
|
294
|
-
} else {
|
|
295
|
-
result[j] += ";" + parameters[i];
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// trim parameters
|
|
300
|
-
for (let i = 0; i < result.length; i++) {
|
|
301
|
-
result[i] = result[i].trim();
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
return result;
|
|
305
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es2017",
|
|
4
|
-
"module": "esnext",
|
|
5
|
-
"lib": ["dom", "dom.iterable", "esnext"],
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"declarationMap": true,
|
|
8
|
-
"sourceMap": true,
|
|
9
|
-
"moduleResolution": "node",
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"strict": true,
|
|
12
|
-
"jsx": "react-jsx",
|
|
13
|
-
"esModuleInterop": true,
|
|
14
|
-
"resolveJsonModule": true,
|
|
15
|
-
"isolatedModules": true,
|
|
16
|
-
"baseUrl": ".",
|
|
17
|
-
"paths": {
|
|
18
|
-
"@/*": ["./src/*"]
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
"include": ["src"],
|
|
22
|
-
"exclude": ["node_modules", "dist"]
|
|
23
|
-
}
|