mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-19 11:21:24 +02:00
Commit Message feat: implement comprehensive shared packages architecture for monorepo SUMMARY: Introduce 10 shared packages to unify common code across all 4 web apps, reducing ~3,000 lines of duplicated code and establishing consistent patterns for authentication, UI components, theming, and utilities. NEW SHARED PACKAGES: - @manacore/shared-auth: Unified auth logic (token management, JWT utils, fetch interceptor, storage/device/network adapters) - @manacore/shared-auth-ui: Reusable auth UI (LoginPage, RegisterPage, OAuth buttons for Google/Apple) - @manacore/shared-tailwind: Unified Tailwind config with 4 themes (lume, nature, stone, ocean) and light/dark mode support - @manacore/shared-icons: Phosphor-based icon library (40+ icons) - @manacore/shared-ui: Atomic design system (Text, Button, Badge, Toggle, Input, Modal) - @manacore/shared-i18n: Unified i18n setup with locale detection - @manacore/shared-config: Environment validation with Zod - @manacore/shared-subscriptio n-types: Subscription type definitions - @manacore/shared-subscriptio n-ui: Subscription UI components (planned) EXTENDED PACKAGES: - @manacore/shared-types: Added auth.ts, theme.ts, ui.ts, common.ts - @manacore/shared-utils: Added format.ts, validation.ts APP MIGRATIONS: - memoro/web: Migrated login (549→46 LOC), tailwind (165→12 LOC), removed 15+ duplicate components - manacore/web: Migrated to client-side auth with shared-auth, added new components (Icon, ThemeToggle, Logo) - manadeck/web: Replaced local authService/tokenManager with shared-auth, migrated auth pages - maerchenzauber/web: Added auth setup, stores, components, routes DELETED FILES (migrated to shared packages): - OAuth buttons (Google/Apple) from memoro, manacore, manadeck - Local authService, tokenManager, deviceManager, jwt utils - Duplicate Modal, Toggle, Text components - iconPaths and ManaIcon components - Subscription-related components (CostCard, PackageCard, etc.) BENEFITS: - 92% reduction in login page code - 93% reduction in tailwind config code - Consistent theming across all apps - Single source of truth for auth logic - Easier maintenance and updates BREAKING CHANGES: - Icon imports now from @manacore/shared-icons - Modal imports from @manacore/shared-ui - OAuth config via setGoogleCl ientId()/setAppleConfig()
This commit is contained in:
parent
725db638ea
commit
ef70a1af0b
198 changed files with 11113 additions and 3656 deletions
93
packages/shared-types/src/auth.ts
Normal file
93
packages/shared-types/src/auth.ts
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
* Authentication-related types
|
||||
*/
|
||||
|
||||
/**
|
||||
* Authentication state
|
||||
*/
|
||||
export type AuthState = 'loading' | 'authenticated' | 'unauthenticated';
|
||||
|
||||
/**
|
||||
* User session
|
||||
*/
|
||||
export interface Session {
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
expiresAt: number;
|
||||
user: AuthUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticated user
|
||||
*/
|
||||
export interface AuthUser {
|
||||
id: string;
|
||||
email: string;
|
||||
emailConfirmed?: boolean;
|
||||
phone?: string;
|
||||
phoneConfirmed?: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
lastSignInAt?: string;
|
||||
appMetadata?: Record<string, unknown>;
|
||||
userMetadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign in credentials
|
||||
*/
|
||||
export interface SignInCredentials {
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign up credentials
|
||||
*/
|
||||
export interface SignUpCredentials {
|
||||
email: string;
|
||||
password: string;
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* OAuth provider
|
||||
*/
|
||||
export type OAuthProvider = 'google' | 'apple' | 'github' | 'facebook';
|
||||
|
||||
/**
|
||||
* Auth result for operations
|
||||
*/
|
||||
export interface AuthResult {
|
||||
success: boolean;
|
||||
error?: string;
|
||||
session?: Session;
|
||||
user?: AuthUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Password reset request
|
||||
*/
|
||||
export interface PasswordResetRequest {
|
||||
email: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Password update request
|
||||
*/
|
||||
export interface PasswordUpdateRequest {
|
||||
password: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auth context value
|
||||
*/
|
||||
export interface AuthContextValue {
|
||||
state: AuthState;
|
||||
user: AuthUser | null;
|
||||
session: Session | null;
|
||||
signIn: (credentials: SignInCredentials) => Promise<AuthResult>;
|
||||
signUp: (credentials: SignUpCredentials) => Promise<AuthResult>;
|
||||
signOut: () => Promise<void>;
|
||||
resetPassword: (email: string) => Promise<AuthResult>;
|
||||
}
|
||||
131
packages/shared-types/src/common.ts
Normal file
131
packages/shared-types/src/common.ts
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
/**
|
||||
* Common utility types
|
||||
*/
|
||||
|
||||
/**
|
||||
* Result type for operations that can fail
|
||||
*/
|
||||
export type Result<T, E = Error> =
|
||||
| { success: true; data: T }
|
||||
| { success: false; error: E };
|
||||
|
||||
/**
|
||||
* Async result type
|
||||
*/
|
||||
export type AsyncResult<T, E = Error> = Promise<Result<T, E>>;
|
||||
|
||||
/**
|
||||
* Make all properties optional recursively
|
||||
*/
|
||||
export type DeepPartial<T> = {
|
||||
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
||||
};
|
||||
|
||||
/**
|
||||
* Make specific properties required
|
||||
*/
|
||||
export type RequiredFields<T, K extends keyof T> = T & Required<Pick<T, K>>;
|
||||
|
||||
/**
|
||||
* Make specific properties optional
|
||||
*/
|
||||
export type OptionalFields<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
||||
|
||||
/**
|
||||
* Extract the type from a Promise
|
||||
*/
|
||||
export type Awaited<T> = T extends Promise<infer U> ? U : T;
|
||||
|
||||
/**
|
||||
* Nullable type
|
||||
*/
|
||||
export type Nullable<T> = T | null;
|
||||
|
||||
/**
|
||||
* Maybe type (nullable and optional)
|
||||
*/
|
||||
export type Maybe<T> = T | null | undefined;
|
||||
|
||||
/**
|
||||
* Dictionary type
|
||||
*/
|
||||
export type Dictionary<T = unknown> = Record<string, T>;
|
||||
|
||||
/**
|
||||
* ID type (for entities)
|
||||
*/
|
||||
export type ID = string;
|
||||
|
||||
/**
|
||||
* Timestamp type
|
||||
*/
|
||||
export type Timestamp = string; // ISO 8601 format
|
||||
|
||||
/**
|
||||
* Sort direction
|
||||
*/
|
||||
export type SortDirection = 'asc' | 'desc';
|
||||
|
||||
/**
|
||||
* Sort configuration
|
||||
*/
|
||||
export interface SortConfig<T = string> {
|
||||
field: T;
|
||||
direction: SortDirection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter operator
|
||||
*/
|
||||
export type FilterOperator = 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'like' | 'in';
|
||||
|
||||
/**
|
||||
* Filter configuration
|
||||
*/
|
||||
export interface FilterConfig<T = string> {
|
||||
field: T;
|
||||
operator: FilterOperator;
|
||||
value: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Entity with timestamps
|
||||
*/
|
||||
export interface TimestampedEntity {
|
||||
created_at: Timestamp;
|
||||
updated_at: Timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Entity with user ownership
|
||||
*/
|
||||
export interface OwnedEntity extends TimestampedEntity {
|
||||
user_id: ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locale code
|
||||
*/
|
||||
export type LocaleCode = 'en' | 'de' | 'fr' | 'es' | 'it' | 'pt' | 'nl' | 'pl' | 'ru' | 'ja' | 'ko' | 'zh';
|
||||
|
||||
/**
|
||||
* Localized string
|
||||
*/
|
||||
export type LocalizedString = {
|
||||
[key in LocaleCode]?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Event handler type
|
||||
*/
|
||||
export type EventHandler<T = void> = (event: T) => void;
|
||||
|
||||
/**
|
||||
* Callback type
|
||||
*/
|
||||
export type Callback<T = void> = () => T;
|
||||
|
||||
/**
|
||||
* Async callback type
|
||||
*/
|
||||
export type AsyncCallback<T = void> = () => Promise<T>;
|
||||
|
|
@ -4,7 +4,19 @@
|
|||
* This package contains common TypeScript types used across all projects.
|
||||
*/
|
||||
|
||||
// Common user types
|
||||
// Theme types
|
||||
export * from './theme';
|
||||
|
||||
// Auth types
|
||||
export * from './auth';
|
||||
|
||||
// UI types
|
||||
export * from './ui';
|
||||
|
||||
// Common utility types
|
||||
export * from './common';
|
||||
|
||||
// API types
|
||||
export interface User {
|
||||
id: string;
|
||||
email: string;
|
||||
|
|
@ -12,7 +24,6 @@ export interface User {
|
|||
updated_at: string;
|
||||
}
|
||||
|
||||
// Common API response types
|
||||
export interface ApiResponse<T> {
|
||||
data: T | null;
|
||||
error: ApiError | null;
|
||||
|
|
|
|||
67
packages/shared-types/src/theme.ts
Normal file
67
packages/shared-types/src/theme.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* Theme-related types
|
||||
*/
|
||||
|
||||
/**
|
||||
* Available theme names
|
||||
*/
|
||||
export type ThemeName = 'lume' | 'nature' | 'stone' | 'ocean';
|
||||
|
||||
/**
|
||||
* Color mode
|
||||
*/
|
||||
export type ColorMode = 'light' | 'dark' | 'system';
|
||||
|
||||
/**
|
||||
* Theme configuration
|
||||
*/
|
||||
export interface ThemeConfig {
|
||||
name: ThemeName;
|
||||
mode: ColorMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme color tokens
|
||||
*/
|
||||
export interface ThemeColors {
|
||||
primary: string;
|
||||
primaryButton: string;
|
||||
primaryButtonText: string;
|
||||
secondary: string;
|
||||
secondaryButton: string;
|
||||
contentBackground: string;
|
||||
contentBackgroundHover: string;
|
||||
contentPageBackground: string;
|
||||
menuBackground: string;
|
||||
menuBackgroundHover: string;
|
||||
pageBackground: string;
|
||||
text: string;
|
||||
textSecondary: string;
|
||||
borderLight: string;
|
||||
border: string;
|
||||
borderStrong: string;
|
||||
error: string;
|
||||
success: string;
|
||||
warning: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete theme with light and dark variants
|
||||
*/
|
||||
export interface Theme {
|
||||
name: ThemeName;
|
||||
light: ThemeColors;
|
||||
dark: ThemeColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme context value
|
||||
*/
|
||||
export interface ThemeContextValue {
|
||||
theme: ThemeName;
|
||||
mode: ColorMode;
|
||||
isDark: boolean;
|
||||
setTheme: (theme: ThemeName) => void;
|
||||
setMode: (mode: ColorMode) => void;
|
||||
toggleMode: () => void;
|
||||
}
|
||||
109
packages/shared-types/src/ui.ts
Normal file
109
packages/shared-types/src/ui.ts
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
* UI-related types
|
||||
*/
|
||||
|
||||
/**
|
||||
* Common size variants
|
||||
*/
|
||||
export type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
||||
|
||||
/**
|
||||
* Button variants
|
||||
*/
|
||||
export type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger' | 'link';
|
||||
|
||||
/**
|
||||
* Text variants
|
||||
*/
|
||||
export type TextVariant = 'h1' | 'h2' | 'h3' | 'h4' | 'body' | 'small' | 'muted' | 'code';
|
||||
|
||||
/**
|
||||
* Font weight
|
||||
*/
|
||||
export type FontWeight = 'normal' | 'medium' | 'semibold' | 'bold';
|
||||
|
||||
/**
|
||||
* Badge variants
|
||||
*/
|
||||
export type BadgeVariant = 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error';
|
||||
|
||||
/**
|
||||
* Input types
|
||||
*/
|
||||
export type InputType = 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'search';
|
||||
|
||||
/**
|
||||
* Toast/notification types
|
||||
*/
|
||||
export type ToastType = 'info' | 'success' | 'warning' | 'error';
|
||||
|
||||
/**
|
||||
* Toast notification
|
||||
*/
|
||||
export interface Toast {
|
||||
id: string;
|
||||
type: ToastType;
|
||||
message: string;
|
||||
title?: string;
|
||||
duration?: number;
|
||||
dismissible?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modal configuration
|
||||
*/
|
||||
export interface ModalConfig {
|
||||
title?: string;
|
||||
description?: string;
|
||||
confirmText?: string;
|
||||
cancelText?: string;
|
||||
dangerous?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dropdown/Select option
|
||||
*/
|
||||
export interface SelectOption<T = string> {
|
||||
value: T;
|
||||
label: string;
|
||||
disabled?: boolean;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tab item
|
||||
*/
|
||||
export interface TabItem {
|
||||
id: string;
|
||||
label: string;
|
||||
icon?: string;
|
||||
disabled?: boolean;
|
||||
badge?: string | number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu item
|
||||
*/
|
||||
export interface MenuItem {
|
||||
id: string;
|
||||
label: string;
|
||||
icon?: string;
|
||||
href?: string;
|
||||
onClick?: () => void;
|
||||
disabled?: boolean;
|
||||
danger?: boolean;
|
||||
divider?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Breadcrumb item
|
||||
*/
|
||||
export interface BreadcrumbItem {
|
||||
label: string;
|
||||
href?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loading state
|
||||
*/
|
||||
export type LoadingState = 'idle' | 'loading' | 'success' | 'error';
|
||||
Loading…
Add table
Add a link
Reference in a new issue