webhoster 0.1.1 → 0.3.1

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.
Files changed (87) hide show
  1. package/.eslintrc.json +74 -58
  2. package/.github/copilot-instructions.md +100 -0
  3. package/.github/workflows/test-matrix.yml +37 -0
  4. package/.test/benchmark.js +28 -0
  5. package/.test/constants.js +4 -0
  6. package/{test → .test}/http2server.js +1 -1
  7. package/{test → .test}/httpserver.js +1 -1
  8. package/{test → .test}/index.js +178 -192
  9. package/.test/multipromise.js +32 -0
  10. package/{test → .test}/tls.js +3 -3
  11. package/{test → .test}/urlencoded.js +3 -0
  12. package/.vscode/launch.json +24 -3
  13. package/README.md +116 -90
  14. package/data/CookieObject.js +14 -14
  15. package/errata/socketio.js +6 -11
  16. package/examples/starter.js +11 -0
  17. package/helpers/HeadersParser.js +7 -8
  18. package/helpers/HttpListener.js +387 -42
  19. package/helpers/RequestHeaders.js +43 -36
  20. package/helpers/RequestReader.js +27 -26
  21. package/helpers/ResponseHeaders.js +47 -36
  22. package/jsconfig.json +1 -1
  23. package/lib/HttpHandler.js +447 -277
  24. package/lib/HttpRequest.js +383 -39
  25. package/lib/HttpResponse.js +316 -52
  26. package/lib/HttpTransaction.js +146 -0
  27. package/middleware/AutoHeadersMiddleware.js +73 -0
  28. package/middleware/CORSMiddleware.js +45 -47
  29. package/middleware/CaseInsensitiveHeadersMiddleware.js +5 -11
  30. package/middleware/ContentDecoderMiddleware.js +81 -35
  31. package/middleware/ContentEncoderMiddleware.js +179 -132
  32. package/middleware/ContentLengthMiddleware.js +66 -41
  33. package/middleware/ContentWriterMiddleware.js +5 -5
  34. package/middleware/HashMiddleware.js +68 -40
  35. package/middleware/HeadMethodMiddleware.js +24 -21
  36. package/middleware/MethodMiddleware.js +29 -36
  37. package/middleware/PathMiddleware.js +49 -66
  38. package/middleware/ReadFormData.js +99 -0
  39. package/middleware/SendJsonMiddleware.js +131 -0
  40. package/middleware/SendStringMiddleware.js +87 -0
  41. package/package.json +38 -29
  42. package/polyfill/FormData.js +164 -0
  43. package/rollup.config.js +0 -1
  44. package/scripts/check-teapot.mjs +40 -0
  45. package/scripts/test-all-sync.sh +6 -0
  46. package/scripts/test-all.sh +7 -0
  47. package/templates/starter.js +55 -0
  48. package/test/fixtures/stream.js +68 -0
  49. package/test/helpers/HttpListener/construct.js +18 -0
  50. package/test/helpers/HttpListener/customOptions.js +22 -0
  51. package/test/helpers/HttpListener/doubleCreate.js +40 -0
  52. package/test/helpers/HttpListener/events.js +77 -0
  53. package/test/helpers/HttpListener/http.js +31 -0
  54. package/test/helpers/HttpListener/http2.js +41 -0
  55. package/test/helpers/HttpListener/https.js +38 -0
  56. package/test/helpers/HttpListener/startAll.js +31 -0
  57. package/test/helpers/HttpListener/stopNotStarted.js +23 -0
  58. package/test/lib/HttpHandler/class.js +8 -0
  59. package/test/lib/HttpHandler/handleRequest.js +11 -0
  60. package/test/lib/HttpHandler/middleware.js +941 -0
  61. package/test/lib/HttpHandler/parse.js +41 -0
  62. package/test/lib/HttpRequest/class.js +8 -0
  63. package/test/lib/HttpRequest/downstream.js +171 -0
  64. package/test/lib/HttpRequest/properties.js +101 -0
  65. package/test/lib/HttpRequest/read.js +518 -0
  66. package/test/lib/HttpResponse/class.js +8 -0
  67. package/test/lib/HttpResponse/properties.js +59 -0
  68. package/test/lib/HttpResponse/send.js +275 -0
  69. package/test/lib/HttpTransaction/class.js +8 -0
  70. package/test/lib/HttpTransaction/ping.js +50 -0
  71. package/test/lib/HttpTransaction/push.js +89 -0
  72. package/test/middleware/SendJsonMiddleware.js +222 -0
  73. package/test/sanity.js +10 -0
  74. package/test/templates/error-teapot.js +47 -0
  75. package/test/templates/starter.js +93 -0
  76. package/tsconfig.json +12 -0
  77. package/types/index.js +61 -34
  78. package/types/typings.d.ts +8 -9
  79. package/utils/AsyncObject.js +6 -3
  80. package/utils/CaseInsensitiveObject.js +2 -3
  81. package/utils/function.js +1 -7
  82. package/utils/headers.js +42 -0
  83. package/utils/qualityValues.js +1 -1
  84. package/utils/stream.js +4 -20
  85. package/index.cjs +0 -3190
  86. package/test/constants.js +0 -4
  87. /package/{test → .test}/cookietester.js +0 -0
