@orpc/standard-server 1.14.10 → 1.14.13
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.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.mjs +88 -40
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -19,7 +19,9 @@ interface EventDecoderOptions {
|
|
|
19
19
|
}
|
|
20
20
|
declare class EventDecoder {
|
|
21
21
|
private options;
|
|
22
|
-
private
|
|
22
|
+
private pending;
|
|
23
|
+
private tail;
|
|
24
|
+
private discardLeadingLF;
|
|
23
25
|
constructor(options?: EventDecoderOptions);
|
|
24
26
|
feed(chunk: string): void;
|
|
25
27
|
end(): void;
|
package/dist/index.d.ts
CHANGED
|
@@ -19,7 +19,9 @@ interface EventDecoderOptions {
|
|
|
19
19
|
}
|
|
20
20
|
declare class EventDecoder {
|
|
21
21
|
private options;
|
|
22
|
-
private
|
|
22
|
+
private pending;
|
|
23
|
+
private tail;
|
|
24
|
+
private discardLeadingLF;
|
|
23
25
|
constructor(options?: EventDecoderOptions);
|
|
24
26
|
feed(chunk: string): void;
|
|
25
27
|
end(): void;
|
package/dist/index.mjs
CHANGED
|
@@ -12,8 +12,13 @@ class ErrorEvent extends Error {
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
const LINE_ENDING_REGEX$1 = /\r\n|\r(?!\n)|\n/;
|
|
16
|
+
const MESSAGE_DELIMITER_REGEX = /(?:\r\n|\r(?!\n)|\n){2}/;
|
|
17
|
+
const MESSAGE_DELIMITER_GLOBAL_REGEX = /(?:\r\n|\r(?!\n)|\n){2}/g;
|
|
18
|
+
const CR = 13;
|
|
19
|
+
const LF = 10;
|
|
20
|
+
const SPACE = 32;
|
|
15
21
|
function decodeEventMessage(encoded) {
|
|
16
|
-
const lines = encoded.replace(/\n+$/, "").split(/\n/);
|
|
17
22
|
const message = {
|
|
18
23
|
data: void 0,
|
|
19
24
|
event: void 0,
|
|
@@ -21,54 +26,94 @@ function decodeEventMessage(encoded) {
|
|
|
21
26
|
retry: void 0,
|
|
22
27
|
comments: []
|
|
23
28
|
};
|
|
24
|
-
for (const line of
|
|
29
|
+
for (const line of encoded.split(LINE_ENDING_REGEX$1)) {
|
|
30
|
+
if (line === "") {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
25
33
|
const index = line.indexOf(":");
|
|
26
|
-
const
|
|
27
|
-
const value = index === -1 ? "" : line.slice(index + 1).replace(/^\s/, "");
|
|
34
|
+
const value = index === -1 ? "" : line.slice(line.charCodeAt(index + 1) === SPACE ? index + 2 : index + 1);
|
|
28
35
|
if (index === 0) {
|
|
29
36
|
message.comments.push(value);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
message.
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
switch (index === -1 ? line : line.slice(0, index)) {
|
|
40
|
+
case "data":
|
|
41
|
+
message.data = message.data === void 0 ? value : `${message.data}
|
|
42
|
+
${value}`;
|
|
43
|
+
break;
|
|
44
|
+
case "event":
|
|
45
|
+
message.event = value;
|
|
46
|
+
break;
|
|
47
|
+
case "id":
|
|
48
|
+
message.id = value;
|
|
49
|
+
break;
|
|
50
|
+
case "retry": {
|
|
51
|
+
const maybeInteger = Number.parseInt(value, 10);
|
|
52
|
+
if (maybeInteger >= 0 && maybeInteger.toString() === value) {
|
|
53
|
+
message.retry = maybeInteger;
|
|
54
|
+
}
|
|
55
|
+
break;
|
|
42
56
|
}
|
|
43
57
|
}
|
|
44
58
|
}
|
|
45
|
-
message.data = message.data?.replace(/\n$/, "");
|
|
46
59
|
return message;
|
|
47
60
|
}
|
|
48
61
|
class EventDecoder {
|
|
49
62
|
constructor(options = {}) {
|
|
50
63
|
this.options = options;
|
|
51
64
|
}
|
|
52
|
-
|
|
65
|
+
pending = [];
|
|
66
|
+
// Last up-to-3 characters of the pending buffer, prefixed to the next chunk
|
|
67
|
+
// so a delimiter straddling the boundary is still found.
|
|
68
|
+
tail = "";
|
|
69
|
+
// Set when a chunk-ending '\r' was already consumed as a line ending, so a
|
|
70
|
+
// leading '\n' in the next chunk is the second half of that CRLF pair.
|
|
71
|
+
discardLeadingLF = false;
|
|
53
72
|
feed(chunk) {
|
|
54
|
-
|
|
55
|
-
const lastCompleteIndex = this.incomplete.lastIndexOf("\n\n");
|
|
56
|
-
if (lastCompleteIndex === -1) {
|
|
73
|
+
if (chunk === "") {
|
|
57
74
|
return;
|
|
58
75
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
76
|
+
if (this.discardLeadingLF) {
|
|
77
|
+
this.discardLeadingLF = false;
|
|
78
|
+
if (chunk.charCodeAt(0) === LF) {
|
|
79
|
+
chunk = chunk.slice(1);
|
|
80
|
+
if (chunk === "") {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const scan = this.tail + chunk;
|
|
86
|
+
if (!MESSAGE_DELIMITER_REGEX.test(scan)) {
|
|
87
|
+
this.pending.push(chunk);
|
|
88
|
+
this.tail = scan.slice(-3);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.pending.push(chunk);
|
|
92
|
+
const buffered = this.pending.length === 1 ? chunk : this.pending.join("");
|
|
93
|
+
const offset = buffered.length - scan.length;
|
|
94
|
+
const parts = [];
|
|
95
|
+
let start = 0;
|
|
96
|
+
for (const match of scan.matchAll(MESSAGE_DELIMITER_GLOBAL_REGEX)) {
|
|
97
|
+
parts.push(buffered.slice(start, offset + match.index));
|
|
98
|
+
start = offset + match.index + match[0].length;
|
|
99
|
+
}
|
|
100
|
+
const incomplete = buffered.slice(start);
|
|
101
|
+
this.pending.length = 0;
|
|
102
|
+
this.tail = incomplete.slice(-3);
|
|
103
|
+
if (incomplete === "") {
|
|
104
|
+
this.discardLeadingLF = chunk.charCodeAt(chunk.length - 1) === CR;
|
|
105
|
+
} else {
|
|
106
|
+
this.pending.push(incomplete);
|
|
107
|
+
}
|
|
108
|
+
for (const encoded of parts) {
|
|
109
|
+
const message = decodeEventMessage(encoded);
|
|
65
110
|
if (this.options.onEvent) {
|
|
66
111
|
this.options.onEvent(message);
|
|
67
112
|
}
|
|
68
113
|
}
|
|
69
114
|
}
|
|
70
115
|
end() {
|
|
71
|
-
if (this.
|
|
116
|
+
if (this.pending.length !== 0) {
|
|
72
117
|
throw new EventDecoderError("Event Iterator ended before complete");
|
|
73
118
|
}
|
|
74
119
|
}
|
|
@@ -94,14 +139,19 @@ class EventDecoderStream extends TransformStream {
|
|
|
94
139
|
}
|
|
95
140
|
}
|
|
96
141
|
|
|
142
|
+
const LINE_ENDING_REGEX = /\r\n|[\n\r]/;
|
|
143
|
+
const LINE_ENDING_GLOBAL_REGEX = /\r\n|[\n\r]/g;
|
|
144
|
+
function containsLineBreak(value) {
|
|
145
|
+
return LINE_ENDING_REGEX.test(value);
|
|
146
|
+
}
|
|
97
147
|
function assertEventId(id) {
|
|
98
|
-
if (id
|
|
99
|
-
throw new EventEncoderError("Event's id must not contain a newline character");
|
|
148
|
+
if (containsLineBreak(id)) {
|
|
149
|
+
throw new EventEncoderError("Event's id must not contain a carriage return or newline character");
|
|
100
150
|
}
|
|
101
151
|
}
|
|
102
152
|
function assertEventName(event) {
|
|
103
|
-
if (event
|
|
104
|
-
throw new EventEncoderError("Event's event must not contain a newline character");
|
|
153
|
+
if (containsLineBreak(event)) {
|
|
154
|
+
throw new EventEncoderError("Event's event must not contain a carriage return or newline character");
|
|
105
155
|
}
|
|
106
156
|
}
|
|
107
157
|
function assertEventRetry(retry) {
|
|
@@ -110,18 +160,16 @@ function assertEventRetry(retry) {
|
|
|
110
160
|
}
|
|
111
161
|
}
|
|
112
162
|
function assertEventComment(comment) {
|
|
113
|
-
if (comment
|
|
114
|
-
throw new EventEncoderError("Event's comment must not contain a newline character");
|
|
163
|
+
if (containsLineBreak(comment)) {
|
|
164
|
+
throw new EventEncoderError("Event's comment must not contain a carriage return or newline character");
|
|
115
165
|
}
|
|
116
166
|
}
|
|
117
167
|
function encodeEventData(data) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
for (const line of lines) {
|
|
121
|
-
output += `data: ${line}
|
|
122
|
-
`;
|
|
168
|
+
if (data === void 0) {
|
|
169
|
+
return "";
|
|
123
170
|
}
|
|
124
|
-
return
|
|
171
|
+
return `data: ${data.replace(LINE_ENDING_GLOBAL_REGEX, "\ndata: ")}
|
|
172
|
+
`;
|
|
125
173
|
}
|
|
126
174
|
function encodeEventComments(comments) {
|
|
127
175
|
let output = "";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orpc/standard-server",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.14.
|
|
4
|
+
"version": "1.14.13",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://orpc.dev",
|
|
7
7
|
"repository": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"dist"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@orpc/shared": "1.14.
|
|
32
|
+
"@orpc/shared": "1.14.13"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
35
|
"build": "unbuild",
|