@standardserver/core 0.0.15 → 0.0.19

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 ADDED
@@ -0,0 +1,308 @@
1
+ # @standardserver/core
2
+
3
+ <div align="center">
4
+ <a href="https://codecov.io/gh/middleapi/standardserver">
5
+ <img alt="codecov" src="https://codecov.io/gh/middleapi/standardserver/branch/main/graph/badge.svg">
6
+ </a>
7
+ <a href="https://www.npmjs.com/package/@standardserver/core">
8
+ <img alt="weekly downloads" src="https://img.shields.io/npm/dw/%40standardserver%2Fcore?logo=npm" />
9
+ </a>
10
+ <a href="https://github.com/middleapi/standardserver/blob/main/LICENSE">
11
+ <img alt="MIT License" src="https://img.shields.io/github/license/middleapi/standardserver?logo=open-source-initiative" />
12
+ </a>
13
+ <a href="https://discord.gg/TXEbwRBvQn">
14
+ <img alt="Discord" src="https://img.shields.io/discord/1308966753044398161?color=7389D8&label&logo=discord&logoColor=ffffff" />
15
+ </a>
16
+ <a href="https://deepwiki.com/middleapi/standardserver">
17
+ <img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki">
18
+ </a>
19
+ </div>
20
+
21
+ `@standardserver/core` is the shared contract package for Standard Server.
22
+
23
+ Standard Server provides a unified interface for client-server communication across HTTP and message-based transports. It lets you keep handler and client code transport-agnostic by working with the same request, response, body, and streaming abstractions whether the transport is Fetch, Node.js HTTP, or a peer-style message channel.
24
+
25
+ This package is the foundation of that model. It defines the core request and response types, shared runtime validators, small utility helpers, and event stream (SSE) helpers.
26
+
27
+ ## Entry Points
28
+
29
+ | Entry point | Purpose |
30
+ | ---------------------- | -------------------------------------------------------- |
31
+ | `@standardserver/core` | Shared request/response types, utilities, and validators |
32
+
33
+ ## Request and response types
34
+
35
+ The main entry point exposes four transport-agnostic shapes:
36
+
37
+ | Export | Description |
38
+ | ---------------------- | --------------------------------------------------------------- |
39
+ | `StandardRequest` | Eager request object with a parsed `body` |
40
+ | `StandardLazyRequest` | Request object with `resolveBody(hint?)` for lazy body parsing |
41
+ | `StandardResponse` | Eager response object with a parsed `body` |
42
+ | `StandardLazyResponse` | Response object with `resolveBody(hint?)` for lazy body parsing |
43
+
44
+ Supporting primitives:
45
+
46
+ | Export | Description |
47
+ | ------------------ | ------------------------------------------------------------- |
48
+ | `StandardMethod` | Common HTTP verbs plus any custom string value |
49
+ | `StandardUrl` | A request URL that must start with `/` and exclude the origin |
50
+ | `StandardHeaders` | `Record<string, string \| string[] \| undefined>` |
51
+ | `StandardBodyHint` | Parsing hint for lazy body resolution |
52
+ | `StandardBody` | Shared body union used by requests and responses |
53
+
54
+ By convention, adapters normalize headers to lowercase keys. `signal` is part of `StandardRequest` only and is used to propagate request cancellation.
55
+
56
+ ```ts
57
+ import type { StandardLazyRequest, StandardResponse } from '@standardserver/core'
58
+
59
+ export async function handle(request: StandardLazyRequest): Promise<StandardResponse> {
60
+ const body = await request.resolveBody()
61
+
62
+ return {
63
+ status: 200,
64
+ headers: { 'content-type': 'application/json' },
65
+ body: {
66
+ ok: true,
67
+ method: request.method,
68
+ url: request.url,
69
+ received: body,
70
+ },
71
+ }
72
+ }
73
+ ```
74
+
75
+ ### Body hints and body values
76
+
77
+ `StandardBodyHint` and `StandardBody` describe the shared body contract used across adapters:
78
+
79
+ | Hint | `StandardBody` value | Typical content type | Notes |
80
+ | ------------------- | ------------------------------ | ----------------------------------- | ----------------------------------------------------- |
81
+ | `json` | `unknown` | `application/json` | Primitives, objects, and arrays |
82
+ | `form-data` | `FormData` | `multipart/form-data` | Multipart form submissions |
83
+ | `url-search-params` | `URLSearchParams` | `application/x-www-form-urlencoded` | URL-encoded forms |
84
+ | `event-stream` | `AsyncIteratorObject<unknown>` | `text/event-stream` | Server-Sent Events (SSE) |
85
+ | `octet-stream` | `ReadableStream<Uint8Array>` | any | Binary payloads |
86
+ | `file` | `File` | any | Fixed-size binary payloads for both `File` and `Blob` |
87
+ | `none` | `undefined` | | Empty body |
88
+
89
+ ### Resolving Body
90
+
91
+ `resolveBody(hint?)` determines how to parse the body using the following priority:
92
+
93
+ 1. If the `standard-server` header is present, use it as the `StandardBodyHint`.
94
+ 2. Otherwise, if `hint?` is provided, use it as the `StandardBodyHint`.
95
+ 3. Otherwise, if `content-type` is one of the common types, parse accordingly.
96
+ 4. Otherwise, if `content-length` exists, treat the body as `file`; if not, treat it as `octet-stream`.
97
+
98
+ For efficient communication, set the `standard-server` header to explicitly hint the body type, especially for file or binary streaming. For example, if you upload a file with a common `content-type` such as `application/json` but omit the `standard-server` header, the server may interpret it as JSON and parse it unexpectedly.
99
+
100
+ ```ts
101
+ const response = await fetch('/upload', {
102
+ method: 'POST',
103
+ headers: {
104
+ 'content-type': 'application/json',
105
+ 'standard-server': 'file', // <- hint the body type to avoid misinterpretation
106
+ },
107
+ body: new Blob(['{"message": "Hello, world!"}'], { type: 'application/json' }),
108
+ })
109
+ ```
110
+
111
+ ## Utilities
112
+
113
+ The main entry point also exports a small set of helpers for common header and URL operations.
114
+
115
+ ### Content-Disposition helpers
116
+
117
+ Use `generateContentDisposition()` to produce a safe `Content-Disposition` value and `getFilenameFromContentDisposition()` to read a filename back from an existing header.
118
+
119
+ ```ts
120
+ import {
121
+ generateContentDisposition,
122
+ getFilenameFromContentDisposition,
123
+ } from '@standardserver/core'
124
+
125
+ const disposition = generateContentDisposition('report "Q2".csv')
126
+ // inline; filename="report \"Q2\".csv"; filename*=utf-8''report%20%22Q2%22.csv
127
+
128
+ const filename = getFilenameFromContentDisposition(disposition)
129
+ // 'report "Q2".csv'
130
+ ```
131
+
132
+ `generateContentDisposition()` preserves an ASCII-safe `filename="..."` value and also emits `filename*=` for UTF-8 aware clients.
133
+
134
+ ### Header helpers
135
+
136
+ `mergeStandardHeaders()` combines two `StandardHeaders` objects while preserving duplicate values, and `flattenStandardHeader()` turns a single header value into a plain string when needed.
137
+
138
+ ```ts
139
+ import {
140
+ flattenStandardHeader,
141
+ mergeStandardHeaders,
142
+ } from '@standardserver/core'
143
+
144
+ const headers = mergeStandardHeaders(
145
+ { 'accept': 'application/json', 'set-cookie': ['a=1'] },
146
+ { 'set-cookie': 'b=2', 'vary': 'accept', 'warning': undefined },
147
+ )
148
+ // {
149
+ // accept: 'application/json',
150
+ // 'set-cookie': ['a=1', 'b=2'],
151
+ // vary: 'accept',
152
+ // }
153
+
154
+ const cookieHeader = flattenStandardHeader(headers['set-cookie'])
155
+ // 'a=1, b=2'
156
+ ```
157
+
158
+ ### URL parsing
159
+
160
+ `parseStandardUrl()` splits a `StandardUrl` into `[pathname, search, hash]` without requiring a full origin.
161
+
162
+ ```ts
163
+ import { parseStandardUrl } from '@standardserver/core'
164
+
165
+ const [pathname, search, hash] = parseStandardUrl('/users/123?tab=settings#profile')
166
+ // pathname => '/users/123'
167
+ // search => '?tab=settings'
168
+ // hash => '#profile'
169
+ ```
170
+
171
+ ## Validators
172
+
173
+ Runtime type guards are useful when requests or responses cross process, transport, or message boundaries.
174
+
175
+ | Export | Checks |
176
+ | ---------------------- | ------------------------------------------------------ |
177
+ | `isStandardMethod()` | Any string value |
178
+ | `isStandardUrl()` | A string starting with `/` |
179
+ | `isStandardHeaders()` | Object values are `string`, `string[]`, or `undefined` |
180
+ | `isStandardRequest()` | |
181
+ | `isStandardResponse()` | |
182
+
183
+ ```ts
184
+ import { isStandardRequest } from '@standardserver/core'
185
+
186
+ export function expectStandardRequest(input: unknown) {
187
+ if (!isStandardRequest(input)) {
188
+ throw new TypeError('Expected a StandardRequest-compatible value')
189
+ }
190
+
191
+ return input
192
+ }
193
+ ```
194
+
195
+ ## Event-Stream Helpers
196
+
197
+ Use Event-Stream Helpers when you need explicit SSE encoding, decoding, or metadata handling.
198
+
199
+ ### Message types and codecs
200
+
201
+ The event-stream entry point exposes:
202
+
203
+ - `EventStreamMessageMeta` for `id`, `retry`, and `comments`
204
+ - `EventStreamMessage` for complete SSE messages
205
+ - `encodeEventStreamMessage()` and `decodeEventStreamMessage()` for single-message codec operations
206
+ - `EventStreamDecoder` and `EventStreamDecoderStream` for chunked stream decoding
207
+
208
+ ```ts
209
+ import {
210
+ decodeEventStreamMessage,
211
+ encodeEventStreamMessage,
212
+ } from '@standardserver/core'
213
+
214
+ const encoded = encodeEventStreamMessage({
215
+ comments: ['bootstrap'],
216
+ event: 'message',
217
+ id: '42',
218
+ retry: 3000,
219
+ data: 'hello\nworld',
220
+ })
221
+
222
+ const decoded = decodeEventStreamMessage(encoded)
223
+ // {
224
+ // comments: ['bootstrap'],
225
+ // event: 'message',
226
+ // id: '42',
227
+ // retry: 3000,
228
+ // data: 'hello\nworld',
229
+ // }
230
+ ```
231
+
232
+ For streaming decode, pipe text chunks through `EventStreamDecoderStream`:
233
+
234
+ ```ts
235
+ import { EventStreamDecoderStream } from '@standardserver/core'
236
+
237
+ const messages = response.body!
238
+ .pipeThrough(new TextDecoderStream())
239
+ .pipeThrough(new EventStreamDecoderStream())
240
+ ```
241
+
242
+ ### Iterator metadata helpers
243
+
244
+ `StandardBody` uses async iterators for event-stream bodies. To attach SSE metadata to a yielded value without changing its visible shape, use `withEventIteratorEventMeta()`.
245
+
246
+ ```ts
247
+ import type { StandardResponse } from '@standardserver/core'
248
+ import {
249
+ unwrapEventIteratorEvent,
250
+ withEventIteratorEventMeta,
251
+ } from '@standardserver/core'
252
+
253
+ const eventValue = withEventIteratorEventMeta(
254
+ { message: 'hello' },
255
+ { id: '1', retry: 3000, comments: ['bootstrap'] },
256
+ )
257
+
258
+ const [data, meta] = unwrapEventIteratorEvent(eventValue)
259
+ // data => { message: 'hello' }
260
+ // meta => { id: '1', retry: 3000, comments: ['bootstrap'] }
261
+
262
+ const response: StandardResponse = {
263
+ status: 200,
264
+ headers: {},
265
+ async* body() {
266
+ yield eventValue
267
+ },
268
+ }
269
+ ```
270
+
271
+ > [!WARNING]
272
+ > Metadata is validated before it is attached: `id`, `event`, and comments must not contain line breaks, and `retry` must be a non-negative integer.
273
+
274
+ ### Errors and low-level assertions
275
+
276
+ The subpath also exports:
277
+
278
+ - `EventStreamEncoderError` for invalid outbound SSE messages
279
+ - `EventStreamDecoderError` for incomplete or invalid inbound stream decoding
280
+ - `EventIteratorErrorEvent` for wrapping structured event-stream error payloads in an `Error`
281
+ - `assertEventStreamMessageId()`, `assertEventStreamMessageName()`, `assertEventStreamMessageRetry()`, and `assertEventStreamMessageComment()` for low-level validation when building custom SSE tooling
282
+
283
+ ```ts
284
+ import { EventIteratorErrorEvent } from '@standardserver/core'
285
+
286
+ const error = new EventIteratorErrorEvent(
287
+ { code: 'E_STREAM', detail: 'Connection lost' },
288
+ { message: 'stream error' },
289
+ )
290
+
291
+ error.message
292
+ // 'stream error'
293
+
294
+ error.data
295
+ // { code: 'E_STREAM', detail: 'Connection lost' }
296
+ ```
297
+
298
+ ## Learn more
299
+
300
+ For the higher-level project overview, see the root [Standard Server README](../../README.md).
301
+
302
+ ## Sponsors
303
+
304
+ <p align="center">
305
+ <a href="https://cdn.jsdelivr.net/gh/middleapi/static/sponsors.svg">
306
+ <img src='https://cdn.jsdelivr.net/gh/middleapi/static/sponsors.svg' alt="Sponsors"/>
307
+ </a>
308
+ </p>
package/dist/index.d.mts CHANGED
@@ -1,3 +1,80 @@
1
+ interface EventStreamMessageMeta {
2
+ /**
3
+ * Event identifier, sent back by the client as `lastEventId` for reconnection attempts.
4
+ *
5
+ * @warning id cannot contain newline characters (`\n`)
6
+ */
7
+ id?: string | undefined;
8
+ /**
9
+ * The number of milliseconds the client should wait before attempting to reconnect.
10
+ */
11
+ retry?: number | undefined;
12
+ /**
13
+ * Comments associated with the event.
14
+ *
15
+ * @warning Comments must not contain newline characters (`\n`).
16
+ */
17
+ comments?: string[] | undefined;
18
+ }
19
+ interface EventStreamMessage extends EventStreamMessageMeta {
20
+ /**
21
+ * Event name (e.g., `message`, `error`).
22
+ */
23
+ event?: string | undefined;
24
+ /**
25
+ * Event data, typically JSON-encoded.
26
+ */
27
+ data?: string | undefined;
28
+ }
29
+
30
+ declare function decodeEventStreamMessage(encoded: string): EventStreamMessage;
31
+ declare class EventStreamDecoder {
32
+ private readonly onEvent;
33
+ private incomplete;
34
+ private trailingCR;
35
+ constructor(onEvent: (event: EventStreamMessage) => void);
36
+ feed(chunk: string): void;
37
+ end(): void;
38
+ }
39
+ declare class EventStreamDecoderStream extends TransformStream<string, EventStreamMessage> {
40
+ constructor();
41
+ }
42
+
43
+ declare function assertEventStreamMessageId(id: string): void;
44
+ declare function assertEventStreamMessageName(event: string): void;
45
+ declare function assertEventStreamMessageRetry(retry: number): void;
46
+ declare function assertEventStreamMessageComment(comment: string): void;
47
+ declare function encodeEventStreamMessageData(data: string | undefined): string;
48
+ declare function encodeEventStreamMessageComments(comments: readonly string[] | undefined): string;
49
+ declare function encodeEventStreamMessage(message: EventStreamMessage): string;
50
+
51
+ declare class EventStreamEncoderError extends TypeError {
52
+ }
53
+ declare class EventStreamDecoderError extends TypeError {
54
+ }
55
+ interface EventIteratorErrorEventOptions extends ErrorOptions {
56
+ message?: string;
57
+ }
58
+ declare class EventIteratorErrorEvent extends Error {
59
+ readonly data: unknown;
60
+ constructor(data: unknown, options?: EventIteratorErrorEventOptions);
61
+ }
62
+
63
+ declare const EVENT_ITERATOR_EVENT_META_SYMBOL: unique symbol;
64
+ declare const EVENT_ITERATOR_EVENT_SOURCE_SYMBOL: unique symbol;
65
+ /**
66
+ * Returns a new iterator *event value* with attached, validated metadata.
67
+ */
68
+ declare function withEventIteratorEventMeta<T extends object>(container: T, meta: EventStreamMessageMeta): T;
69
+ /**
70
+ * Unwraps an iterator event value and extracts its associated metadata.
71
+ */
72
+ declare function unwrapEventIteratorEvent<T>(container: T): [data: T, meta: EventStreamMessageMeta | undefined];
73
+ /**
74
+ * Retrieves metadata attached to a single iterator event value.
75
+ */
76
+ declare function getEventIteratorEventMeta(container: unknown): EventStreamMessageMeta | undefined;
77
+
1
78
  type StandardMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD' | (string & {});
