@interopio/gateway-server 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/web/test.js CHANGED
@@ -1,1395 +1,3 @@
1
- // src/http/exchange.ts
2
- import { Cookie } from "tough-cookie";
3
- function parseHost(headers, defaultHost) {
4
- let host = headers.get("x-forwarded-for");
5
- if (host === void 0) {
6
- host = headers.get("x-forwarded-host");
7
- if (Array.isArray(host)) {
8
- host = host[0];
9
- }
10
- if (host) {
11
- const port = headers.one("x-forwarded-port");
12
- if (port) {
13
- host = `${host}:${port}`;
14
- }
15
- }
16
- host ??= headers.one("host");
17
- }
18
- if (Array.isArray(host)) {
19
- host = host[0];
20
- }
21
- if (host) {
22
- return host.split(",", 1)[0].trim();
23
- }
24
- return defaultHost;
25
- }
26
- function parseProtocol(headers, defaultProtocol) {
27
- let proto = headers.get("x-forwarded-proto");
28
- if (Array.isArray(proto)) {
29
- proto = proto[0];
30
- }
31
- if (proto !== void 0) {
32
- return proto.split(",", 1)[0].trim();
33
- }
34
- return defaultProtocol;
35
- }
36
- var AbstractHttpMessage = class {
37
- #headers;
38
- constructor(headers) {
39
- this.#headers = headers;
40
- }
41
- get headers() {
42
- return this.#headers;
43
- }
44
- };
45
- var AbstractHttpRequest = class _AbstractHttpRequest extends AbstractHttpMessage {
46
- static logIdCounter = 0;
47
- #id;
48
- get id() {
49
- if (this.#id === void 0) {
50
- this.#id = `${this.initId()}-${++_AbstractHttpRequest.logIdCounter}`;
51
- }
52
- return this.#id;
53
- }
54
- initId() {
55
- return "request";
56
- }
57
- get cookies() {
58
- return parseCookies(this.headers);
59
- }
60
- parseHost(defaultHost) {
61
- return parseHost(this.headers, defaultHost);
62
- }
63
- parseProtocol(defaultProtocol) {
64
- return parseProtocol(this.headers, defaultProtocol);
65
- }
66
- };
67
- var AbstractHttpResponse = class extends AbstractHttpMessage {
68
- get cookies() {
69
- return parseResponseCookies(this.headers);
70
- }
71
- setCookieValue(responseCookie) {
72
- const cookie = new Cookie({
73
- key: responseCookie.name,
74
- value: responseCookie.value,
75
- maxAge: responseCookie.maxAge,
76
- domain: responseCookie.domain,
77
- path: responseCookie.path,
78
- secure: responseCookie.secure,
79
- httpOnly: responseCookie.httpOnly,
80
- sameSite: responseCookie.sameSite
81
- });
82
- return cookie.toString();
83
- }
84
- };
85
- function parseHeader(value) {
86
- const list = [];
87
- {
88
- let start = 0;
89
- let end = 0;
90
- for (let i = 0; i < value.length; i++) {
91
- switch (value.charCodeAt(i)) {
92
- case 32:
93
- if (start === end) {
94
- start = end = i + 1;
95
- }
96
- break;
97
- case 44:
98
- list.push(value.slice(start, end));
99
- start = end = i + 1;
100
- break;
101
- default:
102
- end = end + 1;
103
- break;
104
- }
105
- }
106
- list.push(value.slice(start, end));
107
- }
108
- return list;
109
- }
110
- function toList(values) {
111
- if (typeof values === "string") {
112
- values = [values];
113
- }
114
- if (typeof values === "number") {
115
- values = [String(values)];
116
- }
117
- const list = [];
118
- if (values) {
119
- for (const value of values) {
120
- if (value) {
121
- list.push(...parseHeader(value));
122
- }
123
- }
124
- }
125
- return list;
126
- }
127
- function parseCookies(headers) {
128
- return headers.list("cookie").map((s) => s.split(";").map((cs) => Cookie.parse(cs))).flat(1).filter((tc) => tc !== void 0).map((tc) => {
129
- const result = Object.freeze({ name: tc.key, value: tc.value });
130
- return result;
131
- });
132
- }
133
- function parseResponseCookies(headers) {
134
- return headers.list("set-cookie").map((cookie) => {
135
- const parsed = Cookie.parse(cookie);
136
- if (parsed) {
137
- const result = { name: parsed.key, value: parsed.value, maxAge: Number(parsed.maxAge ?? -1) };
138
- if (parsed.httpOnly) result.httpOnly = true;
139
- if (parsed.domain) result.domain = parsed.domain;
140
- if (parsed.path) result.path = parsed.path;
141
- if (parsed.secure) result.secure = true;
142
- if (parsed.httpOnly) result.httpOnly = true;
143
- if (parsed.sameSite) result.sameSite = parsed.sameSite;
144
- return Object.freeze(result);
145
- }
146
- }).filter((cookie) => cookie !== void 0);
147
- }
148
- var MapHttpHeaders = class extends Map {
149
- get(name) {
150
- return super.get(name.toLowerCase());
151
- }
152
- one(name) {
153
- return this.get(name)?.[0];
154
- }
155
- list(name) {
156
- const values = super.get(name.toLowerCase());
157
- return toList(values);
158
- }
159
- set(name, value) {
160
- if (typeof value === "number") {
161
- value = String(value);
162
- }
163
- if (typeof value === "string") {
164
- value = [value];
165
- }
166
- if (value) {
167
- return super.set(name.toLowerCase(), value);
168
- } else {
169
- super.delete(name.toLowerCase());
170
- return this;
171
- }
172
- }
173
- add(name, value) {
174
- const prev = super.get(name.toLowerCase());
175
- if (typeof value === "string") {
176
- value = [value];
177
- }
178
- if (prev) {
179
- value = prev.concat(value);
180
- }
181
- this.set(name, value);
182
- return this;
183
- }
184
- };
185
-
186
- // src/client/exchange.ts
187
- var AbstractClientHttpRequest = class extends AbstractHttpRequest {
188
- constructor(method, uri) {
189
- super(new MapHttpHeaders());
190
- this.URL = uri;
191
- this.method = method;
192
- }
193
- URL;
194
- method;
195
- };
196
- var AbstractClientHttpResponse = class extends AbstractHttpResponse {
197
- constructor(statusCode, headers) {
198
- super(headers);
199
- this.statusCode = statusCode;
200
- }
201
- statusCode;
202
- };
203
-
204
- // src/http/status.ts
205
- var DefaultHttpStatusCode = class {
206
- #value;
207
- constructor(value) {
208
- this.#value = value;
209
- }
210
- get value() {
211
- return this.#value;
212
- }
213
- toString() {
214
- return this.#value.toString();
215
- }
216
- };
217
- var HttpStatus = class _HttpStatus {
218
- static CONTINUE = new _HttpStatus(100, "Continue");
219
- static SWITCHING_PROTOCOLS = new _HttpStatus(101, "Switching Protocols");
220
- // 2xx Success
221
- static OK = new _HttpStatus(200, "OK");
222
- static CREATED = new _HttpStatus(201, "Created");
223
- static ACCEPTED = new _HttpStatus(202, "Accepted");
224
- static NON_AUTHORITATIVE_INFORMATION = new _HttpStatus(203, "Non-Authoritative Information");
225
- static NO_CONTENT = new _HttpStatus(204, "No Content");
226
- static RESET_CONTENT = new _HttpStatus(205, "Reset Content");
227
- static PARTIAL_CONTENT = new _HttpStatus(206, "Partial Content");
228
- static MULTI_STATUS = new _HttpStatus(207, "Multi-Status");
229
- static IM_USED = new _HttpStatus(226, "IM Used");
230
- // 3xx Redirection
231
- static MULTIPLE_CHOICES = new _HttpStatus(300, "Multiple Choices");
232
- static MOVED_PERMANENTLY = new _HttpStatus(301, "Moved Permanently");
233
- // 4xx Client Error
234
- static BAD_REQUEST = new _HttpStatus(400, "Bad Request");
235
- static UNAUTHORIZED = new _HttpStatus(401, "Unauthorized");
236
- static FORBIDDEN = new _HttpStatus(403, "Forbidden");
237
- static NOT_FOUND = new _HttpStatus(404, "Not Found");
238
- static METHOD_NOT_ALLOWED = new _HttpStatus(405, "Method Not Allowed");
239
- static NOT_ACCEPTABLE = new _HttpStatus(406, "Not Acceptable");
240
- static PROXY_AUTHENTICATION_REQUIRED = new _HttpStatus(407, "Proxy Authentication Required");
241
- static REQUEST_TIMEOUT = new _HttpStatus(408, "Request Timeout");
242
- static CONFLICT = new _HttpStatus(409, "Conflict");
243
- static GONE = new _HttpStatus(410, "Gone");
244
- static LENGTH_REQUIRED = new _HttpStatus(411, "Length Required");
245
- static PRECONDITION_FAILED = new _HttpStatus(412, "Precondition Failed");
246
- static PAYLOAD_TOO_LARGE = new _HttpStatus(413, "Payload Too Large");
247
- static URI_TOO_LONG = new _HttpStatus(414, "URI Too Long");
248
- static UNSUPPORTED_MEDIA_TYPE = new _HttpStatus(415, "Unsupported Media Type");
249
- static EXPECTATION_FAILED = new _HttpStatus(417, "Expectation Failed");
250
- static IM_A_TEAPOT = new _HttpStatus(418, "I'm a teapot");
251
- static TOO_EARLY = new _HttpStatus(425, "Too Early");
252
- static UPGRADE_REQUIRED = new _HttpStatus(426, "Upgrade Required");
253
- static PRECONDITION_REQUIRED = new _HttpStatus(428, "Precondition Required");
254
- static TOO_MANY_REQUESTS = new _HttpStatus(429, "Too Many Requests");
255
- static REQUEST_HEADER_FIELDS_TOO_LARGE = new _HttpStatus(431, "Request Header Fields Too Large");
256
- static UNAVAILABLE_FOR_LEGAL_REASONS = new _HttpStatus(451, "Unavailable For Legal Reasons");
257
- // 5xx Server Error
258
- static INTERNAL_SERVER_ERROR = new _HttpStatus(500, "Internal Server Error");
259
- static NOT_IMPLEMENTED = new _HttpStatus(501, "Not Implemented");
260
- static BAD_GATEWAY = new _HttpStatus(502, "Bad Gateway");
261
- static SERVICE_UNAVAILABLE = new _HttpStatus(503, "Service Unavailable");
262
- static GATEWAY_TIMEOUT = new _HttpStatus(504, "Gateway Timeout");
263
- static HTTP_VERSION_NOT_SUPPORTED = new _HttpStatus(505, "HTTP Version Not Supported");
264
- static VARIANT_ALSO_NEGOTIATES = new _HttpStatus(506, "Variant Also Negotiates");
265
- static INSUFFICIENT_STORAGE = new _HttpStatus(507, "Insufficient Storage");
266
- static LOOP_DETECTED = new _HttpStatus(508, "Loop Detected");
267
- static NOT_EXTENDED = new _HttpStatus(510, "Not Extended");
268
- static NETWORK_AUTHENTICATION_REQUIRED = new _HttpStatus(511, "Network Authentication Required");
269
- static #VALUES = [];
270
- static {
271
- Object.keys(_HttpStatus).filter((key) => key !== "VALUES" && key !== "resolve").forEach((key) => {
272
- const value = _HttpStatus[key];
273
- if (value instanceof _HttpStatus) {
274
- Object.defineProperty(value, "name", { enumerable: true, value: key, writable: false });
275
- _HttpStatus.#VALUES.push(value);
276
- }
277
- });
278
- }
279
- static resolve(code) {
280
- for (const status of _HttpStatus.#VALUES) {
281
- if (status.value === code) {
282
- return status;
283
- }
284
- }
285
- }
286
- #value;
287
- #phrase;
288
- constructor(value, phrase) {
289
- this.#value = value;
290
- this.#phrase = phrase;
291
- }
292
- get value() {
293
- return this.#value;
294
- }
295
- get phrase() {
296
- return this.#phrase;
297
- }
298
- toString() {
299
- return `${this.#value} ${this["name"]}`;
300
- }
301
- };
302
- function httpStatusCode(value) {
303
- if (typeof value === "number") {
304
- if (value < 100 || value > 999) {
305
- throw new Error(`status code ${value} should be in range 100-999`);
306
- }
307
- const status = HttpStatus.resolve(value);
308
- if (status !== void 0) {
309
- return status;
310
- }
311
- return new DefaultHttpStatusCode(value);
312
- }
313
- return value;
314
- }
315
-
316
- // src/client/fetch.ts
317
- var FetchClientHttpRequest = class extends AbstractClientHttpRequest {
318
- #body;
319
- constructor(method, uri) {
320
- super(method, uri);
321
- }
322
- async body(body) {
323
- this.#body = body instanceof ReadableStream ? body : await body;
324
- return await this.end();
325
- }
326
- end() {
327
- return Promise.resolve(true);
328
- }
329
- getNativeRequest() {
330
- const method = this.method;
331
- const headers = new Headers();
332
- for (const key of this.headers.keys()) {
333
- if (key.toLowerCase() === "content-length") {
334
- continue;
335
- }
336
- for (const value of this.headers.list(key)) {
337
- headers.append(key, value);
338
- }
339
- }
340
- if (!this.headers.has("accept")) {
341
- headers.append("accept", "*/*");
342
- }
343
- const body = this.#body;
344
- return new Request(this.URL, { method, headers, body });
345
- }
346
- };
347
- function toHttpHeaders(headers) {
348
- const result = new MapHttpHeaders();
349
- for (const [key, value] of headers.entries()) {
350
- result.add(key, value);
351
- }
352
- return result;
353
- }
354
- var FetchClientHttpResponse = class extends AbstractClientHttpResponse {
355
- #response;
356
- constructor(response) {
357
- super(httpStatusCode(response.status), toHttpHeaders(response.headers));
358
- this.#response = response;
359
- }
360
- get statusMessage() {
361
- return this.#response.statusText;
362
- }
363
- get body() {
364
- return this.#response.body ?? void 0;
365
- }
366
- blob() {
367
- return this.#response.blob();
368
- }
369
- };
370
- var FetchClientHttpConnector = class {
371
- #fetch;
372
- constructor(fetchFn = globalThis.fetch) {
373
- this.#fetch = fetchFn;
374
- }
375
- async connect(method, uri, requestCallback) {
376
- const fetchClientHttpRequest = new FetchClientHttpRequest(method, uri);
377
- await requestCallback(fetchClientHttpRequest);
378
- const fetchRequest = fetchClientHttpRequest.getNativeRequest();
379
- const fetchResponse = await this.#fetch(fetchRequest);
380
- return new FetchClientHttpResponse(fetchResponse);
381
- }
382
- };
383
-
384
- // src/mock/client/exchange.ts
385
- import * as stream from "node:stream/web";
386
- var MockClientHttpRequest = class extends AbstractClientHttpRequest {
387
- #writeHandler;
388
- #body = () => {
389
- throw new Error("Body not set");
390
- };
391
- constructor(uri, method) {
392
- super(method, uri);
393
- this.#writeHandler = async (body) => {
394
- const chunks = [];
395
- this.#body = () => {
396
- return stream.ReadableStream.from(chunks);
397
- };
398
- const reader = body.getReader();
399
- let done;
400
- do {
401
- const { value, done: doneReading } = await reader.read();
402
- done = doneReading;
403
- if (value !== void 0) {
404
- chunks.push(value);
405
- }
406
- } while (!done);
407
- return true;
408
- };
409
- }
410
- set writeHandler(handler) {
411
- this.#writeHandler = handler;
412
- }
413
- getNativeRequest() {
414
- return this;
415
- }
416
- getBody() {
417
- return this.#body();
418
- }
419
- body(body) {
420
- const asyncIterator = (async function* () {
421
- if (body instanceof ReadableStream) {
422
- const reader = body.getReader();
423
- let done;
424
- do {
425
- const { value, done: doneReading } = await reader.read();
426
- done = doneReading;
427
- if (value !== void 0) {
428
- yield value;
429
- }
430
- } while (!done);
431
- } else {
432
- const value = await body;
433
- if (value !== void 0) {
434
- yield value;
435
- }
436
- }
437
- })();
438
- return this.#writeHandler(stream.ReadableStream.from(asyncIterator));
439
- }
440
- async end() {
441
- return await this.body(Promise.resolve());
442
- }
443
- };
444
- var MockClientHttpResponse = class extends AbstractHttpResponse {
445
- #statusCode;
446
- #body = stream.ReadableStream.from([]);
447
- constructor(status) {
448
- super(new MapHttpHeaders());
449
- this.#statusCode = httpStatusCode(status);
450
- }
451
- get statusCode() {
452
- return this.#statusCode;
453
- }
454
- addHeader(name, value) {
455
- this.headers.add(name, value);
456
- return this;
457
- }
458
- setHeader(name, value) {
459
- this.headers.set(name, value);
460
- return this;
461
- }
462
- setBody(body, charset) {
463
- this.#body = stream.ReadableStream.from([Buffer.from(body, charset)]);
464
- return this;
465
- }
466
- set body(body) {
467
- this.#body = body;
468
- }
469
- get body() {
470
- return this.#body;
471
- }
472
- async blob() {
473
- const chunks = [];
474
- if (this.body !== void 0) {
475
- for await (const chunk of this.body) {
476
- chunks.push(chunk);
477
- }
478
- }
479
- return new Blob(chunks, { type: this.headers.one("content-type") || "application/octet-stream" });
480
- }
481
- };
482
-
483
- // src/mock/server/exchange.ts
484
- import stream2 from "node:stream/web";
485
-
486
- // src/server/exchange.ts
487
- import http from "node:http";
488
- var ExtendedHttpIncomingMessage = class extends http.IncomingMessage {
489
- // circular reference to the exchange
490
- exchange;
491
- upgradeHead;
492
- get urlBang() {
493
- return this.url;
494
- }
495
- get socketEncrypted() {
496
- return this.socket["encrypted"] === true;
497
- }
498
- };
499
- var ExtendedHttpServerResponse = class extends http.ServerResponse {
500
- markHeadersSent() {
501
- this["_header"] = true;
502
- }
503
- getRawHeaderNames() {
504
- return super["getRawHeaderNames"]();
505
- }
506
- };
507
- var AbstractServerHttpResponse = class extends AbstractHttpResponse {
508
- #cookies = [];
509
- #statusCode;
510
- #state = "new";
511
- #commitActions = [];
512
- setStatusCode(statusCode) {
513
- if (this.#state === "committed") {
514
- return false;
515
- } else {
516
- this.#statusCode = statusCode;
517
- return true;
518
- }
519
- }
520
- setRawStatusCode(statusCode) {
521
- return this.setStatusCode(statusCode === void 0 ? void 0 : httpStatusCode(statusCode));
522
- }
523
- get statusCode() {
524
- return this.#statusCode;
525
- }
526
- addCookie(cookie) {
527
- if (this.#state === "committed") {
528
- throw new Error(`Cannot add cookie ${JSON.stringify(cookie)} because HTTP response has already been committed`);
529
- }
530
- this.#cookies.push(cookie);
531
- return this;
532
- }
533
- beforeCommit(action) {
534
- this.#commitActions.push(action);
535
- }
536
- get commited() {
537
- const state = this.#state;
538
- return state !== "new" && state !== "commit-action-failed";
539
- }
540
- async body(body) {
541
- if (body instanceof ReadableStream) {
542
- throw new Error("ReadableStream body not supported yet");
543
- }
544
- const buffer = await body;
545
- try {
546
- return await this.doCommit(async () => {
547
- return await this.bodyInternal(Promise.resolve(buffer));
548
- }).catch((error) => {
549
- throw error;
550
- });
551
- } catch (error) {
552
- throw error;
553
- }
554
- }
555
- async end() {
556
- if (!this.commited) {
557
- return this.doCommit(async () => {
558
- return await this.bodyInternal(Promise.resolve());
559
- });
560
- } else {
561
- return Promise.resolve(false);
562
- }
563
- }
564
- doCommit(writeAction) {
565
- const state = this.#state;
566
- let allActions = Promise.resolve();
567
- if (state === "new") {
568
- this.#state = "committing";
569
- if (this.#commitActions.length > 0) {
570
- allActions = this.#commitActions.reduce(
571
- (acc, cur) => acc.then(() => cur()),
572
- Promise.resolve()
573
- ).catch((error) => {
574
- const state2 = this.#state;
575
- if (state2 === "committing") {
576
- this.#state = "commit-action-failed";
577
- }
578
- });
579
- }
580
- } else if (state === "commit-action-failed") {
581
- this.#state = "committing";
582
- } else {
583
- return Promise.resolve(false);
584
- }
585
- allActions = allActions.then(() => {
586
- this.applyStatusCode();
587
- this.applyHeaders();
588
- this.applyCookies();
589
- this.#state = "committed";
590
- });
591
- return allActions.then(async () => {
592
- return writeAction !== void 0 ? await writeAction() : true;
593
- });
594
- }
595
- applyStatusCode() {
596
- }
597
- applyHeaders() {
598
- }
599
- applyCookies() {
600
- }
601
- };
602
- var ServerHttpResponseDecorator = class _ServerHttpResponseDecorator {
603
- #delegate;
604
- constructor(response) {
605
- this.#delegate = response;
606
- }
607
- get delegate() {
608
- return this.#delegate;
609
- }
610
- setStatusCode(statusCode) {
611
- return this.delegate.setStatusCode(statusCode);
612
- }
613
- setRawStatusCode(statusCode) {
614
- return this.delegate.setRawStatusCode(statusCode);
615
- }
616
- get statusCode() {
617
- return this.delegate.statusCode;
618
- }
619
- get cookies() {
620
- return this.delegate.cookies;
621
- }
622
- addCookie(cookie) {
623
- this.delegate.addCookie(cookie);
624
- return this;
625
- }
626
- async end() {
627
- return await this.delegate.end();
628
- }
629
- async body(body) {
630
- return await this.#delegate.body(body);
631
- }
632
- get headers() {
633
- return this.#delegate.headers;
634
- }
635
- toString() {
636
- return `${_ServerHttpResponseDecorator.name} [delegate: ${this.delegate.toString()}]`;
637
- }
638
- static getNativeResponse(response) {
639
- if (response instanceof AbstractServerHttpResponse) {
640
- return response.getNativeResponse();
641
- } else if (response instanceof _ServerHttpResponseDecorator) {
642
- return _ServerHttpResponseDecorator.getNativeResponse(response.delegate);
643
- } else {
644
- throw new Error(`Cannot get native response from ${response.constructor.name}`);
645
- }
646
- }
647
- };
648
- var DefaultWebExchange = class {
649
- request;
650
- response;
651
- #attributes = {};
652
- #logId;
653
- #logPrefix = "";
654
- constructor(request, response) {
655
- this.#attributes[LOG_ID_ATTRIBUTE] = request.id;
656
- this.request = request;
657
- this.response = response;
658
- }
659
- get method() {
660
- return this.request.method;
661
- }
662
- get path() {
663
- return this.request.path;
664
- }
665
- get attributes() {
666
- return this.#attributes;
667
- }
668
- attribute(name) {
669
- return this.attributes[name];
670
- }
671
- principal() {
672
- return Promise.resolve(void 0);
673
- }
674
- get logPrefix() {
675
- const value = this.attribute(LOG_ID_ATTRIBUTE);
676
- if (this.#logId !== value) {
677
- this.#logId = value;
678
- this.#logPrefix = value !== void 0 ? `[${value}] ` : "";
679
- }
680
- return this.#logPrefix;
681
- }
682
- };
683
- var LOG_ID_ATTRIBUTE = "io.interop.gateway.server.log_id";
684
-
685
- // src/mock/server/exchange.ts
686
- var MockServerHttpRequest = class extends AbstractHttpRequest {
687
- #url;
688
- #body;
689
- upgrade = false;
690
- constructor(url, method) {
691
- super(new MapHttpHeaders());
692
- if (typeof url === "string") {
693
- if (URL.canParse(url)) {
694
- url = new URL(url);
695
- } else if (URL.canParse(url, "http://localhost")) {
696
- url = new URL(url, "http://localhost");
697
- } else {
698
- throw new TypeError("URL cannot parse url");
699
- }
700
- }
701
- this.#url = url;
702
- this.method = method ?? "GET";
703
- this.setHeader("Host", this.#url.hostname);
704
- this.path = this.#url.pathname ?? "/";
705
- }
706
- method;
707
- path;
708
- get host() {
709
- return super.parseHost(this.#url.host);
710
- }
711
- get protocol() {
712
- return super.parseProtocol(this.#url.protocol.slice(0, -1));
713
- }
714
- get body() {
715
- if (this.#body !== void 0) {
716
- const blob = this.#body;
717
- const asyncIterator = (async function* () {
718
- const bytes = await blob.bytes();
719
- yield bytes;
720
- })();
721
- return stream2.ReadableStream.from(asyncIterator);
722
- }
723
- }
724
- blob() {
725
- const body = this.#body;
726
- return body ? Promise.resolve(body) : Promise.reject(new Error(`no body set`));
727
- }
728
- async text() {
729
- const blob = await this.blob();
730
- return await blob.text();
731
- }
732
- async formData() {
733
- const blob = await this.blob();
734
- const text = await blob.text();
735
- return new URLSearchParams(text);
736
- }
737
- async json() {
738
- const blob = await this.blob();
739
- if (blob.size === 0) {
740
- return void 0;
741
- }
742
- const text = await blob.text();
743
- return JSON.parse(text);
744
- }
745
- async writeBody(body) {
746
- if (body === void 0) {
747
- this.#body = new Blob([]);
748
- return;
749
- }
750
- if (body instanceof ReadableStream) {
751
- const chunks = [];
752
- const reader = body.getReader();
753
- let done = false;
754
- while (!done) {
755
- const { value, done: readDone } = await reader.read();
756
- if (readDone) {
757
- done = true;
758
- } else {
759
- chunks.push(value);
760
- }
761
- }
762
- this.#body = new Blob(chunks);
763
- } else {
764
- body = await body;
765
- if (typeof body === "string") {
766
- this.#body = new Blob([body], { type: "text/plain" });
767
- } else {
768
- this.#body = new Blob([body]);
769
- }
770
- }
771
- if (!this.headers.has("content-type")) {
772
- this.setHeader("Content-Type", this.#body.type || "application/octet-stream");
773
- }
774
- }
775
- get URL() {
776
- return new URL(this.path + this.#url.search + this.#url.hash, `${this.protocol}://${this.host}`);
777
- }
778
- addHeader(name, value) {
779
- this.headers.add(name, value);
780
- return this;
781
- }
782
- setHeader(name, value) {
783
- this.headers.set(name, value);
784
- return this;
785
- }
786
- };
787
- var MockServerHttpResponse = class extends AbstractServerHttpResponse {
788
- #writeHandler;
789
- #body = () => {
790
- throw new Error("No content was written to the response body nor end was called on this response.");
791
- };
792
- constructor() {
793
- super(new MapHttpHeaders());
794
- this.#writeHandler = async (body) => {
795
- const chunks = [];
796
- let bodyStream;
797
- this.#body = () => {
798
- bodyStream ??= stream2.ReadableStream.from(chunks);
799
- return bodyStream;
800
- };
801
- const reader = body.getReader();
802
- let done = false;
803
- do {
804
- const { value, done: readDone } = await reader.read();
805
- if (readDone) {
806
- done = true;
807
- } else {
808
- chunks.push(value);
809
- }
810
- } while (!done);
811
- return true;
812
- };
813
- }
814
- get statusCode() {
815
- return super.statusCode;
816
- }
817
- set writeHandler(handler) {
818
- this.#body = () => {
819
- throw new Error("Not available with custom write handler");
820
- };
821
- this.#writeHandler = handler;
822
- }
823
- getNativeResponse() {
824
- throw new Error("This is a mock. No running server, no native response.");
825
- }
826
- applyStatusCode() {
827
- }
828
- applyHeaders() {
829
- }
830
- applyCookies() {
831
- for (const cookie of this.cookies) {
832
- this.headers.add("Set-Cookie", super.setCookieValue(cookie));
833
- }
834
- }
835
- bodyInternal(body) {
836
- const it = (async function* () {
837
- const resolved = await body;
838
- if (resolved === void 0) {
839
- return;
840
- }
841
- yield resolved;
842
- })();
843
- return this.#writeHandler(stream2.ReadableStream.from(it));
844
- }
845
- async end() {
846
- return this.doCommit(async () => {
847
- return await new Promise((resolve, reject) => {
848
- this.#writeHandler(stream2.ReadableStream.from([]));
849
- });
850
- });
851
- }
852
- getBody() {
853
- return this.#body();
854
- }
855
- };
856
-
857
- // src/logger.ts
858
- import * as GatewayLogging from "@interopio/gateway/logging/core";
859
- function getLogger2(name) {
860
- return GatewayLogging.getLogger(`gateway.server.${name}`);
861
- }
862
-
863
- // src/server/handler.ts
864
- import { AsyncLocalStorage } from "node:async_hooks";
865
- var HttpHeadResponseDecorator = class extends ServerHttpResponseDecorator {
866
- };
867
- var HandlerAdapter = class {
868
- #logger;
869
- #enableLoggingRequestDetails = false;
870
- #delegate;
871
- #storage;
872
- constructor(logger, delegate) {
873
- this.#logger = logger;
874
- this.#delegate = delegate;
875
- }
876
- createExchange(request, response) {
877
- const exchange = new DefaultWebExchange(request, response);
878
- return exchange;
879
- }
880
- set storage(storage) {
881
- this.#storage = storage;
882
- }
883
- set enableLoggingRequestDetails(value) {
884
- this.#enableLoggingRequestDetails = value;
885
- }
886
- formatHeaders(headers) {
887
- let result = "{";
888
- for (const key of headers.keys()) {
889
- if (!this.#enableLoggingRequestDetails) {
890
- result += "masked, ";
891
- break;
892
- } else {
893
- const value = headers.get(key);
894
- result += `"${key}": "${value}", `;
895
- }
896
- }
897
- if (result.endsWith(", ")) {
898
- result = result.slice(0, -2);
899
- }
900
- result += "}";
901
- return result;
902
- }
903
- formatRequest(request) {
904
- const query = request.URL.search;
905
- return `HTTP ${request.method} "${request.path}${query}`;
906
- }
907
- logRequest(exchange) {
908
- if (this.#logger.enabledFor("debug")) {
909
- const trace = this.#logger.enabledFor("trace");
910
- this.#logger.debug(`${exchange.logPrefix}${this.formatRequest(exchange.request)}${trace ? `, headers: ${this.formatHeaders(exchange.request.headers)}` : ""}"`);
911
- }
912
- }
913
- logResponse(exchange) {
914
- if (this.#logger.enabledFor("debug")) {
915
- const trace = this.#logger.enabledFor("trace");
916
- const status = exchange.response.statusCode;
917
- this.#logger.debug(`${exchange.logPrefix}Completed ${status ?? "200 OK"}${trace ? `, headers: ${this.formatHeaders(exchange.response.headers)}` : ""}"`);
918
- }
919
- }
920
- handleUnresolvedError(exchange, error) {
921
- const { request, response, logPrefix } = exchange;
922
- if (response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR)) {
923
- this.#logger.error(`${logPrefix}500 Server Error for ${this.formatRequest(request)}`, error);
924
- return;
925
- }
926
- this.#logger.error(`${logPrefix}Error [${error.message} for ${this.formatRequest(request)}, but already ended (${response.statusCode})`, error);
927
- throw error;
928
- }
929
- async web(exchange) {
930
- return await this.#delegate(exchange);
931
- }
932
- async http(request, response) {
933
- const exchange = this.createExchange(request, response);
934
- const callback = () => {
935
- this.logRequest(exchange);
936
- return this.web(exchange).then(() => {
937
- this.logResponse(exchange);
938
- }).catch((error) => {
939
- this.handleUnresolvedError(exchange, error);
940
- }).then(async () => {
941
- await exchange.response.end();
942
- });
943
- };
944
- await new Promise((resolve, reject) => {
945
- if (this.#storage !== void 0) {
946
- this.#storage.run({ exchange }, () => {
947
- callback().then(() => resolve()).catch((error) => reject(error));
948
- });
949
- } else {
950
- callback().then(() => resolve()).catch((error) => reject(error));
951
- }
952
- });
953
- }
954
- };
955
- var WebHttpHandlerBuilder = class {
956
- #webHandler;
957
- #storage = new AsyncLocalStorage();
958
- #handlerDecorator;
959
- storage(storage) {
960
- this.#storage = storage;
961
- return this;
962
- }
963
- httpHandlerDecorator(decorator) {
964
- if (this.#handlerDecorator === void 0) {
965
- this.#handlerDecorator = decorator;
966
- } else {
967
- const previousDecorator = this.#handlerDecorator;
968
- this.#handlerDecorator = (handler) => {
969
- handler = previousDecorator(handler);
970
- return decorator(handler);
971
- };
972
- }
973
- return this;
974
- }
975
- constructor(webHandler) {
976
- this.#webHandler = webHandler;
977
- }
978
- build() {
979
- const logger = getLogger2("http");
980
- const adapter = new HandlerAdapter(logger, this.#webHandler);
981
- if (this.#storage !== void 0) adapter.storage = this.#storage;
982
- adapter.enableLoggingRequestDetails = false;
983
- const adapted = async (request, response) => adapter.http(request, response);
984
- return this.#handlerDecorator ? this.#handlerDecorator(adapted) : adapted;
985
- }
986
- };
987
-
988
- // src/test/server/handler.ts
989
- import stream3 from "node:stream/web";
990
- var FailureAfterResponseCompletedError = class extends Error {
991
- completedResponse;
992
- constructor(response, options = {}) {
993
- super(`error occurred after response was completed: ${response}`, options);
994
- this.completedResponse = response;
995
- }
996
- };
997
- async function sink() {
998
- try {
999
- return await new Promise((result, _error) => {
1000
- const promise = new Promise((resolve, reject) => {
1001
- Promise.resolve().then(() => {
1002
- result({ promise, resolve, reject });
1003
- });
1004
- });
1005
- });
1006
- } catch (error) {
1007
- throw error;
1008
- }
1009
- }
1010
- var HttpHandlerConnector = class _HttpHandlerConnector {
1011
- static #logger = getLogger2("test.http.handler.connector");
1012
- #httpHandler;
1013
- constructor(httpHandler) {
1014
- this.#httpHandler = httpHandler;
1015
- }
1016
- async connect(method, uri, requestCallback) {
1017
- const requestWriteSink = await sink();
1018
- const handlerSink = await sink();
1019
- const savedResponse = [void 0];
1020
- const mockClientRequest = new MockClientHttpRequest(uri, method);
1021
- const mockServerResponse = new MockServerHttpResponse();
1022
- mockClientRequest.writeHandler = async (responseBody) => {
1023
- this.log("Invoking HttpHandler for ", method, uri);
1024
- const mockServerRequest = await this.adoptRequest(mockClientRequest, responseBody);
1025
- const responseToUse = this.prepareResponse(mockServerResponse, mockServerRequest);
1026
- try {
1027
- await this.#httpHandler(mockServerRequest, responseToUse);
1028
- handlerSink.resolve();
1029
- } catch (e) {
1030
- handlerSink.reject(e);
1031
- }
1032
- return true;
1033
- };
1034
- mockServerResponse.writeHandler = async (responseBody) => {
1035
- this.log("Creating client response for ", method, uri);
1036
- savedResponse[0] = this.adoptResponse(mockServerResponse, responseBody);
1037
- return true;
1038
- };
1039
- this.log("Writing client request for ", method, uri);
1040
- requestCallback(mockClientRequest).then(() => {
1041
- requestWriteSink.resolve();
1042
- }).catch((error) => {
1043
- requestWriteSink.reject(error);
1044
- });
1045
- return Promise.all([requestWriteSink.promise, handlerSink.promise]).catch((error) => {
1046
- const response = savedResponse[0];
1047
- throw response !== void 0 ? new FailureAfterResponseCompletedError(response, { cause: error }) : error;
1048
- }).then(() => {
1049
- const response = savedResponse[0];
1050
- return response ?? this.adoptResponse(mockServerResponse, stream3.ReadableStream.from([]));
1051
- });
1052
- }
1053
- log(message, method, uri) {
1054
- if (_HttpHandlerConnector.#logger.enabledFor("debug")) {
1055
- _HttpHandlerConnector.#logger.debug(`${message} ${method} "${uri.href}"`);
1056
- }
1057
- }
1058
- async adoptRequest(request, body) {
1059
- const method = request.method;
1060
- const uri = request.URL;
1061
- const headers = request.headers;
1062
- const cookies = request.cookies;
1063
- const result = new MockServerHttpRequest(uri, method);
1064
- for (const name of headers.keys()) {
1065
- let value = headers.get(name);
1066
- if (value !== void 0) {
1067
- if (typeof value === "number") {
1068
- value = String(value);
1069
- }
1070
- if (typeof value === "string") {
1071
- result.setHeader(name, value);
1072
- } else {
1073
- for (const v of value) {
1074
- result.addHeader(name, v);
1075
- }
1076
- }
1077
- }
1078
- }
1079
- await result.writeBody(body);
1080
- return result;
1081
- }
1082
- prepareResponse(response, request) {
1083
- return request.method === "HEAD" ? new HttpHeadResponseDecorator(response) : response;
1084
- }
1085
- adoptResponse(response, body) {
1086
- const status = response.statusCode;
1087
- const headers = response.headers;
1088
- const cookies = response.cookies;
1089
- const result = new MockClientHttpResponse(status);
1090
- for (const name of headers.keys()) {
1091
- let value = headers.get(name);
1092
- if (value !== void 0) {
1093
- if (typeof value === "number") {
1094
- value = String(value);
1095
- }
1096
- if (typeof value === "string") {
1097
- result.setHeader(name, value);
1098
- } else {
1099
- for (const v of value) {
1100
- result.addHeader(name, v);
1101
- }
1102
- }
1103
- }
1104
- }
1105
- result.body = body;
1106
- return result;
1107
- }
1108
- };
1109
-
1110
- // src/server/ws-client-verify.ts
1111
- import { IOGateway } from "@interopio/gateway";
1112
- var log = getLogger2("gateway.ws.client-verify");
1113
- function regexifyOriginFilters(originFilters) {
1114
- if (originFilters) {
1115
- const block = (originFilters.block ?? originFilters.blacklist ?? []).map(IOGateway.Filtering.regexify);
1116
- const allow = (originFilters.allow ?? originFilters.whitelist ?? []).map(IOGateway.Filtering.regexify);
1117
- return {
1118
- non_matched: originFilters.non_matched ?? "allow",
1119
- missing: originFilters.missing ?? "allow",
1120
- allow,
1121
- block
1122
- };
1123
- }
1124
- }
1125
-
1126
- // src/server/util/matchers.ts
1127
- var anyExchange = async (_exchange) => {
1128
- return match();
1129
- };
1130
- anyExchange.toString = () => "any-exchange";
1131
- var EMPTY_OBJECT = Object.freeze({});
1132
- var NO_MATCH = Object.freeze({ match: false, variables: EMPTY_OBJECT });
1133
- var match = (variables = EMPTY_OBJECT) => {
1134
- return { match: true, variables };
1135
- };
1136
- var pattern = (pattern2, opts) => {
1137
- const method = opts?.method;
1138
- const matcher = async (exchange) => {
1139
- const request = exchange.request;
1140
- const path = request.path;
1141
- if (method !== void 0 && request.method !== method) {
1142
- return NO_MATCH;
1143
- }
1144
- if (typeof pattern2 === "string") {
1145
- if (path === pattern2) {
1146
- return match();
1147
- }
1148
- return NO_MATCH;
1149
- } else {
1150
- const match2 = pattern2.exec(path);
1151
- if (match2 === null) {
1152
- return NO_MATCH;
1153
- }
1154
- return { match: true, variables: { ...match2.groups } };
1155
- }
1156
- };
1157
- matcher.toString = () => {
1158
- return `pattern(${pattern2.toString()}, method=${method ?? "<any>"})`;
1159
- };
1160
- return matcher;
1161
- };
1162
- var upgradeMatcher = async ({ request }) => {
1163
- const upgrade = request.upgrade && request.headers.one("upgrade")?.toLowerCase() === "websocket";
1164
- return upgrade ? match() : NO_MATCH;
1165
- };
1166
- upgradeMatcher.toString = () => "websocket upgrade";
1167
-
1168
- // src/app/route.ts
1169
- import { IOGateway as IOGateway2 } from "@interopio/gateway";
1170
- async function configure(app, config, routes) {
1171
- const applyCors = (request, options) => {
1172
- if (options?.cors) {
1173
- const cors = options.cors === true ? {
1174
- allowOrigins: options.origins?.allow?.map(IOGateway2.Filtering.regexify),
1175
- allowMethods: request.method === void 0 ? ["*"] : [request.method],
1176
- allowCredentials: options.authorize?.access !== "permitted" ? true : void 0
1177
- } : options.cors;
1178
- const path = request.path;
1179
- routes.cors.push([path, cors]);
1180
- }
1181
- };
1182
- const configurer = new class {
1183
- handle(...handlers) {
1184
- handlers.forEach(({ request, options, handler }) => {
1185
- const matcher = pattern(IOGateway2.Filtering.regexify(request.path), { method: request.method });
1186
- if (options?.authorize) {
1187
- routes.authorize.push([matcher, options.authorize]);
1188
- }
1189
- applyCors(request, options);
1190
- const middleware = async (exchange, next) => {
1191
- const { match: match2, variables } = await matcher(exchange);
1192
- if (match2) {
1193
- await handler(exchange, variables);
1194
- } else {
1195
- await next();
1196
- }
1197
- };
1198
- routes.middleware.push(middleware);
1199
- });
1200
- }
1201
- socket(...sockets) {
1202
- for (const { path, factory, options } of sockets) {
1203
- const route = path ?? "/";
1204
- routes.sockets.set(route, {
1205
- default: path === void 0,
1206
- ping: options?.ping,
1207
- factory,
1208
- maxConnections: options?.maxConnections,
1209
- authorize: options?.authorize,
1210
- originFilters: regexifyOriginFilters(options?.origins)
1211
- });
1212
- }
1213
- }
1214
- }();
1215
- await app(configurer, config);
1216
- }
1217
-
1218
- // src/common/compose.ts
1219
- function compose(...middleware) {
1220
- if (!Array.isArray(middleware)) {
1221
- throw new Error("middleware must be array!");
1222
- }
1223
- const fns = middleware.flat();
1224
- for (const fn of fns) {
1225
- if (typeof fn !== "function") {
1226
- throw new Error("middleware must be compose of functions!");
1227
- }
1228
- }
1229
- return async function(ctx, next) {
1230
- const dispatch = async (i, dispatchedCtx) => {
1231
- const fn = i === fns.length ? next : fns[i];
1232
- if (fn === void 0) {
1233
- return;
1234
- }
1235
- let nextCalled = false;
1236
- let nextResolved = false;
1237
- const nextFn = async (nextCtx) => {
1238
- if (nextCalled) {
1239
- throw new Error("next() called multiple times");
1240
- }
1241
- nextCalled = true;
1242
- try {
1243
- return await dispatch(i + 1, nextCtx ?? dispatchedCtx);
1244
- } finally {
1245
- nextResolved = true;
1246
- }
1247
- };
1248
- const result = await fn(dispatchedCtx, nextFn);
1249
- if (nextCalled && !nextResolved) {
1250
- throw new Error("middleware resolved before downstream.\n You are probably missing an await or return statement in your middleware function.");
1251
- }
1252
- return result;
1253
- };
1254
- return dispatch(0, ctx);
1255
- };
1256
- }
1257
-
1258
- // src/test/server/client.ts
1259
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
1260
- function bindToApp(app) {
1261
- return new AppSpec(app);
1262
- }
1263
- function bindToServer() {
1264
- return new DefaultTestClientBuilder();
1265
- }
1266
- var DefaultTestClient = class {
1267
- #connector;
1268
- #baseUrl;
1269
- #builder;
1270
- constructor(connector, baseUrl, builder) {
1271
- this.#connector = connector;
1272
- this.#baseUrl = baseUrl;
1273
- this.#builder = builder;
1274
- }
1275
- fetch = async (input, init) => {
1276
- try {
1277
- const method = init?.method ?? "GET";
1278
- const uri = new URL(input, this.#baseUrl);
1279
- const response = await this.#connector.connect(method, uri, async (request) => {
1280
- const headers2 = new Headers(init?.headers);
1281
- for (const [name, value] of headers2.entries()) {
1282
- request.headers.add(name, value);
1283
- }
1284
- let body2 = init?.body ?? Promise.resolve();
1285
- if (body2 instanceof ReadableStream) {
1286
- throw new Error(`Unsupported body type ${typeof init?.body} in fetch request`);
1287
- }
1288
- if (body2 instanceof FormData) {
1289
- const formDataEntries = Array.from(body2.entries());
1290
- body2 = new URLSearchParams();
1291
- for (const [key, value] of formDataEntries) {
1292
- body2.append(key, value.toString());
1293
- }
1294
- }
1295
- if (body2 instanceof URLSearchParams) {
1296
- if (!request.headers.has("content-type")) {
1297
- request.headers.set("content-type", "application/x-www-form-urlencoded");
1298
- }
1299
- body2 = body2.toString();
1300
- }
1301
- if (body2 instanceof Blob) {
1302
- body2 = await body2.bytes();
1303
- }
1304
- if (typeof body2 === "string") {
1305
- body2 = Buffer.from(body2);
1306
- }
1307
- await request.body(body2);
1308
- });
1309
- const headers = new Headers();
1310
- for (const key of response.headers.keys()) {
1311
- const values = response.headers.list(key);
1312
- for (const value of values) {
1313
- headers.append(key, value);
1314
- }
1315
- }
1316
- const status = response.statusCode?.value;
1317
- const body = await response.blob();
1318
- return new Response(body, { status, headers });
1319
- } catch (error) {
1320
- return Response.error();
1321
- }
1322
- };
1323
- };
1324
- var DefaultTestClientBuilder = class {
1325
- #httpHandlerBuilder;
1326
- #connector;
1327
- #baseUrl = "http://localhost:8080";
1328
- constructor(httpHandlerBuilder, connector) {
1329
- if (!(httpHandlerBuilder === void 0 || connector === void 0)) {
1330
- throw new Error("You can only set either httpHandlerBuilder or connector, not both.");
1331
- }
1332
- this.#connector = connector;
1333
- this.#httpHandlerBuilder = httpHandlerBuilder;
1334
- }
1335
- baseUrl(baseUrl) {
1336
- this.#baseUrl = baseUrl;
1337
- return this;
1338
- }
1339
- clientConnector(connector) {
1340
- this.#connector = connector;
1341
- return this;
1342
- }
1343
- async build() {
1344
- let connector = this.#connector;
1345
- if (connector === void 0) {
1346
- if (this.#httpHandlerBuilder !== void 0) {
1347
- connector = new HttpHandlerConnector((await this.#httpHandlerBuilder).build());
1348
- }
1349
- }
1350
- connector ??= new FetchClientHttpConnector();
1351
- return new DefaultTestClient(connector, this.#baseUrl, this);
1352
- }
1353
- };
1354
- var AbstractMockServerSpec = class {
1355
- configureClient() {
1356
- const builder = this.initHttpHandlerBuilder();
1357
- return new DefaultTestClientBuilder(builder);
1358
- }
1359
- async build() {
1360
- return await this.configureClient().build();
1361
- }
1362
- };
1363
- var AppSpec = class extends AbstractMockServerSpec {
1364
- #app;
1365
- constructor(app) {
1366
- super();
1367
- this.#app = app;
1368
- }
1369
- async initHttpHandlerBuilder() {
1370
- const routes = {
1371
- middleware: [],
1372
- corsConfig: {
1373
- allowOrigin: ["http://localhost:8086"]
1374
- },
1375
- cors: [],
1376
- authConfig: { type: "none" },
1377
- authorize: [],
1378
- storage: new AsyncLocalStorage2(),
1379
- sockets: /* @__PURE__ */ new Map()
1380
- };
1381
- await configure(this.#app, {}, routes);
1382
- const handler = compose(...routes.middleware);
1383
- return new WebHttpHandlerBuilder(handler);
1384
- }
1385
- };
1386
-
1387
- // src/test/index.ts
1388
- var TestClient = {
1389
- bindToApp,
1390
- bindToServer
1391
- };
1392
- export {
1393
- TestClient
1394
- };
1
+ import{Cookie as W}from"tough-cookie";function ue(r,e){let t=r.get("x-forwarded-for");if(t===void 0){if(t=r.get("x-forwarded-host"),Array.isArray(t)&&(t=t[0]),t){let s=r.one("x-forwarded-port");s&&(t=`${t}:${s}`)}t??=r.one("host")}return Array.isArray(t)&&(t=t[0]),t?t.split(",",1)[0].trim():e}function le(r,e){let t=r.get("x-forwarded-proto");return Array.isArray(t)&&(t=t[0]),t!==void 0?t.split(",",1)[0].trim():e}var v=class{#e;constructor(e){this.#e=e}get headers(){return this.#e}},g=class r extends v{static logIdCounter=0;#e;get id(){return this.#e===void 0&&(this.#e=`${this.initId()}-${++r.logIdCounter}`),this.#e}initId(){return"request"}get cookies(){return me(this.headers)}parseHost(e){return ue(this.headers,e)}parseProtocol(e){return le(this.headers,e)}},m=class extends v{get cookies(){return ge(this.headers)}setCookieValue(e){return new W({key:e.name,value:e.value,maxAge:e.maxAge,domain:e.domain,path:e.path,secure:e.secure,httpOnly:e.httpOnly,sameSite:e.sameSite}).toString()}};function pe(r){let e=[];{let t=0,s=0;for(let n=0;n<r.length;n++)switch(r.charCodeAt(n)){case 32:t===s&&(t=s=n+1);break;case 44:e.push(r.slice(t,s)),t=s=n+1;break;default:s=s+1;break}e.push(r.slice(t,s))}return e}function he(r){typeof r=="string"&&(r=[r]),typeof r=="number"&&(r=[String(r)]);let e=[];if(r)for(let t of r)t&&e.push(...pe(t));return e}function me(r){return r.list("cookie").map(e=>e.split(";").map(t=>W.parse(t))).flat(1).filter(e=>e!==void 0).map(e=>Object.freeze({name:e.key,value:e.value}))}function ge(r){return r.list("set-cookie").map(e=>{let t=W.parse(e);if(t){let s={name:t.key,value:t.value,maxAge:Number(t.maxAge??-1)};return t.httpOnly&&(s.httpOnly=!0),t.domain&&(s.domain=t.domain),t.path&&(s.path=t.path),t.secure&&(s.secure=!0),t.httpOnly&&(s.httpOnly=!0),t.sameSite&&(s.sameSite=t.sameSite),Object.freeze(s)}}).filter(e=>e!==void 0)}var p=class extends Map{get(e){return super.get(e.toLowerCase())}one(e){return this.get(e)?.[0]}list(e){let t=super.get(e.toLowerCase());return he(t)}set(e,t){return typeof t=="number"&&(t=String(t)),typeof t=="string"&&(t=[t]),t?super.set(e.toLowerCase(),t):(super.delete(e.toLowerCase()),this)}add(e,t){let s=super.get(e.toLowerCase());return typeof t=="string"&&(t=[t]),s&&(t=s.concat(t)),this.set(e,t),this}};var y=class extends g{constructor(e,t){super(new p),this.URL=t,this.method=e}URL;method},x=class extends m{constructor(e,t){super(t),this.statusCode=e}statusCode};var $=class{#e;constructor(e){this.#e=e}get value(){return this.#e}toString(){return this.#e.toString()}},H=class r{static CONTINUE=new r(100,"Continue");static SWITCHING_PROTOCOLS=new r(101,"Switching Protocols");static OK=new r(200,"OK");static CREATED=new r(201,"Created");static ACCEPTED=new r(202,"Accepted");static NON_AUTHORITATIVE_INFORMATION=new r(203,"Non-Authoritative Information");static NO_CONTENT=new r(204,"No Content");static RESET_CONTENT=new r(205,"Reset Content");static PARTIAL_CONTENT=new r(206,"Partial Content");static MULTI_STATUS=new r(207,"Multi-Status");static IM_USED=new r(226,"IM Used");static MULTIPLE_CHOICES=new r(300,"Multiple Choices");static MOVED_PERMANENTLY=new r(301,"Moved Permanently");static BAD_REQUEST=new r(400,"Bad Request");static UNAUTHORIZED=new r(401,"Unauthorized");static FORBIDDEN=new r(403,"Forbidden");static NOT_FOUND=new r(404,"Not Found");static METHOD_NOT_ALLOWED=new r(405,"Method Not Allowed");static NOT_ACCEPTABLE=new r(406,"Not Acceptable");static PROXY_AUTHENTICATION_REQUIRED=new r(407,"Proxy Authentication Required");static REQUEST_TIMEOUT=new r(408,"Request Timeout");static CONFLICT=new r(409,"Conflict");static GONE=new r(410,"Gone");static LENGTH_REQUIRED=new r(411,"Length Required");static PRECONDITION_FAILED=new r(412,"Precondition Failed");static PAYLOAD_TOO_LARGE=new r(413,"Payload Too Large");static URI_TOO_LONG=new r(414,"URI Too Long");static UNSUPPORTED_MEDIA_TYPE=new r(415,"Unsupported Media Type");static EXPECTATION_FAILED=new r(417,"Expectation Failed");static IM_A_TEAPOT=new r(418,"I'm a teapot");static TOO_EARLY=new r(425,"Too Early");static UPGRADE_REQUIRED=new r(426,"Upgrade Required");static PRECONDITION_REQUIRED=new r(428,"Precondition Required");static TOO_MANY_REQUESTS=new r(429,"Too Many Requests");static REQUEST_HEADER_FIELDS_TOO_LARGE=new r(431,"Request Header Fields Too Large");static UNAVAILABLE_FOR_LEGAL_REASONS=new r(451,"Unavailable For Legal Reasons");static INTERNAL_SERVER_ERROR=new r(500,"Internal Server Error");static NOT_IMPLEMENTED=new r(501,"Not Implemented");static BAD_GATEWAY=new r(502,"Bad Gateway");static SERVICE_UNAVAILABLE=new r(503,"Service Unavailable");static GATEWAY_TIMEOUT=new r(504,"Gateway Timeout");static HTTP_VERSION_NOT_SUPPORTED=new r(505,"HTTP Version Not Supported");static VARIANT_ALSO_NEGOTIATES=new r(506,"Variant Also Negotiates");static INSUFFICIENT_STORAGE=new r(507,"Insufficient Storage");static LOOP_DETECTED=new r(508,"Loop Detected");static NOT_EXTENDED=new r(510,"Not Extended");static NETWORK_AUTHENTICATION_REQUIRED=new r(511,"Network Authentication Required");static#e=[];static{Object.keys(r).filter(e=>e!=="VALUES"&&e!=="resolve").forEach(e=>{let t=r[e];t instanceof r&&(Object.defineProperty(t,"name",{enumerable:!0,value:e,writable:!1}),r.#e.push(t))})}static resolve(e){for(let t of r.#e)if(t.value===e)return t}#t;#r;constructor(e,t){this.#t=e,this.#r=t}get value(){return this.#t}get phrase(){return this.#r}toString(){return`${this.#t} ${this.name}`}};function b(r){if(typeof r=="number"){if(r<100||r>999)throw new Error(`status code ${r} should be in range 100-999`);let e=H.resolve(r);return e!==void 0?e:new $(r)}return r}var D=class extends y{#e;constructor(e,t){super(e,t)}async body(e){return this.#e=e instanceof ReadableStream?e:await e,await this.end()}end(){return Promise.resolve(!0)}getNativeRequest(){let e=this.method,t=new Headers;for(let n of this.headers.keys())if(n.toLowerCase()!=="content-length")for(let o of this.headers.list(n))t.append(n,o);this.headers.has("accept")||t.append("accept","*/*");let s=this.#e;return new Request(this.URL,{method:e,headers:t,body:s})}};function fe(r){let e=new p;for(let[t,s]of r.entries())e.add(t,s);return e}var V=class extends x{#e;constructor(e){super(b(e.status),fe(e.headers)),this.#e=e}get statusMessage(){return this.#e.statusText}get body(){return this.#e.body??void 0}blob(){return this.#e.blob()}},E=class{#e;constructor(e=globalThis.fetch){this.#e=e}async connect(e,t,s){let n=new D(e,t);await s(n);let o=n.getNativeRequest(),a=await this.#e(o);return new V(a)}};import*as w from"node:stream/web";var k=class extends y{#e;#t=()=>{throw new Error("Body not set")};constructor(e,t){super(t,e),this.#e=async s=>{let n=[];this.#t=()=>w.ReadableStream.from(n);let o=s.getReader(),a;do{let{value:i,done:c}=await o.read();a=c,i!==void 0&&n.push(i)}while(!a);return!0}}set writeHandler(e){this.#e=e}getNativeRequest(){return this}getBody(){return this.#t()}body(e){let t=(async function*(){if(e instanceof ReadableStream){let s=e.getReader(),n;do{let{value:o,done:a}=await s.read();n=a,o!==void 0&&(yield o)}while(!n)}else{let s=await e;s!==void 0&&(yield s)}})();return this.#e(w.ReadableStream.from(t))}async end(){return await this.body(Promise.resolve())}},T=class extends m{#e;#t=w.ReadableStream.from([]);constructor(e){super(new p),this.#e=b(e)}get statusCode(){return this.#e}addHeader(e,t){return this.headers.add(e,t),this}setHeader(e,t){return this.headers.set(e,t),this}setBody(e,t){return this.#t=w.ReadableStream.from([Buffer.from(e,t)]),this}set body(e){this.#t=e}get body(){return this.#t}async blob(){let e=[];if(this.body!==void 0)for await(let t of this.body)e.push(t);return new Blob(e,{type:this.headers.one("content-type")||"application/octet-stream"})}};import M from"node:stream/web";import Z from"node:http";var K=class extends Z.IncomingMessage{exchange;upgradeHead;get urlBang(){return this.url}get socketEncrypted(){return this.socket.encrypted===!0}},J=class extends Z.ServerResponse{markHeadersSent(){this._header=!0}getRawHeaderNames(){return super.getRawHeaderNames()}};var S=class extends m{#e=[];#t;#r="new";#s=[];setStatusCode(e){return this.#r==="committed"?!1:(this.#t=e,!0)}setRawStatusCode(e){return this.setStatusCode(e===void 0?void 0:b(e))}get statusCode(){return this.#t}addCookie(e){if(this.#r==="committed")throw new Error(`Cannot add cookie ${JSON.stringify(e)} because HTTP response has already been committed`);return this.#e.push(e),this}beforeCommit(e){this.#s.push(e)}get commited(){let e=this.#r;return e!=="new"&&e!=="commit-action-failed"}async body(e){if(e instanceof ReadableStream)throw new Error("ReadableStream body not supported yet");let t=await e;try{return await this.doCommit(async()=>await this.bodyInternal(Promise.resolve(t))).catch(s=>{throw s})}catch(s){throw s}}async end(){return this.commited?Promise.resolve(!1):this.doCommit(async()=>await this.bodyInternal(Promise.resolve()))}doCommit(e){let t=this.#r,s=Promise.resolve();if(t==="new")this.#r="committing",this.#s.length>0&&(s=this.#s.reduce((n,o)=>n.then(()=>o()),Promise.resolve()).catch(n=>{this.#r==="committing"&&(this.#r="commit-action-failed")}));else if(t==="commit-action-failed")this.#r="committing";else return Promise.resolve(!1);return s=s.then(()=>{this.applyStatusCode(),this.applyHeaders(),this.applyCookies(),this.#r="committed"}),s.then(async()=>e!==void 0?await e():!0)}applyStatusCode(){}applyHeaders(){}applyCookies(){}};var P=class r{#e;constructor(e){this.#e=e}get delegate(){return this.#e}setStatusCode(e){return this.delegate.setStatusCode(e)}setRawStatusCode(e){return this.delegate.setRawStatusCode(e)}get statusCode(){return this.delegate.statusCode}get cookies(){return this.delegate.cookies}addCookie(e){return this.delegate.addCookie(e),this}async end(){return await this.delegate.end()}async body(e){return await this.#e.body(e)}get headers(){return this.#e.headers}toString(){return`${r.name} [delegate: ${this.delegate.toString()}]`}static getNativeResponse(e){if(e instanceof S)return e.getNativeResponse();if(e instanceof r)return r.getNativeResponse(e.delegate);throw new Error(`Cannot get native response from ${e.constructor.name}`)}};var C=class{request;response;#e={};#t;#r="";constructor(e,t){this.#e[X]=e.id,this.request=e,this.response=t}get method(){return this.request.method}get path(){return this.request.path}get attributes(){return this.#e}attribute(e){return this.attributes[e]}principal(){return Promise.resolve(void 0)}get logPrefix(){let e=this.attribute(X);return this.#t!==e&&(this.#t=e,this.#r=e!==void 0?`[${e}] `:""),this.#r}},X="io.interop.gateway.server.log_id";var L=class extends g{#e;#t;upgrade=!1;constructor(e,t){if(super(new p),typeof e=="string")if(URL.canParse(e))e=new URL(e);else if(URL.canParse(e,"http://localhost"))e=new URL(e,"http://localhost");else throw new TypeError("URL cannot parse url");this.#e=e,this.method=t??"GET",this.setHeader("Host",this.#e.hostname),this.path=this.#e.pathname??"/"}method;path;get host(){return super.parseHost(this.#e.host)}get protocol(){return super.parseProtocol(this.#e.protocol.slice(0,-1))}get body(){if(this.#t!==void 0){let e=this.#t,t=(async function*(){yield await e.bytes()})();return M.ReadableStream.from(t)}}blob(){let e=this.#t;return e?Promise.resolve(e):Promise.reject(new Error("no body set"))}async text(){return await(await this.blob()).text()}async formData(){let t=await(await this.blob()).text();return new URLSearchParams(t)}async json(){let e=await this.blob();if(e.size===0)return;let t=await e.text();return JSON.parse(t)}async writeBody(e){if(e===void 0){this.#t=new Blob([]);return}if(e instanceof ReadableStream){let t=[],s=e.getReader(),n=!1;for(;!n;){let{value:o,done:a}=await s.read();a?n=!0:t.push(o)}this.#t=new Blob(t)}else e=await e,typeof e=="string"?this.#t=new Blob([e],{type:"text/plain"}):this.#t=new Blob([e]);this.headers.has("content-type")||this.setHeader("Content-Type",this.#t.type||"application/octet-stream")}get URL(){return new URL(this.path+this.#e.search+this.#e.hash,`${this.protocol}://${this.host}`)}addHeader(e,t){return this.headers.add(e,t),this}setHeader(e,t){return this.headers.set(e,t),this}},A=class extends S{#e;#t=()=>{throw new Error("No content was written to the response body nor end was called on this response.")};constructor(){super(new p),this.#e=async e=>{let t=[],s;this.#t=()=>(s??=M.ReadableStream.from(t),s);let n=e.getReader(),o=!1;do{let{value:a,done:i}=await n.read();i?o=!0:t.push(a)}while(!o);return!0}}get statusCode(){return super.statusCode}set writeHandler(e){this.#t=()=>{throw new Error("Not available with custom write handler")},this.#e=e}getNativeResponse(){throw new Error("This is a mock. No running server, no native response.")}applyStatusCode(){}applyHeaders(){}applyCookies(){for(let e of this.cookies)this.headers.add("Set-Cookie",super.setCookieValue(e))}bodyInternal(e){let t=(async function*(){let s=await e;s!==void 0&&(yield s)})();return this.#e(M.ReadableStream.from(t))}async end(){return this.doCommit(async()=>await new Promise((e,t)=>{this.#e(M.ReadableStream.from([]))}))}getBody(){return this.#t()}};import*as G from"@interopio/gateway/logging/core";function f(r){return G.getLogger(`gateway.server.${r}`)}import{AsyncLocalStorage as ye}from"node:async_hooks";var O=class extends P{},F=class{#e;#t=!1;#r;#s;constructor(e,t){this.#e=e,this.#r=t}createExchange(e,t){return new C(e,t)}set storage(e){this.#s=e}set enableLoggingRequestDetails(e){this.#t=e}formatHeaders(e){let t="{";for(let s of e.keys())if(this.#t){let n=e.get(s);t+=`"${s}": "${n}", `}else{t+="masked, ";break}return t.endsWith(", ")&&(t=t.slice(0,-2)),t+="}",t}formatRequest(e){let t=e.URL.search;return`HTTP ${e.method} "${e.path}${t}`}logRequest(e){if(this.#e.enabledFor("debug")){let t=this.#e.enabledFor("trace");this.#e.debug(`${e.logPrefix}${this.formatRequest(e.request)}${t?`, headers: ${this.formatHeaders(e.request.headers)}`:""}"`)}}logResponse(e){if(this.#e.enabledFor("debug")){let t=this.#e.enabledFor("trace"),s=e.response.statusCode;this.#e.debug(`${e.logPrefix}Completed ${s??"200 OK"}${t?`, headers: ${this.formatHeaders(e.response.headers)}`:""}"`)}}handleUnresolvedError(e,t){let{request:s,response:n,logPrefix:o}=e;if(n.setStatusCode(H.INTERNAL_SERVER_ERROR)){this.#e.error(`${o}500 Server Error for ${this.formatRequest(s)}`,t);return}throw this.#e.error(`${o}Error [${t.message} for ${this.formatRequest(s)}, but already ended (${n.statusCode})`,t),t}async web(e){return await this.#r(e)}async http(e,t){let s=this.createExchange(e,t),n=()=>(this.logRequest(s),this.web(s).then(()=>{this.logResponse(s)}).catch(o=>{this.handleUnresolvedError(s,o)}).then(async()=>{await s.response.end()}));await new Promise((o,a)=>{this.#s!==void 0?this.#s.run({exchange:s},()=>{n().then(()=>o()).catch(i=>a(i))}):n().then(()=>o()).catch(i=>a(i))})}},B=class{#e;#t=new ye;#r;storage(e){return this.#t=e,this}httpHandlerDecorator(e){if(this.#r===void 0)this.#r=e;else{let t=this.#r;this.#r=s=>(s=t(s),e(s))}return this}constructor(e){this.#e=e}build(){let e=f("http"),t=new F(e,this.#e);this.#t!==void 0&&(t.storage=this.#t),t.enableLoggingRequestDetails=!1;let s=async(n,o)=>t.http(n,o);return this.#r?this.#r(s):s}};import be from"node:stream/web";var j=class extends Error{completedResponse;constructor(e,t={}){super(`error occurred after response was completed: ${e}`,t),this.completedResponse=e}};async function ee(){try{return await new Promise((r,e)=>{let t=new Promise((s,n)=>{Promise.resolve().then(()=>{r({promise:t,resolve:s,reject:n})})})})}catch(r){throw r}}var N=class r{static#e=f("test.http.handler.connector");#t;constructor(e){this.#t=e}async connect(e,t,s){let n=await ee(),o=await ee(),a=[void 0],i=new k(t,e),c=new A;return i.writeHandler=async d=>{this.log("Invoking HttpHandler for ",e,t);let l=await this.adoptRequest(i,d),u=this.prepareResponse(c,l);try{await this.#t(l,u),o.resolve()}catch(h){o.reject(h)}return!0},c.writeHandler=async d=>(this.log("Creating client response for ",e,t),a[0]=this.adoptResponse(c,d),!0),this.log("Writing client request for ",e,t),s(i).then(()=>{n.resolve()}).catch(d=>{n.reject(d)}),Promise.all([n.promise,o.promise]).catch(d=>{let l=a[0];throw l!==void 0?new j(l,{cause:d}):d}).then(()=>a[0]??this.adoptResponse(c,be.ReadableStream.from([])))}log(e,t,s){r.#e.enabledFor("debug")&&r.#e.debug(`${e} ${t} "${s.href}"`)}async adoptRequest(e,t){let s=e.method,n=e.URL,o=e.headers,a=e.cookies,i=new L(n,s);for(let c of o.keys()){let d=o.get(c);if(d!==void 0)if(typeof d=="number"&&(d=String(d)),typeof d=="string")i.setHeader(c,d);else for(let l of d)i.addHeader(c,l)}return await i.writeBody(t),i}prepareResponse(e,t){return t.method==="HEAD"?new O(e):e}adoptResponse(e,t){let s=e.statusCode,n=e.headers,o=e.cookies,a=new T(s);for(let i of n.keys()){let c=n.get(i);if(c!==void 0)if(typeof c=="number"&&(c=String(c)),typeof c=="string")a.setHeader(i,c);else for(let d of c)a.addHeader(i,d)}return a.body=t,a}};import{IOGateway as te}from"@interopio/gateway";var nt=f("gateway.ws.client-verify");function re(r){if(r){let e=(r.block??r.blacklist??[]).map(te.Filtering.regexify),t=(r.allow??r.whitelist??[]).map(te.Filtering.regexify);return{non_matched:r.non_matched??"allow",missing:r.missing??"allow",allow:t,block:e}}}var Re=async r=>z();Re.toString=()=>"any-exchange";var se=Object.freeze({}),I=Object.freeze({match:!1,variables:se}),z=(r=se)=>({match:!0,variables:r}),ne=(r,e)=>{let t=e?.method,s=async n=>{let o=n.request,a=o.path;if(t!==void 0&&o.method!==t)return I;if(typeof r=="string")return a===r?z():I;{let i=r.exec(a);return i===null?I:{match:!0,variables:{...i.groups}}}};return s.toString=()=>`pattern(${r.toString()}, method=${t??"<any>"})`,s};var He=async({request:r})=>r.upgrade&&r.headers.one("upgrade")?.toLowerCase()==="websocket"?z():I;He.toString=()=>"websocket upgrade";import{IOGateway as oe}from"@interopio/gateway";async function ae(r,e,t){let s=(o,a)=>{if(a?.cors){let i=a.cors===!0?{allowOrigins:a.origins?.allow?.map(oe.Filtering.regexify),allowMethods:o.method===void 0?["*"]:[o.method],allowCredentials:a.authorize?.access!=="permitted"?!0:void 0}:a.cors,c=o.path;t.cors.push([c,i])}},n=new class{handle(...o){o.forEach(({request:a,options:i,handler:c})=>{let d=ne(oe.Filtering.regexify(a.path),{method:a.method});i?.authorize&&t.authorize.push([d,i.authorize]),s(a,i);let l=async(u,h)=>{let{match:R,variables:q}=await d(u);R?await c(u,q):await h()};t.middleware.push(l)})}socket(...o){for(let{path:a,factory:i,options:c}of o){let d=a??"/";t.sockets.set(d,{default:a===void 0,ping:c?.ping,factory:i,maxConnections:c?.maxConnections,authorize:c?.authorize,originFilters:re(c?.origins)})}}};await r(n,e)}function ie(...r){if(!Array.isArray(r))throw new Error("middleware must be array!");let e=r.flat();for(let t of e)if(typeof t!="function")throw new Error("middleware must be compose of functions!");return async function(t,s){let n=async(o,a)=>{let i=o===e.length?s:e[o];if(i===void 0)return;let c=!1,d=!1,u=await i(a,async h=>{if(c)throw new Error("next() called multiple times");c=!0;try{return await n(o+1,h??a)}finally{d=!0}});if(c&&!d)throw new Error(`middleware resolved before downstream.
2
+ You are probably missing an await or return statement in your middleware function.`);return u};return n(0,t)}}import{AsyncLocalStorage as we}from"node:async_hooks";function de(r){return new Q(r)}function ce(){return new U}var Y=class{#e;#t;#r;constructor(e,t,s){this.#e=e,this.#t=t,this.#r=s}fetch=async(e,t)=>{try{let s=t?.method??"GET",n=new URL(e,this.#t),o=await this.#e.connect(s,n,async d=>{let l=new Headers(t?.headers);for(let[h,R]of l.entries())d.headers.add(h,R);let u=t?.body??Promise.resolve();if(u instanceof ReadableStream)throw new Error(`Unsupported body type ${typeof t?.body} in fetch request`);if(u instanceof FormData){let h=Array.from(u.entries());u=new URLSearchParams;for(let[R,q]of h)u.append(R,q.toString())}u instanceof URLSearchParams&&(d.headers.has("content-type")||d.headers.set("content-type","application/x-www-form-urlencoded"),u=u.toString()),u instanceof Blob&&(u=await u.bytes()),typeof u=="string"&&(u=Buffer.from(u)),await d.body(u)}),a=new Headers;for(let d of o.headers.keys()){let l=o.headers.list(d);for(let u of l)a.append(d,u)}let i=o.statusCode?.value,c=await o.blob();return new Response(c,{status:i,headers:a})}catch{return Response.error()}}},U=class{#e;#t;#r="http://localhost:8080";constructor(e,t){if(!(e===void 0||t===void 0))throw new Error("You can only set either httpHandlerBuilder or connector, not both.");this.#t=t,this.#e=e}baseUrl(e){return this.#r=e,this}clientConnector(e){return this.#t=e,this}async build(){let e=this.#t;return e===void 0&&this.#e!==void 0&&(e=new N((await this.#e).build())),e??=new E,new Y(e,this.#r,this)}},_=class{configureClient(){let e=this.initHttpHandlerBuilder();return new U(e)}async build(){return await this.configureClient().build()}},Q=class extends _{#e;constructor(e){super(),this.#e=e}async initHttpHandlerBuilder(){let e={middleware:[],corsConfig:{allowOrigin:["http://localhost:8086"]},cors:[],authConfig:{type:"none"},authorize:[],storage:new we,sockets:new Map};await ae(this.#e,{},e);let t=ie(...e.middleware);return new B(t)}};var Ct={bindToApp:de,bindToServer:ce};export{Ct as TestClient};
1395
3
  //# sourceMappingURL=test.js.map