@ahoo-wang/fetcher-eventstream 0.1.5 → 0.2.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/README.md CHANGED
@@ -15,8 +15,6 @@ Support for text/event-stream in Fetcher, enabling Server-Sent Events (SSE) func
15
15
  - **SSE Parsing**: Parses Server-Sent Events according to the specification, including data, event, id, and retry fields
16
16
  - **Streaming Support**: Handles chunked data and multi-line events correctly
17
17
  - **Comment Handling**: Properly ignores comment lines (lines starting with `:`) as per SSE specification
18
- - **Event ID Tracking**: Maintains last event ID for automatic reconnection
19
- - **Retry Management**: Handles retry timeout values for connection reattempts
20
18
  - **TypeScript Support**: Complete TypeScript type definitions
21
19
 
22
20
  ## Installation
@@ -66,11 +64,11 @@ if (response.eventStream) {
66
64
  ### Manual Conversion
67
65
 
68
66
  ```typescript
69
- import { EventStreamConverter } from '@ahoo-wang/fetcher-eventstream';
67
+ import { toServerSentEventStream } from '@ahoo-wang/fetcher-eventstream';
70
68
 
71
69
  // Convert a Response object manually
72
70
  const response = await fetch('/events');
73
- const eventStream = EventStreamConverter.toEventStream(response);
71
+ const eventStream = toServerSentEventStream(response);
74
72
 
75
73
  // Read events from the stream
76
74
  const reader = eventStream.getReader();
@@ -122,7 +120,7 @@ if (response.eventStream) {
122
120
 
123
121
  A utility class for converting `text/event-stream` responses to readable streams.
124
122
 
125
- #### `toEventStream(response: Response): ServerEventStream`
123
+ #### `toServerSentEventStream(response: Response): ServerEventStream`
126
124
 
127
125
  Converts a Response object with a `text/event-stream` body to a readable stream of ServerSentEvent objects.
128
126
 
@@ -0,0 +1,258 @@
1
+ # @ahoo-wang/fetcher-eventstream
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@ahoo-wang/fetcher-eventstream.svg)](https://www.npmjs.com/package/@ahoo-wang/fetcher-eventstream)
4
+ [![Build Status](https://github.com/Ahoo-Wang/fetcher/actions/workflows/ci.yml/badge.svg)](https://github.com/Ahoo-Wang/fetcher/actions)
5
+ [![codecov](https://codecov.io/gh/Ahoo-Wang/Fetcher/graph/badge.svg?token=CUPgk8DmH5)](https://codecov.io/gh/Ahoo-Wang/Fetcher)
6
+ [![License](https://img.shields.io/npm/l/@ahoo-wang/fetcher-eventstream.svg)](https://github.com/Ahoo-Wang/fetcher/blob/main/LICENSE)
7
+ [![npm downloads](https://img.shields.io/npm/dm/@ahoo-wang/fetcher-eventstream.svg)](https://www.npmjs.com/package/@ahoo-wang/fetcher-eventstream)
8
+
9
+ 为 Fetcher 提供 text/event-stream 支持,实现服务器发送事件(SSE)功能。
10
+
11
+ ## 特性
12
+
13
+ - **事件流转换**:将 `text/event-stream` 响应转换为 `ServerSentEvent` 对象的异步生成器
14
+ - **拦截器集成**:自动为 `text/event-stream` 内容类型的响应添加 `eventStream()` 方法
15
+ - **SSE 解析**:根据规范解析服务器发送事件,包括数据、事件、ID 和重试字段
16
+ - **流支持**:正确处理分块数据和多行事件
17
+ - **注释处理**:正确忽略注释行(以 `:` 开头的行)
18
+ - **TypeScript 支持**:完整的 TypeScript 类型定义
19
+
20
+ ## 安装
21
+
22
+ 使用 pnpm:
23
+
24
+ ```bash
25
+ pnpm add @ahoo-wang/fetcher-eventstream
26
+ ```
27
+
28
+ 使用 npm:
29
+
30
+ ```bash
31
+ npm install @ahoo-wang/fetcher-eventstream
32
+ ```
33
+
34
+ 使用 yarn:
35
+
36
+ ```bash
37
+ yarn add @ahoo-wang/fetcher-eventstream
38
+ ```
39
+
40
+ ## 使用
41
+
42
+ ### 带拦截器的基本用法
43
+
44
+ ```typescript
45
+ import { Fetcher } from '@ahoo-wang/fetcher';
46
+ import { EventStreamInterceptor } from '@ahoo-wang/fetcher-eventstream';
47
+
48
+ const fetcher = new Fetcher({
49
+ baseURL: 'https://api.example.com',
50
+ });
51
+
52
+ // 添加事件流拦截器
53
+ fetcher.interceptors.response.use(new EventStreamInterceptor());
54
+
55
+ // 在响应中使用 eventStream 方法处理 text/event-stream 内容类型
56
+ const response = await fetcher.get('/events');
57
+ if (response.eventStream) {
58
+ for await (const event of response.eventStream()) {
59
+ console.log('收到事件:', event);
60
+ }
61
+ }
62
+ ```
63
+
64
+ ### 手动转换
65
+
66
+ ```typescript
67
+ import { toServerSentEventStream } from '@ahoo-wang/fetcher-eventstream';
68
+
69
+ // 手动转换 Response 对象
70
+ const response = await fetch('/events');
71
+ const eventStream = toServerSentEventStream(response);
72
+
73
+ // 从流中读取事件
74
+ const reader = eventStream.getReader();
75
+ try {
76
+ while (true) {
77
+ const { done, value } = await reader.read();
78
+ if (done) break;
79
+ console.log('收到事件:', value);
80
+ }
81
+ } finally {
82
+ reader.releaseLock();
83
+ }
84
+ ```
85
+
86
+ ### 异步迭代器用法
87
+
88
+ ```typescript
89
+ import { Fetcher } from '@ahoo-wang/fetcher';
90
+ import { EventStreamInterceptor } from '@ahoo-wang/fetcher-eventstream';
91
+
92
+ const fetcher = new Fetcher({
93
+ baseURL: 'https://api.example.com',
94
+ interceptors: {
95
+ response: [new EventStreamInterceptor()],
96
+ },
97
+ });
98
+
99
+ // 使用异步迭代
100
+ const response = await fetcher.get('/events');
101
+ if (response.eventStream) {
102
+ for await (const event of response.eventStream()) {
103
+ switch (event.event) {
104
+ case 'message':
105
+ console.log('消息:', event.data);
106
+ break;
107
+ case 'notification':
108
+ console.log('通知:', event.data);
109
+ break;
110
+ default:
111
+ console.log('未知事件:', event);
112
+ }
113
+ }
114
+ }
115
+ ```
116
+
117
+ ## API 参考
118
+
119
+ ### EventStreamConverter
120
+
121
+ 用于将 `text/event-stream` 响应转换为可读流的工具类。
122
+
123
+ #### `toServerSentEventStream(response: Response): ServerEventStream`
124
+
125
+ 将带有 `text/event-stream` 主体的 Response 对象转换为 ServerSentEvent 对象的可读流。
126
+
127
+ **参数:**
128
+
129
+ - `response`:带有 `text/event-stream` 内容类型的 HTTP 响应
130
+
131
+ **返回:**
132
+
133
+ - `ServerEventStream`:ServerSentEvent 对象的可读流
134
+
135
+ ### EventStreamInterceptor
136
+
137
+ 响应拦截器,自动为 `text/event-stream` 内容类型的响应添加 `eventStream()` 方法。
138
+
139
+ #### `intercept(response: Response): Response`
140
+
141
+ 拦截响应,如果内容类型是 `text/event-stream` 则添加 `eventStream()` 方法。
142
+
143
+ **参数:**
144
+
145
+ - `response`:要拦截的 HTTP 响应
146
+
147
+ **返回:**
148
+
149
+ - `Response`:添加了 `eventStream()` 方法的拦截响应
150
+
151
+ ### ServerSentEvent
152
+
153
+ 定义服务器发送事件结构的接口。
154
+
155
+ ```typescript
156
+ interface ServerSentEvent {
157
+ data: string; // 事件数据(必需)
158
+ event?: string; // 事件类型(可选,默认为 'message')
159
+ id?: string; // 事件 ID(可选)
160
+ retry?: number; // 以毫秒为单位的重试超时(可选)
161
+ }
162
+ ```
163
+
164
+ ### ServerSentEventStream
165
+
166
+ ServerSentEvent 对象的可读流的类型别名。
167
+
168
+ ```typescript
169
+ type ServerSentEventStream = ReadableStream<ServerSentEvent>;
170
+ ```
171
+
172
+ ## 服务器发送事件规范合规性
173
+
174
+ 此包完全实现了 [服务器发送事件规范](https://html.spec.whatwg.org/multipage/server-sent-events.html):
175
+
176
+ - **数据字段**:支持多行数据字段
177
+ - **事件字段**:自定义事件类型
178
+ - **ID 字段**:最后事件 ID 跟踪
179
+ - **重试字段**:自动重连超时
180
+ - **注释行**:忽略以 `:` 开头的行
181
+ - **事件分发**:正确的事件分发,默认事件类型为 'message'
182
+
183
+ ## 示例
184
+
185
+ ### 实时通知
186
+
187
+ ```typescript
188
+ import { Fetcher } from '@ahoo-wang/fetcher';
189
+ import { EventStreamInterceptor } from '@ahoo-wang/fetcher-eventstream';
190
+
191
+ const fetcher = new Fetcher({
192
+ baseURL: 'https://api.example.com',
193
+ });
194
+ fetcher.interceptors.response.use(new EventStreamInterceptor());
195
+
196
+ // 监听实时通知
197
+ const response = await fetcher.get('/notifications');
198
+ if (response.eventStream) {
199
+ for await (const event of response.eventStream()) {
200
+ switch (event.event) {
201
+ case 'message':
202
+ showNotification('消息', event.data);
203
+ break;
204
+ case 'alert':
205
+ showAlert('警报', event.data);
206
+ break;
207
+ case 'update':
208
+ handleUpdate(JSON.parse(event.data));
209
+ break;
210
+ }
211
+ }
212
+ }
213
+ ```
214
+
215
+ ### 进度更新
216
+
217
+ ```typescript
218
+ import { Fetcher } from '@ahoo-wang/fetcher';
219
+ import { EventStreamInterceptor } from '@ahoo-wang/fetcher-eventstream';
220
+
221
+ const fetcher = new Fetcher({
222
+ baseURL: 'https://api.example.com',
223
+ });
224
+ fetcher.interceptors.response.use(new EventStreamInterceptor());
225
+
226
+ // 跟踪长时间运行的任务进度
227
+ const response = await fetcher.get('/tasks/123/progress');
228
+ if (response.eventStream) {
229
+ for await (const event of response.eventStream()) {
230
+ if (event.event === 'progress') {
231
+ const progress = JSON.parse(event.data);
232
+ updateProgressBar(progress.percentage);
233
+ } else if (event.event === 'complete') {
234
+ showCompletionMessage(event.data);
235
+ break;
236
+ }
237
+ }
238
+ }
239
+ ```
240
+
241
+ ## 测试
242
+
243
+ 运行此包的测试:
244
+
245
+ ```bash
246
+ pnpm test
247
+ ```
248
+
249
+ 测试套件包括:
250
+
251
+ - 事件流转换测试
252
+ - 拦截器功能测试
253
+ - 边界情况处理(畸形事件、分块数据等)
254
+ - 大事件流的性能测试
255
+
256
+ ## 许可证
257
+
258
+ 本项目采用 [Apache-2.0 许可证](../../LICENSE)。
@@ -3,17 +3,5 @@ import { ServerSentEvent } from './serverSentEventTransformStream';
3
3
  * ServerSentEventStream is a ReadableStream of ServerSentEvent objects
4
4
  */
5
5
  export type ServerSentEventStream = ReadableStream<ServerSentEvent>;
6
- /**
7
- * Responsible for handling event stream responses, including converting Response to event stream (ReadableStream<ServerSentEvent>).
8
- */
9
- export declare class EventStreamConverter {
10
- /**
11
- * Convert HTTP response to server-sent event stream
12
- *
13
- * @param response - HTTP response object, should contain text/event-stream formatted data
14
- * @returns ServerSentEventStream - Server event stream, can be used to read events sent by the server
15
- * @throws Error - Throws error when response body is null
16
- */
17
- static toEventStream(response: Response): ServerSentEventStream;
18
- }
6
+ export declare function toServerSentEventStream(response: Response): ServerSentEventStream;
19
7
  //# sourceMappingURL=eventStreamConverter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"eventStreamConverter.d.ts","sourceRoot":"","sources":["../src/eventStreamConverter.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EAEhB,MAAM,kCAAkC,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;AAEpE;;GAEG;AACH,qBAAa,oBAAoB;IAC/B;;;;;;OAMG;IACH,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,qBAAqB;CAchE"}
1
+ {"version":3,"file":"eventStreamConverter.d.ts","sourceRoot":"","sources":["../src/eventStreamConverter.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EAEhB,MAAM,kCAAkC,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;AAEpE,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,QAAQ,GAAG,qBAAqB,CAajF"}
package/dist/index.es.js CHANGED
@@ -3,46 +3,46 @@ class d {
3
3
  constructor() {
4
4
  this.buffer = "";
5
5
  }
6
- transform(r, t) {
6
+ transform(t, r) {
7
7
  try {
8
- this.buffer += r;
8
+ this.buffer += t;
9
9
  const e = this.buffer.split(`
10
10
  `);
11
11
  this.buffer = e.pop() || "";
12
- for (const n of e)
13
- t.enqueue(n);
12
+ for (const s of e)
13
+ r.enqueue(s);
14
14
  } catch (e) {
15
- t.error(e);
15
+ r.error(e);
16
16
  }
17
17
  }
18
- flush(r) {
18
+ flush(t) {
19
19
  try {
20
- this.buffer && r.enqueue(this.buffer);
21
- } catch (t) {
22
- r.error(t);
20
+ this.buffer && t.enqueue(this.buffer);
21
+ } catch (r) {
22
+ t.error(r);
23
23
  }
24
24
  }
25
25
  }
26
- class c extends TransformStream {
26
+ class u extends TransformStream {
27
27
  constructor() {
28
28
  super(new d());
29
29
  }
30
30
  }
31
- var u = /* @__PURE__ */ ((a) => (a.ID = "id", a.RETRY = "retry", a.EVENT = "event", a.DATA = "data", a))(u || {});
32
- function m(a, r, t) {
33
- switch (a) {
31
+ var c = /* @__PURE__ */ ((n) => (n.ID = "id", n.RETRY = "retry", n.EVENT = "event", n.DATA = "data", n))(c || {});
32
+ function m(n, t, r) {
33
+ switch (n) {
34
34
  case "event":
35
- t.event = r;
35
+ r.event = t;
36
36
  break;
37
37
  case "data":
38
- t.data.push(r);
38
+ r.data.push(t);
39
39
  break;
40
40
  case "id":
41
- t.id = r;
41
+ r.id = t;
42
42
  break;
43
43
  case "retry":
44
- const e = parseInt(r, 10);
45
- isNaN(e) || (t.retry = e);
44
+ const e = parseInt(t, 10);
45
+ isNaN(e) || (r.retry = e);
46
46
  break;
47
47
  }
48
48
  }
@@ -60,11 +60,11 @@ class h {
60
60
  * @param chunk Input string chunk
61
61
  * @param controller Controller for controlling the transform stream
62
62
  */
63
- transform(r, t) {
63
+ transform(t, r) {
64
64
  let e = this.currentEvent;
65
65
  try {
66
- if (r.trim() === "") {
67
- e.data.length > 0 && (t.enqueue({
66
+ if (t.trim() === "") {
67
+ e.data.length > 0 && (r.enqueue({
68
68
  event: e.event || "message",
69
69
  data: e.data.join(`
70
70
  `),
@@ -73,14 +73,14 @@ class h {
73
73
  }), e.event = "message", e.id = e.id, e.retry = e.retry, e.data = []);
74
74
  return;
75
75
  }
76
- if (r.startsWith(":"))
76
+ if (t.startsWith(":"))
77
77
  return;
78
- const n = r.indexOf(":");
79
- let i, s;
80
- n === -1 ? (i = r.toLowerCase(), s = "") : (i = r.substring(0, n).toLowerCase(), s = r.substring(n + 1), s.startsWith(" ") && (s = s.substring(1))), i = i.trim(), s = s.trim(), m(i, s, e);
81
- } catch (n) {
82
- t.error(
83
- n instanceof Error ? n : new Error(String(n))
78
+ const s = t.indexOf(":");
79
+ let i, a;
80
+ s === -1 ? (i = t.toLowerCase(), a = "") : (i = t.substring(0, s).toLowerCase(), a = t.substring(s + 1), a.startsWith(" ") && (a = a.substring(1))), i = i.trim(), a = a.trim(), m(i, a, e);
81
+ } catch (s) {
82
+ r.error(
83
+ s instanceof Error ? s : new Error(String(s))
84
84
  ), e.event = "message", e.id = void 0, e.retry = void 0, e.data = [];
85
85
  }
86
86
  }
@@ -88,22 +88,22 @@ class h {
88
88
  * Called when the stream ends, used to process remaining data
89
89
  * @param controller Controller for controlling the transform stream
90
90
  */
91
- flush(r) {
92
- let t = this.currentEvent;
91
+ flush(t) {
92
+ let r = this.currentEvent;
93
93
  try {
94
- t.data.length > 0 && r.enqueue({
95
- event: t.event || "message",
96
- data: t.data.join(`
94
+ r.data.length > 0 && t.enqueue({
95
+ event: r.event || "message",
96
+ data: r.data.join(`
97
97
  `),
98
- id: t.id || "",
99
- retry: t.retry
98
+ id: r.id || "",
99
+ retry: r.retry
100
100
  });
101
101
  } catch (e) {
102
- r.error(
102
+ t.error(
103
103
  e instanceof Error ? e : new Error(String(e))
104
104
  );
105
105
  } finally {
106
- t.event = "message", t.id = void 0, t.retry = void 0, t.data = [];
106
+ r.event = "message", r.id = void 0, r.retry = void 0, r.data = [];
107
107
  }
108
108
  }
