@hyperttp/core 1.5.6 → 2.0.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/Core/HyperCore.d.ts +206 -0
- package/Core/HyperCore.d.ts.map +1 -0
- package/Core/HyperCore.js +2 -0
- package/Core/HyperCore.js.map +7 -0
- package/README.md +259 -187
- package/defaultConfig.d.ts +12 -0
- package/defaultConfig.d.ts.map +1 -0
- package/defaultConfig.js +2 -0
- package/defaultConfig.js.map +7 -0
- package/index.d.ts +6 -0
- package/index.d.ts.map +1 -0
- package/index.js +2 -0
- package/index.js.map +7 -0
- package/package.json +40 -64
- package/protocols/manager.d.ts +31 -0
- package/protocols/manager.d.ts.map +1 -0
- package/protocols/manager.js +2 -0
- package/protocols/manager.js.map +7 -0
- package/protocols/rest/index.d.ts +9 -0
- package/protocols/rest/index.d.ts.map +1 -0
- package/protocols/rest/index.js +2 -0
- package/protocols/rest/index.js.map +7 -0
- package/protocols/rest/receiver.d.ts +31 -0
- package/protocols/rest/receiver.d.ts.map +1 -0
- package/protocols/rest/receiver.js +2 -0
- package/protocols/rest/receiver.js.map +7 -0
- package/protocols/rest/sender.d.ts +19 -0
- package/protocols/rest/sender.d.ts.map +1 -0
- package/protocols/rest/sender.js +2 -0
- package/protocols/rest/sender.js.map +7 -0
- package/protocols/rest/type.d.ts +71 -0
- package/protocols/rest/type.d.ts.map +1 -0
- package/protocols/rest/type.js +2 -0
- package/protocols/rest/type.js.map +7 -0
- package/rest.d.ts +2 -0
- package/rest.d.ts.map +1 -0
- package/rest.js +2 -0
- package/rest.js.map +7 -0
- package/transports/fetch.d.ts +24 -0
- package/transports/fetch.d.ts.map +1 -0
- package/transports/fetch.js +2 -0
- package/transports/fetch.js.map +7 -0
- package/transports/manager.d.ts +26 -0
- package/transports/manager.d.ts.map +1 -0
- package/transports/manager.js +2 -0
- package/transports/manager.js.map +7 -0
- package/utils/abort.d.ts +23 -0
- package/utils/abort.d.ts.map +1 -0
- package/utils/abort.js +2 -0
- package/utils/abort.js.map +7 -0
- package/{dist/utils → utils}/errors.d.ts +3 -3
- package/utils/errors.d.ts.map +1 -0
- package/utils/errors.js +2 -0
- package/utils/errors.js.map +7 -0
- package/dist/Core/HyperCore.d.ts +0 -171
- package/dist/Core/HyperCore.d.ts.map +0 -1
- package/dist/Core/HyperCore.js +0 -2
- package/dist/Core/HyperCore.js.map +0 -7
- package/dist/Core/RequestBuilder.d.ts +0 -8
- package/dist/Core/RequestBuilder.d.ts.map +0 -1
- package/dist/Core/RequestBuilder.js +0 -2
- package/dist/Core/RequestBuilder.js.map +0 -7
- package/dist/LICENSE +0 -21
- package/dist/README.md +0 -291
- package/dist/defaultConfig.d.ts +0 -7
- package/dist/defaultConfig.d.ts.map +0 -1
- package/dist/defaultConfig.js +0 -2
- package/dist/defaultConfig.js.map +0 -7
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -7
- package/dist/package.json +0 -50
- package/dist/transports/browser.d.ts +0 -37
- package/dist/transports/browser.d.ts.map +0 -1
- package/dist/transports/browser.js +0 -2
- package/dist/transports/browser.js.map +0 -7
- package/dist/transports/manager.d.ts +0 -89
- package/dist/transports/manager.d.ts.map +0 -1
- package/dist/transports/manager.js +0 -7
- package/dist/transports/manager.js.map +0 -7
- package/dist/transports/node.d.ts +0 -33
- package/dist/transports/node.d.ts.map +0 -1
- package/dist/transports/node.js +0 -2
- package/dist/transports/node.js.map +0 -7
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/errors.js +0 -2
- package/dist/utils/errors.js.map +0 -7
- package/dist/utils/normalize.d.ts +0 -35
- package/dist/utils/normalize.d.ts.map +0 -1
- package/dist/utils/normalize.js +0 -2
- package/dist/utils/normalize.js.map +0 -7
- package/dist/utils/pipeline.d.ts +0 -63
- package/dist/utils/pipeline.d.ts.map +0 -1
- package/dist/utils/pipeline.js +0 -2
- package/dist/utils/pipeline.js.map +0 -7
- package/dist/utils/response.d.ts +0 -108
- package/dist/utils/response.d.ts.map +0 -1
- package/dist/utils/response.js +0 -2
- package/dist/utils/response.js.map +0 -7
- package/dist/utils/retryUtils.d.ts +0 -17
- package/dist/utils/retryUtils.d.ts.map +0 -1
- package/dist/utils/retryUtils.js +0 -2
- package/dist/utils/retryUtils.js.map +0 -7
- /package/{dist/Core → Core}/index.d.ts +0 -0
- /package/{dist/Core → Core}/index.d.ts.map +0 -0
- /package/{dist/Core → Core}/index.js +0 -0
- /package/{dist/Core → Core}/index.js.map +0 -0
- /package/{dist/utils → utils}/merge.d.ts +0 -0
- /package/{dist/utils → utils}/merge.d.ts.map +0 -0
- /package/{dist/utils → utils}/merge.js +0 -0
- /package/{dist/utils → utils}/merge.js.map +0 -0
package/README.md
CHANGED
|
@@ -1,290 +1,362 @@
|
|
|
1
|
-
# @hyperttp/core
|
|
1
|
+
# @hyperttp/core
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Protocol-agnostic execution core for client and server communication.
|
|
4
4
|
|
|
5
|
-
**English** | [Русский](
|
|
5
|
+
**English** | [Русский](./lang/ru/README.md)
|
|
6
6
|
|
|
7
|
+
[](https://github.com/IT-IF-OR/hyperttp-core/actions/workflows/ci.yml)
|
|
7
8
|
[](https://www.npmjs.com/package/@hyperttp/core)
|
|
8
9
|
[](https://www.npmjs.com/package/@hyperttp/core)
|
|
9
10
|
[](https://bundlephobia.com/package/@hyperttp/core)
|
|
10
11
|
[](./LICENSE)
|
|
11
12
|
[](https://www.typescriptlang.org/)
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
## Positioning
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
`@hyperttp/core` is a small orchestration kernel, not another wrapper around `fetch` and not a
|
|
17
|
+
batteries-included HTTP framework. It connects three independent extension points:
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
- **Protocols** define communication semantics. A protocol can send through a `HyperSender`,
|
|
20
|
+
receive through a `HyperReceiver`, or implement both roles as a `HyperProtocol`.
|
|
21
|
+
- **Transports** own physical I/O. The current transport contract executes outgoing requests and can
|
|
22
|
+
additionally listen for incoming requests.
|
|
23
|
+
- **Plugins** add client request policy and cross-cutting behavior without expanding the core.
|
|
19
24
|
|
|
20
|
-
|
|
25
|
+
The core owns dispatch, lifecycle, plugin execution and resource coordination. REST is included as
|
|
26
|
+
the baseline protocol; additional protocols, optimized transports and higher-level behavior live in
|
|
27
|
+
separate packages.
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
```text
|
|
30
|
+
Application
|
|
31
|
+
│
|
|
32
|
+
├── Plugins: retry, cache, auth, tracing, metrics, logging, policy
|
|
33
|
+
│
|
|
34
|
+
HyperCore
|
|
35
|
+
│
|
|
36
|
+
├── Protocol: prepare → send → parse
|
|
37
|
+
│ receive → handle → respond
|
|
38
|
+
│
|
|
39
|
+
└── Transport: execute (client) / listen (server)
|
|
40
|
+
Node.js / Bun / Deno / Browser / custom runtime
|
|
41
|
+
```
|
|
30
42
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
> parsing, rate limiting and other plugins already configured.
|
|
43
|
+
This boundary is intentional. New client-side retries, caches, authentication strategies,
|
|
44
|
+
observability tools and other request policies should be plugins. New wire semantics should be
|
|
45
|
+
protocol packages. New I/O implementations should be transport packages.
|
|
35
46
|
|
|
36
|
-
|
|
47
|
+
> Looking for a preconfigured HTTP client? Use
|
|
48
|
+
> [`hyperttp`](https://www.npmjs.com/package/hyperttp), which composes the core with application-level
|
|
49
|
+
> plugins and defaults.
|
|
37
50
|
|
|
38
|
-
##
|
|
51
|
+
## Core properties
|
|
39
52
|
|
|
40
|
-
|
|
53
|
+
- Client and server orchestration.
|
|
54
|
+
- Protocol-independent request envelope and universal response shape.
|
|
55
|
+
- Client lifecycle: `prepare → send → parse`.
|
|
56
|
+
- Server lifecycle: `receive → handle → respond`.
|
|
57
|
+
- Per-protocol transport resolution and coordinated transport ownership.
|
|
58
|
+
- Blocking and background client plugin hooks.
|
|
59
|
+
- Runtime-aware transport selection with a browser-safe fetch fallback.
|
|
60
|
+
- Strict TypeScript contracts and module augmentation for typed protocol namespaces.
|
|
61
|
+
- No bundled runtime dependencies.
|
|
41
62
|
|
|
42
|
-
|
|
43
|
-
| ---------------------- | :---: | :------------: |
|
|
44
|
-
| Transport abstraction | ❌ | ✅ |
|
|
45
|
-
| Plugin pipeline | ❌ | ✅ |
|
|
46
|
-
| Request/Response hooks | ❌ | ✅ |
|
|
47
|
-
| Custom transports | ❌ | ✅ |
|
|
48
|
-
| Built for SDKs | ⚠️ | ✅ |
|
|
49
|
-
| Safe response cleanup | ❌ | ✅ |
|
|
50
|
-
| Runtime auto-detection | ❌ | ✅ |
|
|
63
|
+
## Installation
|
|
51
64
|
|
|
52
|
-
|
|
65
|
+
```bash
|
|
66
|
+
npm install @hyperttp/core @hyperttp/types
|
|
67
|
+
```
|
|
53
68
|
|
|
54
|
-
|
|
69
|
+
Compatible optimized transports can be installed separately. Ensure the selected transport release
|
|
70
|
+
declares compatibility with `@hyperttp/types@^0.3.0`; older transport releases target the v1 type
|
|
71
|
+
contracts and cannot be installed alongside core 2.0. Without an optional transport package, the
|
|
72
|
+
core uses its built-in `FetchTransport` fallback.
|
|
55
73
|
|
|
56
|
-
|
|
57
|
-
- 🚀 Fast manual query string serialization
|
|
58
|
-
- 🔀 Automatic runtime transport selection
|
|
59
|
-
- 🔌 Extensible plugin system
|
|
60
|
-
- 🧠 Request/response lifecycle hooks
|
|
61
|
-
- 🛡️ Protection against Prototype Pollution
|
|
62
|
-
- 🛡️ CRLF header validation
|
|
63
|
-
- 🛡️ Safe `ArrayBuffer` handling
|
|
64
|
-
- 📦 Zero runtime dependencies
|
|
65
|
-
- 🌊 Native stream support
|
|
66
|
-
- 🧹 Automatic resource cleanup
|
|
67
|
-
- 📈 Designed for high concurrency
|
|
74
|
+
## Client quick start
|
|
68
75
|
|
|
69
|
-
|
|
76
|
+
```ts
|
|
77
|
+
import { HyperCore } from "@hyperttp/core";
|
|
70
78
|
|
|
71
|
-
|
|
79
|
+
const core = new HyperCore();
|
|
72
80
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
▼
|
|
77
|
-
@hyperttp/core
|
|
78
|
-
│
|
|
79
|
-
┌───────────────┴───────────────┐
|
|
80
|
-
│ │
|
|
81
|
-
▼ ▼
|
|
82
|
-
Transport Layer Plugin Pipeline
|
|
83
|
-
│ │
|
|
84
|
-
├── BunTransport │
|
|
85
|
-
├── UndiciTransport ├── Retry
|
|
86
|
-
├── NodeTransport ├── Cache
|
|
87
|
-
├── BrowserTransport ├── Parser
|
|
88
|
-
└── Custom Transport └── Пользовательские плагины
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
---
|
|
81
|
+
const response = await core.rest.get("https://example.com/users", {
|
|
82
|
+
query: { page: 1 },
|
|
83
|
+
});
|
|
92
84
|
|
|
93
|
-
|
|
85
|
+
console.log(response.status);
|
|
86
|
+
console.log(response.data);
|
|
94
87
|
|
|
95
|
-
|
|
96
|
-
npm install @hyperttp/core
|
|
88
|
+
await core.destroy();
|
|
97
89
|
```
|
|
98
90
|
|
|
99
|
-
|
|
91
|
+
The same request can use the protocol-independent API:
|
|
100
92
|
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
93
|
+
```ts
|
|
94
|
+
const response = await core.send({
|
|
95
|
+
protocol: "rest",
|
|
96
|
+
input: {
|
|
97
|
+
method: "GET",
|
|
98
|
+
url: "https://example.com/users",
|
|
99
|
+
query: { page: 1 },
|
|
100
|
+
},
|
|
101
|
+
});
|
|
107
102
|
```
|
|
108
103
|
|
|
109
|
-
|
|
104
|
+
## Server quick start
|
|
110
105
|
|
|
111
|
-
|
|
106
|
+
A transport may also expose `listen()`. `HyperCore` connects it to the receiver side of the selected
|
|
107
|
+
protocol:
|
|
112
108
|
|
|
113
109
|
```ts
|
|
114
110
|
import { HyperCore } from "@hyperttp/core";
|
|
115
111
|
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
112
|
+
const core = new HyperCore();
|
|
113
|
+
|
|
114
|
+
const server = await core.listen({
|
|
115
|
+
protocol: "rest",
|
|
116
|
+
host: "127.0.0.1",
|
|
117
|
+
port: 3000,
|
|
118
|
+
handler(request) {
|
|
119
|
+
return {
|
|
120
|
+
status: 200,
|
|
121
|
+
body: {
|
|
122
|
+
method: request.method,
|
|
123
|
+
path: request.path,
|
|
124
|
+
},
|
|
125
|
+
};
|
|
122
126
|
},
|
|
123
127
|
});
|
|
124
128
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
limit: 20,
|
|
129
|
-
},
|
|
130
|
-
});
|
|
129
|
+
// Closes active servers and releases every transport owned by this core.
|
|
130
|
+
await core.destroy();
|
|
131
|
+
```
|
|
131
132
|
|
|
132
|
-
|
|
133
|
+
Protocols can be client-only, server-only or expose both roles. The current transport contract always
|
|
134
|
+
provides client `execute()` and can additionally provide server `listen()`.
|
|
133
135
|
|
|
134
|
-
|
|
135
|
-
```
|
|
136
|
+
## Protocols
|
|
136
137
|
|
|
137
|
-
|
|
138
|
+
REST is the only protocol implemented inside the core. External protocol modules are loaded lazily:
|
|
138
139
|
|
|
139
|
-
|
|
140
|
+
| Protocol | Package | Namespace |
|
|
141
|
+
| --------- | ------------------------------ | ---------------------------- |
|
|
142
|
+
| REST | built in | `core.rest` |
|
|
143
|
+
| GraphQL | `@hyperttp/protocol-graphql` | `core.graphql` |
|
|
144
|
+
| gRPC | `@hyperttp/protocol-grpc` | `core.grpc` |
|
|
145
|
+
| tRPC | `@hyperttp/protocol-trpc` | `core.trpc` |
|
|
146
|
+
| WebSocket | `@hyperttp/protocol-websocket` | `core.ws` / `core.websocket` |
|
|
147
|
+
| SSE | `@hyperttp/protocol-sse` | `core.sse` |
|
|
148
|
+
| MQTT | `@hyperttp/protocol-mqtt` | `core.mqtt` |
|
|
140
149
|
|
|
141
|
-
|
|
142
|
-
|
|
150
|
+
If an optional protocol package is missing, resolution fails with an installation hint instead of
|
|
151
|
+
silently selecting another protocol.
|
|
143
152
|
|
|
144
|
-
|
|
145
|
-
const res = await http.get("/users");
|
|
153
|
+
### Protocol roles
|
|
146
154
|
|
|
147
|
-
|
|
148
|
-
} catch (error) {
|
|
149
|
-
if (TimeoutError.isTimeoutError(error)) {
|
|
150
|
-
console.error("Request timed out.");
|
|
151
|
-
}
|
|
155
|
+
A unified protocol module can expose either or both roles:
|
|
152
156
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
157
|
+
```ts
|
|
158
|
+
const protocol = {
|
|
159
|
+
protocol: "my-protocol",
|
|
160
|
+
sender: mySender, // optional client role
|
|
161
|
+
receiver: myReceiver, // optional server role
|
|
162
|
+
};
|
|
156
163
|
|
|
157
|
-
|
|
158
|
-
}
|
|
164
|
+
core.registerProtocol(protocol);
|
|
159
165
|
```
|
|
160
166
|
|
|
161
|
-
|
|
167
|
+
A sender translates protocol input into a transport request and parses the transport response. A
|
|
168
|
+
receiver translates an incoming transport request into protocol input and serializes the application
|
|
169
|
+
response.
|
|
162
170
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
Read a streaming response:
|
|
171
|
+
Protocol packages can extend typed inputs and namespaces through `@hyperttp/types` module
|
|
172
|
+
augmentation:
|
|
166
173
|
|
|
167
174
|
```ts
|
|
168
|
-
|
|
175
|
+
declare module "@hyperttp/types" {
|
|
176
|
+
interface ProtocolInputMap {
|
|
177
|
+
"my-protocol": MyProtocolInput;
|
|
178
|
+
}
|
|
169
179
|
|
|
170
|
-
|
|
180
|
+
interface HyperProtocols {
|
|
181
|
+
"my-protocol": MyProtocolMethods;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
171
185
|
|
|
172
|
-
|
|
173
|
-
const { done, value } = await reader.read();
|
|
186
|
+
## Transports
|
|
174
187
|
|
|
175
|
-
|
|
188
|
+
A transport describes its client capabilities and optional server capability:
|
|
176
189
|
|
|
177
|
-
|
|
190
|
+
```ts
|
|
191
|
+
interface HyperTransport {
|
|
192
|
+
execute(request: TransportRequest): Promise<TransportResponse>;
|
|
193
|
+
listen?(options: TransportListenOptions): Promise<TransportServer>;
|
|
194
|
+
close?(): Promise<void> | void;
|
|
195
|
+
destroy?(): Promise<void> | void;
|
|
178
196
|
}
|
|
179
197
|
```
|
|
180
198
|
|
|
181
|
-
|
|
199
|
+
- `execute()` is the required client role.
|
|
200
|
+
- `listen()` is the optional server role.
|
|
201
|
+
- `protocols` or `supports()` declares protocol capabilities.
|
|
202
|
+
- The core resolves and retains transports per protocol and closes a shared instance only after its
|
|
203
|
+
last owner releases it.
|
|
204
|
+
|
|
205
|
+
Runtime selection:
|
|
206
|
+
|
|
207
|
+
| Runtime | Preferred package | Fallback |
|
|
208
|
+
| -------------- | ---------------------------- | ------------------------- |
|
|
209
|
+
| Node.js | `@hyperttp/transport-undici` | built-in `FetchTransport` |
|
|
210
|
+
| Bun | `@hyperttp/transport-bun` | built-in `FetchTransport` |
|
|
211
|
+
| Deno | `@hyperttp/transport-deno` | built-in `FetchTransport` |
|
|
212
|
+
| Browser / edge | custom transport | built-in `FetchTransport` |
|
|
213
|
+
|
|
214
|
+
A transport can also be supplied explicitly:
|
|
182
215
|
|
|
183
216
|
```ts
|
|
184
|
-
|
|
185
|
-
|
|
217
|
+
import { HyperCore } from "@hyperttp/core";
|
|
218
|
+
import { UndiciTransport } from "@hyperttp/transport-undici";
|
|
186
219
|
|
|
187
|
-
|
|
220
|
+
const core = new HyperCore({
|
|
221
|
+
customTransport: new UndiciTransport(),
|
|
222
|
+
});
|
|
223
|
+
```
|
|
188
224
|
|
|
189
225
|
## Plugins
|
|
190
226
|
|
|
191
|
-
|
|
227
|
+
Plugins are the intended extension mechanism for client request behavior that does not belong to
|
|
228
|
+
protocol semantics or physical I/O. The current hooks run in the client `send()` lifecycle:
|
|
192
229
|
|
|
193
230
|
```ts
|
|
194
|
-
|
|
195
|
-
name: "logger",
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
req.meta.start = performance.now();
|
|
231
|
+
core.use({
|
|
232
|
+
name: "request-logger",
|
|
233
|
+
phase: "DATA",
|
|
234
|
+
onRequest(request) {
|
|
235
|
+
console.log("request", request.protocol);
|
|
200
236
|
},
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const elapsed = performance.now() - (req.meta.start as number);
|
|
204
|
-
|
|
205
|
-
console.log(`${req.method} ${req.url} -> ${res.status} (${elapsed.toFixed(2)} ms)`);
|
|
237
|
+
onResponse(response) {
|
|
238
|
+
console.log("response", response.status);
|
|
206
239
|
},
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
console.error(`${req.url}: ${error.message}`);
|
|
240
|
+
onError(error) {
|
|
241
|
+
console.error(error);
|
|
210
242
|
},
|
|
211
243
|
});
|
|
212
244
|
```
|
|
213
245
|
|
|
214
|
-
|
|
246
|
+
Hooks:
|
|
215
247
|
|
|
216
|
-
|
|
248
|
+
- `onRequest` can modify a request or return an early response.
|
|
249
|
+
- `onResponse` can inspect or replace a response.
|
|
250
|
+
- `onError` can recover by returning a response.
|
|
251
|
+
- `mode: "background"` detaches response-side work from the blocking path.
|
|
252
|
+
- `enabled(config)` controls registration.
|
|
253
|
+
- `setup(context)` initializes a plugin.
|
|
254
|
+
|
|
255
|
+
Examples of functionality that belongs in plugins:
|
|
217
256
|
|
|
218
|
-
|
|
257
|
+
- retries and circuit breakers;
|
|
258
|
+
- caching and request deduplication;
|
|
259
|
+
- authentication and request signing;
|
|
260
|
+
- tracing, metrics and structured logging;
|
|
261
|
+
- rate limiting, concurrency control and scheduling;
|
|
262
|
+
- schema validation and application-specific policies.
|
|
219
263
|
|
|
220
|
-
|
|
221
|
-
| ---------------- | ------------- |
|
|
222
|
-
| BunTransport | Bun |
|
|
223
|
-
| UndiciTransport | Node.js |
|
|
224
|
-
| NodeTransport | Bun / Node.js |
|
|
225
|
-
| BrowserTransport | Browser |
|
|
226
|
-
| Custom Transport | Any |
|
|
264
|
+
## Built-in REST protocol
|
|
227
265
|
|
|
228
|
-
|
|
266
|
+
The REST package exposes client and server roles through `RestProtocol`.
|
|
229
267
|
|
|
230
268
|
```ts
|
|
231
|
-
|
|
232
|
-
|
|
269
|
+
const getResponse = await core.rest.get("/users", {
|
|
270
|
+
query: { page: 1, tag: ["a", "b"] },
|
|
271
|
+
headers: { accept: "application/json" },
|
|
272
|
+
timeout: 5_000,
|
|
273
|
+
});
|
|
233
274
|
|
|
234
|
-
const
|
|
235
|
-
|
|
275
|
+
const postResponse = await core.rest.post("/users", {
|
|
276
|
+
name: "Ada",
|
|
236
277
|
});
|
|
278
|
+
|
|
279
|
+
const streamResponse = await core.rest.stream("/events");
|
|
237
280
|
```
|
|
238
281
|
|
|
239
|
-
|
|
282
|
+
REST behavior includes:
|
|
283
|
+
|
|
284
|
+
- query serialization with repeated array parameters;
|
|
285
|
+
- header normalization;
|
|
286
|
+
- JSON serialization for plain object and array request bodies;
|
|
287
|
+
- JSON, text and binary response handling;
|
|
288
|
+
- timeout and user abort propagation;
|
|
289
|
+
- unbuffered stream mode;
|
|
290
|
+
- request decoding and response serialization for the server role.
|
|
291
|
+
|
|
292
|
+
REST-specific public types are available from `@hyperttp/core/rest`.
|
|
293
|
+
|
|
294
|
+
## Lifecycle
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
const child = core.extend({ verbose: true }); // shares resolved transport leases
|
|
298
|
+
const isolated = core.create({}); // independent transport lifecycle
|
|
299
|
+
|
|
300
|
+
await child.destroy();
|
|
301
|
+
await isolated.destroy();
|
|
302
|
+
await core.destroy();
|
|
303
|
+
```
|
|
240
304
|
|
|
241
|
-
|
|
305
|
+
- `extend()` creates a related core and shares existing transport ownership.
|
|
306
|
+
- `create()` creates an independent core and does not inherit `customTransport` by default.
|
|
307
|
+
- `destroy()` is idempotent, closes tracked servers and releases transports.
|
|
308
|
+
- `destroy(false)` requests forced shutdown where the transport supports it.
|
|
242
309
|
|
|
243
|
-
|
|
310
|
+
## Error handling
|
|
244
311
|
|
|
245
|
-
|
|
312
|
+
```ts
|
|
313
|
+
import { HyperClientError, TimeoutError } from "@hyperttp/core";
|
|
246
314
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
315
|
+
try {
|
|
316
|
+
await core.rest.get("/slow", { timeout: 1_000 });
|
|
317
|
+
} catch (error) {
|
|
318
|
+
if (TimeoutError.isTimeoutError(error)) {
|
|
319
|
+
console.error("Request timed out");
|
|
320
|
+
} else if (HyperClientError.isHyperClientError(error)) {
|
|
321
|
+
console.error(error.code, error.message);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
```
|
|
251
325
|
|
|
252
|
-
|
|
326
|
+
## Scope
|
|
253
327
|
|
|
254
|
-
|
|
255
|
-
- object reuse
|
|
256
|
-
- optimized semaphore
|
|
257
|
-
- manual query serialization
|
|
258
|
-
- efficient header normalization
|
|
259
|
-
- zero-dependency core
|
|
328
|
+
The stable core is intentionally limited to:
|
|
260
329
|
|
|
261
|
-
|
|
330
|
+
1. protocol registration and dispatch;
|
|
331
|
+
2. transport resolution, sharing and shutdown;
|
|
332
|
+
3. client and server lifecycle orchestration;
|
|
333
|
+
4. plugin execution;
|
|
334
|
+
5. the baseline REST protocol and universal error contracts.
|
|
262
335
|
|
|
263
|
-
|
|
336
|
+
Feature growth should happen through plugins, protocol packages and transport packages. Keeping this
|
|
337
|
+
boundary small makes runtime behavior predictable and allows the core API to stabilize independently
|
|
338
|
+
from the ecosystem around it.
|
|
264
339
|
|
|
265
|
-
|
|
266
|
-
| ---------------------------- | ------------------------ |
|
|
267
|
-
| `hyperttp` | Ready-to-use HTTP client |
|
|
268
|
-
| `@hyperttp/core` | HTTP engine |
|
|
269
|
-
| `@hyperttp/parser` | Response parsing |
|
|
270
|
-
| `@hyperttp/cache` | Cache utilities |
|
|
271
|
-
| `@hyperttp/transport-undici` | Undici transport |
|
|
272
|
-
| `@hyperttp/transport-bun` | Bun transport |
|
|
340
|
+
## Runtime support
|
|
273
341
|
|
|
274
|
-
|
|
342
|
+
- Node.js 20 and newer;
|
|
343
|
+
- current stable Bun;
|
|
344
|
+
- current stable Deno;
|
|
345
|
+
- modern browsers and edge runtimes with Fetch and Web Streams.
|
|
275
346
|
|
|
276
347
|
## Development
|
|
277
348
|
|
|
278
349
|
```bash
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
350
|
+
npm install
|
|
351
|
+
npm run format:check
|
|
352
|
+
npm run lint
|
|
353
|
+
npm run typecheck
|
|
354
|
+
npm run test
|
|
355
|
+
npm run build
|
|
285
356
|
```
|
|
286
357
|
|
|
287
|
-
|
|
358
|
+
The required order is `lint → typecheck → test → build`. CI also verifies browser bundling, runtime
|
|
359
|
+
smoke tests and installation of the generated npm tarball.
|
|
288
360
|
|
|
289
361
|
## License
|
|
290
362
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { HyperClientOptions } from "@hyperttp/types";
|
|
2
|
+
/**
|
|
3
|
+
* @ru Конфигурация по умолчанию универсального ядра.
|
|
4
|
+
* @en Default configuration for the universal core.
|
|
5
|
+
*/
|
|
6
|
+
export declare const defaultCoreConfig: HyperClientOptions;
|
|
7
|
+
/**
|
|
8
|
+
* @ru HTTP-конфигурация по умолчанию для HttpSender.
|
|
9
|
+
* @en Default HTTP configuration for the HttpSender.
|
|
10
|
+
*/
|
|
11
|
+
export declare const defaultHttpConfig: HyperClientOptions;
|
|
12
|
+
//# sourceMappingURL=defaultConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaultConfig.d.ts","sourceRoot":"","sources":["../src/defaultConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,kBAQ/B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,kBAO/B,CAAC"}
|
package/defaultConfig.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/defaultConfig.ts"],
|
|
4
|
+
"sourcesContent": ["import type { HyperClientOptions } from \"@hyperttp/types\";\n\n/**\n * @ru Конфигурация по умолчанию универсального ядра.\n * @en Default configuration for the universal core.\n */\nexport const defaultCoreConfig: HyperClientOptions = {\n retry: {\n maxRetries: 0,\n baseDelay: 100,\n maxDelay: 5000,\n jitter: true,\n },\n verbose: false,\n};\n\n/**\n * @ru HTTP-конфигурация по умолчанию для HttpSender.\n * @en Default HTTP configuration for the HttpSender.\n */\nexport const defaultHttpConfig: HyperClientOptions = {\n retry: {\n maxRetries: 0,\n baseDelay: 100,\n maxDelay: 5000,\n jitter: true,\n },\n};\n"],
|
|
5
|
+
"mappings": "aAMO,aAAM,kBAAwC,CACnD,MAAO,CACL,WAAY,EACZ,UAAW,IACX,SAAU,IACV,OAAQ,IAEV,QAAS,IAOE,kBAAwC,CACnD,MAAO,CACL,WAAY,EACZ,UAAW,IACX,SAAU,IACV,OAAQ",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { HyperCore } from "./Core/index.js";
|
|
2
|
+
export { HyperClientError, TimeoutError } from "./utils/errors.js";
|
|
3
|
+
export { deepMerge } from "./utils/merge.js";
|
|
4
|
+
export { RestProtocol, RestReceiver, RestSender } from "./protocols/rest/index.js";
|
|
5
|
+
export { KNOWN_PROTOCOLS, resetCachedProtocols, resolveProtocol, resolveReceiver, resolveSender, } from "./protocols/manager.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
package/index.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACnF,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,aAAa,GACd,MAAM,wBAAwB,CAAC"}
|
package/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";export{HyperCore}from"./Core/index.js";export{HyperClientError,TimeoutError}from"./utils/errors.js";export{deepMerge}from"./utils/merge.js";export{RestProtocol,RestReceiver,RestSender}from"./protocols/rest/index.js";export{KNOWN_PROTOCOLS,resetCachedProtocols,resolveProtocol,resolveReceiver,resolveSender}from"./protocols/manager.js";
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
package/index.js.map
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["export { HyperCore } from \"./Core/index.js\";\nexport { HyperClientError, TimeoutError } from \"./utils/errors.js\";\nexport { deepMerge } from \"./utils/merge.js\";\nexport { RestProtocol, RestReceiver, RestSender } from \"./protocols/rest/index.js\";\nexport {\n KNOWN_PROTOCOLS,\n resetCachedProtocols,\n resolveProtocol,\n resolveReceiver,\n resolveSender,\n} from \"./protocols/manager.js\";\n"],
|
|
5
|
+
"mappings": "aAAA,OAAS,cAAiB,kBAC1B,OAAS,iBAAkB,iBAAoB,oBAC/C,OAAS,cAAiB,mBAC1B,OAAS,aAAc,aAAc,eAAkB,4BACvD,OACE,gBACA,qBACA,gBACA,gBACA,kBACK",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|