@firtoz/hono-fetcher 2.7.1 → 2.7.2

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.
@@ -68,6 +68,7 @@ var createWebSocketFetcher = (fetcher) => {
68
68
  let finalUrl = request.url;
69
69
  const { init = {}, params, query, config } = request;
70
70
  const autoAccept = config?.autoAccept ?? true;
71
+ const acceptOptions = config?.acceptOptions;
71
72
  if (params && typeof params === "object") {
72
73
  finalUrl = Object.entries(params).reduce((acc, [key, value]) => {
73
74
  return acc.replace(`:${key}`, value);
@@ -85,7 +86,7 @@ var createWebSocketFetcher = (fetcher) => {
85
86
  headers: newHeaders
86
87
  });
87
88
  if (autoAccept && response.webSocket) {
88
- response.webSocket.accept();
89
+ response.webSocket.accept(acceptOptions);
89
90
  }
90
91
  return response;
91
92
  } catch (error) {
@@ -108,5 +109,5 @@ var honoFetcher = (fetcher) => {
108
109
  };
109
110
 
110
111
  export { honoFetcher };
111
- //# sourceMappingURL=chunk-ULIZJ5OD.js.map
112
- //# sourceMappingURL=chunk-ULIZJ5OD.js.map
112
+ //# sourceMappingURL=chunk-5KDMHM65.js.map
113
+ //# sourceMappingURL=chunk-5KDMHM65.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/honoFetcher.ts"],"names":[],"mappings":";AAyDA,SAAS,iBAAA,CACR,KACA,KAAA,EACS;AACT,EAAA,IAAI,CAAC,KAAA,EAAO;AACX,IAAA,OAAO,GAAA;AAAA,EACR;AACA,EAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AACjD,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AAC1C,MAAA;AAAA,IACD;AACA,IAAA,YAAA,CAAa,MAAA,CAAO,GAAA,EAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EACvC;AACA,EAAA,MAAM,UAAA,GAAa,aAAa,QAAA,EAAS;AACzC,EAAA,IAAI,CAAC,UAAA,EAAY;AAChB,IAAA,OAAO,GAAA;AAAA,EACR;AACA,EAAA,MAAM,SAAA,GAAY,GAAA,CAAI,QAAA,CAAS,GAAG,IAAI,GAAA,GAAM,GAAA;AAC5C,EAAA,OAAO,CAAA,EAAG,GAAG,CAAA,EAAG,SAAS,GAAG,UAAU,CAAA,CAAA;AACvC;AAKA,SAAS,kBACR,IAAA,EACmD;AACnD,EAAA,MAAM,EAAE,SAAS,EAAA,EAAI,IAAA,EAAM,IAAI,MAAA,EAAQ,EAAA,EAAI,GAAG,IAAA,EAAK,GAAI,IAAA;AACvD,EAAA,OAAO,IAAA;AACR;AAiJA,IAAM,mBAAA,GAAsB,CAC3B,OAAA,EAIA,MAAA,KAC8B;AAC9B,EAAA,QAAQ,OAAO,OAAA,KAAY;AAC1B,IAAA,IAAI,WAAmB,OAAA,CAAQ,GAAA;AAE/B,IAAA,MAAM,EAAE,IAAA,GAAO,EAAC,EAAG,MAAA,EAAQ,OAAM,GAAI,OAAA;AAErC,IAAA,IAAI,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,EAAU;AACzC,MAAA,QAAA,GAAW,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CAAE,MAAA,CAAO,CAAC,GAAA,EAAK,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM;AAC/D,QAAA,OAAO,GAAA,CAAI,OAAA,CAAQ,CAAA,CAAA,EAAI,GAAG,IAAI,KAAe,CAAA;AAAA,MAC9C,GAAG,QAAQ,CAAA;AAAA,IACZ;AAEA,IAAA,QAAA,GAAW,iBAAA,CAAkB,UAAU,KAAK,CAAA;AAE5C,IAAA,MAAM,yBAAA,GAA4B,OAAA;AAKlC,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI,0BAA0B,IAAA,EAAM;AACnC,MAAA,MAAM,QAAA,GAAW,IAAI,QAAA,EAAS;AAC9B,MAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,MAAA,CAAO,OAAA;AAAA,QACjC,yBAAA,CAA0B;AAAA,OAC3B,EAAG;AACF,QAAA,QAAA,CAAS,MAAA,CAAO,KAAK,KAAe,CAAA;AAAA,MACrC;AACA,MAAA,IAAA,GAAO,QAAA;AAAA,IACR,CAAA,MAAA,IAAW,0BAA0B,IAAA,EAAM;AAC1C,MAAA,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,yBAAA,CAA0B,IAAI,CAAA;AAAA,IACrD;AAEA,IAAA,MAAM,aAAa,IAAI,OAAA;AAAA,MACtB,IAAA,CAAK;AAAA,KACN;AAEA,IAAA,IAAI,IAAA,IAAQ,CAAC,yBAAA,CAA0B,IAAA,EAAM;AAC5C,MAAA,UAAA,CAAW,GAAA,CAAI,gBAAgB,kBAAkB,CAAA;AAAA,IAClD;AAEA,IAAA,IAAI;AACH,MAAA,OAAO,MAAM,QAAQ,QAAA,EAAU;AAAA,QAC9B,GAAG,kBAAkB,IAAI,CAAA;AAAA,QACzB,MAAA,EAAQ,OAAO,WAAA,EAAY;AAAA,QAC3B,OAAA,EAAS,UAAA;AAAA,QACT,GAAI,IAAA,GAAO,EAAE,IAAA,KAAS;AAAC,OACvB,CAAA;AAAA,IACF,SAAS,KAAA,EAAO;AACf,MAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,MAAA,EAAS,MAAM,CAAA,GAAA,CAAA,EAAO,KAAK,CAAA;AACzC,MAAA,MAAM,IAAI,MAAM,CAAA,UAAA,EAAa,MAAM,IAAI,QAAQ,CAAA,EAAA,EAAK,KAAK,CAAA,CAAE,CAAA;AAAA,IAC5D;AAAA,EACD,CAAA;AACD,CAAA;AAEA,IAAM,sBAAA,GAAyB,CAC9B,OAAA,KAI8B;AAC9B,EAAA,QAAQ,OAAO,OAAA,KAAY;AAC1B,IAAA,IAAI,WAAmB,OAAA,CAAQ,GAAA;AAE/B,IAAA,MAAM,EAAE,IAAA,GAAO,IAAI,MAAA,EAAQ,KAAA,EAAO,QAAO,GAAI,OAAA;AAC7C,IAAA,MAAM,UAAA,GAAa,QAAQ,UAAA,IAAc,IAAA;AACzC,IAAA,MAAM,gBAAgB,MAAA,EAAQ,aAAA;AAE9B,IAAA,IAAI,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,EAAU;AACzC,MAAA,QAAA,GAAW,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CAAE,MAAA,CAAO,CAAC,GAAA,EAAK,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM;AAC/D,QAAA,OAAO,GAAA,CAAI,OAAA,CAAQ,CAAA,CAAA,EAAI,GAAG,IAAI,KAAe,CAAA;AAAA,MAC9C,GAAG,QAAQ,CAAA;AAAA,IACZ;AAEA,IAAA,QAAA,GAAW,iBAAA,CAAkB,UAAU,KAAK,CAAA;AAE5C,IAAA,MAAM,aAAa,IAAI,OAAA;AAAA,MACtB,IAAA,CAAK;AAAA,KACN;AACA,IAAA,UAAA,CAAW,GAAA,CAAI,WAAW,WAAW,CAAA;AAErC,IAAA,IAAI;AACH,MAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,QAAA,EAAU;AAAA,QACxC,GAAG,kBAAkB,IAAI,CAAA;AAAA,QACzB,MAAA,EAAQ,KAAA;AAAA,QACR,OAAA,EAAS;AAAA,OACT,CAAA;AAED,MAAA,IAAI,UAAA,IAAc,SAAS,SAAA,EAAW;AACrC,QAAA,QAAA,CAAS,SAAA,CAAU,OAAO,aAAa,CAAA;AAAA,MACxC;AAEA,MAAA,OAAO,QAAA;AAAA,IACR,SAAS,KAAA,EAAO;AACf,MAAA,OAAA,CAAQ,KAAA,CAAM,gCAAgC,KAAK,CAAA;AACnD,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,+BAAA,EAAkC,QAAQ,CAAA,EAAA,EAAK,KAAK,CAAA,CAAE,CAAA;AAAA,IACvE;AAAA,EACD,CAAA;AACD,CAAA;AAIO,IAAM,WAAA,GAAc,CAC1B,OAAA,KAIyB;AACzB,EAAA,MAAM,UAAU,CAAC,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,UAAU,OAAO,CAAA;AAExD,EAAA,MAAM,SAAS,OAAA,CAAQ,MAAA;AAAA,IACtB,CAAC,KAAK,MAAA,KAAW;AAChB,MACC,GAAA,CAGC,MAAM,CAAA,GAAI,mBAAA,CAAoB,SAAS,MAAM,CAAA;AAI/C,MAAA,OAAO,GAAA;AAAA,IACR,CAAA;AAAA,IACA;AAAC,GACF;AAGA,EACC,MAAA,CACC,SAAA,GAAY,sBAAA,CAAuB,OAAO,CAAA;AAE5C,EAAA,OAAO,MAAA;AACR","file":"chunk-5KDMHM65.js","sourcesContent":["import type { Hono } from \"hono\";\nimport type { ExtractSchema } from \"hono/types\";\n\nexport type ParsePathParams<T extends string> =\n\tT extends `${infer _Start}/:${infer Param}/${infer Rest}`\n\t\t? { [K in Param | keyof ParsePathParams<`/${Rest}`>]: string }\n\t\t: T extends `${infer _Start}/:${infer Param}`\n\t\t\t? { [K in Param]: string }\n\t\t\t: never;\n\nexport type HttpMethod = \"get\" | \"post\" | \"put\" | \"delete\" | \"patch\";\n\nexport type HonoSchemaKeys<T extends Hono> = string & keyof ExtractSchema<T>;\n\ntype FilterKeysByMethod<\n\tTApp extends ExtractSchema<unknown>,\n\tTMethod extends HttpMethod,\n> = {\n\t[K in keyof TApp as TApp[K] extends { [key in `$${TMethod}`]: unknown }\n\t\t? K\n\t\t: never]: TApp[K];\n};\n\ntype HonoSchema<TApp extends Hono> = {\n\t[M in HttpMethod]: FilterKeysByMethod<ExtractSchema<TApp>, M>;\n};\n\nexport type JsonResponse<T> = Omit<Response, \"json\"> & {\n\tjson: () => Promise<T>;\n};\n\n/**\n * {@link JsonResponse} intersected with `Disposable` for Workers RPC: `Response`\n * values from `DurableObjectStub#fetch()` may implement `[Symbol.dispose]` even\n * though `Fetcher.fetch` is still typed as `Promise<Response>`. Use with\n * {@link BaseDisposableTypedHonoFetcher} (and `TypedDoFetcher` from `./honoDoFetcher`) so\n * `using resp = await api.get(...)` type-checks when `\"ESNext.Disposable\"` is in `lib`.\n *\n * @see https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/\n */\nexport type RpcDisposableJsonResponse<T> = JsonResponse<T> & Disposable;\n\ntype HasPathParams<T extends string> = T extends `${string}:${string}`\n\t? true\n\t: false;\n\n/**\n * Values allowed in the optional `query` object on fetcher requests.\n * `null` and `undefined` entries are omitted from the serialized query string.\n */\nexport type HonoFetcherQueryParamValue = string | number | boolean;\n\nexport type HonoFetcherQueryParams = Record<\n\tstring,\n\tHonoFetcherQueryParamValue | null | undefined\n>;\n\nfunction appendQueryString(\n\turl: string,\n\tquery?: HonoFetcherQueryParams,\n): string {\n\tif (!query) {\n\t\treturn url;\n\t}\n\tconst searchParams = new URLSearchParams();\n\tfor (const [key, value] of Object.entries(query)) {\n\t\tif (value === undefined || value === null) {\n\t\t\tcontinue;\n\t\t}\n\t\tsearchParams.append(key, String(value));\n\t}\n\tconst serialized = searchParams.toString();\n\tif (!serialized) {\n\t\treturn url;\n\t}\n\tconst separator = url.includes(\"?\") ? \"&\" : \"?\";\n\treturn `${url}${separator}${serialized}`;\n}\n\n/**\n * `RequestInit` fields that honoFetcher sets must not be overwritten by spreading `...init` last.\n */\nfunction restOfRequestInit(\n\tinit: RequestInit,\n): Omit<RequestInit, \"headers\" | \"body\" | \"method\"> {\n\tconst { headers: _h, body: _b, method: _m, ...rest } = init;\n\treturn rest;\n}\n\ntype FetcherParams<SchemaPath extends string> =\n\tHasPathParams<SchemaPath> extends true\n\t\t? {\n\t\t\t\tparams: ParsePathParams<SchemaPath>;\n\t\t\t\tquery?: HonoFetcherQueryParams;\n\t\t\t\tinit?: RequestInit;\n\t\t\t}\n\t\t: {\n\t\t\t\tparams?: never;\n\t\t\t\tquery?: HonoFetcherQueryParams;\n\t\t\t\tinit?: RequestInit;\n\t\t\t};\n\n// biome-ignore lint/complexity/noBannedTypes: We need an empty object to remove the body and form keys from the request object\ntype EmptyObject = {};\n\ntype TypedMethodFetcher<T extends Hono, M extends HttpMethod> = <\n\tSchemaPath extends string & keyof HonoSchema<T>[M],\n>(\n\trequest: {\n\t\turl: SchemaPath;\n\t} & FetcherParams<SchemaPath> &\n\t\t(M extends \"get\" | \"delete\" ? EmptyObject : BodyParams<T, M, SchemaPath>),\n) => Promise<SchemaOutput<T, M, SchemaPath>>;\n\ntype SchemaOutput<\n\tT extends Hono,\n\tM extends HttpMethod,\n\tSchemaPath extends string & keyof HonoSchema<T>[M],\n\tDollarM extends `$${M}` & keyof HonoSchema<T>[M][SchemaPath] = `$${M}` &\n\t\tkeyof HonoSchema<T>[M][SchemaPath],\n> = \"output\" extends keyof HonoSchema<T>[M][SchemaPath][DollarM]\n\t? JsonResponse<HonoSchema<T>[M][SchemaPath][DollarM][\"output\"]>\n\t: never;\n\ntype DoSchemaOutput<\n\tT extends Hono,\n\tM extends HttpMethod,\n\tSchemaPath extends string & keyof HonoSchema<T>[M],\n\tDollarM extends `$${M}` & keyof HonoSchema<T>[M][SchemaPath] = `$${M}` &\n\t\tkeyof HonoSchema<T>[M][SchemaPath],\n> = \"output\" extends keyof HonoSchema<T>[M][SchemaPath][DollarM]\n\t? RpcDisposableJsonResponse<HonoSchema<T>[M][SchemaPath][DollarM][\"output\"]>\n\t: never;\n\ntype BodyParams<\n\tTApp extends Hono,\n\tTMethod extends HttpMethod,\n\tSchemaPath extends string & keyof HonoSchema<TApp>[TMethod],\n\tDollarMethod extends `$${TMethod}` &\n\t\tkeyof HonoSchema<TApp>[TMethod][SchemaPath] = `$${TMethod}` &\n\t\tkeyof HonoSchema<TApp>[TMethod][SchemaPath],\n> = \"input\" extends keyof HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod]\n\t? \"json\" extends keyof HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod][\"input\"]\n\t\t? \"form\" extends keyof HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod][\"input\"]\n\t\t\t?\n\t\t\t\t\t| {\n\t\t\t\t\t\t\tbody: HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod][\"input\"][\"json\"];\n\t\t\t\t\t }\n\t\t\t\t\t| {\n\t\t\t\t\t\t\tform: HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod][\"input\"][\"form\"];\n\t\t\t\t\t }\n\t\t\t: {\n\t\t\t\t\tbody: HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod][\"input\"][\"json\"];\n\t\t\t\t}\n\t\t: \"form\" extends keyof HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod][\"input\"]\n\t\t\t? {\n\t\t\t\t\tform: HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod][\"input\"][\"form\"];\n\t\t\t\t}\n\t\t\t: { body?: unknown } | { form?: unknown }\n\t: EmptyObject;\n\ntype AvailableMethods<T extends Hono> = {\n\t[M in HttpMethod]: keyof HonoSchema<T>[M] extends never ? never : M;\n}[HttpMethod];\n\nexport interface WebSocketConfig {\n\t/**\n\t * Whether to automatically call accept() on the WebSocket before returning.\n\t * Defaults to true for convenience.\n\t *\n\t * In Cloudflare Workers, you must call accept() before using a WebSocket.\n\t * Setting this to false allows you to call accept() manually if needed.\n\t *\n\t * @default true\n\t */\n\tautoAccept?: boolean;\n\t/**\n\t * Arguments for Cloudflare’s `WebSocket#accept` (e.g. `{ allowHalfOpen: true }` when\n\t * [proxying](https://developers.cloudflare.com/workers/runtime-apis/websockets/#close-behavior)\n\t * and coordinating close on both sides). Used only when `autoAccept` is true.\n\t */\n\tacceptOptions?: WebSocketAcceptOptions;\n}\n\nexport type TypedWebSocketFetcher<T extends Hono> = <\n\tSchemaPath extends string & keyof HonoSchema<T>[\"get\"],\n>(\n\trequest: {\n\t\turl: SchemaPath;\n\t\tconfig?: WebSocketConfig;\n\t} & FetcherParams<SchemaPath>,\n) => Promise<Response>;\n\nexport type BaseTypedHonoFetcher<T extends Hono> = {\n\t[M in AvailableMethods<T>]: TypedMethodFetcher<T, M>;\n} & (keyof HonoSchema<T>[\"get\"] extends never\n\t? // biome-ignore lint/complexity/noBannedTypes: We really do want an empty object if the get method is not available\n\t\t{}\n\t: { websocket: TypedWebSocketFetcher<T> });\n\ntype TypedDisposableMethodFetcher<T extends Hono, M extends HttpMethod> = <\n\tSchemaPath extends string & keyof HonoSchema<T>[M],\n>(\n\trequest: {\n\t\turl: SchemaPath;\n\t} & FetcherParams<SchemaPath> &\n\t\t(M extends \"get\" | \"delete\" ? EmptyObject : BodyParams<T, M, SchemaPath>),\n) => Promise<DoSchemaOutput<T, M, SchemaPath>>;\n\nexport type TypedDisposableWebSocketFetcher<T extends Hono> = <\n\tSchemaPath extends string & keyof HonoSchema<T>[\"get\"],\n>(\n\trequest: {\n\t\turl: SchemaPath;\n\t\tconfig?: WebSocketConfig;\n\t} & FetcherParams<SchemaPath>,\n) => Promise<Response & Disposable>;\n\n/**\n * Same shape as {@link BaseTypedHonoFetcher} but HTTP methods return\n * {@link RpcDisposableJsonResponse} and `websocket` returns `Response & Disposable`\n * so `using` on RPC results type-checks for Durable Object clients.\n *\n * @see https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/\n */\nexport type BaseDisposableTypedHonoFetcher<T extends Hono> = {\n\t[M in AvailableMethods<T>]: TypedDisposableMethodFetcher<T, M>;\n} & (keyof HonoSchema<T>[\"get\"] extends never\n\t? // biome-ignore lint/complexity/noBannedTypes: We really do want an empty object if the get method is not available\n\t\t{}\n\t: { websocket: TypedDisposableWebSocketFetcher<T> });\n\nconst createMethodFetcher = <T extends Hono, M extends HttpMethod>(\n\tfetcher: (\n\t\trequest: string,\n\t\tinit?: RequestInit,\n\t) => ReturnType<T[\"request\"]> | Promise<ReturnType<T[\"request\"]>>,\n\tmethod: M,\n): TypedMethodFetcher<T, M> => {\n\treturn (async (request) => {\n\t\tlet finalUrl: string = request.url;\n\n\t\tconst { init = {}, params, query } = request;\n\n\t\tif (params && typeof params === \"object\") {\n\t\t\tfinalUrl = Object.entries(params).reduce((acc, [key, value]) => {\n\t\t\t\treturn acc.replace(`:${key}`, value as string);\n\t\t\t}, finalUrl);\n\t\t}\n\n\t\tfinalUrl = appendQueryString(finalUrl, query);\n\n\t\tconst requestAsOptionalFormBody = request as {\n\t\t\tform?: unknown;\n\t\t\tbody?: unknown;\n\t\t};\n\n\t\tlet body: BodyInit | undefined;\n\t\tif (requestAsOptionalFormBody.form) {\n\t\t\tconst formData = new FormData();\n\t\t\tfor (const [key, value] of Object.entries(\n\t\t\t\trequestAsOptionalFormBody.form,\n\t\t\t)) {\n\t\t\t\tformData.append(key, value as string);\n\t\t\t}\n\t\t\tbody = formData;\n\t\t} else if (requestAsOptionalFormBody.body) {\n\t\t\tbody = JSON.stringify(requestAsOptionalFormBody.body) as BodyInit;\n\t\t}\n\n\t\tconst newHeaders = new Headers(\n\t\t\tinit.headers as unknown as ConstructorParameters<typeof Headers>[0],\n\t\t);\n\n\t\tif (body && !requestAsOptionalFormBody.form) {\n\t\t\tnewHeaders.set(\"Content-Type\", \"application/json\");\n\t\t}\n\n\t\ttry {\n\t\t\treturn await fetcher(finalUrl, {\n\t\t\t\t...restOfRequestInit(init),\n\t\t\t\tmethod: method.toUpperCase(),\n\t\t\t\theaders: newHeaders,\n\t\t\t\t...(body ? { body } : {}),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconsole.error(`Error ${method}ing`, error);\n\t\t\tthrow new Error(`Failed to ${method} ${finalUrl}: ${error}`);\n\t\t}\n\t}) as TypedMethodFetcher<T, M>;\n};\n\nconst createWebSocketFetcher = <T extends Hono>(\n\tfetcher: (\n\t\trequest: string,\n\t\tinit?: RequestInit,\n\t) => ReturnType<T[\"request\"]> | Promise<ReturnType<T[\"request\"]>>,\n): TypedWebSocketFetcher<T> => {\n\treturn (async (request) => {\n\t\tlet finalUrl: string = request.url;\n\n\t\tconst { init = {}, params, query, config } = request;\n\t\tconst autoAccept = config?.autoAccept ?? true;\n\t\tconst acceptOptions = config?.acceptOptions;\n\n\t\tif (params && typeof params === \"object\") {\n\t\t\tfinalUrl = Object.entries(params).reduce((acc, [key, value]) => {\n\t\t\t\treturn acc.replace(`:${key}`, value as string);\n\t\t\t}, finalUrl);\n\t\t}\n\n\t\tfinalUrl = appendQueryString(finalUrl, query);\n\n\t\tconst newHeaders = new Headers(\n\t\t\tinit.headers as unknown as ConstructorParameters<typeof Headers>[0],\n\t\t);\n\t\tnewHeaders.set(\"Upgrade\", \"websocket\");\n\n\t\ttry {\n\t\t\tconst response = await fetcher(finalUrl, {\n\t\t\t\t...restOfRequestInit(init),\n\t\t\t\tmethod: \"GET\",\n\t\t\t\theaders: newHeaders,\n\t\t\t});\n\n\t\t\tif (autoAccept && response.webSocket) {\n\t\t\t\tresponse.webSocket.accept(acceptOptions);\n\t\t\t}\n\n\t\t\treturn response;\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Error upgrading to WebSocket\", error);\n\t\t\tthrow new Error(`Failed to upgrade WebSocket at ${finalUrl}: ${error}`);\n\t\t}\n\t}) as TypedWebSocketFetcher<T>;\n};\n\nexport type TypedHonoFetcher<T extends Hono> = BaseTypedHonoFetcher<T>;\n\nexport const honoFetcher = <T extends Hono>(\n\tfetcher: (\n\t\trequest: string,\n\t\tinit?: RequestInit,\n\t) => ReturnType<T[\"request\"]> | Promise<ReturnType<T[\"request\"]>>,\n): TypedHonoFetcher<T> => {\n\tconst methods = [\"get\", \"post\", \"put\", \"delete\", \"patch\"] as const;\n\n\tconst result = methods.reduce(\n\t\t(acc, method) => {\n\t\t\t(\n\t\t\t\tacc as TypedHonoFetcher<T> & {\n\t\t\t\t\t[M in typeof method]: TypedMethodFetcher<T, M>;\n\t\t\t\t}\n\t\t\t)[method] = createMethodFetcher(fetcher, method) as TypedMethodFetcher<\n\t\t\t\tT,\n\t\t\t\ttypeof method\n\t\t\t>;\n\t\t\treturn acc;\n\t\t},\n\t\t{} as TypedHonoFetcher<T>,\n\t);\n\n\t// Add websocket method\n\t(\n\t\tresult as TypedHonoFetcher<T> & { websocket?: TypedWebSocketFetcher<T> }\n\t).websocket = createWebSocketFetcher(fetcher);\n\n\treturn result;\n};\n"]}
@@ -1,4 +1,4 @@
1
- import { honoFetcher } from './chunk-ULIZJ5OD.js';
1
+ import { honoFetcher } from './chunk-5KDMHM65.js';
2
2
 
3
3
  // src/honoDirectFetcher.ts
4
4
  var honoDirectFetcher = (baseUrl) => {
@@ -8,5 +8,5 @@ var honoDirectFetcher = (baseUrl) => {
8
8
  };
9
9
 
10
10
  export { honoDirectFetcher };
11
- //# sourceMappingURL=chunk-YCTPXFUH.js.map
12
- //# sourceMappingURL=chunk-YCTPXFUH.js.map
11
+ //# sourceMappingURL=chunk-MZBZTJN5.js.map
12
+ //# sourceMappingURL=chunk-MZBZTJN5.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/honoDirectFetcher.ts"],"names":[],"mappings":";;;AAGO,IAAM,iBAAA,GAAoB,CAChC,OAAA,KACyB;AACzB,EAAA,OAAO,WAAA,CAAe,CAAC,OAAA,EAAS,IAAA,KAAS;AACxC,IAAA,OAAO,MAAM,CAAA,EAAG,OAAO,CAAA,EAAG,OAAO,IAAI,IAAI,CAAA;AAAA,EAC1C,CAAC,CAAA;AACF","file":"chunk-YCTPXFUH.js","sourcesContent":["import type { Hono } from \"hono\";\nimport { honoFetcher, type TypedHonoFetcher } from \"./honoFetcher\";\n\nexport const honoDirectFetcher = <T extends Hono>(\n\tbaseUrl: string,\n): TypedHonoFetcher<T> => {\n\treturn honoFetcher<T>((request, init) => {\n\t\treturn fetch(`${baseUrl}${request}`, init) as ReturnType<T[\"request\"]>;\n\t});\n};\n"]}
1
+ {"version":3,"sources":["../src/honoDirectFetcher.ts"],"names":[],"mappings":";;;AAGO,IAAM,iBAAA,GAAoB,CAChC,OAAA,KACyB;AACzB,EAAA,OAAO,WAAA,CAAe,CAAC,OAAA,EAAS,IAAA,KAAS;AACxC,IAAA,OAAO,MAAM,CAAA,EAAG,OAAO,CAAA,EAAG,OAAO,IAAI,IAAI,CAAA;AAAA,EAC1C,CAAC,CAAA;AACF","file":"chunk-MZBZTJN5.js","sourcesContent":["import type { Hono } from \"hono\";\nimport { honoFetcher, type TypedHonoFetcher } from \"./honoFetcher\";\n\nexport const honoDirectFetcher = <T extends Hono>(\n\tbaseUrl: string,\n): TypedHonoFetcher<T> => {\n\treturn honoFetcher<T>((request, init) => {\n\t\treturn fetch(`${baseUrl}${request}`, init) as ReturnType<T[\"request\"]>;\n\t});\n};\n"]}
@@ -1,4 +1,4 @@
1
- import { honoFetcher } from './chunk-ULIZJ5OD.js';
1
+ import { honoFetcher } from './chunk-5KDMHM65.js';
2
2
 
3
3
  // src/honoDoFetcher.ts
4
4
  var DUMMY_URL = "http://dummy-url";
@@ -39,5 +39,5 @@ var honoDoFetcherWithId = (namespace, id) => {
39
39
  };
40
40
 
41
41
  export { honoDoFetcher, honoDoFetcherWithId, honoDoFetcherWithName };
42
- //# sourceMappingURL=chunk-EXAM5VFZ.js.map
43
- //# sourceMappingURL=chunk-EXAM5VFZ.js.map
42
+ //# sourceMappingURL=chunk-WN4MD3WJ.js.map
43
+ //# sourceMappingURL=chunk-WN4MD3WJ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/honoDoFetcher.ts"],"names":[],"mappings":";;;AAQA,IAAM,SAAA,GAAY,kBAAA;AAiDlB,SAAS,eAAA,CAIR,MAEA,GAAA,EAE+C;AAC/C,EAAA,OAAO,MAAA,CAAO,OAAO,GAAA,EAAK;AAAA,IACzB,CAAC,MAAA,CAAO,OAAO,CAAA,GAAI;AAElB,MAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,OAAO,OAAO,CAAA;AAClD,MAAA,IAAI,OAAO,cAAc,UAAA,EAAY;AACpC,QAAA;AAAA,MACD;AACA,MAAA,IAAI;AACH,QAAA,SAAA,CAAU,KAAK,IAAI,CAAA;AAAA,MACpB,SAAS,CAAA,EAAG;AACX,QAAA,OAAA,CAAQ,KAAA;AAAA,UACP,2DAAA;AAAA,UACA;AAAA,SACD;AAAA,MACD;AAAA,IACD;AAAA,GACA,CAAA;AACF;AAkBO,IAAM,aAAA,GAAgB,CAC5B,aAAA,KAGyC;AAIzC,EAAA,MAAM,GAAA,GAAM,WAAA,CAAkC,CAAC,GAAA,EAAK,IAAA,KAAS;AAC5D,IAAA,OAAO,cAAc,KAAA,CAAM,CAAA,EAAG,SAAS,CAAA,EAAG,GAAG,IAAI,IAAI,CAAA;AAAA,EACtD,CAAC,CAAA;AACD,EAAA,OAAO,eAAA;AAAA,IACN,aAAA;AAAA,IACA;AAAA,GACD;AAGD;AAEO,IAAM,qBAAA,GAAwB,CAGpC,SAAA,EACA,IAAA,KACuD;AACvD,EAAA,OAAO,aAAA,CAAc,SAAA,CAAU,SAAA,CAAU,IAAI,CAAC,CAAA;AAI/C;AAEO,IAAM,mBAAA,GAAsB,CAGlC,SAAA,EACA,EAAA,KACuD;AACvD,EAAA,OAAO,aAAA;AAAA,IACN,SAAA,CAAU,GAAA,CAAI,SAAA,CAAU,YAAA,CAAa,EAAE,CAAC;AAAA,GACzC;AACD","file":"chunk-EXAM5VFZ.js","sourcesContent":["import type { Hono, Schema } from \"hono\";\nimport type { ExtractSchema } from \"hono/types\";\nimport {\n\thonoFetcher,\n\ttype BaseDisposableTypedHonoFetcher,\n\ttype TypedHonoFetcher,\n} from \"./honoFetcher\";\n\nconst DUMMY_URL = \"http://dummy-url\";\n\nexport type DOWithHonoApp<S extends Schema = Schema> =\n\tRpc.DurableObjectBranded & {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: We need to be able to pass in any schema\n\t\tapp: Hono<any, S>;\n\t};\n\nexport type DOSchemaMap<T extends DOWithHonoApp> = T extends DOWithHonoApp\n\t? ExtractSchema<T[\"app\"]>\n\t: never;\n\nexport type DOSchemaKeys<T extends DOWithHonoApp> = string &\n\tkeyof DOSchemaMap<T>;\n\nexport type DOStubSchema<T extends DurableObjectStub> =\n\tT extends DurableObjectStub<infer S>\n\t\t? S extends DOWithHonoApp\n\t\t\t? ExtractSchema<S[\"app\"]>\n\t\t\t: never\n\t\t: never;\n\n/**\n * Fetcher for a **real** `DurableObjectStub`: HTTP results are {@link RpcDisposableJsonResponse}\n * and `websocket` returns `Response & Disposable`, matching Workers RPC when the runtime attaches\n * disposers. Use with {@link honoDoFetcher} / {@link honoDoFetcherWithName} / {@link honoDoFetcherWithId}\n * when `T` is a full stub—not with a minimal `Pick<stub, \"fetch\">` mock (that path uses plain\n * {@link TypedHonoFetcher} responses instead).\n *\n * @see https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/\n */\nexport type TypedDoFetcher<T extends DurableObjectStub> =\n\tBaseDisposableTypedHonoFetcher<\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Generic parameter needs flexibility\n\t\tHono<any, DOStubSchema<T>>\n\t>;\n\n/**\n * Argument to {@link honoDoFetcher}: a **full** {@link DurableObjectStub} (production) or a minimal\n * **`{ fetch }`** mock. Only the full stub is typed as {@link TypedDoFetcher} with disposable RPC\n * responses; **`Pick<stub, \"fetch\">`** is typed as {@link TypedHonoFetcher} for `Hono` with ordinary\n * `JsonResponse` / `Response` (no `Disposable` on results—matches mocks without `Symbol.dispose`).\n *\n * @see https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/\n */\nexport type HonoDoFetcherStubInput =\n\t| DurableObjectStub<DOWithHonoApp>\n\t| Pick<DurableObjectStub<DOWithHonoApp>, \"fetch\">;\n\nfunction withStubDispose<\n\tTStub extends Pick<DurableObjectStub<DOWithHonoApp>, \"fetch\">,\n\tTS extends Schema,\n>(\n\tstub: TStub,\n\t// biome-ignore lint/suspicious/noExplicitAny: Matches honoFetcher generic pattern for schema-driven apps\n\tapi: TypedHonoFetcher<Hono<any, TS>>,\n\t// biome-ignore lint/suspicious/noExplicitAny: Matches honoFetcher generic pattern for schema-driven apps\n): TypedHonoFetcher<Hono<any, TS>> & Disposable {\n\treturn Object.assign(api, {\n\t\t[Symbol.dispose]() {\n\t\t\t// Stubs may omit Symbol.dispose (e.g. Vite mocks); DurableObjectStub types may not list it.\n\t\t\tconst disposeFn = Reflect.get(stub, Symbol.dispose);\n\t\t\tif (typeof disposeFn !== \"function\") {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tdisposeFn.call(stub);\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t\"[@firtoz/hono-fetcher] Durable Object stub dispose failed\",\n\t\t\t\t\te,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t});\n}\n\n/**\n * Typed fetcher for a Durable Object stub.\n *\n * - **Full `DurableObjectStub`:** return type is {@link TypedDoFetcher} **`& Disposable`** — each\n * HTTP/WebSocket result is typed as disposable (`RpcDisposableJsonResponse` / `Response & Disposable`)\n * so **`using res = await …`** type-checks when `\"ESNext.Disposable\"` is in `lib`, matching Workers RPC\n * when the runtime attaches `[Symbol.dispose]` (see `@see` below).\n * - **`Pick<stub, \"fetch\">` only (e.g. tests):** return type is **`TypedHonoFetcher<Hono> & Disposable`**\n * — same **`JsonResponse` / `Response`** shapes as {@link honoFetcher}; results are **not** typed as\n * `Disposable` so typings are not faked for mocks that lack RPC disposers.\n *\n * Disposing only the fetcher (`using api = …`) releases the **stub**; RPC **`Response`** disposal\n * (when applicable) is separate — prefer **`using res`**, **`res[Symbol.dispose]()`**, or **`DisposableStack`**.\n *\n * @see https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/\n */\nexport const honoDoFetcher = <const T extends HonoDoFetcherStubInput>(\n\tdurableObject: T,\n): T extends DurableObjectStub<DOWithHonoApp>\n\t? TypedDoFetcher<T> & Disposable\n\t: TypedHonoFetcher<Hono> & Disposable => {\n\ttype OutSchema =\n\t\tT extends DurableObjectStub<DOWithHonoApp> ? DOStubSchema<T> : Schema;\n\t// biome-ignore lint/suspicious/noExplicitAny: Generic parameter needs flexibility\n\tconst api = honoFetcher<Hono<any, OutSchema>>((url, init) => {\n\t\treturn durableObject.fetch(`${DUMMY_URL}${url}`, init);\n\t});\n\treturn withStubDispose(\n\t\tdurableObject,\n\t\tapi,\n\t) as T extends DurableObjectStub<DOWithHonoApp>\n\t\t? TypedDoFetcher<T> & Disposable\n\t\t: TypedHonoFetcher<Hono> & Disposable;\n};\n\nexport const honoDoFetcherWithName = <\n\tconst T extends Rpc.DurableObjectBranded & DOWithHonoApp,\n>(\n\tnamespace: DurableObjectNamespace<T>,\n\tname: string,\n): TypedDoFetcher<DurableObjectStub<T>> & Disposable => {\n\treturn honoDoFetcher(namespace.getByName(name)) as TypedDoFetcher<\n\t\tDurableObjectStub<T>\n\t> &\n\t\tDisposable;\n};\n\nexport const honoDoFetcherWithId = <\n\tconst T extends Rpc.DurableObjectBranded & DOWithHonoApp,\n>(\n\tnamespace: DurableObjectNamespace<T>,\n\tid: string,\n): TypedDoFetcher<DurableObjectStub<T>> & Disposable => {\n\treturn honoDoFetcher(\n\t\tnamespace.get(namespace.idFromString(id)),\n\t) as TypedDoFetcher<DurableObjectStub<T>> & Disposable;\n};\n"]}
1
+ {"version":3,"sources":["../src/honoDoFetcher.ts"],"names":[],"mappings":";;;AAQA,IAAM,SAAA,GAAY,kBAAA;AAiDlB,SAAS,eAAA,CAIR,MAEA,GAAA,EAE+C;AAC/C,EAAA,OAAO,MAAA,CAAO,OAAO,GAAA,EAAK;AAAA,IACzB,CAAC,MAAA,CAAO,OAAO,CAAA,GAAI;AAElB,MAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,OAAO,OAAO,CAAA;AAClD,MAAA,IAAI,OAAO,cAAc,UAAA,EAAY;AACpC,QAAA;AAAA,MACD;AACA,MAAA,IAAI;AACH,QAAA,SAAA,CAAU,KAAK,IAAI,CAAA;AAAA,MACpB,SAAS,CAAA,EAAG;AACX,QAAA,OAAA,CAAQ,KAAA;AAAA,UACP,2DAAA;AAAA,UACA;AAAA,SACD;AAAA,MACD;AAAA,IACD;AAAA,GACA,CAAA;AACF;AAkBO,IAAM,aAAA,GAAgB,CAC5B,aAAA,KAGyC;AAIzC,EAAA,MAAM,GAAA,GAAM,WAAA,CAAkC,CAAC,GAAA,EAAK,IAAA,KAAS;AAC5D,IAAA,OAAO,cAAc,KAAA,CAAM,CAAA,EAAG,SAAS,CAAA,EAAG,GAAG,IAAI,IAAI,CAAA;AAAA,EACtD,CAAC,CAAA;AACD,EAAA,OAAO,eAAA;AAAA,IACN,aAAA;AAAA,IACA;AAAA,GACD;AAGD;AAEO,IAAM,qBAAA,GAAwB,CAGpC,SAAA,EACA,IAAA,KACuD;AACvD,EAAA,OAAO,aAAA,CAAc,SAAA,CAAU,SAAA,CAAU,IAAI,CAAC,CAAA;AAI/C;AAEO,IAAM,mBAAA,GAAsB,CAGlC,SAAA,EACA,EAAA,KACuD;AACvD,EAAA,OAAO,aAAA;AAAA,IACN,SAAA,CAAU,GAAA,CAAI,SAAA,CAAU,YAAA,CAAa,EAAE,CAAC;AAAA,GACzC;AACD","file":"chunk-WN4MD3WJ.js","sourcesContent":["import type { Hono, Schema } from \"hono\";\nimport type { ExtractSchema } from \"hono/types\";\nimport {\n\thonoFetcher,\n\ttype BaseDisposableTypedHonoFetcher,\n\ttype TypedHonoFetcher,\n} from \"./honoFetcher\";\n\nconst DUMMY_URL = \"http://dummy-url\";\n\nexport type DOWithHonoApp<S extends Schema = Schema> =\n\tRpc.DurableObjectBranded & {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: We need to be able to pass in any schema\n\t\tapp: Hono<any, S>;\n\t};\n\nexport type DOSchemaMap<T extends DOWithHonoApp> = T extends DOWithHonoApp\n\t? ExtractSchema<T[\"app\"]>\n\t: never;\n\nexport type DOSchemaKeys<T extends DOWithHonoApp> = string &\n\tkeyof DOSchemaMap<T>;\n\nexport type DOStubSchema<T extends DurableObjectStub> =\n\tT extends DurableObjectStub<infer S>\n\t\t? S extends DOWithHonoApp\n\t\t\t? ExtractSchema<S[\"app\"]>\n\t\t\t: never\n\t\t: never;\n\n/**\n * Fetcher for a **real** `DurableObjectStub`: HTTP results are {@link RpcDisposableJsonResponse}\n * and `websocket` returns `Response & Disposable`, matching Workers RPC when the runtime attaches\n * disposers. Use with {@link honoDoFetcher} / {@link honoDoFetcherWithName} / {@link honoDoFetcherWithId}\n * when `T` is a full stub—not with a minimal `Pick<stub, \"fetch\">` mock (that path uses plain\n * {@link TypedHonoFetcher} responses instead).\n *\n * @see https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/\n */\nexport type TypedDoFetcher<T extends DurableObjectStub> =\n\tBaseDisposableTypedHonoFetcher<\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Generic parameter needs flexibility\n\t\tHono<any, DOStubSchema<T>>\n\t>;\n\n/**\n * Argument to {@link honoDoFetcher}: a **full** {@link DurableObjectStub} (production) or a minimal\n * **`{ fetch }`** mock. Only the full stub is typed as {@link TypedDoFetcher} with disposable RPC\n * responses; **`Pick<stub, \"fetch\">`** is typed as {@link TypedHonoFetcher} for `Hono` with ordinary\n * `JsonResponse` / `Response` (no `Disposable` on results—matches mocks without `Symbol.dispose`).\n *\n * @see https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/\n */\nexport type HonoDoFetcherStubInput =\n\t| DurableObjectStub<DOWithHonoApp>\n\t| Pick<DurableObjectStub<DOWithHonoApp>, \"fetch\">;\n\nfunction withStubDispose<\n\tTStub extends Pick<DurableObjectStub<DOWithHonoApp>, \"fetch\">,\n\tTS extends Schema,\n>(\n\tstub: TStub,\n\t// biome-ignore lint/suspicious/noExplicitAny: Matches honoFetcher generic pattern for schema-driven apps\n\tapi: TypedHonoFetcher<Hono<any, TS>>,\n\t// biome-ignore lint/suspicious/noExplicitAny: Matches honoFetcher generic pattern for schema-driven apps\n): TypedHonoFetcher<Hono<any, TS>> & Disposable {\n\treturn Object.assign(api, {\n\t\t[Symbol.dispose]() {\n\t\t\t// Stubs may omit Symbol.dispose (e.g. Vite mocks); DurableObjectStub types may not list it.\n\t\t\tconst disposeFn = Reflect.get(stub, Symbol.dispose);\n\t\t\tif (typeof disposeFn !== \"function\") {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tdisposeFn.call(stub);\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t\"[@firtoz/hono-fetcher] Durable Object stub dispose failed\",\n\t\t\t\t\te,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t});\n}\n\n/**\n * Typed fetcher for a Durable Object stub.\n *\n * - **Full `DurableObjectStub`:** return type is {@link TypedDoFetcher} **`& Disposable`** — each\n * HTTP/WebSocket result is typed as disposable (`RpcDisposableJsonResponse` / `Response & Disposable`)\n * so **`using res = await …`** type-checks when `\"ESNext.Disposable\"` is in `lib`, matching Workers RPC\n * when the runtime attaches `[Symbol.dispose]` (see `@see` below).\n * - **`Pick<stub, \"fetch\">` only (e.g. tests):** return type is **`TypedHonoFetcher<Hono> & Disposable`**\n * — same **`JsonResponse` / `Response`** shapes as {@link honoFetcher}; results are **not** typed as\n * `Disposable` so typings are not faked for mocks that lack RPC disposers.\n *\n * Disposing only the fetcher (`using api = …`) releases the **stub**; RPC **`Response`** disposal\n * (when applicable) is separate — prefer **`using res`**, **`res[Symbol.dispose]()`**, or **`DisposableStack`**.\n *\n * @see https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/\n */\nexport const honoDoFetcher = <const T extends HonoDoFetcherStubInput>(\n\tdurableObject: T,\n): T extends DurableObjectStub<DOWithHonoApp>\n\t? TypedDoFetcher<T> & Disposable\n\t: TypedHonoFetcher<Hono> & Disposable => {\n\ttype OutSchema =\n\t\tT extends DurableObjectStub<DOWithHonoApp> ? DOStubSchema<T> : Schema;\n\t// biome-ignore lint/suspicious/noExplicitAny: Generic parameter needs flexibility\n\tconst api = honoFetcher<Hono<any, OutSchema>>((url, init) => {\n\t\treturn durableObject.fetch(`${DUMMY_URL}${url}`, init);\n\t});\n\treturn withStubDispose(\n\t\tdurableObject,\n\t\tapi,\n\t) as T extends DurableObjectStub<DOWithHonoApp>\n\t\t? TypedDoFetcher<T> & Disposable\n\t\t: TypedHonoFetcher<Hono> & Disposable;\n};\n\nexport const honoDoFetcherWithName = <\n\tconst T extends Rpc.DurableObjectBranded & DOWithHonoApp,\n>(\n\tnamespace: DurableObjectNamespace<T>,\n\tname: string,\n): TypedDoFetcher<DurableObjectStub<T>> & Disposable => {\n\treturn honoDoFetcher(namespace.getByName(name)) as TypedDoFetcher<\n\t\tDurableObjectStub<T>\n\t> &\n\t\tDisposable;\n};\n\nexport const honoDoFetcherWithId = <\n\tconst T extends Rpc.DurableObjectBranded & DOWithHonoApp,\n>(\n\tnamespace: DurableObjectNamespace<T>,\n\tid: string,\n): TypedDoFetcher<DurableObjectStub<T>> & Disposable => {\n\treturn honoDoFetcher(\n\t\tnamespace.get(namespace.idFromString(id)),\n\t) as TypedDoFetcher<DurableObjectStub<T>> & Disposable;\n};\n"]}
@@ -1,4 +1,4 @@
1
- export { honoDirectFetcher } from './chunk-YCTPXFUH.js';
2
- import './chunk-ULIZJ5OD.js';
1
+ export { honoDirectFetcher } from './chunk-MZBZTJN5.js';
2
+ import './chunk-5KDMHM65.js';
3
3
  //# sourceMappingURL=honoDirectFetcher.js.map
4
4
  //# sourceMappingURL=honoDirectFetcher.js.map
@@ -1,4 +1,4 @@
1
- export { honoDoFetcher, honoDoFetcherWithId, honoDoFetcherWithName } from './chunk-EXAM5VFZ.js';
2
- import './chunk-ULIZJ5OD.js';
1
+ export { honoDoFetcher, honoDoFetcherWithId, honoDoFetcherWithName } from './chunk-WN4MD3WJ.js';
2
+ import './chunk-5KDMHM65.js';
3
3
  //# sourceMappingURL=honoDoFetcher.js.map
4
4
  //# sourceMappingURL=honoDoFetcher.js.map
@@ -77,6 +77,12 @@ export interface WebSocketConfig {
77
77
  * @default true
78
78
  */
79
79
  autoAccept?: boolean;
80
+ /**
81
+ * Arguments for Cloudflare’s `WebSocket#accept` (e.g. `{ allowHalfOpen: true }` when
82
+ * [proxying](https://developers.cloudflare.com/workers/runtime-apis/websockets/#close-behavior)
83
+ * and coordinating close on both sides). Used only when `autoAccept` is true.
84
+ */
85
+ acceptOptions?: WebSocketAcceptOptions;
80
86
  }
81
87
  export type TypedWebSocketFetcher<T extends Hono> = <SchemaPath extends string & keyof HonoSchema<T>["get"]>(request: {
82
88
  url: SchemaPath;
@@ -1,3 +1,3 @@
1
- export { honoFetcher } from './chunk-ULIZJ5OD.js';
1
+ export { honoFetcher } from './chunk-5KDMHM65.js';
2
2
  //# sourceMappingURL=honoFetcher.js.map
3
3
  //# sourceMappingURL=honoFetcher.js.map
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- export { honoDirectFetcher } from './chunk-YCTPXFUH.js';
2
- export { honoDoFetcher, honoDoFetcherWithId, honoDoFetcherWithName } from './chunk-EXAM5VFZ.js';
3
- export { honoFetcher } from './chunk-ULIZJ5OD.js';
1
+ export { honoDirectFetcher } from './chunk-MZBZTJN5.js';
2
+ export { honoDoFetcher, honoDoFetcherWithId, honoDoFetcherWithName } from './chunk-WN4MD3WJ.js';
3
+ export { honoFetcher } from './chunk-5KDMHM65.js';
4
4
  //# sourceMappingURL=index.js.map
5
5
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firtoz/hono-fetcher",
3
- "version": "2.7.1",
3
+ "version": "2.7.2",
4
4
  "description": "Type-safe Hono API client with full TypeScript inference for routes, params, and payloads",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -56,7 +56,7 @@
56
56
  "url": "https://github.com/firtoz/fullstack-toolkit/issues"
57
57
  },
58
58
  "peerDependencies": {
59
- "@cloudflare/workers-types": "^4.20260422.1",
59
+ "@cloudflare/workers-types": "^4.20260423.1",
60
60
  "hono": "^4.12.14"
61
61
  },
62
62
  "engines": {
@@ -174,6 +174,12 @@ export interface WebSocketConfig {
174
174
  * @default true
175
175
  */
176
176
  autoAccept?: boolean;
177
+ /**
178
+ * Arguments for Cloudflare’s `WebSocket#accept` (e.g. `{ allowHalfOpen: true }` when
179
+ * [proxying](https://developers.cloudflare.com/workers/runtime-apis/websockets/#close-behavior)
180
+ * and coordinating close on both sides). Used only when `autoAccept` is true.
181
+ */
182
+ acceptOptions?: WebSocketAcceptOptions;
177
183
  }
178
184
 
179
185
  export type TypedWebSocketFetcher<T extends Hono> = <
@@ -294,7 +300,8 @@ const createWebSocketFetcher = <T extends Hono>(
294
300
  let finalUrl: string = request.url;
295
301
 
296
302
  const { init = {}, params, query, config } = request;
297
- const autoAccept = config?.autoAccept ?? true; // Default to true
303
+ const autoAccept = config?.autoAccept ?? true;
304
+ const acceptOptions = config?.acceptOptions;
298
305
 
299
306
  if (params && typeof params === "object") {
300
307
  finalUrl = Object.entries(params).reduce((acc, [key, value]) => {
@@ -316,9 +323,8 @@ const createWebSocketFetcher = <T extends Hono>(
316
323
  headers: newHeaders,
317
324
  });
318
325
 
319
- // Auto-accept the WebSocket if configured (default: true)
320
326
  if (autoAccept && response.webSocket) {
321
- response.webSocket.accept();
327
+ response.webSocket.accept(acceptOptions);
322
328
  }
323
329
 
324
330
  return response;
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/honoFetcher.ts"],"names":[],"mappings":"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","file":"chunk-ULIZJ5OD.js","sourcesContent":["import type { Hono } from \"hono\";\nimport type { ExtractSchema } from \"hono/types\";\n\nexport type ParsePathParams<T extends string> =\n\tT extends `${infer _Start}/:${infer Param}/${infer Rest}`\n\t\t? { [K in Param | keyof ParsePathParams<`/${Rest}`>]: string }\n\t\t: T extends `${infer _Start}/:${infer Param}`\n\t\t\t? { [K in Param]: string }\n\t\t\t: never;\n\nexport type HttpMethod = \"get\" | \"post\" | \"put\" | \"delete\" | \"patch\";\n\nexport type HonoSchemaKeys<T extends Hono> = string & keyof ExtractSchema<T>;\n\ntype FilterKeysByMethod<\n\tTApp extends ExtractSchema<unknown>,\n\tTMethod extends HttpMethod,\n> = {\n\t[K in keyof TApp as TApp[K] extends { [key in `$${TMethod}`]: unknown }\n\t\t? K\n\t\t: never]: TApp[K];\n};\n\ntype HonoSchema<TApp extends Hono> = {\n\t[M in HttpMethod]: FilterKeysByMethod<ExtractSchema<TApp>, M>;\n};\n\nexport type JsonResponse<T> = Omit<Response, \"json\"> & {\n\tjson: () => Promise<T>;\n};\n\n/**\n * {@link JsonResponse} intersected with `Disposable` for Workers RPC: `Response`\n * values from `DurableObjectStub#fetch()` may implement `[Symbol.dispose]` even\n * though `Fetcher.fetch` is still typed as `Promise<Response>`. Use with\n * {@link BaseDisposableTypedHonoFetcher} (and `TypedDoFetcher` from `./honoDoFetcher`) so\n * `using resp = await api.get(...)` type-checks when `\"ESNext.Disposable\"` is in `lib`.\n *\n * @see https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/\n */\nexport type RpcDisposableJsonResponse<T> = JsonResponse<T> & Disposable;\n\ntype HasPathParams<T extends string> = T extends `${string}:${string}`\n\t? true\n\t: false;\n\n/**\n * Values allowed in the optional `query` object on fetcher requests.\n * `null` and `undefined` entries are omitted from the serialized query string.\n */\nexport type HonoFetcherQueryParamValue = string | number | boolean;\n\nexport type HonoFetcherQueryParams = Record<\n\tstring,\n\tHonoFetcherQueryParamValue | null | undefined\n>;\n\nfunction appendQueryString(\n\turl: string,\n\tquery?: HonoFetcherQueryParams,\n): string {\n\tif (!query) {\n\t\treturn url;\n\t}\n\tconst searchParams = new URLSearchParams();\n\tfor (const [key, value] of Object.entries(query)) {\n\t\tif (value === undefined || value === null) {\n\t\t\tcontinue;\n\t\t}\n\t\tsearchParams.append(key, String(value));\n\t}\n\tconst serialized = searchParams.toString();\n\tif (!serialized) {\n\t\treturn url;\n\t}\n\tconst separator = url.includes(\"?\") ? \"&\" : \"?\";\n\treturn `${url}${separator}${serialized}`;\n}\n\n/**\n * `RequestInit` fields that honoFetcher sets must not be overwritten by spreading `...init` last.\n */\nfunction restOfRequestInit(\n\tinit: RequestInit,\n): Omit<RequestInit, \"headers\" | \"body\" | \"method\"> {\n\tconst { headers: _h, body: _b, method: _m, ...rest } = init;\n\treturn rest;\n}\n\ntype FetcherParams<SchemaPath extends string> =\n\tHasPathParams<SchemaPath> extends true\n\t\t? {\n\t\t\t\tparams: ParsePathParams<SchemaPath>;\n\t\t\t\tquery?: HonoFetcherQueryParams;\n\t\t\t\tinit?: RequestInit;\n\t\t\t}\n\t\t: {\n\t\t\t\tparams?: never;\n\t\t\t\tquery?: HonoFetcherQueryParams;\n\t\t\t\tinit?: RequestInit;\n\t\t\t};\n\n// biome-ignore lint/complexity/noBannedTypes: We need an empty object to remove the body and form keys from the request object\ntype EmptyObject = {};\n\ntype TypedMethodFetcher<T extends Hono, M extends HttpMethod> = <\n\tSchemaPath extends string & keyof HonoSchema<T>[M],\n>(\n\trequest: {\n\t\turl: SchemaPath;\n\t} & FetcherParams<SchemaPath> &\n\t\t(M extends \"get\" | \"delete\" ? EmptyObject : BodyParams<T, M, SchemaPath>),\n) => Promise<SchemaOutput<T, M, SchemaPath>>;\n\ntype SchemaOutput<\n\tT extends Hono,\n\tM extends HttpMethod,\n\tSchemaPath extends string & keyof HonoSchema<T>[M],\n\tDollarM extends `$${M}` & keyof HonoSchema<T>[M][SchemaPath] = `$${M}` &\n\t\tkeyof HonoSchema<T>[M][SchemaPath],\n> = \"output\" extends keyof HonoSchema<T>[M][SchemaPath][DollarM]\n\t? JsonResponse<HonoSchema<T>[M][SchemaPath][DollarM][\"output\"]>\n\t: never;\n\ntype DoSchemaOutput<\n\tT extends Hono,\n\tM extends HttpMethod,\n\tSchemaPath extends string & keyof HonoSchema<T>[M],\n\tDollarM extends `$${M}` & keyof HonoSchema<T>[M][SchemaPath] = `$${M}` &\n\t\tkeyof HonoSchema<T>[M][SchemaPath],\n> = \"output\" extends keyof HonoSchema<T>[M][SchemaPath][DollarM]\n\t? RpcDisposableJsonResponse<HonoSchema<T>[M][SchemaPath][DollarM][\"output\"]>\n\t: never;\n\ntype BodyParams<\n\tTApp extends Hono,\n\tTMethod extends HttpMethod,\n\tSchemaPath extends string & keyof HonoSchema<TApp>[TMethod],\n\tDollarMethod extends `$${TMethod}` &\n\t\tkeyof HonoSchema<TApp>[TMethod][SchemaPath] = `$${TMethod}` &\n\t\tkeyof HonoSchema<TApp>[TMethod][SchemaPath],\n> = \"input\" extends keyof HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod]\n\t? \"json\" extends keyof HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod][\"input\"]\n\t\t? \"form\" extends keyof HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod][\"input\"]\n\t\t\t?\n\t\t\t\t\t| {\n\t\t\t\t\t\t\tbody: HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod][\"input\"][\"json\"];\n\t\t\t\t\t }\n\t\t\t\t\t| {\n\t\t\t\t\t\t\tform: HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod][\"input\"][\"form\"];\n\t\t\t\t\t }\n\t\t\t: {\n\t\t\t\t\tbody: HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod][\"input\"][\"json\"];\n\t\t\t\t}\n\t\t: \"form\" extends keyof HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod][\"input\"]\n\t\t\t? {\n\t\t\t\t\tform: HonoSchema<TApp>[TMethod][SchemaPath][DollarMethod][\"input\"][\"form\"];\n\t\t\t\t}\n\t\t\t: { body?: unknown } | { form?: unknown }\n\t: EmptyObject;\n\ntype AvailableMethods<T extends Hono> = {\n\t[M in HttpMethod]: keyof HonoSchema<T>[M] extends never ? never : M;\n}[HttpMethod];\n\nexport interface WebSocketConfig {\n\t/**\n\t * Whether to automatically call accept() on the WebSocket before returning.\n\t * Defaults to true for convenience.\n\t *\n\t * In Cloudflare Workers, you must call accept() before using a WebSocket.\n\t * Setting this to false allows you to call accept() manually if needed.\n\t *\n\t * @default true\n\t */\n\tautoAccept?: boolean;\n}\n\nexport type TypedWebSocketFetcher<T extends Hono> = <\n\tSchemaPath extends string & keyof HonoSchema<T>[\"get\"],\n>(\n\trequest: {\n\t\turl: SchemaPath;\n\t\tconfig?: WebSocketConfig;\n\t} & FetcherParams<SchemaPath>,\n) => Promise<Response>;\n\nexport type BaseTypedHonoFetcher<T extends Hono> = {\n\t[M in AvailableMethods<T>]: TypedMethodFetcher<T, M>;\n} & (keyof HonoSchema<T>[\"get\"] extends never\n\t? // biome-ignore lint/complexity/noBannedTypes: We really do want an empty object if the get method is not available\n\t\t{}\n\t: { websocket: TypedWebSocketFetcher<T> });\n\ntype TypedDisposableMethodFetcher<T extends Hono, M extends HttpMethod> = <\n\tSchemaPath extends string & keyof HonoSchema<T>[M],\n>(\n\trequest: {\n\t\turl: SchemaPath;\n\t} & FetcherParams<SchemaPath> &\n\t\t(M extends \"get\" | \"delete\" ? EmptyObject : BodyParams<T, M, SchemaPath>),\n) => Promise<DoSchemaOutput<T, M, SchemaPath>>;\n\nexport type TypedDisposableWebSocketFetcher<T extends Hono> = <\n\tSchemaPath extends string & keyof HonoSchema<T>[\"get\"],\n>(\n\trequest: {\n\t\turl: SchemaPath;\n\t\tconfig?: WebSocketConfig;\n\t} & FetcherParams<SchemaPath>,\n) => Promise<Response & Disposable>;\n\n/**\n * Same shape as {@link BaseTypedHonoFetcher} but HTTP methods return\n * {@link RpcDisposableJsonResponse} and `websocket` returns `Response & Disposable`\n * so `using` on RPC results type-checks for Durable Object clients.\n *\n * @see https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/\n */\nexport type BaseDisposableTypedHonoFetcher<T extends Hono> = {\n\t[M in AvailableMethods<T>]: TypedDisposableMethodFetcher<T, M>;\n} & (keyof HonoSchema<T>[\"get\"] extends never\n\t? // biome-ignore lint/complexity/noBannedTypes: We really do want an empty object if the get method is not available\n\t\t{}\n\t: { websocket: TypedDisposableWebSocketFetcher<T> });\n\nconst createMethodFetcher = <T extends Hono, M extends HttpMethod>(\n\tfetcher: (\n\t\trequest: string,\n\t\tinit?: RequestInit,\n\t) => ReturnType<T[\"request\"]> | Promise<ReturnType<T[\"request\"]>>,\n\tmethod: M,\n): TypedMethodFetcher<T, M> => {\n\treturn (async (request) => {\n\t\tlet finalUrl: string = request.url;\n\n\t\tconst { init = {}, params, query } = request;\n\n\t\tif (params && typeof params === \"object\") {\n\t\t\tfinalUrl = Object.entries(params).reduce((acc, [key, value]) => {\n\t\t\t\treturn acc.replace(`:${key}`, value as string);\n\t\t\t}, finalUrl);\n\t\t}\n\n\t\tfinalUrl = appendQueryString(finalUrl, query);\n\n\t\tconst requestAsOptionalFormBody = request as {\n\t\t\tform?: unknown;\n\t\t\tbody?: unknown;\n\t\t};\n\n\t\tlet body: BodyInit | undefined;\n\t\tif (requestAsOptionalFormBody.form) {\n\t\t\tconst formData = new FormData();\n\t\t\tfor (const [key, value] of Object.entries(\n\t\t\t\trequestAsOptionalFormBody.form,\n\t\t\t)) {\n\t\t\t\tformData.append(key, value as string);\n\t\t\t}\n\t\t\tbody = formData;\n\t\t} else if (requestAsOptionalFormBody.body) {\n\t\t\tbody = JSON.stringify(requestAsOptionalFormBody.body) as BodyInit;\n\t\t}\n\n\t\tconst newHeaders = new Headers(\n\t\t\tinit.headers as unknown as ConstructorParameters<typeof Headers>[0],\n\t\t);\n\n\t\tif (body && !requestAsOptionalFormBody.form) {\n\t\t\tnewHeaders.set(\"Content-Type\", \"application/json\");\n\t\t}\n\n\t\ttry {\n\t\t\treturn await fetcher(finalUrl, {\n\t\t\t\t...restOfRequestInit(init),\n\t\t\t\tmethod: method.toUpperCase(),\n\t\t\t\theaders: newHeaders,\n\t\t\t\t...(body ? { body } : {}),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconsole.error(`Error ${method}ing`, error);\n\t\t\tthrow new Error(`Failed to ${method} ${finalUrl}: ${error}`);\n\t\t}\n\t}) as TypedMethodFetcher<T, M>;\n};\n\nconst createWebSocketFetcher = <T extends Hono>(\n\tfetcher: (\n\t\trequest: string,\n\t\tinit?: RequestInit,\n\t) => ReturnType<T[\"request\"]> | Promise<ReturnType<T[\"request\"]>>,\n): TypedWebSocketFetcher<T> => {\n\treturn (async (request) => {\n\t\tlet finalUrl: string = request.url;\n\n\t\tconst { init = {}, params, query, config } = request;\n\t\tconst autoAccept = config?.autoAccept ?? true; // Default to true\n\n\t\tif (params && typeof params === \"object\") {\n\t\t\tfinalUrl = Object.entries(params).reduce((acc, [key, value]) => {\n\t\t\t\treturn acc.replace(`:${key}`, value as string);\n\t\t\t}, finalUrl);\n\t\t}\n\n\t\tfinalUrl = appendQueryString(finalUrl, query);\n\n\t\tconst newHeaders = new Headers(\n\t\t\tinit.headers as unknown as ConstructorParameters<typeof Headers>[0],\n\t\t);\n\t\tnewHeaders.set(\"Upgrade\", \"websocket\");\n\n\t\ttry {\n\t\t\tconst response = await fetcher(finalUrl, {\n\t\t\t\t...restOfRequestInit(init),\n\t\t\t\tmethod: \"GET\",\n\t\t\t\theaders: newHeaders,\n\t\t\t});\n\n\t\t\t// Auto-accept the WebSocket if configured (default: true)\n\t\t\tif (autoAccept && response.webSocket) {\n\t\t\t\tresponse.webSocket.accept();\n\t\t\t}\n\n\t\t\treturn response;\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Error upgrading to WebSocket\", error);\n\t\t\tthrow new Error(`Failed to upgrade WebSocket at ${finalUrl}: ${error}`);\n\t\t}\n\t}) as TypedWebSocketFetcher<T>;\n};\n\nexport type TypedHonoFetcher<T extends Hono> = BaseTypedHonoFetcher<T>;\n\nexport const honoFetcher = <T extends Hono>(\n\tfetcher: (\n\t\trequest: string,\n\t\tinit?: RequestInit,\n\t) => ReturnType<T[\"request\"]> | Promise<ReturnType<T[\"request\"]>>,\n): TypedHonoFetcher<T> => {\n\tconst methods = [\"get\", \"post\", \"put\", \"delete\", \"patch\"] as const;\n\n\tconst result = methods.reduce(\n\t\t(acc, method) => {\n\t\t\t(\n\t\t\t\tacc as TypedHonoFetcher<T> & {\n\t\t\t\t\t[M in typeof method]: TypedMethodFetcher<T, M>;\n\t\t\t\t}\n\t\t\t)[method] = createMethodFetcher(fetcher, method) as TypedMethodFetcher<\n\t\t\t\tT,\n\t\t\t\ttypeof method\n\t\t\t>;\n\t\t\treturn acc;\n\t\t},\n\t\t{} as TypedHonoFetcher<T>,\n\t);\n\n\t// Add websocket method\n\t(\n\t\tresult as TypedHonoFetcher<T> & { websocket?: TypedWebSocketFetcher<T> }\n\t).websocket = createWebSocketFetcher(fetcher);\n\n\treturn result;\n};\n"]}