109
109
  }
@@ -112,32 +112,23 @@ class y extends TransformStream {
112
112
  super(new h());
113
113
  }
114
114
  }
115
- class v {
116
- /**
117
- * Convert HTTP response to server-sent event stream
118
- *
119
- * @param response - HTTP response object, should contain text/event-stream formatted data
120
- * @returns ServerSentEventStream - Server event stream, can be used to read events sent by the server
121
- * @throws Error - Throws error when response body is null
122
- */
123
- static toEventStream(r) {
124
- if (!r.body)
125
- throw new Error("Response body is null");
126
- return r.body.pipeThrough(new TextDecoderStream("utf-8")).pipeThrough(new c()).pipeThrough(new y());
127
- }
115
+ function T(n) {
116
+ if (!n.body)
117
+ throw new Error("Response body is null");
118
+ return n.body.pipeThrough(new TextDecoderStream("utf-8")).pipeThrough(new u()).pipeThrough(new y());
128
119
  }
129
120
  class p {
130
- intercept(r) {
131
- const t = r.headers.get(o);
132
- return t && t.includes(f.TEXT_EVENT_STREAM) && (r.eventStream = () => v.toEventStream(r)), r;
121
+ intercept(t) {
122
+ const r = t.headers.get(o);
123
+ return r && r.includes(f.TEXT_EVENT_STREAM) && (t.eventStream = () => T(t)), t;
133
124
  }
134
125
  }
135
126
  export {
136
- v as EventStreamConverter,
137
127
  p as EventStreamInterceptor,
138
- u as ServerSentEventField,
128
+ c as ServerSentEventField,
139
129
  y as ServerSentEventTransformStream,
140
130
  h as ServerSentEventTransformer,
141
- c as TextLineTransformStream,
142
- d as TextLineTransformer
131
+ u as TextLineTransformStream,
132
+ d as TextLineTransformer,
133
+ T as toServerSentEventStream
143
134
  };
package/dist/index.umd.js CHANGED
@@ -1,4 +1,4 @@
1
- (function(n,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("@ahoo-wang/fetcher")):typeof define=="function"&&define.amd?define(["exports","@ahoo-wang/fetcher"],o):(n=typeof globalThis<"u"?globalThis:n||self,o(n.FetcherEventStream={},n.Fetcher))})(this,(function(n,o){"use strict";class d{constructor(){this.buffer=""}transform(r,t){try{this.buffer+=r;const e=this.buffer.split(`
2
- `);this.buffer=e.pop()||"";for(const s of e)t.enqueue(s)}catch(e){t.error(e)}}flush(r){try{this.buffer&&r.enqueue(this.buffer)}catch(t){r.error(t)}}}class u extends TransformStream{constructor(){super(new d)}}var c=(a=>(a.ID="id",a.RETRY="retry",a.EVENT="event",a.DATA="data",a))(c||{});function T(a,r,t){switch(a){case"event":t.event=r;break;case"data":t.data.push(r);break;case"id":t.id=r;break;case"retry":const e=parseInt(r,10);isNaN(e)||(t.retry=e);break}}class m{constructor(){this.currentEvent={event:"message",id:void 0,retry:void 0,data:[]}}transform(r,t){let e=this.currentEvent;try{if(r.trim()===""){e.data.length>0&&(t.enqueue({event:e.event||"message",data:e.data.join(`
3
- `),id:e.id||"",retry:e.retry}),e.event="message",e.id=e.id,e.retry=e.retry,e.data=[]);return}if(r.startsWith(":"))return;const s=r.indexOf(":");let f,i;s===-1?(f=r.toLowerCase(),i=""):(f=r.substring(0,s).toLowerCase(),i=r.substring(s+1),i.startsWith(" ")&&(i=i.substring(1))),f=f.trim(),i=i.trim(),T(f,i,e)}catch(s){t.error(s instanceof Error?s:new Error(String(s))),e.event="message",e.id=void 0,e.retry=void 0,e.data=[]}}flush(r){let t=this.currentEvent;try{t.data.length>0&&r.enqueue({event:t.event||"message",data:t.data.join(`
4
- `),id:t.id||"",retry:t.retry})}catch(e){r.error(e instanceof Error?e:new Error(String(e)))}finally{t.event="message",t.id=void 0,t.retry=void 0,t.data=[]}}}class v extends TransformStream{constructor(){super(new m)}}class h{static toEventStream(r){if(!r.body)throw new Error("Response body is null");return r.body.pipeThrough(new TextDecoderStream("utf-8")).pipeThrough(new u).pipeThrough(new v)}}class y{intercept(r){const t=r.headers.get(o.ContentTypeHeader);return t&&t.includes(o.ContentTypeValues.TEXT_EVENT_STREAM)&&(r.eventStream=()=>h.toEventStream(r)),r}}n.EventStreamConverter=h,n.EventStreamInterceptor=y,n.ServerSentEventField=c,n.ServerSentEventTransformStream=v,n.ServerSentEventTransformer=m,n.TextLineTransformStream=u,n.TextLineTransformer=d,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(a,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("@ahoo-wang/fetcher")):typeof define=="function"&&define.amd?define(["exports","@ahoo-wang/fetcher"],o):(a=typeof globalThis<"u"?globalThis:a||self,o(a.FetcherEventStream={},a.Fetcher))})(this,(function(a,o){"use strict";class d{constructor(){this.buffer=""}transform(t,r){try{this.buffer+=t;const e=this.buffer.split(`
2
+ `);this.buffer=e.pop()||"";for(const i of e)r.enqueue(i)}catch(e){r.error(e)}}flush(t){try{this.buffer&&t.enqueue(this.buffer)}catch(r){t.error(r)}}}class u extends TransformStream{constructor(){super(new d)}}var c=(n=>(n.ID="id",n.RETRY="retry",n.EVENT="event",n.DATA="data",n))(c||{});function T(n,t,r){switch(n){case"event":r.event=t;break;case"data":r.data.push(t);break;case"id":r.id=t;break;case"retry":const e=parseInt(t,10);isNaN(e)||(r.retry=e);break}}class m{constructor(){this.currentEvent={event:"message",id:void 0,retry:void 0,data:[]}}transform(t,r){let e=this.currentEvent;try{if(t.trim()===""){e.data.length>0&&(r.enqueue({event:e.event||"message",data:e.data.join(`
3
+ `),id:e.id||"",retry:e.retry}),e.event="message",e.id=e.id,e.retry=e.retry,e.data=[]);return}if(t.startsWith(":"))return;const i=t.indexOf(":");let f,s;i===-1?(f=t.toLowerCase(),s=""):(f=t.substring(0,i).toLowerCase(),s=t.substring(i+1),s.startsWith(" ")&&(s=s.substring(1))),f=f.trim(),s=s.trim(),T(f,s,e)}catch(i){r.error(i instanceof Error?i:new Error(String(i))),e.event="message",e.id=void 0,e.retry=void 0,e.data=[]}}flush(t){let r=this.currentEvent;try{r.data.length>0&&t.enqueue({event:r.event||"message",data:r.data.join(`
4
+ `),id:r.id||"",retry:r.retry})}catch(e){t.error(e instanceof Error?e:new Error(String(e)))}finally{r.event="message",r.id=void 0,r.retry=void 0,r.data=[]}}}class h extends TransformStream{constructor(){super(new m)}}function v(n){if(!n.body)throw new Error("Response body is null");return n.body.pipeThrough(new TextDecoderStream("utf-8")).pipeThrough(new u).pipeThrough(new h)}class y{intercept(t){const r=t.headers.get(o.ContentTypeHeader);return r&&r.includes(o.ContentTypeValues.TEXT_EVENT_STREAM)&&(t.eventStream=()=>v(t)),t}}a.EventStreamInterceptor=y,a.ServerSentEventField=c,a.ServerSentEventTransformStream=h,a.ServerSentEventTransformer=m,a.TextLineTransformStream=u,a.TextLineTransformer=d,a.toServerSentEventStream=v,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ahoo-wang/fetcher-eventstream",
3
- "version": "0.1.5",
3
+ "version": "0.2.0",
4
4
  "description": "Support for text/event-stream in Fetcher",
5
5
  "keywords": [
6
6
  "fetch",
@@ -24,16 +24,16 @@
24
24
  "types": "./dist/index.d.ts",
25
25
  "exports": {
26
26
  ".": {
27
+ "types": "./dist/index.d.ts",
27
28
  "import": "./dist/index.es.js",
28
- "require": "./dist/index.umd.js",
29
- "types": "./dist/index.d.ts"
29
+ "require": "./dist/index.umd.js"
30
30
  }
31
31
  },
32
32
  "files": [
33
33
  "dist"
34
34
  ],
35
35
  "dependencies": {
36
- "@ahoo-wang/fetcher": "0.1.5"
36
+ "@ahoo-wang/fetcher": "0.2.0"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@vitest/coverage-v8": "^3.2.4",