@j45/custom-axios
v2.0.0
Published
Shared axios factory for MFE domains
Downloads
215
Readme
@j45/custom-axios
Shared axios factory for MFE domains. Handles session expiry, relogin modal, concurrent 401 queuing, WAF detection, and token attachment.
Install
yarn install @j45/custom-axiosUsage
Minimal
// src/services/custom-axios.ts
import { createJ45Axios } from "@j45/custom-axios";
const customAxios = createJ45Axios({
baseURL: config.baseUrl ?? "",
});
export { customAxios };
export default customAxios;With all options
import { createJ45Axios } from "@j45/custom-axios";
const customAxios = createJ45Axios({
baseURL: config.baseUrl ?? "",
enableWafDetection: true,
refreshOnPaths: [
"workflow/company",
"transaction/statuses/counter",
],
});
export { customAxios };
export default customAxios;fallbackOnUnauthorized (per-request)
For services used by usePagination or callers without a custom onError
handler. Returns the fallback immediately with status: 200 on 401 so no
error modal appears behind the relogin modal.
const response = await customAxios.get("/transaction/external-transfer", {
params,
fallbackOnUnauthorized: {
data: [],
pageCount: "0",
totalPages: "0",
count: "0",
message: "",
},
});
return response.data;featureFlags (auto-persist into sessionStorage)
Pass featureFlags to have the library persist flag values from successful
responses into sessionStorage. For each name, a response whose URL contains
that name writes sessionStorage["<name>-flag"] = String(data?.data?.value ?? data?.value).
The keys are cleared again on a dashboard/root 401.
import { createJ45Axios } from "@j45/custom-axios";
const customAxios = createJ45Axios({
baseURL: config.baseUrl ?? "",
featureFlags: ["new-qlola"],
});
// e.g. GET /system/key/new-qlola → sessionStorage["new-qlola-flag"]
const isNewQlola = sessionStorage.getItem("new-qlola-flag") === "true";
export default customAxios;Adding domain-specific interceptors
createJ45Axios returns a standard axios instance — stack extra
interceptors on top:
import { createJ45Axios } from "@j45/custom-axios";
import { v4 as uuidv4 } from "uuid";
const customAxios = createJ45Axios({
baseURL: config.baseUrl ?? "",
});
customAxios.interceptors.request.use((config) => {
if (config.url?.includes("login")) {
config.headers["grpc-metadata-process_id"] = uuidv4();
}
return config;
});
export default customAxios;Configuration
| Option | Type | Default | Description |
|---|---|---|---|
| baseURL | string | required | API base URL |
| refreshOnPaths | string[] | [] | URL substrings where shouldRefresh: true is sent to the shell's showDialog |
| featureFlags | string[] | [] | Flag names to auto-persist from responses into sessionStorage["<name>-flag"] (cleared on dashboard/root 401) |
| enableWafDetection | boolean | false | Convert WAF HTML error pages to structured JSON errors |
| getToken | () => string \| null | localStorage["access-token"] | Override token source |
Architecture
@j45/custom-axios/
├── config.ts ← default baseUrl resolved per environment
└── src/
├── index.ts ← public API
├── types.ts ← J45AxiosConfig + axios augmentation
├── create-axios.ts ← factory
├── queue.ts ← per-instance queue state
├── interceptors/
│ ├── request-interceptors.ts ← Bearer token attachment
│ ├── waf-interceptors.ts ← WAF HTML → JSON conversion
│ └── auth-interceptors.ts ← 401 / 499 / Another Login handling
└── utils/
├── url-matchers.ts ← pathname helpers
└── env.ts ← hostname → environment baseUrl mappingInterceptor order
Outgoing: request-interceptors → server
Incoming: server → waf-interceptors → auth-interceptors → callerPer-instance isolation — each createJ45Axios() call produces an
independent axios instance with its own queue. A 401 in one MFE never
interferes with another.
Response branches
| Condition | Action |
|---|---|
| 401 on dashboard or root | Clear storage → redirect to /main-page |
| 401 on login URL | Pass through |
| 401 on retried request | Drain queue → reject |
| 401/499 + fallbackOnUnauthorized | Return fallback, open modal in background |
| 401/499 + modal already open | Queue caller, wait for token |
| 401/499 first occurrence | Open modal, suspend caller |
| Another Login Detected | Open modal, suspend caller |
| No response | Reject with 504 |
