@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.
Files changed (112) hide show
  1. package/Core/HyperCore.d.ts +206 -0
  2. package/Core/HyperCore.d.ts.map +1 -0
  3. package/Core/HyperCore.js +2 -0
  4. package/Core/HyperCore.js.map +7 -0
  5. package/README.md +259 -187
  6. package/defaultConfig.d.ts +12 -0
  7. package/defaultConfig.d.ts.map +1 -0
  8. package/defaultConfig.js +2 -0
  9. package/defaultConfig.js.map +7 -0
  10. package/index.d.ts +6 -0
  11. package/index.d.ts.map +1 -0
  12. package/index.js +2 -0
  13. package/index.js.map +7 -0
  14. package/package.json +40 -64
  15. package/protocols/manager.d.ts +31 -0
  16. package/protocols/manager.d.ts.map +1 -0
  17. package/protocols/manager.js +2 -0
  18. package/protocols/manager.js.map +7 -0
  19. package/protocols/rest/index.d.ts +9 -0
  20. package/protocols/rest/index.d.ts.map +1 -0
  21. package/protocols/rest/index.js +2 -0
  22. package/protocols/rest/index.js.map +7 -0
  23. package/protocols/rest/receiver.d.ts +31 -0
  24. package/protocols/rest/receiver.d.ts.map +1 -0
  25. package/protocols/rest/receiver.js +2 -0
  26. package/protocols/rest/receiver.js.map +7 -0
  27. package/protocols/rest/sender.d.ts +19 -0
  28. package/protocols/rest/sender.d.ts.map +1 -0
  29. package/protocols/rest/sender.js +2 -0
  30. package/protocols/rest/sender.js.map +7 -0
  31. package/protocols/rest/type.d.ts +71 -0
  32. package/protocols/rest/type.d.ts.map +1 -0
  33. package/protocols/rest/type.js +2 -0
  34. package/protocols/rest/type.js.map +7 -0
  35. package/rest.d.ts +2 -0
  36. package/rest.d.ts.map +1 -0
  37. package/rest.js +2 -0
  38. package/rest.js.map +7 -0
  39. package/transports/fetch.d.ts +24 -0
  40. package/transports/fetch.d.ts.map +1 -0
  41. package/transports/fetch.js +2 -0
  42. package/transports/fetch.js.map +7 -0
  43. package/transports/manager.d.ts +26 -0
  44. package/transports/manager.d.ts.map +1 -0
  45. package/transports/manager.js +2 -0
  46. package/transports/manager.js.map +7 -0
  47. package/utils/abort.d.ts +23 -0
  48. package/utils/abort.d.ts.map +1 -0
  49. package/utils/abort.js +2 -0
  50. package/utils/abort.js.map +7 -0
  51. package/{dist/utils → utils}/errors.d.ts +3 -3
  52. package/utils/errors.d.ts.map +1 -0
  53. package/utils/errors.js +2 -0
  54. package/utils/errors.js.map +7 -0
  55. package/dist/Core/HyperCore.d.ts +0 -171
  56. package/dist/Core/HyperCore.d.ts.map +0 -1
  57. package/dist/Core/HyperCore.js +0 -2
  58. package/dist/Core/HyperCore.js.map +0 -7
  59. package/dist/Core/RequestBuilder.d.ts +0 -8
  60. package/dist/Core/RequestBuilder.d.ts.map +0 -1
  61. package/dist/Core/RequestBuilder.js +0 -2
  62. package/dist/Core/RequestBuilder.js.map +0 -7
  63. package/dist/LICENSE +0 -21
  64. package/dist/README.md +0 -291
  65. package/dist/defaultConfig.d.ts +0 -7
  66. package/dist/defaultConfig.d.ts.map +0 -1
  67. package/dist/defaultConfig.js +0 -2
  68. package/dist/defaultConfig.js.map +0 -7
  69. package/dist/index.d.ts +0 -3
  70. package/dist/index.d.ts.map +0 -1
  71. package/dist/index.js +0 -2
  72. package/dist/index.js.map +0 -7
  73. package/dist/package.json +0 -50
  74. package/dist/transports/browser.d.ts +0 -37
  75. package/dist/transports/browser.d.ts.map +0 -1
  76. package/dist/transports/browser.js +0 -2
  77. package/dist/transports/browser.js.map +0 -7
  78. package/dist/transports/manager.d.ts +0 -89
  79. package/dist/transports/manager.d.ts.map +0 -1
  80. package/dist/transports/manager.js +0 -7
  81. package/dist/transports/manager.js.map +0 -7
  82. package/dist/transports/node.d.ts +0 -33
  83. package/dist/transports/node.d.ts.map +0 -1
  84. package/dist/transports/node.js +0 -2
  85. package/dist/transports/node.js.map +0 -7
  86. package/dist/utils/errors.d.ts.map +0 -1
  87. package/dist/utils/errors.js +0 -2
  88. package/dist/utils/errors.js.map +0 -7
  89. package/dist/utils/normalize.d.ts +0 -35
  90. package/dist/utils/normalize.d.ts.map +0 -1
  91. package/dist/utils/normalize.js +0 -2
  92. package/dist/utils/normalize.js.map +0 -7
  93. package/dist/utils/pipeline.d.ts +0 -63
  94. package/dist/utils/pipeline.d.ts.map +0 -1
  95. package/dist/utils/pipeline.js +0 -2
  96. package/dist/utils/pipeline.js.map +0 -7
  97. package/dist/utils/response.d.ts +0 -108
  98. package/dist/utils/response.d.ts.map +0 -1
  99. package/dist/utils/response.js +0 -2
  100. package/dist/utils/response.js.map +0 -7
  101. package/dist/utils/retryUtils.d.ts +0 -17
  102. package/dist/utils/retryUtils.d.ts.map +0 -1
  103. package/dist/utils/retryUtils.js +0 -2
  104. package/dist/utils/retryUtils.js.map +0 -7
  105. /package/{dist/Core → Core}/index.d.ts +0 -0
  106. /package/{dist/Core → Core}/index.d.ts.map +0 -0
  107. /package/{dist/Core → Core}/index.js +0 -0
  108. /package/{dist/Core → Core}/index.js.map +0 -0
  109. /package/{dist/utils → utils}/merge.d.ts +0 -0
  110. /package/{dist/utils → utils}/merge.d.ts.map +0 -0
  111. /package/{dist/utils → utils}/merge.js +0 -0
  112. /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
