@bytecodealliance/preview3-shim 0.6.1 → 0.8.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.
Files changed (40) hide show
  1. package/README.md +9 -2
  2. package/dist/browser/cli/environment.d.ts +1 -0
  3. package/dist/browser/cli/environment.js +9 -4
  4. package/dist/browser/cli/exit.js +4 -3
  5. package/dist/browser/cli/run.d.ts +2 -0
  6. package/dist/browser/cli/run.js +11 -3
  7. package/dist/browser/cli/stderr.js +10 -3
  8. package/dist/browser/cli/stdin.js +3 -2
  9. package/dist/browser/cli/stdout.js +10 -3
  10. package/dist/browser/cli/terminal-stderr.js +2 -2
  11. package/dist/browser/cli/terminal-stdin.js +2 -2
  12. package/dist/browser/cli/terminal-stdout.js +2 -2
  13. package/dist/browser/cli.d.ts +3 -0
  14. package/dist/browser/cli.js +3 -0
  15. package/dist/browser/clocks/monotonic-clock.js +7 -7
  16. package/dist/browser/clocks/system-clock.js +4 -3
  17. package/dist/browser/filesystem/preopens.js +3 -2
  18. package/dist/browser/filesystem/types.d.ts +44 -1
  19. package/dist/browser/filesystem/types.js +139 -50
  20. package/dist/browser/filesystem.d.ts +13 -0
  21. package/dist/browser/filesystem.js +20 -0
  22. package/dist/browser/http/client.d.ts +2 -2
  23. package/dist/browser/http/client.js +138 -3
  24. package/dist/browser/http/handler.d.ts +4 -0
  25. package/dist/browser/http/handler.js +11 -3
  26. package/dist/browser/http/types.d.ts +44 -22
  27. package/dist/browser/http/types.js +192 -50
  28. package/dist/browser/http.d.ts +3 -0
  29. package/dist/browser/http.js +3 -0
  30. package/dist/browser/sockets/ip-name-lookup.js +34 -3
  31. package/dist/browser/sockets/types.d.ts +15 -0
  32. package/dist/browser/sockets/types.js +241 -49
  33. package/dist/browser/sockets.d.ts +2 -0
  34. package/dist/browser/sockets.js +2 -0
  35. package/dist/browser/streams.d.ts +20 -0
  36. package/dist/browser/streams.js +106 -0
  37. package/dist/nodejs/filesystem/descriptor.js +14 -17
  38. package/package.json +3 -3
  39. package/dist/common/errors.d.ts +0 -3
  40. package/dist/common/errors.js +0 -5
@@ -1,6 +1,141 @@
1
- import { Todo } from "../../common/errors.js";
2
- function send(request) {
3
- throw new Todo();
1
+ import * as preview2Http from "@bytecodealliance/preview2-shim/http";
2
+ import { readableFromPreview2Input, writeToPreview2Output } from "../streams.js";
3
+ import { Fields, Request, Response } from "./types.js";
4
+ class HttpError extends Error {
5
+ payload;
6
+ constructor(payload, message) {
7
+ super(message ?? payload.tag);
8
+ this.name = "HttpError";
9
+ this.payload = payload;
10
+ }
11
+ }
12
+ function internalError(error) {
13
+ return {
14
+ tag: "internal-error",
15
+ val: error instanceof Error ? error.message : String(error),
16
+ };
17
+ }
18
+ function preview2Options(options) {
19
+ if (!options) {
20
+ return undefined;
21
+ }
22
+ const converted = new preview2Http.types.RequestOptions();
23
+ converted.setConnectTimeout(options.getConnectTimeout());
24
+ converted.setFirstByteTimeout(options.getFirstByteTimeout());
25
+ converted.setBetweenBytesTimeout(options.getBetweenBytesTimeout());
26
+ return converted;
27
+ }
28
+ async function responseTrailers(incomingBody, bodyResult) {
29
+ const completed = await bodyResult;
30
+ if (completed.tag === "err") {
31
+ return completed;
32
+ }
33
+ const future = preview2Http.types.IncomingBody.finish(incomingBody);
34
+ await future.subscribe().block();
35
+ const result = future.get();
36
+ if (!result || result.tag === "err") {
37
+ return { tag: "err", val: internalError("response trailers were already consumed") };
38
+ }
39
+ if (result.val.tag === "err") {
40
+ return { tag: "err", val: result.val.val };
41
+ }
42
+ const fields = result.val.val;
43
+ return {
44
+ tag: "ok",
45
+ val: fields ? new Fields(fields) : undefined,
46
+ };
47
+ }
48
+ function trailerEntries(trailers) {
49
+ if (trailers?.tag === "none") {
50
+ return [];
51
+ }
52
+ if (trailers?.tag === "some") {
53
+ return trailerEntries(trailers.val);
54
+ }
55
+ if (trailers instanceof Fields) {
56
+ return trailers.copyAll();
57
+ }
58
+ if (Array.isArray(trailers)) {
59
+ return trailers;
60
+ }
61
+ throw new TypeError("trailers must be Fields or a list of entries");
62
+ }
63
+ async function send(request) {
64
+ if (!(request instanceof Request)) {
65
+ throw new TypeError("request must be a Request resource");
66
+ }
67
+ const outgoing = new preview2Http.types.OutgoingRequest(request.getHeaders()._preview2.clone());
68
+ outgoing.setMethod(request.getMethod());
69
+ outgoing.setScheme(request.getScheme() ?? { tag: "HTTP" });
70
+ outgoing.setAuthority(request.getAuthority());
71
+ outgoing.setPathWithQuery(request.getPathWithQuery());
72
+ let transmit = Promise.resolve({ tag: "ok", val: undefined });
73
+ const contents = request._body();
74
+ if (contents) {
75
+ const outgoingBody = outgoing.body();
76
+ transmit = (async () => {
77
+ let result = { tag: "ok", val: undefined };
78
+ try {
79
+ await writeToPreview2Output(contents, outgoingBody.write());
80
+ const trailers = await request._trailers();
81
+ if (trailers.tag === "err") {
82
+ result = trailers;
83
+ }
84
+ else if (trailers.val && trailerEntries(trailers.val).length > 0) {
85
+ result = {
86
+ tag: "err",
87
+ val: {
88
+ tag: "internal-error",
89
+ val: "browser Fetch does not support request trailers",
90
+ },
91
+ };
92
+ }
93
+ }
94
+ catch (error) {
95
+ result = { tag: "err", val: internalError(error) };
96
+ }
97
+ finally {
98
+ try {
99
+ preview2Http.types.OutgoingBody.finish(outgoingBody, undefined);
100
+ }
101
+ catch (error) {
102
+ if (result.tag === "ok") {
103
+ result = { tag: "err", val: internalError(error) };
104
+ }
105
+ }
106
+ }
107
+ return result;
108
+ })();
109
+ }
110
+ else {
111
+ transmit = request
112
+ ._trailers()
113
+ .then((trailers) => (trailers.tag === "err" ? trailers : { tag: "ok", val: undefined }));
114
+ }
115
+ const future = preview2Http.outgoingHandler.handle(outgoing, preview2Options(request.getOptions()));
116
+ void transmit.then((result) => request._resolve(result));
117
+ try {
118
+ await future.subscribe().block();
119
+ const result = future.get();
120
+ if (!result || result.tag === "err") {
121
+ throw new HttpError(internalError("HTTP response future was already consumed"));
122
+ }
123
+ if (result.val.tag === "err") {
124
+ throw new HttpError(result.val.val);
125
+ }
126
+ const incoming = result.val.val;
127
+ const headers = new Fields(incoming.headers().clone());
128
+ const incomingBody = incoming.consume();
129
+ const [contents, bodyResult] = readableFromPreview2Input(incomingBody.stream(), internalError);
130
+ const [response] = Response.new(headers, contents, responseTrailers(incomingBody, bodyResult));
131
+ response.setStatusCode(incoming.status());
132
+ return response;
133
+ }
134
+ catch (error) {
135
+ const httpError = error instanceof HttpError ? error : new HttpError(internalError(error));
136
+ request._resolve({ tag: "err", val: httpError.payload });
137
+ throw httpError;
138
+ }
4
139
  }
5
140
  export default {
6
141
  send,
@@ -1,5 +1,9 @@
1
1
  import type { Request, Response } from "../../../types/interfaces/wasi-http-handler.d.ts";
2
+ type Handler = {
3
+ handle(request: Request): Promise<Response> | Response;
4
+ };
2
5
  declare function handle(request: Request): Promise<Response>;
6
+ export declare function _setHandler(handler: Handler | undefined): Handler | undefined;
3
7
  declare const _default: {
4
8
  handle: typeof handle;
5
9
  };
@@ -1,6 +1,14 @@
1
- import { Todo } from "../../common/errors.js";
2
- function handle(request) {
3
- throw new Todo();
1
+ let currentHandler;
2
+ async function handle(request) {
3
+ if (!currentHandler) {
4
+ throw new Error("wasi:http/handler import is not configured");
5
+ }
6
+ return currentHandler.handle(request);
7
+ }
8
+ export function _setHandler(handler) {
9
+ const previous = currentHandler;
10
+ currentHandler = handler;
11
+ return previous;
4
12
  }
5
13
  export default {
6
14
  handle,
@@ -1,6 +1,18 @@
1
- import type { Fields as FieldsT, Request as RequestT, RequestOptions as RequestOptionsT, Response as ResponseT, FieldName, FieldValue, Headers, Method, Scheme, Duration, StatusCode, Trailers, ErrorCode, Result } from "../../../types/interfaces/wasi-http-types.d.ts";
2
- declare class Fields implements FieldsT {
3
- static fromList(entries: Array<[FieldName, FieldValue]>): FieldsT;
1
+ import { types as preview2Types } from "@bytecodealliance/preview2-shim/http";
2
+ import type { Fields as FieldsT, Request as RequestT, RequestOptions as RequestOptionsT, Response as ResponseT, FieldName, FieldValue, Headers, Method, Scheme, Duration, StatusCode, Trailers, HeaderError, ErrorCode, Result } from "../../../types/interfaces/wasi-http-types.d.ts";
3
+ type Preview2Fields = InstanceType<typeof preview2Types.Fields>;
4
+ export declare class HttpError extends Error {
5
+ readonly payload: HeaderError;
6
+ constructor(payload: HeaderError, message?: string);
7
+ }
8
+ export declare const _forbiddenHeaders: {
9
+ value: Set<string>;
10
+ };
11
+ export declare class Fields implements FieldsT {
12
+ #private;
13
+ readonly _preview2: Preview2Fields;
14
+ constructor(fields?: import("@bytecodealliance/preview2-shim/interfaces/wasi-http-types").Fields);
15
+ static fromList(entries: Array<[FieldName, FieldValue]>): Fields;
4
16
  get(name: FieldName): Array<FieldValue>;
5
17
  has(name: FieldName): boolean;
6
18
  set(name: FieldName, value: Array<FieldValue>): void;
@@ -8,10 +20,25 @@ declare class Fields implements FieldsT {
8
20
  getAndDelete(name: FieldName): Array<FieldValue>;
9
21
  append(name: FieldName, value: FieldValue): void;
10
22
  copyAll(): Array<[FieldName, FieldValue]>;
11
- clone(): FieldsT;
23
+ clone(): Fields;
24
+ static _lock(fields: Fields): Fields;
25
+ }
26
+ export declare class RequestOptions implements RequestOptionsT {
27
+ #private;
28
+ getConnectTimeout(): Duration | undefined;
29
+ setConnectTimeout(duration: Duration | undefined): void;
30
+ getFirstByteTimeout(): Duration | undefined;
31
+ setFirstByteTimeout(duration: Duration | undefined): void;
32
+ getBetweenBytesTimeout(): Duration | undefined;
33
+ setBetweenBytesTimeout(duration: Duration | undefined): void;
34
+ clone(): RequestOptions;
35
+ static _lock(options: RequestOptions | undefined): RequestOptions | undefined;
12
36
  }
13
- declare class Request implements RequestT {
14
- static new(headers: Headers, contents: ReadableStream<number> | undefined, trailers: Promise<Result<Trailers | undefined, ErrorCode>>, options: RequestOptions | undefined): [Request, Promise<Result<void, ErrorCode>>];
37
+ type TransmissionResult = Result<void, ErrorCode>;
38
+ type TrailersResult = Result<Trailers | undefined, ErrorCode>;
39
+ export declare class Request implements RequestT {
40
+ #private;
41
+ static new(headers: Headers, contents: ReadableStream<number> | undefined, trailers: Promise<TrailersResult>, options: RequestOptions | undefined): [Request, Promise<TransmissionResult>];
15
42
  getMethod(): Method;
16
43
  setMethod(method: Method): void;
17
44
  getPathWithQuery(): string | undefined;
@@ -20,25 +47,20 @@ declare class Request implements RequestT {
20
47
  setScheme(scheme: Scheme | undefined): void;
21
48
  getAuthority(): string | undefined;
22
49
  setAuthority(authority: string | undefined): void;
23
- getOptions(): RequestOptionsT | undefined;
24
- getHeaders(): Headers;
25
- static consumeBody(this_: Request, res: Promise<Result<void, ErrorCode>>): [ReadableStream<number>, Promise<Result<Trailers | undefined, ErrorCode>>];
26
- }
27
- declare class RequestOptions implements RequestOptionsT {
28
- getConnectTimeout(): Duration | undefined;
29
- setConnectTimeout(duration: Duration | undefined): void;
30
- getFirstByteTimeout(): Duration | undefined;
31
- setFirstByteTimeout(duration: Duration | undefined): void;
32
- getBetweenBytesTimeout(): Duration | undefined;
33
- setBetweenBytesTimeout(duration: Duration | undefined): void;
34
- clone(): RequestOptionsT;
50
+ getOptions(): RequestOptions | undefined;
51
+ getHeaders(): Fields;
52
+ static consumeBody(this_: Request, res: Promise<TransmissionResult>): [ReadableStream<number>, Promise<TrailersResult>];
53
+ _body(): ReadableStream<number> | undefined;
54
+ _trailers(): Promise<TrailersResult>;
55
+ _resolve(result: TransmissionResult): void;
35
56
  }
36
- declare class Response implements ResponseT {
37
- static new(headers: Headers, contents: ReadableStream<number> | undefined, trailers: Promise<Result<Trailers | undefined, ErrorCode>>): [Response, Promise<Result<void, ErrorCode>>];
57
+ export declare class Response implements ResponseT {
58
+ #private;
59
+ static new(headers: Headers, contents: ReadableStream<number> | undefined, trailers: Promise<TrailersResult>): [Response, Promise<TransmissionResult>];
38
60
  getStatusCode(): StatusCode;
39
61
  setStatusCode(statusCode: StatusCode): void;
40
- getHeaders(): Headers;
41
- static consumeBody(this_: Response, res: Promise<Result<void, ErrorCode>>): [ReadableStream<number>, Promise<Result<Trailers | undefined, ErrorCode>>];
62
+ getHeaders(): Fields;
63
+ static consumeBody(this_: Response, res: Promise<TransmissionResult>): [ReadableStream<number>, Promise<TrailersResult>];
42
64
  }
43
65
  declare const _default: {
44
66
  Fields: typeof Fields;
@@ -1,109 +1,251 @@
1
- import { Todo } from "../../common/errors.js";
2
- class Fields {
1
+ import { types as preview2Types } from "@bytecodealliance/preview2-shim/http";
2
+ export class HttpError extends Error {
3
+ payload;
4
+ constructor(payload, message) {
5
+ super(message ?? payload.tag);
6
+ this.name = "HttpError";
7
+ this.payload = payload;
8
+ }
9
+ }
10
+ export const _forbiddenHeaders = {
11
+ value: new Set([
12
+ "connection",
13
+ "http2-settings",
14
+ "host",
15
+ "keep-alive",
16
+ "proxy-authenticate",
17
+ "proxy-authorization",
18
+ "proxy-connection",
19
+ "transfer-encoding",
20
+ "upgrade",
21
+ ]),
22
+ };
23
+ function rejectForbidden(name) {
24
+ if (_forbiddenHeaders.value.has(name.toLowerCase())) {
25
+ throw new HttpError({ tag: "forbidden" }, `Header ${name} is forbidden`);
26
+ }
27
+ }
28
+ export class Fields {
29
+ _preview2;
30
+ #immutable = false;
31
+ constructor(fields = new preview2Types.Fields()) {
32
+ this._preview2 = fields;
33
+ }
3
34
  static fromList(entries) {
4
- throw new Todo();
35
+ for (const [name] of entries) {
36
+ rejectForbidden(name);
37
+ }
38
+ return new Fields(preview2Types.Fields.fromList(entries));
5
39
  }
6
40
  get(name) {
7
- throw new Todo();
41
+ return this._preview2.get(name);
8
42
  }
9
43
  has(name) {
10
- throw new Todo();
44
+ return this._preview2.has(name);
11
45
  }
12
46
  set(name, value) {
13
- throw new Todo();
47
+ this.#ensureMutable();
48
+ rejectForbidden(name);
49
+ this._preview2.set(name, value);
14
50
  }
15
51
  delete(name) {
16
- throw new Todo();
52
+ this.#ensureMutable();
53
+ rejectForbidden(name);
54
+ this._preview2.delete(name);
17
55
  }
18
56
  getAndDelete(name) {
19
- throw new Todo();
57
+ const values = this.get(name);
58
+ this.delete(name);
59
+ return values;
20
60
  }
21
61
  append(name, value) {
22
- throw new Todo();
62
+ this.#ensureMutable();
63
+ rejectForbidden(name);
64
+ this._preview2.append(name, value);
23
65
  }
24
66
  copyAll() {
25
- throw new Todo();
67
+ return this._preview2.entries().map(([name, value]) => [name, value.slice()]);
68
+ }
69
+ clone() {
70
+ return new Fields(this._preview2.clone());
71
+ }
72
+ static _lock(fields) {
73
+ fields.#immutable = true;
74
+ return fields;
75
+ }
76
+ #ensureMutable() {
77
+ if (this.#immutable) {
78
+ throw new HttpError({ tag: "immutable" }, "Cannot modify immutable fields");
79
+ }
80
+ }
81
+ }
82
+ export class RequestOptions {
83
+ #connectTimeout;
84
+ #firstByteTimeout;
85
+ #betweenBytesTimeout;
86
+ #immutable = false;
87
+ getConnectTimeout() {
88
+ return this.#connectTimeout;
89
+ }
90
+ setConnectTimeout(duration) {
91
+ this.#ensureMutable();
92
+ this.#connectTimeout = duration;
93
+ }
94
+ getFirstByteTimeout() {
95
+ return this.#firstByteTimeout;
96
+ }
97
+ setFirstByteTimeout(duration) {
98
+ this.#ensureMutable();
99
+ this.#firstByteTimeout = duration;
100
+ }
101
+ getBetweenBytesTimeout() {
102
+ return this.#betweenBytesTimeout;
103
+ }
104
+ setBetweenBytesTimeout(duration) {
105
+ this.#ensureMutable();
106
+ this.#betweenBytesTimeout = duration;
26
107
  }
27
108
  clone() {
28
- throw new Todo();
109
+ const options = new RequestOptions();
110
+ options.#connectTimeout = this.#connectTimeout;
111
+ options.#firstByteTimeout = this.#firstByteTimeout;
112
+ options.#betweenBytesTimeout = this.#betweenBytesTimeout;
113
+ return options;
114
+ }
115
+ static _lock(options) {
116
+ if (options) {
117
+ options.#immutable = true;
118
+ }
119
+ return options;
120
+ }
121
+ #ensureMutable() {
122
+ if (this.#immutable) {
123
+ throw new HttpError({ tag: "immutable" }, "Cannot modify immutable request options");
124
+ }
29
125
  }
30
126
  }
31
- class Request {
127
+ function emptyByteStream() {
128
+ return new ReadableStream({
129
+ start(controller) {
130
+ controller.close();
131
+ },
132
+ });
133
+ }
134
+ export class Request {
135
+ #method = { tag: "get" };
136
+ #pathWithQuery;
137
+ #scheme;
138
+ #authority;
139
+ #headers;
140
+ #contents;
141
+ #trailers;
142
+ #options;
143
+ #resolveTransmission;
144
+ #consumed = false;
145
+ #transmissionResolved = false;
32
146
  static new(headers, contents, trailers, options) {
33
- throw new Todo();
147
+ if (!(headers instanceof Fields)) {
148
+ throw new TypeError("headers must be a Fields resource");
149
+ }
150
+ if (options !== undefined && !(options instanceof RequestOptions)) {
151
+ throw new TypeError("options must be a RequestOptions resource");
152
+ }
153
+ const request = new Request();
154
+ request.#headers = headers;
155
+ request.#contents = contents;
156
+ request.#trailers = Promise.resolve(trailers);
157
+ request.#options = RequestOptions._lock(options);
158
+ Fields._lock(headers);
159
+ const transmission = new Promise((resolve) => (request.#resolveTransmission = resolve));
160
+ return [request, transmission];
34
161
  }
35
162
  getMethod() {
36
- throw new Todo();
163
+ return this.#method;
37
164
  }
38
165
  setMethod(method) {
39
- throw new Todo();
166
+ this.#method = method;
40
167
  }
41
168
  getPathWithQuery() {
42
- throw new Todo();
169
+ return this.#pathWithQuery;
43
170
  }
44
171
  setPathWithQuery(pathWithQuery) {
45
- throw new Todo();
172
+ this.#pathWithQuery = pathWithQuery;
46
173
  }
47
174
  getScheme() {
48
- throw new Todo();
175
+ return this.#scheme;
49
176
  }
50
177
  setScheme(scheme) {
51
- throw new Todo();
178
+ this.#scheme = scheme;
52
179
  }
53
180
  getAuthority() {
54
- throw new Todo();
181
+ return this.#authority;
55
182
  }
56
183
  setAuthority(authority) {
57
- throw new Todo();
184
+ this.#authority = authority;
58
185
  }
59
186
  getOptions() {
60
- throw new Todo();
187
+ return this.#options;
61
188
  }
62
189
  getHeaders() {
63
- throw new Todo();
190
+ return this.#headers;
64
191
  }
65
192
  static consumeBody(this_, res) {
66
- throw new Todo();
67
- }
68
- }
69
- class RequestOptions {
70
- getConnectTimeout() {
71
- throw new Todo();
193
+ if (this_.#consumed) {
194
+ throw new Error("request body has already been consumed");
195
+ }
196
+ this_.#consumed = true;
197
+ void Promise.resolve(res).catch(() => { });
198
+ return [this_.#contents ?? emptyByteStream(), this_.#trailers];
72
199
  }
73
- setConnectTimeout(duration) {
74
- throw new Todo();
200
+ _body() {
201
+ return this.#contents;
75
202
  }
76
- getFirstByteTimeout() {
77
- throw new Todo();
203
+ _trailers() {
204
+ return this.#trailers;
78
205
  }
79
- setFirstByteTimeout(duration) {
80
- throw new Todo();
81
- }
82
- getBetweenBytesTimeout() {
83
- throw new Todo();
84
- }
85
- setBetweenBytesTimeout(duration) {
86
- throw new Todo();
87
- }
88
- clone() {
89
- throw new Todo();
206
+ _resolve(result) {
207
+ if (!this.#transmissionResolved) {
208
+ this.#transmissionResolved = true;
209
+ this.#resolveTransmission(result);
210
+ }
90
211
  }
91
212
  }
92
- class Response {
213
+ export class Response {
214
+ #statusCode = 200;
215
+ #headers;
216
+ #contents;
217
+ #trailers;
218
+ #consumed = false;
93
219
  static new(headers, contents, trailers) {
94
- throw new Todo();
220
+ if (!(headers instanceof Fields)) {
221
+ throw new TypeError("headers must be a Fields resource");
222
+ }
223
+ const response = new Response();
224
+ response.#headers = headers;
225
+ Fields._lock(headers);
226
+ response.#contents = contents;
227
+ response.#trailers = Promise.resolve(trailers);
228
+ return [response, Promise.resolve({ tag: "ok", val: undefined })];
95
229
  }
96
230
  getStatusCode() {
97
- throw new Todo();
231
+ return this.#statusCode;
98
232
  }
99
233
  setStatusCode(statusCode) {
100
- throw new Todo();
234
+ if (!Number.isInteger(statusCode) || statusCode < 100 || statusCode > 599) {
235
+ throw new RangeError(`invalid HTTP status code: ${statusCode}`);
236
+ }
237
+ this.#statusCode = statusCode;
101
238
  }
102
239
  getHeaders() {
103
- throw new Todo();
240
+ return this.#headers;
104
241
  }
105
242
  static consumeBody(this_, res) {
106
- throw new Todo();
243
+ if (this_.#consumed) {
244
+ throw new Error("response body has already been consumed");
245
+ }
246
+ this_.#consumed = true;
247
+ void Promise.resolve(res).catch(() => { });
248
+ return [this_.#contents ?? emptyByteStream(), this_.#trailers];
107
249
  }
108
250
  }
109
251
  export default {
@@ -1,3 +1,6 @@
1
1
  export { default as client } from "./http/client.js";
2
2
  export { default as handler } from "./http/handler.js";
3
3
  export { default as types } from "./http/types.js";
4
+ export { _forbiddenHeaders, HttpError } from "./http/types.js";
5
+ export { _setRequestStreaming } from "@bytecodealliance/preview2-shim/http";
6
+ export { _setHandler } from "./http/handler.js";
@@ -1,3 +1,6 @@
1
1
  export { default as client } from "./http/client.js";
2
2
  export { default as handler } from "./http/handler.js";
3
3
  export { default as types } from "./http/types.js";
4
+ export { _forbiddenHeaders, HttpError } from "./http/types.js";
5
+ export { _setRequestStreaming } from "@bytecodealliance/preview2-shim/http";
6
+ export { _setHandler } from "./http/handler.js";
@@ -1,6 +1,37 @@
1
- import { Todo } from "../../common/errors.js";
2
- function resolveAddresses(name) {
3
- throw new Todo();
1
+ import { ipNameLookup } from "@bytecodealliance/preview2-shim/sockets";
2
+ class NameLookupError extends Error {
3
+ payload;
4
+ constructor(payload) {
5
+ super(payload.tag);
6
+ this.payload = payload;
7
+ }
8
+ }
9
+ async function resolveAddresses(name) {
10
+ try {
11
+ const stream = ipNameLookup.resolveAddresses({}, name);
12
+ const addresses = [];
13
+ while (true) {
14
+ const address = stream.resolveNextAddress();
15
+ if (!address) {
16
+ break;
17
+ }
18
+ addresses.push(address);
19
+ }
20
+ if (addresses.length === 0) {
21
+ throw new NameLookupError({ tag: "name-unresolvable" });
22
+ }
23
+ return addresses;
24
+ }
25
+ catch (error) {
26
+ if (error instanceof NameLookupError) {
27
+ throw error;
28
+ }
29
+ const tag = typeof error === "string" ? error : error?.tag;
30
+ if (tag === "not-supported") {
31
+ throw new NameLookupError({ tag: "other", val: "not-supported" });
32
+ }
33
+ throw new NameLookupError({ tag: "other", val: String(error) });
34
+ }
4
35
  }
5
36
  export default {
6
37
  resolveAddresses,
@@ -1,6 +1,20 @@
1
+ import * as preview2Sockets from "@bytecodealliance/preview2-shim/sockets";
1
2
  import type { Duration, ErrorCode, IpAddressFamily, IpSocketAddress, Result, TcpSocket as TcpSocketT, UdpSocket as UdpSocketT } from "../../../types/interfaces/wasi-sockets-types.d.ts";
3
+ type TcpProvider = {
4
+ tcp: typeof preview2Sockets.tcp;
5
+ tcpCreateSocket: typeof preview2Sockets.tcpCreateSocket;
6
+ };
7
+ type UdpProvider = {
8
+ udp: typeof preview2Sockets.udp;
9
+ udpCreateSocket: typeof preview2Sockets.udpCreateSocket;
10
+ };
11
+ export declare function socketErrorCode(error: unknown): ErrorCode;
12
+ export declare function _setTcpProvider(provider: TcpProvider): TcpProvider;
13
+ export declare function _setUdpProvider(provider: UdpProvider): UdpProvider;
2
14
  export declare class TcpSocket implements TcpSocketT {
15
+ #private;
3
16
  static create(addressFamily: IpAddressFamily): TcpSocket;
17
+ static _wrap(socket: unknown, input?: unknown, output?: unknown): TcpSocket;
4
18
  bind(localAddress: IpSocketAddress): void;
5
19
  connect(remoteAddress: IpSocketAddress): Promise<void>;
6
20
  listen(): ReadableStream<TcpSocketT>;
@@ -27,6 +41,7 @@ export declare class TcpSocket implements TcpSocketT {
27
41
  setSendBufferSize(value: bigint): void;
28
42
  }
29
43
  export declare class UdpSocket implements UdpSocketT {
44
+ #private;
30
45
  static create(addressFamily: IpAddressFamily): UdpSocket;
31
46
  bind(localAddress: IpSocketAddress): void;
32
47
  connect(remoteAddress: IpSocketAddress): void;