@hypequery/react 0.2.0 → 0.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
@@ -81,9 +81,12 @@ function RevenuePanel() {
81
81
 
82
82
  ```tsx
83
83
  import { createAnalyticsHooks } from '@hypequery/react';
84
- import type { AnalyticsApi } from '../server/api.js';
84
+ import type { InferApiType } from '@hypequery/serve';
85
+ import type { api } from '../server/api.js';
86
+
87
+ import manifest from './hypequery-manifest.json';
85
88
 
86
- import { manifest } from '../server/api.js'; // serve api.manifest(), serialized
89
+ type AnalyticsApi = InferApiType<typeof api>;
87
90
 
88
91
  export const { useMetric, useDataset } = createAnalyticsHooks<AnalyticsApi>({
89
92
  baseUrl: '/api/analytics',
@@ -177,23 +180,17 @@ const { useQuery } = createHooks<AnalyticsApi>({
177
180
  #### Generating the manifest at build time
178
181
 
179
182
  The cleanest way to keep server code out of the browser bundle is to generate a
180
- JSON file at build time and import that on the client. `api.manifest()` is pure —
181
- it reads the configured routes and never touches your database — so this step is
182
- cheap and safe to run in CI.
183
-
184
- ```ts
185
- // scripts/gen-manifest.ts — run before your client build
186
- import { writeFileSync } from 'node:fs';
187
- import { api } from '../server/api.js';
183
+ JSON file at build time and import that on the client.
188
184
 
189
- writeFileSync('src/generated/manifest.json', JSON.stringify(api.manifest(), null, 2));
185
+ ```bash
186
+ npx hypequery generate:manifest analytics/api.ts --output src/generated/hypequery-manifest.json
190
187
  ```
191
188
 
192
189
  ```jsonc
193
190
  // package.json
194
191
  {
195
192
  "scripts": {
196
- "gen:manifest": "tsx scripts/gen-manifest.ts",
193
+ "gen:manifest": "hypequery generate:manifest analytics/api.ts --output src/generated/hypequery-manifest.json",
197
194
  "build": "npm run gen:manifest && <your client build>"
198
195
  }
199
196
  }
@@ -201,9 +198,14 @@ writeFileSync('src/generated/manifest.json', JSON.stringify(api.manifest(), null
201
198
 
202
199
  ```ts
203
200
  // client side — imports plain JSON, no server code in the bundle
204
- import manifest from './generated/manifest.json';
201
+ import { createAnalyticsHooks } from '@hypequery/react';
202
+ import type { InferApiType } from '@hypequery/serve';
203
+ import type { api } from '../analytics/api.js';
204
+ import manifest from './generated/hypequery-manifest.json';
205
205
 
206
- const { useQuery } = createHooks<AnalyticsApi>({
206
+ type AnalyticsApi = InferApiType<typeof api>;
207
+
208
+ const { useMetric, useDataset } = createAnalyticsHooks<AnalyticsApi>({
207
209
  baseUrl: '/api/analytics',
208
210
  manifest,
209
211
  });
@@ -1,17 +1,13 @@
1
- import type { UseQueryOptions as TanstackUseQueryOptions, UseQueryResult, UseInfiniteQueryResult, InfiniteData } from '@tanstack/react-query';
1
+ import type { UseQueryOptions as TanstackUseQueryOptions, UseQueryResult, UseInfiniteQueryOptions as TanstackUseInfiniteQueryOptions, UseInfiniteQueryResult, InfiniteData } from '@tanstack/react-query';
2
2
  import { type CreateHooksConfig } from './createHooks.js';
3
3
  import { HttpError } from './errors.js';
4
- import type { ExtractNames, QueryInput, QueryOutput } from './types.js';
4
+ import type { ExtractNames, QueryInput, QueryOutput, QueryOutputForInput } from './types.js';
5
5
  type DatasetKey<Name extends string> = `dataset:${Name}`;
6
6
  type DatasetNamesFromApi<Api> = ExtractNames<Api> extends infer Key ? Key extends `dataset:${infer Name}` ? Name : never : never;
7
7
  type QueryKey<Name extends string, Input> = Input extends never ? ['hypequery', Name] : ['hypequery', Name, Input];
8
8
  type QueryOptions<Api, Key extends ExtractNames<Api>> = Omit<TanstackUseQueryOptions<QueryOutput<Api, Key>, HttpError, QueryOutput<Api, Key>, QueryKey<Key, QueryInput<Api, Key>>>, 'queryKey' | 'queryFn'>;
9
- type MetricQueryParams<Api, Key extends ExtractNames<Api>> = QueryInput<Api, Key> extends never ? [name: Key, options?: QueryOptions<Api, Key>] : [name: Key, input: QueryInput<Api, Key>, options?: QueryOptions<Api, Key>];
10
- type DatasetQueryParams<Api, Name extends DatasetNamesFromApi<Api>> = QueryInput<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>> extends never ? [name: Name, options?: QueryOptions<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>>] : [
11
- name: Name,
12
- input: QueryInput<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>>,
13
- options?: QueryOptions<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>>
14
- ];
9
+ /** Infinite-query options parameterized by the projected page type. */
10
+ type InfiniteQueryOptions<Api, Key extends ExtractNames<Api>, TPage> = Omit<TanstackUseInfiniteQueryOptions<TPage, HttpError, InfiniteData<TPage, number>, QueryKey<Key, QueryInput<Api, Key>>, number>, 'queryKey' | 'queryFn' | 'getNextPageParam' | 'initialPageParam'>;
15
11
  export interface CreateAnalyticsHooksConfig<Api extends Record<string, {
16
12
  input: any;
17
13
  output: any;
@@ -21,14 +17,20 @@ export interface CreateAnalyticsHooksConfig<Api extends Record<string, {
21
17
  export declare function createAnalyticsHooks<Api extends Record<string, {
22
18
  input: any;
23
19
  output: any;
24
- }>, const TMetrics extends readonly Exclude<ExtractNames<Api>, `dataset:${string}`>[] = readonly Exclude<ExtractNames<Api>, `dataset:${string}`>[]>(config: CreateAnalyticsHooksConfig<Api, TMetrics>): {
25
- readonly useMetric: <Name extends TMetrics extends readonly (infer U)[] ? U extends string ? U : never : Exclude<ExtractNames<Api>, `dataset:${string}`>>(...args: MetricQueryParams<Api, Name>) => UseQueryResult<QueryOutput<Api, Name>, HttpError>;
26
- readonly useDataset: <Name extends DatasetNamesFromApi<Api>>(...args: DatasetQueryParams<Api, Name>) => UseQueryResult<QueryOutput<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>>, HttpError>;
27
- readonly useInfiniteMetric: <Name extends TMetrics extends readonly (infer U)[] ? U extends string ? U : never : Exclude<ExtractNames<Api>, `dataset:${string}`>>(name: Name, input: QueryInput<Api, Name>, options?: Parameters<(<Name_1 extends Extract<keyof Api, string>>(name: Name_1, input: QueryInput<Api, Name_1>, options?: Omit<import("@tanstack/react-query").UseInfiniteQueryOptions<QueryOutput<Api, Name_1>, HttpError, InfiniteData<QueryOutput<Api, Name_1>, number>, QueryInput<Api, Name_1> extends never ? ["hypequery", Name_1] : ["hypequery", Name_1, QueryInput<Api, Name_1>], number>, "queryKey" | "queryFn" | "getNextPageParam" | "initialPageParam"> | undefined) => UseInfiniteQueryResult<InfiniteData<QueryOutput<Api, Name_1>, number>, HttpError>)>[2]) => UseInfiniteQueryResult<InfiniteData<QueryOutput<Api, Name>, number>, HttpError>;
28
- readonly useInfiniteDataset: <Name extends DatasetNamesFromApi<Api>>(name: Name, input: QueryInput<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>>, options?: Parameters<(<Name_1 extends Extract<keyof Api, string>>(name: Name_1, input: QueryInput<Api, Name_1>, options?: Omit<import("@tanstack/react-query").UseInfiniteQueryOptions<QueryOutput<Api, Name_1>, HttpError, InfiniteData<QueryOutput<Api, Name_1>, number>, QueryInput<Api, Name_1> extends never ? ["hypequery", Name_1] : ["hypequery", Name_1, QueryInput<Api, Name_1>], number>, "queryKey" | "queryFn" | "getNextPageParam" | "initialPageParam"> | undefined) => UseInfiniteQueryResult<InfiniteData<QueryOutput<Api, Name_1>, number>, HttpError>)>[2]) => UseInfiniteQueryResult<InfiniteData<QueryOutput<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>>, number>, HttpError>;
29
- readonly useQuery: <Name extends Extract<keyof Api, string>>(...args: QueryInput<Api, Name> extends never ? [name: Name, options?: Omit<TanstackUseQueryOptions<QueryOutput<Api, Name>, HttpError, QueryOutput<Api, Name>, QueryInput<Api, Name> extends never ? ["hypequery", Name] : ["hypequery", Name, QueryInput<Api, Name>]>, "queryKey" | "queryFn"> | undefined] : [name: Name, input: QueryInput<Api, Name>, options?: Omit<TanstackUseQueryOptions<QueryOutput<Api, Name>, HttpError, QueryOutput<Api, Name>, QueryInput<Api, Name> extends never ? ["hypequery", Name] : ["hypequery", Name, QueryInput<Api, Name>]>, "queryKey" | "queryFn"> | undefined]) => UseQueryResult<QueryOutput<Api, Name>, HttpError>;
30
- readonly useMutation: <Name extends Extract<keyof Api, string>>(name: Name, options?: Omit<import("@tanstack/react-query").UseMutationOptions<QueryOutput<Api, Name>, HttpError, QueryInput<Api, Name>, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<QueryOutput<Api, Name>, HttpError, QueryInput<Api, Name>>;
31
- readonly useInfiniteQuery: <Name extends Extract<keyof Api, string>>(name: Name, input: QueryInput<Api, Name>, options?: Omit<import("@tanstack/react-query").UseInfiniteQueryOptions<QueryOutput<Api, Name>, HttpError, InfiniteData<QueryOutput<Api, Name>, number>, QueryInput<Api, Name> extends never ? ["hypequery", Name] : ["hypequery", Name, QueryInput<Api, Name>], number>, "queryKey" | "queryFn" | "getNextPageParam" | "initialPageParam"> | undefined) => UseInfiniteQueryResult<InfiniteData<QueryOutput<Api, Name>, number>, HttpError>;
20
+ }>, TMetrics extends readonly Exclude<ExtractNames<Api>, `dataset:${string}`>[] = readonly Exclude<ExtractNames<Api>, `dataset:${string}`>[]>(config: CreateAnalyticsHooksConfig<Api, TMetrics>): {
21
+ readonly useMetric: {
22
+ <Name extends TMetrics extends readonly (infer U)[] ? U extends string ? U : never : Exclude<ExtractNames<Api>, `dataset:${string}`>>(...args: QueryInput<Api, Name> extends never ? [name: Name, options?: QueryOptions<Api, Name>] : never): UseQueryResult<QueryOutput<Api, Name>, HttpError>;
23
+ <Name extends TMetrics extends readonly (infer U)[] ? U extends string ? U : never : Exclude<ExtractNames<Api>, `dataset:${string}`>, const TInput extends QueryInput<Api, Name>>(name: Name, input: TInput, options?: QueryOptions<Api, Name>): UseQueryResult<QueryOutputForInput<Api, Name, TInput>, HttpError>;
24
+ };
25
+ readonly useDataset: {
26
+ <Name extends DatasetNamesFromApi<Api>>(...args: QueryInput<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>> extends never ? [name: Name, options?: QueryOptions<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>>] : never): UseQueryResult<QueryOutput<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>>, HttpError>;
27
+ <Name extends DatasetNamesFromApi<Api>, const TInput extends QueryInput<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>>>(name: Name, input: TInput, options?: QueryOptions<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>>): UseQueryResult<QueryOutputForInput<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>, TInput>, HttpError>;
28
+ };
29
+ readonly useInfiniteMetric: <Name extends TMetrics extends readonly (infer U)[] ? U extends string ? U : never : Exclude<ExtractNames<Api>, `dataset:${string}`>, const TInput extends QueryInput<Api, Name>>(name: Name, input: TInput, options?: InfiniteQueryOptions<Api, Name, QueryOutputForInput<Api, Name, TInput>>) => UseInfiniteQueryResult<InfiniteData<QueryOutputForInput<Api, Name, TInput>, number>, HttpError>;
30
+ readonly useInfiniteDataset: <Name extends DatasetNamesFromApi<Api>, const TInput extends QueryInput<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>>>(name: Name, input: TInput, options?: InfiniteQueryOptions<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>, QueryOutputForInput<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>, TInput>>) => UseInfiniteQueryResult<InfiniteData<QueryOutputForInput<Api, Extract<ExtractNames<Api>, DatasetKey<Name>>, TInput>, number>, HttpError>;
31
+ readonly useQuery: <Name extends ExtractNames<Api>>(...args: QueryInput<Api, Name> extends never ? [name: Name, options?: Omit<TanstackUseQueryOptions<QueryOutput<Api, Name>, HttpError, QueryOutput<Api, Name>, QueryInput<Api, Name> extends never ? ["hypequery", Name] : ["hypequery", Name, QueryInput<Api, Name>]>, "queryKey" | "queryFn"> | undefined] : [name: Name, input: QueryInput<Api, Name>, options?: Omit<TanstackUseQueryOptions<QueryOutput<Api, Name>, HttpError, QueryOutput<Api, Name>, QueryInput<Api, Name> extends never ? ["hypequery", Name] : ["hypequery", Name, QueryInput<Api, Name>]>, "queryKey" | "queryFn"> | undefined]) => UseQueryResult<QueryOutput<Api, Name>, HttpError>;
32
+ readonly useMutation: <Name extends ExtractNames<Api>>(name: Name, options?: Omit<import("@tanstack/react-query").UseMutationOptions<QueryOutput<Api, Name>, HttpError, QueryInput<Api, Name>, unknown>, "mutationFn"> | undefined) => import("@tanstack/react-query").UseMutationResult<QueryOutput<Api, Name>, HttpError, QueryInput<Api, Name>>;
33
+ readonly useInfiniteQuery: <Name extends ExtractNames<Api>>(name: Name, input: QueryInput<Api, Name>, options?: Omit<TanstackUseInfiniteQueryOptions<QueryOutput<Api, Name>, HttpError, InfiniteData<QueryOutput<Api, Name>, number>, QueryInput<Api, Name> extends never ? ["hypequery", Name] : ["hypequery", Name, QueryInput<Api, Name>], number>, "queryKey" | "queryFn" | "getNextPageParam" | "initialPageParam"> | undefined) => UseInfiniteQueryResult<InfiniteData<QueryOutput<Api, Name>, number>, HttpError>;
32
34
  };
33
35
  export {};
34
36
  //# sourceMappingURL=analyticsHooks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"analyticsHooks.d.ts","sourceRoot":"","sources":["../src/analyticsHooks.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,IAAI,uBAAuB,EAC1C,cAAc,EACd,sBAAsB,EACtB,YAAY,EACb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAExE,KAAK,UAAU,CAAC,IAAI,SAAS,MAAM,IAAI,WAAW,IAAI,EAAE,CAAC;AACzD,KAAK,mBAAmB,CAAC,GAAG,IAC1B,YAAY,CAAC,GAAG,CAAC,SAAS,MAAM,GAAG,GAC/B,GAAG,SAAS,WAAW,MAAM,IAAI,EAAE,GACjC,IAAI,GACJ,KAAK,GACP,KAAK,CAAC;AAEZ,KAAK,QAAQ,CAAC,IAAI,SAAS,MAAM,EAAE,KAAK,IAAI,KAAK,SAAS,KAAK,GAC3D,CAAC,WAAW,EAAE,IAAI,CAAC,GACnB,CAAC,WAAW,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;AAE/B,KAAK,YAAY,CAAC,GAAG,EAAE,GAAG,SAAS,YAAY,CAAC,GAAG,CAAC,IAAI,IAAI,CAC1D,uBAAuB,CACrB,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,EACrB,SAAS,EACT,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,EACrB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CACpC,EACD,UAAU,GAAG,SAAS,CACvB,CAAC;AAEF,KAAK,iBAAiB,CAAC,GAAG,EAAE,GAAG,SAAS,YAAY,CAAC,GAAG,CAAC,IACvD,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,KAAK,GAC9B,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAC7C,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAEjF,KAAK,kBAAkB,CAAC,GAAG,EAAE,IAAI,SAAS,mBAAmB,CAAC,GAAG,CAAC,IAChE,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,KAAK,GACvE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GACvF;IACE,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACpE,OAAO,CAAC,EAAE,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;CAC1E,CAAC;AAER,MAAM,WAAW,0BAA0B,CACzC,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,GAAG,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,CAAC,EACvD,QAAQ,SAAS,SAAS,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,WAAW,MAAM,EAAE,CAAC,EAAE,GAAG,SAAS,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,WAAW,MAAM,EAAE,CAAC,EAAE,CACxI,SAAQ,iBAAiB,CAAC,GAAG,CAAC;IAC9B,OAAO,CAAC,EAAE,QAAQ,CAAC;CACpB;AAED,wBAAgB,oBAAoB,CAClC,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,GAAG,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,CAAC,EACvD,KAAK,CAAC,QAAQ,SAAS,SAAS,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,WAAW,MAAM,EAAE,CAAC,EAAE,GAAG,SAAS,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,WAAW,MAAM,EAAE,CAAC,EAAE,EAC9I,MAAM,EAAE,0BAA0B,CAAC,GAAG,EAAE,QAAQ,CAAC;yBAQ9B,IAAI,0CAN4B,CAAC,+FAOzC,iBAAiB,CAAC,GAAG,EAAE,IAAI,CAAC,KACpC,cAAc,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,SAAS,CAAC;0BAKhC,IAAI,SAAS,mBAAmB,CAAC,GAAG,CAAC,WAC9C,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,KACrC,cAAc,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;iCAMjE,IAAI,0CArBoB,CAAC,4FAsB5C,IAAI,SACH,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,YAClB,UAAU,shBAA+B,CAAC,CAAC,CAAC,KACrD,sBAAsB,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,EAAE,SAAS,CAAC;kCAItD,IAAI,SAAS,mBAAmB,CAAC,GAAG,CAAC,QACzD,IAAI,SACH,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,YAC1D,UAAU,shBAA+B,CAAC,CAAC,CAAC,KACrD,sBAAsB,CACvB,YAAY,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EACpF,SAAS,CACV;;;;EAYF"}
1
+ {"version":3,"file":"analyticsHooks.d.ts","sourceRoot":"","sources":["../src/analyticsHooks.tsx"],"names":[],"mappings":"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"}
@@ -531,7 +531,7 @@ describe('createHooks', () => {
531
531
  expect(fetchMock).toHaveBeenCalled();
532
532
  fetchMock.mockClear();
533
533
  // Options object should disable the query
534
- const { result: result2 } = renderHook(() => useQuery('noInput', { enabled: false, staleTime: 1000 }), { wrapper: createWrapper() });
534
+ renderHook(() => useQuery('noInput', { enabled: false, staleTime: 1000 }), { wrapper: createWrapper() });
535
535
  expect(fetchMock).not.toHaveBeenCalled();
536
536
  });
537
537
  it('uses queryOptions() helper for explicit option marking', async () => {
package/dist/types.d.ts CHANGED
@@ -1,9 +1,62 @@
1
1
  export type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
2
- export type ExtractNames<Api> = Extract<keyof Api, string>;
2
+ export type KnownStringKeys<T> = {
3
+ [K in keyof T]: string extends K ? never : K extends string ? K : never;
4
+ }[keyof T];
5
+ export type ExtractNames<Api> = [KnownStringKeys<Api>] extends [never] ? Extract<keyof Api, string> : KnownStringKeys<Api>;
3
6
  export type QueryInput<Api, Name extends ExtractNames<Api>> = Api[Name] extends {
4
7
  input: infer Input;
5
8
  } ? Input : never;
6
9
  export type QueryOutput<Api, Name extends ExtractNames<Api>> = Api[Name] extends {
7
10
  output: infer Output;
8
11
  } ? Output : never;
12
+ type SemanticInfo<Api, Name extends ExtractNames<Api>> = Api[Name] extends {
13
+ readonly __hypequerySemantic?: infer Info;
14
+ } ? NonNullable<Info> : never;
15
+ type DimensionValue<TDefinition> = TDefinition extends {
16
+ fieldType: 'string';
17
+ } ? string : TDefinition extends {
18
+ fieldType: 'number';
19
+ } ? number : TDefinition extends {
20
+ fieldType: 'boolean';
21
+ } ? boolean : TDefinition extends {
22
+ fieldType: 'timestamp';
23
+ } ? string : unknown;
24
+ type SelectedDimensions<TDimensions, TInput> = TInput extends {
25
+ dimensions: readonly (infer TName)[];
26
+ } ? Extract<TName, KnownStringKeys<TDimensions>> : never;
27
+ type SelectedMeasures<TMeasures, TInput> = TInput extends {
28
+ measures: readonly (infer TName)[];
29
+ } ? Extract<TName, KnownStringKeys<TMeasures>> : KnownStringKeys<TMeasures>;
30
+ type PeriodSelection<TInput> = TInput extends {
31
+ by: string;
32
+ } ? {
33
+ period?: string;
34
+ } : {};
35
+ type WithTypedData<TOutput, TRow> = Omit<TOutput, 'data'> & {
36
+ data: TRow[];
37
+ };
38
+ type DatasetOutputForInput<TInfo, TInput, TFallback> = TInfo extends {
39
+ kind: 'dataset';
40
+ dimensions: infer TDimensions;
41
+ measures: infer TMeasures;
42
+ } ? WithTypedData<TFallback, {
43
+ [K in SelectedDimensions<TDimensions, TInput>]?: DimensionValue<TDimensions[K]>;
44
+ } & {
45
+ [K in SelectedMeasures<TMeasures, TInput>]?: number;
46
+ } & PeriodSelection<TInput>> : TFallback;
47
+ type MetricOutputForInput<TInfo, TInput, TFallback> = TInfo extends {
48
+ kind: 'metric';
49
+ dimensions: infer TDimensions;
50
+ metricName: infer TMetricName extends string;
51
+ } ? WithTypedData<TFallback, {
52
+ [K in SelectedDimensions<TDimensions, TInput>]?: DimensionValue<TDimensions[K]>;
53
+ } & {
54
+ [K in TMetricName]?: number;
55
+ } & PeriodSelection<TInput>> : TFallback;
56
+ export type QueryOutputForInput<Api, Name extends ExtractNames<Api>, TInput> = SemanticInfo<Api, Name> extends infer Info ? Info extends {
57
+ kind: 'dataset';
58
+ } ? DatasetOutputForInput<Info, TInput, QueryOutput<Api, Name>> : Info extends {
59
+ kind: 'metric';
60
+ } ? MetricOutputForInput<Info, TInput, QueryOutput<Api, Name>> : QueryOutput<Api, Name> : QueryOutput<Api, Name>;
61
+ export {};
9
62
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAErE,MAAM,MAAM,YAAY,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,MAAM,CAAC,CAAC;AAE3D,MAAM,MAAM,UAAU,CACpB,GAAG,EACH,IAAI,SAAS,YAAY,CAAC,GAAG,CAAC,IAC5B,GAAG,CAAC,IAAI,CAAC,SAAS;IAAE,KAAK,EAAE,MAAM,KAAK,CAAA;CAAE,GAAG,KAAK,GAAG,KAAK,CAAC;AAE7D,MAAM,MAAM,WAAW,CACrB,GAAG,EACH,IAAI,SAAS,YAAY,CAAC,GAAG,CAAC,IAC5B,GAAG,CAAC,IAAI,CAAC,SAAS;IAAE,MAAM,EAAE,MAAM,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,KAAK,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypequery/react",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "React hooks for consuming hypequery APIs",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -24,12 +24,14 @@
24
24
  "@testing-library/react": "^14.2.1",
25
25
  "@types/react": "^18.2.43",
26
26
  "@types/react-dom": "^18.2.18",
27
- "@vitest/coverage-v8": "^2.1.6",
27
+ "@vitest/coverage-v8": "^3.2.6",
28
28
  "jsdom": "^27.4.0",
29
29
  "react": "^18.2.0",
30
30
  "react-dom": "^18.2.0",
31
31
  "typescript": "^5.7.3",
32
- "vitest": "^2.1.6"
32
+ "vitest": "^3.2.6",
33
+ "@hypequery/datasets": "0.0.0-canary-20260703190705",
34
+ "@hypequery/serve": "0.0.0-canary-20260703190705"
33
35
  },
34
36
  "publishConfig": {
35
37
  "access": "public"
@@ -38,6 +40,7 @@
38
40
  "build": "tsc -b --force && node scripts/verify-dist.js",
39
41
  "types": "tsc -b --noEmit",
40
42
  "test:types": "tsc --project tsconfig.type-tests.json",
41
- "test": "npm run test:types && vitest run"
43
+ "test": "npm run test:types && vitest run",
44
+ "lint": "eslint --ext .ts,.tsx \"src/**/*.ts\" \"src/**/*.tsx\""
42
45
  }
43
46
  }