@kode-frontend/session-interceptor
Version:
Session interceptor for handling jwt token update flow
202 lines (196 loc) • 6.05 kB
JavaScript
;
var __typeError = (msg) => {
throw TypeError(msg);
};
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/headers-interceptor.ts
var startHeadersInterceptor = ({
getHeaders
}) => {
const getInterceptor = (instances) => {
const getOnRequest = (instance) => (config) => {
const headers = getHeaders({
config,
instance
});
headers.forEach((header) => config.headers[header.key] = header.value);
return config;
};
const ejectors = instances.map((instance) => {
const interceptor = instance.interceptors.request.use(
getOnRequest(instance)
);
return () => {
instance.interceptors.response.eject(interceptor);
};
});
const ejectAll = () => {
ejectors.forEach((eject) => {
eject();
});
};
return { ejectAll };
};
return getInterceptor;
};
// src/utils/subscribers.ts
var STORAGE_KEY = "SESSION_IS_ALLOW_TO_REFETCH";
var _Subscribers_instances, clear_fn, invokeAll_fn;
var Subscribers = class {
constructor({ storageGetter, storageSetter }) {
__privateAdd(this, _Subscribers_instances);
this.storageGetter = () => {
return "";
};
this.storageSetter = () => null;
this.$subscribers = [];
this.storageGetter = storageGetter;
this.storageSetter = storageSetter;
this.setAllowToRefetch(true);
}
subscribe(callback) {
this.$subscribers.push(callback);
}
startInvokes() {
setInterval(() => {
if (this.getAllowToRefetch() && this.$subscribers.length > 0) {
__privateMethod(this, _Subscribers_instances, invokeAll_fn).call(this);
__privateMethod(this, _Subscribers_instances, clear_fn).call(this);
}
}, 1e3);
}
getAllowToRefetch() {
return this.storageGetter(STORAGE_KEY) === "true" ? true : false;
}
setAllowToRefetch(payload) {
this.storageSetter(STORAGE_KEY, payload ? "true" : "false");
}
};
_Subscribers_instances = new WeakSet();
clear_fn = function() {
this.$subscribers = [];
};
invokeAll_fn = function() {
return this.$subscribers.forEach((cb) => cb());
};
// src/session-interceptor.ts
var startSessionInterceptor = ({
invalidAccessTokenErrors,
invalidRefreshTokenErrors,
storage,
tokensGetter,
onGotNewTokens,
onInvalidRefreshResponse,
onRefreshError,
onUnhandledError,
checkRefreshTokenInvalid,
checkAccessTokenInvalid
}) => {
const subscribers = new Subscribers(storage);
subscribers.startInvokes();
const getInterceptor = (instances) => {
const onSuccess = (request) => {
return request;
};
const getOnFailure = (instance) => (error) => __async(void 0, null, function* () {
const response = error == null ? void 0 : error.response;
if (!response) {
return Promise.reject(error);
}
let isNeedToRefreshTokens = false;
if (typeof checkAccessTokenInvalid === "function") {
isNeedToRefreshTokens = checkAccessTokenInvalid(response);
} else {
isNeedToRefreshTokens = Boolean(
invalidAccessTokenErrors.find(
(err) => err.status === response.status && err.code === response.data.code
)
);
}
let isRefreshTokenInvalid = false;
if (typeof checkRefreshTokenInvalid === "function") {
isRefreshTokenInvalid = checkRefreshTokenInvalid(response);
} else {
isRefreshTokenInvalid = Boolean(
invalidRefreshTokenErrors.find(
(err) => err.status === response.status && err.code === response.data.code
)
);
}
if (isRefreshTokenInvalid) {
onInvalidRefreshResponse();
return Promise.reject(error);
}
if (!isNeedToRefreshTokens) {
if (onUnhandledError) {
onUnhandledError(error);
}
return Promise.reject(error);
}
if (subscribers.getAllowToRefetch()) {
subscribers.setAllowToRefetch(false);
try {
const tokensResponse = yield tokensGetter();
if (tokensResponse == null ? void 0 : tokensResponse.accessToken) {
if (onGotNewTokens) {
onGotNewTokens(tokensResponse);
}
}
} catch (e) {
onRefreshError == null ? void 0 : onRefreshError();
return;
} finally {
subscribers.setAllowToRefetch(true);
}
}
return new Promise((resolve) => {
subscribers.subscribe(() => {
if (!error.config) {
return;
}
resolve(instance(error.config));
});
});
});
const ejectors = instances.map((instance) => {
const interceptor = instance.interceptors.response.use(
onSuccess,
getOnFailure(instance)
);
return () => {
instance.interceptors.response.eject(interceptor);
};
});
const ejectAll = () => {
ejectors.forEach((eject) => {
eject();
});
};
return { ejectAll };
};
return getInterceptor;
};
exports.startHeadersInterceptor = startHeadersInterceptor;
exports.startSessionInterceptor = startSessionInterceptor;