@firtoz/hono-fetcher 2.3.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,6 +6,8 @@
6
6
 
7
7
  Type-safe Hono API client with full TypeScript inference for routes, params, and payloads.
8
8
 
9
+ > **⚠️ Early WIP Notice:** This package is in very early development and is **not production-ready**. It is TypeScript-only and may have breaking changes. While I (the maintainer) have limited time, I'm open to PRs for features, bug fixes, or additional support (like JS builds). Please feel free to try it out and contribute! See [CONTRIBUTING.md](../../CONTRIBUTING.md) for details.
10
+
9
11
  ## Features
10
12
 
11
13
  - 🔒 **Fully Type-Safe** - Complete TypeScript inference for routes, parameters, request bodies, and responses
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firtoz/hono-fetcher",
3
- "version": "2.3.1",
3
+ "version": "2.4.0",
4
4
  "description": "Type-safe Hono API client with full TypeScript inference for routes, params, and payloads",
5
5
  "main": "./src/index.ts",
6
6
  "module": "./src/index.ts",
@@ -23,7 +23,7 @@
23
23
  "README.md"
24
24
  ],
25
25
  "scripts": {
26
- "typecheck": "tsc --noEmit -p ./tsconfig.json",
26
+ "typecheck": "tsgo --noEmit -p ./tsconfig.json",
27
27
  "lint": "biome check --write src",
28
28
  "lint:ci": "biome ci src",
29
29
  "format": "biome format src --write",
@@ -52,8 +52,8 @@
52
52
  "url": "https://github.com/firtoz/fullstack-toolkit/issues"
53
53
  },
54
54
  "peerDependencies": {
55
- "@cloudflare/workers-types": "^4.20251008.0",
56
- "hono": "^4.10.1"
55
+ "@cloudflare/workers-types": "^4.20260329.1",
56
+ "hono": "^4.12.9"
57
57
  },
58
58
  "engines": {
59
59
  "node": ">=18.0.0"
@@ -62,9 +62,9 @@
62
62
  "access": "public"
63
63
  },
64
64
  "devDependencies": {
65
- "@hono/node-server": "^1.19.5",
66
- "@hono/zod-validator": "^0.7.4",
67
- "bun-types": "^1.3.0",
68
- "zod": "^4.1.12"
65
+ "@hono/node-server": "^1.19.11",
66
+ "@hono/zod-validator": "^0.7.6",
67
+ "bun-types": "^1.3.11",
68
+ "zod": "^4.3.6"
69
69
  }
70
70
  }
@@ -33,14 +33,49 @@ type HasPathParams<T extends string> = T extends `${string}:${string}`
33
33
  ? true
34
34
  : false;
35
35
 
36
+ /**
37
+ * Values allowed in the optional `query` object on fetcher requests.
38
+ * `null` and `undefined` entries are omitted from the serialized query string.
39
+ */
40
+ export type HonoFetcherQueryParamValue = string | number | boolean;
41
+
42
+ export type HonoFetcherQueryParams = Record<
43
+ string,
44
+ HonoFetcherQueryParamValue | null | undefined
45
+ >;
46
+
47
+ function appendQueryString(
48
+ url: string,
49
+ query?: HonoFetcherQueryParams,
50
+ ): string {
51
+ if (!query) {
52
+ return url;
53
+ }
54
+ const searchParams = new URLSearchParams();
55
+ for (const [key, value] of Object.entries(query)) {
56
+ if (value === undefined || value === null) {
57
+ continue;
58
+ }
59
+ searchParams.append(key, String(value));
60
+ }
61
+ const serialized = searchParams.toString();
62
+ if (!serialized) {
63
+ return url;
64
+ }
65
+ const separator = url.includes("?") ? "&" : "?";
66
+ return `${url}${separator}${serialized}`;
67
+ }
68
+
36
69
  type FetcherParams<SchemaPath extends string> =
37
70
  HasPathParams<SchemaPath> extends true
38
71
  ? {
39
72
  params: ParsePathParams<SchemaPath>;
73
+ query?: HonoFetcherQueryParams;
40
74
  init?: RequestInit;
41
75
  }
42
76
  : {
43
77
  params?: never;
78
+ query?: HonoFetcherQueryParams;
44
79
  init?: RequestInit;
45
80
  };
46
81
 
@@ -136,7 +171,7 @@ const createMethodFetcher = <T extends Hono, M extends HttpMethod>(
136
171
  return (async (request) => {
137
172
  let finalUrl: string = request.url;
138
173
 
139
- const { init = {}, params } = request;
174
+ const { init = {}, params, query } = request;
140
175
 
141
176
  if (params && typeof params === "object") {
142
177
  finalUrl = Object.entries(params).reduce((acc, [key, value]) => {
@@ -144,6 +179,8 @@ const createMethodFetcher = <T extends Hono, M extends HttpMethod>(
144
179
  }, finalUrl);
145
180
  }
146
181
 
182
+ finalUrl = appendQueryString(finalUrl, query);
183
+
147
184
  const requestAsOptionalFormBody = request as {
148
185
  form?: unknown;
149
186
  body?: unknown;
@@ -193,7 +230,7 @@ const createWebSocketFetcher = <T extends Hono>(
193
230
  return (async (request) => {
194
231
  let finalUrl: string = request.url;
195
232
 
196
- const { init = {}, params, config } = request;
233
+ const { init = {}, params, query, config } = request;
197
234
  const autoAccept = config?.autoAccept ?? true; // Default to true
198
235
 
199
236
  if (params && typeof params === "object") {
@@ -202,6 +239,8 @@ const createWebSocketFetcher = <T extends Hono>(
202
239
  }, finalUrl);
203
240
  }
204
241
 
242
+ finalUrl = appendQueryString(finalUrl, query);
243
+
205
244
  const newHeaders = new Headers(
206
245
  init.headers as unknown as ConstructorParameters<typeof Headers>[0],
207
246
  );
package/src/index.ts CHANGED
@@ -14,6 +14,8 @@ export {
14
14
  // Core fetcher functionality
15
15
  export {
16
16
  type BaseTypedHonoFetcher,
17
+ type HonoFetcherQueryParamValue,
18
+ type HonoFetcherQueryParams,
17
19
  type HonoSchemaKeys,
18
20
  type HttpMethod,
19
21
  honoFetcher,