2
79
  type StandardUrl = `/${string}` | `/${string}?${string}` | `/${string}#${string}` | `/${string}?${string}#${string}`;
3
80
  interface StandardHeaders {
@@ -80,5 +157,5 @@ declare function isStandardHeaders(maybe: unknown): maybe is StandardHeaders;
80
157
  declare function isStandardRequest(maybe: unknown): maybe is StandardRequest;
81
158
  declare function isStandardResponse(maybe: unknown): maybe is StandardResponse;
82
159
 
83
- export { flattenStandardHeader, generateContentDisposition, getFilenameFromContentDisposition, isStandardHeaders, isStandardMethod, isStandardRequest, isStandardResponse, isStandardUrl, mergeStandardHeaders, parseStandardUrl };
84
- export type { StandardBody, StandardBodyHint, StandardHeaders, StandardLazyRequest, StandardLazyResponse, StandardMethod, StandardRequest, StandardResponse, StandardUrl };
160
+ export { EVENT_ITERATOR_EVENT_META_SYMBOL, EVENT_ITERATOR_EVENT_SOURCE_SYMBOL, EventIteratorErrorEvent, EventStreamDecoder, EventStreamDecoderError, EventStreamDecoderStream, EventStreamEncoderError, assertEventStreamMessageComment, assertEventStreamMessageId, assertEventStreamMessageName, assertEventStreamMessageRetry, decodeEventStreamMessage, encodeEventStreamMessage, encodeEventStreamMessageComments, encodeEventStreamMessageData, flattenStandardHeader, generateContentDisposition, getEventIteratorEventMeta, getFilenameFromContentDisposition, isStandardHeaders, isStandardMethod, isStandardRequest, isStandardResponse, isStandardUrl, mergeStandardHeaders, parseStandardUrl, unwrapEventIteratorEvent, withEventIteratorEventMeta };
161
+ export type { EventIteratorErrorEventOptions, EventStreamMessage, EventStreamMessageMeta, StandardBody, StandardBodyHint, StandardHeaders, StandardLazyRequest, StandardLazyResponse, StandardMethod, StandardRequest, StandardResponse, StandardUrl };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,80 @@
1
+ interface EventStreamMessageMeta {
2
+ /**
3
+ * Event identifier, sent back by the client as `lastEventId` for reconnection attempts.
4
+ *
5
+ * @warning id cannot contain newline characters (`\n`)
6
+ */
7
+ id?: string | undefined;
8
+ /**
9
+ * The number of milliseconds the client should wait before attempting to reconnect.
10
+ */
11
+ retry?: number | undefined;
12
+ /**
13
+ * Comments associated with the event.
14
+ *
15
+ * @warning Comments must not contain newline characters (`\n`).
16
+ */
17
+ comments?: string[] | undefined;
18
+ }
19
+ interface EventStreamMessage extends EventStreamMessageMeta {
20
+ /**
21
+ * Event name (e.g., `message`, `error`).
22
+ */
23
+ event?: string | undefined;
24
+ /**
25
+ * Event data, typically JSON-encoded.
26
+ */
27
+ data?: string | undefined;
28
+ }
29
+
30
+ declare function decodeEventStreamMessage(encoded: string): EventStreamMessage;
31
+ declare class EventStreamDecoder {
32
+ private readonly onEvent;
33
+ private incomplete;
34
+ private trailingCR;
35
+ constructor(onEvent: (event: EventStreamMessage) => void);
36
+ feed(chunk: string): void;
37
+ end(): void;
38
+ }
39
+ declare class EventStreamDecoderStream extends TransformStream<string, EventStreamMessage> {
40
+ constructor();
41
+ }
42
+
43
+ declare function assertEventStreamMessageId(id: string): void;
44
+ declare function assertEventStreamMessageName(event: string): void;
45
+ declare function assertEventStreamMessageRetry(retry: number): void;
46
+ declare function assertEventStreamMessageComment(comment: string): void;
47
+ declare function encodeEventStreamMessageData(data: string | undefined): string;
48
+ declare function encodeEventStreamMessageComments(comments: readonly string[] | undefined): string;
49
+ declare function encodeEventStreamMessage(message: EventStreamMessage): string;
50
+
51
+ declare class EventStreamEncoderError extends TypeError {
52
+ }
53
+ declare class EventStreamDecoderError extends TypeError {
54
+ }
55
+ interface EventIteratorErrorEventOptions extends ErrorOptions {
56
+ message?: string;
57
+ }
58
+ declare class EventIteratorErrorEvent extends Error {
59
+ readonly data: unknown;
60
+ constructor(data: unknown, options?: EventIteratorErrorEventOptions);
61
+ }
62
+
63
+ declare const EVENT_ITERATOR_EVENT_META_SYMBOL: unique symbol;
64
+ declare const EVENT_ITERATOR_EVENT_SOURCE_SYMBOL: unique symbol;
65
+ /**
66
+ * Returns a new iterator *event value* with attached, validated metadata.
67
+ */
68
+ declare function withEventIteratorEventMeta<T extends object>(container: T, meta: EventStreamMessageMeta): T;
69
+ /**
70
+ * Unwraps an iterator event value and extracts its associated metadata.
71
+ */
72
+ declare function unwrapEventIteratorEvent<T>(container: T): [data: T, meta: EventStreamMessageMeta | undefined];
73
+ /**
74
+ * Retrieves metadata attached to a single iterator event value.
75
+ */
76
+ declare function getEventIteratorEventMeta(container: unknown): EventStreamMessageMeta | undefined;
77
+
1
78
  type StandardMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD' | (string & {});
2
79
  type StandardUrl = `/${string}` | `/${string}?${string}` | `/${string}#${string}` | `/${string}?${string}#${string}`;
3
80
  interface StandardHeaders {
@@ -80,5 +157,5 @@ declare function isStandardHeaders(maybe: unknown): maybe is StandardHeaders;
80
157
  declare function isStandardRequest(maybe: unknown): maybe is StandardRequest;
81
158
  declare function isStandardResponse(maybe: unknown): maybe is StandardResponse;
82
159
 
83
- export { flattenStandardHeader, generateContentDisposition, getFilenameFromContentDisposition, isStandardHeaders, isStandardMethod, isStandardRequest, isStandardResponse, isStandardUrl, mergeStandardHeaders, parseStandardUrl };
84
- export type { StandardBody, StandardBodyHint, StandardHeaders, StandardLazyRequest, StandardLazyResponse, StandardMethod, StandardRequest, StandardResponse, StandardUrl };
160
+ export { EVENT_ITERATOR_EVENT_META_SYMBOL, EVENT_ITERATOR_EVENT_SOURCE_SYMBOL, EventIteratorErrorEvent, EventStreamDecoder, EventStreamDecoderError, EventStreamDecoderStream, EventStreamEncoderError, assertEventStreamMessageComment, assertEventStreamMessageId, assertEventStreamMessageName, assertEventStreamMessageRetry, decodeEventStreamMessage, encodeEventStreamMessage, encodeEventStreamMessageComments, encodeEventStreamMessageData, flattenStandardHeader, generateContentDisposition, getEventIteratorEventMeta, getFilenameFromContentDisposition, isStandardHeaders, isStandardMethod, isStandardRequest, isStandardResponse, isStandardUrl, mergeStandardHeaders, parseStandardUrl, unwrapEventIteratorEvent, withEventIteratorEventMeta };
161
+ export type { EventIteratorErrorEventOptions, EventStreamMessage, EventStreamMessageMeta, StandardBody, StandardBodyHint, StandardHeaders, StandardLazyRequest, StandardLazyResponse, StandardMethod, StandardRequest, StandardResponse, StandardUrl };
package/dist/index.mjs CHANGED
@@ -1,4 +1,210 @@
1
- import { tryDecodeURIComponent, toArray, isTypescriptObject } from '@standardserver/shared';
1
+ import { getOrBind, isTypescriptObject, tryDecodeURIComponent, toArray } from '@standardserver/shared';
2
+
3
+ class EventStreamEncoderError extends TypeError {
4
+ }
5
+ class EventStreamDecoderError extends TypeError {
6
+ }
7
+ class EventIteratorErrorEvent extends Error {
8
+ constructor(data, options = {}) {
9
+ super(options?.message ?? "Error Event", options);
10
+ this.data = data;
11
+ }
12
+ }
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/;
17
+ function decodeEventStreamMessage(encoded) {
18
+ const lines = encoded.split(EVENT_STREAM_LINE_DELIMITER_REGEX);
19
+ const message = {};
20
+ for (const line of lines) {
21
+ const index = line.indexOf(":");
22
+ const key = index === -1 ? line : line.slice(0, index);
23
+ const value = index === -1 ? "" : line.slice(index + 1).replace(LEADING_WHITESPACE_REGEX, "");
24
+ if (index === 0) {
25
+ message.comments ??= [];
26
+ message.comments.push(value);
27
+ } else if (key === "data") {
28
+ if (message.data !== void 0) {
29
+ message.data += `
30
+ ${value}`;
31
+ } else {
32
+ message.data = value;
33
+ }
34
+ } else if (key === "event") {
35
+ message.event = value;
36
+ } else if (key === "id") {
37
+ message.id = value;
38
+ } else if (key === "retry") {
39
+ const maybeInteger = Number.parseInt(value);
40
+ if (Number.isInteger(maybeInteger) && maybeInteger >= 0 && maybeInteger.toString() === value) {
41
+ message.retry = maybeInteger;
42
+ }
43
+ }
44
+ }
45
+ return message;
46
+ }
47
+ class EventStreamDecoder {
48
+ constructor(onEvent) {
49
+ this.onEvent = onEvent;
50
+ }
51
+ incomplete = "";
52
+ trailingCR = false;
53
+ feed(chunk) {
54
+ if (this.trailingCR && chunk.startsWith("\n")) {
55
+ chunk = chunk.slice(1);
56
+ }
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);
63
+ this.onEvent(message);
64
+ }
65
+ }
66
+ end() {
67
+ if (this.incomplete) {
68
+ throw new EventStreamDecoderError("Event Stream ended before complete");
69
+ }
70
+ }
71
+ }
72
+ class EventStreamDecoderStream extends TransformStream {
73
+ constructor() {
74
+ let decoder;
75
+ super({
76
+ start(controller) {
77
+ decoder = new EventStreamDecoder((event) => {
78
+ controller.enqueue(event);
79
+ });
80
+ },
81
+ transform(chunk) {
82
+ decoder.feed(chunk);
83
+ },
84
+ flush() {
85
+ decoder.end();
86
+ }
87
+ });
88
+ }
89
+ }
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
+ }
95
+ function assertEventStreamMessageId(id) {
96
+ if (containsEventStreamLineBreak(id)) {
97
+ throw new EventStreamEncoderError("Event's id must not contain a carriage return or newline character");
98
+ }
99
+ }
100
+ function assertEventStreamMessageName(event) {
101
+ if (containsEventStreamLineBreak(event)) {
102
+ throw new EventStreamEncoderError("Event's event must not contain a carriage return or newline character");
103
+ }
104
+ }
105
+ function assertEventStreamMessageRetry(retry) {
106
+ if (!Number.isInteger(retry) || retry < 0) {
107
+ throw new EventStreamEncoderError("Event's retry must be a integer and >= 0");
108
+ }
109
+ }
110
+ function assertEventStreamMessageComment(comment) {
111
+ if (containsEventStreamLineBreak(comment)) {
112
+ throw new EventStreamEncoderError("Event's comment must not contain a carriage return or newline character");
113
+ }
114
+ }
115
+ function encodeEventStreamMessageData(data) {
116
+ let output = "";
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}
121
+ `;
122
+ }
123
+ }
124
+ return output;
125
+ }
126
+ function encodeEventStreamMessageComments(comments) {
127
+ let output = "";
128
+ for (const comment of comments ?? []) {
129
+ assertEventStreamMessageComment(comment);
130
+ output += `: ${comment}
131
+ `;
132
+ }
133
+ return output;
134
+ }
135
+ function encodeEventStreamMessage(message) {
136
+ let output = "";
137
+ output += encodeEventStreamMessageComments(message.comments);
138
+ if (message.event !== void 0) {
139
+ assertEventStreamMessageName(message.event);
140
+ output += `event: ${message.event}
141
+ `;
142
+ }
143
+ if (message.retry !== void 0) {
144
+ assertEventStreamMessageRetry(message.retry);
145
+ output += `retry: ${message.retry}
146
+ `;
147
+ }
148
+ if (message.id !== void 0) {
149
+ assertEventStreamMessageId(message.id);
150
+ output += `id: ${message.id}
151
+ `;
152
+ }
153
+ output += encodeEventStreamMessageData(message.data);
154
+ output += "\n";
155
+ return output;
156
+ }
157
+
158
+ const EVENT_ITERATOR_EVENT_META_SYMBOL = Symbol.for("STANDARDSERVER_EVENT_ITERATOR_EVENT_META");
159
+ const EVENT_ITERATOR_EVENT_SOURCE_SYMBOL = Symbol.for("STANDARDSERVER_EVENT_ITERATOR_EVENT_SOURCE");
160
+ function withEventIteratorEventMeta(container, meta) {
161
+ let assertedMeta;
162
+ if (meta.id !== void 0) {
163
+ assertEventStreamMessageId(meta.id);
164
+ assertedMeta ??= {};
165
+ assertedMeta.id = meta.id;
166
+ }
167
+ if (meta.retry !== void 0) {
168
+ assertEventStreamMessageRetry(meta.retry);
169
+ assertedMeta ??= {};
170
+ assertedMeta.retry = meta.retry;
171
+ }
172
+ if (meta.comments !== void 0) {
173
+ for (const comment of meta.comments) {
174
+ assertEventStreamMessageComment(comment);
175
+ }
176
+ assertedMeta ??= {};
177
+ assertedMeta.comments = meta.comments;
178
+ }
179
+ if (!assertedMeta) {
180
+ return container;
181
+ }
182
+ return new Proxy(container, {
183
+ get(target, prop, _receiver) {
184
+ if (prop === EVENT_ITERATOR_EVENT_SOURCE_SYMBOL) {
185
+ return target;
186
+ }
187
+ if (prop === EVENT_ITERATOR_EVENT_META_SYMBOL) {
188
+ return assertedMeta;
189
+ }
190
+ return getOrBind(target, prop);
191
+ }
192
+ });
193
+ }
194
+ function unwrapEventIteratorEvent(container) {
195
+ if (!isTypescriptObject(container)) {
196
+ return [container, void 0];
197
+ }
198
+ const meta = container[EVENT_ITERATOR_EVENT_META_SYMBOL];
199
+ const target = container[EVENT_ITERATOR_EVENT_SOURCE_SYMBOL] ?? container;
200
+ return [target, meta];
201
+ }
202
+ function getEventIteratorEventMeta(container) {
203
+ if (!isTypescriptObject(container)) {
204
+ return void 0;
205
+ }
206
+ return container[EVENT_ITERATOR_EVENT_META_SYMBOL];
207
+ }
2
208
 
3
209
  function generateContentDisposition(filename) {
4
210
  const encodedFilename = filename.replace(/[^\x20-\x7E]/g, "_").replace(/"/g, '\\"');
@@ -86,4 +292,4 @@ function isStandardResponse(maybe) {
86
292
  return isStandardHeaders(maybe.headers);
87
293
  }
88
294
 
89
- export { flattenStandardHeader, generateContentDisposition, getFilenameFromContentDisposition, isStandardHeaders, isStandardMethod, isStandardRequest, isStandardResponse, isStandardUrl, mergeStandardHeaders, parseStandardUrl };
295
+ export { EVENT_ITERATOR_EVENT_META_SYMBOL, EVENT_ITERATOR_EVENT_SOURCE_SYMBOL, EventIteratorErrorEvent, EventStreamDecoder, EventStreamDecoderError, EventStreamDecoderStream, EventStreamEncoderError, assertEventStreamMessageComment, assertEventStreamMessageId, assertEventStreamMessageName, assertEventStreamMessageRetry, decodeEventStreamMessage, encodeEventStreamMessage, encodeEventStreamMessageComments, encodeEventStreamMessageData, flattenStandardHeader, generateContentDisposition, getEventIteratorEventMeta, getFilenameFromContentDisposition, isStandardHeaders, isStandardMethod, isStandardRequest, isStandardResponse, isStandardUrl, mergeStandardHeaders, parseStandardUrl, unwrapEventIteratorEvent, withEventIteratorEventMeta };
package/package.json CHANGED
@@ -1,32 +1,28 @@
1
1
  {
2
2
  "name": "@standardserver/core",
3
3
  "type": "module",
4
- "version": "0.0.15",
4
+ "version": "0.0.19",
5
5
  "license": "MIT",
6
6
  "homepage": "https://standardserver.dev",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/standardserver/standardserver.git",
9
+ "url": "git+https://github.com/middleapi/standardserver.git",
10
10
  "directory": "packages/core"
11
11
  },
12
12
  "sideEffects": false,
13
13
  "exports": {
14
+ "./package.json": "./package.json",
14
15
  ".": {
15
16
  "types": "./dist/index.d.mts",
16
17
  "import": "./dist/index.mjs",
17
18
  "default": "./dist/index.mjs"
18
- },
19
- "./event-stream": {
20
- "types": "./dist/event-stream/index.d.mts",
21
- "import": "./dist/event-stream/index.mjs",
22
- "default": "./dist/event-stream/index.mjs"
23
19
  }
24
20
  },
25
21
  "files": [
26
22
  "dist"
27
23
  ],
28
24
  "dependencies": {
29
- "@standardserver/shared": "0.0.15"
25
+ "@standardserver/shared": "0.0.19"
30
26
  },
31
27
  "scripts": {
32
28
  "build": "unbuild",
@@ -1,79 +0,0 @@
1
- interface EventStreamMessageMeta {
2
- /**
3
- * Event identifier, sent back by the client as `lastEventId` for reconnection attempts.
4
- *
5
- * @warning id cannot contain newline characters (`\n`)
6
- */
7
- id?: string | undefined;
8
- /**
9
- * The number of milliseconds the client should wait before attempting to reconnect.
10
- */
11
- retry?: number | undefined;
12
- /**
13
- * Comments associated with the event.
14
- *
15
- * @warning Comments must not contain newline characters (`\n`).
16
- */
17
- comments?: string[] | undefined;
18
- }
19
- interface EventStreamMessage extends EventStreamMessageMeta {
20
- /**
21
- * Event name (e.g., `message`, `error`).
22
- */
23
- event?: string | undefined;
24
- /**
25
- * Event data, typically JSON-encoded.
26
- */
27
- data?: string | undefined;
28
- }
29
-
30
- declare function decodeEventStreamMessage(encoded: string): EventStreamMessage;
31
- declare class EventStreamDecoder {
32
- private readonly onEvent;
33
- private incomplete;
34
- private trailingCR;
35
- constructor(onEvent: (event: EventStreamMessage) => void);
36
- feed(chunk: string): void;
37
- end(): void;
38
- }
39
- declare class EventStreamDecoderStream extends TransformStream<string, EventStreamMessage> {
40
- constructor();
41
- }
42
-
43
- declare function assertEventStreamMessageId(id: string): void;
44
- declare function assertEventStreamMessageName(event: string): void;
45
- declare function assertEventStreamMessageRetry(retry: number): void;
46
- declare function assertEventStreamMessageComment(comment: string): void;
47
- declare function encodeEventStreamMessageData(data: string | undefined): string;
48
- declare function encodeEventStreamMessageComments(comments: readonly string[] | undefined): string;
49
- declare function encodeEventStreamMessage(message: EventStreamMessage): string;
50
-
51
- declare class EventStreamEncoderError extends TypeError {
52
- }
53
- declare class EventStreamDecoderError extends TypeError {
54
- }
55
- interface EventIteratorErrorEventOptions extends ErrorOptions {
56
- message?: string;
57
- }
58
- declare class EventIteratorErrorEvent extends Error {
59
- readonly data: unknown;
60
- constructor(data: unknown, options?: EventIteratorErrorEventOptions);
61
- }
62
-
63
- declare const EVENT_ITERATOR_EVENT_META_SYMBOL: symbol;
64
- declare const EVENT_ITERATOR_EVENT_SOURCE_SYMBOL: symbol;
65
- /**
66
- * Returns a new iterator *event value* with attached, validated metadata.
67
- */
68
- declare function withEventIteratorEventMeta<T extends object>(container: T, meta: EventStreamMessageMeta): T;
69
- /**
70
- * Unwraps an iterator event value and extracts its associated metadata.
71
- */
72
- declare function unwrapEventIteratorEvent<T>(container: T): [data: T, meta: EventStreamMessageMeta | undefined];
73
- /**
74
- * Retrieves metadata attached to a single iterator event value.
75
- */
76
- declare function getEventIteratorEventMeta(container: unknown): EventStreamMessageMeta | undefined;
77
-
78
- export { EVENT_ITERATOR_EVENT_META_SYMBOL, EVENT_ITERATOR_EVENT_SOURCE_SYMBOL, EventIteratorErrorEvent, EventStreamDecoder, EventStreamDecoderError, EventStreamDecoderStream, EventStreamEncoderError, assertEventStreamMessageComment, assertEventStreamMessageId, assertEventStreamMessageName, assertEventStreamMessageRetry, decodeEventStreamMessage, encodeEventStreamMessage, encodeEventStreamMessageComments, encodeEventStreamMessageData, getEventIteratorEventMeta, unwrapEventIteratorEvent, withEventIteratorEventMeta };
79
- export type { EventIteratorErrorEventOptions, EventStreamMessage, EventStreamMessageMeta };
@@ -1,79 +0,0 @@
1
- interface EventStreamMessageMeta {
2
- /**
3
- * Event identifier, sent back by the client as `lastEventId` for reconnection attempts.
4
- *
5
- * @warning id cannot contain newline characters (`\n`)
6
- */
7
- id?: string | undefined;
8
- /**
9
- * The number of milliseconds the client should wait before attempting to reconnect.
10
- */
11
- retry?: number | undefined;
12
- /**
13
- * Comments associated with the event.
14
- *
15
- * @warning Comments must not contain newline characters (`\n`).
16
- */
17
- comments?: string[] | undefined;
18
- }
19
- interface EventStreamMessage extends EventStreamMessageMeta {
20
- /**
21
- * Event name (e.g., `message`, `error`).
22
- */
23
- event?: string | undefined;
24
- /**
25
- * Event data, typically JSON-encoded.
26
- */
27
- data?: string | undefined;
28
- }
29
-
30
- declare function decodeEventStreamMessage(encoded: string): EventStreamMessage;
31
- declare class EventStreamDecoder {
32
- private readonly onEvent;
33
- private incomplete;
34
- private trailingCR;
35
- constructor(onEvent: (event: EventStreamMessage) => void);
36
- feed(chunk: string): void;
37
- end(): void;
38
- }
39
- declare class EventStreamDecoderStream extends TransformStream<string, EventStreamMessage> {
40
- constructor();
41
- }
42
-
43
- declare function assertEventStreamMessageId(id: string): void;
44
- declare function assertEventStreamMessageName(event: string): void;
45
- declare function assertEventStreamMessageRetry(retry: number): void;
46
- declare function assertEventStreamMessageComment(comment: string): void;
47
- declare function encodeEventStreamMessageData(data: string | undefined): string;
48
- declare function encodeEventStreamMessageComments(comments: readonly string[] | undefined): string;
49
- declare function encodeEventStreamMessage(message: EventStreamMessage): string;
50
-
51
- declare class EventStreamEncoderError extends TypeError {
52
- }
53
- declare class EventStreamDecoderError extends TypeError {
54
- }
55
- interface EventIteratorErrorEventOptions extends ErrorOptions {
56
- message?: string;
57
- }
58
- declare class EventIteratorErrorEvent extends Error {
59
- readonly data: unknown;
60
- constructor(data: unknown, options?: EventIteratorErrorEventOptions);
61
- }
62
-
63
- declare const EVENT_ITERATOR_EVENT_META_SYMBOL: symbol;
64
- declare const EVENT_ITERATOR_EVENT_SOURCE_SYMBOL: symbol;
65
- /**
66
- * Returns a new iterator *event value* with attached, validated metadata.
67
- */
68
- declare function withEventIteratorEventMeta<T extends object>(container: T, meta: EventStreamMessageMeta): T;
69
- /**
70
- * Unwraps an iterator event value and extracts its associated metadata.
71
- */
72
- declare function unwrapEventIteratorEvent<T>(container: T): [data: T, meta: EventStreamMessageMeta | undefined];
73
- /**
74
- * Retrieves metadata attached to a single iterator event value.
75
- */
76
- declare function getEventIteratorEventMeta(container: unknown): EventStreamMessageMeta | undefined;
77
-
78
- export { EVENT_ITERATOR_EVENT_META_SYMBOL, EVENT_ITERATOR_EVENT_SOURCE_SYMBOL, EventIteratorErrorEvent, EventStreamDecoder, EventStreamDecoderError, EventStreamDecoderStream, EventStreamEncoderError, assertEventStreamMessageComment, assertEventStreamMessageId, assertEventStreamMessageName, assertEventStreamMessageRetry, decodeEventStreamMessage, encodeEventStreamMessage, encodeEventStreamMessageComments, encodeEventStreamMessageData, getEventIteratorEventMeta, unwrapEventIteratorEvent, withEventIteratorEventMeta };
79
- export type { EventIteratorErrorEventOptions, EventStreamMessage, EventStreamMessageMeta };
@@ -1,209 +0,0 @@
1
- import { getPackageSymbol, getOrBind, isTypescriptObject } from '@standardserver/shared';
2
-
3
- class EventStreamEncoderError extends TypeError {
4
- }
5
- class EventStreamDecoderError extends TypeError {
6
- }
7
- class EventIteratorErrorEvent extends Error {
8
- constructor(data, options = {}) {
9
- super(options?.message ?? "Error Event", options);
10
- this.data = data;
11
- }
12
- }
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/;
17
- function decodeEventStreamMessage(encoded) {
18
- const lines = encoded.split(EVENT_STREAM_LINE_DELIMITER_REGEX);
19
- const message = {};
20
- for (const line of lines) {
21
- const index = line.indexOf(":");
22
- const key = index === -1 ? line : line.slice(0, index);
23
- const value = index === -1 ? "" : line.slice(index + 1).replace(LEADING_WHITESPACE_REGEX, "");
24
- if (index === 0) {
25
- message.comments ??= [];
26
- message.comments.push(value);
27
- } else if (key === "data") {
28
- if (message.data !== void 0) {
29
- message.data += `
30
- ${value}`;
31
- } else {
32
- message.data = value;
33
- }
34
- } else if (key === "event") {
35
- message.event = value;
36
- } else if (key === "id") {
37
- message.id = value;
38
- } else if (key === "retry") {
39
- const maybeInteger = Number.parseInt(value);
40
- if (Number.isInteger(maybeInteger) && maybeInteger >= 0 && maybeInteger.toString() === value) {
41
- message.retry = maybeInteger;
42
- }
43
- }
44
- }
45
- return message;
46
- }
47
- class EventStreamDecoder {
48
- constructor(onEvent) {
49
- this.onEvent = onEvent;
50
- }
51
- incomplete = "";
52
- trailingCR = false;
53
- feed(chunk) {
54
- if (this.trailingCR && chunk.startsWith("\n")) {
55
- chunk = chunk.slice(1);
56
- }
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);
63
- this.onEvent(message);
64
- }
65
- }
66
- end() {
67
- if (this.incomplete) {
68
- throw new EventStreamDecoderError("Event Stream ended before complete");
69
- }
70
- }
71
- }
72
- class EventStreamDecoderStream extends TransformStream {
73
- constructor() {
74
- let decoder;
75
- super({
76
- start(controller) {
77
- decoder = new EventStreamDecoder((event) => {
78
- controller.enqueue(event);
79
- });
80
- },
81
- transform(chunk) {
82
- decoder.feed(chunk);
83
- },
84
- flush() {
85
- decoder.end();
86
- }
87
- });
88
- }
89
- }
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
- }
95
- function assertEventStreamMessageId(id) {
96
- if (containsEventStreamLineBreak(id)) {
97
- throw new EventStreamEncoderError("Event's id must not contain a carriage return or newline character");
98
- }
99
- }
100
- function assertEventStreamMessageName(event) {
101
- if (containsEventStreamLineBreak(event)) {
102
- throw new EventStreamEncoderError("Event's event must not contain a carriage return or newline character");
103
- }
104
- }
105
- function assertEventStreamMessageRetry(retry) {
106
- if (!Number.isInteger(retry) || retry < 0) {
107
- throw new EventStreamEncoderError("Event's retry must be a integer and >= 0");
108
- }
109
- }
110
- function assertEventStreamMessageComment(comment) {
111
- if (containsEventStreamLineBreak(comment)) {
112
- throw new EventStreamEncoderError("Event's comment must not contain a carriage return or newline character");
113
- }
114
- }
115
- function encodeEventStreamMessageData(data) {
116
- let output = "";
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}
121
- `;
122
- }
123
- }
124
- return output;
125
- }
126
- function encodeEventStreamMessageComments(comments) {
127
- let output = "";
128
- for (const comment of comments ?? []) {
129
- assertEventStreamMessageComment(comment);
130
- output += `: ${comment}
131
- `;
132
- }
133
- return output;
134
- }
135
- function encodeEventStreamMessage(message) {
136
- let output = "";
137
- output += encodeEventStreamMessageComments(message.comments);
138
- if (message.event !== void 0) {
139
- assertEventStreamMessageName(message.event);
140
- output += `event: ${message.event}
141
- `;
142
- }
143
- if (message.retry !== void 0) {
144
- assertEventStreamMessageRetry(message.retry);
145
- output += `retry: ${message.retry}
146
- `;
147
- }
148
- if (message.id !== void 0) {
149
- assertEventStreamMessageId(message.id);
150
- output += `id: ${message.id}
151
- `;
152
- }
153
- output += encodeEventStreamMessageData(message.data);
154
- output += "\n";
155
- return output;
156
- }
157
-
158
- const EVENT_ITERATOR_EVENT_META_SYMBOL = getPackageSymbol("EVENT_ITERATOR_EVENT_META");
159
- const EVENT_ITERATOR_EVENT_SOURCE_SYMBOL = getPackageSymbol("EVENT_ITERATOR_EVENT_SOURCE");
160
- function withEventIteratorEventMeta(container, meta) {
161
- let assertedMeta;
162
- if (meta.id !== void 0) {
163
- assertEventStreamMessageId(meta.id);
164
- assertedMeta ??= {};
165
- assertedMeta.id = meta.id;
166
- }
167
- if (meta.retry !== void 0) {
168
- assertEventStreamMessageRetry(meta.retry);
169
- assertedMeta ??= {};
170
- assertedMeta.retry = meta.retry;
171
- }
172
- if (meta.comments !== void 0) {
173
- for (const comment of meta.comments) {
174
- assertEventStreamMessageComment(comment);
175
- }
176
- assertedMeta ??= {};
177
- assertedMeta.comments = meta.comments;
178
- }
179
- if (!assertedMeta) {
180
- return container;
181
- }
182
- return new Proxy(container, {
183
- get(target, prop, _receiver) {
184
- if (prop === EVENT_ITERATOR_EVENT_SOURCE_SYMBOL) {
185
- return target;
186
- }
187
- if (prop === EVENT_ITERATOR_EVENT_META_SYMBOL) {
188
- return assertedMeta;
189
- }
190
- return getOrBind(target, prop);
191
- }
192
- });
193
- }
194
- function unwrapEventIteratorEvent(container) {
195
- if (!isTypescriptObject(container)) {
196
- return [container, void 0];
197
- }
198
- const meta = container[EVENT_ITERATOR_EVENT_META_SYMBOL];
199
- const target = container[EVENT_ITERATOR_EVENT_SOURCE_SYMBOL] ?? container;
200
- return [target, meta];
201
- }
202
- function getEventIteratorEventMeta(container) {
203
- if (!isTypescriptObject(container)) {
204
- return void 0;
205
- }
206
- return container[EVENT_ITERATOR_EVENT_META_SYMBOL];
207
- }
208
-
209
- export { EVENT_ITERATOR_EVENT_META_SYMBOL, EVENT_ITERATOR_EVENT_SOURCE_SYMBOL, EventIteratorErrorEvent, EventStreamDecoder, EventStreamDecoderError, EventStreamDecoderStream, EventStreamEncoderError, assertEventStreamMessageComment, assertEventStreamMessageId, assertEventStreamMessageName, assertEventStreamMessageRetry, decodeEventStreamMessage, encodeEventStreamMessage, encodeEventStreamMessageComments, encodeEventStreamMessageData, getEventIteratorEventMeta, unwrapEventIteratorEvent, withEventIteratorEventMeta };