@standardserver/core 0.0.10 → 0.0.12

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.
@@ -31,6 +31,7 @@ declare function decodeEventStreamMessage(encoded: string): EventStreamMessage;
31
31
  declare class EventStreamDecoder {
32
32
  private readonly onEvent;
33
33
  private incomplete;
34
+ private trailingCR;
34
35
  constructor(onEvent: (event: EventStreamMessage) => void);
35
36
  feed(chunk: string): void;
36
37
  end(): void;
@@ -31,6 +31,7 @@ declare function decodeEventStreamMessage(encoded: string): EventStreamMessage;
31
31
  declare class EventStreamDecoder {
32
32
  private readonly onEvent;
33
33
  private incomplete;
34
+ private trailingCR;
34
35
  constructor(onEvent: (event: EventStreamMessage) => void);
35
36
  feed(chunk: string): void;
36
37
  end(): void;
@@ -11,13 +11,16 @@ class EventIteratorErrorEvent extends Error {
11
11
  }
12
12
  }
13
13
 
14
+ const EVENT_STREAM_LINE_DELIMITER_REGEX = /\r\n|[\n\r]/;
15
+ const EVENT_STREAM_DELIMITER_REGEX = /(?:\r\n|\r(?!\n)|\n)(?:\r\n|\r(?!\n)|\n)/;
16
+ const LEADING_WHITESPACE_REGEX = /^\s/;
14
17
  function decodeEventStreamMessage(encoded) {
15
- const lines = encoded.replace(/\n+$/, "").split(/\n/);
18
+ const lines = encoded.split(EVENT_STREAM_LINE_DELIMITER_REGEX);
16
19
  const message = {};
17
20
  for (const line of lines) {
18
21
  const index = line.indexOf(":");
19
22
  const key = index === -1 ? line : line.slice(0, index);
20
- const value = index === -1 ? "" : line.slice(index + 1).replace(/^\s/, "");
23
+ const value = index === -1 ? "" : line.slice(index + 1).replace(LEADING_WHITESPACE_REGEX, "");
21
24
  if (index === 0) {
22
25
  message.comments ??= [];
23
26
  message.comments.push(value);
@@ -46,18 +49,17 @@ class EventStreamDecoder {
46
49
  this.onEvent = onEvent;
47
50
  }
48
51
  incomplete = "";
52
+ trailingCR = false;
49
53
  feed(chunk) {
50
- this.incomplete += chunk;
51
- const lastCompleteIndex = this.incomplete.lastIndexOf("\n\n");
52
- if (lastCompleteIndex === -1) {
53
- return;
54
+ if (this.trailingCR && chunk.startsWith("\n")) {
55
+ chunk = chunk.slice(1);
54
56
  }
55
- const completes = this.incomplete.slice(0, lastCompleteIndex).split(/\n\n/);
56
- this.incomplete = this.incomplete.slice(lastCompleteIndex + 2);
57
- for (const encoded of completes) {
58
- const message = decodeEventStreamMessage(`${encoded}
59
-
60
- `);
57
+ this.trailingCR = chunk.endsWith("\r");
58
+ this.incomplete += chunk;
59
+ const parts = this.incomplete.split(EVENT_STREAM_DELIMITER_REGEX);
60
+ this.incomplete = parts.pop();
61
+ for (const encoded of parts) {
62
+ const message = decodeEventStreamMessage(encoded);
61
63
  this.onEvent(message);
62
64
  }
63
65
  }
@@ -86,14 +88,18 @@ class EventStreamDecoderStream extends TransformStream {
86
88
  }
87
89
  }
88
90
 
91
+ const EVENT_STREAM_LINE_ENDING_REGEX = /\r\n|[\n\r]/;
92
+ function containsEventStreamLineBreak(value) {
93
+ return EVENT_STREAM_LINE_ENDING_REGEX.test(value);
94
+ }
89
95
  function assertEventStreamMessageId(id) {
90
- if (id.includes("\n")) {
91
- throw new EventStreamEncoderError("Event's id must not contain a newline character");
96
+ if (containsEventStreamLineBreak(id)) {
97
+ throw new EventStreamEncoderError("Event's id must not contain a carriage return or newline character");
92
98
  }
93
99
  }
94
100
  function assertEventStreamMessageName(event) {
95
- if (event.includes("\n")) {
96
- throw new EventStreamEncoderError("Event's event must not contain a newline character");
101
+ if (containsEventStreamLineBreak(event)) {
102
+ throw new EventStreamEncoderError("Event's event must not contain a carriage return or newline character");
97
103
  }
98
104
  }
99
105
  function assertEventStreamMessageRetry(retry) {
@@ -102,16 +108,18 @@ function assertEventStreamMessageRetry(retry) {
102
108
  }
103
109
  }
104
110
  function assertEventStreamMessageComment(comment) {
105
- if (comment.includes("\n")) {
106
- throw new EventStreamEncoderError("Event's comment must not contain a newline character");
111
+ if (containsEventStreamLineBreak(comment)) {
112
+ throw new EventStreamEncoderError("Event's comment must not contain a carriage return or newline character");
107
113
  }
108
114
  }
109
115
  function encodeEventStreamMessageData(data) {
110
- const lines = data?.split(/\n/) ?? [];
111
116
  let output = "";
112
- for (const line of lines) {
113
- output += `data: ${line}
117
+ if (data !== void 0) {
118
+ const lines = data.split(EVENT_STREAM_LINE_ENDING_REGEX);
119
+ for (const line of lines) {
120
+ output += `data: ${line}
114
121
  `;
122
+ }
115
123
  }
116
124
  return output;
117
125
  }
package/dist/index.d.mts CHANGED
@@ -21,7 +21,7 @@ interface StandardRequest {
21
21
  /**
22
22
  * The body has been parsed based on the content headers.
23
23
  */
24
- body?: StandardBody | undefined;
24
+ body: StandardBody | undefined;
25
25
  /**
26
26
  * An AbortSignal to communicate aborting of request.
27
27
  */
@@ -50,7 +50,7 @@ interface StandardResponse {
50
50
  /**
51
51
  * The body has been parsed based on the content headers.
52
52
  */
53
- body?: StandardBody | undefined;
53
+ body: StandardBody | undefined;
54
54
  }
55
55
  interface StandardLazyResponse extends Omit<StandardResponse, 'body'> {
56
56
  /**
package/dist/index.d.ts CHANGED
@@ -21,7 +21,7 @@ interface StandardRequest {
21
21
  /**
22
22
  * The body has been parsed based on the content headers.
23
23
  */
24
- body?: StandardBody | undefined;
24
+ body: StandardBody | undefined;
25
25
  /**
26
26
  * An AbortSignal to communicate aborting of request.
27
27
  */
@@ -50,7 +50,7 @@ interface StandardResponse {
50
50
  /**
51
51
  * The body has been parsed based on the content headers.
52
52
  */
53
- body?: StandardBody | undefined;
53
+ body: StandardBody | undefined;
54
54
  }
55
55
  interface StandardLazyResponse extends Omit<StandardResponse, 'body'> {
56
56
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@standardserver/core",
3
3
  "type": "module",
4
- "version": "0.0.10",
4
+ "version": "0.0.12",
5
5
  "license": "MIT",
6
6
  "homepage": "https://standardserver.dev",
7
7
  "repository": {
@@ -9,6 +9,7 @@
9
9
  "url": "git+https://github.com/standardserver/standardserver.git",
10
10
  "directory": "packages/core"
11
11
  },
12
+ "sideEffects": false,
12
13
  "exports": {
13
14
  ".": {
14
15
  "types": "./dist/index.d.mts",
@@ -25,7 +26,7 @@
25
26
  "dist"
26
27
  ],
27
28
  "dependencies": {
28
- "@standardserver/shared": "0.0.10"
29
+ "@standardserver/shared": "0.0.12"
29
30
  },
30
31
  "scripts": {
31
32
  "build": "unbuild",