webhoster 0.3.2 → 0.3.3

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.
@@ -0,0 +1,29 @@
1
+ name: Publish Package
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions:
9
+ id-token: write # Required for OIDC
10
+ contents: read
11
+
12
+ jobs:
13
+ publish:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-node@v4
19
+ with:
20
+ node-version: '20'
21
+ registry-url: 'https://registry.npmjs.org'
22
+
23
+ # Ensure npm 11.5.1 or later is installed
24
+ - name: Update npm
25
+ run: npm install -g npm@latest
26
+ - run: npm ci
27
+ - run: npm run build --if-present
28
+ - run: npm test
29
+ - run: npm publish
@@ -148,6 +148,7 @@ export default class HttpListener {
148
148
 
149
149
  this.httpServer.keepAliveTimeout = 5000;
150
150
  this.httpServer.requestTimeout = 300_000;
151
+ // @ts-expect-error Missing types
151
152
  this.httpServer.setTimeout(120_000, (socket) => {
152
153
  if (!socket) {
153
154
  console.warn('HTTP socket (unknown) timed out.');
@@ -163,6 +164,7 @@ export default class HttpListener {
163
164
  // console.error('HTTP server error', err);
164
165
  });
165
166
  this.httpServer.addListener('clientError', this.#httpClientErrorListener = (error, socket) => {
167
+ // @ts-expect-error Missing types
166
168
  if (error?.code === 'ECONNRESET') {
167
169
  // console.warn('HTTP client connection reset.');
168
170
  return;
@@ -194,6 +196,7 @@ export default class HttpListener {
194
196
 
195
197
  this.httpsServer.keepAliveTimeout = 5000;
196
198
  this.httpsServer.requestTimeout = 300_000;
199
+ // @ts-expect-error Missing types
197
200
  this.httpsServer.setTimeout(120_000, (socket) => {
198
201
  if (!socket) {
199
202
  // console.warn('HTTPS socket (unknown) timed out.');
@@ -208,6 +211,7 @@ export default class HttpListener {
208
211
  // console.error('HTTPS server error', err);
209
212
  });
210
213
  this.httpsServer.addListener('clientError', this.#httpsClientErrorListener = (error, socket) => {
214
+ // @ts-expect-error Missing types
211
215
  if (error?.code === 'ECONNRESET') {
212
216
  console.warn('HTTPS client connection reset.');
213
217
  return;
@@ -237,77 +241,7 @@ export default class HttpListener {
237
241
  host: this.secureHost,
238
242
  }, () => {
239
243
  this.http2Server.removeListener('error', reject);
240
-
241
- /** @type {Set<WeakRef<Http2Session>>} */
242
- const sessions = new Set();
243
- /** @type {WeakMap<Http2Session, {timestamp:number, identity:string}>} */
244
- const sessionMetadata = new WeakMap();
245
- /** @type {Set<WeakRef<Http2Stream>>} */
246
- const streams = new Set();
247
- /** @type {WeakMap<Http2Stream, {timestamp:number, identity:string, path:string}>} */
248
- const streamMetadata = new WeakMap();
249
- /** @return {void} */
250
- function logUsage() {
251
- if (global.gc) {
252
- console.debug('Perfoming garbage collection.');
253
- global.gc();
254
- }
255
- for (const reference of sessions) {
256
- const session = reference.deref();
257
- if (!session) {
258
- sessions.delete(reference);
259
- continue;
260
- }
261
- const metadata = sessionMetadata.get(session);
262
- if (session.destroyed) {
263
- console.warn('SESSION destroyed from', metadata.identity, 'since', metadata.timestamp);
264
- } else {
265
- console.debug('SESSION alive from', metadata.identity, 'since', metadata.timestamp);
266
- }
267
- }
268
- for (const reference of streams) {
269
- const stream = reference.deref();
270
- if (!stream) {
271
- streams.delete(reference);
272
- continue;
273
- }
274
- const metadata = streamMetadata.get(stream);
275
- if (stream.destroyed) {
276
- console.warn('STREAM destroyed from', metadata.identity, 'since', metadata.timestamp, 'for', metadata.path);
277
- } else {
278
- console.debug('STREAM alive from', metadata.identity, 'since', metadata.timestamp, 'for', metadata.path);
279
- }
280
- }
281
- if (sessions.size) {
282
- console.debug('Active sessions:', sessions.size);
283
- }
284
- if (streams.size) {
285
- console.debug('Active streams:', streams.size);
286
- }
287
- if ('process' in globalThis) {
288
- if ('getActiveResourcesInfo' in globalThis.process) {
289
- console.dir('Active Resources', globalThis.process.getActiveResourcesInfo());
290
- }
291
- if ('_getActiveRequests' in globalThis.process) {
292
- console.dir('Active Requests', globalThis.process._getActiveRequests());
293
- }
294
- if ('_getActiveHandles' in globalThis.process) {
295
- const handles = globalThis.process._getActiveHandles();
296
- for (const handle of handles) {
297
- if (handle instanceof Socket) {
298
- console.debug('Active Handle (Socket)', `${handle.localAddress}:${handle.localPort} <=> ${handle.remoteAddress}:${handle.remotePort}`);
299
- } else if (handle instanceof Server) {
300
- console.debug('Active Handle (Server)', `${handle.address()?.port}`);
301
- } else {
302
- console.debug('Active Handle (unknown)', handle);
303
- }
304
- }
305
- }
306
- }
307
- }
308
- // setInterval(logUsage, 300_000);
309
- // logUsage();
310
-
244
+ // @ts-expect-error Missing types
311
245
  this.http2Server.setTimeout(120_000, (socket) => {
312
246
  if (!socket) {
313
247
  console.warn('HTTP2 socket (unknown) timed out.');
@@ -325,6 +259,7 @@ export default class HttpListener {
325
259
  this.http2Server.addListener('clientError', this.#http2ClientErrorListener = (error, socket) => {
326
260
  // No clear way to signal back to client why a socket has failed because
327
261
  // it's unsure if it's HTTP1 or HTTP2. Just destroy and log server-side.
262
+ // @ts-expect-error Missing types
328
263
  if (error?.code === 'ECONNRESET') {
329
264
  // console.warn('HTTP/2 client connection reset.');
330
265
  } else {
@@ -333,6 +268,7 @@ export default class HttpListener {
333
268
  if (!socket.destroyed) socket.destroy(error);
334
269
  });
335
270
  this.http2Server.addListener('sessionError', this.#http2SessionErrorListener = (error, session) => {
271
+ // @ts-expect-error Missing types
336
272
  if (error?.code === 'ECONNRESET') {
337
273
  // console.warn('HTTP/2 client connection reset.');
338
274
  } else if (error?.message === 'SOCKET_TIMEOUT') {
@@ -344,12 +280,7 @@ export default class HttpListener {
344
280
  });
345
281
 
346
282
  this.http2Server.addListener('session', this.#http2SessionListener = (session) => {
347
- sessions.add(new WeakRef(session));
348
283
  const identity = `${session.socket.remoteFamily}:${session.socket.remoteAddress}:${session.socket.remotePort}`;
349
- sessionMetadata.set(session, {
350
- timestamp: performance.now(),
351
- identity,
352
- });
353
284
  session.setTimeout(60_000, () => {
354
285
  // console.warn(`HTTP/2 session ${identity} timed out.`);
355
286
  session.destroy(new Error('SESSION_TIMEOUT'));
@@ -361,6 +292,7 @@ export default class HttpListener {
361
292
  session.ping((error) => {
362
293
  if (!error) return;
363
294
  if (session.destroyed) return;
295
+ // @ts-expect-error Missing types
364
296
  if (error.code === 'ERR_HTTP2_PING_CANCEL') return;
365
297
  console.error(`Ping to ${identity} failed.`, error);
366
298
  });
@@ -373,49 +305,42 @@ export default class HttpListener {
373
305
 
374
306
  // Logic handlers
375
307
  this.http2Server.addListener('stream', this.#http2StreamListener = (stream, headers) => {
376
- streams.add(new WeakRef(stream));
377
- streamMetadata.set(stream, {
378
- timestamp: performance.now(),
379
- identity: `${stream.session?.socket.remoteFamily}:${stream.session?.socket.remoteAddress}:${stream.session?.socket.remotePort}`,
380
- path: headers[':path'],
381
- });
382
-
383
308
  stream.setTimeout(300_000, () => {
384
309
  stream.destroy(new Error('SOCKET_TIMEOUT'));
385
310
  });
386
311
  stream.addListener('error', (error) => {
312
+ // @ts-expect-error Missing types
387
313
  if (error?.code === 'ECONNRESET') {
388
314
  // console.warn('HTTP/2 stream connection reset.', headers[':path']);
389
315
  } else {
390
316
  console.error('HTTP/2 stream error', headers, error);
391
317
  }
392
318
  });
319
+ // @ts-expect-error Missing types
393
320
  this.httpHandler.handleHttp2Stream(stream, headers).catch((error) => {
394
321
  console.error('HTTP2 handler failed.', error);
395
322
  });
396
323
  });
397
- this.http2Server.addListener('request', this.#http2RequestListener = (request, res) => {
324
+ this.http2Server.addListener('request', this.#http2RequestListener = (request, response) => {
398
325
  if (request.httpVersionMajor >= 2) return;
399
- // @ts-ignore Ignore typings
326
+ // @ts-expect-error Missing types
400
327
  request.setTimeout(300_000, (socket) => {
401
328
  if (!socket) {
402
329
  // console.warn('HTTP1 in HTTP2 request (unknown) timed out.');
403
330
  return;
404
331
  }
405
- // const identity = `${socket.remoteFamily}:${socket.remoteAddress}:${socket.remotePort}`;
406
- // console.warn(`HTTP1 in HTTP2 request ${identity} timed out.`);
407
332
  socket.destroy(new Error('SOCKET_TIMEOUT'));
408
333
  });
409
- res.setTimeout(300_000, (socket) => {
334
+ // @ts-expect-error Missing types
335
+ response.setTimeout(300_000, (socket) => {
410
336
  if (!socket) {
411
337
  // console.warn('HTTP1 in HTTP2 response (unknown) timed out.');
412
338
  return;
413
339
  }
414
- const identity = `${socket.remoteFamily}:${socket.remoteAddress}:${socket.remotePort}`;
415
- // console.warn(`HTTP1 in HTTP2 response ${identity} timed out.`);
416
340
  socket.destroy(new Error('SOCKET_TIMEOUT'));
417
341
  });
418
342
  request.addListener('error', (error) => {
343
+ // @ts-expect-error Missing types
419
344
  if (error?.code === 'ECONNRESET') {
420
345
  // console.warn('Request stream connection reset.', req.url);
421
346
  } else {
@@ -425,17 +350,18 @@ export default class HttpListener {
425
350
  request.destroy(error);
426
351
  }
427
352
  });
428
- res.addListener('error', (error) => {
353
+ response.addListener('error', (error) => {
354
+ // @ts-expect-error Missing types
429
355
  if (error?.code === 'ECONNRESET') {
430
356
  // console.warn('Response stream connection reset.', req.url);
431
357
  } else {
432
358
  console.error('Response stream error', request.url, request.headers, error);
433
359
  }
434
- if (!res.destroyed) {
435
- res.destroy(error);
360
+ if (!response.destroyed) {
361
+ response.destroy(error);
436
362
  }
437
363
  });
438
- this.httpHandler.handleHttp1Request(request, res).catch((error) => {
364
+ this.httpHandler.handleHttp1Request(request, response).catch((error) => {
439
365
  console.error('HTTP1 in HTTP2 handler failed.', error);
440
366
  });
441
367
  });
@@ -2,7 +2,6 @@
2
2
 
3
3
  import { TextDecoder } from 'node:util';
4
4
  import AsyncObject from '../utils/AsyncObject.js';
5
- import { noop } from '../utils/function.js';
6
5
  import RequestHeaders from './RequestHeaders.js';
7
6
 
8
7
  /**
@@ -11,7 +10,6 @@ import RequestHeaders from './RequestHeaders.js';
11
10
  */
12
11
 
13
12
  const BUFFER_SIZE = 4096;
14
- const STREAM_WAIT_MS = 0;
15
13
 
16
14
  /** @type {WeakMap<HttpRequest, RequestReader>} */
17
15
  const cache = new WeakMap();
@@ -45,8 +43,6 @@ export default class RequestReader {
45
43
  const hp = new RequestHeaders(this.request);
46
44
  let data = Buffer.allocUnsafe(Math.min(BUFFER_SIZE, hp.contentLength || BUFFER_SIZE));
47
45
  let bytesWritten = 0;
48
- /** @type {NodeJS.Timeout} */
49
- let sendPingTimeout = null;
50
46
  this.request.stream.on('readable', () => {
51
47
  let chunk;
52
48
  // eslint-disable-next-line no-cond-assign
@@ -70,15 +66,8 @@ export default class RequestReader {
70
66
  }
71
67
  bytesWritten += buffer.copy(data, bytesWritten);
72
68
  }
73
- clearTimeout(sendPingTimeout);
74
- if (this.request.canPing) {
75
- sendPingTimeout = setTimeout(() => {
76
- this.request.ping().catch(noop);
77
- }, STREAM_WAIT_MS);
78
- }
79
69
  });
80
70
  this.request.stream.on('end', () => {
81
- clearTimeout(sendPingTimeout);
82
71
  if (data.length > bytesWritten) {
83
72
  // Must partition to clear unsafe allocation
84
73
  data = data.subarray(0, bytesWritten);
@@ -145,6 +145,7 @@ export default class HttpHandler {
145
145
 
146
146
  // Check if error handler
147
147
  const isErrorHandler = (typeof middleware === 'object'
148
+ && 'onError' in middleware
148
149
  && typeof middleware.onError === 'function');
149
150
 
150
151
  let value = middleware;
@@ -186,6 +187,7 @@ export default class HttpHandler {
186
187
  }
187
188
 
188
189
  // Sync operation returned Promise
190
+ // @ts-expect-error TS improperly thinks result can be null
189
191
  if (typeof result === 'object' && typeof result.then === 'function') {
190
192
  if (isErrorHandler) transaction.error = null;
191
193
  result = await result;
@@ -216,6 +218,7 @@ export default class HttpHandler {
216
218
  const { treeIndex } = transaction.state;
217
219
  treeIndex.push(-1);
218
220
  const { length } = value;
221
+ // eslint-disable-next-line no-plusplus
219
222
  for (let index = 0; index < length; index++) {
220
223
  const innerMiddleware = value[index];
221
224
  treeIndex[treeIndex.length - 1] += 1;
@@ -333,6 +336,7 @@ export default class HttpHandler {
333
336
 
334
337
  const request = new HttpRequest({
335
338
  headers,
339
+ // @ts-expect-error JSDoc syntax limitation
336
340
  method,
337
341
  stream: incomingMessage,
338
342
 
@@ -428,7 +432,7 @@ export default class HttpHandler {
428
432
  }
429
433
  }
430
434
 
431
- // eslint-disable-next-line @typescript-eslint/no-this-alias
435
+ // eslint-disable-next-line @typescript-eslint/no-this-alias, unicorn/no-this-assignment
432
436
  const context = this;
433
437
 
434
438
  /** @type {Promise<any>[]} */
@@ -436,6 +440,7 @@ export default class HttpHandler {
436
440
 
437
441
  const request = new HttpRequest({
438
442
  headers,
443
+ // @ts-expect-error JSDoc syntax limitation
439
444
  method,
440
445
  stream,
441
446
 
@@ -492,7 +497,7 @@ export default class HttpHandler {
492
497
  'cache-control',
493
498
  ]) {
494
499
  if (passedHeader in headers) {
495
- // @ts-ignore Coerce
500
+ // @ts-expect-error Coerce
496
501
  newHeaders[passedHeader] = headers[passedHeader];
497
502
  }
498
503
  }
@@ -500,10 +505,15 @@ export default class HttpHandler {
500
505
  // Build promise function
501
506
  const promiseFunction = async () => {
502
507
  try {
508
+ /** @type {import('node:http2').ServerHttp2Stream} */
503
509
  const pushStream = await new Promise((resolve, reject) => {
504
- stream.pushStream(newHeaders, ((error, newStream) => (error ? reject(error) : resolve(newStream))));
510
+ stream.pushStream(
511
+ newHeaders,
512
+ ((error, newStream) => (error ? reject(error) : resolve(newStream))),
513
+ );
505
514
  });
506
515
  pushStream.addListener('error', (error) => {
516
+ // @ts-expect-error Missing types
507
517
  if (error?.code === 'ECONNRESET') {
508
518
  console.warn('HTTP/2 stream connection reset.', headers[':path']);
509
519
  } else {
@@ -140,7 +140,9 @@ export default class HttpRequest {
140
140
  if (this.#readable === undefined) {
141
141
  if (this.method === 'GET' || this.method === 'HEAD') {
142
142
  this.#readable = null;
143
+ // @ts-expect-error Missing types
143
144
  } else if (Readable.toWeb) {
145
+ // @ts-expect-error Missing types
144
146
  this.#readable = Readable.toWeb(this.stream);
145
147
  this.#bodyUsed = true;
146
148
  } else {
@@ -226,7 +228,7 @@ export default class HttpRequest {
226
228
  }
227
229
 
228
230
  /**
229
- * @return {Promise<ArrayBuffer>}
231
+ * @return {Promise<ArrayBufferLike>}
230
232
  */
231
233
  async arrayBuffer() {
232
234
  try {
@@ -264,7 +266,7 @@ export default class HttpRequest {
264
266
  try {
265
267
  const module = await import('node:buffer');
266
268
  if ('Blob' in module === false) throw new Error('NOT_SUPPORTED');
267
- BlobClass = module.Blob;
269
+ BlobClass = /** @type {typeof Blob} */ (module.Blob);
268
270
  } catch {
269
271
  BlobClass = null;
270
272
  }
@@ -389,6 +391,7 @@ export default class HttpRequest {
389
391
  }
390
392
  }
391
393
 
394
+ // eslint-disable-next-line class-methods-use-this
392
395
  async formData() {
393
396
  throw new Error('UNSUPPORTED_MEDIA_TYPE');
394
397
  }
@@ -124,6 +124,7 @@ export default class HttpResponse {
124
124
  async sendRaw(body) {
125
125
  this.body = body;
126
126
  await new Promise((resolve, reject) => {
127
+ // @ts-expect-error Error is any
127
128
  this.stream.end(body, (error) => (error ? reject(error) : resolve()));
128
129
  });
129
130
  return 0;
@@ -135,7 +136,7 @@ export default class HttpResponse {
135
136
  }
136
137
 
137
138
  /**
138
- * @param {Transform} stream
139
+ * @param {import('stream').Transform} stream
139
140
  * @return {this}
140
141
  */
141
142
  addUpstream(stream) {
@@ -162,6 +163,7 @@ export default class HttpResponse {
162
163
  // Called directly by user and needs finalizer calls
163
164
 
164
165
  this.isStreaming = true;
166
+ // eslint-disable-next-line no-plusplus
165
167
  for (let index = 0; index < this.finalizers.length; index++) {
166
168
  const process = this.finalizers[index];
167
169
  const result = process(this);
@@ -183,11 +185,13 @@ export default class HttpResponse {
183
185
  ];
184
186
  }
185
187
 
186
- this.#pipeline = array[0];
187
- // @ts-ignore Bad typings
188
+ // eslint-disable-next-line prefer-destructuring
189
+ this.#pipeline = /** @type {Writable} */ (array[0]);
190
+ // @ts-expect-error Bad typings
188
191
  pipeline(array, (error) => {
189
192
  this.#pipelineComplete = true;
190
193
  let nextCallback;
194
+ // eslint-disable-next-line no-cond-assign
191
195
  while ((nextCallback = this.#pipelineCallbacks.shift()) != null) {
192
196
  nextCallback(error);
193
197
  }
@@ -282,6 +286,7 @@ export default class HttpResponse {
282
286
  /** @type {void|Promise<boolean|void>} */
283
287
  let pendingPromise;
284
288
  let index;
289
+ // eslint-disable-next-line no-plusplus
285
290
  for (index = 0; index < this.finalizers.length; index++) {
286
291
  const process = this.finalizers[index];
287
292
  if (needsAsync) {
@@ -303,6 +308,7 @@ export default class HttpResponse {
303
308
  if (pendingPromise) {
304
309
  pendingPromise.then(async (initialResult) => {
305
310
  if (initialResult !== false) {
311
+ // eslint-disable-next-line no-plusplus
306
312
  for (index = 0; index < pendingProcessors.length; index++) {
307
313
  const process = pendingProcessors[index];
308
314
  const result = process(this);
@@ -1,5 +1,6 @@
1
1
  import { Transform } from 'node:stream';
2
2
  import {
3
+ // @ts-expect-error Bad typings
3
4
  BrotliDecompress, Gunzip, Inflate,
4
5
  } from 'node:zlib';
5
6
 
@@ -69,17 +70,20 @@ export default class ContentDecoderMiddleware {
69
70
  const gzipOptions = { chunkSize: this.chunkSize };
70
71
  const newDownstream = new Transform({
71
72
 
72
- read: (...args) => {
73
+ read: (...arguments_) => {
73
74
  if (!initialized) {
74
75
  /** @type {import("zlib").Gzip} */
75
76
  switch (contentEncoding) {
76
77
  case 'deflate':
78
+ // @ts-expect-error Bad typings
77
79
  gzipStream = new Inflate(gzipOptions);
78
80
  break;
79
81
  case 'gzip':
82
+ // @ts-expect-error Bad typings
80
83
  gzipStream = new Gunzip(gzipOptions);
81
84
  break;
82
85
  case 'br':
86
+ // @ts-expect-error Bad typings
83
87
  gzipStream = new BrotliDecompress(gzipOptions);
84
88
  break;
85
89
  default:
@@ -89,7 +93,7 @@ export default class ContentDecoderMiddleware {
89
93
  // To newDownstream <= gzipStream < =inputStream
90
94
 
91
95
  // Forward errors
92
- gzipStream.on('error', (err) => inputStream.emit('error', err));
96
+ gzipStream.on('error', (error) => inputStream.emit('error', error));
93
97
  gzipStream.on('data', (chunk) => newDownstream.push(chunk));
94
98
 
95
99
  inputStream.on('end', () => gzipStream.end());
@@ -104,12 +108,13 @@ export default class ContentDecoderMiddleware {
104
108
  initialized = true;
105
109
  }
106
110
 
107
- Transform.prototype._read.call(this, ...args);
111
+ // eslint-disable-next-line no-underscore-dangle
112
+ Transform.prototype._read.call(this, ...arguments_);
108
113
  },
109
114
  transform: (chunk, chunkEncoding, callback) => {
110
- gzipStream.write(chunk, (err) => {
111
- if (err) console.error(err);
112
- callback(err);
115
+ gzipStream.write(chunk, (error) => {
116
+ if (error) console.error(error);
117
+ callback(error);
113
118
  });
114
119
  },
115
120
  flush: (callback) => {
@@ -129,7 +134,6 @@ export default class ContentDecoderMiddleware {
129
134
  },
130
135
  });
131
136
 
132
- newDownstream.tag = 'ContentDecoder';
133
137
  inputStream = request.addDownstream(newDownstream, { autoPause: true });
134
138
 
135
139
  return CONTINUE;
@@ -75,8 +75,9 @@ export default class ContentEncoderMiddleware {
75
75
  let encoding = COMPATIBLE_ENCODINGS[0];
76
76
  const allowWildcards = (encodings.get('*')?.q !== 0);
77
77
  const encodingEntries = [...encodings.entries()];
78
- // @ts-expect-error Cannot cast to COMPATIBLE_ENCODINGS
79
- encoding = (encodingEntries.find(([value, spec]) => spec.q !== 0 && COMPATIBLE_ENCODINGS.includes(value))?.[0]);
78
+ encoding = /** @type {COMPATIBLE_ENCODING} */ (encodingEntries
79
+ .find(([value, spec]) => spec.q !== 0
80
+ && COMPATIBLE_ENCODINGS.includes(/** @type {COMPATIBLE_ENCODING} */ (value)))?.[0]);
80
81
  if (allowWildcards && (encoding === '*' || !encoding)) {
81
82
  // Server preference
82
83
  // Get first compatible encoding not specified
@@ -154,7 +155,7 @@ export default class ContentEncoderMiddleware {
154
155
  encoding = getContentEncoding().toLowerCase?.();
155
156
  }
156
157
 
157
- const isEventStream = response.headers['content-type']?.includes('text/event-stream');
158
+ const isEventStream = /** @type {string|null} */ (response.headers['content-type'])?.includes('text/event-stream');
158
159
 
159
160
  let newStream;
160
161
  switch (encoding) {
package/package.json CHANGED
@@ -24,7 +24,16 @@
24
24
  "node": ">v16.13"
25
25
  },
26
26
  "exports": {
27
- "./*": "./*"
27
+ "./data/*": "./data/*",
28
+ "./errata/*": "./errata/*",
29
+ "./examples/*": "./examples/*",
30
+ "./helpers/*": "./helpers/*",
31
+ "./lib/*": "./lib/*",
32
+ "./middlewares/*": "./middlewares/*",
33
+ "./polyfills/*": "./polyfills/*",
34
+ "./templates/*": "./templates/*",
35
+ "./types/*": "./types/*",
36
+ "./utils/*": "./utils/*"
28
37
  },
29
38
  "keywords": [
30
39
  "http",
@@ -42,6 +51,7 @@
42
51
  "scripts": {
43
52
  "debug-test": "ava --serial",
44
53
  "test": "c8 ava",
54
+ "prepublishOnly": "rm -Rf typings && tsc --emitDeclarationOnly",
45
55
  "pretestallsync": "rimraf coverage",
46
56
  "testallsync": "scripts/test-all-sync.sh",
47
57
  "posttestallsync": "c8 report",
@@ -50,5 +60,6 @@
50
60
  "posttestall": "c8 report"
51
61
  },
52
62
  "type": "module",
53
- "version": "0.3.2"
54
- }
63
+ "types": "typings/index.d.ts",
64
+ "version": "0.3.3"
65
+ }
package/tsconfig.json CHANGED
@@ -1,12 +1,30 @@
1
1
  {
2
2
  "compilerOptions": {
3
+ "allowJs": true,
3
4
  "checkJs": true,
4
5
  "noImplicitAny": true,
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "declarationDir": "typings",
9
+ "outDir": "/dev/null",
5
10
  "target": "es2022",
6
11
  "module": "esnext",
7
12
  "moduleResolution": "node"
8
13
  },
14
+ "include": [
15
+ "./data/*",
16
+ "./errata/*",
17
+ "./examples/*",
18
+ "./helpers/*",
19
+ "./lib/*",
20
+ "./middlewares/*",
21
+ "./polyfills/*",
22
+ "./templates/*",
23
+ "./types/*",
24
+ "./utils/*"
25
+ ],
9
26
  "exclude": [
10
- "**/node_modules/*"
27
+ "**/node_modules/*",
28
+ "**/test/*"
11
29
  ]
12
30
  }
package/types/index.js CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  /** @typedef {import('node:stream').Duplex} Duplex */
18
18
 
19
- /** @typedef {import('./typings').Middleware} Middleware */
19
+ /** @typedef {import('./typings.js').Middleware} Middleware */
20
20
 
21
21
  /** @typedef {true|false|0} MiddlewareFlowInstruction */
22
22