- > High-performance HTTP engine for Node.js and Bun.
3
+ > Protocol-agnostic execution core for client and server communication.
4
4
 
5
- **English** | [Русский](https://github.com/IT-IF-OR/hyperttp-core/tree/main/lang/ru)
5
+ **English** | [Русский](./lang/ru/README.md)
6
6
 
7
+ [![CI](https://github.com/IT-IF-OR/hyperttp-core/actions/workflows/ci.yml/badge.svg)](https://github.com/IT-IF-OR/hyperttp-core/actions/workflows/ci.yml)
7
8
  [![npm version](https://img.shields.io/npm/v/@hyperttp/core)](https://www.npmjs.com/package/@hyperttp/core)
8
9
  [![npm downloads](https://img.shields.io/npm/dm/@hyperttp/core)](https://www.npmjs.com/package/@hyperttp/core)
9
10
  [![bundle size](https://img.shields.io/bundlephobia/minzip/@hyperttp/core)](https://bundlephobia.com/package/@hyperttp/core)
10
11
  [![license](https://img.shields.io/npm/l/@hyperttp/core)](./LICENSE)
11
12
  [![typescript](https://img.shields.io/badge/TypeScript-strict-blue)](https://www.typescriptlang.org/)
12
13
 
13
- ---
14
+ ## Positioning
14
15
 
15
- ## What is @hyperttp/core?
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
- **@hyperttp/core** is a low-level, high-performance HTTP engine designed for building fast,
18
- extensible HTTP clients and SDKs.
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
- It provides:
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
- - ⚡ Optimized request execution pipeline
23
- - 🔀 Runtime-aware transport abstraction
24
- - 🔌 Plugin lifecycle hooks
25
- - 🛡️ Safe request/response handling
26
- - 📦 Zero runtime dependencies
27
-
28
- `@hyperttp/core` is the foundation that powers **hyperttp**,
29
- but it can also be used directly to build custom HTTP clients, SDKs, API wrappers and internal tooling.
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
- > 💡 Looking for a batteries-included client?
32
- >
33
- > Use **[`hyperttp`](https://www.npmjs.com/package/hyperttp)** — it ships with retries, caching,
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
- ## Why @hyperttp/core?
51
+ ## Core properties
39
52
 
40
- Unlike the native `fetch()`, HyperCore is designed as an extensible HTTP engine rather than just a request API.
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
- | Feature | fetch | @hyperttp/core |
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
- ## Features
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
- - ⚡ Optimized hot paths with minimal allocations
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
- ## Architecture
79
+ const core = new HyperCore();
72
80
 
73
- ```text
74
- hyperttp
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
- ## Installation
85
+ console.log(response.status);
86
+ console.log(response.data);
94
87
 
95
- ```bash
96
- npm install @hyperttp/core
88
+ await core.destroy();
97
89
  ```
98
90
 
99
- Recommended transports:
91
+ The same request can use the protocol-independent API:
100
92
 
101
- ```bash
102
- # Bun
103
- npm install @hyperttp/transport-bun
104
-
105
- # Node.js
106
- npm install @hyperttp/transport-undici
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
- ## Quick Start
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 http = new HyperCore({
117
- network: {
118
- baseURL: "https://api.example.com",
119
- headers: {
120
- "X-App-Version": "1.0.0",
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
- const response = await http.get("/users", {
126
- query: {
127
- page: 1,
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
- const users = await response.json();
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
- console.log(users);
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
- ## Error Handling
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
- ```ts
142
- import { HyperCore, HttpClientError, TimeoutError } from "@hyperttp/core";
150
+ If an optional protocol package is missing, resolution fails with an installation hint instead of
151
+ silently selecting another protocol.
143
152
 
144
- try {
145
- const res = await http.get("/users");
153
+ ### Protocol roles
146
154
 
147
- console.log(await res.json());
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
- if (HttpClientError.isHttpClientError(error)) {
154
- console.error(error.statusCode, error.message);
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
- throw error;
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
- ## Streaming
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
- const response = await http.stream("https://stream.example.com/audio");
175
+ declare module "@hyperttp/types" {
176
+ interface ProtocolInputMap {
177
+ "my-protocol": MyProtocolInput;
178
+ }
169
179
 
170
- const reader = response.body.getReader();
180
+ interface HyperProtocols {
181
+ "my-protocol": MyProtocolMethods;
182
+ }
183
+ }
184
+ ```
171
185
 
172
- while (true) {
173
- const { done, value } = await reader.read();
186
+ ## Transports
174
187
 
175
- if (done) break;
188
+ A transport describes its client capabilities and optional server capability:
176
189
 
177
- console.log(value.length);
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
- Discard a response body without buffering:
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
- await http.dump("https://api.example.com/ping");
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
- HyperCore exposes request lifecycle hooks that allow intercepting requests, responses and errors.
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
- http.use({
195
- name: "logger",
196
- priority: 10,
197
-
198
- onRequest(req) {
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
- onResponse(res, req) {
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
- onError(error, req) {
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
- ## Transports
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
- HyperCore automatically detects the current runtime, or you can provide your own transport.
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
- | Transport | Runtime |
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
- Example:
266
+ The REST package exposes client and server roles through `RestProtocol`.
229
267
 
230
268
  ```ts
231
- import { HyperCore } from "@hyperttp/core";
232
- import { UndiciTransport } from "@hyperttp/transport-undici";
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 http = new HyperCore({
235
- customTransport: new UndiciTransport(),
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
- ## Performance
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
- HyperCore is optimized for sustained high concurrency.
310
+ ## Error handling
244
311
 
245
- Recent stress testing:
312
+ ```ts
313
+ import { HyperClientError, TimeoutError } from "@hyperttp/core";
246
314
 
247
- - **200,000 requests**
248
- - **1000 concurrent connections**
249
- - **120 seconds**
250
- - **0 request errors**
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
- Optimizations include:
326
+ ## Scope
253
327
 
254
- - minimal allocations
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
- ## Ecosystem
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
- | Package | Description |
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
- bun install
280
-
281
- bun run lint
282
- bun run typecheck
283
- bun run test
284
- bun run build
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"}
@@ -0,0 +1,2 @@
1
+ "use strict";export const defaultCoreConfig={retry:{maxRetries:0,baseDelay:100,maxDelay:5e3,jitter:!0},verbose:!1},defaultHttpConfig={retry:{maxRetries:0,baseDelay:100,maxDelay:5e3,jitter:!0}};
2
+ //# sourceMappingURL=defaultConfig.js.map
@@ -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
+ }