@danstackme/apity
Version:
Type-safe API client generator for React applications with file-based routing and runtime validation
123 lines (119 loc) • 3.71 kB
JavaScript
import { QueryClient, QueryClientProvider, useQuery, useMutation } from '@tanstack/react-query';
import { createContext, useContext } from 'react';
import { jsx } from 'react/jsx-runtime';
import axios from 'axios';
// src/useFetch.ts
var ApiContext = createContext(null);
function useApiContext() {
const context = useContext(ApiContext);
if (!context) {
throw new Error("useApiContext must be used within an ApiProvider");
}
return context;
}
function ApiProvider({ children, api }) {
const queryClient = api.queryClient ?? new QueryClient();
const value = {
client: api.client,
queryClient,
config: api.config
};
return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(ApiContext.Provider, { value, children }) });
}
// src/utils.ts
function getParamName(path) {
const match = path.match(/\[([^\]]+)\]/);
return match ? match[1] : "";
}
function interpolatePath(path, params) {
return path.replace(/\[([^\]]+)\]/g, (_, key) => {
if (!params[key]) {
throw new Error(`Missing path parameter: ${key}`);
}
return params[key];
});
}
// src/useFetch.ts
function useFetch(options) {
const { path, params, query, enabled = true, ...queryOptions } = options;
const { client, config } = useApiContext();
if (path.includes("[") && (!params || Object.keys(params).length === 0)) {
throw new Error(`Missing path parameter: ${getParamName(path)}`);
}
const url = interpolatePath(path, params || {});
return useQuery({
...queryOptions,
queryKey: [path, params, query],
queryFn: async () => {
const response = await client.get(url, {
baseURL: config.baseUrl,
params: query
});
return response.data;
},
enabled
});
}
function useMutate(options) {
const { path, params, method, ...mutationOptions } = options;
const { client, config } = useApiContext();
if (path.includes("[") && (!params || Object.keys(params).length === 0)) {
throw new Error(`Missing path parameter: ${getParamName(path)}`);
}
const url = interpolatePath(path, params || {});
return useMutation({
...mutationOptions,
mutationFn: async (data) => {
const response = await client.request({
method,
url,
baseURL: config.baseUrl,
data
});
return response.data;
}
});
}
function createApiEndpoint(config) {
return {
...config,
method: config.method,
response: config.response,
body: config.body,
query: config.query
};
}
function createApi(config) {
const queryClient = config.queryClient || new QueryClient();
const client = config.client || axios.create();
client.defaults.baseURL = config.baseUrl;
if (config.headers) {
Object.assign(client.defaults.headers, config.headers);
}
const middlewareFns = [];
if (config.middleware) {
if (config.middleware.before) {
middlewareFns.push(config.middleware.before);
client.interceptors.request.use(config.middleware.before);
}
if (config.middleware.after) {
middlewareFns.push(config.middleware.after);
client.interceptors.response.use(config.middleware.after);
}
if (config.middleware.onError) {
middlewareFns.push(config.middleware.onError);
client.interceptors.response.use(void 0, config.middleware.onError);
}
}
return {
client,
queryClient,
config,
middleware: middlewareFns,
fetchEndpoints: config.fetchEndpoints,
mutateEndpoints: config.mutateEndpoints
};
}
export { ApiProvider, createApi, createApiEndpoint, useApiContext, useFetch, useMutate };
//# sourceMappingURL=index.js.map
//# sourceMappingURL=index.js.map