kmod-cli 1.4.14 → 1.5.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.
|
@@ -91,7 +91,7 @@ export interface DeleteManyParams {
|
|
|
91
91
|
meta?: AxiosRequestConfig;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
export interface CustomParams {
|
|
94
|
+
export interface CustomParams extends AxiosRequestConfig {
|
|
95
95
|
url?: string;
|
|
96
96
|
method?: 'get' | 'post' | 'put' | 'patch' | 'delete';
|
|
97
97
|
payload?: any;
|
|
@@ -221,8 +221,7 @@ class DataProvider {
|
|
|
221
221
|
options: DataProviderOptions = {}
|
|
222
222
|
) {
|
|
223
223
|
this.httpClient = httpClient;
|
|
224
|
-
|
|
225
|
-
// Lấy baseURL từ httpClient
|
|
224
|
+
|
|
226
225
|
const baseURL = httpClient.defaults.baseURL || '';
|
|
227
226
|
this.apiUrl = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL;
|
|
228
227
|
|
|
@@ -804,7 +803,8 @@ export function useOne<T = any>(
|
|
|
804
803
|
|
|
805
804
|
export function useCreate<T = any, V = any>(
|
|
806
805
|
resource: string,
|
|
807
|
-
options: UseMutationOptions<T
|
|
806
|
+
options: UseMutationOptions<T>,
|
|
807
|
+
meta?:AxiosRequestConfig
|
|
808
808
|
) {
|
|
809
809
|
const [loading, setLoading] = useState<boolean>(false);
|
|
810
810
|
const [error, setError] = useState<DataProviderError | null>(null);
|
|
@@ -819,7 +819,8 @@ export function useCreate<T = any, V = any>(
|
|
|
819
819
|
|
|
820
820
|
try {
|
|
821
821
|
const result = await dataProvider.create<T, V>(resource, {
|
|
822
|
-
variables
|
|
822
|
+
variables,
|
|
823
|
+
meta,
|
|
823
824
|
});
|
|
824
825
|
if (onSuccess) {
|
|
825
826
|
onSuccess(result.data);
|
|
@@ -842,7 +843,8 @@ export function useCreate<T = any, V = any>(
|
|
|
842
843
|
|
|
843
844
|
export function useUpdate<T = any, V = any>(
|
|
844
845
|
resource: string,
|
|
845
|
-
options: UseMutationOptions<T
|
|
846
|
+
options: UseMutationOptions<T>,
|
|
847
|
+
meta?: AxiosRequestConfig
|
|
846
848
|
) {
|
|
847
849
|
const [loading, setLoading] = useState<boolean>(false);
|
|
848
850
|
const [error, setError] = useState<DataProviderError | null>(null);
|
|
@@ -857,7 +859,7 @@ export function useUpdate<T = any, V = any>(
|
|
|
857
859
|
setError(null);
|
|
858
860
|
|
|
859
861
|
try {
|
|
860
|
-
const result = await dataProvider.update<T, V>(resource, { id, variables });
|
|
862
|
+
const result = await dataProvider.update<T, V>(resource, { id, variables, meta });
|
|
861
863
|
if (onSuccess) {
|
|
862
864
|
onSuccess(result.data);
|
|
863
865
|
}
|
|
@@ -881,7 +883,8 @@ export function useUpdate<T = any, V = any>(
|
|
|
881
883
|
|
|
882
884
|
export function useDelete<T = any>(
|
|
883
885
|
resource: string,
|
|
884
|
-
options: UseMutationOptions<T
|
|
886
|
+
options: UseMutationOptions<T>,
|
|
887
|
+
meta?: AxiosRequestConfig
|
|
885
888
|
) {
|
|
886
889
|
const [loading, setLoading] = useState<boolean>(false);
|
|
887
890
|
const [error, setError] = useState<DataProviderError | null>(null);
|
|
@@ -896,7 +899,7 @@ export function useDelete<T = any>(
|
|
|
896
899
|
setError(null);
|
|
897
900
|
|
|
898
901
|
try {
|
|
899
|
-
const result = await dataProvider.deleteOne<T>(resource, { id });
|
|
902
|
+
const result = await dataProvider.deleteOne<T>(resource, { id, meta });
|
|
900
903
|
if (onSuccess) {
|
|
901
904
|
onSuccess(result.data);
|
|
902
905
|
}
|
|
@@ -920,7 +923,7 @@ export function useDelete<T = any>(
|
|
|
920
923
|
|
|
921
924
|
export function useCustom<T = any>(
|
|
922
925
|
resource: string,
|
|
923
|
-
options: UseMutationOptions<T> & CustomParams
|
|
926
|
+
options: UseMutationOptions<T> & CustomParams,
|
|
924
927
|
) {
|
|
925
928
|
const [loading, setLoading] = useState<boolean>(false);
|
|
926
929
|
const [error, setError] = useState<DataProviderError | null>(null);
|
|
@@ -942,6 +945,7 @@ export function useCustom<T = any>(
|
|
|
942
945
|
method: options.method,
|
|
943
946
|
headers: options.headers,
|
|
944
947
|
query: options.query,
|
|
948
|
+
...options
|
|
945
949
|
});
|
|
946
950
|
if (onSuccess) {
|
|
947
951
|
onSuccess(result.data);
|
|
@@ -990,33 +994,70 @@ export const useDataProvider = () => {
|
|
|
990
994
|
|
|
991
995
|
/**
|
|
992
996
|
* Create HTTP client with authentication
|
|
997
|
+
* @param url Base URL for the HTTP client
|
|
998
|
+
* @param options Configuration options for the HTTP client
|
|
999
|
+
* @param options.tokenName Name of the token to use for authentication
|
|
1000
|
+
* @param options.tokenStorage Storage mechanism for the token
|
|
1001
|
+
* @param options.authorizationType Type of authorization (e.g., Bearer, Basic)
|
|
1002
|
+
* @param options.withCredentials Whether to send cookies with requests (defaults to true if tokenStorage is "http-only")
|
|
1003
|
+
* @returns Configured Axios instance
|
|
993
1004
|
*/
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1005
|
+
|
|
1006
|
+
export interface ICreateHttpClientOptions {
|
|
1007
|
+
tokenName?: string ;
|
|
1008
|
+
tokenStorage?: "local" | "session" | "cookie" | "http-only";
|
|
1009
|
+
authorizationType?: "Bearer" | "Basic" | string;
|
|
1010
|
+
withCredentials?: boolean;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
export interface ICreateHttpClient {
|
|
1014
|
+
url?: string;
|
|
1015
|
+
options?: ICreateHttpClientOptions
|
|
1016
|
+
}
|
|
1017
|
+
export function createHttpClient({url, options = {}}:ICreateHttpClient): AxiosInstance {
|
|
1018
|
+
const {
|
|
1019
|
+
tokenName = "token",
|
|
1020
|
+
tokenStorage = "http-only",
|
|
1021
|
+
authorizationType = "Bearer",
|
|
1022
|
+
} = options;
|
|
1023
|
+
|
|
1024
|
+
const withCredentials =
|
|
1025
|
+
options.withCredentials ?? tokenStorage === "http-only";
|
|
1026
|
+
|
|
1027
|
+
|
|
1000
1028
|
const axiosInstance = axios.create({
|
|
1001
|
-
baseURL:
|
|
1029
|
+
baseURL: url || "https://api.example.com",
|
|
1030
|
+
withCredentials,
|
|
1002
1031
|
});
|
|
1003
1032
|
|
|
1004
|
-
axiosInstance.interceptors.request.use(config => {
|
|
1033
|
+
axiosInstance.interceptors.request.use((config) => {
|
|
1005
1034
|
let token: string | null = null;
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1035
|
+
|
|
1036
|
+
switch (options.tokenStorage) {
|
|
1037
|
+
case "local":
|
|
1038
|
+
token = localStorage.getItem(tokenName);
|
|
1039
|
+
break;
|
|
1040
|
+
|
|
1041
|
+
case "session":
|
|
1042
|
+
token = sessionStorage.getItem(tokenName);
|
|
1043
|
+
break;
|
|
1044
|
+
|
|
1045
|
+
case "cookie":
|
|
1046
|
+
token = cookiesProvider.get(tokenName) ?? null;
|
|
1047
|
+
break;
|
|
1048
|
+
|
|
1049
|
+
case "http-only":
|
|
1050
|
+
// NO READ
|
|
1051
|
+
// HttpOnly cookies are not accessible via JavaScript
|
|
1052
|
+
// Browser will send it automatically
|
|
1053
|
+
break;
|
|
1014
1054
|
}
|
|
1015
|
-
|
|
1055
|
+
|
|
1056
|
+
// Just set token if available in storage
|
|
1016
1057
|
if (token) {
|
|
1017
|
-
config.headers.Authorization = `${
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1058
|
+
config.headers.Authorization = `${authorizationType} ${token}`;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1020
1061
|
return config;
|
|
1021
1062
|
});
|
|
1022
1063
|
|
|
@@ -1046,15 +1087,36 @@ interface AuthContextValue {
|
|
|
1046
1087
|
isAuthenticated: () => boolean;
|
|
1047
1088
|
setUser: (user: AuthUser | null) => void;
|
|
1048
1089
|
login: (payload: LoginPayload, type?: "full" | "simple") => Promise<any>;
|
|
1049
|
-
logout: () =>
|
|
1090
|
+
logout: (params: CustomParams, type?: TypeResponse) => Promise<any>;
|
|
1050
1091
|
getMe: (type?: "full" | "simple") => Promise<any>;
|
|
1051
1092
|
}
|
|
1052
1093
|
|
|
1094
|
+
/**
|
|
1095
|
+
* Authentication Provider Urls Props
|
|
1096
|
+
* @param loginUrl - URL for login API
|
|
1097
|
+
* @param logoutUrl - URL for logout API
|
|
1098
|
+
* @param meUrl - URL for fetching current user info
|
|
1099
|
+
* @returns AuthProviderUrls
|
|
1100
|
+
*/
|
|
1101
|
+
export interface AuthProviderUrls {
|
|
1102
|
+
loginUrl: string;
|
|
1103
|
+
logoutUrl?: string;
|
|
1104
|
+
meUrl?: string;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
/**
|
|
1108
|
+
* Authentication Provider Props
|
|
1109
|
+
* @param children - React children nodes
|
|
1110
|
+
* @param urls - AuthProviderUrls
|
|
1111
|
+
* @param tokenKey - Key for token storage
|
|
1112
|
+
* @param keysCleanUpOnLogout - Additional keys to clean up on logout
|
|
1113
|
+
* @returns AuthProviderProps
|
|
1114
|
+
*/
|
|
1053
1115
|
export interface AuthProviderProps {
|
|
1054
1116
|
children: React.ReactNode;
|
|
1055
|
-
|
|
1056
|
-
meUrl: string;
|
|
1117
|
+
urls: AuthProviderUrls;
|
|
1057
1118
|
tokenKey: string;
|
|
1119
|
+
keysCleanUpOnLogout?: string[] | string;
|
|
1058
1120
|
}
|
|
1059
1121
|
|
|
1060
1122
|
export type TypeResponse = "full" | "simple";
|
|
@@ -1071,13 +1133,21 @@ export const useAuth = () => {
|
|
|
1071
1133
|
|
|
1072
1134
|
export const AuthProvider: React.FC<AuthProviderProps> = ({
|
|
1073
1135
|
children,
|
|
1074
|
-
|
|
1075
|
-
meUrl = '/auth/me',
|
|
1136
|
+
urls,
|
|
1076
1137
|
tokenKey = 'token',
|
|
1138
|
+
keysCleanUpOnLogout = ["token"],
|
|
1077
1139
|
}) => {
|
|
1078
1140
|
const dataProvider = useDataProvider();
|
|
1079
1141
|
const [user, setUser] = useState<AuthUser | null>(null);
|
|
1080
1142
|
|
|
1143
|
+
const { loginUrl, meUrl, logoutUrl } = urls;
|
|
1144
|
+
|
|
1145
|
+
function removeKeys(key: string) {
|
|
1146
|
+
cookiesProvider.remove(key);
|
|
1147
|
+
localStorage.removeItem(key);
|
|
1148
|
+
sessionStorage.removeItem(key);
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1081
1151
|
const login = useCallback(async (payload: LoginPayload, type: TypeResponse = "full") => {
|
|
1082
1152
|
try {
|
|
1083
1153
|
const res = await dataProvider.custom<any>({
|
|
@@ -1096,15 +1166,37 @@ export const AuthProvider: React.FC<AuthProviderProps> = ({
|
|
|
1096
1166
|
}
|
|
1097
1167
|
, [dataProvider, loginUrl]);
|
|
1098
1168
|
|
|
1099
|
-
const logout = useCallback(() => {
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1169
|
+
const logout = useCallback(async (params: CustomParams, type: TypeResponse = "full") => {
|
|
1170
|
+
|
|
1171
|
+
try {
|
|
1172
|
+
const res = await dataProvider.custom<any>({
|
|
1173
|
+
url: params.url || logoutUrl,
|
|
1174
|
+
...params,
|
|
1175
|
+
});
|
|
1176
|
+
|
|
1177
|
+
if (type === "simple") {
|
|
1178
|
+
return res.data;
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
return res;
|
|
1182
|
+
} catch (error) {
|
|
1183
|
+
throw error;
|
|
1184
|
+
} finally {
|
|
1185
|
+
setUser(null);
|
|
1186
|
+
dataProvider.clearAllCache();
|
|
1187
|
+
if(Array.isArray(keysCleanUpOnLogout)){
|
|
1188
|
+
keysCleanUpOnLogout.forEach((key) => {
|
|
1189
|
+
removeKeys(key);
|
|
1190
|
+
});
|
|
1191
|
+
} else {
|
|
1192
|
+
removeKeys(keysCleanUpOnLogout);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
}, [dataProvider, logoutUrl]);
|
|
1105
1197
|
|
|
1106
1198
|
const isAuthenticated = () => {
|
|
1107
|
-
return
|
|
1199
|
+
return user !== null;
|
|
1108
1200
|
};
|
|
1109
1201
|
const getToken = useCallback(() => {
|
|
1110
1202
|
return cookiesProvider.get(tokenKey);
|
|
@@ -1124,12 +1216,17 @@ export const AuthProvider: React.FC<AuthProviderProps> = ({
|
|
|
1124
1216
|
} catch {
|
|
1125
1217
|
return null;
|
|
1126
1218
|
}
|
|
1127
|
-
}, [dataProvider, meUrl
|
|
1219
|
+
}, [dataProvider, meUrl]);
|
|
1220
|
+
|
|
1221
|
+
useEffect(() => {
|
|
1222
|
+
getMe().then((u: any) => u && setUser(u));
|
|
1223
|
+
}, [getMe]);
|
|
1224
|
+
|
|
1128
1225
|
|
|
1129
1226
|
const value: AuthContextValue = {
|
|
1130
1227
|
user,
|
|
1131
1228
|
setUser,
|
|
1132
|
-
token: getToken(),
|
|
1229
|
+
token: getToken() ?? null,
|
|
1133
1230
|
isAuthenticated: isAuthenticated,
|
|
1134
1231
|
login,
|
|
1135
1232
|
logout,
|
|
@@ -1167,28 +1264,39 @@ export const cookiesProvider = {
|
|
|
1167
1264
|
|
|
1168
1265
|
// =================== Example ===================
|
|
1169
1266
|
|
|
1170
|
-
// create httpClient
|
|
1267
|
+
// create httpClient - (can create multiple httpClients for different apis)
|
|
1171
1268
|
|
|
1172
1269
|
// const TOKEN = "token";
|
|
1173
1270
|
|
|
1174
|
-
// const httpClient = createHttpClient(
|
|
1175
|
-
// `${process.env.NEXT_PUBLIC_API_URL}`,
|
|
1176
|
-
//
|
|
1177
|
-
//
|
|
1178
|
-
//
|
|
1179
|
-
//
|
|
1271
|
+
// const httpClient = createHttpClient({
|
|
1272
|
+
// url: `${process.env.NEXT_PUBLIC_API_URL}`,
|
|
1273
|
+
// options: {
|
|
1274
|
+
// authorizationType: "Bearer",
|
|
1275
|
+
// tokenName: TOKEN,
|
|
1276
|
+
// tokenStorage: "cookie",
|
|
1277
|
+
// withCredentials: true, --- optionals (default to true if tokenStorage is "http-only")
|
|
1278
|
+
// },
|
|
1279
|
+
// });
|
|
1180
1280
|
|
|
1181
1281
|
|
|
1182
1282
|
// create dataProvider
|
|
1183
1283
|
|
|
1184
1284
|
// const dataProvider = useDataProvider(httpClient);
|
|
1185
1285
|
|
|
1286
|
+
// const urls = {
|
|
1287
|
+
// loginUrl: "/auth/login", --> api_login
|
|
1288
|
+
// logoutUrl: "/auth/logout", --> api_logout
|
|
1289
|
+
// meUrl: "/auth/me", --> api_get_me_by_token
|
|
1290
|
+
// }
|
|
1291
|
+
|
|
1292
|
+
// const keysRemoveOnLogout = [TOKEN, "refreshToken", "user"];
|
|
1293
|
+
|
|
1186
1294
|
// wrapped all into:
|
|
1187
1295
|
// <DataProvider dataProvider={dataProvider}>
|
|
1188
1296
|
// <AuthProvider
|
|
1189
|
-
//
|
|
1297
|
+
// urls={urls} --> api_login
|
|
1190
1298
|
// tokenKey={TOKEN}
|
|
1191
|
-
//
|
|
1299
|
+
// keysCleanUpOnLogout={keysRemoveOnLogout} --> optional (default to ["token"]) - additional keys to clean up on logout
|
|
1192
1300
|
// >
|
|
1193
1301
|
// <App />
|
|
1194
1302
|
// </AuthProvider>
|