@neog-cloud/neog-api-client 0.1.2 → 0.1.4
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/auth/AuthProvider.d.ts +2 -1
- package/dist/auth/options.d.ts +1 -0
- package/dist/auth/storage.d.ts +2 -5
- package/dist/auth/types.d.ts +25 -16
- package/dist/client/neogClient.d.ts +1 -0
- package/dist/index.cjs +118 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +24 -6
- package/dist/index.mjs +118 -13
- package/dist/index.mjs.map +1 -1
- package/dist/utils/apiUrlResolver.d.ts +4 -0
- package/package.json +2 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { AuthContextType, AuthState } from "./types";
|
|
2
|
+
import { AuthContextType, AuthState, UserInfo } from "./types";
|
|
3
3
|
import { NeogAuthOptions } from "./options";
|
|
4
4
|
export type AuthProviderFactory = {
|
|
5
5
|
AuthProvider: React.FC<{
|
|
@@ -7,6 +7,7 @@ export type AuthProviderFactory = {
|
|
|
7
7
|
}>;
|
|
8
8
|
useAuth: () => AuthContextType;
|
|
9
9
|
getToken: () => string | null;
|
|
10
|
+
getUser: () => UserInfo;
|
|
10
11
|
setToken: (token: string | null, refreshToken?: string | null, user?: AuthState["user"]) => void;
|
|
11
12
|
logout: () => void;
|
|
12
13
|
refreshAccessToken: () => Promise<string | null>;
|
package/dist/auth/options.d.ts
CHANGED
package/dist/auth/storage.d.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
+
import { UserInfo } from "./types";
|
|
1
2
|
export interface StoredAuthState {
|
|
2
3
|
accessToken: string | null;
|
|
3
4
|
refreshToken?: string | null;
|
|
4
5
|
expiresAt?: number | null;
|
|
5
|
-
user?:
|
|
6
|
-
id: string;
|
|
7
|
-
name?: string;
|
|
8
|
-
email?: string;
|
|
9
|
-
} | null;
|
|
6
|
+
user?: UserInfo;
|
|
10
7
|
}
|
|
11
8
|
export declare const saveAuthState: (storageKey: string, state: StoredAuthState) => void;
|
|
12
9
|
export declare const loadAuthState: (storageKey: string) => StoredAuthState | null;
|
package/dist/auth/types.d.ts
CHANGED
|
@@ -1,27 +1,40 @@
|
|
|
1
|
+
export type ApiLocation = {
|
|
2
|
+
host: string;
|
|
3
|
+
api_url: string;
|
|
4
|
+
};
|
|
5
|
+
export type NeogApiUrl = {
|
|
6
|
+
location?: ApiLocation[];
|
|
7
|
+
url?: string;
|
|
8
|
+
};
|
|
9
|
+
export type UserInfo = {
|
|
10
|
+
id?: string;
|
|
11
|
+
sub?: string;
|
|
12
|
+
name?: string;
|
|
13
|
+
email?: string;
|
|
14
|
+
preferred_username?: string;
|
|
15
|
+
given_name?: string;
|
|
16
|
+
family_name?: string;
|
|
17
|
+
comp_refid?: string;
|
|
18
|
+
permissions?: unknown;
|
|
19
|
+
neog_api_url?: NeogApiUrl;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
} | null;
|
|
1
22
|
export interface AuthContextType {
|
|
2
23
|
token: string | null;
|
|
3
24
|
refreshToken?: string | null;
|
|
4
|
-
user?:
|
|
5
|
-
id: string;
|
|
6
|
-
name?: string;
|
|
7
|
-
email?: string;
|
|
8
|
-
} | null;
|
|
25
|
+
user?: UserInfo;
|
|
9
26
|
isAuthenticated: boolean;
|
|
10
27
|
loading: boolean;
|
|
11
28
|
error?: string | null;
|
|
12
29
|
login: (username: string, password: string) => Promise<void>;
|
|
13
30
|
logout: () => void;
|
|
14
31
|
getToken: () => string | null;
|
|
15
|
-
setToken?: (token: string, refreshToken?: string) => void;
|
|
32
|
+
setToken?: (token: string | null, refreshToken?: string | null, user?: UserInfo) => void;
|
|
16
33
|
}
|
|
17
34
|
export type AuthState = {
|
|
18
35
|
token: string | null;
|
|
19
36
|
refreshToken?: string | null;
|
|
20
|
-
user?:
|
|
21
|
-
id: string;
|
|
22
|
-
name?: string;
|
|
23
|
-
email?: string;
|
|
24
|
-
} | null;
|
|
37
|
+
user?: UserInfo;
|
|
25
38
|
isAuthenticated: boolean;
|
|
26
39
|
};
|
|
27
40
|
export type TokenResponse = {
|
|
@@ -29,9 +42,5 @@ export type TokenResponse = {
|
|
|
29
42
|
refresh_token?: string;
|
|
30
43
|
expires_in?: number;
|
|
31
44
|
expires_at?: number;
|
|
32
|
-
user?:
|
|
33
|
-
id: string;
|
|
34
|
-
name?: string;
|
|
35
|
-
email?: string;
|
|
36
|
-
} | null;
|
|
45
|
+
user?: UserInfo;
|
|
37
46
|
};
|
|
@@ -5,6 +5,7 @@ export type GetTokenHandler = () => string | null;
|
|
|
5
5
|
export type LogoutHandler = () => void;
|
|
6
6
|
export type CreateClientDeps = {
|
|
7
7
|
baseUrl: string;
|
|
8
|
+
baseUrlResolver?: () => string;
|
|
8
9
|
getToken: GetTokenHandler;
|
|
9
10
|
refreshToken: RefreshTokenHandler;
|
|
10
11
|
logout: LogoutHandler;
|
package/dist/index.cjs
CHANGED
|
@@ -1391,6 +1391,8 @@ const getErrorMessage = (error, fallback = "Erro ao processar a requisição") =
|
|
|
1391
1391
|
return fallback;
|
|
1392
1392
|
};
|
|
1393
1393
|
|
|
1394
|
+
const USERINFO_ERROR_MESSAGE = "Nao foi possivel carregar dados do usuario";
|
|
1395
|
+
const USERINFO_RETRY_DELAY_MS = 500;
|
|
1394
1396
|
const resolveExpiresAt = (data) => {
|
|
1395
1397
|
if (data.expires_at)
|
|
1396
1398
|
return data.expires_at;
|
|
@@ -1398,18 +1400,24 @@ const resolveExpiresAt = (data) => {
|
|
|
1398
1400
|
return Date.now() + data.expires_in * 1000;
|
|
1399
1401
|
return null;
|
|
1400
1402
|
};
|
|
1403
|
+
const resolveEndpoint = (template, realm) => {
|
|
1404
|
+
if (!realm)
|
|
1405
|
+
return template;
|
|
1406
|
+
return template.replace("{realm}", realm).replace(":realm", realm);
|
|
1407
|
+
};
|
|
1401
1408
|
const createAuthProvider = (options) => {
|
|
1402
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1409
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
1403
1410
|
const storageKey = (_a = options.storageKey) !== null && _a !== void 0 ? _a : "neog_auth";
|
|
1404
1411
|
const authBaseUrl = (_b = options.authBaseUrl) !== null && _b !== void 0 ? _b : options.baseUrl;
|
|
1405
1412
|
const authRequestFormat = (_c = options.authRequestFormat) !== null && _c !== void 0 ? _c : "form";
|
|
1406
1413
|
const authGrantType = (_d = options.authGrantType) !== null && _d !== void 0 ? _d : "password";
|
|
1407
1414
|
const authScope = (_e = options.authScope) !== null && _e !== void 0 ? _e : "openid profile email";
|
|
1415
|
+
const userInfoEndpoint = (_f = options.userInfoEndpoint) !== null && _f !== void 0 ? _f : "/realms/{realm}/protocol/openid-connect/userinfo";
|
|
1408
1416
|
const stored = loadAuthState(storageKey);
|
|
1409
1417
|
const initialState = {
|
|
1410
|
-
token: (
|
|
1411
|
-
refreshToken: (
|
|
1412
|
-
user: (
|
|
1418
|
+
token: (_g = stored === null || stored === void 0 ? void 0 : stored.accessToken) !== null && _g !== void 0 ? _g : null,
|
|
1419
|
+
refreshToken: (_h = stored === null || stored === void 0 ? void 0 : stored.refreshToken) !== null && _h !== void 0 ? _h : null,
|
|
1420
|
+
user: (_j = stored === null || stored === void 0 ? void 0 : stored.user) !== null && _j !== void 0 ? _j : null,
|
|
1413
1421
|
isAuthenticated: Boolean(stored === null || stored === void 0 ? void 0 : stored.accessToken),
|
|
1414
1422
|
};
|
|
1415
1423
|
const AuthContext = require$$0.createContext(undefined);
|
|
@@ -1427,6 +1435,7 @@ const createAuthProvider = (options) => {
|
|
|
1427
1435
|
saveAuthState(storageKey, payload);
|
|
1428
1436
|
};
|
|
1429
1437
|
const getToken = () => authRef.current.token;
|
|
1438
|
+
const getUser = () => { var _a; return (_a = authRef.current.user) !== null && _a !== void 0 ? _a : null; };
|
|
1430
1439
|
const setToken = (token, refreshToken, user) => {
|
|
1431
1440
|
var _a, _b, _c, _d, _e;
|
|
1432
1441
|
authRef.current = {
|
|
@@ -1444,6 +1453,32 @@ const createAuthProvider = (options) => {
|
|
|
1444
1453
|
clearAuthState(storageKey);
|
|
1445
1454
|
(_a = stateSetterRef.current) === null || _a === void 0 ? void 0 : _a.call(stateSetterRef, authRef.current);
|
|
1446
1455
|
};
|
|
1456
|
+
const fetchUserInfo = async (accessToken) => {
|
|
1457
|
+
var _a, _b;
|
|
1458
|
+
const endpoint = resolveEndpoint(userInfoEndpoint, options.authRealm);
|
|
1459
|
+
const url = `${authBaseUrl}${endpoint}`;
|
|
1460
|
+
try {
|
|
1461
|
+
const response = await axios.get(url, {
|
|
1462
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
1463
|
+
timeout: options.requestTimeoutMs,
|
|
1464
|
+
});
|
|
1465
|
+
return response.data;
|
|
1466
|
+
}
|
|
1467
|
+
catch (err) {
|
|
1468
|
+
const message = getErrorMessage(err, "Falha ao carregar userinfo");
|
|
1469
|
+
const status = axios.isAxiosError(err) ? (_a = err.response) === null || _a === void 0 ? void 0 : _a.status : undefined;
|
|
1470
|
+
(_b = options.onErrorLog) === null || _b === void 0 ? void 0 : _b.call(options, { url, status, message });
|
|
1471
|
+
return null;
|
|
1472
|
+
}
|
|
1473
|
+
};
|
|
1474
|
+
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
1475
|
+
const fetchUserInfoWithRetry = async (accessToken) => {
|
|
1476
|
+
const info = await fetchUserInfo(accessToken);
|
|
1477
|
+
if (info)
|
|
1478
|
+
return info;
|
|
1479
|
+
await wait(USERINFO_RETRY_DELAY_MS);
|
|
1480
|
+
return fetchUserInfo(accessToken);
|
|
1481
|
+
};
|
|
1447
1482
|
const refreshAccessToken = async () => {
|
|
1448
1483
|
if (!options.tokenRefreshEndpoint)
|
|
1449
1484
|
return null;
|
|
@@ -1565,8 +1600,36 @@ const createAuthProvider = (options) => {
|
|
|
1565
1600
|
}
|
|
1566
1601
|
void handleRefreshIfExpired();
|
|
1567
1602
|
}, [handleRefreshIfExpired]);
|
|
1603
|
+
require$$0.useEffect(() => {
|
|
1604
|
+
if (!state.token || state.user)
|
|
1605
|
+
return;
|
|
1606
|
+
let cancelled = false;
|
|
1607
|
+
void (async () => {
|
|
1608
|
+
var _a, _b;
|
|
1609
|
+
const info = await fetchUserInfoWithRetry(state.token);
|
|
1610
|
+
if (cancelled)
|
|
1611
|
+
return;
|
|
1612
|
+
if (!info) {
|
|
1613
|
+
handleLogout();
|
|
1614
|
+
if (isMounted.current) {
|
|
1615
|
+
setError(USERINFO_ERROR_MESSAGE);
|
|
1616
|
+
}
|
|
1617
|
+
return;
|
|
1618
|
+
}
|
|
1619
|
+
const nextState = {
|
|
1620
|
+
token: authRef.current.token,
|
|
1621
|
+
refreshToken: authRef.current.refreshToken,
|
|
1622
|
+
user: info,
|
|
1623
|
+
isAuthenticated: Boolean(authRef.current.token),
|
|
1624
|
+
};
|
|
1625
|
+
syncState(nextState, (_b = (_a = loadAuthState(storageKey)) === null || _a === void 0 ? void 0 : _a.expiresAt) !== null && _b !== void 0 ? _b : null);
|
|
1626
|
+
})();
|
|
1627
|
+
return () => {
|
|
1628
|
+
cancelled = true;
|
|
1629
|
+
};
|
|
1630
|
+
}, [state.token, state.user, syncState, handleLogout]);
|
|
1568
1631
|
const login = require$$0.useCallback(async (username, password) => {
|
|
1569
|
-
var _a, _b
|
|
1632
|
+
var _a, _b;
|
|
1570
1633
|
setLoading(true);
|
|
1571
1634
|
setError(null);
|
|
1572
1635
|
try {
|
|
@@ -1600,7 +1663,13 @@ const createAuthProvider = (options) => {
|
|
|
1600
1663
|
const token = data.access_token;
|
|
1601
1664
|
const refreshToken = (_b = data.refresh_token) !== null && _b !== void 0 ? _b : null;
|
|
1602
1665
|
const expiresAt = resolveExpiresAt(data);
|
|
1603
|
-
const
|
|
1666
|
+
const userInfo = token ? await fetchUserInfoWithRetry(token) : null;
|
|
1667
|
+
if (token && !userInfo) {
|
|
1668
|
+
handleLogout();
|
|
1669
|
+
setError(USERINFO_ERROR_MESSAGE);
|
|
1670
|
+
throw new Error(USERINFO_ERROR_MESSAGE);
|
|
1671
|
+
}
|
|
1672
|
+
const user = userInfo !== null && userInfo !== void 0 ? userInfo : null;
|
|
1604
1673
|
const nextState = {
|
|
1605
1674
|
token,
|
|
1606
1675
|
refreshToken,
|
|
@@ -1629,6 +1698,7 @@ const createAuthProvider = (options) => {
|
|
|
1629
1698
|
authRequestFormat,
|
|
1630
1699
|
authGrantType,
|
|
1631
1700
|
authScope,
|
|
1701
|
+
handleLogout,
|
|
1632
1702
|
]);
|
|
1633
1703
|
const contextValue = require$$0.useMemo(() => {
|
|
1634
1704
|
var _a, _b;
|
|
@@ -1642,12 +1712,12 @@ const createAuthProvider = (options) => {
|
|
|
1642
1712
|
login,
|
|
1643
1713
|
logout: handleLogout,
|
|
1644
1714
|
getToken: () => authRef.current.token,
|
|
1645
|
-
setToken: (token, refreshToken) => {
|
|
1715
|
+
setToken: (token, refreshToken, user) => {
|
|
1646
1716
|
var _a, _b, _c;
|
|
1647
1717
|
const nextState = {
|
|
1648
1718
|
token,
|
|
1649
1719
|
refreshToken: refreshToken !== null && refreshToken !== void 0 ? refreshToken : null,
|
|
1650
|
-
user: (_a = authRef.current.user) !== null && _a !== void 0 ? _a : null,
|
|
1720
|
+
user: (_a = user !== null && user !== void 0 ? user : authRef.current.user) !== null && _a !== void 0 ? _a : null,
|
|
1651
1721
|
isAuthenticated: Boolean(token),
|
|
1652
1722
|
};
|
|
1653
1723
|
syncState(nextState, (_c = (_b = loadAuthState(storageKey)) === null || _b === void 0 ? void 0 : _b.expiresAt) !== null && _c !== void 0 ? _c : null);
|
|
@@ -1667,6 +1737,7 @@ const createAuthProvider = (options) => {
|
|
|
1667
1737
|
AuthProvider,
|
|
1668
1738
|
useAuth,
|
|
1669
1739
|
getToken,
|
|
1740
|
+
getUser,
|
|
1670
1741
|
setToken,
|
|
1671
1742
|
logout,
|
|
1672
1743
|
refreshAccessToken,
|
|
@@ -1689,7 +1760,7 @@ const shouldRetry = (config) => {
|
|
|
1689
1760
|
const createNeogClient = (deps, opts) => {
|
|
1690
1761
|
var _a;
|
|
1691
1762
|
const instance = axios.create({
|
|
1692
|
-
baseURL: deps.baseUrl,
|
|
1763
|
+
baseURL: deps.baseUrlResolver ? deps.baseUrlResolver() : deps.baseUrl,
|
|
1693
1764
|
timeout: (_a = opts === null || opts === void 0 ? void 0 : opts.timeoutMs) !== null && _a !== void 0 ? _a : deps.requestTimeoutMs,
|
|
1694
1765
|
headers: {
|
|
1695
1766
|
...deps.defaultHeaders,
|
|
@@ -1697,13 +1768,16 @@ const createNeogClient = (deps, opts) => {
|
|
|
1697
1768
|
},
|
|
1698
1769
|
});
|
|
1699
1770
|
instance.interceptors.request.use((config) => {
|
|
1700
|
-
var _a, _b;
|
|
1771
|
+
var _a, _b, _c;
|
|
1772
|
+
if (deps.baseUrlResolver) {
|
|
1773
|
+
config.baseURL = (_a = deps.baseUrlResolver()) !== null && _a !== void 0 ? _a : deps.baseUrl;
|
|
1774
|
+
}
|
|
1701
1775
|
if (config.url && config.method) {
|
|
1702
|
-
(
|
|
1776
|
+
(_b = deps.onRequestLog) === null || _b === void 0 ? void 0 : _b.call(deps, { url: config.url, method: config.method });
|
|
1703
1777
|
}
|
|
1704
1778
|
const token = deps.getToken();
|
|
1705
1779
|
if (token) {
|
|
1706
|
-
const headers = axios.AxiosHeaders.from(((
|
|
1780
|
+
const headers = axios.AxiosHeaders.from(((_c = config.headers) !== null && _c !== void 0 ? _c : {}));
|
|
1707
1781
|
headers.set("Authorization", `Bearer ${token}`);
|
|
1708
1782
|
config.headers = headers;
|
|
1709
1783
|
}
|
|
@@ -1764,10 +1838,41 @@ const createNeogClient = (deps, opts) => {
|
|
|
1764
1838
|
};
|
|
1765
1839
|
};
|
|
1766
1840
|
|
|
1841
|
+
const getHostname = () => {
|
|
1842
|
+
if (typeof window === "undefined")
|
|
1843
|
+
return null;
|
|
1844
|
+
return window.location.hostname;
|
|
1845
|
+
};
|
|
1846
|
+
const getApiUrl = (user, defaultUrl) => {
|
|
1847
|
+
try {
|
|
1848
|
+
if (!(user === null || user === void 0 ? void 0 : user.neog_api_url)) {
|
|
1849
|
+
return defaultUrl;
|
|
1850
|
+
}
|
|
1851
|
+
const currentHostname = getHostname();
|
|
1852
|
+
if (currentHostname && Array.isArray(user.neog_api_url.location)) {
|
|
1853
|
+
const matchingLocation = user.neog_api_url.location.find((location) => location.host === currentHostname);
|
|
1854
|
+
if (matchingLocation === null || matchingLocation === void 0 ? void 0 : matchingLocation.api_url) {
|
|
1855
|
+
return matchingLocation.api_url;
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
if (user.neog_api_url.url) {
|
|
1859
|
+
return user.neog_api_url.url;
|
|
1860
|
+
}
|
|
1861
|
+
return defaultUrl;
|
|
1862
|
+
}
|
|
1863
|
+
catch (error) {
|
|
1864
|
+
if (typeof console !== "undefined") {
|
|
1865
|
+
console.warn("Error determining API URL, using default:", error);
|
|
1866
|
+
}
|
|
1867
|
+
return defaultUrl;
|
|
1868
|
+
}
|
|
1869
|
+
};
|
|
1870
|
+
|
|
1767
1871
|
function createNeogAuth(options) {
|
|
1768
|
-
const { AuthProvider, useAuth, getToken, logout, refreshAccessToken } = createAuthProvider(options);
|
|
1872
|
+
const { AuthProvider, useAuth, getToken, getUser, logout, refreshAccessToken } = createAuthProvider(options);
|
|
1769
1873
|
const createNeogClient$1 = (opts) => createNeogClient({
|
|
1770
1874
|
baseUrl: options.baseUrl,
|
|
1875
|
+
baseUrlResolver: () => getApiUrl(getUser(), options.baseUrl),
|
|
1771
1876
|
getToken,
|
|
1772
1877
|
refreshToken: refreshAccessToken,
|
|
1773
1878
|
logout,
|