fix: resolve circular dependency between utils and service libraries

Moved useAuthStore from utils to service to break circular dependency:
- utils was importing from service (supabase client, types)
- service was importing from utils (useAuthStore)
- Solution: moved useAuthStore and related storage utilities to service

Changes:
- Created libs/service/src/storage/ with cookies.ts and local-storage.ts
- Moved use-auth-store.ts from utils/hooks to service/hooks/auth
- Updated all 20+ files to import useAuthStore from service instead of utils
- Removed useAuthStore export from utils
- Added storage exports to service index

This fixes the build error: "Could not execute command because the task graph has a circular dependency"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Maulana Sodiqin
2025-11-25 02:34:52 +07:00
co-authored by Claude
parent 9e9bfc2793
commit 1cb2443b58
32 changed files with 23078 additions and 40 deletions
+2
View File
@@ -1,5 +1,7 @@
import { supabase } from '../../supabase';
export * from './use-auth-store';
// Supabase GitHub OAuth hook
export const useGitHubAuth = () => {
const signInWithGitHub = async () => {
@@ -0,0 +1,46 @@
import { create } from 'zustand';
import { TLoginItem } from '../../types';
import { SessionToken, SessionUser } from '../../storage';
export enum ESessionStatus {
Authenticated = 'authenticated',
Authenticating = 'authenticating',
Unauthenticated = 'unauthenticated',
}
type SessionState = {
isLoading: boolean;
session?: TLoginItem;
status?: ESessionStatus;
setLoading: (val: boolean) => void;
setSession: (payload: TLoginItem) => void;
clearSession: () => void;
};
export const useAuthStore = create<SessionState>((set) => {
const session = SessionToken.get();
const user = SessionUser.get();
const isAuthenticated = !!session;
return {
isLoading: false,
session: isAuthenticated ? { token: session.token, user } : undefined,
status: isAuthenticated
? ESessionStatus.Authenticated
: ESessionStatus.Unauthenticated,
setLoading: (val) => set({ isLoading: val }),
setSession: (data) => {
SessionToken.set({ token: data.token });
SessionUser.set(data.user);
set({
session: data,
status: ESessionStatus.Authenticated,
});
},
clearSession: () => {
SessionToken.remove();
SessionUser.remove();
set({ session: undefined, status: ESessionStatus.Unauthenticated });
},
};
});
+1 -1
View File
@@ -1,6 +1,6 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { supabase } from '../../supabase';
import { useAuthStore } from '@imphnen-frontend-service/utils';
import { useAuthStore } from '../auth';
import { useEffect } from 'react';
export type Message = {
+1 -1
View File
@@ -1,7 +1,7 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import * as teamsApi from '../../api/teams';
import { supabase, getAuthenticatedClient } from '../../supabase';
import { useAuthStore } from '@imphnen-frontend-service/utils';
import { useAuthStore } from '../auth';
import type {
TCreateTeamRequest,
TUpdateTeamRequest,
+1 -1
View File
@@ -1,6 +1,6 @@
import { useMutation } from '@tanstack/react-query';
import { supabase, getAuthenticatedClient } from '../../supabase';
import { useAuthStore } from '@imphnen-frontend-service/utils';
import { useAuthStore } from '../auth';
// Supabase Storage-based upload hooks
+1 -1
View File
@@ -1,7 +1,7 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { userService } from '../../api/users';
import { supabase, getAuthenticatedClient } from '../../supabase';
import { useAuthStore } from '@imphnen-frontend-service/utils';
import { useAuthStore } from '../auth';
// Supabase-based user hooks
+1
View File
@@ -3,3 +3,4 @@ export * from './hooks';
export * from './types';
export * from './schemas';
export * from './supabase';
export * from './storage';
+36
View File
@@ -0,0 +1,36 @@
import Cookies from 'js-cookie';
type TTokenItem = {
access_token: string;
refresh_token: string;
};
const TOKEN_KEY = 'token';
type TStoredToken =
| {
token?: TTokenItem;
}
| undefined;
export const SessionToken = {
set: (val: TStoredToken) => {
Cookies.set(TOKEN_KEY, JSON.stringify(val), {
secure: true,
sameSite: 'Strict',
expires: 7,
});
},
get: (): TStoredToken => {
const token = Cookies.get(TOKEN_KEY);
if (!token) return undefined;
try {
return JSON.parse(token);
} catch {
return undefined;
}
},
remove: () => {
Cookies.remove(TOKEN_KEY);
},
};
+2
View File
@@ -0,0 +1,2 @@
export * from './cookies';
export * from './local-storage';
+38
View File
@@ -0,0 +1,38 @@
export type TPermissionItem = {
id: string;
name: string;
created_at: string;
updated_at: string;
};
type TRoleItem = {
id: string;
name: string;
created_at: string;
updated_at: string;
permissions: TPermissionItem[];
};
type TUserItem = {
id: string;
avatar: string;
birthdate: string;
email: string;
fullname: string;
gender: string;
is_active: boolean;
phone_number: string;
role: TRoleItem;
bio?: string;
location?: string;
skills?: string[];
};
export const SessionUser = {
set: (val?: TUserItem) => localStorage.setItem('users', JSON.stringify(val)),
get: (): TUserItem | undefined => {
const users = localStorage.getItem('users');
return users ? JSON.parse(users) : undefined;
},
remove: () => localStorage.removeItem('users'),
};
-1
View File
@@ -1,5 +1,4 @@
export * from './use-query-state';
export * from './use-auth-store';
export * from './use-modal-login';
export * from './use-session';
export * from './use-register';
+1 -2
View File
@@ -1,5 +1,4 @@
import { supabase } from '@imphnen-frontend-service/service';
import { useAuthStore } from './';
import { supabase, useAuthStore } from '@imphnen-frontend-service/service';
import { useNavigate } from 'react-router';
export const useSession = () => {