@stiviar/modeled-react 1.0.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 +73 -0
- package/dist/index.d.mts +37 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +5150 -0
- package/dist/index.mjs +5136 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# @stiviar/react
|
|
2
|
+
|
|
3
|
+
React bindings for [stiviar](https://github.com/szlkeve/stiviar) — a declarative, type-safe API layer.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm i @stiviar/react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Define your models once:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
// api.ts
|
|
17
|
+
import { register } from "@stiviar/core";
|
|
18
|
+
import { Todos, TodosSchema, Users, UsersSchema } from "./types";
|
|
19
|
+
|
|
20
|
+
export const api = register<{
|
|
21
|
+
users: { type: Users };
|
|
22
|
+
todos: { type: Todos };
|
|
23
|
+
}>({
|
|
24
|
+
users: {
|
|
25
|
+
url: "https://api.example.com/users",
|
|
26
|
+
schema: UsersSchema,
|
|
27
|
+
},
|
|
28
|
+
todos: {
|
|
29
|
+
url: "https://api.example.com/todos",
|
|
30
|
+
schema: TodosSchema,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export const useData = api.useData;
|
|
35
|
+
export const isContractValid = api.isContractValid;
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Use it in a component:
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
// Component.tsx
|
|
42
|
+
import { useData } from "./api";
|
|
43
|
+
|
|
44
|
+
export function Component() {
|
|
45
|
+
const { data, isLoading, error } = useData("users");
|
|
46
|
+
|
|
47
|
+
if (isLoading) return <p>Loading…</p>;
|
|
48
|
+
if (error) return <p>Something went wrong.</p>;
|
|
49
|
+
|
|
50
|
+
return <div>user count: {data?.length}</div>;
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Types declared for a model flow through the whole codebase — hover `data` in your IDE and see the inferred type, with a compile-time error if your schema and type ever drift apart.
|
|
55
|
+
|
|
56
|
+
## Testing
|
|
57
|
+
|
|
58
|
+
Swap the fetch implementation at registration time so components stay testable without a network:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
export const api = register<TypeModel>(apiModel, {
|
|
62
|
+
fetchFn: IS_DEV ? mockFetch : fetch,
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## API
|
|
67
|
+
|
|
68
|
+
- `useData(key, params?)` — TanStack Query-backed fetch hook for a registered endpoint
|
|
69
|
+
- `isContractValid(openApiSchema)` — validates a live OpenAPI contract against your registered types
|
|
70
|
+
|
|
71
|
+
## License
|
|
72
|
+
|
|
73
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
2
|
+
import z from 'zod';
|
|
3
|
+
|
|
4
|
+
type BaseApiTypeMap = {
|
|
5
|
+
[stateName: string]: {
|
|
6
|
+
type: object | string | number | boolean;
|
|
7
|
+
} & ({
|
|
8
|
+
params: {
|
|
9
|
+
[param: string]: string | number;
|
|
10
|
+
};
|
|
11
|
+
} | {
|
|
12
|
+
params?: undefined;
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
type ApiModel<ApiTypeMap extends BaseApiTypeMap> = {
|
|
16
|
+
[NAME in keyof ApiTypeMap]: {
|
|
17
|
+
schema: z.ZodType<ApiTypeMap[NAME]["type"]>;
|
|
18
|
+
url: ApiTypeMap[NAME]["params"] extends object ? (params: ApiTypeMap[NAME]["params"]) => string : string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
type UseDataArgs<ApiTypeMap extends BaseApiTypeMap, NAME extends keyof ApiTypeMap> = ApiTypeMap[NAME]["params"] extends object ? [stateName: NAME, params: ApiTypeMap[NAME]["params"]] : [stateName: NAME, params?: undefined];
|
|
22
|
+
type Options = {
|
|
23
|
+
fetchFn?: (url: string) => Promise<unknown>;
|
|
24
|
+
baseUrl?: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
declare function register<ApiTypeMap extends BaseApiTypeMap>(apiModel: ApiModel<ApiTypeMap>, options?: Options): {
|
|
28
|
+
useData: <NAME extends keyof ApiTypeMap>(...args: UseDataArgs<ApiTypeMap, NAME>) => {
|
|
29
|
+
data: ApiTypeMap[NAME]["type"] | undefined;
|
|
30
|
+
isLoading: boolean;
|
|
31
|
+
error: Error | null;
|
|
32
|
+
};
|
|
33
|
+
client: QueryClient;
|
|
34
|
+
invalidate: <NAME extends string | number>(...args: UseDataArgs<BaseApiTypeMap, NAME>) => Promise<void>;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export { register };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
2
|
+
import z from 'zod';
|
|
3
|
+
|
|
4
|
+
type BaseApiTypeMap = {
|
|
5
|
+
[stateName: string]: {
|
|
6
|
+
type: object | string | number | boolean;
|
|
7
|
+
} & ({
|
|
8
|
+
params: {
|
|
9
|
+
[param: string]: string | number;
|
|
10
|
+
};
|
|
11
|
+
} | {
|
|
12
|
+
params?: undefined;
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
type ApiModel<ApiTypeMap extends BaseApiTypeMap> = {
|
|
16
|
+
[NAME in keyof ApiTypeMap]: {
|
|
17
|
+
schema: z.ZodType<ApiTypeMap[NAME]["type"]>;
|
|
18
|
+
url: ApiTypeMap[NAME]["params"] extends object ? (params: ApiTypeMap[NAME]["params"]) => string : string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
type UseDataArgs<ApiTypeMap extends BaseApiTypeMap, NAME extends keyof ApiTypeMap> = ApiTypeMap[NAME]["params"] extends object ? [stateName: NAME, params: ApiTypeMap[NAME]["params"]] : [stateName: NAME, params?: undefined];
|
|
22
|
+
type Options = {
|
|
23
|
+
fetchFn?: (url: string) => Promise<unknown>;
|
|
24
|
+
baseUrl?: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
declare function register<ApiTypeMap extends BaseApiTypeMap>(apiModel: ApiModel<ApiTypeMap>, options?: Options): {
|
|
28
|
+
useData: <NAME extends keyof ApiTypeMap>(...args: UseDataArgs<ApiTypeMap, NAME>) => {
|
|
29
|
+
data: ApiTypeMap[NAME]["type"] | undefined;
|
|
30
|
+
isLoading: boolean;
|
|
31
|
+
error: Error | null;
|
|
32
|
+
};
|
|
33
|
+
client: QueryClient;
|
|
34
|
+
invalidate: <NAME extends string | number>(...args: UseDataArgs<BaseApiTypeMap, NAME>) => Promise<void>;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export { register };
|