diff --git a/.gitignore b/.gitignore index 768b60bd7..b7e97c1e0 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,16 @@ coverage/ # TypeScript *.tsbuildinfo +# Drizzle compiled config files +drizzle.config.js +drizzle.config.d.ts +drizzle.config.js.map + +# Compiled JS in packages (src should be TS only) +packages/*/src/**/*.js +packages/*/src/**/*.js.map +packages/*/src/**/*.d.ts + # Cache .cache/ .parcel-cache/ diff --git a/apps/picture/packages/design-tokens/native/theme.d.ts b/apps/picture/packages/design-tokens/native/theme.d.ts index 95fde6bf6..9df08e0f7 100644 --- a/apps/picture/packages/design-tokens/native/theme.d.ts +++ b/apps/picture/packages/design-tokens/native/theme.d.ts @@ -949,13 +949,4 @@ declare function isValidThemeVariant(variant: string): variant is ThemeVariant; */ type NativeTheme = ReturnType; -export { - type ColorMode, - type NativeTheme, - type SemanticColors, - type ThemeVariant, - createNativeTheme, - getThemeColors, - getThemeVariants, - isValidThemeVariant, -}; +export { type ColorMode, type NativeTheme, type SemanticColors, type ThemeVariant, createNativeTheme, getThemeColors, getThemeVariants, isValidThemeVariant }; diff --git a/apps/picture/packages/design-tokens/native/theme.js b/apps/picture/packages/design-tokens/native/theme.js index 88ca1c413..2d3202f72 100644 --- a/apps/picture/packages/design-tokens/native/theme.js +++ b/apps/picture/packages/design-tokens/native/theme.js @@ -1,580 +1,577 @@ -'use strict'; +"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { - for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { - if ((from && typeof from === 'object') || typeof from === 'function') { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { - get: () => from[key], - enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable, - }); - } - return to; + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; }; -var __toCommonJS = (mod) => __copyProps(__defProp({}, '__esModule', { value: true }), mod); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // native/theme.ts var theme_exports = {}; __export(theme_exports, { - createNativeTheme: () => createNativeTheme, - getThemeColors: () => getThemeColors, - getThemeVariants: () => getThemeVariants, - isValidThemeVariant: () => isValidThemeVariant, + createNativeTheme: () => createNativeTheme, + getThemeColors: () => getThemeColors, + getThemeVariants: () => getThemeVariants, + isValidThemeVariant: () => isValidThemeVariant }); module.exports = __toCommonJS(theme_exports); // src/colors.ts var baseColors = { - // Pure colors - black: '#000000', - white: '#ffffff', - // Grays - gray: { - 50: '#f9fafb', - 100: '#f3f4f6', - 200: '#e5e7eb', - 300: '#d1d5db', - 400: '#9ca3af', - 500: '#6b7280', - 600: '#4b5563', - 700: '#374151', - 800: '#1f2937', - 900: '#111827', - 950: '#0a0a0a', - }, - // Indigo (Default primary) - indigo: { - 200: '#c7d2fe', - 300: '#a5b4fc', - 400: '#818cf8', - 500: '#6366f1', - 600: '#4f46e5', - 700: '#4338ca', - 800: '#3730a3', - }, - // Violet (Default secondary) - violet: { - 300: '#c4b5fd', - 400: '#a78bfa', - 500: '#8b5cf6', - 600: '#7c3aed', - }, - // Orange (Sunset theme) - orange: { - 300: '#fdba74', - 400: '#fb923c', - 500: '#f97316', - 600: '#ea580c', - }, - // Pink (Sunset theme) - pink: { - 300: '#f9a8d4', - 400: '#f472b6', - 500: '#ec4899', - 600: '#db2777', - }, - // Sky (Ocean theme) - sky: { - 300: '#7dd3fc', - 400: '#38bdf8', - 500: '#0ea5e9', - 600: '#0284c7', - }, - // Emerald (Ocean theme + status) - emerald: { - 300: '#6ee7b7', - 400: '#34d399', - 500: '#10b981', - 600: '#059669', - }, - // Status colors - red: { - 500: '#ef4444', - 600: '#dc2626', - }, - amber: { - 500: '#f59e0b', - }, - blue: { - 500: '#3b82f6', - }, + // Pure colors + black: "#000000", + white: "#ffffff", + // Grays + gray: { + 50: "#f9fafb", + 100: "#f3f4f6", + 200: "#e5e7eb", + 300: "#d1d5db", + 400: "#9ca3af", + 500: "#6b7280", + 600: "#4b5563", + 700: "#374151", + 800: "#1f2937", + 900: "#111827", + 950: "#0a0a0a" + }, + // Indigo (Default primary) + indigo: { + 200: "#c7d2fe", + 300: "#a5b4fc", + 400: "#818cf8", + 500: "#6366f1", + 600: "#4f46e5", + 700: "#4338ca", + 800: "#3730a3" + }, + // Violet (Default secondary) + violet: { + 300: "#c4b5fd", + 400: "#a78bfa", + 500: "#8b5cf6", + 600: "#7c3aed" + }, + // Orange (Sunset theme) + orange: { + 300: "#fdba74", + 400: "#fb923c", + 500: "#f97316", + 600: "#ea580c" + }, + // Pink (Sunset theme) + pink: { + 300: "#f9a8d4", + 400: "#f472b6", + 500: "#ec4899", + 600: "#db2777" + }, + // Sky (Ocean theme) + sky: { + 300: "#7dd3fc", + 400: "#38bdf8", + 500: "#0ea5e9", + 600: "#0284c7" + }, + // Emerald (Ocean theme + status) + emerald: { + 300: "#6ee7b7", + 400: "#34d399", + 500: "#10b981", + 600: "#059669" + }, + // Status colors + red: { + 500: "#ef4444", + 600: "#dc2626" + }, + amber: { + 500: "#f59e0b" + }, + blue: { + 500: "#3b82f6" + } }; var semanticColors = { - /** - * Dark mode colors - */ - dark: { - // Backgrounds - background: baseColors.black, - surface: '#1a1a1a', - elevated: '#242424', - overlay: 'rgba(0, 0, 0, 0.8)', - // Borders & Dividers - border: '#383838', - divider: '#2a2a2a', - // Input fields - input: { - background: '#1f1f1f', - border: '#383838', - text: baseColors.gray[100], - placeholder: baseColors.gray[500], - }, - // Text colors - text: { - primary: baseColors.gray[100], - secondary: baseColors.gray[300], - tertiary: baseColors.gray[400], - disabled: baseColors.gray[500], - inverse: baseColors.black, - }, - // Primary brand color (Indigo) - primary: { - default: baseColors.indigo[400], - hover: baseColors.indigo[300], - active: baseColors.indigo[500], - light: baseColors.indigo[200], - dark: baseColors.indigo[600], - contrast: baseColors.white, - }, - // Secondary accent color (Violet) - secondary: { - default: baseColors.violet[400], - light: baseColors.violet[300], - dark: baseColors.violet[500], - contrast: baseColors.white, - }, - // Status colors - success: baseColors.emerald[500], - warning: baseColors.amber[500], - error: baseColors.red[500], - info: baseColors.blue[500], - // Semantic colors - favorite: baseColors.red[500], - like: baseColors.red[500], - tag: baseColors.indigo[400], - // Special UI elements - skeleton: '#2a2a2a', - shimmer: '#383838', - }, - /** - * Light mode colors - */ - light: { - // Backgrounds - background: baseColors.white, - surface: baseColors.gray[50], - elevated: baseColors.white, - overlay: 'rgba(0, 0, 0, 0.5)', - // Borders & Dividers - border: baseColors.gray[200], - divider: baseColors.gray[100], - // Input fields - input: { - background: baseColors.white, - border: baseColors.gray[300], - text: baseColors.gray[900], - placeholder: baseColors.gray[400], - }, - // Text colors - text: { - primary: baseColors.gray[900], - secondary: baseColors.gray[700], - tertiary: baseColors.gray[500], - disabled: baseColors.gray[400], - inverse: baseColors.white, - }, - // Primary brand color (Indigo) - primary: { - default: baseColors.indigo[500], - hover: baseColors.indigo[600], - active: baseColors.indigo[700], - light: baseColors.indigo[400], - dark: baseColors.indigo[800], - contrast: baseColors.white, - }, - // Secondary accent color (Violet) - secondary: { - default: baseColors.violet[500], - light: baseColors.violet[400], - dark: baseColors.violet[600], - contrast: baseColors.white, - }, - // Status colors - success: baseColors.emerald[500], - warning: baseColors.amber[500], - error: baseColors.red[500], - info: baseColors.blue[500], - // Semantic colors - favorite: baseColors.red[500], - like: baseColors.red[500], - tag: baseColors.indigo[500], - // Special UI elements - skeleton: baseColors.gray[200], - shimmer: baseColors.gray[100], - }, + /** + * Dark mode colors + */ + dark: { + // Backgrounds + background: baseColors.black, + surface: "#1a1a1a", + elevated: "#242424", + overlay: "rgba(0, 0, 0, 0.8)", + // Borders & Dividers + border: "#383838", + divider: "#2a2a2a", + // Input fields + input: { + background: "#1f1f1f", + border: "#383838", + text: baseColors.gray[100], + placeholder: baseColors.gray[500] + }, + // Text colors + text: { + primary: baseColors.gray[100], + secondary: baseColors.gray[300], + tertiary: baseColors.gray[400], + disabled: baseColors.gray[500], + inverse: baseColors.black + }, + // Primary brand color (Indigo) + primary: { + default: baseColors.indigo[400], + hover: baseColors.indigo[300], + active: baseColors.indigo[500], + light: baseColors.indigo[200], + dark: baseColors.indigo[600], + contrast: baseColors.white + }, + // Secondary accent color (Violet) + secondary: { + default: baseColors.violet[400], + light: baseColors.violet[300], + dark: baseColors.violet[500], + contrast: baseColors.white + }, + // Status colors + success: baseColors.emerald[500], + warning: baseColors.amber[500], + error: baseColors.red[500], + info: baseColors.blue[500], + // Semantic colors + favorite: baseColors.red[500], + like: baseColors.red[500], + tag: baseColors.indigo[400], + // Special UI elements + skeleton: "#2a2a2a", + shimmer: "#383838" + }, + /** + * Light mode colors + */ + light: { + // Backgrounds + background: baseColors.white, + surface: baseColors.gray[50], + elevated: baseColors.white, + overlay: "rgba(0, 0, 0, 0.5)", + // Borders & Dividers + border: baseColors.gray[200], + divider: baseColors.gray[100], + // Input fields + input: { + background: baseColors.white, + border: baseColors.gray[300], + text: baseColors.gray[900], + placeholder: baseColors.gray[400] + }, + // Text colors + text: { + primary: baseColors.gray[900], + secondary: baseColors.gray[700], + tertiary: baseColors.gray[500], + disabled: baseColors.gray[400], + inverse: baseColors.white + }, + // Primary brand color (Indigo) + primary: { + default: baseColors.indigo[500], + hover: baseColors.indigo[600], + active: baseColors.indigo[700], + light: baseColors.indigo[400], + dark: baseColors.indigo[800], + contrast: baseColors.white + }, + // Secondary accent color (Violet) + secondary: { + default: baseColors.violet[500], + light: baseColors.violet[400], + dark: baseColors.violet[600], + contrast: baseColors.white + }, + // Status colors + success: baseColors.emerald[500], + warning: baseColors.amber[500], + error: baseColors.red[500], + info: baseColors.blue[500], + // Semantic colors + favorite: baseColors.red[500], + like: baseColors.red[500], + tag: baseColors.indigo[500], + // Special UI elements + skeleton: baseColors.gray[200], + shimmer: baseColors.gray[100] + } }; // src/shadows.ts var shadows = { - dark: { - sm: { - shadowColor: '#000', - shadowOffset: { width: 0, height: 1 }, - shadowOpacity: 0.2, - shadowRadius: 2, - elevation: 2, - // Android - }, - md: { - shadowColor: '#000', - shadowOffset: { width: 0, height: 4 }, - shadowOpacity: 0.3, - shadowRadius: 6, - elevation: 4, - }, - lg: { - shadowColor: '#000', - shadowOffset: { width: 0, height: 10 }, - shadowOpacity: 0.4, - shadowRadius: 15, - elevation: 8, - }, - }, - light: { - sm: { - shadowColor: '#000', - shadowOffset: { width: 0, height: 1 }, - shadowOpacity: 0.1, - shadowRadius: 2, - elevation: 2, - }, - md: { - shadowColor: '#000', - shadowOffset: { width: 0, height: 4 }, - shadowOpacity: 0.15, - shadowRadius: 6, - elevation: 4, - }, - lg: { - shadowColor: '#000', - shadowOffset: { width: 0, height: 10 }, - shadowOpacity: 0.2, - shadowRadius: 15, - elevation: 8, - }, - }, + dark: { + sm: { + shadowColor: "#000", + shadowOffset: { width: 0, height: 1 }, + shadowOpacity: 0.2, + shadowRadius: 2, + elevation: 2 + // Android + }, + md: { + shadowColor: "#000", + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.3, + shadowRadius: 6, + elevation: 4 + }, + lg: { + shadowColor: "#000", + shadowOffset: { width: 0, height: 10 }, + shadowOpacity: 0.4, + shadowRadius: 15, + elevation: 8 + } + }, + light: { + sm: { + shadowColor: "#000", + shadowOffset: { width: 0, height: 1 }, + shadowOpacity: 0.1, + shadowRadius: 2, + elevation: 2 + }, + md: { + shadowColor: "#000", + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.15, + shadowRadius: 6, + elevation: 4 + }, + lg: { + shadowColor: "#000", + shadowOffset: { width: 0, height: 10 }, + shadowOpacity: 0.2, + shadowRadius: 15, + elevation: 8 + } + } }; var opacity = { - disabled: 0.5, - overlay: 0.8, - hover: 0.9, - pressed: 0.7, + disabled: 0.5, + overlay: 0.8, + hover: 0.9, + pressed: 0.7 }; // src/themes/default.ts var defaultTheme = { - name: 'default', - displayName: 'Indigo', - colors: { - light: semanticColors.light, - dark: semanticColors.dark, - }, - shadows, - opacity, + name: "default", + displayName: "Indigo", + colors: { + light: semanticColors.light, + dark: semanticColors.dark + }, + shadows, + opacity }; // src/themes/sunset.ts var sunsetTheme = { - name: 'sunset', - displayName: 'Sunset', - colors: { - light: semanticColors.light, - // Uses default light mode - dark: { - ...semanticColors.dark, - // Override backgrounds for warmer tone - background: '#0a0a0a', - surface: '#1f1410', - elevated: '#2a1f1a', - // Override borders - border: '#3d2f28', - divider: '#2a1f1a', - // Override input - input: { - background: '#1a1410', - border: '#3d2f28', - text: '#fef3c7', - // amber-100 - placeholder: '#92400e', - // amber-800 - }, - // Override text colors (warmer) - text: { - primary: '#fef3c7', - // amber-100 - secondary: '#fcd34d', - // amber-300 - tertiary: '#f59e0b', - // amber-500 - disabled: '#92400e', - // amber-800 - inverse: '#0a0a0a', - }, - // Primary: Orange - primary: { - default: baseColors.orange[400], - hover: baseColors.orange[300], - active: baseColors.orange[500], - light: '#fed7aa', - // orange-200 - dark: baseColors.orange[600], - contrast: baseColors.white, - }, - // Secondary: Pink - secondary: { - default: baseColors.pink[400], - light: baseColors.pink[300], - dark: baseColors.pink[500], - contrast: baseColors.white, - }, - // Status - success: baseColors.emerald[500], - warning: '#fbbf24', - // amber-400 - error: '#f43f5e', - // rose-500 - info: '#60a5fa', - // blue-400 - // Semantic - favorite: '#f43f5e', - // rose-500 - like: '#f43f5e', - // rose-500 - tag: baseColors.orange[400], - // Special - skeleton: '#2a1f1a', - shimmer: '#3d2f28', - }, - }, - shadows, - opacity, + name: "sunset", + displayName: "Sunset", + colors: { + light: semanticColors.light, + // Uses default light mode + dark: { + ...semanticColors.dark, + // Override backgrounds for warmer tone + background: "#0a0a0a", + surface: "#1f1410", + elevated: "#2a1f1a", + // Override borders + border: "#3d2f28", + divider: "#2a1f1a", + // Override input + input: { + background: "#1a1410", + border: "#3d2f28", + text: "#fef3c7", + // amber-100 + placeholder: "#92400e" + // amber-800 + }, + // Override text colors (warmer) + text: { + primary: "#fef3c7", + // amber-100 + secondary: "#fcd34d", + // amber-300 + tertiary: "#f59e0b", + // amber-500 + disabled: "#92400e", + // amber-800 + inverse: "#0a0a0a" + }, + // Primary: Orange + primary: { + default: baseColors.orange[400], + hover: baseColors.orange[300], + active: baseColors.orange[500], + light: "#fed7aa", + // orange-200 + dark: baseColors.orange[600], + contrast: baseColors.white + }, + // Secondary: Pink + secondary: { + default: baseColors.pink[400], + light: baseColors.pink[300], + dark: baseColors.pink[500], + contrast: baseColors.white + }, + // Status + success: baseColors.emerald[500], + warning: "#fbbf24", + // amber-400 + error: "#f43f5e", + // rose-500 + info: "#60a5fa", + // blue-400 + // Semantic + favorite: "#f43f5e", + // rose-500 + like: "#f43f5e", + // rose-500 + tag: baseColors.orange[400], + // Special + skeleton: "#2a1f1a", + shimmer: "#3d2f28" + } + }, + shadows, + opacity }; // src/themes/ocean.ts var oceanColors = { - teal: { - 200: '#99f6e4', - 300: '#5eead4', - 400: '#2dd4bf', - 500: '#14b8a6', - 600: '#0d9488', - }, - cyan: { - 300: '#67e8f9', - 400: '#22d3ee', - 500: '#06b6d4', - }, - slate: { - 700: '#334155', - 800: '#1e293b', - 900: '#0f172a', - 950: '#020617', - }, + teal: { + 200: "#99f6e4", + 300: "#5eead4", + 400: "#2dd4bf", + 500: "#14b8a6", + 600: "#0d9488" + }, + cyan: { + 300: "#67e8f9", + 400: "#22d3ee", + 500: "#06b6d4" + }, + slate: { + 700: "#334155", + 800: "#1e293b", + 900: "#0f172a", + 950: "#020617" + } }; var oceanTheme = { - name: 'ocean', - displayName: 'Ocean', - colors: { - light: semanticColors.light, - // Uses default light mode - dark: { - ...semanticColors.dark, - // Override backgrounds for cooler tone - background: oceanColors.slate[950], - surface: oceanColors.slate[900], - elevated: oceanColors.slate[800], - // Override borders - border: oceanColors.slate[700], - divider: oceanColors.slate[800], - // Override input - input: { - background: oceanColors.slate[900], - border: oceanColors.slate[700], - text: '#e0f2fe', - // sky-100 - placeholder: '#0c4a6e', - // sky-900 - }, - // Override text colors (cooler) - text: { - primary: '#e0f2fe', - // sky-100 - secondary: '#7dd3fc', - // sky-300 - tertiary: '#38bdf8', - // sky-400 - disabled: '#0c4a6e', - // sky-900 - inverse: oceanColors.slate[950], - }, - // Primary: Teal - primary: { - default: oceanColors.teal[400], - hover: oceanColors.teal[300], - active: oceanColors.teal[500], - light: oceanColors.teal[200], - dark: oceanColors.teal[600], - contrast: baseColors.white, - }, - // Secondary: Cyan - secondary: { - default: oceanColors.cyan[400], - light: oceanColors.cyan[300], - dark: oceanColors.cyan[500], - contrast: baseColors.white, - }, - // Status - success: baseColors.emerald[500], - warning: '#fbbf24', - // amber-400 - error: '#f43f5e', - // rose-500 - info: '#0ea5e9', - // sky-500 - // Semantic - favorite: '#f43f5e', - // rose-500 - like: '#f43f5e', - // rose-500 - tag: oceanColors.teal[400], - // Special - skeleton: oceanColors.slate[800], - shimmer: oceanColors.slate[700], - }, - }, - shadows, - opacity, + name: "ocean", + displayName: "Ocean", + colors: { + light: semanticColors.light, + // Uses default light mode + dark: { + ...semanticColors.dark, + // Override backgrounds for cooler tone + background: oceanColors.slate[950], + surface: oceanColors.slate[900], + elevated: oceanColors.slate[800], + // Override borders + border: oceanColors.slate[700], + divider: oceanColors.slate[800], + // Override input + input: { + background: oceanColors.slate[900], + border: oceanColors.slate[700], + text: "#e0f2fe", + // sky-100 + placeholder: "#0c4a6e" + // sky-900 + }, + // Override text colors (cooler) + text: { + primary: "#e0f2fe", + // sky-100 + secondary: "#7dd3fc", + // sky-300 + tertiary: "#38bdf8", + // sky-400 + disabled: "#0c4a6e", + // sky-900 + inverse: oceanColors.slate[950] + }, + // Primary: Teal + primary: { + default: oceanColors.teal[400], + hover: oceanColors.teal[300], + active: oceanColors.teal[500], + light: oceanColors.teal[200], + dark: oceanColors.teal[600], + contrast: baseColors.white + }, + // Secondary: Cyan + secondary: { + default: oceanColors.cyan[400], + light: oceanColors.cyan[300], + dark: oceanColors.cyan[500], + contrast: baseColors.white + }, + // Status + success: baseColors.emerald[500], + warning: "#fbbf24", + // amber-400 + error: "#f43f5e", + // rose-500 + info: "#0ea5e9", + // sky-500 + // Semantic + favorite: "#f43f5e", + // rose-500 + like: "#f43f5e", + // rose-500 + tag: oceanColors.teal[400], + // Special + skeleton: oceanColors.slate[800], + shimmer: oceanColors.slate[700] + } + }, + shadows, + opacity }; // src/themes/index.ts var themes = { - default: defaultTheme, - sunset: sunsetTheme, - ocean: oceanTheme, + default: defaultTheme, + sunset: sunsetTheme, + ocean: oceanTheme }; // src/spacing.ts var spacing = { - 0: 0, - 1: 4, - // 0.25rem - 2: 8, - // 0.5rem - 3: 12, - // 0.75rem - 4: 16, - // 1rem - 5: 20, - // 1.25rem - 6: 24, - // 1.5rem - 7: 28, - // 1.75rem - 8: 32, - // 2rem - 9: 36, - // 2.25rem - 10: 40, - // 2.5rem - 11: 44, - // 2.75rem - 12: 48, - // 3rem - 14: 56, - // 3.5rem - 16: 64, - // 4rem - 20: 80, - // 5rem - 24: 96, - // 6rem - 28: 112, - // 7rem - 32: 128, - // 8rem + 0: 0, + 1: 4, + // 0.25rem + 2: 8, + // 0.5rem + 3: 12, + // 0.75rem + 4: 16, + // 1rem + 5: 20, + // 1.25rem + 6: 24, + // 1.5rem + 7: 28, + // 1.75rem + 8: 32, + // 2rem + 9: 36, + // 2.25rem + 10: 40, + // 2.5rem + 11: 44, + // 2.75rem + 12: 48, + // 3rem + 14: 56, + // 3.5rem + 16: 64, + // 4rem + 20: 80, + // 5rem + 24: 96, + // 6rem + 28: 112, + // 7rem + 32: 128 + // 8rem }; var borderRadius = { - none: 0, - sm: 4, - DEFAULT: 8, - md: 8, - lg: 12, - xl: 16, - '2xl': 24, - '3xl': 32, - full: 9999, + none: 0, + sm: 4, + DEFAULT: 8, + md: 8, + lg: 12, + xl: 16, + "2xl": 24, + "3xl": 32, + full: 9999 }; // src/typography.ts var fontSize = { - xs: 12, - sm: 14, - base: 16, - lg: 18, - xl: 20, - '2xl': 24, - '3xl': 30, - '4xl': 36, - '5xl': 48, - '6xl': 60, - '7xl': 72, - '8xl': 96, + xs: 12, + sm: 14, + base: 16, + lg: 18, + xl: 20, + "2xl": 24, + "3xl": 30, + "4xl": 36, + "5xl": 48, + "6xl": 60, + "7xl": 72, + "8xl": 96 }; var fontWeight = { - regular: '400', - medium: '500', - semibold: '600', - bold: '700', + regular: "400", + medium: "500", + semibold: "600", + bold: "700" }; // native/theme.ts -function getThemeColors(variant = 'default', mode = 'dark') { - const theme = themes[variant]; - return theme.colors[mode]; +function getThemeColors(variant = "default", mode = "dark") { + const theme = themes[variant]; + return theme.colors[mode]; } -function createNativeTheme(variant = 'default', mode = 'dark') { - const theme = themes[variant]; - const colors = theme.colors[mode]; - const shadows2 = theme.shadows[mode]; - return { - variant, - mode, - colors, - spacing, - borderRadius, - fontSize, - fontWeight, - shadows: shadows2, - opacity: theme.opacity, - }; +function createNativeTheme(variant = "default", mode = "dark") { + const theme = themes[variant]; + const colors = theme.colors[mode]; + const shadows2 = theme.shadows[mode]; + return { + variant, + mode, + colors, + spacing, + borderRadius, + fontSize, + fontWeight, + shadows: shadows2, + opacity: theme.opacity + }; } function getThemeVariants() { - return Object.keys(themes); + return Object.keys(themes); } function isValidThemeVariant(variant) { - return variant in themes; + return variant in themes; } // Annotate the CommonJS export names for ESM import in node: -0 && - (module.exports = { - createNativeTheme, - getThemeColors, - getThemeVariants, - isValidThemeVariant, - }); +0 && (module.exports = { + createNativeTheme, + getThemeColors, + getThemeVariants, + isValidThemeVariant +}); diff --git a/docs/MICROSERVICES_API_OVERVIEW.md b/docs/MICROSERVICES_API_OVERVIEW.md new file mode 100644 index 000000000..d4553f28b --- /dev/null +++ b/docs/MICROSERVICES_API_OVERVIEW.md @@ -0,0 +1,466 @@ +# ManaCore Microservices - API Overview + +Dieses Dokument gibt einen Überblick über alle Microservices im ManaCore-Monorepo und beschreibt Optionen, diese als öffentliche APIs anzubieten. + +## Inhaltsverzeichnis + +1. [Service-Übersicht](#service-übersicht) +2. [Core Services (API-fähig)](#core-services-api-fähig) +3. [Bot Services](#bot-services) +4. [Aktuelle Architektur](#aktuelle-architektur) +5. [API-Strategien](#api-strategien) +6. [Empfehlung](#empfehlung) + +--- + +## Service-Übersicht + +| Service | Port | Typ | API-Ready | Beschreibung | +|---------|------|-----|-----------|--------------| +| **mana-core-auth** | 3001 | NestJS | ✅ | Zentrale Authentifizierung & Credits | +| **mana-search** | 3021 | NestJS | ✅ | Web-Suche & Content-Extraktion | +| **mana-stt** | 3020 | FastAPI | ✅ | Speech-to-Text (Whisper, Voxtral) | +| **mana-tts** | 3022 | FastAPI | ✅ | Text-to-Speech (Kokoro, F5-TTS) | +| Matrix Bots | 3310-3318 | NestJS | ❌ | Matrix-basierte Bots | +| Telegram Bots | 3300-3304 | NestJS | ❌ | Telegram-basierte Bots | + +--- + +## Core Services (API-fähig) + +Diese Services haben bereits REST-APIs und eignen sich für öffentliche Bereitstellung: + +### 1. mana-core-auth (Port 3001) + +**Zweck:** Zentrale Authentifizierung, JWT-Tokens, Credit-System + +**Endpoints:** +``` +POST /api/v1/auth/register - Benutzer registrieren +POST /api/v1/auth/login - Login (JWT erhalten) +POST /api/v1/auth/validate - Token validieren +POST /api/v1/auth/refresh - Token erneuern +GET /api/v1/auth/jwks - JWKS für Token-Verifikation +GET /api/v1/credits/balance - Credit-Guthaben +POST /api/v1/credits/use - Credits verbrauchen +``` + +**Stack:** NestJS + Better Auth + Drizzle + PostgreSQL + Redis + +--- + +### 2. mana-search (Port 3021) + +**Zweck:** Meta-Suchmaschine mit Content-Extraktion + +**Endpoints:** +``` +POST /api/v1/search - Web-Suche (Google, Bing, DuckDuckGo, etc.) +POST /api/v1/extract - URL-Inhalt extrahieren (Markdown) +POST /api/v1/extract/bulk - Bulk-Extraktion (max 20 URLs) +GET /api/v1/search/engines - Verfügbare Suchmaschinen +GET /health - Health Check +GET /metrics - Prometheus Metriken +``` + +**Stack:** NestJS + SearXNG + Redis (Cache: 1h Suche, 24h Extraktion) + +**Beispiel-Request:** +```json +POST /api/v1/search +{ + "query": "machine learning", + "options": { + "categories": ["general", "science"], + "engines": ["google", "wikipedia"], + "limit": 10 + } +} +``` + +--- + +### 3. mana-stt (Port 3020) + +**Zweck:** Audio-Transkription (optimiert für Deutsch) + +**Endpoints:** +``` +POST /transcribe - Whisper Large V3 Turbo +POST /transcribe/voxtral - Voxtral Mini (3B) +POST /transcribe/auto - Automatische Modellwahl +GET /models - Verfügbare Modelle +GET /health - Health Check +``` + +**Unterstützte Formate:** MP3, WAV, M4A, FLAC, OGG, WebM, MP4 (max 100MB) + +**Stack:** Python + FastAPI + MLX (Apple Silicon optimiert) + +**Beispiel-Request:** +```bash +curl -X POST http://localhost:3020/transcribe \ + -F "file=@audio.mp3" \ + -F "language=de" +``` + +--- + +### 4. mana-tts (Port 3022) + +**Zweck:** Text-zu-Sprache Synthese + +**Endpoints:** +``` +POST /synthesize/kokoro - Schnelle Preset-Stimmen (30+) +POST /synthesize - F5-TTS Voice Cloning +POST /synthesize/auto - Automatische Modellwahl +GET /voices - Alle verfügbaren Stimmen +POST /voices - Custom Voice registrieren +DELETE /voices/{id} - Custom Voice löschen +GET /health - Health Check +``` + +**Modelle:** +- Kokoro-82M (~300MB): 30+ Preset-Stimmen, schnell +- F5-TTS (~6GB): Voice Cloning mit Referenz-Audio + +**Stack:** Python + FastAPI + MLX (Apple Silicon optimiert) + +**Beispiel-Request:** +```json +POST /synthesize/kokoro +{ + "text": "Hallo Welt", + "voice": "af_heart", + "speed": 1.0, + "output_format": "mp3" +} +``` + +--- + +## Bot Services + +Diese Services sind für Matrix/Telegram konzipiert, nicht als direkte APIs: + +| Bot | Port | Funktion | +|-----|------|----------| +| matrix-mana-bot | 3310 | All-in-One (AI, Todos, Kalender) | +| matrix-ollama-bot | 3311 | LLM Chat (lokales Ollama) | +| matrix-stats-bot | 3312 | Analytics Reports | +| matrix-project-doc-bot | 3313 | Blog-Generierung | +| matrix-todo-bot | 3314 | Task Management | +| matrix-calendar-bot | 3315 | Kalender/Events | +| matrix-nutriphi-bot | 3316 | Ernährungs-Tracking | +| matrix-zitare-bot | 3317 | Zitate | +| matrix-clock-bot | 3318 | Timer/Alarme | +| matrix-tts-bot | 3023 | Sprachausgabe | + +--- + +## Aktuelle Architektur + +``` + ┌──────────────────────────────────┐ + │ Clients │ + │ (Web, Mobile, Bots) │ + └────────────┬─────────────────────┘ + │ + ┌────────────────────┼────────────────────┐ + │ │ │ + ▼ ▼ ▼ + ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ + │ mana-core-auth│ │ mana-search │ │ mana-stt │ + │ Port 3001 │ │ Port 3021 │ │ Port 3020 │ + │ │ │ │ │ │ + │ • Auth/JWT │ │ • Web Search │ │ • Whisper │ + │ • Credits │ │ • Extraction │ │ • Voxtral │ + │ • Stripe │ │ • SearXNG │ │ │ + └───────────────┘ └───────────────┘ └───────────────┘ + │ │ + │ ┌───────────────────┤ + │ │ │ + ▼ ▼ ▼ + ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ + │ mana-tts │ │ Matrix Bots │ │ Telegram Bots │ + │ Port 3022 │ │ (10 Bots) │ │ (6 Bots) │ + │ │ │ │ │ │ + │ • Kokoro │ │ • GDPR-konform│ │ • Cloud-based │ + │ • F5-TTS │ │ • Self-hosted │ │ │ + └───────────────┘ └───────────────┘ └───────────────┘ +``` + +--- + +## API-Strategien + +### Option 1: Direkte Exposition (Einfach) + +**Beschreibung:** Jeden Service direkt über eigenen Port/Subdomain exponieren. + +``` +api.mana.how/auth → mana-core-auth:3001 +api.mana.how/search → mana-search:3021 +api.mana.how/stt → mana-stt:3020 +api.mana.how/tts → mana-tts:3022 +``` + +**Vorteile:** +- Schnell umzusetzen +- Kein zusätzlicher Service +- Einfaches Debugging + +**Nachteile:** +- Keine zentrale Rate-Limiting +- Keine einheitliche Auth +- Kein API-Key Management +- Schwierige Abrechnung + +**Aufwand:** ~1-2 Tage (Nginx/Traefik Konfiguration) + +--- + +### Option 2: API Gateway (Kong, Traefik, etc.) + +**Beschreibung:** Zentraler Gateway vor allen Services. + +``` + ┌─────────────────┐ + │ API Gateway │ + │ (Kong/Traefik)│ + │ │ + │ • Rate Limiting │ + │ • API Keys │ + │ • Logging │ + │ • Metrics │ + └────────┬────────┘ + │ + ┌────────────────────┼────────────────────┐ + │ │ │ + ▼ ▼ ▼ + mana-auth mana-search mana-stt +``` + +**Vorteile:** +- Zentrale Authentifizierung +- Rate Limiting pro API-Key +- Request/Response Logging +- Einfache Abrechnung möglich +- SSL-Terminierung + +**Nachteile:** +- Zusätzliche Infrastruktur +- Mehr Komplexität +- Single Point of Failure + +**Empfohlene Tools:** +| Tool | Beschreibung | Aufwand | +|------|--------------|---------| +| **Kong** | Enterprise-ready, Plugin-System | Mittel | +| **Traefik** | Kubernetes-nativ, einfach | Gering | +| **APISIX** | High-performance, Lua-Plugins | Mittel | +| **Tyk** | Open Source, Dashboard | Mittel | + +**Aufwand:** ~3-5 Tage + +--- + +### Option 3: Custom API Service (NestJS) + +**Beschreibung:** Eigener API-Service als Facade vor den Microservices. + +```typescript +// api-gateway/src/app.module.ts +@Module({ + imports: [ + AuthModule, // API Key Validation + RateLimitModule, // Redis-based rate limiting + SearchModule, // Proxy zu mana-search + SttModule, // Proxy zu mana-stt + TtsModule, // Proxy zu mana-tts + BillingModule, // Credit/Usage tracking + ], +}) +export class AppModule {} +``` + +**Features:** +- API-Key Management (eigene DB-Tabelle) +- Usage Tracking pro Key +- Credit-System Integration +- Flexible Rate Limits +- Custom Transformationen + +**Vorteile:** +- Volle Kontrolle +- Integration mit mana-core-auth +- TypeScript/NestJS Konsistenz +- Einfache Erweiterung + +**Nachteile:** +- Mehr Entwicklungsaufwand +- Eigene Wartung + +**Aufwand:** ~1-2 Wochen + +--- + +### Option 4: Serverless/Edge (Cloudflare Workers) + +**Beschreibung:** Edge-basierter API-Proxy mit Cloudflare Workers. + +```javascript +// workers/api-proxy/src/index.ts +export default { + async fetch(request, env) { + const apiKey = request.headers.get('X-API-Key'); + + // Rate limiting via KV + const rateLimit = await env.RATE_LIMITS.get(apiKey); + if (rateLimit > 1000) { + return new Response('Rate limit exceeded', { status: 429 }); + } + + // Route to backend + const url = new URL(request.url); + if (url.pathname.startsWith('/v1/search')) { + return fetch(`https://search.internal.mana.how${url.pathname}`, request); + } + // ... + } +}; +``` + +**Vorteile:** +- Global verteilt (Edge) +- Sehr schnell +- Auto-Scaling +- DDoS-Schutz inklusive + +**Nachteile:** +- Vendor Lock-in +- Begrenzte Rechenzeit (50ms CPU) +- Nicht für lange Requests (STT/TTS) + +**Aufwand:** ~3-5 Tage + +--- + +### Option 5: Managed API Platform (Rapid API, etc.) + +**Beschreibung:** APIs auf Marketplace-Plattform veröffentlichen. + +**Plattformen:** +| Plattform | Vorteile | Nachteile | +|-----------|----------|-----------| +| **RapidAPI** | Große Reichweite, Abrechnung | 20% Commission | +| **AWS API Gateway** | AWS-Integration | Komplexität | +| **Google Cloud Endpoints** | GCP-Integration | Vendor Lock-in | +| **Azure API Management** | Enterprise Features | Kosten | + +**Vorteile:** +- Sofortige Monetarisierung +- Bestehendes Billing +- Marketing/Discovery + +**Nachteile:** +- Hohe Gebühren (15-20%) +- Weniger Kontrolle +- Vendor Lock-in + +**Aufwand:** ~1 Woche + +--- + +## Empfehlung + +### Kurzfristig (MVP): Option 2 - Traefik API Gateway + +```yaml +# docker-compose.api.yml +services: + traefik: + image: traefik:v3.0 + command: + - "--api.dashboard=true" + - "--providers.docker=true" + - "--entrypoints.websecure.address=:443" + ports: + - "443:443" + labels: + - "traefik.http.middlewares.api-auth.plugin.apikey.headerName=X-API-Key" + - "traefik.http.middlewares.rate-limit.ratelimit.average=100" + + mana-search: + labels: + - "traefik.http.routers.search.rule=Host(`api.mana.how`) && PathPrefix(`/v1/search`)" + - "traefik.http.routers.search.middlewares=api-auth,rate-limit" +``` + +**Warum Traefik?** +- Bereits im Stack (Docker-native) +- Einfache Konfiguration via Labels +- Built-in Rate Limiting +- Let's Encrypt Integration +- Dashboard für Monitoring + +**Aufwand:** ~2-3 Tage + +--- + +### Mittelfristig: Option 3 - Custom NestJS Gateway + +Sobald komplexere Anforderungen entstehen: +- Flexible Pricing Tiers +- Usage-based Billing +- Webhook-Integrationen +- SDK-Generierung + +**Struktur:** +``` +services/ + mana-api-gateway/ + src/ + modules/ + auth/ # API Key Management + billing/ # Usage Tracking + proxy/ # Service Proxying + guards/ + api-key.guard.ts + rate-limit.guard.ts +``` + +--- + +## Nächste Schritte + +1. **Entscheidung:** Welche Option passt am besten? +2. **API Design:** OpenAPI Spec für alle Endpoints +3. **Pricing:** Tier-Modell definieren (Free/Pro/Enterprise) +4. **Documentation:** API-Docs mit Redoc/Swagger +5. **SDK:** Client-Libraries generieren (TypeScript, Python) + +--- + +## Anhang: Port-Übersicht + +| Port | Service | Typ | +|------|---------|-----| +| 3001 | mana-core-auth | Auth | +| 3020 | mana-stt | AI/ML | +| 3021 | mana-search | Search | +| 3022 | mana-tts | AI/ML | +| 3023 | matrix-tts-bot | Bot | +| 3300 | telegram-stats-bot | Bot | +| 3301 | telegram-ollama-bot | Bot | +| 3304 | telegram-todo-bot | Bot | +| 3310 | matrix-mana-bot | Bot | +| 3311 | matrix-ollama-bot | Bot | +| 3312 | matrix-stats-bot | Bot | +| 3313 | matrix-project-doc-bot | Bot | +| 3314 | matrix-todo-bot | Bot | +| 3315 | matrix-calendar-bot | Bot | +| 3316 | matrix-nutriphi-bot | Bot | +| 3317 | matrix-zitare-bot | Bot | +| 3318 | matrix-clock-bot | Bot | diff --git a/services/matrix-tts-bot/data/bot-storage.json b/services/matrix-tts-bot/data/bot-storage.json index 899ce4df1..0fee43b1f 100644 --- a/services/matrix-tts-bot/data/bot-storage.json +++ b/services/matrix-tts-bot/data/bot-storage.json @@ -1,7 +1,7 @@ { - "syncToken": "s418_17406_0_34_85_1_3_40_0_1_2", - "filter": null, - "appserviceUsers": {}, - "appserviceTransactions": {}, - "kvStore": {} -} + "syncToken": "s467_19128_20_46_85_1_3_41_0_1_2", + "filter": null, + "appserviceUsers": {}, + "appserviceTransactions": {}, + "kvStore": {} +} \ No newline at end of file