@hypequery/react 0.0.3 → 0.1.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
@@ -63,7 +63,7 @@ Factory function that creates type-safe `useQuery` and `useMutation` hooks for y
63
63
  interface CreateHooksConfig<TApi> {
64
64
  baseUrl: string; // Required: API base URL (e.g., '/api' or 'https://api.example.com')
65
65
  fetchFn?: typeof fetch; // Optional: Custom fetch implementation (defaults to global fetch)
66
- headers?: Record<string, string>; // Optional: Default headers for all requests
66
+ headers?: Record<string, string> | (() => Record<string, string>); // Optional: Default headers or a resolver function
67
67
  config?: Record<string, QueryMethodConfig>; // Optional: Per-route HTTP method overrides
68
68
  api?: TApi; // Optional: API object to auto-extract HTTP methods
69
69
  }
@@ -10,7 +10,7 @@ export interface CreateHooksConfig<TApi = Record<string, {
10
10
  }>> {
11
11
  baseUrl: string;
12
12
  fetchFn?: typeof fetch;
13
- headers?: Record<string, string>;
13
+ headers?: Record<string, string> | (() => Record<string, string>);
14
14
  config?: Record<string, QueryMethodConfig>;
15
15
  api?: TApi;
16
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createHooks.d.ts","sourceRoot":"","sources":["../src/createHooks.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,IAAI,uBAAuB,EAC/C,KAAK,kBAAkB,IAAI,0BAA0B,EACrD,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;IAC3F,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC3C,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,QAAA,MAAM,cAAc,eAAkC,CAAC;AAEvD,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG;IAAE,CAAC,cAAc,CAAC,EAAE,IAAI,CAAA;CAAE,CAEtF;AA6DD,wBAAgB,WAAW,CAAC,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,GAAG,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,CAAC,EACjF,MAAM,EAAE,iBAAiB,CAAC,GAAG,CAAC;wBAkEZ,IAAI,SAAS,YAAY,CAAC,GAAG,CAAC,+kBAE7C,cAAc,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,SAAS,CAAC;2BAwC/B,IAAI,SAAS,YAAY,CAAC,GAAG,CAAC,QAC3C,IAAI,kIAET,iBAAiB,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;EAW/E"}
1
+ {"version":3,"file":"createHooks.d.ts","sourceRoot":"","sources":["../src/createHooks.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,IAAI,uBAAuB,EAC/C,KAAK,kBAAkB,IAAI,0BAA0B,EACrD,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;IAC3F,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC3C,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,QAAA,MAAM,cAAc,eAAkC,CAAC;AAEvD,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG;IAAE,CAAC,cAAc,CAAC,EAAE,IAAI,CAAA;CAAE,CAEtF;AA6DD,wBAAgB,WAAW,CAAC,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,GAAG,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,CAAC,EACjF,MAAM,EAAE,iBAAiB,CAAC,GAAG,CAAC;wBAmEZ,IAAI,SAAS,YAAY,CAAC,GAAG,CAAC,+kBAE7C,cAAc,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,SAAS,CAAC;2BAwC/B,IAAI,SAAS,YAAY,CAAC,GAAG,CAAC,QAC3C,IAAI,kIAET,iBAAiB,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;EAW/E"}
@@ -78,10 +78,11 @@ export function createHooks(config) {
78
78
  else if (input !== undefined) {
79
79
  body = JSON.stringify(input);
80
80
  }
81
+ const resolvedHeaders = typeof headers === 'function' ? headers() : headers;
81
82
  const res = await fetchFn(finalUrl, {
82
83
  method,
83
84
  headers: {
84
- ...headers,
85
+ ...resolvedHeaders,
85
86
  ...(body ? { 'content-type': 'application/json' } : {}),
86
87
  },
87
88
  body,
@@ -67,6 +67,32 @@ describe('createHooks', () => {
67
67
  await waitFor(() => expect(result.current.data).toEqual({ status: 'ok' }));
68
68
  expect(fetchMock).toHaveBeenCalledWith('https://example.com/api/noInput', expect.objectContaining({ method: 'GET' }));
69
69
  });
70
+ it('invokes header factory per request', async () => {
71
+ const headerFactory = vi.fn()
72
+ .mockReturnValueOnce({ 'x-token': 'first' })
73
+ .mockReturnValueOnce({ 'x-token': 'second' });
74
+ const { useQuery } = createHooks({
75
+ baseUrl: 'https://example.com/api',
76
+ fetchFn: fetchMock,
77
+ headers: headerFactory,
78
+ });
79
+ fetchMock.mockResolvedValue(mockSuccessResponse({ name: 'User' }));
80
+ const first = renderHook(() => useQuery('getUser', { id: '1' }), {
81
+ wrapper: createWrapper(),
82
+ });
83
+ await waitFor(() => {
84
+ expect(first.result.current.data).toEqual({ name: 'User' });
85
+ });
86
+ const second = renderHook(() => useQuery('getUser', { id: '2' }), {
87
+ wrapper: createWrapper(),
88
+ });
89
+ await waitFor(() => {
90
+ expect(second.result.current.data).toEqual({ name: 'User' });
91
+ });
92
+ expect(headerFactory).toHaveBeenCalledTimes(2);
93
+ expect(fetchMock.mock.calls[0][1]?.headers).toMatchObject({ 'x-token': 'first' });
94
+ expect(fetchMock.mock.calls[1][1]?.headers).toMatchObject({ 'x-token': 'second' });
95
+ });
70
96
  });
71
97
  describe('HTTP Method Handling', () => {
72
98
  const fetchMock = vi.fn();
@@ -0,0 +1,9 @@
1
+ /**
2
+ * HTTP error with status code and response body
3
+ */
4
+ export declare class HttpError extends Error {
5
+ readonly status: number;
6
+ readonly body: unknown;
7
+ constructor(message: string, status: number, body: unknown);
8
+ }
9
+ //# sourceMappingURL=errors.d.ts.map
package/dist/errors.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * HTTP error with status code and response body
3
+ */
4
+ export class HttpError extends Error {
5
+ constructor(message, status, body) {
6
+ super(message);
7
+ this.status = status;
8
+ this.body = body;
9
+ this.name = 'HttpError';
10
+ // Maintain proper prototype chain for instanceof checks
11
+ Object.setPrototypeOf(this, HttpError.prototype);
12
+ }
13
+ }
@@ -0,0 +1,5 @@
1
+ export { createHooks, queryOptions } from './createHooks.js';
2
+ export { HttpError } from './errors.js';
3
+ export type { QueryInput, QueryOutput, HttpMethod } from './types.js';
4
+ export type { CreateHooksConfig, QueryMethodConfig } from './createHooks.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,9 @@
1
+ export type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
2
+ export type ExtractNames<Api> = Extract<keyof Api, string>;
3
+ export type QueryInput<Api, Name extends ExtractNames<Api>> = Api[Name] extends {
4
+ input: infer Input;
5
+ } ? Input : never;
6
+ export type QueryOutput<Api, Name extends ExtractNames<Api>> = Api[Name] extends {
7
+ output: infer Output;
8
+ } ? Output : never;
9
+ //# sourceMappingURL=types.d.ts.map
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypequery/react",
3
- "version": "0.0.3",
3
+ "version": "0.1.0",
4
4
  "description": "React hooks for consuming hypequery APIs",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -35,7 +35,7 @@
35
35
  "access": "public"
36
36
  },
37
37
  "scripts": {
38
- "build": "tsc -b",
38
+ "build": "tsc -b --force && node scripts/verify-dist.js",
39
39
  "types": "tsc -b --noEmit",
40
40
  "test:types": "tsc --project tsconfig.type-tests.json",
41
41
  "test": "npm run test:types && vitest run"