@squonk/account-server-client 4.4.0-4-4.2197467763 → 4.4.0-4-4.2200269934
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/dist/api/actions/actions.cjs +4 -4
- package/dist/api/actions/actions.cjs.map +1 -1
- package/dist/api/actions/actions.d.cts +35 -17
- package/dist/api/actions/actions.d.cts.map +1 -1
- package/dist/api/actions/actions.d.ts +35 -17
- package/dist/api/actions/actions.d.ts.map +1 -1
- package/dist/api/actions/actions.fetch.cjs +4 -4
- package/dist/api/actions/actions.fetch.cjs.map +1 -1
- package/dist/api/actions/actions.fetch.d.cts +35 -17
- package/dist/api/actions/actions.fetch.d.cts.map +1 -1
- package/dist/api/actions/actions.fetch.d.ts +35 -17
- package/dist/api/actions/actions.fetch.d.ts.map +1 -1
- package/dist/api/actions/actions.fetch.js +4 -4
- package/dist/api/actions/actions.fetch.js.map +1 -1
- package/dist/api/actions/actions.js +4 -4
- package/dist/api/actions/actions.js.map +1 -1
- package/dist/api/asset/asset.cjs +22 -22
- package/dist/api/asset/asset.cjs.map +1 -1
- package/dist/api/asset/asset.d.cts +76 -40
- package/dist/api/asset/asset.d.cts.map +1 -1
- package/dist/api/asset/asset.d.ts +76 -40
- package/dist/api/asset/asset.d.ts.map +1 -1
- package/dist/api/asset/asset.fetch.cjs +22 -22
- package/dist/api/asset/asset.fetch.cjs.map +1 -1
- package/dist/api/asset/asset.fetch.d.cts +76 -40
- package/dist/api/asset/asset.fetch.d.cts.map +1 -1
- package/dist/api/asset/asset.fetch.d.ts +76 -40
- package/dist/api/asset/asset.fetch.d.ts.map +1 -1
- package/dist/api/asset/asset.fetch.js +22 -22
- package/dist/api/asset/asset.fetch.js.map +1 -1
- package/dist/api/asset/asset.js +22 -22
- package/dist/api/asset/asset.js.map +1 -1
- package/dist/api/charges/charges.cjs +16 -16
- package/dist/api/charges/charges.cjs.map +1 -1
- package/dist/api/charges/charges.d.cts +137 -65
- package/dist/api/charges/charges.d.cts.map +1 -1
- package/dist/api/charges/charges.d.ts +137 -65
- package/dist/api/charges/charges.d.ts.map +1 -1
- package/dist/api/charges/charges.fetch.cjs +16 -16
- package/dist/api/charges/charges.fetch.cjs.map +1 -1
- package/dist/api/charges/charges.fetch.d.cts +137 -65
- package/dist/api/charges/charges.fetch.d.cts.map +1 -1
- package/dist/api/charges/charges.fetch.d.ts +137 -65
- package/dist/api/charges/charges.fetch.d.ts.map +1 -1
- package/dist/api/charges/charges.fetch.js +16 -16
- package/dist/api/charges/charges.fetch.js.map +1 -1
- package/dist/api/charges/charges.js +16 -16
- package/dist/api/charges/charges.js.map +1 -1
- package/dist/api/event-stream/event-stream.cjs +12 -12
- package/dist/api/event-stream/event-stream.cjs.map +1 -1
- package/dist/api/event-stream/event-stream.d.cts +71 -35
- package/dist/api/event-stream/event-stream.d.cts.map +1 -1
- package/dist/api/event-stream/event-stream.d.ts +71 -35
- package/dist/api/event-stream/event-stream.d.ts.map +1 -1
- package/dist/api/event-stream/event-stream.fetch.cjs +12 -12
- package/dist/api/event-stream/event-stream.fetch.cjs.map +1 -1
- package/dist/api/event-stream/event-stream.fetch.d.cts +71 -35
- package/dist/api/event-stream/event-stream.fetch.d.cts.map +1 -1
- package/dist/api/event-stream/event-stream.fetch.d.ts +71 -35
- package/dist/api/event-stream/event-stream.fetch.d.ts.map +1 -1
- package/dist/api/event-stream/event-stream.fetch.js +12 -12
- package/dist/api/event-stream/event-stream.fetch.js.map +1 -1
- package/dist/api/event-stream/event-stream.js +12 -12
- package/dist/api/event-stream/event-stream.js.map +1 -1
- package/dist/api/merchant/merchant.cjs +8 -8
- package/dist/api/merchant/merchant.cjs.map +1 -1
- package/dist/api/merchant/merchant.d.cts +69 -33
- package/dist/api/merchant/merchant.d.cts.map +1 -1
- package/dist/api/merchant/merchant.d.ts +69 -33
- package/dist/api/merchant/merchant.d.ts.map +1 -1
- package/dist/api/merchant/merchant.fetch.cjs +8 -8
- package/dist/api/merchant/merchant.fetch.cjs.map +1 -1
- package/dist/api/merchant/merchant.fetch.d.cts +69 -33
- package/dist/api/merchant/merchant.fetch.d.cts.map +1 -1
- package/dist/api/merchant/merchant.fetch.d.ts +69 -33
- package/dist/api/merchant/merchant.fetch.d.ts.map +1 -1
- package/dist/api/merchant/merchant.fetch.js +8 -8
- package/dist/api/merchant/merchant.fetch.js.map +1 -1
- package/dist/api/merchant/merchant.js +8 -8
- package/dist/api/merchant/merchant.js.map +1 -1
- package/dist/api/organisation/organisation.cjs +18 -18
- package/dist/api/organisation/organisation.cjs.map +1 -1
- package/dist/api/organisation/organisation.d.cts +106 -52
- package/dist/api/organisation/organisation.d.cts.map +1 -1
- package/dist/api/organisation/organisation.d.ts +106 -52
- package/dist/api/organisation/organisation.d.ts.map +1 -1
- package/dist/api/organisation/organisation.fetch.cjs +18 -18
- package/dist/api/organisation/organisation.fetch.cjs.map +1 -1
- package/dist/api/organisation/organisation.fetch.d.cts +106 -52
- package/dist/api/organisation/organisation.fetch.d.cts.map +1 -1
- package/dist/api/organisation/organisation.fetch.d.ts +106 -52
- package/dist/api/organisation/organisation.fetch.d.ts.map +1 -1
- package/dist/api/organisation/organisation.fetch.js +18 -18
- package/dist/api/organisation/organisation.fetch.js.map +1 -1
- package/dist/api/organisation/organisation.js +18 -18
- package/dist/api/organisation/organisation.js.map +1 -1
- package/dist/api/product/product.cjs +30 -30
- package/dist/api/product/product.cjs.map +1 -1
- package/dist/api/product/product.d.cts +208 -100
- package/dist/api/product/product.d.cts.map +1 -1
- package/dist/api/product/product.d.ts +208 -100
- package/dist/api/product/product.d.ts.map +1 -1
- package/dist/api/product/product.fetch.cjs +30 -30
- package/dist/api/product/product.fetch.cjs.map +1 -1
- package/dist/api/product/product.fetch.d.cts +208 -100
- package/dist/api/product/product.fetch.d.cts.map +1 -1
- package/dist/api/product/product.fetch.d.ts +208 -100
- package/dist/api/product/product.fetch.d.ts.map +1 -1
- package/dist/api/product/product.fetch.js +30 -30
- package/dist/api/product/product.fetch.js.map +1 -1
- package/dist/api/product/product.js +30 -30
- package/dist/api/product/product.js.map +1 -1
- package/dist/api/state/state.cjs +4 -4
- package/dist/api/state/state.cjs.map +1 -1
- package/dist/api/state/state.d.cts +35 -17
- package/dist/api/state/state.d.cts.map +1 -1
- package/dist/api/state/state.d.ts +35 -17
- package/dist/api/state/state.d.ts.map +1 -1
- package/dist/api/state/state.fetch.cjs +4 -4
- package/dist/api/state/state.fetch.cjs.map +1 -1
- package/dist/api/state/state.fetch.d.cts +35 -17
- package/dist/api/state/state.fetch.d.cts.map +1 -1
- package/dist/api/state/state.fetch.d.ts +35 -17
- package/dist/api/state/state.fetch.d.ts.map +1 -1
- package/dist/api/state/state.fetch.js +4 -4
- package/dist/api/state/state.fetch.js.map +1 -1
- package/dist/api/state/state.js +4 -4
- package/dist/api/state/state.js.map +1 -1
- package/dist/api/unit/unit.cjs +30 -30
- package/dist/api/unit/unit.cjs.map +1 -1
- package/dist/api/unit/unit.d.cts +144 -72
- package/dist/api/unit/unit.d.cts.map +1 -1
- package/dist/api/unit/unit.d.ts +144 -72
- package/dist/api/unit/unit.d.ts.map +1 -1
- package/dist/api/unit/unit.fetch.cjs +30 -30
- package/dist/api/unit/unit.fetch.cjs.map +1 -1
- package/dist/api/unit/unit.fetch.d.cts +144 -72
- package/dist/api/unit/unit.fetch.d.cts.map +1 -1
- package/dist/api/unit/unit.fetch.d.ts +144 -72
- package/dist/api/unit/unit.fetch.d.ts.map +1 -1
- package/dist/api/unit/unit.fetch.js +30 -30
- package/dist/api/unit/unit.fetch.js.map +1 -1
- package/dist/api/unit/unit.js +30 -30
- package/dist/api/unit/unit.js.map +1 -1
- package/dist/api/user/user.cjs +20 -20
- package/dist/api/user/user.cjs.map +1 -1
- package/dist/api/user/user.d.cts +107 -53
- package/dist/api/user/user.d.cts.map +1 -1
- package/dist/api/user/user.d.ts +107 -53
- package/dist/api/user/user.d.ts.map +1 -1
- package/dist/api/user/user.fetch.cjs +20 -20
- package/dist/api/user/user.fetch.cjs.map +1 -1
- package/dist/api/user/user.fetch.d.cts +107 -53
- package/dist/api/user/user.fetch.d.cts.map +1 -1
- package/dist/api/user/user.fetch.d.ts +107 -53
- package/dist/api/user/user.fetch.d.ts.map +1 -1
- package/dist/api/user/user.fetch.js +20 -20
- package/dist/api/user/user.fetch.js.map +1 -1
- package/dist/api/user/user.js +20 -20
- package/dist/api/user/user.js.map +1 -1
- package/package.json +7 -5
- package/src/api/actions/actions.fetch.ts +103 -12
- package/src/api/actions/actions.ts +103 -12
- package/src/api/asset/asset.fetch.ts +303 -94
- package/src/api/asset/asset.ts +303 -94
- package/src/api/charges/charges.fetch.ts +456 -54
- package/src/api/charges/charges.ts +456 -54
- package/src/api/event-stream/event-stream.fetch.ts +262 -58
- package/src/api/event-stream/event-stream.ts +262 -58
- package/src/api/merchant/merchant.fetch.ts +212 -28
- package/src/api/merchant/merchant.ts +212 -28
- package/src/api/organisation/organisation.fetch.ts +381 -86
- package/src/api/organisation/organisation.ts +381 -86
- package/src/api/product/product.fetch.ts +724 -130
- package/src/api/product/product.ts +724 -130
- package/src/api/state/state.fetch.ts +105 -16
- package/src/api/state/state.ts +105 -16
- package/src/api/unit/unit.fetch.ts +521 -146
- package/src/api/unit/unit.ts +521 -146
- package/src/api/user/user.fetch.ts +401 -101
- package/src/api/user/user.ts +401 -101
- package/tests/README.md +98 -0
- package/tests/component.test.tsx +191 -0
- package/tests/tsconfig.json +7 -0
- package/tests/type-tests.tsx +196 -0
package/tests/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Type Safety Tests
|
|
2
|
+
|
|
3
|
+
This directory contains example type-level tests for the generated OpenAPI client to ensure type safety and correct inference.
|
|
4
|
+
|
|
5
|
+
**Note:** These tests are examples that use the Data Manager API (`openapi.yaml`). To use these tests, you'll need to:
|
|
6
|
+
|
|
7
|
+
1. Have the Data Manager OpenAPI spec as `openapi.yaml` in the project root
|
|
8
|
+
2. Generate the client with `pnpm orval`
|
|
9
|
+
3. Then run `pnpm test`
|
|
10
|
+
|
|
11
|
+
For other OpenAPI specs, use these tests as a template and adapt the imports and type names to match your generated client.
|
|
12
|
+
|
|
13
|
+
## Test Files
|
|
14
|
+
|
|
15
|
+
### `type-tests.tsx`
|
|
16
|
+
|
|
17
|
+
Pure type-level tests that verify:
|
|
18
|
+
|
|
19
|
+
- queryKey is optional in query options
|
|
20
|
+
- select callbacks properly infer types
|
|
21
|
+
- Parameter requirements are enforced
|
|
22
|
+
- Query options type checking
|
|
23
|
+
- TData generic inference with and without select
|
|
24
|
+
- Error types
|
|
25
|
+
- Request options
|
|
26
|
+
|
|
27
|
+
These tests use `@ts-expect-error` annotations to verify that invalid code is correctly rejected by TypeScript.
|
|
28
|
+
|
|
29
|
+
### `react-component-tests.tsx`
|
|
30
|
+
|
|
31
|
+
React component examples that test:
|
|
32
|
+
|
|
33
|
+
- Basic query usage in components
|
|
34
|
+
- Data transformation with select
|
|
35
|
+
- Conditional queries (enabled prop)
|
|
36
|
+
- Custom queryKeys
|
|
37
|
+
- Mutations (create, delete)
|
|
38
|
+
- Multiple queries in one component
|
|
39
|
+
- Query parameters
|
|
40
|
+
- Complex select transformations
|
|
41
|
+
- Error handling
|
|
42
|
+
- Dependent queries
|
|
43
|
+
|
|
44
|
+
## Running Tests
|
|
45
|
+
|
|
46
|
+
### Type Check Only
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Check all tests
|
|
50
|
+
pnpm run test:types
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### With Generated Client
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# 1. Ensure you have openapi.yaml with Data Manager API spec
|
|
57
|
+
# 2. Generate the client
|
|
58
|
+
pnpm orval
|
|
59
|
+
|
|
60
|
+
# 3. Run type checks
|
|
61
|
+
pnpm test
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## What These Tests Verify
|
|
65
|
+
|
|
66
|
+
1. **queryKey Optional**: Orval correctly detects React Query v5 and generates `Partial<UseQueryOptions>`, making queryKey optional
|
|
67
|
+
2. **Type Inference**: Select callbacks properly transform data types - return type inferred from select function
|
|
68
|
+
3. **Parameter Safety**: Required parameters are enforced at compile time
|
|
69
|
+
4. **React Query v5**: All v5 options available (gcTime, not cacheTime)
|
|
70
|
+
5. **Invalid Options Rejected**: TypeScript catches typos and invalid options in query configuration
|
|
71
|
+
6. **No Runtime Tests**: These are compile-time only - we trust React Query's runtime behavior
|
|
72
|
+
|
|
73
|
+
## Why This Matters
|
|
74
|
+
|
|
75
|
+
The root cause of the type issues was the peerDependency range `>=4` in package.json. This made Orval unable to definitively detect React Query v5, so it generated hooks for v4 which don't use `Partial<UseQueryOptions>`. This caused:
|
|
76
|
+
|
|
77
|
+
- queryKey to be required (React Query v5 has it as the 4th generic parameter in UseQueryOptions)
|
|
78
|
+
- select callbacks to have incorrect type inference
|
|
79
|
+
|
|
80
|
+
By setting peerDependencies to `>=5`, Orval correctly detects v5 and generates the proper types.
|
|
81
|
+
|
|
82
|
+
## Adapting These Tests
|
|
83
|
+
|
|
84
|
+
These example tests import from `../src/api/job/job` and use Data Manager API types. To use them with your OpenAPI spec:
|
|
85
|
+
|
|
86
|
+
1. Update imports to match your generated API structure (e.g., `../src/api/your-endpoint/your-endpoint`)
|
|
87
|
+
2. Replace type names with types from your spec (e.g., replace `JobsGetResponse` with your response types)
|
|
88
|
+
3. Update parameter names and structures to match your API
|
|
89
|
+
4. Keep the same test patterns - they verify the core type safety features
|
|
90
|
+
|
|
91
|
+
## Adding New Tests
|
|
92
|
+
|
|
93
|
+
When adding new tests:
|
|
94
|
+
|
|
95
|
+
1. Name test functions descriptively (e.g., `TestQueryKeyOptional`)
|
|
96
|
+
2. Use `@ts-expect-error` to verify invalid code is rejected
|
|
97
|
+
3. Add comments explaining what's being tested
|
|
98
|
+
4. Keep tests focused on type safety, not runtime behavior
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-safe React component tests
|
|
3
|
+
* Verifies type safety of using generated hooks in actual React components
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useGetJobs, useGetJob } from '../src/api/job/job';
|
|
7
|
+
import type { GetJobsParams } from '../src/api/api-schemas';
|
|
8
|
+
|
|
9
|
+
// Test 1: Basic component with query
|
|
10
|
+
export function JobListComponent() {
|
|
11
|
+
const { data, isLoading, error } = useGetJobs(undefined, {
|
|
12
|
+
query: {
|
|
13
|
+
enabled: true,
|
|
14
|
+
staleTime: 5000,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
if (isLoading) return <div>Loading...</div>;
|
|
19
|
+
if (error) return <div>Error: {JSON.stringify(error)}</div>;
|
|
20
|
+
if (!data) return null;
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<ul>
|
|
24
|
+
{data.jobs.map((job) => (
|
|
25
|
+
<li key={job.id}>{job.name}</li>
|
|
26
|
+
))}
|
|
27
|
+
</ul>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Test 2: Component with transformed data using select
|
|
32
|
+
export function JobIdsComponent() {
|
|
33
|
+
const { data: jobIds } = useGetJobs(undefined, {
|
|
34
|
+
query: {
|
|
35
|
+
select: (response) => response.jobs.map((j) => j.id),
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div>
|
|
41
|
+
{jobIds?.map((id) => (
|
|
42
|
+
<div key={id}>Job ID: {id}</div>
|
|
43
|
+
))}
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Test 3: Component with parameters
|
|
49
|
+
export function JobDetailComponent({ jobId }: { jobId: number }) {
|
|
50
|
+
const { data: job } = useGetJob(jobId, undefined, {
|
|
51
|
+
query: {
|
|
52
|
+
enabled: jobId > 0,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return <div>{job?.name}</div>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Test 4: Component with conditional query
|
|
60
|
+
export function ConditionalJobComponent({ shouldFetch, jobId }: { shouldFetch: boolean; jobId: number }) {
|
|
61
|
+
const { data, isFetching } = useGetJob(jobId, undefined, {
|
|
62
|
+
query: {
|
|
63
|
+
enabled: shouldFetch,
|
|
64
|
+
refetchOnWindowFocus: false,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (!shouldFetch) return <div>Fetch disabled</div>;
|
|
69
|
+
if (isFetching) return <div>Fetching...</div>;
|
|
70
|
+
|
|
71
|
+
return <div>{data?.name}</div>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Test 5: Component with custom queryKey
|
|
75
|
+
export function CustomQueryKeyComponent() {
|
|
76
|
+
const customKey = ['jobs', 'custom', 'key'];
|
|
77
|
+
|
|
78
|
+
const { data } = useGetJobs(undefined, {
|
|
79
|
+
query: {
|
|
80
|
+
queryKey: customKey,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
return <div>{data?.count} jobs</div>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Test 6 (mutation tests removed - job endpoints are read-only)
|
|
88
|
+
|
|
89
|
+
// Test 7: Component with multiple queries
|
|
90
|
+
export function MultipleQueriesComponent({ jobId }: { jobId: number }) {
|
|
91
|
+
const { data: jobs } = useGetJobs(undefined, {
|
|
92
|
+
query: { staleTime: 10000 },
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const { data: specificJob } = useGetJob(jobId, undefined, {
|
|
96
|
+
query: { enabled: jobId > 0 },
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<div>
|
|
101
|
+
<div>Total jobs: {jobs?.count}</div>
|
|
102
|
+
<div>Current job: {specificJob?.name}</div>
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Test 8: Component with query params
|
|
108
|
+
export function FilteredJobsComponent({ projectId }: { projectId?: string }) {
|
|
109
|
+
const params: GetJobsParams | undefined = projectId
|
|
110
|
+
? {
|
|
111
|
+
project_id: projectId,
|
|
112
|
+
}
|
|
113
|
+
: undefined;
|
|
114
|
+
|
|
115
|
+
const { data } = useGetJobs(params, {
|
|
116
|
+
query: {
|
|
117
|
+
enabled: Boolean(projectId),
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
return <div>{data?.jobs.length} filtered jobs</div>;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Test 9: Component with complex select transformation
|
|
125
|
+
export function TransformedJobDataComponent() {
|
|
126
|
+
const { data: transformedData } = useGetJobs(undefined, {
|
|
127
|
+
query: {
|
|
128
|
+
select: (response) => ({
|
|
129
|
+
totalCount: response.count,
|
|
130
|
+
jobNames: response.jobs.map((j) => j.name),
|
|
131
|
+
firstJob: response.jobs[0],
|
|
132
|
+
}),
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<div>
|
|
138
|
+
<div>Total: {transformedData?.totalCount}</div>
|
|
139
|
+
<div>Names: {transformedData?.jobNames.join(', ')}</div>
|
|
140
|
+
<div>First: {transformedData?.firstJob?.name}</div>
|
|
141
|
+
</div>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Test 10 (mutation tests removed - job endpoints are read-only)
|
|
146
|
+
|
|
147
|
+
// Test 11: Component with error handling
|
|
148
|
+
export function ErrorHandlingComponent() {
|
|
149
|
+
const { data, isLoading, isError, error, refetch } = useGetJobs(undefined, {
|
|
150
|
+
query: {
|
|
151
|
+
retry: 2,
|
|
152
|
+
retryDelay: 1000,
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
if (isLoading) {
|
|
157
|
+
return <div>Loading jobs...</div>;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (isError) {
|
|
161
|
+
return (
|
|
162
|
+
<div>
|
|
163
|
+
<div>Error occurred: {JSON.stringify(error)}</div>
|
|
164
|
+
<button onClick={() => refetch()}>Retry</button>
|
|
165
|
+
</div>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return <div>Loaded {data?.count} jobs</div>;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Test 12: Component with dependent queries
|
|
173
|
+
export function DependentQueriesComponent() {
|
|
174
|
+
const { data: jobs } = useGetJobs(undefined, {
|
|
175
|
+
query: { staleTime: 5000 },
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const firstJobId = jobs?.jobs[0]?.id;
|
|
179
|
+
|
|
180
|
+
const { data: firstJob } = useGetJob(firstJobId ?? 0, undefined, {
|
|
181
|
+
query: {
|
|
182
|
+
enabled: Boolean(firstJobId),
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
return (
|
|
187
|
+
<div>
|
|
188
|
+
{jobs && <div>First job: {firstJob?.name}</div>}
|
|
189
|
+
</div>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-level tests for the generated client
|
|
3
|
+
* These tests verify type safety and won't be executed at runtime
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useGetJobs, useGetJob, useGetJobByVersion } from "../src/api/job/job";
|
|
7
|
+
|
|
8
|
+
// Test 1: queryKey should be optional
|
|
9
|
+
function TestQueryKeyOptional() {
|
|
10
|
+
// Should compile without queryKey
|
|
11
|
+
useGetJobs(undefined, { query: { enabled: true, staleTime: 5000 } });
|
|
12
|
+
|
|
13
|
+
// Should also work with queryKey
|
|
14
|
+
useGetJobs(undefined, { query: { queryKey: ["custom", "key"], enabled: true } });
|
|
15
|
+
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Test 2: select callback should properly infer types
|
|
20
|
+
function TestSelectCallback() {
|
|
21
|
+
// Should infer that data is JobSummary[] after select
|
|
22
|
+
const { data } = useGetJobs(undefined, {
|
|
23
|
+
query: {
|
|
24
|
+
select: (data) => {
|
|
25
|
+
// data should be JobsGetResponse (verified by accessing properties)
|
|
26
|
+
data.count satisfies number;
|
|
27
|
+
data.jobs satisfies unknown[];
|
|
28
|
+
|
|
29
|
+
// Return type should be inferred from select function
|
|
30
|
+
return data.jobs;
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// data should be JobSummary[] (return type of select), not JobsGetResponse
|
|
36
|
+
if (data) {
|
|
37
|
+
// This should work because data is JobSummary[]
|
|
38
|
+
data.forEach((job) => {
|
|
39
|
+
job.id satisfies number;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// @ts-expect-error - data should NOT have count property (it's an array now)
|
|
43
|
+
const count = data.count;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Test 3: select with transformation
|
|
50
|
+
function TestSelectTransformation() {
|
|
51
|
+
const { data } = useGetJobs(undefined, {
|
|
52
|
+
query: {
|
|
53
|
+
select: (response) => {
|
|
54
|
+
// Transform to just job IDs
|
|
55
|
+
return response.jobs.map((job) => job.id);
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (data) {
|
|
61
|
+
// data should be number[]
|
|
62
|
+
data satisfies number[];
|
|
63
|
+
|
|
64
|
+
// @ts-expect-error - should not have JobSummary properties
|
|
65
|
+
const firstJob = data[0]?.name;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Test 4: Parameters with required fields
|
|
72
|
+
function TestRequiredParameters() {
|
|
73
|
+
// Should require jobId parameter
|
|
74
|
+
useGetJob(123, undefined, { query: { enabled: true } });
|
|
75
|
+
|
|
76
|
+
// @ts-expect-error - jobId is required
|
|
77
|
+
useGetJob(undefined, undefined, { query: { enabled: true } });
|
|
78
|
+
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Test 5: Parameters object with required fields
|
|
83
|
+
function TestRequiredParametersObject() {
|
|
84
|
+
// Should require params with collection, job and version
|
|
85
|
+
useGetJobByVersion(
|
|
86
|
+
{ collection: "im-test", job: "test-job", version: "1.0.0" },
|
|
87
|
+
{ query: { enabled: true } },
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// Params are all required - this would be caught without 'as any'
|
|
91
|
+
// Using 'as any' to demonstrate the type requirement exists
|
|
92
|
+
useGetJobByVersion({ collection: "im-test", version: "1.0.0" } as any, {
|
|
93
|
+
query: { enabled: true },
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Test 6: Query options type checking
|
|
100
|
+
function TestQueryOptions() {
|
|
101
|
+
useGetJobs(undefined, {
|
|
102
|
+
query: { enabled: true, staleTime: 5000, gcTime: 10000, refetchOnWindowFocus: false, retry: 3 },
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
useGetJobs(undefined, {
|
|
106
|
+
query: {
|
|
107
|
+
// @ts-expect-error - invalid option should be rejected
|
|
108
|
+
invalidOption: true,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Test 7: TData generic inference
|
|
116
|
+
function TestTDataInference() {
|
|
117
|
+
// Without select, TData = JobsGetResponse
|
|
118
|
+
const { data: data1 } = useGetJobs(undefined, { query: { enabled: true } });
|
|
119
|
+
|
|
120
|
+
if (data1) {
|
|
121
|
+
// Should have count and jobs properties
|
|
122
|
+
data1.count satisfies number;
|
|
123
|
+
data1.jobs satisfies unknown[];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// With select, TData = return type of select
|
|
127
|
+
const { data: data2 } = useGetJobs(undefined, {
|
|
128
|
+
query: { select: (d) => d.jobs, enabled: true },
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
if (data2) {
|
|
132
|
+
// Should be array, not have count property
|
|
133
|
+
data2.forEach((job) => {
|
|
134
|
+
job.id satisfies number;
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// @ts-expect-error - should not have count
|
|
138
|
+
const count = data2.count;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Test 8: Error type
|
|
145
|
+
function TestErrorType() {
|
|
146
|
+
const { error } = useGetJobs(undefined, { query: { enabled: true } });
|
|
147
|
+
|
|
148
|
+
if (error) {
|
|
149
|
+
// Error should have proper type structure (ErrorType<DmError>)
|
|
150
|
+
error satisfies unknown;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Test 9: Suspense query (if enabled)
|
|
157
|
+
// Uncomment if you have suspense queries enabled
|
|
158
|
+
// import { useGetJobsSuspense } from '../src/job/job';
|
|
159
|
+
//
|
|
160
|
+
// function TestSuspenseQuery() {
|
|
161
|
+
// const { data } = useGetJobsSuspense(undefined, {
|
|
162
|
+
// query: {
|
|
163
|
+
// select: (data) => data.jobs,
|
|
164
|
+
// },
|
|
165
|
+
// });
|
|
166
|
+
//
|
|
167
|
+
// // In suspense queries, data is never undefined
|
|
168
|
+
// const jobs = data; // Should be JobSummary[], not undefined
|
|
169
|
+
//
|
|
170
|
+
// return null;
|
|
171
|
+
// }
|
|
172
|
+
|
|
173
|
+
// Test 10: Request options
|
|
174
|
+
function TestRequestOptions() {
|
|
175
|
+
useGetJobs(undefined, {
|
|
176
|
+
query: { enabled: true },
|
|
177
|
+
request: {
|
|
178
|
+
// Request options from custom axios instance
|
|
179
|
+
headers: { "X-Custom-Header": "value" },
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export {
|
|
187
|
+
TestQueryKeyOptional,
|
|
188
|
+
TestSelectCallback,
|
|
189
|
+
TestSelectTransformation,
|
|
190
|
+
TestRequiredParameters,
|
|
191
|
+
TestRequiredParametersObject,
|
|
192
|
+
TestQueryOptions,
|
|
193
|
+
TestTDataInference,
|
|
194
|
+
TestErrorType,
|
|
195
|
+
TestRequestOptions,
|
|
196
|
+
};
|