@@ -1,6 +1,6 @@
1
1
  import HeadersHandler from './HeadersParser.js';
2
2
 
3
- /** @typedef {import('../types').HttpRequest} HttpRequest */
3
+ /** @typedef {import('../lib/HttpRequest.js').default} HttpRequest */
4
4
 
5
5
  /**
6
6
  * @param {string} cookieString
@@ -15,42 +15,50 @@ function getEntriesFromCookie(cookieString) {
15
15
  name = '';
16
16
  value = pair.trim();
17
17
  } else {
18
- name = pair.substr(0, indexOfEquals).trim();
19
- value = pair.substr(indexOfEquals + 1).trim();
18
+ name = pair.slice(0, indexOfEquals).trim();
19
+ value = pair.slice(indexOfEquals + 1).trim();
20
20
  }
21
21
  const firstQuote = value.indexOf('"');
22
22
  const lastQuote = value.lastIndexOf('"');
23
23
  if (firstQuote !== -1 && lastQuote !== -1) {
24
- value = value.substring(firstQuote + 1, lastQuote);
24
+ value = value.slice(firstQuote + 1, lastQuote);
25
25
  }
26
26
  return [name, value];
27
27
  });
28
28
  }
29
29
 
30
+ /** @type {WeakMap<HttpRequest, RequestHeaders>} */
31
+ const instanceCache = new WeakMap();
32
+
30
33
  export default class RequestHeaders extends HeadersHandler {
31
- /** @param {HttpRequest} req */
32
- constructor(req) {
33
- super(req.headers);
34
+ /** @param {HttpRequest} request */
35
+ constructor(request) {
36
+ const instance = instanceCache.get(request);
37
+ if (instance) return instance;
38
+ super(request.headers);
39
+ instanceCache.set(request, this);
40
+ }
41
+
42
+ /**
43
+ * @param {HttpRequest} request
44
+ * @return {{get:(name:string)=>string,all:(name:string)=>string[]}}
45
+ */
46
+ static cookies(request) {
47
+ const instance = new RequestHeaders(request);
48
+ return instance.cookies;
34
49
  }
35
50
 
36
51
  /** @type {Object<string,string[]>} */
37
52
  #cookiesProxy = null;
38
53
 
54
+ /** @return {{get:(name:string)=>string,all:(name:string)=>string[]}} */
39
55
  get cookies() {
40
56
  // eslint-disable-next-line @typescript-eslint/no-this-alias
41
57
  const instance = this;
42
58
  return {
43
- /**
44
- * @param {string} name
45
- * @return {string}
46
- */
47
59
  get(name) {
48
60
  return instance.cookieEntries[name]?.[0];
49
61
  },
50
- /**
51
- * @param {string} name
52
- * @return {string[]}
53
- */
54
62
  all(name) {
55
63
  return instance.cookieEntries[name] ?? [];
56
64
  },
@@ -73,42 +81,41 @@ export default class RequestHeaders extends HeadersHandler {
73
81
  const cookieString = (instance.headers.cookie ?? '');
74
82
  const split = cookieString.split(';');
75
83
  const values = [];
76
- for (let i = 0; i < split.length; i += 1) {
77
- const [key, value] = split[i].split('=');
84
+ for (const element of split) {
85
+ const [key, value] = element.split('=');
78
86
  if (key.trim() === cookieName) values.push(value);
79
87
  }
80
88
  const arrayProxy = new Proxy(values, {
81
- get: (arrayTarget, arrayProp, receiver) => {
82
- if (typeof arrayProp !== 'string') {
83
- return Reflect.get(arrayTarget, arrayProp, receiver);
89
+ get: (arrayTarget, arrayProperty, receiver) => {
90
+ if (typeof arrayProperty !== 'string') {
91
+ return Reflect.get(arrayTarget, arrayProperty, receiver);
84
92
  }
85
- if (arrayProp === 'length') {
93
+ if (arrayProperty === 'length') {
86
94
  return getEntriesFromCookie(instance.headers.cookie ?? '')
87
95
  .filter(([key]) => (key === cookieName)).length;
88
96
  }
89
- if (Number.isNaN(parseInt(arrayProp, 10))) {
90
- return Reflect.get(arrayTarget, arrayProp, receiver);
97
+ if (Number.isNaN(Number.parseInt(arrayProperty, 10))) {
98
+ return Reflect.get(arrayTarget, arrayProperty, receiver);
91
99
  }
92
100
  const entries = getEntriesFromCookie(instance.headers.cookie ?? '');
93
101
  let count = 0;
94
- for (let i = 0; i < entries.length; i += 1) {
95
- const entry = entries[i];
102
+ for (const entry of entries) {
96
103
  if (entry[0] === cookieName) {
97
- if (arrayProp === count.toString()) {
104
+ if (arrayProperty === count.toString()) {
98
105
  return entry[1];
99
106
  }
100
107
  count += 1;
101
108
  }
102
109
  }
103
- return Reflect.get(arrayTarget, arrayProp, receiver);
110
+ return Reflect.get(arrayTarget, arrayProperty, receiver);
104
111
  },
105
- set: (arrayTarget, arrayProp, value, receiver) => {
106
- Reflect.set(arrayTarget, arrayProp, value, receiver);
107
- if (typeof arrayProp !== 'string') return true;
108
- const result = getEntriesFromCookie(instance.headers.cookie ?? '').reduce((prev, curr) => {
109
- if (!curr[0]) return prev;
110
- if (curr[0] === cookieName) return prev;
111
- return `${prev};${curr[0]}=${curr[1]}`;
112
+ set: (arrayTarget, arrayProperty, value, receiver) => {
113
+ Reflect.set(arrayTarget, arrayProperty, value, receiver);
114
+ if (typeof arrayProperty !== 'string') return true;
115
+ const result = getEntriesFromCookie(instance.headers.cookie ?? '').reduce((previous, current) => {
116
+ if (!current[0]) return previous;
117
+ if (current[0] === cookieName) return previous;
118
+ return `${previous};${current[0]}=${current[1]}`;
112
119
  }, arrayTarget.map((v) => `${cookieName}=${v}`).join(';'));
113
120
  instance.headers.cookie = result;
114
121
  return true;
@@ -122,8 +129,8 @@ export default class RequestHeaders extends HeadersHandler {
122
129
  const split = cookieString.split(';');
123
130
  /** @type {string[]} */
124
131
  const keys = [];
125
- for (let i = 0; i < split.length; i += 1) {
126
- const [key] = split[i].split('=');
132
+ for (const element of split) {
133
+ const [key] = element.split('=');
127
134
  const trimmed = key?.trim();
128
135
  if (trimmed && !keys.includes(trimmed)) {
129
136
  keys.push(trimmed);
@@ -1,6 +1,6 @@
1
1
  /** @typedef {import('../types').HttpRequest} HttpRequest */
2
2
 
3
- import { TextDecoder } from 'util';
3
+ import { TextDecoder } from 'node:util';
4
4
  import AsyncObject from '../utils/AsyncObject.js';
5
5
  import { noop } from '../utils/function.js';
6
6
  import RequestHeaders from './RequestHeaders.js';
@@ -43,7 +43,7 @@ export default class RequestReader {
43
43
  if (this.#buffer.isBusy() || this.#buffer.hasValue()) return this.#buffer.get();
44
44
  this.#buffer.prepare();
45
45
  const hp = new RequestHeaders(this.request);
46
- let data = Buffer.alloc(Math.min(BUFFER_SIZE, hp.contentLength || BUFFER_SIZE));
46
+ let data = Buffer.allocUnsafe(Math.min(BUFFER_SIZE, hp.contentLength || BUFFER_SIZE));
47
47
  let bytesWritten = 0;
48
48
  /** @type {NodeJS.Timeout} */
49
49
  let sendPingTimeout = null;
@@ -64,7 +64,7 @@ export default class RequestReader {
64
64
  while (newLength < buffer.length + data.length) {
65
65
  newLength *= 2;
66
66
  }
67
- const newBuffer = Buffer.alloc(newLength);
67
+ const newBuffer = Buffer.allocUnsafe(newLength);
68
68
  data.copy(newBuffer);
69
69
  data = newBuffer;
70
70
  }
@@ -80,12 +80,13 @@ export default class RequestReader {
80
80
  this.request.stream.on('end', () => {
81
81
  clearTimeout(sendPingTimeout);
82
82
  if (data.length > bytesWritten) {
83
+ // Must partition to clear unsafe allocation
83
84
  data = data.subarray(0, bytesWritten);
84
85
  }
85
86
  this.#buffer.set(data);
86
87
  });
87
- this.request.stream.on('error', (err) => {
88
- this.#buffer.reset(err);
88
+ this.request.stream.on('error', (error) => {
89
+ this.#buffer.reset(error);
89
90
  });
90
91
  return this.#buffer.get();
91
92
  }
@@ -93,9 +94,9 @@ export default class RequestReader {
93
94
  /** @return {Promise<string>} */
94
95
  readString() {
95
96
  return this.readBuffer().then((buffer) => {
96
- const reqHeaders = new RequestHeaders(this.request);
97
+ const requestHeaders = new RequestHeaders(this.request);
97
98
  // TODO: Compare TextDecoder, Buffer.from(), and StringDecoder performance
98
- const decoder = new TextDecoder(reqHeaders.charset || 'utf-8');
99
+ const decoder = new TextDecoder(requestHeaders.charset || 'utf-8');
99
100
  return decoder.decode(buffer);
100
101
  });
101
102
  }
@@ -116,38 +117,38 @@ export default class RequestReader {
116
117
  */
117
118
  readUrlEncoded() {
118
119
  // https://url.spec.whatwg.org/#urlencoded-parsing
119
- const reqHeaders = new RequestHeaders(this.request);
120
- const decoder = new TextDecoder(reqHeaders.charset || 'utf-8');
120
+ const requestHeaders = new RequestHeaders(this.request);
121
+ const decoder = new TextDecoder(requestHeaders.charset || 'utf-8');
121
122
  return this.readBuffer().then((buffer) => {
122
123
  const sequences = [];
123
124
  let startIndex = 0;
124
- for (let i = 0; i < buffer.length; i += 1) {
125
- if (buffer[i] === 0x26) {
126
- sequences.push(buffer.subarray(startIndex, i));
127
- startIndex = i + 1;
125
+ for (let index = 0; index < buffer.length; index += 1) {
126
+ if (buffer[index] === 0x26) {
127
+ sequences.push(buffer.subarray(startIndex, index));
128
+ startIndex = index + 1;
128
129
  }
129
- if (i === buffer.length - 1) {
130
- sequences.push(buffer.subarray(startIndex, i));
130
+ if (index === buffer.length - 1) {
131
+ sequences.push(buffer.subarray(startIndex, index));
131
132
  }
132
133
  }
133
134
  /** @type {[string, string][]} */
134
135
  const output = [];
135
- sequences.forEach((bytes) => {
136
- if (!bytes.length) return;
136
+ for (const bytes of sequences) {
137
+ if (!bytes.length) continue;
137
138
 
138
139
  // Find 0x3D and replace 0x2B in one loop for better performance
139
140
  let indexOf0x3D = -1;
140
- for (let i = 0; i < bytes.length; i += 1) {
141
- switch (bytes[i]) {
141
+ for (let index = 0; index < bytes.length; index += 1) {
142
+ switch (bytes[index]) {
142
143
  case 0x3D:
143
144
  if (indexOf0x3D === -1) {
144
- indexOf0x3D = i;
145
+ indexOf0x3D = index;
145
146
  }
146
147
  break;
147
148
  case 0x2B:
148
149
  // Replace bytes on original stream for memory conservation
149
150
  // eslint-disable-next-line no-param-reassign
150
- bytes[i] = 0x20;
151
+ bytes[index] = 0x20;
151
152
  break;
152
153
  default:
153
154
  }
@@ -164,7 +165,7 @@ export default class RequestReader {
164
165
  const nameString = decodeURIComponent(decoder.decode(name));
165
166
  const valueString = decodeURIComponent(decoder.decode(value));
166
167
  output.push([nameString, valueString]);
167
- });
168
+ }
168
169
  return output;
169
170
  });
170
171
  }
@@ -184,8 +185,8 @@ export default class RequestReader {
184
185
  * @return {Promise<Object<string, any>|null>}
185
186
  */
186
187
  readObject() {
187
- const reqHeaders = new RequestHeaders(this.request);
188
- const mediaType = reqHeaders.mediaType?.toLowerCase() ?? '';
188
+ const requestHeaders = new RequestHeaders(this.request);
189
+ const mediaType = requestHeaders.mediaType?.toLowerCase() ?? '';
189
190
  switch (mediaType) {
190
191
  case 'application/json':
191
192
  return this.readJSON();
@@ -201,8 +202,8 @@ export default class RequestReader {
201
202
  * @return {Promise<Object<string,any>|string|Buffer>}
202
203
  */
203
204
  read() {
204
- const reqHeaders = new RequestHeaders(this.request);
205
- const mediaType = reqHeaders.mediaType?.toLowerCase() ?? '';
205
+ const requestHeaders = new RequestHeaders(this.request);
206
+ const mediaType = requestHeaders.mediaType?.toLowerCase() ?? '';
206
207
  switch (mediaType) {
207
208
  case 'application/json':
208
209
  return this.readJSON();
@@ -2,7 +2,7 @@ import CookieObject from '../data/CookieObject.js';
2
2
 
3
3
  import HeadersHandler from './HeadersParser.js';
4
4
 
5
- /** @typedef {import('../types').HttpResponse} HttpResponse */
5
+ /** @typedef {import('../lib/HttpResponse.js').default} HttpResponse */
6
6
  /** @typedef {import('../types').CookieDetails} CookieDetails */
7
7
 
8
8
  /** @type {(keyof CookieDetails)[]} */
@@ -18,10 +18,23 @@ const COOKIE_DETAIL_KEYS = [
18
18
  'sameSite',
19
19
  ];
20
20
 
21
+ /** @type {WeakMap<HttpResponse, ResponseHeaders>} */
22
+ const instanceCache = new WeakMap();
23
+
21
24
  export default class ResponseHeaders extends HeadersHandler {
22
25
  /** @param {HttpResponse} res */
26
+ // @ts-ignore Cached constructor
23
27
  constructor(res) {
28
+ const instance = instanceCache.get(res);
29
+ if (instance) return instance;
24
30
  super(res.headers);
31
+ instanceCache.set(res, this);
32
+ }
33
+
34
+ /** @param {HttpResponse} res */
35
+ static cookies(res) {
36
+ const instance = new ResponseHeaders(res);
37
+ return instance.cookies;
25
38
  }
26
39
 
27
40
  /** @type {CookieObject[]} */
@@ -29,8 +42,8 @@ export default class ResponseHeaders extends HeadersHandler {
29
42
 
30
43
  /** @type {ProxyHandler<CookieObject>} */
31
44
  #cookieObjectProxyHandler = {
32
- set: (cookieTarget, cookieProp, cookieValue, receiver) => {
33
- Reflect.set(cookieTarget, cookieProp, cookieValue, receiver);
45
+ set: (cookieTarget, cookieProperty, cookieValue, receiver) => {
46
+ Reflect.set(cookieTarget, cookieProperty, cookieValue, receiver);
34
47
  const index = this.cookieEntries.findIndex((entry) => entry.toString() === cookieTarget.toString());
35
48
  if (index !== -1) {
36
49
  // Force reflection
@@ -94,9 +107,9 @@ export default class ResponseHeaders extends HeadersHandler {
94
107
  case 'utf-8':
95
108
  case 'utf8':
96
109
  return 'utf-8';
97
- default:
98
110
  case 'base64':
99
111
  case 'hex':
112
+ default:
100
113
  return /** @type {BufferEncoding} */ (charset);
101
114
  }
102
115
  }
@@ -118,9 +131,9 @@ export default class ResponseHeaders extends HeadersHandler {
118
131
  case 'utf8':
119
132
  this.charset = 'utf-8';
120
133
  break;
121
- default:
122
134
  case 'base64':
123
135
  case 'hex':
136
+ default:
124
137
  this.charset = bufferEncoding;
125
138
  }
126
139
  }
@@ -149,7 +162,7 @@ export default class ResponseHeaders extends HeadersHandler {
149
162
  }
150
163
 
151
164
  get cookies() {
152
- // eslint-disable-next-line @typescript-eslint/no-this-alias
165
+ // eslint-disable-next-line unicorn/no-this-assignment, @typescript-eslint/no-this-alias
153
166
  const instance = this;
154
167
  return {
155
168
  /**
@@ -205,7 +218,7 @@ export default class ResponseHeaders extends HeadersHandler {
205
218
  return details[key] === cookieObject[key];
206
219
  }
207
220
  }))
208
- .sort((a, b) => (b?.path?.length ?? 0 - a?.path?.length ?? 0));
221
+ .sort((a, b) => ((b?.path?.length ?? 0) - (a?.path?.length ?? 0)));
209
222
  },
210
223
  /**
211
224
  * @param {string|CookieDetails} cookie
@@ -217,14 +230,14 @@ export default class ResponseHeaders extends HeadersHandler {
217
230
  path: '',
218
231
  ...details,
219
232
  });
220
- if (!cookieObject) {
233
+ if (cookieObject) {
234
+ for (const key of COOKIE_DETAIL_KEYS) {
235
+ // @ts-expect-error Coerce
236
+ cookieObject[key] = details[key];
237
+ }
238
+ } else {
221
239
  cookieObject = new Proxy(new CookieObject(details), instance.#cookieObjectProxyHandler);
222
240
  instance.cookieEntries.push(cookieObject);
223
- } else {
224
- COOKIE_DETAIL_KEYS.forEach((key) => {
225
- // @ts-ignore Coerce
226
- cookieObject[key] = details[key];
227
- });
228
241
  }
229
242
  return cookieObject;
230
243
  },
@@ -235,9 +248,9 @@ export default class ResponseHeaders extends HeadersHandler {
235
248
  remove(partial) {
236
249
  const items = this.getAll(partial);
237
250
  const count = items.length;
238
- items.forEach((item) => {
251
+ for (const item of items) {
239
252
  instance.cookieEntries.splice(instance.cookieEntries.indexOf(item), 1);
240
- });
253
+ }
241
254
  return count;
242
255
  },
243
256
  /**
@@ -262,13 +275,11 @@ export default class ResponseHeaders extends HeadersHandler {
262
275
  */
263
276
  expireAll(partial) {
264
277
  const items = this.getAll(partial);
265
- items.forEach((item) => {
266
- /* eslint-disable no-param-reassign */
278
+ for (const item of items) {
267
279
  item.expires = null;
268
280
  item.maxAge = 0;
269
281
  item.value = '';
270
- /* eslint-enable no-param-reassign */
271
- });
282
+ }
272
283
  return items;
273
284
  },
274
285
  };
@@ -289,37 +300,37 @@ export default class ResponseHeaders extends HeadersHandler {
289
300
  instance.#cookieObjectProxyHandler,
290
301
  ));
291
302
  this.#setCookiesProxy = new Proxy(values, {
292
- get: (arrayTarget, arrayProp, receiver) => {
293
- if (typeof arrayProp !== 'string') {
294
- return Reflect.get(arrayTarget, arrayProp, receiver);
303
+ get: (arrayTarget, arrayProperty, receiver) => {
304
+ if (typeof arrayProperty !== 'string') {
305
+ return Reflect.get(arrayTarget, arrayProperty, receiver);
295
306
  }
296
- if (arrayProp === 'length') {
307
+ if (arrayProperty === 'length') {
297
308
  return instance.headers['set-cookie'].length;
298
309
  }
299
- if (Number.isNaN(parseInt(arrayProp, 10))) {
300
- return Reflect.get(arrayTarget, arrayProp, receiver);
310
+ if (Number.isNaN(Number.parseInt(arrayProperty, 10))) {
311
+ return Reflect.get(arrayTarget, arrayProperty, receiver);
301
312
  }
302
- const entry = instance.headers['set-cookie'][arrayProp];
303
- if (typeof entry === 'undefined') {
313
+ const entry = instance.headers['set-cookie'][arrayProperty];
314
+ if (entry === undefined) {
304
315
  return entry;
305
316
  }
306
- if (arrayProp in arrayTarget === false) {
317
+ if (arrayProperty in arrayTarget === false) {
307
318
  Reflect.set(
308
319
  arrayTarget,
309
- arrayProp,
320
+ arrayProperty,
310
321
  new Proxy(new CookieObject(entry), instance.#cookieObjectProxyHandler),
311
322
  );
312
323
  }
313
- return Reflect.get(arrayTarget, arrayProp, receiver);
324
+ return Reflect.get(arrayTarget, arrayProperty, receiver);
314
325
  },
315
- set: (arrayTarget, arrayProp, value, receiver) => {
316
- Reflect.set(arrayTarget, arrayProp, value, receiver);
317
- if (typeof arrayProp !== 'string') return true;
318
- if (arrayProp === 'length') {
319
- Reflect.set(instance.headers['set-cookie'], arrayProp, value);
326
+ set: (arrayTarget, arrayProperty, value, receiver) => {
327
+ Reflect.set(arrayTarget, arrayProperty, value, receiver);
328
+ if (typeof arrayProperty !== 'string') return true;
329
+ if (arrayProperty === 'length') {
330
+ Reflect.set(instance.headers['set-cookie'], arrayProperty, value);
320
331
  }
321
332
  if (value instanceof CookieObject) {
322
- instance.headers['set-cookie'][arrayProp] = value.toString();
333
+ instance.headers['set-cookie'][arrayProperty] = value.toString();
323
334
  }
324
335
  return true;
325
336
  },
package/jsconfig.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "compilerOptions": {
3
3
  "checkJs": true,
4
4
  "noImplicitAny": true,
5
- "target": "es2020",
5
+ "target": "es2022",
6
6
  "module": "esnext",
7
7
  "moduleResolution": "node"
8
8
  },