@krainovsd/js-helpers 0.19.0-beta.1 → 0.19.0-beta.11
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/lib/cjs/index.cjs +128 -57
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/esm/api/api.constants.js +8 -7
- package/lib/esm/api/api.constants.js.map +1 -1
- package/lib/esm/api/api.js +29 -18
- package/lib/esm/api/api.js.map +1 -1
- package/lib/esm/api/oauth.js +92 -32
- package/lib/esm/api/oauth.js.map +1 -1
- package/lib/index.d.ts +27 -14
- package/package.json +1 -1
package/lib/cjs/index.cjs
CHANGED
|
@@ -1757,13 +1757,14 @@ function throttle(func, interval) {
|
|
|
1757
1757
|
|
|
1758
1758
|
const RESPONSE_DATA_SYMBOL = Symbol("response data");
|
|
1759
1759
|
const REQUEST_ERROR = {
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1760
|
+
Http: "http",
|
|
1761
|
+
Network: "network",
|
|
1762
|
+
Timeout: "timeout",
|
|
1763
|
+
Abort: "abort",
|
|
1764
|
+
Validation: "validation",
|
|
1765
|
+
Cache: "cache",
|
|
1766
|
+
Unknown: "unknown",
|
|
1767
|
+
Disabled: "disabled",
|
|
1767
1768
|
};
|
|
1768
1769
|
class OauthState {
|
|
1769
1770
|
_fetching = false;
|
|
@@ -1789,6 +1790,7 @@ function createFetchClient(options) {
|
|
|
1789
1790
|
let retries = options.retries;
|
|
1790
1791
|
let timeout = options.timeout;
|
|
1791
1792
|
let refetchAfterAuthGlobal = options.refetchAfterAuth;
|
|
1793
|
+
let enabled = options.enabled ?? true;
|
|
1792
1794
|
function recreate(options) {
|
|
1793
1795
|
if ("client" in options) {
|
|
1794
1796
|
client = options.client;
|
|
@@ -1808,8 +1810,18 @@ function createFetchClient(options) {
|
|
|
1808
1810
|
if ("refetchAfterAuth" in options) {
|
|
1809
1811
|
refetchAfterAuthGlobal = options.refetchAfterAuth;
|
|
1810
1812
|
}
|
|
1813
|
+
if ("enabled" in options) {
|
|
1814
|
+
enabled = options.enabled ?? true;
|
|
1815
|
+
}
|
|
1811
1816
|
}
|
|
1812
1817
|
async function handleRequest(request) {
|
|
1818
|
+
if (!enabled) {
|
|
1819
|
+
return {
|
|
1820
|
+
response: null,
|
|
1821
|
+
data: new ResponseError({ message: "requests disabled", status: 0 }),
|
|
1822
|
+
error: REQUEST_ERROR.Disabled,
|
|
1823
|
+
};
|
|
1824
|
+
}
|
|
1813
1825
|
const timeoutController = new AbortController();
|
|
1814
1826
|
const requestController = new AbortController();
|
|
1815
1827
|
const requestTimeout = request.timeout ?? timeout;
|
|
@@ -1918,12 +1930,12 @@ function createFetchClient(options) {
|
|
|
1918
1930
|
if (!response.ok) {
|
|
1919
1931
|
if (response.status === 304) {
|
|
1920
1932
|
const error = new ResponseError({
|
|
1921
|
-
message: REQUEST_ERROR.
|
|
1933
|
+
message: REQUEST_ERROR.Cache,
|
|
1922
1934
|
status: response.status,
|
|
1923
1935
|
headers: Object.fromEntries(response.headers.entries()),
|
|
1924
1936
|
});
|
|
1925
|
-
request.onError?.(REQUEST_ERROR.
|
|
1926
|
-
return { data: error, error: REQUEST_ERROR.
|
|
1937
|
+
request.onError?.(REQUEST_ERROR.Cache, error);
|
|
1938
|
+
return { data: error, error: REQUEST_ERROR.Cache, response };
|
|
1927
1939
|
}
|
|
1928
1940
|
/** if you need observe other than only 401 status, you can override some statuses in after handler middleware to 401 */
|
|
1929
1941
|
if (response.status === 401 && refetchAfterAuth) {
|
|
@@ -1966,14 +1978,14 @@ function createFetchClient(options) {
|
|
|
1966
1978
|
catch { }
|
|
1967
1979
|
const error = new ResponseError({
|
|
1968
1980
|
status: response.status,
|
|
1969
|
-
message: REQUEST_ERROR.
|
|
1981
|
+
message: REQUEST_ERROR.Http,
|
|
1970
1982
|
description: result,
|
|
1971
1983
|
headers: Object.fromEntries(response.headers.entries()),
|
|
1972
1984
|
});
|
|
1973
|
-
request.onError?.(REQUEST_ERROR.
|
|
1985
|
+
request.onError?.(REQUEST_ERROR.Http, error);
|
|
1974
1986
|
return {
|
|
1975
1987
|
data: error,
|
|
1976
|
-
error: REQUEST_ERROR.
|
|
1988
|
+
error: REQUEST_ERROR.Http,
|
|
1977
1989
|
response,
|
|
1978
1990
|
};
|
|
1979
1991
|
}
|
|
@@ -2042,36 +2054,36 @@ function createFetchClient(options) {
|
|
|
2042
2054
|
}
|
|
2043
2055
|
if (err instanceof TypeError) {
|
|
2044
2056
|
const error = new ResponseError({
|
|
2045
|
-
message: REQUEST_ERROR.
|
|
2057
|
+
message: REQUEST_ERROR.Network,
|
|
2046
2058
|
status: 0,
|
|
2047
2059
|
description: String(err.message),
|
|
2048
2060
|
});
|
|
2049
|
-
request.onError?.(REQUEST_ERROR.
|
|
2050
|
-
return { data: error, error: REQUEST_ERROR.
|
|
2061
|
+
request.onError?.(REQUEST_ERROR.Network, error);
|
|
2062
|
+
return { data: error, error: REQUEST_ERROR.Network, response: null };
|
|
2051
2063
|
}
|
|
2052
2064
|
if (err instanceof Error && err.name === "AbortError") {
|
|
2053
2065
|
if (timeoutController.signal.aborted) {
|
|
2054
2066
|
const error = new ResponseError({
|
|
2055
|
-
message: REQUEST_ERROR.
|
|
2067
|
+
message: REQUEST_ERROR.Timeout,
|
|
2056
2068
|
status: 0,
|
|
2057
2069
|
});
|
|
2058
|
-
request.onError?.(REQUEST_ERROR.
|
|
2059
|
-
return { data: error, error: REQUEST_ERROR.
|
|
2070
|
+
request.onError?.(REQUEST_ERROR.Timeout, error);
|
|
2071
|
+
return { data: error, error: REQUEST_ERROR.Timeout, response: null };
|
|
2060
2072
|
}
|
|
2061
2073
|
const error = new ResponseError({
|
|
2062
|
-
message: REQUEST_ERROR.
|
|
2074
|
+
message: REQUEST_ERROR.Abort,
|
|
2063
2075
|
status: 0,
|
|
2064
2076
|
});
|
|
2065
|
-
request.onError?.(REQUEST_ERROR.
|
|
2066
|
-
return { data: error, error: REQUEST_ERROR.
|
|
2077
|
+
request.onError?.(REQUEST_ERROR.Abort, error);
|
|
2078
|
+
return { data: error, error: REQUEST_ERROR.Abort, response: null };
|
|
2067
2079
|
}
|
|
2068
2080
|
const error = new ResponseError({
|
|
2069
|
-
message: REQUEST_ERROR.
|
|
2081
|
+
message: REQUEST_ERROR.Unknown,
|
|
2070
2082
|
status: 0,
|
|
2071
2083
|
description: String(err),
|
|
2072
2084
|
});
|
|
2073
|
-
request.onError?.(REQUEST_ERROR.
|
|
2074
|
-
return { data: error, error: REQUEST_ERROR.
|
|
2085
|
+
request.onError?.(REQUEST_ERROR.Unknown, error);
|
|
2086
|
+
return { data: error, error: REQUEST_ERROR.Unknown, response: null };
|
|
2075
2087
|
}
|
|
2076
2088
|
finally {
|
|
2077
2089
|
requestController.abort();
|
|
@@ -2112,18 +2124,51 @@ function executeAfterHandlers(handlers, request, response) {
|
|
|
2112
2124
|
}
|
|
2113
2125
|
|
|
2114
2126
|
function createOauthProvider(opts = {}) {
|
|
2115
|
-
const { refreshTokenWindowUrl = window.origin, closeObserveSubWindowInterval = 500, waitSubWindow =
|
|
2127
|
+
const { refreshTokenWindowUrl = window.origin, closeObserveSubWindowInterval = 500, waitSubWindow = 15000, loginUrl = undefined, logoutUrl = undefined, clearPageUrl = OAUTH_CLEAR_PAGE_URL, errorPageUrl = OAUTH_ERROR_PAGE_URL, logoutPageUrl = OAUTH_LOGOUT_PAGE_URL, afterClearPageUrl = "/", expiresTokenQueryName = OAUTH_TOKEN_EXPIRES_STORAGE_NAME, tokenStorageName = OAUTH_TOKEN_STORAGE_NAME, expiresTokenStorageName = OAUTH_TOKEN_EXPIRES_STORAGE_NAME, tokenRequest = undefined, forceSetToken = false, subWindow = true, refreshToken = false, } = opts;
|
|
2116
2128
|
let processing = false;
|
|
2129
|
+
function getExpiresDate(expires) {
|
|
2130
|
+
return Date.now() + (expires - 30) * 1000;
|
|
2131
|
+
}
|
|
2132
|
+
function checkExpires(expires) {
|
|
2133
|
+
return expires != undefined && !Number.isNaN(+expires) && Date.now() < +expires;
|
|
2134
|
+
}
|
|
2117
2135
|
async function refetchAfterRefreshFlow(request) {
|
|
2118
2136
|
if (processing) {
|
|
2119
|
-
await
|
|
2137
|
+
await beforeHandlerSetToken(request);
|
|
2138
|
+
return request;
|
|
2139
|
+
}
|
|
2140
|
+
processing = true;
|
|
2141
|
+
if (refreshToken && tokenRequest) {
|
|
2142
|
+
const tokenInfo = await startRefreshFlow();
|
|
2143
|
+
if (tokenInfo == undefined) {
|
|
2144
|
+
if (subWindow) {
|
|
2145
|
+
await startLoginFlowInSubWindow();
|
|
2146
|
+
}
|
|
2147
|
+
else {
|
|
2148
|
+
await startLoginFlow();
|
|
2149
|
+
}
|
|
2150
|
+
processing = false;
|
|
2151
|
+
await beforeHandlerSetToken(request);
|
|
2152
|
+
return request;
|
|
2153
|
+
}
|
|
2154
|
+
processing = false;
|
|
2155
|
+
await beforeHandlerSetToken(request);
|
|
2120
2156
|
return request;
|
|
2121
2157
|
}
|
|
2122
|
-
|
|
2123
|
-
|
|
2158
|
+
if (subWindow) {
|
|
2159
|
+
await startLoginFlowInSubWindow();
|
|
2160
|
+
}
|
|
2161
|
+
else {
|
|
2162
|
+
await startLoginFlow();
|
|
2163
|
+
}
|
|
2164
|
+
processing = false;
|
|
2165
|
+
await beforeHandlerSetToken(request);
|
|
2124
2166
|
return request;
|
|
2125
2167
|
}
|
|
2126
|
-
|
|
2168
|
+
function isServicePageCheck() {
|
|
2169
|
+
return [errorPageUrl, clearPageUrl, logoutPageUrl].some((u) => document.location.pathname === u);
|
|
2170
|
+
}
|
|
2171
|
+
async function startLoginFlowInSubWindow() {
|
|
2127
2172
|
processing = true;
|
|
2128
2173
|
let waiting = true;
|
|
2129
2174
|
const url = new URL(typeof refreshTokenWindowUrl === "function" ? refreshTokenWindowUrl() : refreshTokenWindowUrl);
|
|
@@ -2165,7 +2210,7 @@ function createOauthProvider(opts = {}) {
|
|
|
2165
2210
|
if ("onSubWindowOpenError" in opts)
|
|
2166
2211
|
opts.onSubWindowOpenError?.();
|
|
2167
2212
|
else {
|
|
2168
|
-
startLoginFlow();
|
|
2213
|
+
await startLoginFlow();
|
|
2169
2214
|
}
|
|
2170
2215
|
waiting = false;
|
|
2171
2216
|
return;
|
|
@@ -2174,21 +2219,34 @@ function createOauthProvider(opts = {}) {
|
|
|
2174
2219
|
processing = false;
|
|
2175
2220
|
}
|
|
2176
2221
|
// Trigger an oauth flow through some proxy server
|
|
2177
|
-
function startLoginFlow(loginUrlArg = loginUrl) {
|
|
2222
|
+
async function startLoginFlow(loginUrlArg = loginUrl, delay = 2000) {
|
|
2178
2223
|
loginUrlArg ??= `/api/v1/auth?frontend_protocol=${window.location.protocol.replace(":", "")}&frontend_host=${window.location.host}&comeback_path=${window.location.pathname}${encodeURIComponent(window.location.search)}`;
|
|
2179
2224
|
window.location.replace(typeof loginUrlArg === "function" ? loginUrlArg() : loginUrlArg);
|
|
2225
|
+
await wait(delay);
|
|
2180
2226
|
return null;
|
|
2181
2227
|
}
|
|
2182
2228
|
// Trigger an oauth flow through some proxy server
|
|
2183
|
-
function startLogoutFlow(logoutUrlArg = logoutUrl) {
|
|
2184
|
-
logoutUrlArg ??= `/api/v1/auth/logout?frontend_protocol=${window.location.protocol.replace(":", "")}&frontend_host=${window.location.host}
|
|
2229
|
+
async function startLogoutFlow(logoutUrlArg = logoutUrl, delay = 2000) {
|
|
2230
|
+
logoutUrlArg ??= `/api/v1/auth/logout?frontend_protocol=${window.location.protocol.replace(":", "")}&frontend_host=${window.location.host}`;
|
|
2185
2231
|
window.location.replace(typeof logoutUrlArg === "function" ? logoutUrlArg() : logoutUrlArg);
|
|
2232
|
+
await wait(delay);
|
|
2186
2233
|
return null;
|
|
2187
2234
|
}
|
|
2235
|
+
async function startRefreshFlow() {
|
|
2236
|
+
const tokenInfo = await tokenRequest?.();
|
|
2237
|
+
if (tokenInfo) {
|
|
2238
|
+
localStorage.setItem(tokenStorageName, tokenInfo.token);
|
|
2239
|
+
if (tokenInfo.expires !== 0) {
|
|
2240
|
+
tokenInfo.expires = getExpiresDate(tokenInfo.expires);
|
|
2241
|
+
localStorage.setItem(expiresTokenStorageName, String(tokenInfo.expires));
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
return tokenInfo;
|
|
2245
|
+
}
|
|
2188
2246
|
// Processing an oauth flow: extract expires, get token, close sub windows, check if logout/clear/error url
|
|
2189
2247
|
async function register() {
|
|
2190
2248
|
if (window.location.pathname === logoutPageUrl) {
|
|
2191
|
-
startLogoutFlow();
|
|
2249
|
+
await startLogoutFlow();
|
|
2192
2250
|
return false;
|
|
2193
2251
|
}
|
|
2194
2252
|
if (window.location.pathname === clearPageUrl) {
|
|
@@ -2212,30 +2270,29 @@ function createOauthProvider(opts = {}) {
|
|
|
2212
2270
|
? refreshQuery[refreshQuery.length - 1] === "true"
|
|
2213
2271
|
: false;
|
|
2214
2272
|
/** Expires token */
|
|
2215
|
-
const
|
|
2273
|
+
const expiresStr = isString(expiresQuery)
|
|
2216
2274
|
? expiresQuery
|
|
2217
2275
|
: isArray(expiresQuery)
|
|
2218
2276
|
? expiresQuery[expiresQuery.length - 1]
|
|
2219
|
-
:
|
|
2220
|
-
|
|
2221
|
-
|
|
2277
|
+
: null;
|
|
2278
|
+
const expires = expiresStr ? getExpiresDate(+expiresStr) : null;
|
|
2279
|
+
if (checkExpires(expires)) {
|
|
2280
|
+
localStorage.setItem(expiresTokenStorageName, String(expires));
|
|
2222
2281
|
if (tokenRequest) {
|
|
2223
|
-
const
|
|
2224
|
-
if (
|
|
2225
|
-
localStorage.setItem(tokenStorageName, token);
|
|
2282
|
+
const tokenInfo = await tokenRequest();
|
|
2283
|
+
if (tokenInfo != undefined) {
|
|
2284
|
+
localStorage.setItem(tokenStorageName, tokenInfo.token);
|
|
2226
2285
|
}
|
|
2227
2286
|
}
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
/** Delete expires query */
|
|
2238
|
-
if (expires) {
|
|
2287
|
+
/** Close if OnlyRefresh window */
|
|
2288
|
+
if (isRefresh) {
|
|
2289
|
+
const channel = new BroadcastChannel(OAUTH_REFRESH_QUERY);
|
|
2290
|
+
channel.postMessage(true);
|
|
2291
|
+
channel.close();
|
|
2292
|
+
window.close();
|
|
2293
|
+
return false;
|
|
2294
|
+
}
|
|
2295
|
+
/** Delete expires query */
|
|
2239
2296
|
const url = new URL(window.location.href);
|
|
2240
2297
|
url.searchParams.delete(expiresTokenQueryName);
|
|
2241
2298
|
window.location.replace(url.toString());
|
|
@@ -2243,7 +2300,16 @@ function createOauthProvider(opts = {}) {
|
|
|
2243
2300
|
}
|
|
2244
2301
|
return true;
|
|
2245
2302
|
}
|
|
2246
|
-
async function
|
|
2303
|
+
async function beforeHandlerCheckExpires(request) {
|
|
2304
|
+
if (isServicePageCheck())
|
|
2305
|
+
return;
|
|
2306
|
+
const expires = localStorage.getItem(expiresTokenStorageName);
|
|
2307
|
+
if (checkExpires(expires)) {
|
|
2308
|
+
return;
|
|
2309
|
+
}
|
|
2310
|
+
await refetchAfterRefreshFlow(request);
|
|
2311
|
+
}
|
|
2312
|
+
async function beforeHandlerSetToken(request) {
|
|
2247
2313
|
if (processing)
|
|
2248
2314
|
await waitUntil(() => processing);
|
|
2249
2315
|
const token = request.token ?? localStorage.getItem(tokenStorageName);
|
|
@@ -2255,12 +2321,17 @@ function createOauthProvider(opts = {}) {
|
|
|
2255
2321
|
};
|
|
2256
2322
|
}
|
|
2257
2323
|
return {
|
|
2258
|
-
|
|
2324
|
+
startRefreshFlow,
|
|
2325
|
+
startLoginFlowInSubWindow,
|
|
2259
2326
|
startLoginFlow,
|
|
2260
2327
|
startLogoutFlow,
|
|
2261
|
-
register,
|
|
2262
2328
|
refetchAfterRefreshFlow,
|
|
2263
|
-
|
|
2329
|
+
beforeHandlerSetToken,
|
|
2330
|
+
beforeHandlerCheckExpires,
|
|
2331
|
+
register,
|
|
2332
|
+
get isServicePage() {
|
|
2333
|
+
return isServicePageCheck();
|
|
2334
|
+
},
|
|
2264
2335
|
get processing() {
|
|
2265
2336
|
return processing;
|
|
2266
2337
|
},
|