@hyperttp/core 1.5.6 → 2.0.1
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 +208 -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 +37 -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 +36 -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 +31 -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 +111 -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 +35 -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 +39 -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/utils/errors.d.ts +46 -0
- 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 +0 -38
- 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
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/Core/RequestBuilder.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n HttpClientOptions,\n InternalRequest,\n RequestInterface,\n RequestBodyData,\n Method,\n ResponseType,\n} from \"@hyperttp/types\";\nimport { CacheManager } from \"hcacher\";\nimport { normalizeBody, normalizeUrl } from \"../utils/normalize.js\";\nimport { mergeHeadersFast } from \"../utils/response.js\";\n\n/**\n * @ru Создаёт AbortSignal с тайм-аутом и привязкой к пользовательскому сигналу отмены.\n * @en Creates an AbortSignal with timeout and user abort signal binding.\n * @param userSignal - Optional external abort signal.\n * @param timeoutMs - Timeout in milliseconds.\n * @param meta - Metadata object receiving cleanup function.\n * @returns AbortSignal bound to the timeout and user signal.\n */\nfunction createTimeoutSignal(\n userSignal: AbortSignal | undefined,\n timeoutMs: number,\n meta: any,\n): AbortSignal {\n const controller = new AbortController();\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n\n if (userSignal) {\n userSignal.removeEventListener(\"abort\", onUserAbort);\n }\n clearTimeout(timeoutId);\n };\n\n const timeoutId = setTimeout(() => {\n (controller.signal as any).isTimeout = true;\n controller.abort(new DOMException(\"Timeout\", \"TimeoutError\"));\n cleanup();\n }, timeoutMs);\n\n const onUserAbort = () => {\n controller.abort(userSignal?.reason);\n cleanup();\n };\n\n if (userSignal) {\n if (userSignal.aborted) {\n onUserAbort();\n } else {\n userSignal.addEventListener(\"abort\", onUserAbort);\n }\n }\n\n meta.cleanupSignal = cleanup;\n\n return controller.signal;\n}\n\n/**\n * @ru Применяет тайм-аут к сигналу отмены.\n * @en Applies a timeout to the abort signal.\n * @param signal - Optional external abort signal.\n * @param timeout - Timeout in milliseconds (skip if null/<=0).\n * @param meta - Metadata object receiving cleanup function.\n * @returns New abort signal with timeout, or the original signal.\n */\nfunction applyTimeout(\n signal: AbortSignal | undefined,\n timeout: number | undefined,\n meta: any,\n): AbortSignal | undefined {\n if (timeout == null || timeout <= 0) return signal;\n return createTimeoutSignal(signal, timeout, meta);\n}\n\nexport class RequestBuilder {\n private readonly urlCache = new CacheManager<string>({ maxSize: 512, ttl: 60_000 });\n\n build(\n method: Method,\n req: RequestInterface | string,\n body: RequestBodyData | undefined,\n signal: AbortSignal | undefined,\n responseType: \"stream\" | undefined,\n defaultHeaders: Record<string, string | string[]>,\n config: HttpClientOptions,\n pooled?: InternalRequest,\n ): InternalRequest {\n const internalReq = pooled ?? {\n method: \"GET\" as Method,\n url: \"\",\n headers: defaultHeaders,\n body: undefined,\n signal: undefined,\n meta: {\n responseType: undefined as ResponseType | undefined,\n timings: {\n networkMs: undefined as number | undefined,\n },\n },\n stealth: undefined,\n };\n\n const metaObj = internalReq.meta as {\n responseType: ResponseType | undefined;\n timings: {\n networkMs: number | undefined;\n };\n cleanupSignal?: () => void;\n };\n\n if (typeof req === \"string\") {\n internalReq.method = method;\n internalReq.url = this.resolveUrl(req, config.baseURL);\n\n if (body !== undefined) {\n internalReq.headers = Object.assign({}, defaultHeaders);\n } else {\n internalReq.headers = defaultHeaders;\n }\n\n internalReq.body = body !== undefined ? normalizeBody(method, body) : undefined;\n internalReq.signal = applyTimeout(signal, config.network?.timeout, metaObj);\n metaObj.responseType = responseType;\n internalReq.stealth = config.network?.stealth;\n return internalReq;\n }\n\n const rawUrl = normalizeUrl(req);\n if (!rawUrl) throw new Error(`[HyperCore] URL is undefined for ${method}`);\n\n let finalUrl: string;\n\n if (req.query) {\n const cacheKey = rawUrl + \"_base\";\n let baseUrl = this.urlCache.get(cacheKey);\n\n if (!baseUrl) {\n baseUrl = config.baseURL ? new URL(rawUrl, config.baseURL).href : new URL(rawUrl).href;\n this.urlCache.set(cacheKey, baseUrl);\n }\n\n finalUrl = this.appendQueryString(baseUrl, req.query);\n } else {\n let cachedUrl = this.urlCache.get(rawUrl);\n if (!cachedUrl) {\n cachedUrl = config.baseURL ? new URL(rawUrl, config.baseURL).href : new URL(rawUrl).href;\n this.urlCache.set(rawUrl, cachedUrl);\n }\n finalUrl = cachedUrl;\n }\n\n internalReq.method = method;\n internalReq.url = finalUrl;\n\n const finalBody = req.body ?? body;\n\n if (req.headers || finalBody !== undefined) {\n const targetHeaders = Object.assign({}, defaultHeaders);\n internalReq.headers = req.headers\n ? mergeHeadersFast(targetHeaders, req.headers)\n : targetHeaders;\n } else {\n internalReq.headers = defaultHeaders;\n }\n\n internalReq.body = normalizeBody(method, finalBody);\n internalReq.signal = applyTimeout(req.signal ?? signal, config.network?.timeout, metaObj);\n\n metaObj.responseType =\n responseType ?? (req.meta as { responseType?: ResponseType })?.responseType;\n\n if (req.stealth) {\n if (config.network?.stealth) {\n const nextStealth = Object.assign({}, config.network.stealth, req.stealth);\n internalReq.stealth = nextStealth;\n } else {\n internalReq.stealth = req.stealth;\n }\n } else {\n internalReq.stealth = config.network?.stealth;\n }\n\n return internalReq;\n }\n\n public resolveUrl(url: string, baseURL?: string): string {\n if (!url) throw new Error(\"[HyperCore] URL is undefined\");\n\n let finalUrl = this.urlCache.get(url);\n if (finalUrl) return finalUrl;\n\n const isAbsolute = url.startsWith(\"http://\") || url.startsWith(\"https://\");\n if (isAbsolute && !url.includes(\"?\")) {\n finalUrl = url;\n } else {\n finalUrl = baseURL ? new URL(url, baseURL).href : new URL(url).href;\n }\n\n this.urlCache.set(url, finalUrl);\n return finalUrl;\n }\n\n private appendQueryString(baseUrl: string, query: Record<string, unknown>): string {\n let qs = \"\";\n for (const k in query) {\n if (!Object.prototype.hasOwnProperty.call(query, k)) continue;\n const v = query[k];\n if (v == null) continue;\n if (Array.isArray(v)) {\n for (let j = 0; j < v.length; j++) {\n if (qs) qs += \"&\";\n qs += encodeURIComponent(k) + \"=\" + encodeURIComponent(String(v[j]));\n }\n } else {\n if (qs) qs += \"&\";\n qs += encodeURIComponent(k) + \"=\" + encodeURIComponent(String(v));\n }\n }\n if (!qs) return baseUrl;\n return baseUrl + (baseUrl.includes(\"?\") ? \"&\" : \"?\") + qs;\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["CacheManager", "normalizeBody", "normalizeUrl", "mergeHeadersFast", "createTimeoutSignal", "userSignal", "timeoutMs", "meta", "controller", "cleaned", "cleanup", "onUserAbort", "timeoutId", "applyTimeout", "signal", "timeout", "method", "req", "body", "responseType", "defaultHeaders", "config", "pooled", "internalReq", "metaObj", "rawUrl", "finalUrl", "cacheKey", "baseUrl", "cachedUrl", "finalBody", "targetHeaders", "nextStealth", "url", "baseURL", "query", "qs", "k", "v", "j"]
|
|
7
|
-
}
|
package/dist/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 IT IF OR
|
|
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/dist/README.md
DELETED
|
@@ -1,291 +0,0 @@
|
|
|
1
|
-
# @hyperttp/core ⚡
|
|
2
|
-
|
|
3
|
-
> High-performance HTTP engine for Node.js and Bun.
|
|
4
|
-
|
|
5
|
-
**English** | [Русский](https://github.com/IT-IF-OR/hyperttp-core/tree/main/lang/ru)
|
|
6
|
-
|
|
7
|
-
[](https://www.npmjs.com/package/@hyperttp/core)
|
|
8
|
-
[](https://www.npmjs.com/package/@hyperttp/core)
|
|
9
|
-
[](https://bundlephobia.com/package/@hyperttp/core)
|
|
10
|
-
[](./LICENSE)
|
|
11
|
-
[](https://www.typescriptlang.org/)
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## What is @hyperttp/core?
|
|
16
|
-
|
|
17
|
-
**@hyperttp/core** is a low-level, high-performance HTTP engine designed for building fast,
|
|
18
|
-
extensible HTTP clients and SDKs.
|
|
19
|
-
|
|
20
|
-
It provides:
|
|
21
|
-
|
|
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.
|
|
30
|
-
|
|
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.
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## Why @hyperttp/core?
|
|
39
|
-
|
|
40
|
-
Unlike the native `fetch()`, HyperCore is designed as an extensible HTTP engine rather than just a request API.
|
|
41
|
-
|
|
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 | ❌ | ✅ |
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## Features
|
|
55
|
-
|
|
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
|
|
68
|
-
|
|
69
|
-
---
|
|
70
|
-
|
|
71
|
-
## Architecture
|
|
72
|
-
|
|
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
|
-
---
|
|
92
|
-
|
|
93
|
-
## Installation
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
npm install @hyperttp/core
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
Recommended transports:
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
# Bun
|
|
103
|
-
npm install @hyperttp/transport-bun
|
|
104
|
-
|
|
105
|
-
# Node.js
|
|
106
|
-
npm install @hyperttp/transport-undici
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
---
|
|
110
|
-
|
|
111
|
-
## Quick Start
|
|
112
|
-
|
|
113
|
-
```ts
|
|
114
|
-
import { HyperCore } from "@hyperttp/core";
|
|
115
|
-
|
|
116
|
-
const http = new HyperCore({
|
|
117
|
-
network: {
|
|
118
|
-
baseURL: "https://api.example.com",
|
|
119
|
-
headers: {
|
|
120
|
-
"X-App-Version": "1.0.0",
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
const response = await http.get("/users", {
|
|
126
|
-
query: {
|
|
127
|
-
page: 1,
|
|
128
|
-
limit: 20,
|
|
129
|
-
},
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
const users = await response.json();
|
|
133
|
-
|
|
134
|
-
console.log(users);
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
---
|
|
138
|
-
|
|
139
|
-
## Error Handling
|
|
140
|
-
|
|
141
|
-
```ts
|
|
142
|
-
import { HyperCore, HttpClientError, TimeoutError } from "@hyperttp/core";
|
|
143
|
-
|
|
144
|
-
try {
|
|
145
|
-
const res = await http.get("/users");
|
|
146
|
-
|
|
147
|
-
console.log(await res.json());
|
|
148
|
-
} catch (error) {
|
|
149
|
-
if (TimeoutError.isTimeoutError(error)) {
|
|
150
|
-
console.error("Request timed out.");
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (HttpClientError.isHttpClientError(error)) {
|
|
154
|
-
console.error(error.statusCode, error.message);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
throw error;
|
|
158
|
-
}
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
## Streaming
|
|
164
|
-
|
|
165
|
-
Read a streaming response:
|
|
166
|
-
|
|
167
|
-
```ts
|
|
168
|
-
const response = await http.stream("https://stream.example.com/audio");
|
|
169
|
-
|
|
170
|
-
const reader = response.body.getReader();
|
|
171
|
-
|
|
172
|
-
while (true) {
|
|
173
|
-
const { done, value } = await reader.read();
|
|
174
|
-
|
|
175
|
-
if (done) break;
|
|
176
|
-
|
|
177
|
-
console.log(value.length);
|
|
178
|
-
}
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
Discard a response body without buffering:
|
|
182
|
-
|
|
183
|
-
```ts
|
|
184
|
-
await http.dump("https://api.example.com/ping");
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
## Plugins
|
|
190
|
-
|
|
191
|
-
HyperCore exposes request lifecycle hooks that allow intercepting requests, responses and errors.
|
|
192
|
-
|
|
193
|
-
```ts
|
|
194
|
-
http.use({
|
|
195
|
-
name: "logger",
|
|
196
|
-
priority: 10,
|
|
197
|
-
|
|
198
|
-
onRequest(req) {
|
|
199
|
-
req.meta.start = performance.now();
|
|
200
|
-
},
|
|
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)`);
|
|
206
|
-
},
|
|
207
|
-
|
|
208
|
-
onError(error, req) {
|
|
209
|
-
console.error(`${req.url}: ${error.message}`);
|
|
210
|
-
},
|
|
211
|
-
});
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
---
|
|
215
|
-
|
|
216
|
-
## Transports
|
|
217
|
-
|
|
218
|
-
HyperCore automatically detects the current runtime, or you can provide your own transport.
|
|
219
|
-
|
|
220
|
-
| Transport | Runtime |
|
|
221
|
-
| ---------------- | ------------- |
|
|
222
|
-
| BunTransport | Bun |
|
|
223
|
-
| UndiciTransport | Node.js |
|
|
224
|
-
| NodeTransport | Bun / Node.js |
|
|
225
|
-
| BrowserTransport | Browser |
|
|
226
|
-
| Custom Transport | Any |
|
|
227
|
-
|
|
228
|
-
Example:
|
|
229
|
-
|
|
230
|
-
```ts
|
|
231
|
-
import { HyperCore } from "@hyperttp/core";
|
|
232
|
-
import { UndiciTransport } from "@hyperttp/transport-undici";
|
|
233
|
-
|
|
234
|
-
const http = new HyperCore({
|
|
235
|
-
customTransport: new UndiciTransport(),
|
|
236
|
-
});
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
---
|
|
240
|
-
|
|
241
|
-
## Performance
|
|
242
|
-
|
|
243
|
-
HyperCore is optimized for sustained high concurrency.
|
|
244
|
-
|
|
245
|
-
Recent stress testing:
|
|
246
|
-
|
|
247
|
-
- **200,000 requests**
|
|
248
|
-
- **1000 concurrent connections**
|
|
249
|
-
- **120 seconds**
|
|
250
|
-
- **0 request errors**
|
|
251
|
-
|
|
252
|
-
Optimizations include:
|
|
253
|
-
|
|
254
|
-
- minimal allocations
|
|
255
|
-
- object reuse
|
|
256
|
-
- optimized semaphore
|
|
257
|
-
- manual query serialization
|
|
258
|
-
- efficient header normalization
|
|
259
|
-
- zero-dependency core
|
|
260
|
-
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
## Ecosystem
|
|
264
|
-
|
|
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 |
|
|
273
|
-
|
|
274
|
-
---
|
|
275
|
-
|
|
276
|
-
## Development
|
|
277
|
-
|
|
278
|
-
```bash
|
|
279
|
-
bun install
|
|
280
|
-
|
|
281
|
-
bun run lint
|
|
282
|
-
bun run typecheck
|
|
283
|
-
bun run test
|
|
284
|
-
bun run build
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
---
|
|
288
|
-
|
|
289
|
-
## License
|
|
290
|
-
|
|
291
|
-
MIT
|
package/dist/defaultConfig.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { HttpClientOptions } from "@hyperttp/types";
|
|
2
|
-
/**
|
|
3
|
-
* @ru Конфигурация по умолчанию для HTTP-клиента Hyperttp.
|
|
4
|
-
* @en Default configuration for the Hyperttp HTTP client.
|
|
5
|
-
*/
|
|
6
|
-
export declare const defaultConfig: HttpClientOptions;
|
|
7
|
-
//# sourceMappingURL=defaultConfig.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"defaultConfig.d.ts","sourceRoot":"","sources":["../src/defaultConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,iBAiB3B,CAAC"}
|
package/dist/defaultConfig.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";export const defaultConfig={network:{timeout:3e4,maxConcurrent:128,pipelining:0,keepAliveTimeout:5e3,followRedirects:!0,maxRedirects:5,rejectUnauthorized:!0},retry:{maxRetries:0,baseDelay:100,maxDelay:5e3,jitter:!0},verbose:!1};
|
|
2
|
-
//# sourceMappingURL=defaultConfig.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/defaultConfig.ts"],
|
|
4
|
-
"sourcesContent": ["import type { HttpClientOptions } from \"@hyperttp/types\";\n\n/**\n * @ru Конфигурация по умолчанию для HTTP-клиента Hyperttp.\n * @en Default configuration for the Hyperttp HTTP client.\n */\nexport const defaultConfig: HttpClientOptions = {\n network: {\n timeout: 30000,\n maxConcurrent: 128,\n pipelining: 0,\n keepAliveTimeout: 5000,\n followRedirects: true,\n maxRedirects: 5,\n rejectUnauthorized: true,\n },\n retry: {\n maxRetries: 0,\n baseDelay: 100,\n maxDelay: 5000,\n jitter: true,\n },\n verbose: false,\n};\n"],
|
|
5
|
-
"mappings": "aAMO,aAAM,cAAmC,CAC9C,QAAS,CACP,QAAS,IACT,cAAe,IACf,WAAY,EACZ,iBAAkB,IAClB,gBAAiB,GACjB,aAAc,EACd,mBAAoB,IAEtB,MAAO,CACL,WAAY,EACZ,UAAW,IACX,SAAU,IACV,OAAQ,IAEV,QAAS",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
package/dist/index.d.ts
DELETED
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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,SAAS,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
DELETED
package/dist/index.js.map
DELETED
package/dist/package.json
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@hyperttp/core",
|
|
3
|
-
"version": "1.5.6",
|
|
4
|
-
"description": "High-performance, extensible HTTP client for Node.js, Bun, Deno and Browser",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"sideEffects": false,
|
|
7
|
-
"main": "./index.js",
|
|
8
|
-
"types": "./index.d.ts",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"types": "./index.d.ts",
|
|
12
|
-
"import": "./index.js"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"keywords": [
|
|
16
|
-
"http",
|
|
17
|
-
"client",
|
|
18
|
-
"high-performance",
|
|
19
|
-
"undici",
|
|
20
|
-
"fetch",
|
|
21
|
-
"bun",
|
|
22
|
-
"deno",
|
|
23
|
-
"isomorphic",
|
|
24
|
-
"hyperttp"
|
|
25
|
-
],
|
|
26
|
-
"author": "dirold2",
|
|
27
|
-
"license": "MIT",
|
|
28
|
-
"repository": {
|
|
29
|
-
"type": "git",
|
|
30
|
-
"url": "git+https://github.com/IT-IF-OR/hyperttp-core.git"
|
|
31
|
-
},
|
|
32
|
-
"peerDependencies": {
|
|
33
|
-
"@hyperttp/types": "^0.2.5",
|
|
34
|
-
"@hyperttp/transport-bun": "^0.2.4",
|
|
35
|
-
"@hyperttp/transport-undici": "^0.2.5",
|
|
36
|
-
"hcacher": "^0.1.0"
|
|
37
|
-
},
|
|
38
|
-
"peerDependenciesMeta": {
|
|
39
|
-
"@hyperttp/types": {
|
|
40
|
-
"optional": false
|
|
41
|
-
},
|
|
42
|
-
"@hyperttp/transport-bun": {
|
|
43
|
-
"optional": true
|
|
44
|
-
},
|
|
45
|
-
"@hyperttp/transport-undici": {
|
|
46
|
-
"optional": true
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
"private": false
|
|
50
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { HttpClientOptions, HyperTransport, TransportRequest, TransportResponse } from "@hyperttp/types";
|
|
2
|
-
/**
|
|
3
|
-
* @ru Конфигурация транспорта для браузера.
|
|
4
|
-
* @en Browser transport configuration.
|
|
5
|
-
*/
|
|
6
|
-
export interface BrowserTransportConfig extends HttpClientOptions {
|
|
7
|
-
/**
|
|
8
|
-
* @ru Базовый URL для относительных путей. По умолчанию — window.location.origin.
|
|
9
|
-
* @en Base URL for relative paths. Defaults to window.location.origin.
|
|
10
|
-
*/
|
|
11
|
-
baseUrl?: string;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* @ru Реализация транспорта для браузера с использованием глобального fetch API.
|
|
15
|
-
* Оптимизирован для минимального размера и максимальной совместимости.
|
|
16
|
-
* @en Browser transport implementation using the global fetch API.
|
|
17
|
-
* Optimized for minimal size and maximum compatibility.
|
|
18
|
-
*/
|
|
19
|
-
export declare class BrowserTransport implements HyperTransport {
|
|
20
|
-
config: BrowserTransportConfig;
|
|
21
|
-
private readonly isProduction;
|
|
22
|
-
private readonly cleanBaseUrl;
|
|
23
|
-
/**
|
|
24
|
-
* @ru Создаёт экземпляр BrowserTransport.
|
|
25
|
-
* @en Creates a BrowserTransport instance.
|
|
26
|
-
* @param config - Transport configuration.
|
|
27
|
-
*/
|
|
28
|
-
constructor(config: BrowserTransportConfig);
|
|
29
|
-
/**
|
|
30
|
-
* @ru Выполняет HTTP-запрос через глобальный fetch.
|
|
31
|
-
* @en Executes an HTTP request via the global fetch.
|
|
32
|
-
* @param req - The normalized transport request.
|
|
33
|
-
* @returns Promise resolving to the transport response.
|
|
34
|
-
*/
|
|
35
|
-
execute(req: TransportRequest): Promise<TransportResponse>;
|
|
36
|
-
}
|
|
37
|
-
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/transports/browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EAElB,MAAM,iBAAiB,CAAC;AAEzB;;;GAGG;AACH,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC/D;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAaD;;;;;GAKG;AACH,qBAAa,gBAAiB,YAAW,cAAc;IASlC,MAAM,EAAE,sBAAsB;IARjD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IAEtC;;;;OAIG;IACH,YAAmB,MAAM,EAAE,sBAAsB,EAehD;IAED;;;;;OAKG;IACU,OAAO,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA6DtE;CACF"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";export class BrowserTransport{config;isProduction;cleanBaseUrl;constructor(s){this.config=s;const o=typeof window<"u"&&["localhost","127.0.0.1","::1"].includes(window.location.hostname),c=typeof process<"u"&&process.env,a=typeof import.meta<"u";this.isProduction=!o&&(c&&!0||a&&import.meta.env?.PROD===!0);const r=s.baseUrl??(typeof window<"u"?window.location.origin:"");this.cleanBaseUrl=r.endsWith("/")?r.slice(0,-1):r}async execute(s){const o=s.url,a=o.startsWith("http://")||o.startsWith("https://")||o.startsWith("//")?o:o.charCodeAt(0)===47?this.cleanBaseUrl+o:this.cleanBaseUrl+"/"+o;if(this.isProduction&&a.includes("//localhost"))throw new Error("Localhost URL detected in production environment");const r=Object.create(null);if(s.headers)if(s.headers instanceof Headers)s.headers.forEach((t,e)=>{r[e.toLowerCase()]=t});else if(Array.isArray(s.headers))for(let t=0;t<s.headers.length;t++){const e=s.headers[t];e&&typeof e[0]=="string"&&(r[e[0].toLowerCase()]=String(e[1]))}else{const t=s.headers;for(const e in t){const i=t[e];i!=null&&(r[e.toLowerCase()]=Array.isArray(i)?i.join(", "):String(i))}}const n=await globalThis.fetch(a,{method:s.method,headers:r,body:s.body,signal:s.signal}),l=Object.create(null);return n.headers.forEach((t,e)=>{l[e]=t}),{status:n.status,url:n.url,body:n.body,headers:l,_raw:n}}}
|
|
2
|
-
//# sourceMappingURL=browser.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/transports/browser.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n HttpClientOptions,\n HyperTransport,\n TransportRequest,\n TransportResponse,\n TransportResponsePayload,\n} from \"@hyperttp/types\";\n\n/**\n * @ru Конфигурация транспорта для браузера.\n * @en Browser transport configuration.\n */\nexport interface BrowserTransportConfig extends HttpClientOptions {\n /**\n * @ru Базовый URL для относительных путей. По умолчанию — window.location.origin.\n * @en Base URL for relative paths. Defaults to window.location.origin.\n */\n baseUrl?: string;\n}\n\n/**\n * @ru Интерфейс для безопасного доступа к мета-окружению сборщиков (Vite, Webpack и др.).\n * @en Interface for safe access to bundler meta-environment (Vite, Webpack, etc.).\n */\ninterface ImportMetaEnv {\n env?: {\n PROD?: boolean;\n [key: string]: unknown;\n };\n}\n\n/**\n * @ru Реализация транспорта для браузера с использованием глобального fetch API.\n * Оптимизирован для минимального размера и максимальной совместимости.\n * @en Browser transport implementation using the global fetch API.\n * Optimized for minimal size and maximum compatibility.\n */\nexport class BrowserTransport implements HyperTransport {\n private readonly isProduction: boolean;\n private readonly cleanBaseUrl: string;\n\n /**\n * @ru Создаёт экземпляр BrowserTransport.\n * @en Creates a BrowserTransport instance.\n * @param config - Transport configuration.\n */\n constructor(public config: BrowserTransportConfig) {\n const isLocalhost =\n typeof window !== \"undefined\" &&\n [\"localhost\", \"127.0.0.1\", \"::1\"].includes(window.location.hostname);\n\n const hasProcess = typeof process !== \"undefined\" && process.env;\n const hasMeta = typeof import.meta !== \"undefined\";\n\n this.isProduction =\n !isLocalhost &&\n ((hasProcess && process.env.NODE_ENV === \"production\") ||\n (hasMeta && (import.meta as unknown as ImportMetaEnv).env?.PROD === true));\n\n const base = config.baseUrl ?? (typeof window !== \"undefined\" ? window.location.origin : \"\");\n this.cleanBaseUrl = base.endsWith(\"/\") ? base.slice(0, -1) : base;\n }\n\n /**\n * @ru Выполняет HTTP-запрос через глобальный fetch.\n * @en Executes an HTTP request via the global fetch.\n * @param req - The normalized transport request.\n * @returns Promise resolving to the transport response.\n */\n public async execute(req: TransportRequest): Promise<TransportResponse> {\n const urlStr = req.url;\n\n const isAbsolute =\n urlStr.startsWith(\"http://\") || urlStr.startsWith(\"https://\") || urlStr.startsWith(\"//\");\n\n const fullUrl = isAbsolute\n ? urlStr\n : urlStr.charCodeAt(0) === 47\n ? this.cleanBaseUrl + urlStr\n : this.cleanBaseUrl + \"/\" + urlStr;\n\n if (this.isProduction && fullUrl.includes(\"//localhost\")) {\n throw new Error(\"Localhost URL detected in production environment\");\n }\n\n const finalHeaders: Record<string, string> = Object.create(null);\n if (req.headers) {\n if (req.headers instanceof Headers) {\n req.headers.forEach((value, key) => {\n finalHeaders[key.toLowerCase()] = value;\n });\n } else if (Array.isArray(req.headers)) {\n for (let i = 0; i < req.headers.length; i++) {\n const pair = req.headers[i] as unknown as [string, string] | undefined;\n if (pair && typeof pair[0] === \"string\") {\n finalHeaders[pair[0].toLowerCase()] = String(pair[1]);\n }\n }\n } else {\n const src = req.headers as Record<string, unknown>;\n for (const key in src) {\n const value = src[key];\n if (value != null) {\n finalHeaders[key.toLowerCase()] = Array.isArray(value)\n ? value.join(\", \")\n : String(value);\n }\n }\n }\n }\n\n const res = await globalThis.fetch(fullUrl, {\n method: req.method,\n headers: finalHeaders as HeadersInit,\n body: req.body as BodyInit | null,\n signal: req.signal,\n });\n\n const resHeaders: Record<string, string> = Object.create(null);\n res.headers.forEach((value, key) => {\n resHeaders[key] = value;\n });\n\n return {\n status: res.status,\n url: res.url,\n body: res.body as unknown as TransportResponsePayload,\n headers: resHeaders,\n _raw: res,\n } as TransportResponse;\n }\n}\n"],
|
|
5
|
-
"mappings": "aAqCM,aAAO,gBAAgB,CASR,OARF,aACA,aAOjB,YAAmBA,EAA8B,aAA9BA,EACjB,MAAMC,EACJ,OAAO,OAAW,KAClB,CAAC,YAAa,YAAa,KAAK,EAAE,SAAS,OAAO,SAAS,QAAQ,EAE/DC,EAAa,OAAO,QAAY,KAAe,QAAQ,IACvDC,EAAU,OAAO,YAAgB,IAEvC,KAAK,aACH,CAACF,IACCC,GAAc,IACbC,GAAY,YAAyC,KAAK,OAAS,IAExE,MAAMC,EAAOJ,EAAO,UAAY,OAAO,OAAW,IAAc,OAAO,SAAS,OAAS,IACzF,KAAK,aAAeI,EAAK,SAAS,GAAG,EAAIA,EAAK,MAAM,EAAG,EAAE,EAAIA,CAC/D,CAQO,MAAM,QAAQC,EAAqB,CACxC,MAAMC,EAASD,EAAI,IAKbE,EAFJD,EAAO,WAAW,SAAS,GAAKA,EAAO,WAAW,UAAU,GAAKA,EAAO,WAAW,IAAI,EAGrFA,EACAA,EAAO,WAAW,CAAC,IAAM,GACvB,KAAK,aAAeA,EACpB,KAAK,aAAe,IAAMA,EAEhC,GAAI,KAAK,cAAgBC,EAAQ,SAAS,aAAa,EACrD,MAAM,IAAI,MAAM,kDAAkD,EAGpE,MAAMC,EAAuC,OAAO,OAAO,IAAI,EAC/D,GAAIH,EAAI,QACN,GAAIA,EAAI,mBAAmB,QACzBA,EAAI,QAAQ,QAAQ,CAACI,EAAOC,IAAO,CACjCF,EAAaE,EAAI,YAAW,CAAE,EAAID,CACpC,CAAC,UACQ,MAAM,QAAQJ,EAAI,OAAO,EAClC,QAASM,EAAI,EAAGA,EAAIN,EAAI,QAAQ,OAAQM,IAAK,CAC3C,MAAMC,EAAOP,EAAI,QAAQM,CAAC,EACtBC,GAAQ,OAAOA,EAAK,CAAC,GAAM,WAC7BJ,EAAaI,EAAK,CAAC,EAAE,YAAW,CAAE,EAAI,OAAOA,EAAK,CAAC,CAAC,EAExD,KACK,CACL,MAAMC,EAAMR,EAAI,QAChB,UAAWK,KAAOG,EAAK,CACrB,MAAMJ,EAAQI,EAAIH,CAAG,EACjBD,GAAS,OACXD,EAAaE,EAAI,YAAW,CAAE,EAAI,MAAM,QAAQD,CAAK,EACjDA,EAAM,KAAK,IAAI,EACf,OAAOA,CAAK,EAEpB,CACF,CAGF,MAAMK,EAAM,MAAM,WAAW,MAAMP,EAAS,CAC1C,OAAQF,EAAI,OACZ,QAASG,EACT,KAAMH,EAAI,KACV,OAAQA,EAAI,OACb,EAEKU,EAAqC,OAAO,OAAO,IAAI,EAC7D,OAAAD,EAAI,QAAQ,QAAQ,CAACL,EAAOC,IAAO,CACjCK,EAAWL,CAAG,EAAID,CACpB,CAAC,EAEM,CACL,OAAQK,EAAI,OACZ,IAAKA,EAAI,IACT,KAAMA,EAAI,KACV,QAASC,EACT,KAAMD,EAEV",
|
|
6
|
-
"names": ["config", "isLocalhost", "hasProcess", "hasMeta", "base", "req", "urlStr", "fullUrl", "finalHeaders", "value", "key", "i", "pair", "src", "res", "resHeaders"]
|
|
7
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import type { HttpClientOptions, HyperTransport } from "@hyperttp/types";
|
|
2
|
-
/**
|
|
3
|
-
* @ru Поддерживаемые среды выполнения для автоматического выбора транспорта.
|
|
4
|
-
* @en Supported runtime environments for automatic transport selection.
|
|
5
|
-
*/
|
|
6
|
-
export type Runtime = "bun" | "node" | "deno" | "browser";
|
|
7
|
-
/**
|
|
8
|
-
* @ru Определяет текущую среду выполнения при загрузке модуля.
|
|
9
|
-
* Порядок проверки: Bun → Deno → Node.js → Browser.
|
|
10
|
-
* @en Detects the current runtime at module load time.
|
|
11
|
-
* Detection order: Bun → Deno → Node.js → Browser.
|
|
12
|
-
*/
|
|
13
|
-
export declare const CURRENT_RUNTIME: Runtime;
|
|
14
|
-
/**
|
|
15
|
-
* @ru Разрешает и создаёт оптимальный транспорт для текущей среды.
|
|
16
|
-
* Перебирает кандидатов по приоритету, кэширует первый успешный результат.
|
|
17
|
-
* @en Resolves and creates the optimal transport for the current runtime.
|
|
18
|
-
* Iterates candidates by priority, caches the first successful result.
|
|
19
|
-
* @param config - Client configuration options.
|
|
20
|
-
* @returns Promise resolving to the instantiated transport.
|
|
21
|
-
* @throws Error if no compatible transport is found.
|
|
22
|
-
*/
|
|
23
|
-
export declare function resolveTransport(config: HttpClientOptions): Promise<HyperTransport>;
|
|
24
|
-
/**
|
|
25
|
-
* @ru Менеджер транспорта с ленивой инициализацией и кэшированием.
|
|
26
|
-
* Поддерживает синхронный доступ, отложенную инициализацию и корректное завершение.
|
|
27
|
-
* @en Transport manager with lazy initialization and caching.
|
|
28
|
-
* Supports synchronous access, deferred initialization, and graceful shutdown.
|
|
29
|
-
*/
|
|
30
|
-
export declare class TransportManager {
|
|
31
|
-
/**
|
|
32
|
-
* @ru Текущий экземпляр транспорта (null до инициализации).
|
|
33
|
-
* @en Current transport instance (null before initialization).
|
|
34
|
-
*/
|
|
35
|
-
transport: HyperTransport | null;
|
|
36
|
-
/**
|
|
37
|
-
* @ru Промис отложенной инициализации транспорта.
|
|
38
|
-
* @en Deferred transport initialization promise.
|
|
39
|
-
*/
|
|
40
|
-
private promise;
|
|
41
|
-
/**
|
|
42
|
-
* @ru Конфигурация клиента для создания транспорта.
|
|
43
|
-
* @en Client configuration for transport creation.
|
|
44
|
-
*/
|
|
45
|
-
private config;
|
|
46
|
-
/**
|
|
47
|
-
* @ru Создаёт менеджер транспорта с опциональным пользовательским транспортом.
|
|
48
|
-
* @en Creates a transport manager with an optional custom transport.
|
|
49
|
-
* @param config - Client configuration options.
|
|
50
|
-
* @param custom - Optional custom transport instance.
|
|
51
|
-
*/
|
|
52
|
-
constructor(config: HttpClientOptions, custom?: HyperTransport);
|
|
53
|
-
/**
|
|
54
|
-
* @ru Синхронно возвращает текущий транспорт или null, если не инициализирован.
|
|
55
|
-
* @en Synchronously returns the current transport or null if not initialized.
|
|
56
|
-
* @returns The transport instance or null.
|
|
57
|
-
*/
|
|
58
|
-
getSync(): HyperTransport | null;
|
|
59
|
-
/**
|
|
60
|
-
* @ru Гарантирует наличие транспорта, инициализируя его при необходимости.
|
|
61
|
-
* Повторные вызовы возвращают один и тот же промис.
|
|
62
|
-
* @en Ensures a transport exists, initializing it if necessary.
|
|
63
|
-
* Repeated calls return the same promise.
|
|
64
|
-
* @returns Promise resolving to the transport instance.
|
|
65
|
-
*/
|
|
66
|
-
ensure(): Promise<HyperTransport>;
|
|
67
|
-
/**
|
|
68
|
-
* @ru Возвращает транспорт синхронно или промис, если требуется инициализация.
|
|
69
|
-
* @en Returns the transport synchronously or a promise if initialization is needed.
|
|
70
|
-
* @returns The transport instance or a promise resolving to it.
|
|
71
|
-
*/
|
|
72
|
-
get(): HyperTransport | Promise<HyperTransport>;
|
|
73
|
-
/**
|
|
74
|
-
* @ru Обновляет конфигурацию транспорта, если он поддерживает setConfig.
|
|
75
|
-
* @en Updates the transport configuration if it supports setConfig.
|
|
76
|
-
* @param config - New client configuration options.
|
|
77
|
-
*/
|
|
78
|
-
setConfig(config: HttpClientOptions): void;
|
|
79
|
-
/**
|
|
80
|
-
* @ru Завершает работу транспорта и освобождает ресурсы.
|
|
81
|
-
* В graceful-режиме вызывает close(), иначе — destroy().
|
|
82
|
-
* @en Shuts down the transport and releases resources.
|
|
83
|
-
* In graceful mode calls close(), otherwise calls destroy().
|
|
84
|
-
* @param graceful - If true, waits for active requests to complete.
|
|
85
|
-
* @returns Promise that resolves when shutdown is complete.
|
|
86
|
-
*/
|
|
87
|
-
destroy(graceful?: boolean): Promise<void>;
|
|
88
|
-
}
|
|
89
|
-
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/transports/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEzE;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAyB1D;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,OAK1B,CAAC;AA4JL;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CA+BzF;AAED;;;;;GAKG;AACH,qBAAa,gBAAgB;IAC3B;;;OAGG;IACI,SAAS,EAAE,cAAc,GAAG,IAAI,CAAQ;IAE/C;;;OAGG;IACH,OAAO,CAAC,OAAO,CAAwC;IAEvD;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAoB;IAElC;;;;;OAKG;IACH,YAAY,MAAM,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,cAAc,EAU7D;IAED;;;;OAIG;IACI,OAAO,IAAI,cAAc,GAAG,IAAI,CAEtC;IAED;;;;;;OAMG;IACI,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC,CAUvC;IAED;;;;OAIG;IACI,GAAG,IAAI,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAErD;IAED;;;;OAIG;IACI,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAOhD;IAED;;;;;;;OAOG;IACU,OAAO,CAAC,QAAQ,UAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBnD;CACF"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
"use strict";export const CURRENT_RUNTIME=typeof Bun<"u"?"bun":typeof Deno<"u"?"deno":typeof process<"u"&&process.versions?.node?"node":"browser";const i=[{name:"Bun",runtime:["bun"],pkg:"@hyperttp/transport-bun",export:"BunTransport",priority:100},{name:"Deno",runtime:["deno"],pkg:"@hyperttp/transport-deno",export:"DenoTransport",priority:95},{name:"Undici",runtime:["node"],pkg:"@hyperttp/transport-undici",export:"UndiciTransport",priority:90},{name:"Browser",runtime:["browser"],pkg:"./browser.js",export:"BrowserTransport",priority:80},{name:"Node",runtime:["node","bun","deno"],pkg:"./node.js",export:"NodeTransport",priority:10}];i.forEach(Object.freeze),Object.freeze(i);const f=new Set(i.map(t=>t.pkg)),u=i.filter(t=>t.runtime.includes(CURRENT_RUNTIME)).sort((t,r)=>r.priority-t.priority);let s=null;function c(t){if(!t||typeof t!="object")return!1;const r=t,e=r.code;if(e==="ERR_MODULE_NOT_FOUND"||e==="MODULE_NOT_FOUND")return!0;const n=t instanceof Error?t.message:String(r.message??"");return n.includes("Cannot find module")||n.includes("Failed to resolve")||n.includes("Failed to load")}function d(t,r,e){const n=typeof process<"u"&&!1,o=typeof process<"u"&&process.env?.DEBUG==="1",l=t.includes(CURRENT_RUNTIME);if(o||n&&l){const p=`Failed to load preferred transport "${t}"`,a="Falling back to alternative transport...";e?.logger?(e.logger("warn",`[Hyperttp Debug] ${p}`,r),e.logger("warn",`[Hyperttp Debug] ${a}`)):(console.warn(`
|
|
2
|
-
\u26A0\uFE0F [Hyperttp Debug] ${p}:`),console.error(r),console.warn(`${a}
|
|
3
|
-
`))}}async function y(t,r,e){if(!f.has(t))throw new Error(`[Hyperttp Security] Blocked untrusted transport import attempt: ${t}`);try{const n=await import(t),o=n[r]??n.default;return typeof o=="function"?o:null}catch(n){if(c(n))return d(t,n,e),null;throw n}}export async function resolveTransport(t){if(t.customTransport)return t.customTransport;if(s)return new s(t);const r=[];for(let e=0;e<u.length;e++){const n=u[e];try{const o=await y(n.pkg,n.export,t);if(!o){r.push(`${n.pkg} (missing export or not installed)`);continue}return s=o,new o(t)}catch(o){if(c(o)){r.push(`${n.pkg} (not installed)`);continue}throw new Error(`[Hyperttp] Transport crash in ${n.pkg}: ${o?.message}`,{cause:o})}}throw new Error(`No compatible transport for runtime="${CURRENT_RUNTIME}".
|
|
4
|
-
Failures:
|
|
5
|
-
- ${r.join(`
|
|
6
|
-
- `)}`)}export class TransportManager{transport=null;promise=null;config;constructor(r,e){this.config=r,e?this.transport=e:r.customTransport?this.transport=r.customTransport:s&&(this.transport=new s(r))}getSync(){return this.transport}ensure(){return this.transport!==null?this.promise||(this.promise=Promise.resolve(this.transport)):this.promise!==null?this.promise:this.promise=resolveTransport(this.config).then(r=>(this.transport=r,r))}get(){return this.transport??this.ensure()}setConfig(r){this.config=r;const e=this.transport;typeof e?.setConfig=="function"&&e.setConfig(r)}async destroy(r=!0){const e=this.transport;if(e)try{if(r&&typeof e.close=="function"){await e.close();return}typeof e.destroy=="function"&&await e.destroy()}finally{this.transport=null,this.promise=null}}}
|
|
7
|
-
//# sourceMappingURL=manager.js.map
|