mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-24 02:16:41 +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
173
packages/shared-config/src/features.ts
Normal file
173
packages/shared-config/src/features.ts
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/**
|
||||
* Feature flag utilities
|
||||
*/
|
||||
|
||||
/**
|
||||
* Feature flag configuration
|
||||
*/
|
||||
export interface FeatureFlag {
|
||||
/** Feature key */
|
||||
key: string;
|
||||
/** Default enabled state */
|
||||
defaultEnabled: boolean;
|
||||
/** Description */
|
||||
description?: string;
|
||||
/** Environment variable to override */
|
||||
envVar?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a feature flag manager
|
||||
*/
|
||||
export function createFeatureFlags<T extends Record<string, FeatureFlag>>(
|
||||
flags: T,
|
||||
env: NodeJS.ProcessEnv = process.env
|
||||
) {
|
||||
type FlagKey = keyof T;
|
||||
|
||||
/**
|
||||
* Check if a feature is enabled
|
||||
*/
|
||||
function isEnabled(key: FlagKey): boolean {
|
||||
const flag = flags[key];
|
||||
|
||||
if (!flag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check environment variable override
|
||||
if (flag.envVar) {
|
||||
const envValue = env[flag.envVar];
|
||||
if (envValue !== undefined) {
|
||||
return ['true', '1', 'yes', 'on'].includes(envValue.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
// Check generic feature flag env var
|
||||
const genericEnvVar = `FEATURE_${String(key).toUpperCase()}`;
|
||||
const genericValue = env[genericEnvVar];
|
||||
if (genericValue !== undefined) {
|
||||
return ['true', '1', 'yes', 'on'].includes(genericValue.toLowerCase());
|
||||
}
|
||||
|
||||
return flag.defaultEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all enabled features
|
||||
*/
|
||||
function getEnabledFeatures(): FlagKey[] {
|
||||
return (Object.keys(flags) as FlagKey[]).filter(isEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all disabled features
|
||||
*/
|
||||
function getDisabledFeatures(): FlagKey[] {
|
||||
return (Object.keys(flags) as FlagKey[]).filter(key => !isEnabled(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get feature configuration
|
||||
*/
|
||||
function getFlag(key: FlagKey): FeatureFlag | undefined {
|
||||
return flags[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all flags with their current state
|
||||
*/
|
||||
function getAllFlags(): Record<string, boolean> {
|
||||
const result: Record<string, boolean> = {};
|
||||
for (const key of Object.keys(flags) as FlagKey[]) {
|
||||
result[String(key)] = isEnabled(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return {
|
||||
isEnabled,
|
||||
getEnabledFeatures,
|
||||
getDisabledFeatures,
|
||||
getFlag,
|
||||
getAllFlags,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple feature check using environment variable
|
||||
*/
|
||||
export function isFeatureEnabled(
|
||||
featureName: string,
|
||||
defaultValue: boolean = false,
|
||||
env: NodeJS.ProcessEnv = process.env
|
||||
): boolean {
|
||||
const envVar = `FEATURE_${featureName.toUpperCase().replace(/[^A-Z0-9]/g, '_')}`;
|
||||
const value = env[envVar];
|
||||
|
||||
if (value === undefined) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return ['true', '1', 'yes', 'on'].includes(value.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* App metadata configuration
|
||||
*/
|
||||
export interface AppMetadata {
|
||||
/** App name */
|
||||
name: string;
|
||||
/** App version */
|
||||
version: string;
|
||||
/** App description */
|
||||
description?: string;
|
||||
/** Build number */
|
||||
buildNumber?: string;
|
||||
/** Git commit hash */
|
||||
commitHash?: string;
|
||||
/** Build timestamp */
|
||||
buildTime?: string;
|
||||
/** Environment */
|
||||
environment?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create app metadata from environment
|
||||
*/
|
||||
export function createAppMetadata(
|
||||
config: {
|
||||
name: string;
|
||||
version: string;
|
||||
description?: string;
|
||||
},
|
||||
env: NodeJS.ProcessEnv = process.env
|
||||
): AppMetadata {
|
||||
return {
|
||||
name: config.name,
|
||||
version: config.version,
|
||||
description: config.description,
|
||||
buildNumber: env.BUILD_NUMBER || env.VITE_BUILD_NUMBER,
|
||||
commitHash: env.COMMIT_HASH || env.VITE_COMMIT_HASH || env.GIT_COMMIT,
|
||||
buildTime: env.BUILD_TIME || env.VITE_BUILD_TIME,
|
||||
environment: env.NODE_ENV || 'development',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Format version string with build info
|
||||
*/
|
||||
export function formatVersion(metadata: AppMetadata): string {
|
||||
let version = metadata.version;
|
||||
|
||||
if (metadata.buildNumber) {
|
||||
version += ` (${metadata.buildNumber})`;
|
||||
}
|
||||
|
||||
if (metadata.commitHash) {
|
||||
const shortHash = metadata.commitHash.substring(0, 7);
|
||||
version += ` [${shortHash}]`;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue