@venn-lang/http 0.1.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/LICENSE +21 -0
- package/README.md +162 -0
- package/dist/index.d.ts +213 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +577 -0
- package/dist/index.js.map +1 -0
- package/dist/node.d.mts +63 -0
- package/dist/node.d.mts.map +1 -0
- package/dist/node.mjs +146 -0
- package/dist/node.mjs.map +1 -0
- package/package.json +61 -0
- package/src/actions/build-request.ts +110 -0
- package/src/actions/http-action.ts +36 -0
- package/src/actions/index.ts +18 -0
- package/src/actions/request-params.ts +32 -0
- package/src/actions/request.types.ts +28 -0
- package/src/clients/fake-client.ts +37 -0
- package/src/clients/fetch-client.ts +59 -0
- package/src/clients/index.ts +2 -0
- package/src/index.ts +11 -0
- package/src/matchers/header.ts +29 -0
- package/src/matchers/index.ts +4 -0
- package/src/node.ts +6 -0
- package/src/plugin.ts +22 -0
- package/src/port/http-client.port.ts +15 -0
- package/src/port/http-client.types.ts +29 -0
- package/src/port/index.ts +2 -0
- package/src/server/http-server.errors.ts +36 -0
- package/src/server/http-server.port.ts +15 -0
- package/src/server/http-server.types.ts +39 -0
- package/src/server/index.ts +12 -0
- package/src/server/memory-server.ts +78 -0
- package/src/server/node-server.ts +122 -0
- package/src/server/on-action.ts +42 -0
- package/src/server/serve-action.ts +99 -0
- package/src/types.ts +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vinicius Borges
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# @venn-lang/http
|
|
2
|
+
|
|
3
|
+
> The `http` namespace: seven request verbs, a server, and the two ports they ride.
|
|
4
|
+
|
|
5
|
+
Venn's grammar knows no verbs. `@venn-lang/http` registers the `http` namespace with the runtime, so
|
|
6
|
+
`http.get` resolves to an action, `res` gets a known shape, and the editor can complete and document
|
|
7
|
+
both. The plugin itself never touches the network: requests go through the `HttpClient` port and
|
|
8
|
+
servers through the `HttpServer` port, so the CLI binds `fetch` and a real socket while a test binds
|
|
9
|
+
a fake and stays offline.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
Nothing to install yet. The package is unpublished (version `0.0.0`) and ships inside
|
|
14
|
+
`@venn-lang/stdlib`, which the `venn` CLI and the language server both load. A `.vn` file declares it:
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
use "venn/http"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
module demo.api
|
|
24
|
+
|
|
25
|
+
use "venn/http"
|
|
26
|
+
use "venn/assert"
|
|
27
|
+
|
|
28
|
+
config { baseUrl: "https://api.test" }
|
|
29
|
+
|
|
30
|
+
flow "Health" {
|
|
31
|
+
step "the service answers" {
|
|
32
|
+
const res = http.get "/health"
|
|
33
|
+
expect res.status == 200
|
|
34
|
+
expect res.ok
|
|
35
|
+
expect res header "content-type"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
A relative path is joined onto `config.baseUrl`; a URL with a scheme passes through untouched.
|
|
41
|
+
|
|
42
|
+
## API
|
|
43
|
+
|
|
44
|
+
Everything below is exported from the package barrel.
|
|
45
|
+
|
|
46
|
+
| Export | What it is |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| `httpPlugin` (also the default export) | The `PluginDefinition`: namespace `http`, `requires: ["net"]`. |
|
|
49
|
+
| `HttpClientPort` | `Port<HttpClient>`, id `venn.port.http-client`, version 1, method `request`. |
|
|
50
|
+
| `createFetchClient()` | The real client, backed by the global `fetch`. |
|
|
51
|
+
| `createFakeClient({ responses })` | The double: canned responses keyed by URL, `okResponse()` for anything else. |
|
|
52
|
+
| `okResponse(overrides?)` | A `200` response with body `{"ok":true}`, for seeding the fake. |
|
|
53
|
+
| `HttpServerPort` | `Port<HttpServer>`, id `venn.port.http-server`, version 1, method `listen`. |
|
|
54
|
+
| `createMemoryServer()` | The double: no socket, and `deliver(request)` to knock on its door. |
|
|
55
|
+
| `serveAction()`, `onAction()` | The two `ActionDefinition`s behind `http.serve` and `http.on`. |
|
|
56
|
+
| `portInUse`, `listenFailed`, `asListenError` | `VennError` producers for `VN7020` and `VN7021`. |
|
|
57
|
+
|
|
58
|
+
Types: `HttpClient`, `HttpRequest`, `HttpResponse`, `HttpServer`, `RequestHandler`, `RunningServer`,
|
|
59
|
+
`ServerRequest`, `ServerReply`, `ServeHandle`, `MemoryServer`, `MemoryHttpServer`.
|
|
60
|
+
|
|
61
|
+
The subpath `@venn-lang/http/node` carries the one file that imports `node:*`:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { createNodeServer, type NodeHttpServer } from "@venn-lang/http/node";
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`createNodeServer()` binds a real socket and adds `closeAll()`, so whoever owns the process can give
|
|
68
|
+
its sockets back on the way out. Keeping it behind a subpath is what lets the main entry stay neutral
|
|
69
|
+
and run in the editor's worker.
|
|
70
|
+
|
|
71
|
+
## Verbs
|
|
72
|
+
|
|
73
|
+
| Verb | Shape | Result |
|
|
74
|
+
| --- | --- | --- |
|
|
75
|
+
| `http.get` `http.post` `http.put` `http.patch` `http.delete` `http.head` `http.options` | `http.get url { … }` | `http.Response` |
|
|
76
|
+
| `http.serve` | `http.serve { port, host }` | `http.Server` |
|
|
77
|
+
| `http.on` | `http.on(server, handler)` | nothing |
|
|
78
|
+
|
|
79
|
+
Every request verb takes the URL as its one positional argument. The rest is the trailing options map:
|
|
80
|
+
|
|
81
|
+
| Option | Meaning |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| `headers` | Extra headers. Anything set here wins over what Venn would infer. |
|
|
84
|
+
| `query` | Appended to the URL as a query string, encoded for you. |
|
|
85
|
+
| `body` | What to send. A map becomes JSON; a string is sent as written. |
|
|
86
|
+
| `encode` | `json`, `form`, `multipart` or `raw`. Defaults to `json` for a map, `raw` for a string. |
|
|
87
|
+
| `bearer` | Shorthand for `Authorization: Bearer …`. |
|
|
88
|
+
| `basic` | `{ user, pass }`, as HTTP basic auth. |
|
|
89
|
+
|
|
90
|
+
`http.serve` takes `port` (`0` asks for any free one) and `host` (defaults to `127.0.0.1`).
|
|
91
|
+
|
|
92
|
+
## Serving
|
|
93
|
+
|
|
94
|
+
A server is not a request-response verb: it stays, and the requests arrive afterwards. So `http.serve`
|
|
95
|
+
hands back a handle, and `http.on` says what to answer with.
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
use "venn/http"
|
|
99
|
+
|
|
100
|
+
const api = http.serve { port: 0 }
|
|
101
|
+
defer { api.close() }
|
|
102
|
+
|
|
103
|
+
http.on(api, route)
|
|
104
|
+
|
|
105
|
+
fn route(req) {
|
|
106
|
+
const path = req.url.before("?")
|
|
107
|
+
path == "/health" ? { ok: true, method: req.method } : { status: 404 }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
print "listening on http://127.0.0.1:${api.port}"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The handler is an ordinary `fn`, so everything the language does works inside it. A map carrying
|
|
114
|
+
`status`, `headers` or `body` is taken as a reply; anything else becomes the body of a `200`;
|
|
115
|
+
returning nothing sends `204`. Until `http.on` runs, the server answers `404`, so a request that
|
|
116
|
+
arrives early gets an answer instead of hanging.
|
|
117
|
+
|
|
118
|
+
## Matchers and types
|
|
119
|
+
|
|
120
|
+
`header` is the one matcher: `expect res header "content-type"` passes when the response carries that
|
|
121
|
+
header. It declares an optional second argument for the expected value, but the check today is
|
|
122
|
+
presence only.
|
|
123
|
+
|
|
124
|
+
The plugin publishes four types to the checker: `http.Response` (`status`, `ok`, `headers`, `body`
|
|
125
|
+
as raw text, `json` as that text parsed, `time`), `http.Request`, `http.Reply` and `http.Server`.
|
|
126
|
+
`json` is the one field nothing can know the shape of, so give it one by naming it:
|
|
127
|
+
`const price: Price = res.json`.
|
|
128
|
+
|
|
129
|
+
## Ports and conformance
|
|
130
|
+
|
|
131
|
+
Two ports, each with two implementations and a suite both must pass:
|
|
132
|
+
|
|
133
|
+
- `HttpClient`: `createFetchClient` and `createFakeClient`, checked by
|
|
134
|
+
`src/clients/http-client.suite.ts`. The test stubs the global `fetch` so the real client's mapping
|
|
135
|
+
runs the same suite offline.
|
|
136
|
+
- `HttpServer`: `createNodeServer` and `createMemoryServer`, checked by
|
|
137
|
+
`src/server/http-server.suite.ts`. The double keeps its own book of bound ports, so a flow that
|
|
138
|
+
binds the same port twice fails there exactly as it would against a real socket.
|
|
139
|
+
|
|
140
|
+
Binding one implementation looks like this:
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
import { createFakeClient, HttpClientPort, okResponse } from "@venn-lang/http";
|
|
144
|
+
|
|
145
|
+
const ports = [
|
|
146
|
+
{
|
|
147
|
+
port: HttpClientPort,
|
|
148
|
+
impl: createFakeClient({
|
|
149
|
+
responses: { "https://api.test/health": okResponse({ status: 200 }) },
|
|
150
|
+
}),
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
A socket that refuses to bind is translated at the producer: `EADDRINUSE` becomes `VN7020`, anything
|
|
156
|
+
else `VN7021`. No caller ever reads a `node:net` errno.
|
|
157
|
+
|
|
158
|
+
## See also
|
|
159
|
+
|
|
160
|
+
- [`@venn-lang/sdk`](../sdk) for `definePlugin`, `defineAction` and `defineMatcher`.
|
|
161
|
+
- [`@venn-lang/stdlib`](../stdlib) for the plugin list and the default port bindings.
|
|
162
|
+
- [`@venn-lang/ws`](../std-ws) and [`@venn-lang/mqtt`](../std-mqtt), the other two network plugins.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { ActionDefinition, PluginDefinition } from "@venn-lang/sdk";
|
|
2
|
+
import { Port, VennError } from "@venn-lang/contracts";
|
|
3
|
+
//#region src/port/http-client.types.d.ts
|
|
4
|
+
/** One request, ready to send: the verb, the absolute URL and the payload. */
|
|
5
|
+
interface HttpRequest {
|
|
6
|
+
method: string;
|
|
7
|
+
url: string;
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
body?: string;
|
|
10
|
+
/** Aborted when a `race` this request runs inside has already been won. */
|
|
11
|
+
signal?: AbortSignal;
|
|
12
|
+
}
|
|
13
|
+
/** What an http verb hands back, and what `res` holds in a flow. */
|
|
14
|
+
interface HttpResponse {
|
|
15
|
+
status: number;
|
|
16
|
+
ok: boolean;
|
|
17
|
+
headers: Record<string, string>;
|
|
18
|
+
body: string;
|
|
19
|
+
json: unknown;
|
|
20
|
+
time: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Sending one request and reading the reply.
|
|
24
|
+
*
|
|
25
|
+
* Two implementations: `createFetchClient` over a real socket and
|
|
26
|
+
* `createFakeClient` for tests. The conformance suite is what says they agree.
|
|
27
|
+
*/
|
|
28
|
+
interface HttpClient {
|
|
29
|
+
request(req: HttpRequest): Promise<HttpResponse>;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/port/http-client.port.d.ts
|
|
33
|
+
/**
|
|
34
|
+
* The port descriptor an http verb resolves through `ctx.port(...)`.
|
|
35
|
+
*
|
|
36
|
+
* Declares the `net` capability, so a host that cannot open sockets refuses the
|
|
37
|
+
* binding at load time with a readable diagnostic.
|
|
38
|
+
*/
|
|
39
|
+
declare const HttpClientPort: Port<HttpClient>;
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/clients/fake-client.d.ts
|
|
42
|
+
/**
|
|
43
|
+
* A 200 response with a small JSON body, for tests that only care about a field
|
|
44
|
+
* or two.
|
|
45
|
+
*
|
|
46
|
+
* @param overrides Fields to replace on the default response.
|
|
47
|
+
* @returns A complete {@link HttpResponse}.
|
|
48
|
+
*/
|
|
49
|
+
declare function okResponse(overrides?: Partial<HttpResponse>): HttpResponse;
|
|
50
|
+
/**
|
|
51
|
+
* The double: answers from a table keyed by the request's full URL.
|
|
52
|
+
*
|
|
53
|
+
* A URL with no entry gets {@link okResponse}, so a test only has to name the
|
|
54
|
+
* responses it cares about. Never touches the network.
|
|
55
|
+
*
|
|
56
|
+
* @param args.responses Canned responses, keyed by the URL the flow requests.
|
|
57
|
+
*/
|
|
58
|
+
declare function createFakeClient(args?: {
|
|
59
|
+
responses?: Record<string, HttpResponse>;
|
|
60
|
+
}): HttpClient;
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/clients/fetch-client.d.ts
|
|
63
|
+
/**
|
|
64
|
+
* The real client, over the global `fetch`. Requires the `net` capability.
|
|
65
|
+
*
|
|
66
|
+
* The body is always read as text and parsed afterwards, so a reply that claims
|
|
67
|
+
* JSON but is not still arrives whole in `body` instead of throwing.
|
|
68
|
+
*/
|
|
69
|
+
declare function createFetchClient(): HttpClient;
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/plugin.d.ts
|
|
72
|
+
/**
|
|
73
|
+
* The `http` namespace: the request verbs, `http.serve`/`http.on`, the `header`
|
|
74
|
+
* matcher and the types they trade in.
|
|
75
|
+
*
|
|
76
|
+
* Requires the `net` capability, so a host without it refuses the plugin at load
|
|
77
|
+
* time rather than failing mid-flow. The compiler treats it exactly as it treats
|
|
78
|
+
* a third-party plugin.
|
|
79
|
+
*/
|
|
80
|
+
declare const httpPlugin: PluginDefinition;
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/server/http-server.errors.d.ts
|
|
83
|
+
/** VN7020: the address the flow asked for is already taken by something else. */
|
|
84
|
+
declare function portInUse(args: {
|
|
85
|
+
port: number;
|
|
86
|
+
host: string;
|
|
87
|
+
}): VennError;
|
|
88
|
+
/** VN7021: the socket refused to bind for any other reason. */
|
|
89
|
+
declare function listenFailed(args: {
|
|
90
|
+
port: number;
|
|
91
|
+
host: string;
|
|
92
|
+
cause: string;
|
|
93
|
+
}): VennError;
|
|
94
|
+
/**
|
|
95
|
+
* Whatever the socket threw, as a Venn error: VN7020 for `EADDRINUSE`, VN7021
|
|
96
|
+
* for anything else.
|
|
97
|
+
*
|
|
98
|
+
* The translation lives at the producer so no caller has to read a `node:net`
|
|
99
|
+
* errno to know what went wrong.
|
|
100
|
+
*/
|
|
101
|
+
declare function asListenError(args: {
|
|
102
|
+
port: number;
|
|
103
|
+
host: string;
|
|
104
|
+
error: unknown;
|
|
105
|
+
}): VennError;
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/server/http-server.types.d.ts
|
|
108
|
+
/** One request a server received, as the language sees it. */
|
|
109
|
+
interface ServerRequest {
|
|
110
|
+
method: string;
|
|
111
|
+
/** The path with its query string, exactly as it arrived. */
|
|
112
|
+
url: string;
|
|
113
|
+
headers: Record<string, string>;
|
|
114
|
+
body: string;
|
|
115
|
+
}
|
|
116
|
+
/** What a handler answers with. Every field has a sensible default. */
|
|
117
|
+
interface ServerReply {
|
|
118
|
+
status?: number;
|
|
119
|
+
headers?: Record<string, string>;
|
|
120
|
+
/** A string is sent as-is; anything else is sent as JSON. */
|
|
121
|
+
body?: unknown;
|
|
122
|
+
}
|
|
123
|
+
/** Called once per request. Returning nothing sends `204 No Content`. */
|
|
124
|
+
type RequestHandler = (request: ServerRequest) => ServerReply | undefined | Promise<ServerReply | undefined>;
|
|
125
|
+
/** A server that is listening, and how to stop it. */
|
|
126
|
+
interface RunningServer {
|
|
127
|
+
/** The port it actually bound to. Asking for 0 gets one chosen for you. */
|
|
128
|
+
readonly port: number;
|
|
129
|
+
close(): Promise<void>;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Accepting requests over HTTP.
|
|
133
|
+
*
|
|
134
|
+
* Two implementations: `createNodeServer` binds a real socket, and
|
|
135
|
+
* `createMemoryServer` keeps the handler in memory so a test can deliver a
|
|
136
|
+
* request without a network. The conformance suite is what says they agree.
|
|
137
|
+
*/
|
|
138
|
+
interface HttpServer {
|
|
139
|
+
listen(args: {
|
|
140
|
+
port: number;
|
|
141
|
+
host?: string;
|
|
142
|
+
handle: RequestHandler;
|
|
143
|
+
}): Promise<RunningServer>;
|
|
144
|
+
}
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/server/http-server.port.d.ts
|
|
147
|
+
/**
|
|
148
|
+
* The port descriptor `http.serve` resolves through `ctx.port(...)`.
|
|
149
|
+
*
|
|
150
|
+
* Declares the `net` capability, so a host that cannot bind a socket refuses the
|
|
151
|
+
* binding at load time rather than mid-flow.
|
|
152
|
+
*/
|
|
153
|
+
declare const HttpServerPort: Port<HttpServer>;
|
|
154
|
+
//#endregion
|
|
155
|
+
//#region src/server/memory-server.d.ts
|
|
156
|
+
/** A server that is listening in memory, plus the way to knock on its door. */
|
|
157
|
+
interface MemoryServer extends RunningServer {
|
|
158
|
+
/** Deliver a request as though it had arrived over the network. */
|
|
159
|
+
deliver(request: Partial<ServerRequest>): Promise<ServerReply>;
|
|
160
|
+
readonly closed: boolean;
|
|
161
|
+
}
|
|
162
|
+
/** The double factory, which keeps every server it started so a test can find it. */
|
|
163
|
+
interface MemoryHttpServer extends HttpServer {
|
|
164
|
+
/** Every server started through this, newest last. */
|
|
165
|
+
readonly started: readonly MemoryServer[];
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* The double: no socket, no network, no waiting.
|
|
169
|
+
*
|
|
170
|
+
* A test starts the flow that serves, hands it a request and reads the reply,
|
|
171
|
+
* running the same handler the real server would call. Ports are book-kept here
|
|
172
|
+
* rather than by the operating system, so tests beside each other never collide.
|
|
173
|
+
*/
|
|
174
|
+
declare function createMemoryServer(): MemoryHttpServer;
|
|
175
|
+
//#endregion
|
|
176
|
+
//#region src/server/on-action.d.ts
|
|
177
|
+
/**
|
|
178
|
+
* `http.on server handler`: say what the server answers with.
|
|
179
|
+
*
|
|
180
|
+
* The handler is an ordinary `fn`, so everything the language already does
|
|
181
|
+
* applies inside it: it can call any verb, and it waits for what it reaches for
|
|
182
|
+
* without saying so. Whatever it returns becomes the reply. Calling `http.on`
|
|
183
|
+
* again replaces the handler.
|
|
184
|
+
*/
|
|
185
|
+
declare function onAction(): ActionDefinition;
|
|
186
|
+
//#endregion
|
|
187
|
+
//#region src/server/serve-action.d.ts
|
|
188
|
+
/**
|
|
189
|
+
* The value `http.serve` hands back, seen by flows as `http.Server`.
|
|
190
|
+
*
|
|
191
|
+
* A server is not a request-response verb: it stays, and the requests arrive
|
|
192
|
+
* afterwards. So the verb returns something the program holds on to: the port it
|
|
193
|
+
* got, and what it may do with it.
|
|
194
|
+
*/
|
|
195
|
+
interface ServeHandle {
|
|
196
|
+
kind: "http-server";
|
|
197
|
+
port: number;
|
|
198
|
+
/** Deliver one request to whatever `handle` was last given. Used by tests. */
|
|
199
|
+
deliver: (request: Partial<ServerRequest>) => Promise<ServerReply>;
|
|
200
|
+
close: () => Promise<void>;
|
|
201
|
+
/** Replace the handler. `http.on` is how a flow reaches this. */
|
|
202
|
+
onRequest: (handle: (request: ServerRequest) => unknown) => void;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* `let api = http.serve { port: 8080 }`: start listening.
|
|
206
|
+
*
|
|
207
|
+
* The handler starts as a 404 and `http.on` replaces it, so a request arriving
|
|
208
|
+
* before the flow has said what to do with it gets an answer instead of hanging.
|
|
209
|
+
*/
|
|
210
|
+
declare function serveAction(): ActionDefinition;
|
|
211
|
+
//#endregion
|
|
212
|
+
export { type HttpClient, HttpClientPort, type HttpRequest, type HttpResponse, type HttpServer, HttpServerPort, type MemoryHttpServer, type MemoryServer, type RequestHandler, type RunningServer, type ServeHandle, type ServerReply, type ServerRequest, asListenError, createFakeClient, createFetchClient, createMemoryServer, httpPlugin as default, httpPlugin, listenFailed, okResponse, onAction, portInUse, serveAction };
|
|
213
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/port/http-client.types.ts","../src/port/http-client.port.ts","../src/clients/fake-client.ts","../src/clients/fetch-client.ts","../src/plugin.ts","../src/server/http-server.errors.ts","../src/server/http-server.types.ts","../src/server/http-server.port.ts","../src/server/memory-server.ts","../src/server/on-action.ts","../src/server/serve-action.ts"],"mappings":";;;;UACiB;EACf;EACA;EACA,UAAU;EACV;;EAEA,SAAS;;;UAIM;EACf;EACA;EACA,SAAS;EACT;EACA;EACA;;;;;;;;UASe;EACf,QAAQ,KAAK,cAAc,QAAQ;;;;;;;;;;cClBxB,gBAAgB,KAAK;;;;;;;;;;iBCAlB,WAAW,YAAW,QAAQ,gBAAqB;;;;;;;;;iBAoBnD,iBACd;EAAQ,YAAY,eAAe;IAClC;;;;;;;;;iBCvBa,qBAAqB;;;;;;;;;;;cCKxB,YAAY;;;;iBCVT,UAAU;EAAQ;EAAc;IAAiB;;iBASjD,aAAa;EAAQ;EAAc;EAAc;IAAkB;;;;;;;;iBAenE,cAAc;EAAQ;EAAc;EAAc;IAAmB;;;;UC1BpE;EACf;;EAEA;EACA,SAAS;EACT;;;UAIe;EACf;EACA,UAAU;;EAEV;;;KAIU,kBACV,SAAS,kBACN,0BAA0B,QAAQ;;UAGtB;;WAEN;EACT,SAAS;;;;;;;;;UAUM;EACf,OAAO;IAAQ;IAAc;IAAe,QAAQ;MAAmB,QAAQ;;;;;;;;;;cC5BpE,gBAAgB,KAAK;;;;UCIjB,qBAAqB;;EAEpC,QAAQ,SAAS,QAAQ,iBAAiB,QAAQ;WACzC;;;UAIM,yBAAyB;;WAE/B,kBAAkB;;;;;;;;;iBAUb,sBAAsB;;;;;;;;;;;iBCpBtB,YAAY;;;;;;;;;;UCKX;EACf;EACA;;EAEA,UAAU,SAAS,QAAQ,mBAAmB,QAAQ;EACtD,aAAa;;EAEb,YAAY,SAAS,SAAS;;;;;;;;iBAShB,eAAe"}
|