mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-06 10:02:04 +00:00
refactor(api): extract shared API prefix URL resolution
This commit is contained in:
parent
503aefa09a
commit
b0ce047154
3 changed files with 40 additions and 23 deletions
|
|
@ -1,28 +1,12 @@
|
||||||
import ky, { type HTTPError, type KyInstance, type Options } from "ky";
|
import ky, { type HTTPError, type KyInstance, type Options } from "ky";
|
||||||
import { env } from "@/lib/env";
|
import { env } from "@/lib/env";
|
||||||
|
import { resolveApiPrefixUrl } from "@/lib/resolve-api-prefix-url";
|
||||||
import { API_PATHS } from "@/api/api-paths";
|
import { API_PATHS } from "@/api/api-paths";
|
||||||
import { createApiErrorFromResponse, mapHttpStatusToMessage } from "@/api/api-error";
|
import { createApiErrorFromResponse, mapHttpStatusToMessage } from "@/api/api-error";
|
||||||
import { queryKeys } from "@/infra/query-key/query-key";
|
import { queryKeys } from "@/infra/query-key/query-key";
|
||||||
import queryClient from "@/lib/query/query-client";
|
import queryClient from "@/lib/query/query-client";
|
||||||
import { clearAuth, getAccessToken } from "@/lib/auth/auth-storage";
|
import { clearAuth, getAccessToken } from "@/lib/auth/auth-storage";
|
||||||
|
|
||||||
function resolvePrefixUrl(url: string): string {
|
|
||||||
const trimmed = url.trim() || "/api";
|
|
||||||
|
|
||||||
if (trimmed.startsWith("http")) {
|
|
||||||
return trimmed.endsWith("/") ? trimmed : `${trimmed}/`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const path = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
||||||
const pathWithSlash = path.endsWith("/") ? path : `${path}/`;
|
|
||||||
const origin =
|
|
||||||
typeof window !== "undefined" && window.location?.origin
|
|
||||||
? window.location.origin
|
|
||||||
: "http://localhost:3000";
|
|
||||||
|
|
||||||
return `${origin}${pathWithSlash}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearSessionAndRedirectToLogin(): void {
|
function clearSessionAndRedirectToLogin(): void {
|
||||||
clearAuth();
|
clearAuth();
|
||||||
queryClient.setQueryData(queryKeys.auth.session(), null);
|
queryClient.setQueryData(queryKeys.auth.session(), null);
|
||||||
|
|
@ -37,7 +21,7 @@ function isAuthLoginRequest(request: Request): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const api: KyInstance = ky.create({
|
export const api: KyInstance = ky.create({
|
||||||
prefixUrl: resolvePrefixUrl(env.apiUrl),
|
prefixUrl: resolveApiPrefixUrl(env.apiUrl),
|
||||||
headers: {
|
headers: {
|
||||||
Accept: "application/json",
|
Accept: "application/json",
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { API_PATHS } from "@/api/api-paths";
|
import { API_PATHS } from "@/api/api-paths";
|
||||||
import { env } from "@/lib/env";
|
import { env } from "@/lib/env";
|
||||||
|
import { resolveApiBaseUrl } from "@/lib/resolve-api-prefix-url";
|
||||||
import type {
|
import type {
|
||||||
VendorPortalComment,
|
VendorPortalComment,
|
||||||
VendorPortalDispatchDetail,
|
VendorPortalDispatchDetail,
|
||||||
|
|
@ -9,11 +10,8 @@ import type {
|
||||||
} from "@/domain/vendor-portal/types/vendor-portal";
|
} from "@/domain/vendor-portal/types/vendor-portal";
|
||||||
|
|
||||||
function resolveVendorPortalUrl(path: string): string {
|
function resolveVendorPortalUrl(path: string): string {
|
||||||
const base = env.apiUrl.trim().replace(/\/$/, "");
|
const base = resolveApiBaseUrl(env.apiUrl);
|
||||||
const prefix = base.startsWith("http")
|
return `${base}/${API_PATHS.vendorPortal.base}${path}`;
|
||||||
? base
|
|
||||||
: `${typeof window !== "undefined" ? window.location.origin : "http://localhost:3000"}${base.startsWith("/") ? base : `/${base}`}`;
|
|
||||||
return `${prefix}/${API_PATHS.vendorPortal.base}${path}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function vendorPortalCall<T>(
|
async function vendorPortalCall<T>(
|
||||||
|
|
|
||||||
35
src/lib/resolve-api-prefix-url.ts
Normal file
35
src/lib/resolve-api-prefix-url.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
const DEFAULT_ORIGIN = "http://localhost:3000";
|
||||||
|
|
||||||
|
function getDefaultOrigin(): string {
|
||||||
|
if (typeof window !== "undefined" && window.location?.origin) {
|
||||||
|
return window.location.origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEFAULT_ORIGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves VITE_API_URL to a Ky-compatible prefixUrl (always ends with /).
|
||||||
|
*
|
||||||
|
* Contract:
|
||||||
|
* - Relative paths (e.g. `/api`) are joined with the app origin.
|
||||||
|
* - Absolute URLs are used as-is; they must already include `/api` for production.
|
||||||
|
* - API_PATHS do not include `/api` — only this prefix supplies it.
|
||||||
|
*/
|
||||||
|
export function resolveApiPrefixUrl(url: string, origin = getDefaultOrigin()): string {
|
||||||
|
const trimmed = url.trim() || "/api";
|
||||||
|
|
||||||
|
if (trimmed.startsWith("http")) {
|
||||||
|
return trimmed.endsWith("/") ? trimmed : `${trimmed}/`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
||||||
|
const pathWithSlash = path.endsWith("/") ? path : `${path}/`;
|
||||||
|
|
||||||
|
return `${origin}${pathWithSlash}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** API base without trailing slash (for fetch URLs outside Ky). */
|
||||||
|
export function resolveApiBaseUrl(url: string, origin = getDefaultOrigin()): string {
|
||||||
|
return resolveApiPrefixUrl(url, origin).replace(/\/$/, "");
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue