@hyperttp/core 2.0.0 → 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 +6 -4
- package/Core/HyperCore.d.ts.map +1 -1
- package/Core/HyperCore.js +1 -1
- package/Core/HyperCore.js.map +3 -3
- package/package.json +2 -2
- package/protocols/manager.d.ts +6 -0
- package/protocols/manager.d.ts.map +1 -1
- package/protocols/manager.js.map +2 -2
- package/protocols/rest/receiver.d.ts +5 -0
- package/protocols/rest/receiver.d.ts.map +1 -1
- package/protocols/rest/receiver.js.map +2 -2
- package/protocols/rest/sender.d.ts +12 -0
- package/protocols/rest/sender.d.ts.map +1 -1
- package/protocols/rest/sender.js.map +2 -2
- package/protocols/rest/type.d.ts +40 -0
- package/protocols/rest/type.d.ts.map +1 -1
- package/transports/fetch.d.ts +11 -0
- package/transports/fetch.d.ts.map +1 -1
- package/transports/fetch.js.map +2 -2
- package/transports/manager.d.ts +15 -2
- package/transports/manager.d.ts.map +1 -1
- package/transports/manager.js.map +2 -2
- package/utils/errors.d.ts +12 -4
- package/utils/errors.d.ts.map +1 -1
- package/utils/errors.js.map +2 -2
package/Core/HyperCore.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare class HyperCore implements IHyperCore {
|
|
|
15
15
|
readonly config: HyperClientOptions;
|
|
16
16
|
private readonly registry;
|
|
17
17
|
private readonly pluginCtx;
|
|
18
|
-
private
|
|
18
|
+
private plugins;
|
|
19
19
|
private readonly servers;
|
|
20
20
|
private readonly protocolNamespaces;
|
|
21
21
|
private readonly generatedFlatMethods;
|
|
@@ -194,10 +194,12 @@ export declare class HyperCore implements IHyperCore {
|
|
|
194
194
|
create(options: Partial<HyperClientOptions>): IHyperCore;
|
|
195
195
|
/**
|
|
196
196
|
* @ru Завершает работу ядра и освобождает ресурсы: закрывает активные серверы,
|
|
197
|
-
* затем освобождает удержание транспорта.
|
|
197
|
+
* затем освобождает удержание транспорта. Graceful-дренирование активных запросов
|
|
198
|
+
* определяется реализацией `TransportServer.close()`.
|
|
198
199
|
* @en Shuts down the core and releases resources: closes active servers, then
|
|
199
|
-
* releases the transport hold.
|
|
200
|
-
*
|
|
200
|
+
* releases the transport hold. Graceful draining of in-flight requests is defined
|
|
201
|
+
* by the `TransportServer.close()` implementation.
|
|
202
|
+
* @param graceful - If true, prefers `transport.close()`; otherwise prefers `transport.destroy()`.
|
|
201
203
|
* @returns Promise that resolves when shutdown is complete.
|
|
202
204
|
*/
|
|
203
205
|
destroy(graceful?: boolean): Promise<void>;
|
package/Core/HyperCore.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HyperCore.d.ts","sourceRoot":"","sources":["../../src/Core/HyperCore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,cAAc,EACd,aAAa,EACb,WAAW,EACX,wBAAwB,EACxB,cAAc,EACd,UAAU,EAIV,cAAc,EACd,WAAW,EAIX,eAAe,EACf,iBAAiB,EAClB,MAAM,iBAAiB,CAAC;AA+JzB,MAAM,WAAW,SAAU,SAAQ,cAAc;CAAG;AAEpD;;;;;;;;;GASG;AACH,qBAAa,SAAU,YAAW,UAAU;IAC1C,SAAgB,MAAM,EAAE,kBAAkB,CAAC;IAE3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAC1D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAC1C,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"HyperCore.d.ts","sourceRoot":"","sources":["../../src/Core/HyperCore.ts"],"names":[],"mappings":"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"}
|
package/Core/HyperCore.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";import{defaultCoreConfig as w}from"../defaultConfig.js";import{KNOWN_PROTOCOLS as m,resolveProtocol as d}from"../protocols/manager.js";import{evictCachedTransport as S,resolveTransport as x}from"../transports/manager.js";import{HyperClientError as
|
|
1
|
+
"use strict";import{defaultCoreConfig as w}from"../defaultConfig.js";import{KNOWN_PROTOCOLS as m,resolveProtocol as d}from"../protocols/manager.js";import{evictCachedTransport as S,resolveTransport as x}from"../transports/manager.js";import{HyperClientError as p}from"../utils/errors.js";let g=0,P=Date.now().toString(36)+"-";const v=Object.freeze({START:0,PREPARE:1,CONTROL:2,FORMAT:3,NETWORK:4,DATA:5});function q(){return g=g+1>>>0,g===0&&(P=Date.now().toString(36)+"-"),P+(g>>>0).toString(36)}const f=new WeakMap;function T(h){f.set(h,(f.get(h)??0)+1)}function b(h){const e=(f.get(h)??1)-1;return e<=0?f.delete(h):f.set(h,e),e}class R{requestId=q();startTime=performance.now();signal;requestMeta;requestState;constructor(e){this.signal=e}get meta(){return this.requestMeta??={}}set meta(e){this.requestMeta=e}get state(){return this.requestState??={}}set state(e){this.requestState=e}}function H(h){return new R(h.signal)}function N(h){return new R(h.signal)}function y(h){return typeof h=="object"&&h!==null&&"data"in h&&"status"in h&&!("input"in h)}class O{protocols=new Map;register(e){this.protocols.set(e.protocol,e)}get(e){return this.protocols.get(e)}has(e){return this.protocols.has(e)}get size(){return this.protocols.size}}export class HyperCore{config;registry=new O;pluginCtx;plugins=[];servers=new Set;protocolNamespaces=new Set;generatedFlatMethods=new Set;transportPromises=new Map;transports=new Map;retainedTransports=new Set;fixedTransport;destroyPromise=null;isDestroyed=!1;constructor(e={},t,r){if(this.config={...w,...e,retry:{...w.retry,...e.retry}},this.fixedTransport=t??null,t&&(T(t),this.retainedTransports.add(t)),r)for(const[a,u]of r)this.transportPromises.set(a,u.then(C=>this.retainResolvedTransport(a,C)));this.pluginCtx={config:this.config,core:this};const o=this.config.protocols;if(o)for(let a=0;a<o.length;a++)this.registerProtocol(o[a]);const s=this.config.senders;if(s)for(let a=0;a<s.length;a++)this.registerSender(s[a]);const i=this.config.customSender;i&&this.registerSender(i);const n=this.config.receivers;if(n)for(let a=0;a<n.length;a++)this.registerReceiver(n[a]);const c=this.config.plugins;if(c)for(let a=0;a<c.length;a++){const u=c[a];if(typeof u=="string")throw new p(`[HyperCore] Plugin module "${u}" cannot be loaded by the synchronous constructor. Import it and pass the plugin instance instead.`);this.use(u)}const l=this;for(let a=0;a<m.length;a++){const u=m[a];!this.registry.has(u)&&l[u]===void 0&&(l[u]=this.createLazyNamespace(u),this.protocolNamespaces.add(u))}}getProtocol(e){return this.registry.get(e)}getSender(e){return this.registry.get(e)?.sender}getReceiver(e){return this.registry.get(e)?.receiver}async getTransportName(){return(await this.acquireTransport()).constructor.name}async getSenderName(e="rest"){let t=this.registry.get(e);t||(t=await d(e),this.registerProtocol(t));const r=t.sender;if(!r)throw new p(`[HyperCore] Protocol "${e}" has no sender (client role).`);return r.constructor.name}async getReceiverName(e="rest"){let t=this.registry.get(e);t||(t=await d(e),this.registerProtocol(t));const r=t.receiver;if(!r)throw new p(`[HyperCore] Protocol "${e}" has no receiver (server role).`);return r.constructor.name}async getProtocolName(e="rest"){let t=this.registry.get(e);if(t||(t=await d(e),this.registerProtocol(t)),t.name)return t.name;const r=t.constructor;return r&&r.name&&r.name!=="Object"?r.name:String(t.protocol)}registerProtocol(e){const t=String(e.protocol),r=this;if(t==="__proto__"||t==="prototype"||t==="constructor"||t in HyperCore.prototype||t in this&&!this.protocolNamespaces.has(t))throw new p(`[HyperCore] Protocol name "${t}" conflicts with the core API.`);this.registry.register(e);const s=e.sender?.methods;if(s&&typeof s=="object"){const i=Object.create(null);for(const n in s){if(!Object.hasOwn(s,n))continue;const c=s[n];if(typeof c!="function")continue;const l=(...a)=>c.apply(s,[this,...a]);i[n]=l,this.generatedFlatMethods.has(n)?r[n]=l:!(n in HyperCore.prototype)&&!(n in this)&&(r[n]=l,this.generatedFlatMethods.add(n))}r[t]=i,this.protocolNamespaces.add(t)}return this}registerSender(e){const t=this.registry.get(e.protocol);return this.registerProtocol({protocol:e.protocol,sender:e,receiver:t?.receiver})}registerReceiver(e){const t=this.registry.get(e.protocol);return this.registerProtocol({protocol:e.protocol,sender:t?.sender,receiver:e})}createLazyNamespace(e){const t={get:(r,o)=>{if(!(typeof o!="string"||o==="then"))return(...s)=>this.dispatchLazyMethod(e,o,s)}};return new Proxy({},t)}async dispatchLazyMethod(e,t,r){let o=this.registry.get(e);o||(o=await d(e),this.registerProtocol(o));const s=o.sender;if(!s)throw new p(`[HyperCore] Protocol "${e}" has no sender (client role).`);const i=s.methods,n=i?.[t];if(typeof n!="function")throw new TypeError(`[HyperCore] Protocol "${e}" has no method "${t}".`);return n.apply(i,[this,...r])}async send(e){const t=H(e),r=this.plugins;let o=e;if(r.length===0){const s=this.registry.get(e.protocol)?.sender;if(s)return this.runSender(s,e,t)}try{let s;for(let i=0;i<r.length;i++){const n=r[i];if(typeof n.onRequest!="function")continue;const c=await n.onRequest(o,this.pluginCtx,t);if(c!=null){if(y(c)){s=c;break}o=c,t.signal=o.signal}}if(!s){const i=await this.resolveRequestSender(o.protocol);s=await this.runSender(i,o,t)}return await this.runResponseHooks(s,o,t,r)}catch(s){for(let i=0;i<r.length;i++){const n=r[i];if(typeof n.onError!="function")continue;const c=await n.onError(s,o,this.pluginCtx,t);if(c!=null&&y(c))return c}throw s}}async resolveRequestSender(e){let t=this.registry.get(e);t||(t=await d(e),this.registerProtocol(t));const r=t.sender;if(!r)throw new p(`[HyperCore] Protocol "${e}" has no sender (client role).`);return r}async runResponseHooks(e,t,r,o){let s=e;for(let i=0;i<o.length;i++){const n=o[i];if(typeof n.onResponse!="function")continue;if(n.mode==="background"){Promise.resolve().then(()=>n.onResponse(s,t,this.pluginCtx,r)).catch(l=>this.reportBackgroundPluginError(l));continue}const c=await n.onResponse(s,t,this.pluginCtx,r);c!=null&&y(c)&&(s=c)}return s}reportBackgroundPluginError(e){const t=this.config.onError;if(typeof t=="function")try{t(e);return}catch(r){console.error("[HyperCore] Background error handler failed:",r)}console.error("[HyperCore] Background plugin error:",e)}async acquireTransport(e="rest"){if(this.isDestroyed)throw new p("[HyperCore] Cannot acquire transport on a destroyed core instance.");const t=this.transports.get(e);if(t)return t;let r=this.transportPromises.get(e);if(!r){r=this.resolveAndRetainTransport(e);let s;s=r.catch(i=>{throw this.transportPromises.get(e)===s&&this.transportPromises.delete(e),i}),this.transportPromises.set(e,s),r=s}const o=await r;if(this.isDestroyed)throw new p("[HyperCore] Core instance was destroyed while resolving transport.");return o}async resolveAndRetainTransport(e){const t=this.fixedTransport??await x(e,{customTransport:this.config.customTransport});if(!(typeof t.supports=="function"?t.supports(e):t.protocols?.includes(e)??!0))throw new p(`[HyperCore] Transport "${t.constructor.name}" does not support protocol "${e}".`);return this.retainResolvedTransport(e,t)}retainResolvedTransport(e,t){return this.retainedTransports.has(t)||(T(t),this.retainedTransports.add(t)),this.transports.set(e,t),t}async runSender(e,t,r){const o=this.transports.get(t.protocol)??await this.acquireTransport(t.protocol),s=e.prepare(t,r),i=await e.send(s,o,r);return e.parse(i,r)}async listen(e){const t=await this.acquireTransport(e.protocol);if(typeof t.listen!="function")throw new p(`[HyperCore] Transport "${t.constructor.name}" does not support listen() (server role).`);let r=this.registry.get(e.protocol);r||(r=await d(e.protocol),this.registerProtocol(r));const o=r.receiver;if(!o)throw new p(`[HyperCore] Protocol "${e.protocol}" has no receiver (server role).`);const s=e.handler,i=async c=>{const l=N(c),a=await o.receive(c,l),u=s?await s(a,l):await o.handle(a,l);return o.respond(u,l)},n=await t.listen({host:e.host,port:e.port,signal:e.signal,onRequest:i});if(this.isDestroyed)throw await n.close(),new p("[HyperCore] Core instance was destroyed while starting the server.");return this.servers.add(n),n}use(e){return(e.enabled?e.enabled(this.config):!0)?(e.setup?.(this.pluginCtx),this.plugins=[...this.plugins,e].sort((r,o)=>(v[r.phase??""]??0)-(v[o.phase??""]??0)),this):this}extend(e){const t=e.customTransport??this.fixedTransport??void 0,r=e.customTransport?void 0:this.transportPromises;return new HyperCore({...this.config,...e},t,r)}create(e){const t={...this.config};return delete t.customTransport,new HyperCore({...t,...e})}destroy(e=!0){return this.destroyPromise||(this.destroyPromise=this.performDestroy(e)),this.destroyPromise}async performDestroy(e){this.isDestroyed=!0;for(const r of this.servers)try{await r.close()}catch{}this.servers.clear(),await Promise.allSettled(this.transportPromises.values()),this.transportPromises.clear(),this.transports.clear();const t=[...this.retainedTransports];this.retainedTransports.clear();for(const r of t)b(r)>0||(S(r),e&&typeof r.close=="function"?await r.close():typeof r.destroy=="function"?await r.destroy():typeof r.close=="function"&&await r.close())}}
|
|
2
2
|
//# sourceMappingURL=HyperCore.js.map
|
package/Core/HyperCore.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Core/HyperCore.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n HyperClientOptions,\n HyperPlugin,\n HyperProtocol,\n HyperProtocols,\n HyperReceiver,\n HyperSender,\n HyperServerListenOptions,\n HyperTransport,\n IHyperCore,\n PluginContext,\n ProtocolRegistry,\n RequestContext,\n SenderProtocol,\n SendRequest,\n ServerRequestContext,\n TransportRequest,\n TransportResponse,\n TransportServer,\n UniversalResponse,\n} from \"@hyperttp/types\";\nimport { defaultCoreConfig } from \"../defaultConfig.js\";\nimport { KNOWN_PROTOCOLS, resolveProtocol } from \"../protocols/manager.js\";\nimport { evictCachedTransport, resolveTransport } from \"../transports/manager.js\";\nimport { HyperClientError } from \"../utils/errors.js\";\n\nlet requestCounter = 0;\nlet requestIdBase = Date.now().toString(36) + \"-\";\n\nconst PLUGIN_PHASE_ORDER: Readonly<Record<string, number>> = Object.freeze({\n START: 0,\n PREPARE: 1,\n CONTROL: 2,\n FORMAT: 3,\n NETWORK: 4,\n DATA: 5,\n});\n\n/**\n * @ru Генерирует уникальный идентификатор запроса без аллокаций на каждый вызов:\n * базовый таймстемп пересчитывается при переполнении счётчика, а уникальность\n * обеспечивает инкрементальный битовый счётчик (общий для всех ядер).\n * @en Generates a unique request identifier without per-call allocations:\n * the base timestamp is recalculated when the counter wraps around, and uniqueness\n * is ensured by an incremental bitwise counter (shared across all cores).\n * @returns A compact unique string identifier.\n */\nfunction createRequestId(): string {\n requestCounter = (requestCounter + 1) >>> 0;\n if (requestCounter === 0) {\n requestIdBase = Date.now().toString(36) + \"-\";\n }\n return requestIdBase + (requestCounter >>> 0).toString(36);\n}\n\n/**\n * @ru Счётчик активных удержаний транспорта. Позволяет нескольким ядрам\n * (например, через `extend()`) разделять один транспорт, закрывая его только\n * после освобождения последней ссылки.\n * @en Active transport hold count. Lets multiple cores (e.g. via `extend()`)\n * share one transport, closing it only after the last reference is released.\n */\nconst transportRefs = new WeakMap<HyperTransport, number>();\n\nfunction retainTransport(transport: HyperTransport): void {\n transportRefs.set(transport, (transportRefs.get(transport) ?? 0) + 1);\n}\n\nfunction releaseTransport(transport: HyperTransport): number {\n const next = (transportRefs.get(transport) ?? 1) - 1;\n if (next <= 0) {\n transportRefs.delete(transport);\n } else {\n transportRefs.set(transport, next);\n }\n return next;\n}\n\n/**\n * @ru Создаёт RequestContext на один цикл выполнения (prepare → send → parse).\n * `meta` и `state` инициализируются лениво при первом обращении, чтобы не\n * аллоцировать объекты для запросов, которые их не используют.\n * @en Creates a RequestContext for a single execution cycle (prepare → send → parse).\n * `meta` and `state` are initialized lazily on first access to avoid allocating\n * objects for requests that never use them.\n * @param req - The universal request being dispatched.\n * @returns A new RequestContext.\n */\nclass DefaultRequestContext implements RequestContext {\n public readonly requestId = createRequestId();\n public readonly startTime = performance.now();\n public readonly signal?: AbortSignal;\n private requestMeta?: Record<string, unknown>;\n private requestState?: Record<string, unknown>;\n\n constructor(signal?: AbortSignal) {\n this.signal = signal;\n }\n\n public get meta(): Record<string, unknown> {\n return (this.requestMeta ??= {});\n }\n\n public set meta(value: Record<string, unknown>) {\n this.requestMeta = value;\n }\n\n public get state(): Record<string, unknown> {\n return (this.requestState ??= {});\n }\n\n public set state(value: Record<string, unknown>) {\n this.requestState = value;\n }\n}\n\nfunction createRequestContext(req: SendRequest<unknown, string>): RequestContext {\n return new DefaultRequestContext(req.signal);\n}\n\n/**\n * @ru Создаёт ServerRequestContext на один серверный цикл (receive → handle → respond).\n * `meta` и `state` инициализируются лениво, как и в клиентском контексте.\n * @en Creates a ServerRequestContext for a single server cycle (receive → handle → respond).\n * `meta` and `state` are initialized lazily, like in the client context.\n * @param raw - The raw transport request being received.\n * @returns A new ServerRequestContext.\n */\nfunction createServerRequestContext(raw: TransportRequest): ServerRequestContext {\n return new DefaultRequestContext(raw.signal) as ServerRequestContext;\n}\n\n/**\n * @ru Проверяет, является ли значение UniversalResponse (а не SendRequest).\n * @en Checks whether the value is a UniversalResponse (rather than a SendRequest).\n * @param value - The value to inspect.\n * @returns True if the value carries response shape (data + status).\n */\nfunction isUniversalResponse(value: unknown): value is UniversalResponse {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"data\" in value &&\n \"status\" in value &&\n !(\"input\" in value)\n );\n}\n\n/**\n * @ru Внутренний реестр протоколов: хранит единые модули (Sender + Receiver).\n * @en Internal protocol registry: stores unified modules (Sender + Receiver).\n */\nclass DefaultProtocolRegistry implements ProtocolRegistry {\n private readonly protocols = new Map<SenderProtocol, HyperProtocol>();\n\n public register<P extends SenderProtocol>(\n protocol: HyperProtocol<unknown, unknown, unknown, unknown, P>,\n ): void {\n this.protocols.set(protocol.protocol, protocol);\n }\n\n public get<P extends SenderProtocol>(\n protocol: P,\n ): HyperProtocol<unknown, unknown, unknown, unknown, P> | undefined {\n return this.protocols.get(protocol) as\n | HyperProtocol<unknown, unknown, unknown, unknown, P>\n | undefined;\n }\n\n public has(protocol: SenderProtocol): boolean {\n return this.protocols.has(protocol);\n }\n\n public get size(): number {\n return this.protocols.size;\n }\n}\n\n// oxlint-disable-next-line no-unsafe-declaration-merging\nexport interface HyperCore extends HyperProtocols {}\n\n/**\n * @ru Универсальное ядро v2.0.0. Протокол-независимый диспетчер: регистрирует\n * единые модули протоколов (Sender + Receiver), выполняет клиентский цикл\n * prepare → send → parse и серверный цикл receive → handle → respond через\n * физический транспорт, а также прогоняет хуки плагинов.\n * @en Universal core v2.0.0. Protocol-agnostic dispatcher: registers unified\n * protocol modules (Sender + Receiver), runs the client cycle prepare → send → parse\n * and the server cycle receive → handle → respond through the physical transport,\n * and executes plugin hooks.\n */\nexport class HyperCore implements IHyperCore {\n public readonly config: HyperClientOptions;\n\n private readonly registry = new DefaultProtocolRegistry();\n private readonly pluginCtx: PluginContext;\n private readonly plugins: HyperPlugin[] = [];\n private readonly servers = new Set<TransportServer>();\n private readonly protocolNamespaces = new Set<string>();\n private readonly generatedFlatMethods = new Set<string>();\n private readonly transportPromises = new Map<SenderProtocol, Promise<HyperTransport>>();\n private readonly transports = new Map<SenderProtocol, HyperTransport>();\n private readonly retainedTransports = new Set<HyperTransport>();\n private readonly fixedTransport: HyperTransport | null;\n private destroyPromise: Promise<void> | null = null;\n private isDestroyed = false;\n\n constructor(\n config: Partial<HyperClientOptions> = {},\n transport?: HyperTransport,\n sharedTransportPromises?: ReadonlyMap<SenderProtocol, Promise<HyperTransport>>,\n ) {\n this.config = {\n ...defaultCoreConfig,\n ...config,\n retry: {\n ...defaultCoreConfig.retry,\n ...config.retry,\n },\n };\n this.fixedTransport = transport ?? null;\n if (transport) {\n retainTransport(transport);\n this.retainedTransports.add(transport);\n }\n if (sharedTransportPromises) {\n for (const [protocol, sharedPromise] of sharedTransportPromises) {\n this.transportPromises.set(\n protocol,\n sharedPromise.then((sharedTransport) =>\n this.retainResolvedTransport(protocol, sharedTransport),\n ),\n );\n }\n }\n this.pluginCtx = { config: this.config, core: this };\n\n const protocols = this.config.protocols;\n if (protocols) {\n for (let i = 0; i < protocols.length; i++) {\n this.registerProtocol(protocols[i]!);\n }\n }\n\n const senders = this.config.senders;\n if (senders) {\n for (let i = 0; i < senders.length; i++) {\n this.registerSender(senders[i]!);\n }\n }\n\n const customSender = this.config.customSender;\n if (customSender) {\n this.registerSender(customSender);\n }\n\n const receivers = this.config.receivers;\n if (receivers) {\n for (let i = 0; i < receivers.length; i++) {\n this.registerReceiver(receivers[i]!);\n }\n }\n\n const plugins = this.config.plugins;\n if (plugins) {\n for (let i = 0; i < plugins.length; i++) {\n const plugin = plugins[i]!;\n if (typeof plugin === \"string\") {\n throw new HyperClientError(\n `[HyperCore] Plugin module \"${plugin}\" cannot be loaded by the synchronous constructor. Import it and pass the plugin instance instead.`,\n );\n }\n this.use(plugin);\n }\n }\n\n const namespaces = this as unknown as Record<string, unknown>;\n for (let i = 0; i < KNOWN_PROTOCOLS.length; i++) {\n const protocol = KNOWN_PROTOCOLS[i]!;\n if (!this.registry.has(protocol) && namespaces[protocol] === undefined) {\n namespaces[protocol] = this.createLazyNamespace(protocol);\n this.protocolNamespaces.add(protocol);\n }\n }\n }\n\n /**\n * @ru Получает зарегистрированный модуль протокола (Sender + Receiver).\n * @en Gets a registered protocol module (Sender + Receiver).\n */\n public getProtocol<P extends SenderProtocol>(\n protocol: P,\n ): HyperProtocol<unknown, unknown, unknown, unknown, P> | undefined {\n return this.registry.get(protocol);\n }\n\n /**\n * @ru Получает зарегистрированный сендер протокола.\n * @en Gets a registered protocol sender.\n */\n public getSender<P extends SenderProtocol>(\n protocol: P,\n ): HyperSender<unknown, unknown, unknown, unknown, P> | undefined {\n return this.registry.get(protocol)?.sender;\n }\n\n /**\n * @ru Получает зарегистрированный ресивер протокола.\n * @en Gets a registered protocol receiver.\n */\n public getReceiver<P extends SenderProtocol>(\n protocol: P,\n ): HyperReceiver<unknown, unknown, unknown, unknown, P> | undefined {\n return this.registry.get(protocol)?.receiver;\n }\n\n /**\n * @ru Возвращает имя текущего транспорта.\n * @en Returns the name of the current transport.\n * @returns Transport constructor name.\n */\n public async getTransportName(): Promise<string> {\n const t = await this.acquireTransport();\n return t.constructor.name;\n }\n\n /**\n * @ru Возвращает имя сендера протокола (по умолчанию — \"rest\").\n * Протокол резолвится лениво, если ещё не зарегистрирован.\n * @en Returns the sender constructor name for a protocol (default \"rest\").\n * The protocol is resolved lazily if not registered yet.\n * @param protocol - The protocol to inspect.\n * @returns Sender constructor name.\n */\n public async getSenderName(protocol: SenderProtocol = \"rest\"): Promise<string> {\n let resolved = this.registry.get(protocol);\n if (!resolved) {\n resolved = await resolveProtocol(protocol);\n this.registerProtocol(resolved);\n }\n const sender = resolved.sender;\n if (!sender) {\n throw new HyperClientError(`[HyperCore] Protocol \"${protocol}\" has no sender (client role).`);\n }\n return sender.constructor.name;\n }\n\n /**\n * @ru Возвращает имя ресивера протокола (по умолчанию — \"rest\").\n * Протокол резолвится лениво, если ещё не зарегистрирован.\n * @en Returns the receiver constructor name for a protocol (default \"rest\").\n * The protocol is resolved lazily if not registered yet.\n * @param protocol - The protocol to inspect.\n * @returns Receiver constructor name.\n */\n public async getReceiverName(protocol: SenderProtocol = \"rest\"): Promise<string> {\n let resolved = this.registry.get(protocol);\n if (!resolved) {\n resolved = await resolveProtocol(protocol);\n this.registerProtocol(resolved);\n }\n const receiver = resolved.receiver;\n if (!receiver) {\n throw new HyperClientError(\n `[HyperCore] Protocol \"${protocol}\" has no receiver (server role).`,\n );\n }\n return receiver.constructor.name;\n }\n\n /**\n * @ru Возвращает имя модуля протокола (по умолчанию — \"rest\"): предпочитает\n * `name`, затем `constructor.name`, затем идентификатор протокола.\n * Протокол резолвится лениво, если ещё не зарегистрирован.\n * @en Returns the protocol module name (default \"rest\"): prefers `name`, then\n * `constructor.name`, then the protocol identifier.\n * The protocol is resolved lazily if not registered yet.\n * @param protocol - The protocol to inspect.\n * @returns The protocol module display name.\n */\n public async getProtocolName(protocol: SenderProtocol = \"rest\"): Promise<string> {\n let resolved = this.registry.get(protocol);\n if (!resolved) {\n resolved = await resolveProtocol(protocol);\n this.registerProtocol(resolved);\n }\n if (resolved.name) return resolved.name;\n const ctor = resolved.constructor;\n return ctor && ctor.name && ctor.name !== \"Object\" ? ctor.name : String(resolved.protocol);\n }\n\n /**\n * @ru Регистрирует единый модуль протокола и раскрывает методы его сендера\n * на ядре (например, `core.rest` для REST).\n * @en Registers a unified protocol module and exposes its sender methods on the\n * core (e.g., `core.rest` for REST).\n * @param protocol - The protocol module to register.\n * @returns This instance for chaining.\n */\n public registerProtocol<P extends SenderProtocol>(\n protocol: HyperProtocol<unknown, unknown, unknown, unknown, P>,\n ): this {\n const protocolName = String(protocol.protocol);\n const namespaces = this as unknown as Record<string, unknown>;\n const isReserved =\n protocolName === \"__proto__\" ||\n protocolName === \"prototype\" ||\n protocolName === \"constructor\" ||\n protocolName in HyperCore.prototype ||\n (protocolName in this && !this.protocolNamespaces.has(protocolName));\n\n if (isReserved) {\n throw new HyperClientError(\n `[HyperCore] Protocol name \"${protocolName}\" conflicts with the core API.`,\n );\n }\n\n this.registry.register(protocol);\n\n const methods = protocol.sender?.methods;\n if (methods && typeof methods === \"object\") {\n const namespace: Record<string, unknown> = Object.create(null);\n\n for (const name in methods) {\n const method = methods[name] as ((...args: unknown[]) => unknown) | undefined;\n if (typeof method !== \"function\") continue;\n\n const boundMethod = (...args: unknown[]) => method.apply(methods, [this, ...args]);\n namespace[name] = boundMethod;\n\n if (this.generatedFlatMethods.has(name)) {\n namespaces[name] = boundMethod;\n } else if (!(name in HyperCore.prototype) && !(name in this)) {\n namespaces[name] = boundMethod;\n this.generatedFlatMethods.add(name);\n }\n }\n\n namespaces[protocolName] = namespace;\n this.protocolNamespaces.add(protocolName);\n }\n\n return this;\n }\n\n /**\n * @ru Регистрирует сендер протокола, оборачивая его в модуль протокола.\n * Существующий ресивер того же протокола сохраняется.\n * @en Registers a protocol sender, wrapping it into a protocol module.\n * An existing receiver for the same protocol is preserved.\n * @param sender - The protocol sender to register.\n * @returns This instance for chaining.\n */\n public registerSender<P extends SenderProtocol>(\n sender: HyperSender<unknown, unknown, unknown, unknown, P>,\n ): this {\n const existing = this.registry.get(sender.protocol);\n return this.registerProtocol({\n protocol: sender.protocol,\n sender,\n receiver: existing?.receiver,\n });\n }\n\n /**\n * @ru Регистрирует ресивер протокола, оборачивая его в модуль протокола.\n * Существующий сендер того же протокола сохраняется.\n * @en Registers a protocol receiver, wrapping it into a protocol module.\n * An existing sender for the same protocol is preserved.\n * @param receiver - The protocol receiver to register.\n * @returns This instance for chaining.\n */\n public registerReceiver<P extends SenderProtocol>(\n receiver: HyperReceiver<unknown, unknown, unknown, unknown, P>,\n ): this {\n const existing = this.registry.get(receiver.protocol);\n return this.registerProtocol({\n protocol: receiver.protocol,\n sender: existing?.sender,\n receiver,\n });\n }\n\n /**\n * @ru Создаёт ленивый namespace методов протокола: методы доступны ещё до\n * регистрации протокола и резолвятся по требованию при первом вызове.\n * @en Creates a lazy protocol methods namespace: methods are reachable before\n * the protocol is registered and are resolved on first call.\n * @param protocol - The protocol to expose lazily.\n * @returns A Proxy that dispatches method calls to the resolved protocol sender.\n */\n private createLazyNamespace(protocol: SenderProtocol): Record<string, unknown> {\n const handler: ProxyHandler<Record<string, unknown>> = {\n get: (_target, name) => {\n if (typeof name !== \"string\" || name === \"then\") return undefined;\n return (...args: unknown[]) => this.dispatchLazyMethod(protocol, name, args);\n },\n };\n return new Proxy({}, handler);\n }\n\n /**\n * @ru Разрешает протокол по требованию и вызывает метод `methods`-поверхности\n * его сендера, биндя ядро первым аргументом.\n * @en Resolves the protocol on demand and calls a method on its sender\n * `methods` surface, binding the core as the first argument.\n * @param protocol - The protocol identifier.\n * @param name - The method name on the sender surface.\n * @param args - Arguments forwarded after the core instance.\n * @returns The result of the sender method call.\n */\n private async dispatchLazyMethod(\n protocol: SenderProtocol,\n name: string,\n args: unknown[],\n ): Promise<unknown> {\n let resolved = this.registry.get(protocol);\n if (!resolved) {\n resolved = await resolveProtocol(protocol);\n this.registerProtocol(resolved);\n }\n\n const sender = resolved.sender;\n if (!sender) {\n throw new HyperClientError(`[HyperCore] Protocol \"${protocol}\" has no sender (client role).`);\n }\n\n const methods = sender.methods as\n | Record<string, (...callArgs: unknown[]) => unknown>\n | undefined;\n const method = methods?.[name];\n if (typeof method !== \"function\") {\n throw new TypeError(`[HyperCore] Protocol \"${protocol}\" has no method \"${name}\".`);\n }\n return method.apply(methods, [this, ...args]);\n }\n\n /**\n * @ru Основной метод диспетчеризации: выбирает сендер по протоколу и выполняет\n * трёхфазный цикл с поддержкой плагинов.\n * @en Main dispatch method: resolves the sender by protocol and runs the three-phase\n * cycle with plugin support.\n * @param req - The universal request envelope.\n * @returns A promise resolving to the normalized universal response.\n */\n public async send<TInput = unknown, TOutput = unknown, P extends string = string>(\n req: SendRequest<TInput, P>,\n ): Promise<UniversalResponse<TOutput>> {\n const ctx = createRequestContext(req as SendRequest<unknown, string>);\n let currentReq = req as SendRequest<any, any>;\n\n if (this.plugins.length === 0) {\n const sender = this.registry.get(req.protocol)?.sender;\n if (sender) {\n return this.runSender<TInput, TOutput>(sender, req as SendRequest<TInput, string>, ctx);\n }\n }\n\n try {\n let response: UniversalResponse<TOutput> | undefined;\n\n for (let i = 0; i < this.plugins.length; i++) {\n const plugin = this.plugins[i]!;\n if (typeof plugin.onRequest !== \"function\") continue;\n\n const result = await plugin.onRequest(currentReq, this.pluginCtx, ctx);\n if (result == null) continue;\n\n if (isUniversalResponse(result)) {\n response = result as UniversalResponse<TOutput>;\n break;\n }\n\n currentReq = result as SendRequest<any, any>;\n (ctx as { signal?: AbortSignal }).signal = currentReq.signal;\n }\n\n if (!response) {\n const sender = await this.resolveRequestSender(currentReq.protocol);\n response = await this.runSender<unknown, TOutput>(sender, currentReq, ctx);\n }\n\n return await this.runResponseHooks(response, currentReq, ctx);\n } catch (err) {\n for (let i = 0; i < this.plugins.length; i++) {\n const plugin = this.plugins[i]!;\n if (typeof plugin.onError !== \"function\") continue;\n\n const recovered = await plugin.onError(err, currentReq, this.pluginCtx, ctx);\n if (recovered != null && isUniversalResponse(recovered)) {\n return recovered as UniversalResponse<TOutput>;\n }\n }\n throw err;\n }\n }\n\n private async resolveRequestSender(\n protocol: SenderProtocol,\n ): Promise<HyperSender<any, any, any, any>> {\n let resolved = this.registry.get(protocol);\n if (!resolved) {\n resolved = await resolveProtocol(protocol);\n this.registerProtocol(resolved);\n }\n\n const sender = resolved.sender;\n if (!sender) {\n throw new HyperClientError(`[HyperCore] Protocol \"${protocol}\" has no sender (client role).`);\n }\n return sender;\n }\n\n private async runResponseHooks<TOutput>(\n initialResponse: UniversalResponse<TOutput>,\n req: SendRequest<any, any>,\n ctx: RequestContext,\n ): Promise<UniversalResponse<TOutput>> {\n let response = initialResponse;\n\n for (let i = 0; i < this.plugins.length; i++) {\n const plugin = this.plugins[i]!;\n if (typeof plugin.onResponse !== \"function\") continue;\n\n if (plugin.mode === \"background\") {\n void Promise.resolve()\n .then(() => plugin.onResponse!(response, req, this.pluginCtx, ctx))\n .catch((err: unknown) => this.reportBackgroundPluginError(err));\n continue;\n }\n\n const result = await plugin.onResponse(response, req, this.pluginCtx, ctx);\n if (result != null && isUniversalResponse(result)) {\n response = result as UniversalResponse<TOutput>;\n }\n }\n\n return response;\n }\n\n private reportBackgroundPluginError(err: unknown): void {\n const customOnError = (this.config as Record<string, unknown>).onError;\n if (typeof customOnError === \"function\") {\n try {\n (customOnError as (error: unknown) => void)(err);\n return;\n } catch (handlerError) {\n console.error(\"[HyperCore] Background error handler failed:\", handlerError);\n }\n }\n console.error(\"[HyperCore] Background plugin error:\", err);\n }\n\n /**\n * @ru Атомарно получает транспорт для конкретного протокола и удерживает\n * каждый физический экземпляр ровно один раз за время жизни ядра.\n * @en Atomically acquires a transport for a protocol and retains each physical\n * instance exactly once for the lifetime of this core.\n */\n private async acquireTransport(protocol: SenderProtocol = \"rest\"): Promise<HyperTransport> {\n if (this.isDestroyed) {\n throw new HyperClientError(\n \"[HyperCore] Cannot acquire transport on a destroyed core instance.\",\n );\n }\n\n const existing = this.transports.get(protocol);\n if (existing) return existing;\n\n let pending = this.transportPromises.get(protocol);\n if (!pending) {\n pending = this.resolveAndRetainTransport(protocol);\n this.transportPromises.set(protocol, pending);\n }\n\n const transport = await pending;\n if (this.isDestroyed) {\n throw new HyperClientError(\n \"[HyperCore] Core instance was destroyed while resolving transport.\",\n );\n }\n\n return transport;\n }\n\n private async resolveAndRetainTransport(protocol: SenderProtocol): Promise<HyperTransport> {\n const transport =\n this.fixedTransport ??\n (await resolveTransport(protocol, { customTransport: this.config.customTransport }));\n const supportsProtocol =\n typeof transport.supports === \"function\"\n ? transport.supports(protocol)\n : (transport.protocols?.includes(protocol) ?? true);\n\n if (!supportsProtocol) {\n throw new HyperClientError(\n `[HyperCore] Transport \"${transport.constructor.name}\" does not support protocol \"${protocol}\".`,\n );\n }\n\n return this.retainResolvedTransport(protocol, transport);\n }\n\n private retainResolvedTransport(\n protocol: SenderProtocol,\n transport: HyperTransport,\n ): HyperTransport {\n if (!this.retainedTransports.has(transport)) {\n retainTransport(transport);\n this.retainedTransports.add(transport);\n }\n\n this.transports.set(protocol, transport);\n return transport;\n }\n\n /**\n * @ru Выполняет ядро цикла запроса: prepare → send → parse через физический\n * транспорт. Транспорт получается через `acquireTransport()`.\n * @en Runs the core request cycle: prepare → send → parse through the physical\n * transport. The transport is acquired via `acquireTransport()`.\n * @param sender - The resolved protocol sender.\n * @param req - The (possibly plugin-modified) universal request.\n * @param ctx - The per-request execution context.\n * @returns The normalized universal response.\n */\n private async runSender<TInput, TOutput>(\n sender: HyperSender<any, any, any, any>,\n req: SendRequest<TInput, string>,\n ctx: RequestContext,\n ): Promise<UniversalResponse<TOutput>> {\n const transport =\n this.transports.get(req.protocol) ?? (await this.acquireTransport(req.protocol));\n const prepared = sender.prepare(req, ctx);\n const raw = await sender.send(prepared, transport, ctx);\n return sender.parse(raw, ctx) as UniversalResponse<TOutput>;\n }\n\n /**\n * @ru Запускает сервер для указанного протокола: связывает транспорт, ресивер и\n * application handler в цепочку receive → handle → respond.\n * @en Starts a server for the given protocol, wiring transport, receiver, and\n * application handler into the receive → handle → respond pipeline.\n * @template P - The protocol identifier.\n * @param options - The server listen options.\n * @returns A promise resolving to the transport server handle.\n */\n public async listen<P extends SenderProtocol = SenderProtocol>(\n options: HyperServerListenOptions<P>,\n ): Promise<TransportServer> {\n const transport = await this.acquireTransport(options.protocol);\n\n if (typeof transport.listen !== \"function\") {\n throw new HyperClientError(\n `[HyperCore] Transport \"${transport.constructor.name}\" does not support listen() (server role).`,\n );\n }\n\n let resolved = this.registry.get(options.protocol);\n if (!resolved) {\n resolved = await resolveProtocol(options.protocol);\n this.registerProtocol(resolved);\n }\n\n const receiver = resolved.receiver as\n | HyperReceiver<unknown, unknown, TransportRequest, TransportResponse, P>\n | undefined;\n if (!receiver) {\n throw new HyperClientError(\n `[HyperCore] Protocol \"${options.protocol}\" has no receiver (server role).`,\n );\n }\n\n const handler = options.handler as\n | ((request: unknown, ctx: ServerRequestContext) => unknown)\n | undefined;\n\n const onRequest = async (raw: TransportRequest): Promise<TransportResponse> => {\n const ctx = createServerRequestContext(raw);\n const request = await receiver.receive(raw, ctx);\n const response = handler ? await handler(request, ctx) : await receiver.handle(request, ctx);\n return receiver.respond(response, ctx);\n };\n\n const server = await transport.listen!({\n host: options.host,\n port: options.port,\n signal: options.signal,\n onRequest,\n });\n\n if (this.isDestroyed) {\n await server.close();\n throw new HyperClientError(\n \"[HyperCore] Core instance was destroyed while starting the server.\",\n );\n }\n\n this.servers.add(server);\n return server;\n }\n\n /**\n * @ru Регистрирует плагин. Пропускает отключённые плагины.\n * @en Registers a plugin. Skips disabled plugins.\n * @param plugin - The plugin instance to register.\n * @returns This instance for chaining.\n */\n public use(plugin: HyperPlugin): this {\n const enabled = plugin.enabled ? plugin.enabled(this.config) : true;\n if (!enabled) return this;\n\n plugin.setup?.(this.pluginCtx);\n this.plugins.push(plugin);\n this.plugins.sort(\n (a, b) => (PLUGIN_PHASE_ORDER[a.phase ?? \"\"] ?? 0) - (PLUGIN_PHASE_ORDER[b.phase ?? \"\"] ?? 0),\n );\n return this;\n }\n\n /**\n * @ru Создаёт новый экземпляр ядра с расширенной/переопределённой конфигурацией,\n * переиспользуя текущий транспорт.\n * @en Creates a new core instance with extended/overridden configuration,\n * reusing the current transport.\n * @param options - Partial configuration overrides.\n * @returns A new IHyperCore instance.\n */\n public extend(options: Partial<HyperClientOptions>): IHyperCore {\n const transport = options.customTransport ?? this.fixedTransport ?? undefined;\n const sharedTransports = options.customTransport ? undefined : this.transportPromises;\n return new HyperCore({ ...this.config, ...options }, transport, sharedTransports);\n }\n\n /**\n * @ru Создаёт полностью независимый экземпляр ядра на основе текущей\n * конфигурации: не переиспользует текущий транспорт и по умолчанию не\n * наследует `customTransport`.\n * @en Creates a fully independent core instance based on the current config:\n * it does not reuse the current transport and does not inherit\n * `customTransport` by default.\n * @param options - Partial configuration overrides.\n * @returns A new IHyperCore instance.\n */\n public create(options: Partial<HyperClientOptions>): IHyperCore {\n const base: Partial<HyperClientOptions> = { ...this.config };\n delete base.customTransport;\n return new HyperCore({ ...base, ...options });\n }\n\n /**\n * @ru Завершает работу ядра и освобождает ресурсы: закрывает активные серверы,\n * затем освобождает удержание транспорта.\n * @en Shuts down the core and releases resources: closes active servers, then\n * releases the transport hold.\n * @param graceful - If true, waits for active requests to complete.\n * @returns Promise that resolves when shutdown is complete.\n */\n public destroy(graceful = true): Promise<void> {\n if (!this.destroyPromise) {\n this.destroyPromise = this.performDestroy(graceful);\n }\n return this.destroyPromise;\n }\n\n private async performDestroy(graceful: boolean): Promise<void> {\n this.isDestroyed = true;\n\n for (const server of this.servers) {\n try {\n await server.close();\n } catch {\n // Continue releasing the remaining resources.\n }\n }\n this.servers.clear();\n\n await Promise.allSettled(this.transportPromises.values());\n this.transportPromises.clear();\n this.transports.clear();\n\n const transports = [...this.retainedTransports];\n this.retainedTransports.clear();\n\n for (const transport of transports) {\n if (releaseTransport(transport) > 0) continue;\n\n evictCachedTransport(transport);\n\n if (graceful && typeof transport.close === \"function\") {\n await transport.close();\n } else if (typeof transport.destroy === \"function\") {\n await transport.destroy();\n } else if (typeof transport.close === \"function\") {\n await transport.close();\n }\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["defaultCoreConfig", "KNOWN_PROTOCOLS", "resolveProtocol", "evictCachedTransport", "resolveTransport", "HyperClientError", "requestCounter", "requestIdBase", "PLUGIN_PHASE_ORDER", "createRequestId", "transportRefs", "retainTransport", "transport", "releaseTransport", "next", "DefaultRequestContext", "signal", "value", "createRequestContext", "req", "createServerRequestContext", "raw", "isUniversalResponse", "DefaultProtocolRegistry", "protocol", "config", "sharedTransportPromises", "sharedPromise", "sharedTransport", "protocols", "senders", "customSender", "receivers", "plugins", "plugin", "namespaces", "resolved", "sender", "receiver", "ctor", "protocolName", "methods", "namespace", "name", "method", "boundMethod", "args", "existing", "handler", "_target", "ctx", "currentReq", "response", "
|
|
4
|
+
"sourcesContent": ["import type {\n HyperClientOptions,\n HyperPlugin,\n HyperProtocol,\n HyperProtocols,\n HyperReceiver,\n HyperSender,\n HyperServerListenOptions,\n HyperTransport,\n IHyperCore,\n PluginContext,\n ProtocolRegistry,\n RequestContext,\n SenderProtocol,\n SendRequest,\n ServerRequestContext,\n TransportRequest,\n TransportResponse,\n TransportServer,\n UniversalResponse,\n} from \"@hyperttp/types\";\nimport { defaultCoreConfig } from \"../defaultConfig.js\";\nimport { KNOWN_PROTOCOLS, resolveProtocol } from \"../protocols/manager.js\";\nimport { evictCachedTransport, resolveTransport } from \"../transports/manager.js\";\nimport { HyperClientError } from \"../utils/errors.js\";\n\nlet requestCounter = 0;\nlet requestIdBase = Date.now().toString(36) + \"-\";\n\nconst PLUGIN_PHASE_ORDER: Readonly<Record<string, number>> = Object.freeze({\n START: 0,\n PREPARE: 1,\n CONTROL: 2,\n FORMAT: 3,\n NETWORK: 4,\n DATA: 5,\n});\n\n/**\n * @ru Генерирует уникальный идентификатор запроса без аллокаций на каждый вызов:\n * базовый таймстемп пересчитывается при переполнении счётчика, а уникальность\n * обеспечивает инкрементальный битовый счётчик (общий для всех ядер).\n * @en Generates a unique request identifier without per-call allocations:\n * the base timestamp is recalculated when the counter wraps around, and uniqueness\n * is ensured by an incremental bitwise counter (shared across all cores).\n * @returns A compact unique string identifier.\n */\nfunction createRequestId(): string {\n requestCounter = (requestCounter + 1) >>> 0;\n if (requestCounter === 0) {\n requestIdBase = Date.now().toString(36) + \"-\";\n }\n return requestIdBase + (requestCounter >>> 0).toString(36);\n}\n\n/**\n * @ru Счётчик активных удержаний транспорта. Позволяет нескольким ядрам\n * (например, через `extend()`) разделять один транспорт, закрывая его только\n * после освобождения последней ссылки.\n * @en Active transport hold count. Lets multiple cores (e.g. via `extend()`)\n * share one transport, closing it only after the last reference is released.\n */\nconst transportRefs = new WeakMap<HyperTransport, number>();\n\nfunction retainTransport(transport: HyperTransport): void {\n transportRefs.set(transport, (transportRefs.get(transport) ?? 0) + 1);\n}\n\nfunction releaseTransport(transport: HyperTransport): number {\n const next = (transportRefs.get(transport) ?? 1) - 1;\n if (next <= 0) {\n transportRefs.delete(transport);\n } else {\n transportRefs.set(transport, next);\n }\n return next;\n}\n\n/**\n * @ru Создаёт RequestContext на один цикл выполнения (prepare → send → parse).\n * `meta` и `state` инициализируются лениво при первом обращении, чтобы не\n * аллоцировать объекты для запросов, которые их не используют.\n * @en Creates a RequestContext for a single execution cycle (prepare → send → parse).\n * `meta` and `state` are initialized lazily on first access to avoid allocating\n * objects for requests that never use them.\n * @param req - The universal request being dispatched.\n * @returns A new RequestContext.\n */\nclass DefaultRequestContext implements RequestContext {\n public readonly requestId = createRequestId();\n public readonly startTime = performance.now();\n public readonly signal?: AbortSignal;\n private requestMeta?: Record<string, unknown>;\n private requestState?: Record<string, unknown>;\n\n constructor(signal?: AbortSignal) {\n this.signal = signal;\n }\n\n public get meta(): Record<string, unknown> {\n return (this.requestMeta ??= {});\n }\n\n public set meta(value: Record<string, unknown>) {\n this.requestMeta = value;\n }\n\n public get state(): Record<string, unknown> {\n return (this.requestState ??= {});\n }\n\n public set state(value: Record<string, unknown>) {\n this.requestState = value;\n }\n}\n\nfunction createRequestContext(req: SendRequest<unknown, string>): RequestContext {\n return new DefaultRequestContext(req.signal);\n}\n\n/**\n * @ru Создаёт ServerRequestContext на один серверный цикл (receive → handle → respond).\n * `meta` и `state` инициализируются лениво, как и в клиентском контексте.\n * @en Creates a ServerRequestContext for a single server cycle (receive → handle → respond).\n * `meta` and `state` are initialized lazily, like in the client context.\n * @param raw - The raw transport request being received.\n * @returns A new ServerRequestContext.\n */\nfunction createServerRequestContext(raw: TransportRequest): ServerRequestContext {\n return new DefaultRequestContext(raw.signal) as ServerRequestContext;\n}\n\n/**\n * @ru Проверяет, является ли значение UniversalResponse (а не SendRequest).\n * @en Checks whether the value is a UniversalResponse (rather than a SendRequest).\n * @param value - The value to inspect.\n * @returns True if the value carries response shape (data + status).\n */\nfunction isUniversalResponse(value: unknown): value is UniversalResponse {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"data\" in value &&\n \"status\" in value &&\n !(\"input\" in value)\n );\n}\n\n/**\n * @ru Внутренний реестр протоколов: хранит единые модули (Sender + Receiver).\n * @en Internal protocol registry: stores unified modules (Sender + Receiver).\n */\nclass DefaultProtocolRegistry implements ProtocolRegistry {\n private readonly protocols = new Map<SenderProtocol, HyperProtocol>();\n\n public register<P extends SenderProtocol>(\n protocol: HyperProtocol<unknown, unknown, unknown, unknown, P>,\n ): void {\n this.protocols.set(protocol.protocol, protocol);\n }\n\n public get<P extends SenderProtocol>(\n protocol: P,\n ): HyperProtocol<unknown, unknown, unknown, unknown, P> | undefined {\n return this.protocols.get(protocol) as\n | HyperProtocol<unknown, unknown, unknown, unknown, P>\n | undefined;\n }\n\n public has(protocol: SenderProtocol): boolean {\n return this.protocols.has(protocol);\n }\n\n public get size(): number {\n return this.protocols.size;\n }\n}\n\n// oxlint-disable-next-line no-unsafe-declaration-merging\nexport interface HyperCore extends HyperProtocols {}\n\n/**\n * @ru Универсальное ядро v2.0.0. Протокол-независимый диспетчер: регистрирует\n * единые модули протоколов (Sender + Receiver), выполняет клиентский цикл\n * prepare → send → parse и серверный цикл receive → handle → respond через\n * физический транспорт, а также прогоняет хуки плагинов.\n * @en Universal core v2.0.0. Protocol-agnostic dispatcher: registers unified\n * protocol modules (Sender + Receiver), runs the client cycle prepare → send → parse\n * and the server cycle receive → handle → respond through the physical transport,\n * and executes plugin hooks.\n */\nexport class HyperCore implements IHyperCore {\n public readonly config: HyperClientOptions;\n\n private readonly registry = new DefaultProtocolRegistry();\n private readonly pluginCtx: PluginContext;\n private plugins: HyperPlugin[] = [];\n private readonly servers = new Set<TransportServer>();\n private readonly protocolNamespaces = new Set<string>();\n private readonly generatedFlatMethods = new Set<string>();\n private readonly transportPromises = new Map<SenderProtocol, Promise<HyperTransport>>();\n private readonly transports = new Map<SenderProtocol, HyperTransport>();\n private readonly retainedTransports = new Set<HyperTransport>();\n private readonly fixedTransport: HyperTransport | null;\n private destroyPromise: Promise<void> | null = null;\n private isDestroyed = false;\n\n constructor(\n config: Partial<HyperClientOptions> = {},\n transport?: HyperTransport,\n sharedTransportPromises?: ReadonlyMap<SenderProtocol, Promise<HyperTransport>>,\n ) {\n this.config = {\n ...defaultCoreConfig,\n ...config,\n retry: {\n ...defaultCoreConfig.retry,\n ...config.retry,\n },\n };\n this.fixedTransport = transport ?? null;\n if (transport) {\n retainTransport(transport);\n this.retainedTransports.add(transport);\n }\n if (sharedTransportPromises) {\n for (const [protocol, sharedPromise] of sharedTransportPromises) {\n this.transportPromises.set(\n protocol,\n sharedPromise.then((sharedTransport) =>\n this.retainResolvedTransport(protocol, sharedTransport),\n ),\n );\n }\n }\n this.pluginCtx = { config: this.config, core: this };\n\n const protocols = this.config.protocols;\n if (protocols) {\n for (let i = 0; i < protocols.length; i++) {\n this.registerProtocol(protocols[i]!);\n }\n }\n\n const senders = this.config.senders;\n if (senders) {\n for (let i = 0; i < senders.length; i++) {\n this.registerSender(senders[i]!);\n }\n }\n\n const customSender = this.config.customSender;\n if (customSender) {\n this.registerSender(customSender);\n }\n\n const receivers = this.config.receivers;\n if (receivers) {\n for (let i = 0; i < receivers.length; i++) {\n this.registerReceiver(receivers[i]!);\n }\n }\n\n const plugins = this.config.plugins;\n if (plugins) {\n for (let i = 0; i < plugins.length; i++) {\n const plugin = plugins[i]!;\n if (typeof plugin === \"string\") {\n throw new HyperClientError(\n `[HyperCore] Plugin module \"${plugin}\" cannot be loaded by the synchronous constructor. Import it and pass the plugin instance instead.`,\n );\n }\n this.use(plugin);\n }\n }\n\n const namespaces = this as unknown as Record<string, unknown>;\n for (let i = 0; i < KNOWN_PROTOCOLS.length; i++) {\n const protocol = KNOWN_PROTOCOLS[i]!;\n if (!this.registry.has(protocol) && namespaces[protocol] === undefined) {\n namespaces[protocol] = this.createLazyNamespace(protocol);\n this.protocolNamespaces.add(protocol);\n }\n }\n }\n\n /**\n * @ru Получает зарегистрированный модуль протокола (Sender + Receiver).\n * @en Gets a registered protocol module (Sender + Receiver).\n */\n public getProtocol<P extends SenderProtocol>(\n protocol: P,\n ): HyperProtocol<unknown, unknown, unknown, unknown, P> | undefined {\n return this.registry.get(protocol);\n }\n\n /**\n * @ru Получает зарегистрированный сендер протокола.\n * @en Gets a registered protocol sender.\n */\n public getSender<P extends SenderProtocol>(\n protocol: P,\n ): HyperSender<unknown, unknown, unknown, unknown, P> | undefined {\n return this.registry.get(protocol)?.sender;\n }\n\n /**\n * @ru Получает зарегистрированный ресивер протокола.\n * @en Gets a registered protocol receiver.\n */\n public getReceiver<P extends SenderProtocol>(\n protocol: P,\n ): HyperReceiver<unknown, unknown, unknown, unknown, P> | undefined {\n return this.registry.get(protocol)?.receiver;\n }\n\n /**\n * @ru Возвращает имя текущего транспорта.\n * @en Returns the name of the current transport.\n * @returns Transport constructor name.\n */\n public async getTransportName(): Promise<string> {\n const t = await this.acquireTransport();\n return t.constructor.name;\n }\n\n /**\n * @ru Возвращает имя сендера протокола (по умолчанию — \"rest\").\n * Протокол резолвится лениво, если ещё не зарегистрирован.\n * @en Returns the sender constructor name for a protocol (default \"rest\").\n * The protocol is resolved lazily if not registered yet.\n * @param protocol - The protocol to inspect.\n * @returns Sender constructor name.\n */\n public async getSenderName(protocol: SenderProtocol = \"rest\"): Promise<string> {\n let resolved = this.registry.get(protocol);\n if (!resolved) {\n resolved = await resolveProtocol(protocol);\n this.registerProtocol(resolved);\n }\n const sender = resolved.sender;\n if (!sender) {\n throw new HyperClientError(`[HyperCore] Protocol \"${protocol}\" has no sender (client role).`);\n }\n return sender.constructor.name;\n }\n\n /**\n * @ru Возвращает имя ресивера протокола (по умолчанию — \"rest\").\n * Протокол резолвится лениво, если ещё не зарегистрирован.\n * @en Returns the receiver constructor name for a protocol (default \"rest\").\n * The protocol is resolved lazily if not registered yet.\n * @param protocol - The protocol to inspect.\n * @returns Receiver constructor name.\n */\n public async getReceiverName(protocol: SenderProtocol = \"rest\"): Promise<string> {\n let resolved = this.registry.get(protocol);\n if (!resolved) {\n resolved = await resolveProtocol(protocol);\n this.registerProtocol(resolved);\n }\n const receiver = resolved.receiver;\n if (!receiver) {\n throw new HyperClientError(\n `[HyperCore] Protocol \"${protocol}\" has no receiver (server role).`,\n );\n }\n return receiver.constructor.name;\n }\n\n /**\n * @ru Возвращает имя модуля протокола (по умолчанию — \"rest\"): предпочитает\n * `name`, затем `constructor.name`, затем идентификатор протокола.\n * Протокол резолвится лениво, если ещё не зарегистрирован.\n * @en Returns the protocol module name (default \"rest\"): prefers `name`, then\n * `constructor.name`, then the protocol identifier.\n * The protocol is resolved lazily if not registered yet.\n * @param protocol - The protocol to inspect.\n * @returns The protocol module display name.\n */\n public async getProtocolName(protocol: SenderProtocol = \"rest\"): Promise<string> {\n let resolved = this.registry.get(protocol);\n if (!resolved) {\n resolved = await resolveProtocol(protocol);\n this.registerProtocol(resolved);\n }\n if (resolved.name) return resolved.name;\n const ctor = resolved.constructor;\n return ctor && ctor.name && ctor.name !== \"Object\" ? ctor.name : String(resolved.protocol);\n }\n\n /**\n * @ru Регистрирует единый модуль протокола и раскрывает методы его сендера\n * на ядре (например, `core.rest` для REST).\n * @en Registers a unified protocol module and exposes its sender methods on the\n * core (e.g., `core.rest` for REST).\n * @param protocol - The protocol module to register.\n * @returns This instance for chaining.\n */\n public registerProtocol<P extends SenderProtocol>(\n protocol: HyperProtocol<unknown, unknown, unknown, unknown, P>,\n ): this {\n const protocolName = String(protocol.protocol);\n const namespaces = this as unknown as Record<string, unknown>;\n const isReserved =\n protocolName === \"__proto__\" ||\n protocolName === \"prototype\" ||\n protocolName === \"constructor\" ||\n protocolName in HyperCore.prototype ||\n (protocolName in this && !this.protocolNamespaces.has(protocolName));\n\n if (isReserved) {\n throw new HyperClientError(\n `[HyperCore] Protocol name \"${protocolName}\" conflicts with the core API.`,\n );\n }\n\n this.registry.register(protocol);\n\n const methods = protocol.sender?.methods;\n if (methods && typeof methods === \"object\") {\n const namespace: Record<string, unknown> = Object.create(null);\n\n for (const name in methods) {\n if (!Object.hasOwn(methods, name)) continue;\n\n const method = methods[name] as ((...args: unknown[]) => unknown) | undefined;\n if (typeof method !== \"function\") continue;\n\n const boundMethod = (...args: unknown[]) => method.apply(methods, [this, ...args]);\n namespace[name] = boundMethod;\n\n if (this.generatedFlatMethods.has(name)) {\n namespaces[name] = boundMethod;\n } else if (!(name in HyperCore.prototype) && !(name in this)) {\n namespaces[name] = boundMethod;\n this.generatedFlatMethods.add(name);\n }\n }\n\n namespaces[protocolName] = namespace;\n this.protocolNamespaces.add(protocolName);\n }\n\n return this;\n }\n\n /**\n * @ru Регистрирует сендер протокола, оборачивая его в модуль протокола.\n * Существующий ресивер того же протокола сохраняется.\n * @en Registers a protocol sender, wrapping it into a protocol module.\n * An existing receiver for the same protocol is preserved.\n * @param sender - The protocol sender to register.\n * @returns This instance for chaining.\n */\n public registerSender<P extends SenderProtocol>(\n sender: HyperSender<unknown, unknown, unknown, unknown, P>,\n ): this {\n const existing = this.registry.get(sender.protocol);\n return this.registerProtocol({\n protocol: sender.protocol,\n sender,\n receiver: existing?.receiver,\n });\n }\n\n /**\n * @ru Регистрирует ресивер протокола, оборачивая его в модуль протокола.\n * Существующий сендер того же протокола сохраняется.\n * @en Registers a protocol receiver, wrapping it into a protocol module.\n * An existing sender for the same protocol is preserved.\n * @param receiver - The protocol receiver to register.\n * @returns This instance for chaining.\n */\n public registerReceiver<P extends SenderProtocol>(\n receiver: HyperReceiver<unknown, unknown, unknown, unknown, P>,\n ): this {\n const existing = this.registry.get(receiver.protocol);\n return this.registerProtocol({\n protocol: receiver.protocol,\n sender: existing?.sender,\n receiver,\n });\n }\n\n /**\n * @ru Создаёт ленивый namespace методов протокола: методы доступны ещё до\n * регистрации протокола и резолвятся по требованию при первом вызове.\n * @en Creates a lazy protocol methods namespace: methods are reachable before\n * the protocol is registered and are resolved on first call.\n * @param protocol - The protocol to expose lazily.\n * @returns A Proxy that dispatches method calls to the resolved protocol sender.\n */\n private createLazyNamespace(protocol: SenderProtocol): Record<string, unknown> {\n const handler: ProxyHandler<Record<string, unknown>> = {\n get: (_target, name) => {\n if (typeof name !== \"string\" || name === \"then\") return undefined;\n return (...args: unknown[]) => this.dispatchLazyMethod(protocol, name, args);\n },\n };\n return new Proxy({}, handler);\n }\n\n /**\n * @ru Разрешает протокол по требованию и вызывает метод `methods`-поверхности\n * его сендера, биндя ядро первым аргументом.\n * @en Resolves the protocol on demand and calls a method on its sender\n * `methods` surface, binding the core as the first argument.\n * @param protocol - The protocol identifier.\n * @param name - The method name on the sender surface.\n * @param args - Arguments forwarded after the core instance.\n * @returns The result of the sender method call.\n */\n private async dispatchLazyMethod(\n protocol: SenderProtocol,\n name: string,\n args: unknown[],\n ): Promise<unknown> {\n let resolved = this.registry.get(protocol);\n if (!resolved) {\n resolved = await resolveProtocol(protocol);\n this.registerProtocol(resolved);\n }\n\n const sender = resolved.sender;\n if (!sender) {\n throw new HyperClientError(`[HyperCore] Protocol \"${protocol}\" has no sender (client role).`);\n }\n\n const methods = sender.methods as\n | Record<string, (...callArgs: unknown[]) => unknown>\n | undefined;\n const method = methods?.[name];\n if (typeof method !== \"function\") {\n throw new TypeError(`[HyperCore] Protocol \"${protocol}\" has no method \"${name}\".`);\n }\n return method.apply(methods, [this, ...args]);\n }\n\n /**\n * @ru Основной метод диспетчеризации: выбирает сендер по протоколу и выполняет\n * трёхфазный цикл с поддержкой плагинов.\n * @en Main dispatch method: resolves the sender by protocol and runs the three-phase\n * cycle with plugin support.\n * @param req - The universal request envelope.\n * @returns A promise resolving to the normalized universal response.\n */\n public async send<TInput = unknown, TOutput = unknown, P extends string = string>(\n req: SendRequest<TInput, P>,\n ): Promise<UniversalResponse<TOutput>> {\n const ctx = createRequestContext(req as SendRequest<unknown, string>);\n const plugins = this.plugins;\n let currentReq = req as SendRequest<any, any>;\n\n if (plugins.length === 0) {\n const sender = this.registry.get(req.protocol)?.sender;\n if (sender) {\n return this.runSender<TInput, TOutput>(sender, req as SendRequest<TInput, string>, ctx);\n }\n }\n\n try {\n let response: UniversalResponse<TOutput> | undefined;\n\n for (let i = 0; i < plugins.length; i++) {\n const plugin = plugins[i]!;\n if (typeof plugin.onRequest !== \"function\") continue;\n\n const result = await plugin.onRequest(currentReq, this.pluginCtx, ctx);\n if (result == null) continue;\n\n if (isUniversalResponse(result)) {\n response = result as UniversalResponse<TOutput>;\n break;\n }\n\n currentReq = result as SendRequest<any, any>;\n (ctx as { signal?: AbortSignal }).signal = currentReq.signal;\n }\n\n if (!response) {\n const sender = await this.resolveRequestSender(currentReq.protocol);\n response = await this.runSender<unknown, TOutput>(sender, currentReq, ctx);\n }\n\n return await this.runResponseHooks(response, currentReq, ctx, plugins);\n } catch (err) {\n for (let i = 0; i < plugins.length; i++) {\n const plugin = plugins[i]!;\n if (typeof plugin.onError !== \"function\") continue;\n\n const recovered = await plugin.onError(err, currentReq, this.pluginCtx, ctx);\n if (recovered != null && isUniversalResponse(recovered)) {\n return recovered as UniversalResponse<TOutput>;\n }\n }\n throw err;\n }\n }\n\n private async resolveRequestSender(\n protocol: SenderProtocol,\n ): Promise<HyperSender<any, any, any, any>> {\n let resolved = this.registry.get(protocol);\n if (!resolved) {\n resolved = await resolveProtocol(protocol);\n this.registerProtocol(resolved);\n }\n\n const sender = resolved.sender;\n if (!sender) {\n throw new HyperClientError(`[HyperCore] Protocol \"${protocol}\" has no sender (client role).`);\n }\n return sender;\n }\n\n private async runResponseHooks<TOutput>(\n initialResponse: UniversalResponse<TOutput>,\n req: SendRequest<any, any>,\n ctx: RequestContext,\n plugins: readonly HyperPlugin[],\n ): Promise<UniversalResponse<TOutput>> {\n let response = initialResponse;\n\n for (let i = 0; i < plugins.length; i++) {\n const plugin = plugins[i]!;\n if (typeof plugin.onResponse !== \"function\") continue;\n\n if (plugin.mode === \"background\") {\n void Promise.resolve()\n .then(() => plugin.onResponse!(response, req, this.pluginCtx, ctx))\n .catch((err: unknown) => this.reportBackgroundPluginError(err));\n continue;\n }\n\n const result = await plugin.onResponse(response, req, this.pluginCtx, ctx);\n if (result != null && isUniversalResponse(result)) {\n response = result as UniversalResponse<TOutput>;\n }\n }\n\n return response;\n }\n\n private reportBackgroundPluginError(err: unknown): void {\n const customOnError = (this.config as Record<string, unknown>).onError;\n if (typeof customOnError === \"function\") {\n try {\n (customOnError as (error: unknown) => void)(err);\n return;\n } catch (handlerError) {\n console.error(\"[HyperCore] Background error handler failed:\", handlerError);\n }\n }\n console.error(\"[HyperCore] Background plugin error:\", err);\n }\n\n /**\n * @ru Атомарно получает транспорт для конкретного протокола и удерживает\n * каждый физический экземпляр ровно один раз за время жизни ядра.\n * @en Atomically acquires a transport for a protocol and retains each physical\n * instance exactly once for the lifetime of this core.\n */\n private async acquireTransport(protocol: SenderProtocol = \"rest\"): Promise<HyperTransport> {\n if (this.isDestroyed) {\n throw new HyperClientError(\n \"[HyperCore] Cannot acquire transport on a destroyed core instance.\",\n );\n }\n\n const existing = this.transports.get(protocol);\n if (existing) return existing;\n\n let pending = this.transportPromises.get(protocol);\n if (!pending) {\n pending = this.resolveAndRetainTransport(protocol);\n let tracked!: Promise<HyperTransport>;\n tracked = pending.catch((err: unknown) => {\n if (this.transportPromises.get(protocol) === tracked) {\n this.transportPromises.delete(protocol);\n }\n throw err;\n });\n this.transportPromises.set(protocol, tracked);\n pending = tracked;\n }\n\n const transport = await pending;\n if (this.isDestroyed) {\n throw new HyperClientError(\n \"[HyperCore] Core instance was destroyed while resolving transport.\",\n );\n }\n\n return transport;\n }\n\n private async resolveAndRetainTransport(protocol: SenderProtocol): Promise<HyperTransport> {\n const transport =\n this.fixedTransport ??\n (await resolveTransport(protocol, { customTransport: this.config.customTransport }));\n const supportsProtocol =\n typeof transport.supports === \"function\"\n ? transport.supports(protocol)\n : (transport.protocols?.includes(protocol) ?? true);\n\n if (!supportsProtocol) {\n throw new HyperClientError(\n `[HyperCore] Transport \"${transport.constructor.name}\" does not support protocol \"${protocol}\".`,\n );\n }\n\n return this.retainResolvedTransport(protocol, transport);\n }\n\n private retainResolvedTransport(\n protocol: SenderProtocol,\n transport: HyperTransport,\n ): HyperTransport {\n if (!this.retainedTransports.has(transport)) {\n retainTransport(transport);\n this.retainedTransports.add(transport);\n }\n\n this.transports.set(protocol, transport);\n return transport;\n }\n\n /**\n * @ru Выполняет ядро цикла запроса: prepare → send → parse через физический\n * транспорт. Транспорт получается через `acquireTransport()`.\n * @en Runs the core request cycle: prepare → send → parse through the physical\n * transport. The transport is acquired via `acquireTransport()`.\n * @param sender - The resolved protocol sender.\n * @param req - The (possibly plugin-modified) universal request.\n * @param ctx - The per-request execution context.\n * @returns The normalized universal response.\n */\n private async runSender<TInput, TOutput>(\n sender: HyperSender<any, any, any, any>,\n req: SendRequest<TInput, string>,\n ctx: RequestContext,\n ): Promise<UniversalResponse<TOutput>> {\n const transport =\n this.transports.get(req.protocol) ?? (await this.acquireTransport(req.protocol));\n const prepared = sender.prepare(req, ctx);\n const raw = await sender.send(prepared, transport, ctx);\n return sender.parse(raw, ctx) as UniversalResponse<TOutput>;\n }\n\n /**\n * @ru Запускает сервер для указанного протокола: связывает транспорт, ресивер и\n * application handler в цепочку receive → handle → respond.\n * @en Starts a server for the given protocol, wiring transport, receiver, and\n * application handler into the receive → handle → respond pipeline.\n * @template P - The protocol identifier.\n * @param options - The server listen options.\n * @returns A promise resolving to the transport server handle.\n */\n public async listen<P extends SenderProtocol = SenderProtocol>(\n options: HyperServerListenOptions<P>,\n ): Promise<TransportServer> {\n const transport = await this.acquireTransport(options.protocol);\n\n if (typeof transport.listen !== \"function\") {\n throw new HyperClientError(\n `[HyperCore] Transport \"${transport.constructor.name}\" does not support listen() (server role).`,\n );\n }\n\n let resolved = this.registry.get(options.protocol);\n if (!resolved) {\n resolved = await resolveProtocol(options.protocol);\n this.registerProtocol(resolved);\n }\n\n const receiver = resolved.receiver as\n | HyperReceiver<unknown, unknown, TransportRequest, TransportResponse, P>\n | undefined;\n if (!receiver) {\n throw new HyperClientError(\n `[HyperCore] Protocol \"${options.protocol}\" has no receiver (server role).`,\n );\n }\n\n const handler = options.handler as\n | ((request: unknown, ctx: ServerRequestContext) => unknown)\n | undefined;\n\n const onRequest = async (raw: TransportRequest): Promise<TransportResponse> => {\n const ctx = createServerRequestContext(raw);\n const request = await receiver.receive(raw, ctx);\n const response = handler ? await handler(request, ctx) : await receiver.handle(request, ctx);\n return receiver.respond(response, ctx);\n };\n\n const server = await transport.listen!({\n host: options.host,\n port: options.port,\n signal: options.signal,\n onRequest,\n });\n\n if (this.isDestroyed) {\n await server.close();\n throw new HyperClientError(\n \"[HyperCore] Core instance was destroyed while starting the server.\",\n );\n }\n\n this.servers.add(server);\n return server;\n }\n\n /**\n * @ru Регистрирует плагин. Пропускает отключённые плагины.\n * @en Registers a plugin. Skips disabled plugins.\n * @param plugin - The plugin instance to register.\n * @returns This instance for chaining.\n */\n public use(plugin: HyperPlugin): this {\n const enabled = plugin.enabled ? plugin.enabled(this.config) : true;\n if (!enabled) return this;\n\n plugin.setup?.(this.pluginCtx);\n this.plugins = [...this.plugins, plugin].sort(\n (a, b) => (PLUGIN_PHASE_ORDER[a.phase ?? \"\"] ?? 0) - (PLUGIN_PHASE_ORDER[b.phase ?? \"\"] ?? 0),\n );\n return this;\n }\n\n /**\n * @ru Создаёт новый экземпляр ядра с расширенной/переопределённой конфигурацией,\n * переиспользуя текущий транспорт.\n * @en Creates a new core instance with extended/overridden configuration,\n * reusing the current transport.\n * @param options - Partial configuration overrides.\n * @returns A new IHyperCore instance.\n */\n public extend(options: Partial<HyperClientOptions>): IHyperCore {\n const transport = options.customTransport ?? this.fixedTransport ?? undefined;\n const sharedTransports = options.customTransport ? undefined : this.transportPromises;\n return new HyperCore({ ...this.config, ...options }, transport, sharedTransports);\n }\n\n /**\n * @ru Создаёт полностью независимый экземпляр ядра на основе текущей\n * конфигурации: не переиспользует текущий транспорт и по умолчанию не\n * наследует `customTransport`.\n * @en Creates a fully independent core instance based on the current config:\n * it does not reuse the current transport and does not inherit\n * `customTransport` by default.\n * @param options - Partial configuration overrides.\n * @returns A new IHyperCore instance.\n */\n public create(options: Partial<HyperClientOptions>): IHyperCore {\n const base: Partial<HyperClientOptions> = { ...this.config };\n delete base.customTransport;\n return new HyperCore({ ...base, ...options });\n }\n\n /**\n * @ru Завершает работу ядра и освобождает ресурсы: закрывает активные серверы,\n * затем освобождает удержание транспорта. Graceful-дренирование активных запросов\n * определяется реализацией `TransportServer.close()`.\n * @en Shuts down the core and releases resources: closes active servers, then\n * releases the transport hold. Graceful draining of in-flight requests is defined\n * by the `TransportServer.close()` implementation.\n * @param graceful - If true, prefers `transport.close()`; otherwise prefers `transport.destroy()`.\n * @returns Promise that resolves when shutdown is complete.\n */\n public destroy(graceful = true): Promise<void> {\n if (!this.destroyPromise) {\n this.destroyPromise = this.performDestroy(graceful);\n }\n return this.destroyPromise;\n }\n\n private async performDestroy(graceful: boolean): Promise<void> {\n this.isDestroyed = true;\n\n for (const server of this.servers) {\n try {\n await server.close();\n } catch {\n // Continue releasing the remaining resources.\n }\n }\n this.servers.clear();\n\n await Promise.allSettled(this.transportPromises.values());\n this.transportPromises.clear();\n this.transports.clear();\n\n const transports = [...this.retainedTransports];\n this.retainedTransports.clear();\n\n for (const transport of transports) {\n if (releaseTransport(transport) > 0) continue;\n\n evictCachedTransport(transport);\n\n if (graceful && typeof transport.close === \"function\") {\n await transport.close();\n } else if (typeof transport.destroy === \"function\") {\n await transport.destroy();\n } else if (typeof transport.close === \"function\") {\n await transport.close();\n }\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["defaultCoreConfig", "KNOWN_PROTOCOLS", "resolveProtocol", "evictCachedTransport", "resolveTransport", "HyperClientError", "requestCounter", "requestIdBase", "PLUGIN_PHASE_ORDER", "createRequestId", "transportRefs", "retainTransport", "transport", "releaseTransport", "next", "DefaultRequestContext", "signal", "value", "createRequestContext", "req", "createServerRequestContext", "raw", "isUniversalResponse", "DefaultProtocolRegistry", "protocol", "config", "sharedTransportPromises", "sharedPromise", "sharedTransport", "protocols", "i", "senders", "customSender", "receivers", "plugins", "plugin", "namespaces", "resolved", "sender", "receiver", "ctor", "protocolName", "methods", "namespace", "name", "method", "boundMethod", "args", "existing", "handler", "_target", "ctx", "currentReq", "response", "result", "err", "recovered", "initialResponse", "customOnError", "handlerError", "pending", "tracked", "prepared", "options", "onRequest", "request", "server", "a", "b", "sharedTransports", "base", "graceful", "transports"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperttp/core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Protocol-agnostic client/server execution core with pluggable protocols, transports and client policies",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"browser",
|
|
@@ -51,6 +51,6 @@
|
|
|
51
51
|
"engines": {
|
|
52
52
|
"node": ">=20"
|
|
53
53
|
},
|
|
54
|
-
"packageManager": "bun@1.
|
|
54
|
+
"packageManager": "bun@1.4.0",
|
|
55
55
|
"private": false
|
|
56
56
|
}
|
package/protocols/manager.d.ts
CHANGED
|
@@ -27,5 +27,11 @@ export declare function resolveSender<P extends SenderProtocol>(protocol: P, opt
|
|
|
27
27
|
export declare function resolveReceiver<P extends SenderProtocol>(protocol: P, options?: {
|
|
28
28
|
[key: string]: unknown;
|
|
29
29
|
}): Promise<HyperReceiver<unknown, unknown, unknown, unknown, P>>;
|
|
30
|
+
/**
|
|
31
|
+
* @ru Очищает кэш загруженных модулей протоколов. Не выгружает уже импортированные
|
|
32
|
+
* JavaScript-модули из runtime.
|
|
33
|
+
* @en Clears the loaded protocol-module cache. It does not unload JavaScript
|
|
34
|
+
* modules already imported by the runtime.
|
|
35
|
+
*/
|
|
30
36
|
export declare function resetCachedProtocols(): void;
|
|
31
37
|
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/protocols/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAoCjG;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,cAAc,EAGnD,CAAC;AAsBH;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,CAAC,SAAS,cAAc,EAC5D,QAAQ,EAAE,CAAC,EACX,OAAO,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GACnC,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAqC/D;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,CAAC,SAAS,cAAc,EAC1D,QAAQ,EAAE,CAAC,EACX,OAAO,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GACnC,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAM7D;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,CAAC,SAAS,cAAc,EAC5D,QAAQ,EAAE,CAAC,EACX,OAAO,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GACnC,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAM/D;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/protocols/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAoCjG;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,cAAc,EAGnD,CAAC;AAsBH;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,CAAC,SAAS,cAAc,EAC5D,QAAQ,EAAE,CAAC,EACX,OAAO,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GACnC,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAqC/D;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,CAAC,SAAS,cAAc,EAC1D,QAAQ,EAAE,CAAC,EACX,OAAO,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GACnC,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAM7D;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,CAAC,SAAS,cAAc,EAC5D,QAAQ,EAAE,CAAC,EACX,OAAO,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GACnC,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAM/D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
|
package/protocols/manager.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/protocols/manager.ts"],
|
|
4
|
-
"sourcesContent": ["import type { HyperProtocol, HyperReceiver, HyperSender, SenderProtocol } from \"@hyperttp/types\";\nimport { HyperClientError } from \"../utils/errors.js\";\nimport { RestProtocol } from \"./rest/index.js\";\n\ntype ProtocolDef = {\n readonly protocol: SenderProtocol;\n readonly pkg: string;\n readonly export: string;\n readonly priority: number;\n};\n\nconst PROTOCOL_DEFS: readonly ProtocolDef[] = [\n {\n protocol: \"graphql\",\n pkg: \"@hyperttp/protocol-graphql\",\n export: \"GraphQLProtocol\",\n priority: 100,\n },\n { protocol: \"grpc\", pkg: \"@hyperttp/protocol-grpc\", export: \"GrpcProtocol\", priority: 100 },\n { protocol: \"trpc\", pkg: \"@hyperttp/protocol-trpc\", export: \"TrpcProtocol\", priority: 100 },\n {\n protocol: \"ws\",\n pkg: \"@hyperttp/protocol-websocket\",\n export: \"WebSocketProtocol\",\n priority: 100,\n },\n {\n protocol: \"websocket\",\n pkg: \"@hyperttp/protocol-websocket\",\n export: \"WebSocketProtocol\",\n priority: 90,\n },\n { protocol: \"sse\", pkg: \"@hyperttp/protocol-sse\", export: \"SseProtocol\", priority: 100 },\n { protocol: \"mqtt\", pkg: \"@hyperttp/protocol-mqtt\", export: \"MqttProtocol\", priority: 100 },\n];\n\n/**\n * @ru Известные протоколы ядра: встроенный rest и пакетные модули.\n * @en Known core protocols: the built-in rest and packaged modules.\n */\nexport const KNOWN_PROTOCOLS: readonly SenderProtocol[] = Object.freeze([\n \"rest\",\n ...PROTOCOL_DEFS.map((d) => d.protocol),\n]);\n\nconst protocolCache = new Map<string, HyperProtocol>();\n\nfunction isModuleNotFoundError(err: unknown): boolean {\n if (!err || typeof err !== \"object\") return false;\n const e = err as Record<string, unknown>;\n if (e.code === \"ERR_MODULE_NOT_FOUND\" || e.code === \"MODULE_NOT_FOUND\") return true;\n\n const msg = err instanceof Error ? err.message : String(e.message ?? \"\");\n return (\n msg.includes(\"Cannot find module\") ||\n msg.includes(\"Failed to resolve\") ||\n msg.includes(\"Failed to load\")\n );\n}\n\nasync function dynamicImport(pkg: string): Promise<Record<string, unknown>> {\n /* @vite-ignore */\n return import(/* webpackIgnore: true */ pkg);\n}\n\n/**\n * @ru Разрешает модуль протокола. Встроенный rest возвращается статически,\n * остальные протоколы загружаются из пакетных модулей по требованию.\n * @en Resolves a protocol module. The built-in rest is returned statically,\n * other protocols are loaded from packaged modules on demand.\n */\nexport async function resolveProtocol<P extends SenderProtocol>(\n protocol: P,\n options?: { [key: string]: unknown },\n): Promise<HyperProtocol<unknown, unknown, unknown, unknown, P>> {\n const cached = protocolCache.get(protocol);\n if (cached) {\n return cached as HyperProtocol<unknown, unknown, unknown, unknown, P>;\n }\n\n if (protocol === \"rest\") {\n protocolCache.set(protocol, RestProtocol);\n return RestProtocol as HyperProtocol<unknown, unknown, unknown, unknown, P>;\n }\n\n for (let i = 0; i < PROTOCOL_DEFS.length; i++) {\n const def = PROTOCOL_DEFS[i]!;\n if (def.protocol !== protocol) continue;\n\n try {\n const mod = await dynamicImport(def.pkg);\n const candidate = (mod[def.export] ?? mod.default) as\n | { new (opts?: unknown): HyperProtocol }\n | HyperProtocol\n | undefined;\n const instance =\n typeof candidate === \"function\" ? new candidate(options) : (candidate as HyperProtocol);\n\n if (!instance || typeof instance.protocol !== \"string\") continue;\n\n protocolCache.set(protocol, instance);\n return instance as HyperProtocol<unknown, unknown, unknown, unknown, P>;\n } catch (err) {\n if (!isModuleNotFoundError(err)) throw err;\n }\n }\n\n const pkgDef = PROTOCOL_DEFS.find((d) => d.protocol === protocol);\n const hint = pkgDef ? ` Did you forget to install \"${pkgDef.pkg}\"?` : \"\";\n\n throw new HyperClientError(`[HyperCore] No protocol available for \"${protocol}\".${hint}`);\n}\n\n/**\n * @ru Разрешает клиентский сендер протокола.\n * @en Resolves the client sender of a protocol.\n */\nexport async function resolveSender<P extends SenderProtocol>(\n protocol: P,\n options?: { [key: string]: unknown },\n): Promise<HyperSender<unknown, unknown, unknown, unknown, P>> {\n const resolved = await resolveProtocol(protocol, options);\n if (!resolved.sender) {\n throw new HyperClientError(`[HyperCore] Protocol \"${protocol}\" has no sender (client role).`);\n }\n return resolved.sender;\n}\n\n/**\n * @ru Разрешает серверный ресивер протокола.\n * @en Resolves the server receiver of a protocol.\n */\nexport async function resolveReceiver<P extends SenderProtocol>(\n protocol: P,\n options?: { [key: string]: unknown },\n): Promise<HyperReceiver<unknown, unknown, unknown, unknown, P>> {\n const resolved = await resolveProtocol(protocol, options);\n if (!resolved.receiver) {\n throw new HyperClientError(`[HyperCore] Protocol \"${protocol}\" has no receiver (server role).`);\n }\n return resolved.receiver;\n}\n\nexport function resetCachedProtocols(): void {\n protocolCache.clear();\n}\n"],
|
|
5
|
-
"mappings": "aACA,OAAS,oBAAAA,MAAwB,qBACjC,OAAS,gBAAAC,MAAoB,kBAS7B,MAAMC,EAAwC,CAC5C,CACE,SAAU,UACV,IAAK,6BACL,OAAQ,kBACR,SAAU,KAEZ,CAAE,SAAU,OAAQ,IAAK,0BAA2B,OAAQ,eAAgB,SAAU,GAAG,EACzF,CAAE,SAAU,OAAQ,IAAK,0BAA2B,OAAQ,eAAgB,SAAU,GAAG,EACzF,CACE,SAAU,KACV,IAAK,+BACL,OAAQ,oBACR,SAAU,KAEZ,CACE,SAAU,YACV,IAAK,+BACL,OAAQ,oBACR,SAAU,IAEZ,CAAE,SAAU,MAAO,IAAK,yBAA0B,OAAQ,cAAe,SAAU,GAAG,EACtF,CAAE,SAAU,OAAQ,IAAK,0BAA2B,OAAQ,eAAgB,SAAU,GAAG,GAOpF,aAAM,gBAA6C,OAAO,OAAO,CACtE,OACA,GAAGA,EAAc,IAAKC,GAAMA,EAAE,QAAQ,EACvC,EAED,MAAMC,EAAgB,IAAI,IAE1B,SAASC,EAAsBC,EAAY,CACzC,GAAI,CAACA,GAAO,OAAOA,GAAQ,SAAU,MAAO,GAC5C,MAAMC,EAAID,EACV,GAAIC,EAAE,OAAS,wBAA0BA,EAAE,OAAS,mBAAoB,MAAO,GAE/E,MAAMC,EAAMF,aAAe,MAAQA,EAAI,QAAU,OAAOC,EAAE,SAAW,EAAE,EACvE,OACEC,EAAI,SAAS,oBAAoB,GACjCA,EAAI,SAAS,mBAAmB,GAChCA,EAAI,SAAS,gBAAgB,CAEjC,CAEA,eAAeC,EAAcC,EAAW,CAEtC,OAAO,OAAiCA,EAC1C,CAQA,sBAAsB,gBACpBC,EACAC,EAAoC,CAEpC,MAAMC,EAAST,EAAc,IAAIO,CAAQ,EACzC,GAAIE,EACF,OAAOA,EAGT,GAAIF,IAAa,OACf,OAAAP,EAAc,IAAIO,EAAUV,CAAY,EACjCA,EAGT,QAASa,EAAI,EAAGA,EAAIZ,EAAc,OAAQY,IAAK,CAC7C,MAAMC,EAAMb,EAAcY,CAAC,EAC3B,GAAIC,EAAI,WAAaJ,EAErB,GAAI,CACF,MAAMK,EAAM,MAAMP,EAAcM,EAAI,GAAG,EACjCE,EAAaD,EAAID,EAAI,MAAM,GAAKC,EAAI,QAIpCE,EACJ,OAAOD,GAAc,WAAa,IAAIA,EAAUL,CAAO,EAAKK,EAE9D,GAAI,CAACC,GAAY,OAAOA,EAAS,UAAa,SAAU,SAExD,OAAAd,EAAc,IAAIO,EAAUO,CAAQ,EAC7BA,CACT,OAASZ,EAAK,CACZ,GAAI,CAACD,EAAsBC,CAAG,EAAG,MAAMA,CACzC,CACF,CAEA,MAAMa,EAASjB,EAAc,KAAMC,GAAMA,EAAE,WAAaQ,CAAQ,EAC1DS,EAAOD,EAAS,+BAA+BA,EAAO,GAAG,KAAO,GAEtE,MAAM,IAAInB,EAAiB,0CAA0CW,CAAQ,KAAKS,CAAI,EAAE,CAC1F,CAMA,sBAAsB,cACpBT,EACAC,EAAoC,CAEpC,MAAMS,EAAW,MAAM,gBAAgBV,EAAUC,CAAO,EACxD,GAAI,CAACS,EAAS,OACZ,MAAM,IAAIrB,EAAiB,yBAAyBW,CAAQ,gCAAgC,EAE9F,OAAOU,EAAS,MAClB,CAMA,sBAAsB,gBACpBV,EACAC,EAAoC,CAEpC,MAAMS,EAAW,MAAM,gBAAgBV,EAAUC,CAAO,EACxD,GAAI,CAACS,EAAS,SACZ,MAAM,IAAIrB,EAAiB,yBAAyBW,CAAQ,kCAAkC,EAEhG,OAAOU,EAAS,QAClB,
|
|
4
|
+
"sourcesContent": ["import type { HyperProtocol, HyperReceiver, HyperSender, SenderProtocol } from \"@hyperttp/types\";\nimport { HyperClientError } from \"../utils/errors.js\";\nimport { RestProtocol } from \"./rest/index.js\";\n\ntype ProtocolDef = {\n readonly protocol: SenderProtocol;\n readonly pkg: string;\n readonly export: string;\n readonly priority: number;\n};\n\nconst PROTOCOL_DEFS: readonly ProtocolDef[] = [\n {\n protocol: \"graphql\",\n pkg: \"@hyperttp/protocol-graphql\",\n export: \"GraphQLProtocol\",\n priority: 100,\n },\n { protocol: \"grpc\", pkg: \"@hyperttp/protocol-grpc\", export: \"GrpcProtocol\", priority: 100 },\n { protocol: \"trpc\", pkg: \"@hyperttp/protocol-trpc\", export: \"TrpcProtocol\", priority: 100 },\n {\n protocol: \"ws\",\n pkg: \"@hyperttp/protocol-websocket\",\n export: \"WebSocketProtocol\",\n priority: 100,\n },\n {\n protocol: \"websocket\",\n pkg: \"@hyperttp/protocol-websocket\",\n export: \"WebSocketProtocol\",\n priority: 90,\n },\n { protocol: \"sse\", pkg: \"@hyperttp/protocol-sse\", export: \"SseProtocol\", priority: 100 },\n { protocol: \"mqtt\", pkg: \"@hyperttp/protocol-mqtt\", export: \"MqttProtocol\", priority: 100 },\n];\n\n/**\n * @ru Известные протоколы ядра: встроенный rest и пакетные модули.\n * @en Known core protocols: the built-in rest and packaged modules.\n */\nexport const KNOWN_PROTOCOLS: readonly SenderProtocol[] = Object.freeze([\n \"rest\",\n ...PROTOCOL_DEFS.map((d) => d.protocol),\n]);\n\nconst protocolCache = new Map<string, HyperProtocol>();\n\nfunction isModuleNotFoundError(err: unknown): boolean {\n if (!err || typeof err !== \"object\") return false;\n const e = err as Record<string, unknown>;\n if (e.code === \"ERR_MODULE_NOT_FOUND\" || e.code === \"MODULE_NOT_FOUND\") return true;\n\n const msg = err instanceof Error ? err.message : String(e.message ?? \"\");\n return (\n msg.includes(\"Cannot find module\") ||\n msg.includes(\"Failed to resolve\") ||\n msg.includes(\"Failed to load\")\n );\n}\n\nasync function dynamicImport(pkg: string): Promise<Record<string, unknown>> {\n /* @vite-ignore */\n return import(/* webpackIgnore: true */ pkg);\n}\n\n/**\n * @ru Разрешает модуль протокола. Встроенный rest возвращается статически,\n * остальные протоколы загружаются из пакетных модулей по требованию.\n * @en Resolves a protocol module. The built-in rest is returned statically,\n * other protocols are loaded from packaged modules on demand.\n */\nexport async function resolveProtocol<P extends SenderProtocol>(\n protocol: P,\n options?: { [key: string]: unknown },\n): Promise<HyperProtocol<unknown, unknown, unknown, unknown, P>> {\n const cached = protocolCache.get(protocol);\n if (cached) {\n return cached as HyperProtocol<unknown, unknown, unknown, unknown, P>;\n }\n\n if (protocol === \"rest\") {\n protocolCache.set(protocol, RestProtocol);\n return RestProtocol as HyperProtocol<unknown, unknown, unknown, unknown, P>;\n }\n\n for (let i = 0; i < PROTOCOL_DEFS.length; i++) {\n const def = PROTOCOL_DEFS[i]!;\n if (def.protocol !== protocol) continue;\n\n try {\n const mod = await dynamicImport(def.pkg);\n const candidate = (mod[def.export] ?? mod.default) as\n | { new (opts?: unknown): HyperProtocol }\n | HyperProtocol\n | undefined;\n const instance =\n typeof candidate === \"function\" ? new candidate(options) : (candidate as HyperProtocol);\n\n if (!instance || typeof instance.protocol !== \"string\") continue;\n\n protocolCache.set(protocol, instance);\n return instance as HyperProtocol<unknown, unknown, unknown, unknown, P>;\n } catch (err) {\n if (!isModuleNotFoundError(err)) throw err;\n }\n }\n\n const pkgDef = PROTOCOL_DEFS.find((d) => d.protocol === protocol);\n const hint = pkgDef ? ` Did you forget to install \"${pkgDef.pkg}\"?` : \"\";\n\n throw new HyperClientError(`[HyperCore] No protocol available for \"${protocol}\".${hint}`);\n}\n\n/**\n * @ru Разрешает клиентский сендер протокола.\n * @en Resolves the client sender of a protocol.\n */\nexport async function resolveSender<P extends SenderProtocol>(\n protocol: P,\n options?: { [key: string]: unknown },\n): Promise<HyperSender<unknown, unknown, unknown, unknown, P>> {\n const resolved = await resolveProtocol(protocol, options);\n if (!resolved.sender) {\n throw new HyperClientError(`[HyperCore] Protocol \"${protocol}\" has no sender (client role).`);\n }\n return resolved.sender;\n}\n\n/**\n * @ru Разрешает серверный ресивер протокола.\n * @en Resolves the server receiver of a protocol.\n */\nexport async function resolveReceiver<P extends SenderProtocol>(\n protocol: P,\n options?: { [key: string]: unknown },\n): Promise<HyperReceiver<unknown, unknown, unknown, unknown, P>> {\n const resolved = await resolveProtocol(protocol, options);\n if (!resolved.receiver) {\n throw new HyperClientError(`[HyperCore] Protocol \"${protocol}\" has no receiver (server role).`);\n }\n return resolved.receiver;\n}\n\n/**\n * @ru Очищает кэш загруженных модулей протоколов. Не выгружает уже импортированные\n * JavaScript-модули из runtime.\n * @en Clears the loaded protocol-module cache. It does not unload JavaScript\n * modules already imported by the runtime.\n */\nexport function resetCachedProtocols(): void {\n protocolCache.clear();\n}\n"],
|
|
5
|
+
"mappings": "aACA,OAAS,oBAAAA,MAAwB,qBACjC,OAAS,gBAAAC,MAAoB,kBAS7B,MAAMC,EAAwC,CAC5C,CACE,SAAU,UACV,IAAK,6BACL,OAAQ,kBACR,SAAU,KAEZ,CAAE,SAAU,OAAQ,IAAK,0BAA2B,OAAQ,eAAgB,SAAU,GAAG,EACzF,CAAE,SAAU,OAAQ,IAAK,0BAA2B,OAAQ,eAAgB,SAAU,GAAG,EACzF,CACE,SAAU,KACV,IAAK,+BACL,OAAQ,oBACR,SAAU,KAEZ,CACE,SAAU,YACV,IAAK,+BACL,OAAQ,oBACR,SAAU,IAEZ,CAAE,SAAU,MAAO,IAAK,yBAA0B,OAAQ,cAAe,SAAU,GAAG,EACtF,CAAE,SAAU,OAAQ,IAAK,0BAA2B,OAAQ,eAAgB,SAAU,GAAG,GAOpF,aAAM,gBAA6C,OAAO,OAAO,CACtE,OACA,GAAGA,EAAc,IAAKC,GAAMA,EAAE,QAAQ,EACvC,EAED,MAAMC,EAAgB,IAAI,IAE1B,SAASC,EAAsBC,EAAY,CACzC,GAAI,CAACA,GAAO,OAAOA,GAAQ,SAAU,MAAO,GAC5C,MAAMC,EAAID,EACV,GAAIC,EAAE,OAAS,wBAA0BA,EAAE,OAAS,mBAAoB,MAAO,GAE/E,MAAMC,EAAMF,aAAe,MAAQA,EAAI,QAAU,OAAOC,EAAE,SAAW,EAAE,EACvE,OACEC,EAAI,SAAS,oBAAoB,GACjCA,EAAI,SAAS,mBAAmB,GAChCA,EAAI,SAAS,gBAAgB,CAEjC,CAEA,eAAeC,EAAcC,EAAW,CAEtC,OAAO,OAAiCA,EAC1C,CAQA,sBAAsB,gBACpBC,EACAC,EAAoC,CAEpC,MAAMC,EAAST,EAAc,IAAIO,CAAQ,EACzC,GAAIE,EACF,OAAOA,EAGT,GAAIF,IAAa,OACf,OAAAP,EAAc,IAAIO,EAAUV,CAAY,EACjCA,EAGT,QAASa,EAAI,EAAGA,EAAIZ,EAAc,OAAQY,IAAK,CAC7C,MAAMC,EAAMb,EAAcY,CAAC,EAC3B,GAAIC,EAAI,WAAaJ,EAErB,GAAI,CACF,MAAMK,EAAM,MAAMP,EAAcM,EAAI,GAAG,EACjCE,EAAaD,EAAID,EAAI,MAAM,GAAKC,EAAI,QAIpCE,EACJ,OAAOD,GAAc,WAAa,IAAIA,EAAUL,CAAO,EAAKK,EAE9D,GAAI,CAACC,GAAY,OAAOA,EAAS,UAAa,SAAU,SAExD,OAAAd,EAAc,IAAIO,EAAUO,CAAQ,EAC7BA,CACT,OAASZ,EAAK,CACZ,GAAI,CAACD,EAAsBC,CAAG,EAAG,MAAMA,CACzC,CACF,CAEA,MAAMa,EAASjB,EAAc,KAAMC,GAAMA,EAAE,WAAaQ,CAAQ,EAC1DS,EAAOD,EAAS,+BAA+BA,EAAO,GAAG,KAAO,GAEtE,MAAM,IAAInB,EAAiB,0CAA0CW,CAAQ,KAAKS,CAAI,EAAE,CAC1F,CAMA,sBAAsB,cACpBT,EACAC,EAAoC,CAEpC,MAAMS,EAAW,MAAM,gBAAgBV,EAAUC,CAAO,EACxD,GAAI,CAACS,EAAS,OACZ,MAAM,IAAIrB,EAAiB,yBAAyBW,CAAQ,gCAAgC,EAE9F,OAAOU,EAAS,MAClB,CAMA,sBAAsB,gBACpBV,EACAC,EAAoC,CAEpC,MAAMS,EAAW,MAAM,gBAAgBV,EAAUC,CAAO,EACxD,GAAI,CAACS,EAAS,SACZ,MAAM,IAAIrB,EAAiB,yBAAyBW,CAAQ,kCAAkC,EAEhG,OAAOU,EAAS,QAClB,CAQM,gBAAU,sBAAoB,CAClCjB,EAAc,MAAK,CACrB",
|
|
6
6
|
"names": ["HyperClientError", "RestProtocol", "PROTOCOL_DEFS", "d", "protocolCache", "isModuleNotFoundError", "err", "e", "msg", "dynamicImport", "pkg", "protocol", "options", "cached", "i", "def", "mod", "candidate", "instance", "pkgDef", "hint", "resolved"]
|
|
7
7
|
}
|
|
@@ -9,6 +9,11 @@ import type { RestServerHandler, RestServerInput, RestServerResponse } from "./t
|
|
|
9
9
|
export declare class RestReceiver implements HyperReceiver<RestServerInput, RestServerResponse, TransportRequest, TransportResponse> {
|
|
10
10
|
readonly protocol = "rest";
|
|
11
11
|
protected readonly handler?: RestServerHandler;
|
|
12
|
+
/**
|
|
13
|
+
* @ru Создаёт REST-ресивер с необязательным application handler.
|
|
14
|
+
* @en Creates a REST receiver with an optional application handler.
|
|
15
|
+
* @param options - Настройки ресивера и его обработчик. @en Receiver settings and its handler.
|
|
16
|
+
*/
|
|
12
17
|
constructor(options?: {
|
|
13
18
|
handler?: RestServerHandler;
|
|
14
19
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"receiver.d.ts","sourceRoot":"","sources":["../../../src/protocols/rest/receiver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAoHxF;;;;;GAKG;AACH,qBAAa,YAAa,YAAW,aAAa,CAChD,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,CAClB;IACC,QAAQ,CAAC,QAAQ,UAAU;IAC3B,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAE/C,YAAY,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,iBAAiB,CAAA;KAAO,EAExD;IAED;;;OAGG;IACH,OAAO,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,oBAAoB,GAAG,eAAe,CAU1E;IAED;;;OAGG;IACH,MAAM,CACJ,OAAO,EAAE,eAAe,EACxB,GAAG,EAAE,oBAAoB,GACxB,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAYlD;IAED;;;OAGG;IACH,OAAO,CAAC,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,oBAAoB,GAAG,iBAAiB,CAqBnF;CACF"}
|
|
1
|
+
{"version":3,"file":"receiver.d.ts","sourceRoot":"","sources":["../../../src/protocols/rest/receiver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAoHxF;;;;;GAKG;AACH,qBAAa,YAAa,YAAW,aAAa,CAChD,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,CAClB;IACC,QAAQ,CAAC,QAAQ,UAAU;IAC3B,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAE/C;;;;OAIG;IACH,YAAY,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,iBAAiB,CAAA;KAAO,EAExD;IAED;;;OAGG;IACH,OAAO,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,oBAAoB,GAAG,eAAe,CAU1E;IAED;;;OAGG;IACH,MAAM,CACJ,OAAO,EAAE,eAAe,EACxB,GAAG,EAAE,oBAAoB,GACxB,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAYlD;IAED;;;OAGG;IACH,OAAO,CAAC,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,oBAAoB,GAAG,iBAAiB,CAqBnF;CACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/protocols/rest/receiver.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n HyperReceiver,\n ServerRequestContext,\n TransportRequest,\n TransportResponse,\n} from \"@hyperttp/types\";\nimport type { RestServerHandler, RestServerInput, RestServerResponse } from \"./type.js\";\nimport { HyperClientError } from \"../../utils/errors.js\";\n\nconst JSON_TYPE = \"application/json\";\nconst TEXT_DECODER = new TextDecoder();\nconst TEXT_ENCODER = new TextEncoder();\nconst HAS_BUFFER = typeof Buffer !== \"undefined\";\n\nfunction decodeUtf8(bytes: Uint8Array): string {\n if (HAS_BUFFER) {\n return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString(\"utf8\");\n }\n return TEXT_DECODER.decode(bytes);\n}\n\nfunction decodeArrayBuffer(ab: ArrayBuffer): string {\n if (HAS_BUFFER) {\n return Buffer.from(ab).toString(\"utf8\");\n }\n return TEXT_DECODER.decode(ab);\n}\n\nfunction encodeUtf8(str: string): Uint8Array {\n if (HAS_BUFFER) {\n return Buffer.from(str);\n }\n return TEXT_ENCODER.encode(str);\n}\n\nconst defaultStatusTexts: Record<number, string> = {\n 200: \"OK\",\n 201: \"Created\",\n 204: \"No Content\",\n 400: \"Bad Request\",\n 401: \"Unauthorized\",\n 403: \"Forbidden\",\n 404: \"Not Found\",\n 500: \"Internal Server Error\",\n};\n\n/**\n * @ru Разбирает query-строку URL в словарь (поддерживает повторные ключи как массивы).\n * @en Parses a URL query string into a dictionary (supports repeated keys as arrays).\n */\nfunction parseQuery(queryString: string): Record<string, string | string[]> {\n if (!queryString) return {};\n const out: Record<string, string | string[]> = {};\n\n for (const [key, value] of new URLSearchParams(queryString)) {\n const existing = out[key];\n if (existing === undefined) {\n out[key] = value;\n } else if (Array.isArray(existing)) {\n existing.push(value);\n } else {\n out[key] = [existing, value];\n }\n }\n\n return out;\n}\n\n/**\n * @ru Регистронезависимое получение значения заголовка.\n * @en Case-insensitive header value lookup.\n */\nfunction getHeaderValue(\n headers: Readonly<Record<string, string | string[]>>,\n name: string,\n): string | undefined {\n const direct = headers[name] ?? headers[name.toLowerCase()];\n if (direct !== undefined) {\n return Array.isArray(direct) ? direct[0] : direct;\n }\n const targetKey = name.toLowerCase();\n for (const key in headers) {\n if (key.toLowerCase() === targetKey) {\n const val = headers[key];\n return Array.isArray(val) ? val[0] : val;\n }\n }\n return undefined;\n}\n\n/**\n * @ru Декодирует тело запроса по content-type.\n * @en Decodes the request body based on content-type.\n */\nfunction parseTextBody(\n headers: Readonly<Record<string, string | string[]>>,\n text: string,\n): unknown {\n const contentType = getHeaderValue(headers, \"content-type\") ?? \"\";\n if (contentType.includes(JSON_TYPE)) {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n return text;\n}\n\nfunction decodeBody(raw: TransportRequest): unknown {\n const body = raw.body;\n if (body == null) return undefined;\n if (body instanceof Uint8Array) {\n return parseTextBody(raw.headers, decodeUtf8(body));\n }\n if (body instanceof ArrayBuffer) {\n return parseTextBody(raw.headers, decodeArrayBuffer(body));\n }\n if (typeof body === \"string\") return parseTextBody(raw.headers, body);\n return body;\n}\n\n/**\n * @ru REST/HTTP серверный адаптер. Зеркальная к `RestSender` реализация\n * трёхфазного цикла receive → handle → respond.\n * @en REST/HTTP server adapter. Mirror implementation of `RestSender` for the\n * three-phase receive → handle → respond cycle.\n */\nexport class RestReceiver implements HyperReceiver<\n RestServerInput,\n RestServerResponse,\n TransportRequest,\n TransportResponse\n> {\n readonly protocol = \"rest\";\n protected readonly handler?: RestServerHandler;\n\n constructor(options: { handler?: RestServerHandler } = {}) {\n this.handler = options.handler;\n }\n\n /**\n * @ru Фаза приёма: разбирает сырой запрос транспорта в REST-структуру.\n * @en Receive phase: parses raw transport request into REST input structure.\n */\n receive(raw: TransportRequest, _ctx: ServerRequestContext): RestServerInput {\n const url = new URL(raw.url, \"http://hyperttp.local\");\n\n return {\n method: raw.method,\n path: url.pathname,\n headers: raw.headers,\n query: parseQuery(url.search.slice(1)),\n body: decodeBody(raw),\n };\n }\n\n /**\n * @ru Фаза обработки: вызывает зарегистрированный handler.\n * @en Handle phase: executes the registered application handler.\n */\n handle(\n request: RestServerInput,\n ctx: ServerRequestContext,\n ): RestServerResponse | Promise<RestServerResponse> {\n if (ctx.signal?.aborted) {\n throw ctx.signal.reason ?? new Error(\"Request aborted\");\n }\n\n if (!this.handler) {\n throw new HyperClientError(\n '[RestReceiver] No application handler registered for protocol \"rest\".',\n );\n }\n\n return this.handler(request, ctx);\n }\n\n /**\n * @ru Фаза ответа: сериализует протокольный ответ в транспортный формат.\n * @en Respond phase: serializes protocol response to raw transport format.\n */\n respond(response: RestServerResponse, _ctx: ServerRequestContext): TransportResponse {\n const headers: Record<string, string> = { ...response.headers };\n const status = response.status ?? 200;\n\n let body: unknown = response.body;\n if (body instanceof ArrayBuffer) {\n body = new Uint8Array(body);\n } else if (ArrayBuffer.isView(body) && !(body instanceof Uint8Array)) {\n body = new Uint8Array(body.buffer, body.byteOffset, body.byteLength).slice();\n } else if (body != null && typeof body === \"object\" && !(body instanceof Uint8Array)) {\n body = JSON.stringify(body);\n const hasContentType = Object.keys(headers).some((k) => k.toLowerCase() === \"content-type\");\n if (!hasContentType) headers[\"content-type\"] = JSON_TYPE;\n }\n\n return {\n status,\n statusText: defaultStatusTexts[status] ?? \"\",\n headers,\n body: body == null ? undefined : body instanceof Uint8Array ? body : encodeUtf8(String(body)),\n };\n }\n}\n"],
|
|
5
|
-
"mappings": "aAOA,OAAS,oBAAAA,MAAwB,wBAEjC,MAAMC,EAAY,mBACZC,EAAe,IAAI,YACnBC,EAAe,IAAI,YACnBC,EAAa,OAAO,OAAW,IAErC,SAASC,EAAWC,EAAiB,CACnC,OAAIF,EACK,OAAO,KAAKE,EAAM,OAAQA,EAAM,WAAYA,EAAM,UAAU,EAAE,SAAS,MAAM,EAE/EJ,EAAa,OAAOI,CAAK,CAClC,CAEA,SAASC,EAAkBC,EAAe,CACxC,OAAIJ,EACK,OAAO,KAAKI,CAAE,EAAE,SAAS,MAAM,EAEjCN,EAAa,OAAOM,CAAE,CAC/B,CAEA,SAASC,EAAWC,EAAW,CAC7B,OAAIN,EACK,OAAO,KAAKM,CAAG,EAEjBP,EAAa,OAAOO,CAAG,CAChC,CAEA,MAAMC,EAA6C,CACjD,IAAK,KACL,IAAK,UACL,IAAK,aACL,IAAK,cACL,IAAK,eACL,IAAK,YACL,IAAK,YACL,IAAK,yBAOP,SAASC,EAAWC,EAAmB,CACrC,GAAI,CAACA,EAAa,MAAO,CAAA,EACzB,MAAMC,EAAyC,CAAA,EAE/C,SAAW,CAACC,EAAKC,CAAK,IAAK,IAAI,gBAAgBH,CAAW,EAAG,CAC3D,MAAMI,EAAWH,EAAIC,CAAG,EACpBE,IAAa,OACfH,EAAIC,CAAG,EAAIC,EACF,MAAM,QAAQC,CAAQ,EAC/BA,EAAS,KAAKD,CAAK,EAEnBF,EAAIC,CAAG,EAAI,CAACE,EAAUD,CAAK,CAE/B,CAEA,OAAOF,CACT,CAMA,SAASI,EACPC,EACAC,EAAY,CAEZ,MAAMC,EAASF,EAAQC,CAAI,GAAKD,EAAQC,EAAK,YAAW,CAAE,EAC1D,GAAIC,IAAW,OACb,OAAO,MAAM,QAAQA,CAAM,EAAIA,EAAO,CAAC,EAAIA,EAE7C,MAAMC,EAAYF,EAAK,YAAW,EAClC,UAAWL,KAAOI,EAChB,GAAIJ,EAAI,YAAW,IAAOO,EAAW,CACnC,MAAMC,EAAMJ,EAAQJ,CAAG,EACvB,OAAO,MAAM,QAAQQ,CAAG,EAAIA,EAAI,CAAC,EAAIA,CACvC,CAGJ,CAMA,SAASC,EACPL,EACAM,EAAY,CAGZ,IADoBP,EAAeC,EAAS,cAAc,GAAK,IAC/C,SAASlB,CAAS,EAChC,GAAI,CACF,OAAO,KAAK,MAAMwB,CAAI,CACxB,MAAQ,CACN,OAAOA,CACT,CAEF,OAAOA,CACT,CAEA,SAASC,EAAWC,EAAqB,CACvC,MAAMC,EAAOD,EAAI,KACjB,GAAIC,GAAQ,KACZ,OAAIA,aAAgB,WACXJ,EAAcG,EAAI,QAAStB,EAAWuB,CAAI,CAAC,EAEhDA,aAAgB,YACXJ,EAAcG,EAAI,QAASpB,EAAkBqB,CAAI,CAAC,EAEvD,OAAOA,GAAS,SAAiBJ,EAAcG,EAAI,QAASC,CAAI,EAC7DA,CACT,CAQM,aAAO,YAAY,CAMd,SAAW,OACD,
|
|
4
|
+
"sourcesContent": ["import type {\n HyperReceiver,\n ServerRequestContext,\n TransportRequest,\n TransportResponse,\n} from \"@hyperttp/types\";\nimport type { RestServerHandler, RestServerInput, RestServerResponse } from \"./type.js\";\nimport { HyperClientError } from \"../../utils/errors.js\";\n\nconst JSON_TYPE = \"application/json\";\nconst TEXT_DECODER = new TextDecoder();\nconst TEXT_ENCODER = new TextEncoder();\nconst HAS_BUFFER = typeof Buffer !== \"undefined\";\n\nfunction decodeUtf8(bytes: Uint8Array): string {\n if (HAS_BUFFER) {\n return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString(\"utf8\");\n }\n return TEXT_DECODER.decode(bytes);\n}\n\nfunction decodeArrayBuffer(ab: ArrayBuffer): string {\n if (HAS_BUFFER) {\n return Buffer.from(ab).toString(\"utf8\");\n }\n return TEXT_DECODER.decode(ab);\n}\n\nfunction encodeUtf8(str: string): Uint8Array {\n if (HAS_BUFFER) {\n return Buffer.from(str);\n }\n return TEXT_ENCODER.encode(str);\n}\n\nconst defaultStatusTexts: Record<number, string> = {\n 200: \"OK\",\n 201: \"Created\",\n 204: \"No Content\",\n 400: \"Bad Request\",\n 401: \"Unauthorized\",\n 403: \"Forbidden\",\n 404: \"Not Found\",\n 500: \"Internal Server Error\",\n};\n\n/**\n * @ru Разбирает query-строку URL в словарь (поддерживает повторные ключи как массивы).\n * @en Parses a URL query string into a dictionary (supports repeated keys as arrays).\n */\nfunction parseQuery(queryString: string): Record<string, string | string[]> {\n if (!queryString) return {};\n const out: Record<string, string | string[]> = {};\n\n for (const [key, value] of new URLSearchParams(queryString)) {\n const existing = out[key];\n if (existing === undefined) {\n out[key] = value;\n } else if (Array.isArray(existing)) {\n existing.push(value);\n } else {\n out[key] = [existing, value];\n }\n }\n\n return out;\n}\n\n/**\n * @ru Регистронезависимое получение значения заголовка.\n * @en Case-insensitive header value lookup.\n */\nfunction getHeaderValue(\n headers: Readonly<Record<string, string | string[]>>,\n name: string,\n): string | undefined {\n const direct = headers[name] ?? headers[name.toLowerCase()];\n if (direct !== undefined) {\n return Array.isArray(direct) ? direct[0] : direct;\n }\n const targetKey = name.toLowerCase();\n for (const key in headers) {\n if (key.toLowerCase() === targetKey) {\n const val = headers[key];\n return Array.isArray(val) ? val[0] : val;\n }\n }\n return undefined;\n}\n\n/**\n * @ru Декодирует тело запроса по content-type.\n * @en Decodes the request body based on content-type.\n */\nfunction parseTextBody(\n headers: Readonly<Record<string, string | string[]>>,\n text: string,\n): unknown {\n const contentType = getHeaderValue(headers, \"content-type\") ?? \"\";\n if (contentType.includes(JSON_TYPE)) {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n return text;\n}\n\nfunction decodeBody(raw: TransportRequest): unknown {\n const body = raw.body;\n if (body == null) return undefined;\n if (body instanceof Uint8Array) {\n return parseTextBody(raw.headers, decodeUtf8(body));\n }\n if (body instanceof ArrayBuffer) {\n return parseTextBody(raw.headers, decodeArrayBuffer(body));\n }\n if (typeof body === \"string\") return parseTextBody(raw.headers, body);\n return body;\n}\n\n/**\n * @ru REST/HTTP серверный адаптер. Зеркальная к `RestSender` реализация\n * трёхфазного цикла receive → handle → respond.\n * @en REST/HTTP server adapter. Mirror implementation of `RestSender` for the\n * three-phase receive → handle → respond cycle.\n */\nexport class RestReceiver implements HyperReceiver<\n RestServerInput,\n RestServerResponse,\n TransportRequest,\n TransportResponse\n> {\n readonly protocol = \"rest\";\n protected readonly handler?: RestServerHandler;\n\n /**\n * @ru Создаёт REST-ресивер с необязательным application handler.\n * @en Creates a REST receiver with an optional application handler.\n * @param options - Настройки ресивера и его обработчик. @en Receiver settings and its handler.\n */\n constructor(options: { handler?: RestServerHandler } = {}) {\n this.handler = options.handler;\n }\n\n /**\n * @ru Фаза приёма: разбирает сырой запрос транспорта в REST-структуру.\n * @en Receive phase: parses raw transport request into REST input structure.\n */\n receive(raw: TransportRequest, _ctx: ServerRequestContext): RestServerInput {\n const url = new URL(raw.url, \"http://hyperttp.local\");\n\n return {\n method: raw.method,\n path: url.pathname,\n headers: raw.headers,\n query: parseQuery(url.search.slice(1)),\n body: decodeBody(raw),\n };\n }\n\n /**\n * @ru Фаза обработки: вызывает зарегистрированный handler.\n * @en Handle phase: executes the registered application handler.\n */\n handle(\n request: RestServerInput,\n ctx: ServerRequestContext,\n ): RestServerResponse | Promise<RestServerResponse> {\n if (ctx.signal?.aborted) {\n throw ctx.signal.reason ?? new Error(\"Request aborted\");\n }\n\n if (!this.handler) {\n throw new HyperClientError(\n '[RestReceiver] No application handler registered for protocol \"rest\".',\n );\n }\n\n return this.handler(request, ctx);\n }\n\n /**\n * @ru Фаза ответа: сериализует протокольный ответ в транспортный формат.\n * @en Respond phase: serializes protocol response to raw transport format.\n */\n respond(response: RestServerResponse, _ctx: ServerRequestContext): TransportResponse {\n const headers: Record<string, string> = { ...response.headers };\n const status = response.status ?? 200;\n\n let body: unknown = response.body;\n if (body instanceof ArrayBuffer) {\n body = new Uint8Array(body);\n } else if (ArrayBuffer.isView(body) && !(body instanceof Uint8Array)) {\n body = new Uint8Array(body.buffer, body.byteOffset, body.byteLength).slice();\n } else if (body != null && typeof body === \"object\" && !(body instanceof Uint8Array)) {\n body = JSON.stringify(body);\n const hasContentType = Object.keys(headers).some((k) => k.toLowerCase() === \"content-type\");\n if (!hasContentType) headers[\"content-type\"] = JSON_TYPE;\n }\n\n return {\n status,\n statusText: defaultStatusTexts[status] ?? \"\",\n headers,\n body: body == null ? undefined : body instanceof Uint8Array ? body : encodeUtf8(String(body)),\n };\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["HyperClientError", "JSON_TYPE", "TEXT_DECODER", "TEXT_ENCODER", "HAS_BUFFER", "decodeUtf8", "bytes", "decodeArrayBuffer", "ab", "encodeUtf8", "str", "defaultStatusTexts", "parseQuery", "queryString", "out", "key", "value", "existing", "getHeaderValue", "headers", "name", "direct", "targetKey", "val", "parseTextBody", "text", "decodeBody", "raw", "body", "options", "_ctx", "url", "request", "ctx", "response", "status", "k"]
|
|
7
7
|
}
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
import type { HyperSender, HyperTransport, RequestContext, SendRequest, TransportRequest, TransportResponse, UniversalResponse } from "@hyperttp/types";
|
|
2
2
|
import type { RestInput } from "./type.js";
|
|
3
|
+
/**
|
|
4
|
+
* @ru Опции REST-сендера. Транспорт выбирается ядром; поле `transport` сохранено
|
|
5
|
+
* для совместимости с пользовательскими конфигурациями.
|
|
6
|
+
* @en REST sender options. The core selects the transport; `transport` remains
|
|
7
|
+
* for compatibility with custom configurations.
|
|
8
|
+
*/
|
|
3
9
|
export interface RestSenderOptions {
|
|
10
|
+
/** @ru Пользовательский транспорт. @en Custom transport. */
|
|
4
11
|
transport?: HyperTransport;
|
|
5
12
|
[key: string]: unknown;
|
|
6
13
|
}
|
|
7
14
|
export declare class RestSender implements HyperSender<RestInput, unknown, TransportRequest, TransportResponse> {
|
|
8
15
|
readonly protocol = "rest";
|
|
9
16
|
protected readonly options?: RestSenderOptions;
|
|
17
|
+
/**
|
|
18
|
+
* @ru Создаёт REST-сендер с необязательными пользовательскими настройками.
|
|
19
|
+
* @en Creates a REST sender with optional custom settings.
|
|
20
|
+
* @param options - Настройки сендера. @en Sender settings.
|
|
21
|
+
*/
|
|
10
22
|
constructor(options?: RestSenderOptions);
|
|
11
23
|
readonly methods: Readonly<Record<string, (...args: any[]) => any>>;
|
|
12
24
|
prepare(request: SendRequest<RestInput, string>, ctx: RequestContext): TransportRequest;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sender.d.ts","sourceRoot":"","sources":["../../../src/protocols/rest/sender.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EAEd,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,SAAS,EAAkC,MAAM,WAAW,CAAC;AAgB3E,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AA4DD,qBAAa,UAAW,YAAW,WAAW,CAC5C,SAAS,EACT,OAAO,EACP,gBAAgB,EAChB,iBAAiB,CAClB;IACC,QAAQ,CAAC,QAAQ,UAAU;IAC3B,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAE/C,YAAY,OAAO,CAAC,EAAE,iBAAiB,EAEtC;IAED,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,CAyGjE;IAEF,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,cAAc,GAAG,gBAAgB,CAgEtF;IAEK,IAAI,CACR,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE,cAAc,EACzB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAiB5B;IAED,KAAK,CAAC,GAAG,EAAE,iBAAiB,EAAE,IAAI,EAAE,cAAc,GAAG,iBAAiB,CAAC,OAAO,CAAC,CA6B9E;IAED,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,QAAQ;IAuChB,OAAO,CAAC,cAAc;CAevB"}
|
|
1
|
+
{"version":3,"file":"sender.d.ts","sourceRoot":"","sources":["../../../src/protocols/rest/sender.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EAEd,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,SAAS,EAAkC,MAAM,WAAW,CAAC;AAgB3E;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AA4DD,qBAAa,UAAW,YAAW,WAAW,CAC5C,SAAS,EACT,OAAO,EACP,gBAAgB,EAChB,iBAAiB,CAClB;IACC,QAAQ,CAAC,QAAQ,UAAU;IAC3B,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAE/C;;;;OAIG;IACH,YAAY,OAAO,CAAC,EAAE,iBAAiB,EAEtC;IAED,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,CAyGjE;IAEF,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,cAAc,GAAG,gBAAgB,CAgEtF;IAEK,IAAI,CACR,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE,cAAc,EACzB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAiB5B;IAED,KAAK,CAAC,GAAG,EAAE,iBAAiB,EAAE,IAAI,EAAE,cAAc,GAAG,iBAAiB,CAAC,OAAO,CAAC,CA6B9E;IAED,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,QAAQ;IAuChB,OAAO,CAAC,cAAc;CAevB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/protocols/rest/sender.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n HyperSender,\n HyperTransport,\n IHyperCore,\n RequestContext,\n SendRequest,\n TransportRequest,\n TransportResponse,\n UniversalResponse,\n} from \"@hyperttp/types\";\nimport type { RestInput, RestRequestOptions, HttpMethod } from \"./type.js\";\nimport { TimeoutError } from \"../../utils/errors.js\";\nimport { applyTimeout } from \"../../utils/abort.js\";\n\nconst STREAM_HINT = \"rest:stream\";\nconst TEXT_DECODER = new TextDecoder();\nconst REQUEST_CLEANUPS = new WeakMap<TransportRequest, () => void>();\n\ntype RestTransportRequest = TransportRequest & {\n stream?: boolean;\n};\n\ntype RestTransportResponse = TransportResponse & {\n [STREAM_HINT]?: boolean;\n};\n\nexport interface RestSenderOptions {\n transport?: HyperTransport;\n [key: string]: unknown;\n}\n\nconst defaultStatusTexts: Record<number, string> = {\n 200: \"OK\",\n 201: \"Created\",\n 204: \"No Content\",\n 400: \"Bad Request\",\n 401: \"Unauthorized\",\n 403: \"Forbidden\",\n 404: \"Not Found\",\n 500: \"Internal Server Error\",\n};\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") {\n return false;\n }\n const proto = Object.getPrototypeOf(value);\n return proto === null || proto === Object.prototype;\n}\n\nasync function collectBody(body: unknown): Promise<unknown> {\n if (body instanceof Uint8Array) return body;\n if (body instanceof ArrayBuffer) return new Uint8Array(body);\n if (ArrayBuffer.isView(body)) {\n return new Uint8Array(body.buffer, body.byteOffset, body.byteLength).slice();\n }\n\n if (body && typeof body === \"object\" && \"arrayBuffer\" in body) {\n const arrayBuffer = (body as { arrayBuffer?: unknown }).arrayBuffer;\n if (typeof arrayBuffer === \"function\") {\n return new Uint8Array(await arrayBuffer.call(body));\n }\n }\n\n if (typeof ReadableStream !== \"undefined\" && body instanceof ReadableStream) {\n const reader = body.getReader();\n const chunks: Uint8Array[] = [];\n let totalLength = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n const chunk = value instanceof Uint8Array ? value : new Uint8Array(value);\n chunks.push(chunk);\n totalLength += chunk.byteLength;\n }\n\n const collected = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n collected.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return collected;\n }\n\n return body;\n}\n\nexport class RestSender implements HyperSender<\n RestInput,\n unknown,\n TransportRequest,\n TransportResponse\n> {\n readonly protocol = \"rest\";\n protected readonly options?: RestSenderOptions;\n\n constructor(options?: RestSenderOptions) {\n this.options = options;\n }\n\n readonly methods: Readonly<Record<string, (...args: any[]) => any>> = {\n get: (core: IHyperCore, url: string, options?: RestRequestOptions, signal?: AbortSignal) =>\n this.dispatch(core, { method: \"GET\", url, ...options, signal: signal ?? options?.signal }),\n\n post: (\n core: IHyperCore,\n url: string,\n body?: unknown,\n options?: Omit<RestRequestOptions, \"body\">,\n signal?: AbortSignal,\n ) =>\n this.dispatch(core, {\n method: \"POST\",\n url,\n ...options,\n body,\n signal: signal ?? options?.signal,\n }),\n\n put: (\n core: IHyperCore,\n url: string,\n body?: unknown,\n options?: Omit<RestRequestOptions, \"body\">,\n signal?: AbortSignal,\n ) =>\n this.dispatch(core, {\n method: \"PUT\",\n url,\n ...options,\n body,\n signal: signal ?? options?.signal,\n }),\n\n patch: (\n core: IHyperCore,\n url: string,\n body?: unknown,\n options?: Omit<RestRequestOptions, \"body\">,\n signal?: AbortSignal,\n ) =>\n this.dispatch(core, {\n method: \"PATCH\",\n url,\n ...options,\n body,\n signal: signal ?? options?.signal,\n }),\n\n delete: (core: IHyperCore, url: string, options?: RestRequestOptions, signal?: AbortSignal) =>\n this.dispatch(core, { method: \"DELETE\", url, ...options, signal: signal ?? options?.signal }),\n\n head: (core: IHyperCore, url: string, options?: RestRequestOptions, signal?: AbortSignal) =>\n this.dispatch(core, { method: \"HEAD\", url, ...options, signal: signal ?? options?.signal }),\n\n options: (core: IHyperCore, url: string, options?: RestRequestOptions, signal?: AbortSignal) =>\n this.dispatch(core, {\n method: \"OPTIONS\",\n url,\n ...options,\n signal: signal ?? options?.signal,\n }),\n\n query: (\n core: IHyperCore,\n url: string,\n body?: unknown,\n options?: Omit<RestRequestOptions, \"body\">,\n signal?: AbortSignal,\n ) =>\n this.dispatch(core, {\n method: \"QUERY\",\n url,\n ...options,\n body,\n signal: signal ?? options?.signal,\n }),\n\n request: (\n core: IHyperCore,\n method: HttpMethod | (string & {}),\n url: string,\n options?: RestRequestOptions,\n signal?: AbortSignal,\n ) =>\n this.dispatch(core, {\n method: method as HttpMethod,\n url,\n ...options,\n signal: signal ?? options?.signal,\n }),\n\n stream: (\n core: IHyperCore,\n url: string,\n options?: Omit<RestRequestOptions, \"stream\">,\n signal?: AbortSignal,\n ) =>\n this.dispatch(core, {\n method: \"GET\",\n url,\n ...options,\n stream: true,\n signal: signal ?? options?.signal,\n }),\n };\n\n prepare(request: SendRequest<RestInput, string>, ctx: RequestContext): TransportRequest {\n const { input } = request;\n const inputSignal = request.signal ?? input.signal ?? ctx.signal;\n const timeout = input.timeout;\n let cleanupSignal: (() => void) | undefined;\n let signal = inputSignal;\n\n if (timeout != null && timeout > 0) {\n const timeoutMeta: { cleanupSignal?: () => void } = {};\n signal = applyTimeout(\n inputSignal,\n timeout,\n timeoutMeta,\n () => new TimeoutError(input.url, timeout),\n );\n cleanupSignal = timeoutMeta.cleanupSignal;\n }\n\n const headers: Record<string, string> = {};\n\n if (input.headers) {\n if (input.headers instanceof Headers) {\n input.headers.forEach((value, key) => {\n headers[key.toLowerCase()] = value;\n });\n } else if (Array.isArray(input.headers)) {\n for (const [key, value] of input.headers) {\n headers[key.toLowerCase()] = value;\n }\n } else {\n for (const key in input.headers) {\n const value = (input.headers as Record<string, unknown>)[key];\n\n if (value != null) {\n headers[key.toLowerCase()] = String(value);\n }\n }\n }\n }\n\n let body = input.body;\n\n if (body !== undefined && body !== null && (isPlainObject(body) || Array.isArray(body))) {\n body = JSON.stringify(body);\n if (!headers[\"content-type\"]) {\n headers[\"content-type\"] = \"application/json; charset=utf-8\";\n }\n }\n\n const prepared = {\n method: input.method.toUpperCase(),\n url: this.buildUrl(input.url, input.query),\n headers,\n body,\n signal,\n protocol: this.protocol,\n stream: input.stream,\n stealth: (input as any).stealth,\n followRedirects: input.followRedirects,\n maxRedirects: input.maxRedirects,\n } as RestTransportRequest;\n\n if (cleanupSignal) REQUEST_CLEANUPS.set(prepared, cleanupSignal);\n return prepared;\n }\n\n async send(\n prepared: TransportRequest,\n transport: HyperTransport,\n _ctx: RequestContext,\n ): Promise<TransportResponse> {\n const restRequest = prepared as RestTransportRequest;\n try {\n const response = await transport.execute(prepared);\n if (restRequest.stream) {\n return { ...response, [STREAM_HINT]: true } as RestTransportResponse;\n }\n\n const body = await collectBody(response.body);\n return body === response.body ? response : { ...response, body };\n } finally {\n const cleanup = REQUEST_CLEANUPS.get(prepared);\n if (cleanup) {\n REQUEST_CLEANUPS.delete(prepared);\n cleanup();\n }\n }\n }\n\n parse(raw: TransportResponse, _ctx: RequestContext): UniversalResponse<unknown> {\n const ok = raw.status >= 200 && raw.status < 300;\n let parsedData: unknown = raw.body;\n\n if (!(raw as RestTransportResponse)[STREAM_HINT] && raw.body instanceof Uint8Array) {\n const contentType = this.getHeaderValue(raw.headers, \"content-type\") ?? \"\";\n const text = TEXT_DECODER.decode(raw.body);\n\n if (contentType.includes(\"application/json\")) {\n try {\n parsedData = JSON.parse(text);\n } catch {\n parsedData = text;\n }\n } else if (contentType.includes(\"text/\") || contentType.includes(\"application/xml\")) {\n parsedData = text;\n }\n }\n\n return {\n protocol: this.protocol,\n ok,\n status: raw.status,\n statusText: raw.statusText || defaultStatusTexts[raw.status] || \"\",\n headers: raw.headers,\n url: raw.url,\n data: parsedData,\n raw,\n };\n }\n\n private dispatch(core: IHyperCore, input: RestInput): Promise<UniversalResponse<unknown>> {\n return core.send<RestInput, unknown, \"rest\">({\n protocol: \"rest\",\n input,\n signal: input.signal,\n });\n }\n\n private buildUrl(baseUrl: string, query?: RestInput[\"query\"]): string {\n if (!query) {\n return baseUrl;\n }\n\n const parts: string[] = [];\n\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n const values = Array.isArray(value) ? value : [value];\n\n for (const v of values) {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(v))}`);\n }\n }\n\n if (parts.length === 0) {\n return baseUrl;\n }\n\n const queryString = parts.join(\"&\");\n const hashIndex = baseUrl.indexOf(\"#\");\n\n if (hashIndex !== -1) {\n const urlBeforeHash = baseUrl.slice(0, hashIndex);\n const hashPart = baseUrl.slice(hashIndex);\n const separator = urlBeforeHash.includes(\"?\") ? \"&\" : \"?\";\n\n return `${urlBeforeHash}${separator}${queryString}${hashPart}`;\n }\n\n const separator = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n\n return `${baseUrl}${separator}${queryString}`;\n }\n\n private getHeaderValue(\n headers: Record<string, string | string[]>,\n name: string,\n ): string | undefined {\n const target = name.toLowerCase();\n const direct = headers[target] ?? headers[name];\n if (direct !== undefined) return Array.isArray(direct) ? direct[0] : direct;\n\n for (const key in headers) {\n if (key.toLowerCase() !== target) continue;\n const value = headers[key];\n return Array.isArray(value) ? value[0] : value;\n }\n return undefined;\n }\n}\n"],
|
|
5
|
-
"mappings": "aAWA,OAAS,gBAAAA,MAAoB,wBAC7B,OAAS,gBAAAC,MAAoB,uBAE7B,MAAMC,EAAc,cACdC,EAAe,IAAI,YACnBC,EAAmB,IAAI,
|
|
4
|
+
"sourcesContent": ["import type {\n HyperSender,\n HyperTransport,\n IHyperCore,\n RequestContext,\n SendRequest,\n TransportRequest,\n TransportResponse,\n UniversalResponse,\n} from \"@hyperttp/types\";\nimport type { RestInput, RestRequestOptions, HttpMethod } from \"./type.js\";\nimport { TimeoutError } from \"../../utils/errors.js\";\nimport { applyTimeout } from \"../../utils/abort.js\";\n\nconst STREAM_HINT = \"rest:stream\";\nconst TEXT_DECODER = new TextDecoder();\nconst REQUEST_CLEANUPS = new WeakMap<TransportRequest, () => void>();\n\ntype RestTransportRequest = TransportRequest & {\n stream?: boolean;\n};\n\ntype RestTransportResponse = TransportResponse & {\n [STREAM_HINT]?: boolean;\n};\n\n/**\n * @ru Опции REST-сендера. Транспорт выбирается ядром; поле `transport` сохранено\n * для совместимости с пользовательскими конфигурациями.\n * @en REST sender options. The core selects the transport; `transport` remains\n * for compatibility with custom configurations.\n */\nexport interface RestSenderOptions {\n /** @ru Пользовательский транспорт. @en Custom transport. */\n transport?: HyperTransport;\n [key: string]: unknown;\n}\n\nconst defaultStatusTexts: Record<number, string> = {\n 200: \"OK\",\n 201: \"Created\",\n 204: \"No Content\",\n 400: \"Bad Request\",\n 401: \"Unauthorized\",\n 403: \"Forbidden\",\n 404: \"Not Found\",\n 500: \"Internal Server Error\",\n};\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") {\n return false;\n }\n const proto = Object.getPrototypeOf(value);\n return proto === null || proto === Object.prototype;\n}\n\nasync function collectBody(body: unknown): Promise<unknown> {\n if (body instanceof Uint8Array) return body;\n if (body instanceof ArrayBuffer) return new Uint8Array(body);\n if (ArrayBuffer.isView(body)) {\n return new Uint8Array(body.buffer, body.byteOffset, body.byteLength).slice();\n }\n\n if (body && typeof body === \"object\" && \"arrayBuffer\" in body) {\n const arrayBuffer = (body as { arrayBuffer?: unknown }).arrayBuffer;\n if (typeof arrayBuffer === \"function\") {\n return new Uint8Array(await arrayBuffer.call(body));\n }\n }\n\n if (typeof ReadableStream !== \"undefined\" && body instanceof ReadableStream) {\n const reader = body.getReader();\n const chunks: Uint8Array[] = [];\n let totalLength = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n const chunk = value instanceof Uint8Array ? value : new Uint8Array(value);\n chunks.push(chunk);\n totalLength += chunk.byteLength;\n }\n\n const collected = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n collected.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return collected;\n }\n\n return body;\n}\n\nexport class RestSender implements HyperSender<\n RestInput,\n unknown,\n TransportRequest,\n TransportResponse\n> {\n readonly protocol = \"rest\";\n protected readonly options?: RestSenderOptions;\n\n /**\n * @ru Создаёт REST-сендер с необязательными пользовательскими настройками.\n * @en Creates a REST sender with optional custom settings.\n * @param options - Настройки сендера. @en Sender settings.\n */\n constructor(options?: RestSenderOptions) {\n this.options = options;\n }\n\n readonly methods: Readonly<Record<string, (...args: any[]) => any>> = {\n get: (core: IHyperCore, url: string, options?: RestRequestOptions, signal?: AbortSignal) =>\n this.dispatch(core, { method: \"GET\", url, ...options, signal: signal ?? options?.signal }),\n\n post: (\n core: IHyperCore,\n url: string,\n body?: unknown,\n options?: Omit<RestRequestOptions, \"body\">,\n signal?: AbortSignal,\n ) =>\n this.dispatch(core, {\n method: \"POST\",\n url,\n ...options,\n body,\n signal: signal ?? options?.signal,\n }),\n\n put: (\n core: IHyperCore,\n url: string,\n body?: unknown,\n options?: Omit<RestRequestOptions, \"body\">,\n signal?: AbortSignal,\n ) =>\n this.dispatch(core, {\n method: \"PUT\",\n url,\n ...options,\n body,\n signal: signal ?? options?.signal,\n }),\n\n patch: (\n core: IHyperCore,\n url: string,\n body?: unknown,\n options?: Omit<RestRequestOptions, \"body\">,\n signal?: AbortSignal,\n ) =>\n this.dispatch(core, {\n method: \"PATCH\",\n url,\n ...options,\n body,\n signal: signal ?? options?.signal,\n }),\n\n delete: (core: IHyperCore, url: string, options?: RestRequestOptions, signal?: AbortSignal) =>\n this.dispatch(core, { method: \"DELETE\", url, ...options, signal: signal ?? options?.signal }),\n\n head: (core: IHyperCore, url: string, options?: RestRequestOptions, signal?: AbortSignal) =>\n this.dispatch(core, { method: \"HEAD\", url, ...options, signal: signal ?? options?.signal }),\n\n options: (core: IHyperCore, url: string, options?: RestRequestOptions, signal?: AbortSignal) =>\n this.dispatch(core, {\n method: \"OPTIONS\",\n url,\n ...options,\n signal: signal ?? options?.signal,\n }),\n\n query: (\n core: IHyperCore,\n url: string,\n body?: unknown,\n options?: Omit<RestRequestOptions, \"body\">,\n signal?: AbortSignal,\n ) =>\n this.dispatch(core, {\n method: \"QUERY\",\n url,\n ...options,\n body,\n signal: signal ?? options?.signal,\n }),\n\n request: (\n core: IHyperCore,\n method: HttpMethod | (string & {}),\n url: string,\n options?: RestRequestOptions,\n signal?: AbortSignal,\n ) =>\n this.dispatch(core, {\n method: method as HttpMethod,\n url,\n ...options,\n signal: signal ?? options?.signal,\n }),\n\n stream: (\n core: IHyperCore,\n url: string,\n options?: Omit<RestRequestOptions, \"stream\">,\n signal?: AbortSignal,\n ) =>\n this.dispatch(core, {\n method: \"GET\",\n url,\n ...options,\n stream: true,\n signal: signal ?? options?.signal,\n }),\n };\n\n prepare(request: SendRequest<RestInput, string>, ctx: RequestContext): TransportRequest {\n const { input } = request;\n const inputSignal = request.signal ?? input.signal ?? ctx.signal;\n const timeout = input.timeout;\n let cleanupSignal: (() => void) | undefined;\n let signal = inputSignal;\n\n if (timeout != null && timeout > 0) {\n const timeoutMeta: { cleanupSignal?: () => void } = {};\n signal = applyTimeout(\n inputSignal,\n timeout,\n timeoutMeta,\n () => new TimeoutError(input.url, timeout),\n );\n cleanupSignal = timeoutMeta.cleanupSignal;\n }\n\n const headers: Record<string, string> = {};\n\n if (input.headers) {\n if (input.headers instanceof Headers) {\n input.headers.forEach((value, key) => {\n headers[key.toLowerCase()] = value;\n });\n } else if (Array.isArray(input.headers)) {\n for (const [key, value] of input.headers) {\n headers[key.toLowerCase()] = value;\n }\n } else {\n for (const key in input.headers) {\n const value = (input.headers as Record<string, unknown>)[key];\n\n if (value != null) {\n headers[key.toLowerCase()] = String(value);\n }\n }\n }\n }\n\n let body = input.body;\n\n if (body !== undefined && body !== null && (isPlainObject(body) || Array.isArray(body))) {\n body = JSON.stringify(body);\n if (!headers[\"content-type\"]) {\n headers[\"content-type\"] = \"application/json; charset=utf-8\";\n }\n }\n\n const prepared = {\n method: input.method.toUpperCase(),\n url: this.buildUrl(input.url, input.query),\n headers,\n body,\n signal,\n protocol: this.protocol,\n stream: input.stream,\n stealth: (input as any).stealth,\n followRedirects: input.followRedirects,\n maxRedirects: input.maxRedirects,\n } as RestTransportRequest;\n\n if (cleanupSignal) REQUEST_CLEANUPS.set(prepared, cleanupSignal);\n return prepared;\n }\n\n async send(\n prepared: TransportRequest,\n transport: HyperTransport,\n _ctx: RequestContext,\n ): Promise<TransportResponse> {\n const restRequest = prepared as RestTransportRequest;\n try {\n const response = await transport.execute(prepared);\n if (restRequest.stream) {\n return { ...response, [STREAM_HINT]: true } as RestTransportResponse;\n }\n\n const body = await collectBody(response.body);\n return body === response.body ? response : { ...response, body };\n } finally {\n const cleanup = REQUEST_CLEANUPS.get(prepared);\n if (cleanup) {\n REQUEST_CLEANUPS.delete(prepared);\n cleanup();\n }\n }\n }\n\n parse(raw: TransportResponse, _ctx: RequestContext): UniversalResponse<unknown> {\n const ok = raw.status >= 200 && raw.status < 300;\n let parsedData: unknown = raw.body;\n\n if (!(raw as RestTransportResponse)[STREAM_HINT] && raw.body instanceof Uint8Array) {\n const contentType = this.getHeaderValue(raw.headers, \"content-type\") ?? \"\";\n const text = TEXT_DECODER.decode(raw.body);\n\n if (contentType.includes(\"application/json\")) {\n try {\n parsedData = JSON.parse(text);\n } catch {\n parsedData = text;\n }\n } else if (contentType.includes(\"text/\") || contentType.includes(\"application/xml\")) {\n parsedData = text;\n }\n }\n\n return {\n protocol: this.protocol,\n ok,\n status: raw.status,\n statusText: raw.statusText || defaultStatusTexts[raw.status] || \"\",\n headers: raw.headers,\n url: raw.url,\n data: parsedData,\n raw,\n };\n }\n\n private dispatch(core: IHyperCore, input: RestInput): Promise<UniversalResponse<unknown>> {\n return core.send<RestInput, unknown, \"rest\">({\n protocol: \"rest\",\n input,\n signal: input.signal,\n });\n }\n\n private buildUrl(baseUrl: string, query?: RestInput[\"query\"]): string {\n if (!query) {\n return baseUrl;\n }\n\n const parts: string[] = [];\n\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) {\n continue;\n }\n\n const values = Array.isArray(value) ? value : [value];\n\n for (const v of values) {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(v))}`);\n }\n }\n\n if (parts.length === 0) {\n return baseUrl;\n }\n\n const queryString = parts.join(\"&\");\n const hashIndex = baseUrl.indexOf(\"#\");\n\n if (hashIndex !== -1) {\n const urlBeforeHash = baseUrl.slice(0, hashIndex);\n const hashPart = baseUrl.slice(hashIndex);\n const separator = urlBeforeHash.includes(\"?\") ? \"&\" : \"?\";\n\n return `${urlBeforeHash}${separator}${queryString}${hashPart}`;\n }\n\n const separator = baseUrl.includes(\"?\") ? \"&\" : \"?\";\n\n return `${baseUrl}${separator}${queryString}`;\n }\n\n private getHeaderValue(\n headers: Record<string, string | string[]>,\n name: string,\n ): string | undefined {\n const target = name.toLowerCase();\n const direct = headers[target] ?? headers[name];\n if (direct !== undefined) return Array.isArray(direct) ? direct[0] : direct;\n\n for (const key in headers) {\n if (key.toLowerCase() !== target) continue;\n const value = headers[key];\n return Array.isArray(value) ? value[0] : value;\n }\n return undefined;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["TimeoutError", "applyTimeout", "STREAM_HINT", "TEXT_DECODER", "REQUEST_CLEANUPS", "defaultStatusTexts", "isPlainObject", "value", "proto", "collectBody", "body", "arrayBuffer", "reader", "chunks", "totalLength", "done", "chunk", "collected", "offset", "options", "core", "url", "signal", "method", "request", "ctx", "input", "inputSignal", "timeout", "cleanupSignal", "timeoutMeta", "headers", "key", "prepared", "transport", "_ctx", "restRequest", "response", "cleanup", "raw", "ok", "parsedData", "contentType", "text", "baseUrl", "query", "parts", "values", "v", "queryString", "hashIndex", "urlBeforeHash", "hashPart", "separator", "name", "target", "direct"]
|
|
7
7
|
}
|
package/protocols/rest/type.d.ts
CHANGED
|
@@ -1,17 +1,49 @@
|
|
|
1
1
|
import type { HyperSender, ServerRequestContext, UniversalResponse } from "@hyperttp/types";
|
|
2
|
+
/**
|
|
3
|
+
* @ru Поддерживаемый HTTP-метод REST-запроса. `QUERY` предназначен для совместимых
|
|
4
|
+
* с ним серверов и прокси.
|
|
5
|
+
* @en Supported HTTP method for a REST request. `QUERY` is intended for servers
|
|
6
|
+
* and proxies that support it.
|
|
7
|
+
*/
|
|
2
8
|
export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS" | "QUERY";
|
|
9
|
+
/**
|
|
10
|
+
* @ru Входные данные REST-запроса, используемые `core.send()` и методами `core.rest`.
|
|
11
|
+
* @en REST request input used by `core.send()` and `core.rest` methods.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* core.send({
|
|
15
|
+
* protocol: "rest",
|
|
16
|
+
* input: { method: "POST", url: "https://api.example.test/items", body: { name: "item" } },
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* @template TBody - Тип тела запроса до сериализации.
|
|
20
|
+
*/
|
|
3
21
|
export interface RestInput<TBody = unknown> {
|
|
22
|
+
/** @ru HTTP-метод запроса. @en HTTP method for the request. */
|
|
4
23
|
method: HttpMethod;
|
|
24
|
+
/** @ru Абсолютный или относительный URL. @en Absolute or relative URL. */
|
|
5
25
|
url: string;
|
|
26
|
+
/** @ru Заголовки запроса. @en Request headers. */
|
|
6
27
|
headers?: Record<string, string>;
|
|
28
|
+
/** @ru Query-параметры, добавляемые к URL. @en Query parameters appended to the URL. */
|
|
7
29
|
query?: Record<string, string | number | boolean | (string | number | boolean)[]>;
|
|
30
|
+
/** @ru Тело запроса; plain object и массив сериализуются в JSON. @en Request body; plain objects and arrays are serialized as JSON. */
|
|
8
31
|
body?: TBody;
|
|
32
|
+
/** @ru Таймаут в миллисекундах. @en Timeout in milliseconds. */
|
|
9
33
|
timeout?: number;
|
|
34
|
+
/** @ru Не буферизовать тело ответа и вернуть поток транспорта. @en Do not buffer the response body and return the transport stream. */
|
|
10
35
|
stream?: boolean;
|
|
36
|
+
/** @ru Отключает автоматические redirect-ы транспорта. @en Disables automatic transport redirects. */
|
|
11
37
|
followRedirects?: boolean;
|
|
38
|
+
/** @ru Максимальное число redirect-ов, если транспорт поддерживает настройку. @en Maximum redirect count when supported by the transport. */
|
|
12
39
|
maxRedirects?: number;
|
|
40
|
+
/** @ru Сигнал отмены запроса. @en Request cancellation signal. */
|
|
13
41
|
signal?: AbortSignal;
|
|
14
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* @ru Опции shortcut-методов REST без `method` и `url`.
|
|
45
|
+
* @en REST shortcut-method options excluding `method` and `url`.
|
|
46
|
+
*/
|
|
15
47
|
export type RestRequestOptions = Omit<RestInput, "method" | "url">;
|
|
16
48
|
/**
|
|
17
49
|
* @ru Разобранный серверный REST-запрос, получаемый ресивером из сырого транспорта.
|
|
@@ -41,7 +73,15 @@ export interface RestServerResponse {
|
|
|
41
73
|
* @returns The response to serialize.
|
|
42
74
|
*/
|
|
43
75
|
export type RestServerHandler = (request: RestServerInput, ctx: ServerRequestContext) => RestServerResponse | Promise<RestServerResponse>;
|
|
76
|
+
/**
|
|
77
|
+
* @ru Типизированная поверхность shortcut-методов REST, доступная как `core.rest`.
|
|
78
|
+
* @en Typed REST shortcut-method surface available as `core.rest`.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* const response = await core.rest.get<{ id: string }>("https://api.example.test/items/1");
|
|
82
|
+
*/
|
|
44
83
|
export interface RestClientMethods {
|
|
84
|
+
/** @ru Выполняет GET-запрос. @en Performs a GET request. */
|
|
45
85
|
get<T = unknown>(url: string, options?: RestRequestOptions, signal?: AbortSignal): Promise<UniversalResponse<T>>;
|
|
46
86
|
post<T = unknown>(url: string, body?: unknown, options?: Omit<RestRequestOptions, "body">, signal?: AbortSignal): Promise<UniversalResponse<T>>;
|
|
47
87
|
put<T = unknown>(url: string, body?: unknown, options?: Omit<RestRequestOptions, "body">, signal?: AbortSignal): Promise<UniversalResponse<T>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../../src/protocols/rest/type.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../../src/protocols/rest/type.ts"],"names":[],"mappings":"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"}
|
package/transports/fetch.d.ts
CHANGED
|
@@ -5,6 +5,12 @@ export interface FetchTransportOptions {
|
|
|
5
5
|
* @en Custom list of supported protocols.
|
|
6
6
|
*/
|
|
7
7
|
protocols?: SenderProtocol[];
|
|
8
|
+
/**
|
|
9
|
+
* @ru Максимальный размер входящего серверного тела в байтах. Превышение
|
|
10
|
+
* возвращает HTTP 413 до передачи тела обработчику.
|
|
11
|
+
* @en Maximum incoming server request body size in bytes. Exceeding it returns
|
|
12
|
+
* HTTP 413 before the body reaches the handler.
|
|
13
|
+
*/
|
|
8
14
|
maxBodyBytes?: number;
|
|
9
15
|
}
|
|
10
16
|
/**
|
|
@@ -16,6 +22,11 @@ export interface FetchTransportOptions {
|
|
|
16
22
|
export declare class FetchTransport implements HyperTransport {
|
|
17
23
|
readonly protocols: readonly SenderProtocol[];
|
|
18
24
|
private readonly maxBodyBytes;
|
|
25
|
+
/**
|
|
26
|
+
* @ru Создаёт fallback-транспорт на базе глобального `fetch`.
|
|
27
|
+
* @en Creates a fallback transport based on global `fetch`.
|
|
28
|
+
* @param options - Поддерживаемые протоколы и серверный лимит тела. @en Supported protocols and server body limit.
|
|
29
|
+
*/
|
|
19
30
|
constructor(options?: FetchTransportOptions);
|
|
20
31
|
execute(req: TransportRequest): Promise<TransportResponse>;
|
|
21
32
|
listen(options: TransportListenOptions): Promise<TransportServer>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/transports/fetch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAIzB,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAgBD;;;;;GAKG;AACH,qBAAa,cAAe,YAAW,cAAc;IACnD,SAAgB,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IACrD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IAEtC,YAAY,OAAO,GAAE,qBAA0B,EAG9C;IAEY,OAAO,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA4CtE;IAEY,MAAM,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,eAAe,CAAC,CAiJ7E;IAEY,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAG;CACvC"}
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/transports/fetch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAIzB,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;IAC7B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAgBD;;;;;GAKG;AACH,qBAAa,cAAe,YAAW,cAAc;IACnD,SAAgB,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IACrD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IAEtC;;;;OAIG;IACH,YAAY,OAAO,GAAE,qBAA0B,EAG9C;IAEY,OAAO,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA4CtE;IAEY,MAAM,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,eAAe,CAAC,CAiJ7E;IAEY,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAG;CACvC"}
|
package/transports/fetch.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/transports/fetch.ts"],
|
|
4
|
-
"sourcesContent": ["import type { IncomingMessage, OutgoingHttpHeaders, ServerResponse } from \"node:http\";\nimport type {\n HyperTransport,\n SenderProtocol,\n TransportListenOptions,\n TransportRequest,\n TransportResponse,\n TransportServer,\n} from \"@hyperttp/types\";\n\nconst DEFAULT_MAX_BODY_BYTES = 10 * 1024 * 1024;\n\nexport interface FetchTransportOptions {\n /**\n * @ru Кастомный список поддерживаемых протоколов.\n * @en Custom list of supported protocols.\n */\n protocols?: SenderProtocol[];\n maxBodyBytes?: number;\n}\n\ntype ExtendedTransportRequest = TransportRequest & {\n stream?: boolean;\n followRedirects?: boolean;\n};\n\nasync function loadNodeHttp(): Promise<typeof import(\"node:http\")> {\n if (typeof process === \"undefined\" || !process.versions?.node) {\n throw new Error(\"[FetchTransport] listen() is only available in Node.js.\");\n }\n\n const specifier = \"node:http\";\n return import(/* @vite-ignore */ specifier);\n}\n\n/**\n * @ru Минимальный транспорт на базе нативного fetch. Гарантированный fallback,\n * когда ни один пакетный транспорт (@hyperttp/transport-undici/bun) не установлен.\n * @en Minimal native fetch-based transport. A guaranteed fallback used when no\n * packaged transport (@hyperttp/transport-undici/bun) is installed.\n */\nexport class FetchTransport implements HyperTransport {\n public readonly protocols: readonly SenderProtocol[];\n private readonly maxBodyBytes: number;\n\n constructor(options: FetchTransportOptions = {}) {\n this.protocols = Object.freeze(options.protocols ?? [\"rest\"]);\n this.maxBodyBytes = options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;\n }\n\n public async execute(req: TransportRequest): Promise<TransportResponse> {\n const extendedRequest = req as ExtendedTransportRequest;\n const isBodyAllowed = req.method !== \"GET\" && req.method !== \"HEAD\";\n\n const res = await fetch(req.url, {\n method: req.method,\n headers: req.headers as Record<string, string>,\n body: isBodyAllowed ? ((req.body ?? null) as BodyInit | null) : null,\n signal: req.signal,\n redirect: extendedRequest.followRedirects === false ? \"manual\" : \"follow\",\n });\n\n const body = extendedRequest.stream ? res.body : new Uint8Array(await res.arrayBuffer());\n const headers: Record<string, string | string[]> = {};\n\n if (typeof res.headers.getSetCookie === \"function\") {\n const cookies = res.headers.getSetCookie();\n if (cookies.length > 0) {\n headers[\"set-cookie\"] = cookies;\n }\n }\n\n res.headers.forEach((value, key) => {\n const lowerKey = key.toLowerCase();\n\n if (lowerKey === \"set-cookie\" && headers[\"set-cookie\"]) {\n return;\n }\n\n if (headers[lowerKey]) {\n const existing = headers[lowerKey];\n headers[lowerKey] = Array.isArray(existing) ? [...existing, value] : [existing, value];\n } else {\n headers[lowerKey] = value;\n }\n });\n\n return {\n status: res.status,\n statusText: res.statusText,\n headers,\n url: res.url,\n body,\n };\n }\n\n public async listen(options: TransportListenOptions): Promise<TransportServer> {\n const { host, port, signal, onRequest } = options;\n if (signal?.aborted) {\n throw signal.reason ?? new DOMException(\"The operation was aborted\", \"AbortError\");\n }\n\n const { createServer } = await loadNodeHttp();\n\n const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n const requestController = new AbortController();\n const abortRequest = () => {\n if (!requestController.signal.aborted) {\n requestController.abort(new DOMException(\"Client disconnected\", \"AbortError\"));\n }\n };\n const abortIncompleteRequest = () => {\n if (!req.complete) abortRequest();\n };\n const abortIncompleteResponse = () => {\n if (!res.writableEnded) abortRequest();\n };\n\n req.once(\"aborted\", abortRequest);\n req.once(\"close\", abortIncompleteRequest);\n res.once(\"close\", abortIncompleteResponse);\n\n try {\n const contentLength = Number(req.headers[\"content-length\"] ?? 0);\n if (Number.isFinite(contentLength) && contentLength > this.maxBodyBytes) {\n res.writeHead(413);\n res.end(\"Payload Too Large\");\n return;\n }\n\n const chunks: Uint8Array[] = [];\n let receivedBytes = 0;\n\n for await (const chunk of req) {\n receivedBytes += chunk.byteLength;\n if (receivedBytes > this.maxBodyBytes) {\n res.writeHead(413);\n res.end(\"Payload Too Large\");\n return;\n }\n chunks.push(chunk);\n }\n\n const body = chunks.length > 0 ? Buffer.concat(chunks) : undefined;\n const headers: Record<string, string | string[]> = {};\n\n for (const [key, value] of Object.entries(req.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n\n const transportRequest: TransportRequest = {\n method: req.method ?? \"GET\",\n url: req.url ?? \"/\",\n headers,\n body,\n signal: requestController.signal,\n protocol: this.protocols[0] ?? \"rest\",\n };\n\n if (!onRequest) {\n res.writeHead(501);\n res.end(\"Not Implemented\");\n return;\n }\n\n const response = await onRequest(transportRequest);\n const outgoingHeaders: OutgoingHttpHeaders = {};\n\n for (const [key, value] of Object.entries(response.headers)) {\n outgoingHeaders[key] = value;\n }\n\n res.writeHead(response.status, response.statusText ?? \"\", outgoingHeaders);\n\n if (response.body != null) {\n if (response.body instanceof Uint8Array) {\n res.end(response.body);\n } else if (typeof response.body === \"string\") {\n res.end(response.body);\n } else {\n res.end(JSON.stringify(response.body));\n }\n } else {\n res.end();\n }\n } catch {\n if (!res.headersSent) {\n res.writeHead(500);\n res.end(\"Internal Server Error\");\n } else {\n res.destroy();\n }\n } finally {\n req.removeListener(\"aborted\", abortRequest);\n req.removeListener(\"close\", abortIncompleteRequest);\n res.removeListener(\"close\", abortIncompleteResponse);\n }\n });\n\n let closed = false;\n const close = (): Promise<void> => {\n if (closed) return Promise.resolve();\n closed = true;\n signal?.removeEventListener(\"abort\", closeOnAbort);\n server.removeListener(\"error\", reportRuntimeError);\n\n if (!server.listening) return Promise.resolve();\n return new Promise<void>((resolveClose, rejectClose) => {\n server.close((error) => {\n if (error) rejectClose(error);\n else resolveClose();\n });\n });\n };\n const closeOnAbort = () => {\n void close();\n };\n const reportRuntimeError = (error: Error) => {\n console.error(\"[FetchTransport] HTTP server error:\", error);\n };\n\n if (signal?.aborted) {\n throw signal.reason ?? new DOMException(\"The operation was aborted\", \"AbortError\");\n }\n signal?.addEventListener(\"abort\", closeOnAbort, { once: true });\n\n return new Promise<TransportServer>((resolve, reject) => {\n const rejectStartup = (error: Error) => {\n signal?.removeEventListener(\"abort\", closeOnAbort);\n reject(error);\n };\n\n server.once(\"error\", rejectStartup);\n server.listen({ host, port }, () => {\n server.removeListener(\"error\", rejectStartup);\n server.on(\"error\", reportRuntimeError);\n resolve({ close });\n });\n });\n }\n\n public async close(): Promise<void> {}\n}\n"],
|
|
5
|
-
"mappings": "aAUA,MAAMA,EAAyB,
|
|
4
|
+
"sourcesContent": ["import type { IncomingMessage, OutgoingHttpHeaders, ServerResponse } from \"node:http\";\nimport type {\n HyperTransport,\n SenderProtocol,\n TransportListenOptions,\n TransportRequest,\n TransportResponse,\n TransportServer,\n} from \"@hyperttp/types\";\n\nconst DEFAULT_MAX_BODY_BYTES = 10 * 1024 * 1024;\n\nexport interface FetchTransportOptions {\n /**\n * @ru Кастомный список поддерживаемых протоколов.\n * @en Custom list of supported protocols.\n */\n protocols?: SenderProtocol[];\n /**\n * @ru Максимальный размер входящего серверного тела в байтах. Превышение\n * возвращает HTTP 413 до передачи тела обработчику.\n * @en Maximum incoming server request body size in bytes. Exceeding it returns\n * HTTP 413 before the body reaches the handler.\n */\n maxBodyBytes?: number;\n}\n\ntype ExtendedTransportRequest = TransportRequest & {\n stream?: boolean;\n followRedirects?: boolean;\n};\n\nasync function loadNodeHttp(): Promise<typeof import(\"node:http\")> {\n if (typeof process === \"undefined\" || !process.versions?.node) {\n throw new Error(\"[FetchTransport] listen() is only available in Node.js.\");\n }\n\n const specifier = \"node:http\";\n return import(/* @vite-ignore */ specifier);\n}\n\n/**\n * @ru Минимальный транспорт на базе нативного fetch. Гарантированный fallback,\n * когда ни один пакетный транспорт (@hyperttp/transport-undici/bun) не установлен.\n * @en Minimal native fetch-based transport. A guaranteed fallback used when no\n * packaged transport (@hyperttp/transport-undici/bun) is installed.\n */\nexport class FetchTransport implements HyperTransport {\n public readonly protocols: readonly SenderProtocol[];\n private readonly maxBodyBytes: number;\n\n /**\n * @ru Создаёт fallback-транспорт на базе глобального `fetch`.\n * @en Creates a fallback transport based on global `fetch`.\n * @param options - Поддерживаемые протоколы и серверный лимит тела. @en Supported protocols and server body limit.\n */\n constructor(options: FetchTransportOptions = {}) {\n this.protocols = Object.freeze(options.protocols ?? [\"rest\"]);\n this.maxBodyBytes = options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;\n }\n\n public async execute(req: TransportRequest): Promise<TransportResponse> {\n const extendedRequest = req as ExtendedTransportRequest;\n const isBodyAllowed = req.method !== \"GET\" && req.method !== \"HEAD\";\n\n const res = await fetch(req.url, {\n method: req.method,\n headers: req.headers as Record<string, string>,\n body: isBodyAllowed ? ((req.body ?? null) as BodyInit | null) : null,\n signal: req.signal,\n redirect: extendedRequest.followRedirects === false ? \"manual\" : \"follow\",\n });\n\n const body = extendedRequest.stream ? res.body : new Uint8Array(await res.arrayBuffer());\n const headers: Record<string, string | string[]> = {};\n\n if (typeof res.headers.getSetCookie === \"function\") {\n const cookies = res.headers.getSetCookie();\n if (cookies.length > 0) {\n headers[\"set-cookie\"] = cookies;\n }\n }\n\n res.headers.forEach((value, key) => {\n const lowerKey = key.toLowerCase();\n\n if (lowerKey === \"set-cookie\" && headers[\"set-cookie\"]) {\n return;\n }\n\n if (headers[lowerKey]) {\n const existing = headers[lowerKey];\n headers[lowerKey] = Array.isArray(existing) ? [...existing, value] : [existing, value];\n } else {\n headers[lowerKey] = value;\n }\n });\n\n return {\n status: res.status,\n statusText: res.statusText,\n headers,\n url: res.url,\n body,\n };\n }\n\n public async listen(options: TransportListenOptions): Promise<TransportServer> {\n const { host, port, signal, onRequest } = options;\n if (signal?.aborted) {\n throw signal.reason ?? new DOMException(\"The operation was aborted\", \"AbortError\");\n }\n\n const { createServer } = await loadNodeHttp();\n\n const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n const requestController = new AbortController();\n const abortRequest = () => {\n if (!requestController.signal.aborted) {\n requestController.abort(new DOMException(\"Client disconnected\", \"AbortError\"));\n }\n };\n const abortIncompleteRequest = () => {\n if (!req.complete) abortRequest();\n };\n const abortIncompleteResponse = () => {\n if (!res.writableEnded) abortRequest();\n };\n\n req.once(\"aborted\", abortRequest);\n req.once(\"close\", abortIncompleteRequest);\n res.once(\"close\", abortIncompleteResponse);\n\n try {\n const contentLength = Number(req.headers[\"content-length\"] ?? 0);\n if (Number.isFinite(contentLength) && contentLength > this.maxBodyBytes) {\n res.writeHead(413);\n res.end(\"Payload Too Large\");\n return;\n }\n\n const chunks: Uint8Array[] = [];\n let receivedBytes = 0;\n\n for await (const chunk of req) {\n receivedBytes += chunk.byteLength;\n if (receivedBytes > this.maxBodyBytes) {\n res.writeHead(413);\n res.end(\"Payload Too Large\");\n return;\n }\n chunks.push(chunk);\n }\n\n const body = chunks.length > 0 ? Buffer.concat(chunks) : undefined;\n const headers: Record<string, string | string[]> = {};\n\n for (const [key, value] of Object.entries(req.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n\n const transportRequest: TransportRequest = {\n method: req.method ?? \"GET\",\n url: req.url ?? \"/\",\n headers,\n body,\n signal: requestController.signal,\n protocol: this.protocols[0] ?? \"rest\",\n };\n\n if (!onRequest) {\n res.writeHead(501);\n res.end(\"Not Implemented\");\n return;\n }\n\n const response = await onRequest(transportRequest);\n const outgoingHeaders: OutgoingHttpHeaders = {};\n\n for (const [key, value] of Object.entries(response.headers)) {\n outgoingHeaders[key] = value;\n }\n\n res.writeHead(response.status, response.statusText ?? \"\", outgoingHeaders);\n\n if (response.body != null) {\n if (response.body instanceof Uint8Array) {\n res.end(response.body);\n } else if (typeof response.body === \"string\") {\n res.end(response.body);\n } else {\n res.end(JSON.stringify(response.body));\n }\n } else {\n res.end();\n }\n } catch {\n if (!res.headersSent) {\n res.writeHead(500);\n res.end(\"Internal Server Error\");\n } else {\n res.destroy();\n }\n } finally {\n req.removeListener(\"aborted\", abortRequest);\n req.removeListener(\"close\", abortIncompleteRequest);\n res.removeListener(\"close\", abortIncompleteResponse);\n }\n });\n\n let closed = false;\n const close = (): Promise<void> => {\n if (closed) return Promise.resolve();\n closed = true;\n signal?.removeEventListener(\"abort\", closeOnAbort);\n server.removeListener(\"error\", reportRuntimeError);\n\n if (!server.listening) return Promise.resolve();\n return new Promise<void>((resolveClose, rejectClose) => {\n server.close((error) => {\n if (error) rejectClose(error);\n else resolveClose();\n });\n });\n };\n const closeOnAbort = () => {\n void close();\n };\n const reportRuntimeError = (error: Error) => {\n console.error(\"[FetchTransport] HTTP server error:\", error);\n };\n\n if (signal?.aborted) {\n throw signal.reason ?? new DOMException(\"The operation was aborted\", \"AbortError\");\n }\n signal?.addEventListener(\"abort\", closeOnAbort, { once: true });\n\n return new Promise<TransportServer>((resolve, reject) => {\n const rejectStartup = (error: Error) => {\n signal?.removeEventListener(\"abort\", closeOnAbort);\n reject(error);\n };\n\n server.once(\"error\", rejectStartup);\n server.listen({ host, port }, () => {\n server.removeListener(\"error\", rejectStartup);\n server.on(\"error\", reportRuntimeError);\n resolve({ close });\n });\n });\n }\n\n public async close(): Promise<void> {}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["DEFAULT_MAX_BODY_BYTES", "loadNodeHttp", "options", "req", "extendedRequest", "isBodyAllowed", "res", "body", "headers", "cookies", "value", "key", "lowerKey", "existing", "host", "port", "signal", "onRequest", "createServer", "server", "requestController", "abortRequest", "abortIncompleteRequest", "abortIncompleteResponse", "contentLength", "chunks", "receivedBytes", "chunk", "transportRequest", "response", "outgoingHeaders", "closed", "close", "closeOnAbort", "reportRuntimeError", "resolveClose", "rejectClose", "error", "resolve", "reject", "rejectStartup"]
|
|
7
7
|
}
|
package/transports/manager.d.ts
CHANGED
|
@@ -17,10 +17,23 @@ export declare const CURRENT_RUNTIME: Runtime;
|
|
|
17
17
|
*/
|
|
18
18
|
export declare function resolveTransport(protocol?: SenderProtocol, config?: ResolveTransportOptions): Promise<HyperTransport>;
|
|
19
19
|
/**
|
|
20
|
-
* @ru Синхронно возвращает транспорт из кэша без
|
|
21
|
-
* @en Synchronously returns a cached transport without Promise
|
|
20
|
+
* @ru Синхронно возвращает транспорт из кэша без создания Promise.
|
|
21
|
+
* @en Synchronously returns a cached transport without creating a Promise.
|
|
22
|
+
* @param protocol - Протокол, для которого запрашивается транспорт. @en Protocol whose transport is requested.
|
|
23
|
+
* @returns Кэшированный транспорт или `undefined`. @en Cached transport or `undefined`.
|
|
22
24
|
*/
|
|
23
25
|
export declare function getCachedTransport(protocol?: SenderProtocol): HyperTransport | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* @ru Удаляет все записи кэша, ссылающиеся на указанный транспорт.
|
|
28
|
+
* @en Removes every cache entry that references the given transport.
|
|
29
|
+
* @param transport - Экземпляр транспорта для удаления из кэша. @en Transport instance to evict from the cache.
|
|
30
|
+
*/
|
|
24
31
|
export declare function evictCachedTransport(transport: HyperTransport): void;
|
|
32
|
+
/**
|
|
33
|
+
* @ru Очищает кэш транспортов и ожидающих их разрешений. Не закрывает уже
|
|
34
|
+
* созданные экземпляры транспорта.
|
|
35
|
+
* @en Clears cached transports and pending resolutions. It does not close
|
|
36
|
+
* already-created transport instances.
|
|
37
|
+
*/
|
|
25
38
|
export declare function resetCachedTransport(): void;
|
|
26
39
|
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/transports/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAMtE,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAE1D;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,eAAO,MAAM,eAAe,EAAE,OAK1B,CAAC;AA4FL;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,GAAE,cAAuB,EACjC,MAAM,CAAC,EAAE,uBAAuB,GAC/B,OAAO,CAAC,cAAc,CAAC,CAyBzB;AAED
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/transports/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAMtE,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAE1D;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,eAAO,MAAM,eAAe,EAAE,OAK1B,CAAC;AA4FL;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,GAAE,cAAuB,EACjC,MAAM,CAAC,EAAE,uBAAuB,GAC/B,OAAO,CAAC,cAAc,CAAC,CAyBzB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,GAAE,cAAuB,GAAG,cAAc,GAAG,SAAS,CAEhG;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,CAMpE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAG3C"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/transports/manager.ts"],
|
|
4
|
-
"sourcesContent": ["import type { HyperTransport, SenderProtocol } from \"@hyperttp/types\";\nimport { FetchTransport, type FetchTransportOptions } from \"./fetch.js\";\n\ndeclare const Bun: unknown;\ndeclare const Deno: unknown;\n\nexport type Runtime = \"bun\" | \"node\" | \"deno\" | \"browser\";\n\n/**\n * @ru Опции разрешения транспорта. `customTransport` имеет приоритет над автовыбором.\n * @en Transport resolution options. `customTransport` takes priority over auto-selection.\n */\nexport interface ResolveTransportOptions {\n customTransport?: HyperTransport;\n [key: string]: unknown;\n}\n\nexport const CURRENT_RUNTIME: Runtime = (() => {\n if (typeof Bun !== \"undefined\") return \"bun\";\n if (typeof Deno !== \"undefined\") return \"deno\";\n if (typeof process !== \"undefined\" && process.versions?.node) return \"node\";\n return \"browser\";\n})();\n\ntype TransportDef = {\n readonly runtime: readonly Runtime[];\n readonly pkg: string;\n readonly export: string;\n readonly priority: number;\n};\n\nconst TRANSPORT_DEFS: readonly TransportDef[] = [\n { runtime: [\"bun\"], pkg: \"@hyperttp/transport-bun\", export: \"BunTransport\", priority: 100 },\n { runtime: [\"node\"], pkg: \"@hyperttp/transport-undici\", export: \"UndiciTransport\", priority: 90 },\n { runtime: [\"deno\"], pkg: \"@hyperttp/transport-deno\", export: \"DenoTransport\", priority: 85 },\n];\n\nconst CANDIDATES: readonly TransportDef[] = TRANSPORT_DEFS.filter((t) =>\n t.runtime.includes(CURRENT_RUNTIME),\n).sort((a, b) => b.priority - a.priority);\n\nconst transportCache = new Map<string, HyperTransport>();\nconst transportResolutions = new Map<string, Promise<HyperTransport>>();\n\nfunction isModuleNotFoundError(err: unknown): boolean {\n if (!err || typeof err !== \"object\") return false;\n const e = err as Record<string, unknown>;\n if (e.code === \"ERR_MODULE_NOT_FOUND\" || e.code === \"MODULE_NOT_FOUND\") return true;\n\n const msg = err instanceof Error ? err.message : String(e.message ?? \"\");\n return (\n msg.includes(\"Cannot find module\") ||\n msg.includes(\"Failed to resolve\") ||\n msg.includes(\"Failed to load\")\n );\n}\n\nasync function dynamicImport(pkg: string): Promise<Record<string, unknown>> {\n /* @vite-ignore */\n return import(/* webpackIgnore: true */ pkg);\n}\n\nfunction supportsProtocol(transport: HyperTransport, protocol: SenderProtocol): boolean {\n return typeof transport.supports === \"function\"\n ? transport.supports(protocol)\n : (transport.protocols?.includes(protocol) ?? true);\n}\n\nasync function disposeUnusedTransport(transport: HyperTransport): Promise<void> {\n if (typeof transport.destroy === \"function\") {\n await transport.destroy();\n } else if (typeof transport.close === \"function\") {\n await transport.close();\n }\n}\n\nasync function createTransport(\n protocol: SenderProtocol,\n config?: ResolveTransportOptions,\n): Promise<HyperTransport> {\n for (let i = 0; i < CANDIDATES.length; i++) {\n const t = CANDIDATES[i]!;\n try {\n const mod = await dynamicImport(t.pkg);\n const candidate = (mod[t.export] ?? mod.default) as\n | { new (opts?: unknown): HyperTransport }\n | undefined;\n if (typeof candidate !== \"function\") continue;\n\n const instance = new candidate(config ?? {});\n if (!supportsProtocol(instance, protocol)) {\n await disposeUnusedTransport(instance);\n continue;\n }\n\n return instance;\n } catch (err) {\n if (!isModuleNotFoundError(err)) throw err;\n }\n }\n\n console.warn(\n `[HyperCore] Fast transport (e.g. @hyperttp/transport-undici) unavailable for runtime \"${CURRENT_RUNTIME}\". Falling back to slow FetchTransport.`,\n );\n\n const fetchTransport = new FetchTransport(config as unknown as FetchTransportOptions);\n if (supportsProtocol(fetchTransport, protocol)) return fetchTransport;\n\n await disposeUnusedTransport(fetchTransport);\n throw new Error(\n `[HyperCore] No transport available for protocol \"${protocol}\" in runtime \"${CURRENT_RUNTIME}\".`,\n );\n}\n\n/**\n * @ru Разрешает оптимальный транспорт для указанного протокола и текущей среды.\n * Кастомный транспорт из конфигурации имеет приоритет над автовыбором.\n * @en Resolves optimal transport for the given protocol and current runtime.\n * A custom transport from the config takes priority over auto-selection.\n */\nexport async function resolveTransport(\n protocol: SenderProtocol = \"rest\",\n config?: ResolveTransportOptions,\n): Promise<HyperTransport> {\n if (config?.customTransport) {\n if (!supportsProtocol(config.customTransport, protocol)) {\n throw new Error(`[HyperCore] Custom transport does not support protocol \"${protocol}\".`);\n }\n return config.customTransport;\n }\n\n const cached = transportCache.get(protocol);\n if (cached) return cached;\n\n const pending = transportResolutions.get(protocol);\n if (pending) return pending;\n\n const resolution = createTransport(protocol, config)\n .then((transport) => {\n transportCache.set(protocol, transport);\n return transport;\n })\n .finally(() => {\n transportResolutions.delete(protocol);\n });\n\n transportResolutions.set(protocol, resolution);\n return resolution;\n}\n\n/**\n * @ru Синхронно возвращает транспорт из кэша без
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import type { HyperTransport, SenderProtocol } from \"@hyperttp/types\";\nimport { FetchTransport, type FetchTransportOptions } from \"./fetch.js\";\n\ndeclare const Bun: unknown;\ndeclare const Deno: unknown;\n\nexport type Runtime = \"bun\" | \"node\" | \"deno\" | \"browser\";\n\n/**\n * @ru Опции разрешения транспорта. `customTransport` имеет приоритет над автовыбором.\n * @en Transport resolution options. `customTransport` takes priority over auto-selection.\n */\nexport interface ResolveTransportOptions {\n customTransport?: HyperTransport;\n [key: string]: unknown;\n}\n\nexport const CURRENT_RUNTIME: Runtime = (() => {\n if (typeof Bun !== \"undefined\") return \"bun\";\n if (typeof Deno !== \"undefined\") return \"deno\";\n if (typeof process !== \"undefined\" && process.versions?.node) return \"node\";\n return \"browser\";\n})();\n\ntype TransportDef = {\n readonly runtime: readonly Runtime[];\n readonly pkg: string;\n readonly export: string;\n readonly priority: number;\n};\n\nconst TRANSPORT_DEFS: readonly TransportDef[] = [\n { runtime: [\"bun\"], pkg: \"@hyperttp/transport-bun\", export: \"BunTransport\", priority: 100 },\n { runtime: [\"node\"], pkg: \"@hyperttp/transport-undici\", export: \"UndiciTransport\", priority: 90 },\n { runtime: [\"deno\"], pkg: \"@hyperttp/transport-deno\", export: \"DenoTransport\", priority: 85 },\n];\n\nconst CANDIDATES: readonly TransportDef[] = TRANSPORT_DEFS.filter((t) =>\n t.runtime.includes(CURRENT_RUNTIME),\n).sort((a, b) => b.priority - a.priority);\n\nconst transportCache = new Map<string, HyperTransport>();\nconst transportResolutions = new Map<string, Promise<HyperTransport>>();\n\nfunction isModuleNotFoundError(err: unknown): boolean {\n if (!err || typeof err !== \"object\") return false;\n const e = err as Record<string, unknown>;\n if (e.code === \"ERR_MODULE_NOT_FOUND\" || e.code === \"MODULE_NOT_FOUND\") return true;\n\n const msg = err instanceof Error ? err.message : String(e.message ?? \"\");\n return (\n msg.includes(\"Cannot find module\") ||\n msg.includes(\"Failed to resolve\") ||\n msg.includes(\"Failed to load\")\n );\n}\n\nasync function dynamicImport(pkg: string): Promise<Record<string, unknown>> {\n /* @vite-ignore */\n return import(/* webpackIgnore: true */ pkg);\n}\n\nfunction supportsProtocol(transport: HyperTransport, protocol: SenderProtocol): boolean {\n return typeof transport.supports === \"function\"\n ? transport.supports(protocol)\n : (transport.protocols?.includes(protocol) ?? true);\n}\n\nasync function disposeUnusedTransport(transport: HyperTransport): Promise<void> {\n if (typeof transport.destroy === \"function\") {\n await transport.destroy();\n } else if (typeof transport.close === \"function\") {\n await transport.close();\n }\n}\n\nasync function createTransport(\n protocol: SenderProtocol,\n config?: ResolveTransportOptions,\n): Promise<HyperTransport> {\n for (let i = 0; i < CANDIDATES.length; i++) {\n const t = CANDIDATES[i]!;\n try {\n const mod = await dynamicImport(t.pkg);\n const candidate = (mod[t.export] ?? mod.default) as\n | { new (opts?: unknown): HyperTransport }\n | undefined;\n if (typeof candidate !== \"function\") continue;\n\n const instance = new candidate(config ?? {});\n if (!supportsProtocol(instance, protocol)) {\n await disposeUnusedTransport(instance);\n continue;\n }\n\n return instance;\n } catch (err) {\n if (!isModuleNotFoundError(err)) throw err;\n }\n }\n\n console.warn(\n `[HyperCore] Fast transport (e.g. @hyperttp/transport-undici) unavailable for runtime \"${CURRENT_RUNTIME}\". Falling back to slow FetchTransport.`,\n );\n\n const fetchTransport = new FetchTransport(config as unknown as FetchTransportOptions);\n if (supportsProtocol(fetchTransport, protocol)) return fetchTransport;\n\n await disposeUnusedTransport(fetchTransport);\n throw new Error(\n `[HyperCore] No transport available for protocol \"${protocol}\" in runtime \"${CURRENT_RUNTIME}\".`,\n );\n}\n\n/**\n * @ru Разрешает оптимальный транспорт для указанного протокола и текущей среды.\n * Кастомный транспорт из конфигурации имеет приоритет над автовыбором.\n * @en Resolves optimal transport for the given protocol and current runtime.\n * A custom transport from the config takes priority over auto-selection.\n */\nexport async function resolveTransport(\n protocol: SenderProtocol = \"rest\",\n config?: ResolveTransportOptions,\n): Promise<HyperTransport> {\n if (config?.customTransport) {\n if (!supportsProtocol(config.customTransport, protocol)) {\n throw new Error(`[HyperCore] Custom transport does not support protocol \"${protocol}\".`);\n }\n return config.customTransport;\n }\n\n const cached = transportCache.get(protocol);\n if (cached) return cached;\n\n const pending = transportResolutions.get(protocol);\n if (pending) return pending;\n\n const resolution = createTransport(protocol, config)\n .then((transport) => {\n transportCache.set(protocol, transport);\n return transport;\n })\n .finally(() => {\n transportResolutions.delete(protocol);\n });\n\n transportResolutions.set(protocol, resolution);\n return resolution;\n}\n\n/**\n * @ru Синхронно возвращает транспорт из кэша без создания Promise.\n * @en Synchronously returns a cached transport without creating a Promise.\n * @param protocol - Протокол, для которого запрашивается транспорт. @en Protocol whose transport is requested.\n * @returns Кэшированный транспорт или `undefined`. @en Cached transport or `undefined`.\n */\nexport function getCachedTransport(protocol: SenderProtocol = \"rest\"): HyperTransport | undefined {\n return transportCache.get(protocol);\n}\n\n/**\n * @ru Удаляет все записи кэша, ссылающиеся на указанный транспорт.\n * @en Removes every cache entry that references the given transport.\n * @param transport - Экземпляр транспорта для удаления из кэша. @en Transport instance to evict from the cache.\n */\nexport function evictCachedTransport(transport: HyperTransport): void {\n for (const [protocol, cached] of transportCache) {\n if (cached === transport) {\n transportCache.delete(protocol);\n }\n }\n}\n\n/**\n * @ru Очищает кэш транспортов и ожидающих их разрешений. Не закрывает уже\n * созданные экземпляры транспорта.\n * @en Clears cached transports and pending resolutions. It does not close\n * already-created transport instances.\n */\nexport function resetCachedTransport(): void {\n transportCache.clear();\n transportResolutions.clear();\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["FetchTransport", "TRANSPORT_DEFS", "CANDIDATES", "a", "b", "transportCache", "transportResolutions", "isModuleNotFoundError", "err", "msg", "dynamicImport", "pkg", "supportsProtocol", "transport", "protocol", "disposeUnusedTransport", "createTransport", "config", "i", "t", "mod", "candidate", "instance", "fetchTransport", "cached", "pending", "resolution"]
|
|
7
7
|
}
|
package/utils/errors.d.ts
CHANGED
|
@@ -9,8 +9,14 @@ export declare class HyperClientError extends Error {
|
|
|
9
9
|
url?: string | undefined;
|
|
10
10
|
method?: string | undefined;
|
|
11
11
|
/**
|
|
12
|
-
* @ru Создает
|
|
13
|
-
* @en Creates a
|
|
12
|
+
* @ru Создает ошибку Hyperttp с дополнительным сетевым контекстом.
|
|
13
|
+
* @en Creates a Hyperttp error with optional network context.
|
|
14
|
+
* @param message - Человекочитаемое описание ошибки. @en Human-readable error description.
|
|
15
|
+
* @param code - Машиночитаемый код ошибки. @en Machine-readable error code.
|
|
16
|
+
* @param statusCode - Связанный HTTP-статус, если есть. @en Associated HTTP status, when available.
|
|
17
|
+
* @param originalError - Исходная ошибка как `cause`. @en Original error exposed as `cause`.
|
|
18
|
+
* @param url - URL, связанный с ошибкой. @en URL associated with the error.
|
|
19
|
+
* @param method - HTTP-метод, связанный с ошибкой. @en HTTP method associated with the error.
|
|
14
20
|
*/
|
|
15
21
|
constructor(message: string, code?: string, statusCode?: number | undefined, originalError?: Error | undefined, url?: string | undefined, method?: string | undefined);
|
|
16
22
|
/**
|
|
@@ -25,8 +31,10 @@ export declare class HyperClientError extends Error {
|
|
|
25
31
|
*/
|
|
26
32
|
export declare class TimeoutError extends HyperClientError {
|
|
27
33
|
/**
|
|
28
|
-
* @ru Создает
|
|
29
|
-
* @en Creates a
|
|
34
|
+
* @ru Создает ошибку таймаута для указанного URL.
|
|
35
|
+
* @en Creates a timeout error for the given URL.
|
|
36
|
+
* @param url - URL запроса с истекшим таймаутом. @en URL of the timed-out request.
|
|
37
|
+
* @param timeout - Лимит времени в миллисекундах. @en Time limit in milliseconds.
|
|
30
38
|
*/
|
|
31
39
|
constructor(url: string, timeout: number);
|
|
32
40
|
/**
|
package/utils/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IAahC,IAAI,EAAE,MAAM;IACZ,UAAU,CAAC,EAAE,MAAM;IACnB,aAAa,CAAC,EAAE,KAAK;IACrB,GAAG,CAAC,EAAE,MAAM;IACZ,MAAM,CAAC,EAAE,MAAM;IAhBxB;;;;;;;;;OASG;IACH,YACE,OAAO,EAAE,MAAM,EACR,IAAI,GAAE,MAAsB,EAC5B,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,aAAa,CAAC,EAAE,KAAK,YAAA,EACrB,GAAG,CAAC,EAAE,MAAM,YAAA,EACZ,MAAM,CAAC,EAAE,MAAM,YAAA,EAKvB;IAED;;;OAGG;IACH,OAAc,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,gBAAgB,CAKtE;CACF;AAED;;;GAGG;AACH,qBAAa,YAAa,SAAQ,gBAAgB;IAChD;;;;;OAKG;IACH,YAAY,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAIvC;IAED;;;OAGG;IACH,OAAc,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,YAAY,CAE9D;CACF"}
|
package/utils/errors.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/errors.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @ru Базовый класс ошибок клиента Hyperttp, агрегирующий контекст неудачного сетевого запроса.\n * @en Base error class for the Hyperttp client, providing explicit layout context for failed requests.\n */\nexport class HyperClientError extends Error {\n /**\n * @ru Создает
|
|
5
|
-
"mappings": "aAIM,aAAO,yBAAyB,KAAK,
|
|
4
|
+
"sourcesContent": ["/**\n * @ru Базовый класс ошибок клиента Hyperttp, агрегирующий контекст неудачного сетевого запроса.\n * @en Base error class for the Hyperttp client, providing explicit layout context for failed requests.\n */\nexport class HyperClientError extends Error {\n /**\n * @ru Создает ошибку Hyperttp с дополнительным сетевым контекстом.\n * @en Creates a Hyperttp error with optional network context.\n * @param message - Человекочитаемое описание ошибки. @en Human-readable error description.\n * @param code - Машиночитаемый код ошибки. @en Machine-readable error code.\n * @param statusCode - Связанный HTTP-статус, если есть. @en Associated HTTP status, when available.\n * @param originalError - Исходная ошибка как `cause`. @en Original error exposed as `cause`.\n * @param url - URL, связанный с ошибкой. @en URL associated with the error.\n * @param method - HTTP-метод, связанный с ошибкой. @en HTTP method associated with the error.\n */\n constructor(\n message: string,\n public code: string = \"HYPER_ERROR\",\n public statusCode?: number,\n public originalError?: Error,\n public url?: string,\n public method?: string,\n ) {\n super(message, originalError ? { cause: originalError } : undefined);\n this.name = \"HyperClientError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n /**\n * @ru Проверяет, является ли ошибка экземпляром HttpClientError (безопасно для разрозненных бандлов).\n * @en Checks if an error is an HttpClientError instance (bundle boundary safe).\n */\n public static isHyperClientError(err: unknown): err is HyperClientError {\n return (\n err instanceof HyperClientError ||\n (err instanceof Error && (err as any).code === \"HYPER_ERROR\")\n );\n }\n}\n\n/**\n * @ru Ошибка, возникающая при превышении лимита времени ожидания ответа от сервера.\n * @en Error thrown when a network request exceeds its allocated execution timeout threshold.\n */\nexport class TimeoutError extends HyperClientError {\n /**\n * @ru Создает ошибку таймаута для указанного URL.\n * @en Creates a timeout error for the given URL.\n * @param url - URL запроса с истекшим таймаутом. @en URL of the timed-out request.\n * @param timeout - Лимит времени в миллисекундах. @en Time limit in milliseconds.\n */\n constructor(url: string, timeout: number) {\n super(`Timeout after ${timeout}ms`, \"TIMEOUT\", 408, undefined, url);\n this.name = \"TimeoutError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n /**\n * @ru Проверяет, является ли ошибка экземпляром TimeoutError.\n * @en Checks if an error is a TimeoutError instance.\n */\n public static isTimeoutError(err: unknown): err is TimeoutError {\n return err instanceof TimeoutError || (err instanceof Error && (err as any).code === \"TIMEOUT\");\n }\n}\n"],
|
|
5
|
+
"mappings": "aAIM,aAAO,yBAAyB,KAAK,CAahC,KACA,WACA,cACA,IACA,OANT,YACEA,EACOC,EAAe,cACfC,EACAC,EACAC,EACAC,EAAe,CAEtB,MAAML,EAASG,EAAgB,CAAE,MAAOA,CAAa,EAAK,MAAS,YAN5DF,kBACAC,qBACAC,WACAC,cACAC,EAGP,KAAK,KAAO,mBACZ,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CAMO,OAAO,mBAAmBC,EAAY,CAC3C,OACEA,aAAe,kBACdA,aAAe,OAAUA,EAAY,OAAS,aAEnD,EAOI,aAAO,qBAAqB,gBAAgB,CAOhD,YAAYF,EAAaG,EAAe,CACtC,MAAM,iBAAiBA,CAAO,KAAM,UAAW,IAAK,OAAWH,CAAG,EAClE,KAAK,KAAO,eACZ,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CAMO,OAAO,eAAeE,EAAY,CACvC,OAAOA,aAAe,cAAiBA,aAAe,OAAUA,EAAY,OAAS,SACvF",
|
|
6
6
|
"names": ["message", "code", "statusCode", "originalError", "url", "method", "err", "timeout"]
|
|
7
7
|
}
|