Project Init

This commit is contained in:
Muluhabt
2026-05-29 15:23:46 +03:00
commit 2fbc557aac
67387 changed files with 6063341 additions and 0 deletions

3
libs/api/src/index.ts Normal file
View File

@@ -0,0 +1,3 @@
export * from './lib/base-api';
export * from './lib/query-and-mutation';
export * from './lib/session';

View File

@@ -0,0 +1,23 @@
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { resolveSessionContext } from '../session';
const BASE_API_URL =
(import.meta as { env?: Record<string, string> }).env?.['VITE_BASE_API_URL'] ??
'http://localhost:3000';
export const baseApi = createApi({
reducerPath: 'baseApi',
baseQuery: fetchBaseQuery({
baseUrl: BASE_API_URL,
prepareHeaders: (headers, { getState }) => {
const { token, sessionHeaders } = resolveSessionContext(
getState() as { auth?: { token?: string } },
);
if (token) headers.set('Authorization', `Bearer ${token}`);
Object.entries(sessionHeaders).forEach(([k, v]) => headers.set(k, v));
return headers;
},
}),
tagTypes: ['Api'],
endpoints: () => ({}),
});

View File

@@ -0,0 +1,44 @@
import { baseApi } from '../base-api';
export type ApiQueryArgs = {
url: string;
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
params?: Record<string, unknown>;
body?: unknown;
headers?: Record<string, string>;
cacheKey?: string | unknown[];
};
const queryApi = baseApi.injectEndpoints({
endpoints: (builder) => ({
apiQuery: builder.query<unknown, ApiQueryArgs>({
query: ({ url, params }) => ({ url, params }),
}),
apiMutation: builder.mutation<unknown, ApiQueryArgs>({
query: ({ url, method = 'POST', body, headers }) => ({
url,
method,
body,
headers,
}),
}),
}),
overrideExisting: false,
});
export const { useApiQueryQuery, useApiMutationMutation } = queryApi;
export function useApiQuery<TData = unknown>(
args: ApiQueryArgs,
options?: Parameters<typeof useApiQueryQuery>[1],
) {
return useApiQueryQuery(args, options) as ReturnType<typeof useApiQueryQuery> & {
data: TData | undefined;
};
}
export function useApiMutation<TData = unknown>() {
return useApiMutationMutation() as ReturnType<typeof useApiMutationMutation> & {
data: TData | undefined;
};
}

View File

@@ -0,0 +1,29 @@
export const SESSION_HEADER_KEYS = {
tenantId: 'x-tenant-id',
organizationUnitId: 'x-organization-unit-id',
currentPositionId: 'x-current-position-id',
currentProjectId: 'x-current-project-id',
} as const;
const TOKEN_STORAGE_KEYS = [
'ema-backoffice-auth-token',
'ema-portal-auth-token',
'auth-token',
] as const;
export function resolveTokenFromStorage(): string | undefined {
for (const key of TOKEN_STORAGE_KEYS) {
const stored = localStorage.getItem(key);
if (stored) return stored;
}
const match = document.cookie.match(/(?:^|;\s*)auth-token=([^;]*)/);
return match ? decodeURIComponent(match[1]) : undefined;
}
export function resolveSessionContext(state?: { auth?: { token?: string } }): {
token: string | undefined;
sessionHeaders: Record<string, string>;
} {
const token = state?.auth?.token ?? resolveTokenFromStorage();
return { token, sessionHeaders: {} };
}