@ryneex/api-client 1.0.0-beta.1 → 1.0.0-beta.3
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/index.d.ts +43 -10
- package/index.js +121 -67
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as axios from 'axios';
|
|
2
|
-
import { AxiosRequestConfig, AxiosError, AxiosInstance } from 'axios';
|
|
2
|
+
import { AxiosRequestConfig, AxiosResponse, AxiosError, AxiosInstance } from 'axios';
|
|
3
3
|
import z, { ZodError } from 'zod';
|
|
4
4
|
import { UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
|
|
5
5
|
|
|
@@ -9,30 +9,43 @@ type ClientPayload<TInput, TVariables> = {} & (unknown extends TInput ? unknown
|
|
|
9
9
|
variables: TVariables;
|
|
10
10
|
});
|
|
11
11
|
type OptionalPayload<T> = object extends T ? void : T;
|
|
12
|
-
type ClientOptions<TOutputSchema extends z.ZodType, TInputSchema extends z.ZodType, TVariablesSchema extends z.ZodType, TOutput = z.
|
|
12
|
+
type ClientOptions<TOutputSchema extends z.ZodType, TInputSchema extends z.ZodType, TVariablesSchema extends z.ZodType, TOutput = z.output<TOutputSchema>, TInput = z.input<TInputSchema>, TVariables = z.input<TVariablesSchema>> = {
|
|
13
13
|
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
14
14
|
path: string | ((payload: ClientPayload<TInput, TVariables>) => string);
|
|
15
15
|
axiosOptions?: (payload: ClientPayload<TInput, TVariables>) => AxiosRequestConfig;
|
|
16
16
|
variablesSchema?: TVariablesSchema;
|
|
17
17
|
inputSchema?: TInputSchema;
|
|
18
18
|
outputSchema: TOutputSchema;
|
|
19
|
-
transform?: (data: z.
|
|
19
|
+
transform?: (data: z.output<TOutputSchema>, payload: ClientPayload<TInput, TVariables>) => TOutput;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
type ReactQueryOptions<TOutput, TInput, TVariables> = Omit<UseQueryOptions<TOutput,
|
|
22
|
+
type ReactQueryOptions<TOutput, TInput, TVariables> = Omit<UseQueryOptions<TOutput, ClientError>, "queryFn" | "queryKey"> & {
|
|
23
23
|
queryKey?: unknown[];
|
|
24
24
|
} & (object extends ClientPayload<TInput, TVariables> ? unknown : {
|
|
25
25
|
data: ClientPayload<TInput, TVariables>;
|
|
26
26
|
}) & {
|
|
27
27
|
onSuccess?: (data: TOutput, payload: ClientPayload<TInput, TVariables>) => void;
|
|
28
|
-
onError?: (error:
|
|
28
|
+
onError?: (error: ClientError, payload: ClientPayload<TInput, TVariables>) => void;
|
|
29
29
|
};
|
|
30
|
-
type ReactMutationOptions<TOutput, TInput, TVariables> = Omit<UseMutationOptions<TOutput,
|
|
30
|
+
type ReactMutationOptions<TOutput, TInput, TVariables> = Omit<UseMutationOptions<TOutput, ClientError, object extends ClientPayload<TInput, TVariables> ? void : ClientPayload<TInput, TVariables>>, "mutationFn"> & {};
|
|
31
|
+
|
|
32
|
+
type Ok<T> = {
|
|
33
|
+
success: true;
|
|
34
|
+
data: T;
|
|
35
|
+
response: AxiosResponse;
|
|
36
|
+
};
|
|
37
|
+
type ClientError = ValidationError | AxiosError;
|
|
38
|
+
type Err<E> = {
|
|
39
|
+
success: false;
|
|
40
|
+
error: E;
|
|
41
|
+
};
|
|
42
|
+
type Result<T, E> = Ok<T> | Err<E>;
|
|
31
43
|
|
|
32
44
|
declare function createClient(axios: AxiosInstance): {
|
|
33
|
-
create: <TOutputSchema extends z.ZodType, TInputSchema extends z.ZodType, TVariablesSchema extends z.ZodType, TOutput = z.core.output<TOutputSchema>, TInput = z.core.
|
|
34
|
-
|
|
35
|
-
|
|
45
|
+
create: <TOutputSchema extends z.ZodType, TInputSchema extends z.ZodType, TVariablesSchema extends z.ZodType, TOutput = z.core.output<TOutputSchema>, TInput = z.core.input<TInputSchema>, TVariables = z.core.input<TVariablesSchema>>(opts: ClientOptions<TOutputSchema, TInputSchema, TVariablesSchema, TOutput, TInput, TVariables>) => ((_payload: OptionalPayload<ClientPayload<TInput, TVariables>>) => Promise<Result<TOutput, ClientError>>) & {
|
|
46
|
+
call: (_payload: OptionalPayload<ClientPayload<TInput, TVariables>>) => Promise<Result<TOutput, ClientError>>;
|
|
47
|
+
queryOptions: (_opts: object extends ClientPayload<TInput, TVariables> ? ReactQueryOptions<TOutput, TInput, TVariables> | void : ReactQueryOptions<TOutput, TInput, TVariables>) => UseQueryOptions<TOutput, ClientError>;
|
|
48
|
+
mutationOptions: (_opts: ReactMutationOptions<TOutput, TInput, TVariables> | void) => UseMutationOptions<TOutput, ClientError, object extends ClientPayload<TInput, TVariables> ? void : ClientPayload<TInput, TVariables>>;
|
|
36
49
|
queryKey: (data?: ClientPayload<TInput, TVariables>) => (string | ClientPayload<TInput, TVariables>)[];
|
|
37
50
|
mutationKey: () => string[];
|
|
38
51
|
config: {
|
|
@@ -48,4 +61,24 @@ declare function createClient(axios: AxiosInstance): {
|
|
|
48
61
|
};
|
|
49
62
|
};
|
|
50
63
|
|
|
51
|
-
|
|
64
|
+
declare function callApi<TOutputSchema extends z.ZodType, TInputSchema extends z.ZodType, TVariablesSchema extends z.ZodType, TOutput = z.output<TOutputSchema>, TInput = z.input<TInputSchema>, TVariables = z.input<TVariablesSchema>>(opts: ClientOptions<TOutputSchema, TInputSchema, TVariablesSchema, TOutput, TInput, TVariables> & {
|
|
65
|
+
axios: AxiosInstance;
|
|
66
|
+
}, data: ClientPayload<TInput, TVariables>): Promise<Result<TOutput, ClientError>>;
|
|
67
|
+
declare function getResponse<TOutputSchema extends z.ZodType, TInputSchema extends z.ZodType, TVariablesSchema extends z.ZodType, TOutput = z.output<TOutputSchema>, TInput = z.input<TInputSchema>, TVariables = z.input<TVariablesSchema>>(request: Promise<AxiosResponse<TOutput>>, opts: ClientOptions<TOutputSchema, TInputSchema, TVariablesSchema, TOutput, TInput, TVariables>, payload: ClientPayload<TInput, TVariables>): Promise<Result<TOutput, ClientError>>;
|
|
68
|
+
|
|
69
|
+
declare const VALIDATION_ERROR_NAMES: {
|
|
70
|
+
readonly INPUT: "InputValidationError";
|
|
71
|
+
readonly VARIABLE: "VariableValidationError";
|
|
72
|
+
readonly OUTPUT: "OutputValidationError";
|
|
73
|
+
};
|
|
74
|
+
type ApiClientErrorProps = {
|
|
75
|
+
type: keyof typeof VALIDATION_ERROR_NAMES;
|
|
76
|
+
issues: z.core.$ZodIssue[];
|
|
77
|
+
};
|
|
78
|
+
declare class ValidationError extends ZodError {
|
|
79
|
+
constructor({ type, issues }: ApiClientErrorProps);
|
|
80
|
+
}
|
|
81
|
+
declare function ok<T>(data: T, response: AxiosResponse): Ok<T>;
|
|
82
|
+
declare function err<E>(error: E): Err<E>;
|
|
83
|
+
|
|
84
|
+
export { type ApiClientErrorProps, type ClientError, type ClientOptions, type ClientPayload, type Err, type Ok, type OptionalPayload, type ReactMutationOptions, type ReactQueryOptions, type Result, VALIDATION_ERROR_NAMES, ValidationError, callApi, createClient, err, getResponse, ok };
|
package/index.js
CHANGED
|
@@ -1,62 +1,5 @@
|
|
|
1
1
|
// src/lib/api-client.ts
|
|
2
2
|
import "zod";
|
|
3
|
-
|
|
4
|
-
// src/lib/call-api.ts
|
|
5
|
-
import "zod";
|
|
6
|
-
async function callApi(opts, data) {
|
|
7
|
-
if (typeof data !== "object")
|
|
8
|
-
throw new Error("API SDK: Data must be an object");
|
|
9
|
-
if (opts.inputSchema && "input" in data) {
|
|
10
|
-
opts.inputSchema.parse(data.input);
|
|
11
|
-
}
|
|
12
|
-
if (opts.variablesSchema && "variables" in data) {
|
|
13
|
-
opts.variablesSchema.parse(data.variables);
|
|
14
|
-
}
|
|
15
|
-
const axiosOptions = opts.axiosOptions?.(data);
|
|
16
|
-
const url = typeof opts.path === "function" ? opts.path(data) : opts.path;
|
|
17
|
-
if (opts.method === "GET") {
|
|
18
|
-
const response = await opts.axios.get(url, axiosOptions);
|
|
19
|
-
return getResponse(opts, data, response);
|
|
20
|
-
}
|
|
21
|
-
if (opts.method === "POST") {
|
|
22
|
-
const response = await opts.axios.post(
|
|
23
|
-
url,
|
|
24
|
-
axiosOptions?.data,
|
|
25
|
-
axiosOptions
|
|
26
|
-
);
|
|
27
|
-
return getResponse(opts, data, response);
|
|
28
|
-
}
|
|
29
|
-
if (opts.method === "PUT") {
|
|
30
|
-
const response = await opts.axios.put(
|
|
31
|
-
url,
|
|
32
|
-
axiosOptions?.data,
|
|
33
|
-
axiosOptions
|
|
34
|
-
);
|
|
35
|
-
return getResponse(opts, data, response);
|
|
36
|
-
}
|
|
37
|
-
if (opts.method === "PATCH") {
|
|
38
|
-
const response = await opts.axios.patch(
|
|
39
|
-
url,
|
|
40
|
-
axiosOptions?.data,
|
|
41
|
-
axiosOptions
|
|
42
|
-
);
|
|
43
|
-
return getResponse(opts, data, response);
|
|
44
|
-
}
|
|
45
|
-
if (opts.method === "DELETE") {
|
|
46
|
-
const response = await opts.axios.delete(url, axiosOptions);
|
|
47
|
-
return getResponse(opts, data, response);
|
|
48
|
-
}
|
|
49
|
-
throw new Error(`API SDK: Unsupported method: ${opts.method}`);
|
|
50
|
-
}
|
|
51
|
-
function getResponse(opts, payload, response) {
|
|
52
|
-
const parsedData = opts.outputSchema.parse(response.data);
|
|
53
|
-
if (opts.transform) {
|
|
54
|
-
return { ...response, data: opts.transform(parsedData, payload) };
|
|
55
|
-
}
|
|
56
|
-
return { ...response, data: parsedData };
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// src/lib/api-client.ts
|
|
60
3
|
import "@tanstack/react-query";
|
|
61
4
|
function createClient(axios) {
|
|
62
5
|
function create(opts) {
|
|
@@ -73,14 +16,13 @@ function createClient(axios) {
|
|
|
73
16
|
const data = _data ?? {};
|
|
74
17
|
return {
|
|
75
18
|
queryFn: async () => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
options.onSuccess?.(
|
|
79
|
-
return
|
|
80
|
-
} catch (error) {
|
|
81
|
-
options.onError?.(error, data);
|
|
82
|
-
throw error;
|
|
19
|
+
const result = await callApi(apiOptionas, data);
|
|
20
|
+
if (result.success) {
|
|
21
|
+
options.onSuccess?.(result.data, data);
|
|
22
|
+
return result.data;
|
|
83
23
|
}
|
|
24
|
+
options.onError?.(result.error, data);
|
|
25
|
+
throw result.error;
|
|
84
26
|
},
|
|
85
27
|
queryKey: queryKey(data),
|
|
86
28
|
...options
|
|
@@ -91,14 +33,16 @@ function createClient(axios) {
|
|
|
91
33
|
return {
|
|
92
34
|
mutationFn: async (_data) => {
|
|
93
35
|
const data = _data ?? {};
|
|
94
|
-
const
|
|
95
|
-
return
|
|
36
|
+
const result = await callApi(apiOptionas, data);
|
|
37
|
+
if (result.success) return result.data;
|
|
38
|
+
throw result.error;
|
|
96
39
|
},
|
|
97
40
|
mutationKey: mutationKey(),
|
|
98
41
|
...options
|
|
99
42
|
};
|
|
100
43
|
};
|
|
101
44
|
return Object.assign(call, {
|
|
45
|
+
call,
|
|
102
46
|
queryOptions,
|
|
103
47
|
mutationOptions,
|
|
104
48
|
queryKey,
|
|
@@ -112,6 +56,116 @@ function createClient(axios) {
|
|
|
112
56
|
}
|
|
113
57
|
return { create };
|
|
114
58
|
}
|
|
59
|
+
|
|
60
|
+
// src/lib/call-api.ts
|
|
61
|
+
import "zod";
|
|
62
|
+
async function callApi(opts, data) {
|
|
63
|
+
if (typeof data !== "object")
|
|
64
|
+
throw new Error("API_CLIENT_INTERNAL_ERROR: Data must be an object");
|
|
65
|
+
if (opts.inputSchema && "input" in data) {
|
|
66
|
+
const parsedResult = opts.inputSchema.safeParse(data.input);
|
|
67
|
+
if (!parsedResult.success)
|
|
68
|
+
return err(
|
|
69
|
+
new ValidationError({
|
|
70
|
+
type: "INPUT",
|
|
71
|
+
issues: parsedResult.error.issues
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
if (opts.variablesSchema && "variables" in data) {
|
|
76
|
+
const parsedResult = opts.variablesSchema.safeParse(data.variables);
|
|
77
|
+
if (!parsedResult.success)
|
|
78
|
+
return err(
|
|
79
|
+
new ValidationError({
|
|
80
|
+
type: "VARIABLE",
|
|
81
|
+
issues: parsedResult.error.issues
|
|
82
|
+
})
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
const axiosOptions = opts.axiosOptions?.(data);
|
|
86
|
+
const url = typeof opts.path === "function" ? opts.path(data) : opts.path;
|
|
87
|
+
if (opts.method === "GET") {
|
|
88
|
+
return await getResponse(
|
|
89
|
+
opts.axios.get(url, axiosOptions),
|
|
90
|
+
opts,
|
|
91
|
+
data
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
if (opts.method === "POST") {
|
|
95
|
+
return await getResponse(
|
|
96
|
+
opts.axios.post(url, axiosOptions?.data, axiosOptions),
|
|
97
|
+
opts,
|
|
98
|
+
data
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
if (opts.method === "PUT") {
|
|
102
|
+
return await getResponse(
|
|
103
|
+
opts.axios.put(url, axiosOptions?.data, axiosOptions),
|
|
104
|
+
opts,
|
|
105
|
+
data
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
if (opts.method === "PATCH") {
|
|
109
|
+
return await getResponse(
|
|
110
|
+
opts.axios.patch(url, axiosOptions?.data, axiosOptions),
|
|
111
|
+
opts,
|
|
112
|
+
data
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
if (opts.method === "DELETE") {
|
|
116
|
+
return await getResponse(
|
|
117
|
+
opts.axios.delete(url, axiosOptions),
|
|
118
|
+
opts,
|
|
119
|
+
data
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
throw new Error(`API SDK: Unsupported method: ${opts.method}`);
|
|
123
|
+
}
|
|
124
|
+
async function getResponse(request, opts, payload) {
|
|
125
|
+
try {
|
|
126
|
+
const response = await request;
|
|
127
|
+
const parsedResult = opts.outputSchema.safeParse(response.data);
|
|
128
|
+
if (!parsedResult.success)
|
|
129
|
+
return err(
|
|
130
|
+
new ValidationError({
|
|
131
|
+
type: "OUTPUT",
|
|
132
|
+
issues: parsedResult.error.issues
|
|
133
|
+
})
|
|
134
|
+
);
|
|
135
|
+
if (opts.transform) {
|
|
136
|
+
return ok(opts.transform(parsedResult.data, payload), response);
|
|
137
|
+
}
|
|
138
|
+
return ok(parsedResult.data, response);
|
|
139
|
+
} catch (error) {
|
|
140
|
+
return err(error);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/lib/result.ts
|
|
145
|
+
import { ZodError } from "zod";
|
|
146
|
+
var VALIDATION_ERROR_NAMES = {
|
|
147
|
+
INPUT: "InputValidationError",
|
|
148
|
+
VARIABLE: "VariableValidationError",
|
|
149
|
+
OUTPUT: "OutputValidationError"
|
|
150
|
+
};
|
|
151
|
+
var ValidationError = class extends ZodError {
|
|
152
|
+
constructor({ type, issues }) {
|
|
153
|
+
super(issues);
|
|
154
|
+
this.name = VALIDATION_ERROR_NAMES[type];
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
function ok(data, response) {
|
|
158
|
+
return { success: true, data, response };
|
|
159
|
+
}
|
|
160
|
+
function err(error) {
|
|
161
|
+
return { success: false, error };
|
|
162
|
+
}
|
|
115
163
|
export {
|
|
116
|
-
|
|
164
|
+
VALIDATION_ERROR_NAMES,
|
|
165
|
+
ValidationError,
|
|
166
|
+
callApi,
|
|
167
|
+
createClient,
|
|
168
|
+
err,
|
|
169
|
+
getResponse,
|
|
170
|
+
ok
|
|
117
171
|
};
|