mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 01:41:08 +02:00
Backend: - Add Gemini-powered profile generation (text + image) - Add image processing with background removal (sharp) - Add S3 storage service for figure images - Extend figures schema with generatedProfile, language, status columns - Wire up synchronous generation pipeline on POST /api/v1/figures Frontend (Mobile + Web): - Replace all mock data with real API calls - Show generatedProfile data (subtitle, backstory, stats, items, specialAttack) - Display generated images from S3 or name placeholders - Create web API service ($lib/api.ts) - Delete mock cards data files Infrastructure: - Add CORS origin for web dev port (5196) - Add GEMINI_API_KEY + FIGGOS_STORAGE_PUBLIC_URL to env generation - Add figgos-storage bucket to shared-storage factory - Add .gitignore for workbench/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
749 lines
24 KiB
JavaScript
749 lines
24 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Environment Variable Generator
|
|
*
|
|
* Reads from .env.development and generates app-specific .env files
|
|
* with the appropriate prefixes for each platform.
|
|
*
|
|
* Usage: pnpm setup:env
|
|
*/
|
|
|
|
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
import { join, dirname } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const ROOT_DIR = join(__dirname, '..');
|
|
const ENV_FILE = join(ROOT_DIR, '.env.development');
|
|
|
|
// Parse a .env file into an object
|
|
function parseEnvFile(content) {
|
|
const env = {};
|
|
const lines = content.split('\n');
|
|
|
|
for (const line of lines) {
|
|
const trimmed = line.trim();
|
|
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
|
|
const match = trimmed.match(/^([^=]+)=(.*)$/);
|
|
if (match) {
|
|
let [, key, value] = match;
|
|
// Handle quoted values
|
|
if (
|
|
(value.startsWith('"') && value.endsWith('"')) ||
|
|
(value.startsWith("'") && value.endsWith("'"))
|
|
) {
|
|
value = value.slice(1, -1);
|
|
}
|
|
env[key.trim()] = value;
|
|
}
|
|
}
|
|
return env;
|
|
}
|
|
|
|
// Generate env file content
|
|
function generateEnvContent(vars) {
|
|
const lines = ['# Auto-generated by scripts/generate-env.mjs', '# Source: .env.development', ''];
|
|
for (const [key, value] of Object.entries(vars)) {
|
|
// Quote values that contain special characters or newlines
|
|
const needsQuotes = value.includes('\n') || value.includes(' ') || value.includes('#');
|
|
const formattedValue = needsQuotes ? `"${value}"` : value;
|
|
lines.push(`${key}=${formattedValue}`);
|
|
}
|
|
return lines.join('\n') + '\n';
|
|
}
|
|
|
|
// App configurations - maps source variables to target variables
|
|
const APP_CONFIGS = [
|
|
// Mana Core Auth Service
|
|
{
|
|
path: 'services/mana-core-auth/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.MANA_CORE_AUTH_PORT || '3001',
|
|
DATABASE_URL: (env) => env.MANA_CORE_AUTH_DATABASE_URL,
|
|
REDIS_HOST: (env) => env.REDIS_HOST,
|
|
REDIS_PORT: (env) => env.REDIS_PORT,
|
|
REDIS_PASSWORD: (env) => env.REDIS_PASSWORD || '',
|
|
JWT_PRIVATE_KEY: (env) => env.JWT_PRIVATE_KEY,
|
|
JWT_PUBLIC_KEY: (env) => env.JWT_PUBLIC_KEY,
|
|
JWT_ACCESS_TOKEN_EXPIRY: (env) => env.JWT_ACCESS_TOKEN_EXPIRY,
|
|
JWT_REFRESH_TOKEN_EXPIRY: (env) => env.JWT_REFRESH_TOKEN_EXPIRY,
|
|
JWT_ISSUER: (env) => env.JWT_ISSUER,
|
|
JWT_AUDIENCE: (env) => env.JWT_AUDIENCE,
|
|
STRIPE_SECRET_KEY: (env) => env.STRIPE_SECRET_KEY,
|
|
STRIPE_PUBLISHABLE_KEY: (env) => env.STRIPE_PUBLISHABLE_KEY,
|
|
STRIPE_WEBHOOK_SECRET: (env) => env.STRIPE_WEBHOOK_SECRET,
|
|
CORS_ORIGINS: (env) => env.CORS_ORIGINS,
|
|
CREDITS_SIGNUP_BONUS: (env) => env.CREDITS_SIGNUP_BONUS,
|
|
CREDITS_DAILY_FREE: (env) => env.CREDITS_DAILY_FREE,
|
|
RATE_LIMIT_TTL: (env) => env.RATE_LIMIT_TTL,
|
|
RATE_LIMIT_MAX: (env) => env.RATE_LIMIT_MAX,
|
|
GOOGLE_GENAI_API_KEY: (env) => env.GOOGLE_GENAI_API_KEY,
|
|
},
|
|
},
|
|
|
|
// Chat Backend
|
|
{
|
|
path: 'apps/chat/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.CHAT_BACKEND_PORT || '3002',
|
|
DEV_BYPASS_AUTH: () => 'true',
|
|
DEV_USER_ID: (env) => env.DEV_USER_ID || '00000000-0000-0000-0000-000000000000',
|
|
OPENROUTER_API_KEY: (env) => env.OPENROUTER_API_KEY,
|
|
OLLAMA_URL: (env) => env.OLLAMA_URL || 'http://localhost:11434',
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
DATABASE_URL: (env) => env.CHAT_DATABASE_URL,
|
|
},
|
|
},
|
|
|
|
// Chat Mobile (Expo)
|
|
{
|
|
path: 'apps/chat/apps/mobile/.env',
|
|
vars: {
|
|
EXPO_PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
EXPO_PUBLIC_SUPABASE_URL: (env) => env.CHAT_SUPABASE_URL,
|
|
EXPO_PUBLIC_SUPABASE_ANON_KEY: (env) => env.CHAT_SUPABASE_ANON_KEY,
|
|
EXPO_PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.CHAT_BACKEND_PORT || '3002'}`,
|
|
},
|
|
},
|
|
|
|
// Chat Web (SvelteKit)
|
|
{
|
|
path: 'apps/chat/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
PUBLIC_SUPABASE_URL: (env) => env.CHAT_SUPABASE_URL,
|
|
PUBLIC_SUPABASE_ANON_KEY: (env) => env.CHAT_SUPABASE_ANON_KEY,
|
|
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.CHAT_BACKEND_PORT || '3002'}`,
|
|
},
|
|
},
|
|
|
|
// Manacore Mobile
|
|
{
|
|
path: 'apps/manacore/apps/mobile/.env',
|
|
vars: {
|
|
EXPO_PUBLIC_SUPABASE_URL: (env) => env.MANACORE_SUPABASE_URL,
|
|
EXPO_PUBLIC_SUPABASE_ANON_KEY: (env) => env.MANACORE_SUPABASE_ANON_KEY,
|
|
},
|
|
},
|
|
|
|
// Manacore Web
|
|
{
|
|
path: 'apps/manacore/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_SUPABASE_URL: (env) => env.MANACORE_SUPABASE_URL,
|
|
PUBLIC_SUPABASE_ANON_KEY: (env) => env.MANACORE_SUPABASE_ANON_KEY,
|
|
MIDDLEWARE_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Memoro Mobile
|
|
{
|
|
path: 'apps/memoro/apps/mobile/.env',
|
|
vars: {
|
|
EXPO_PUBLIC_SUPABASE_URL: (env) => env.MEMORO_SUPABASE_URL,
|
|
EXPO_PUBLIC_SUPABASE_ANON_KEY: (env) => env.MEMORO_SUPABASE_ANON_KEY,
|
|
EXPO_PUBLIC_MIDDLEWARE_API_URL: (env) => env.MEMORO_MIDDLEWARE_API_URL,
|
|
EXPO_PUBLIC_APPID: (env) => env.MEMORO_APPID,
|
|
},
|
|
},
|
|
|
|
// Memoro Web
|
|
{
|
|
path: 'apps/memoro/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_SUPABASE_URL: (env) => env.MEMORO_SUPABASE_URL,
|
|
PUBLIC_SUPABASE_ANON_KEY: (env) => env.MEMORO_SUPABASE_ANON_KEY,
|
|
},
|
|
},
|
|
|
|
// Manadeck Backend
|
|
{
|
|
path: 'apps/manadeck/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.MANADECK_BACKEND_PORT || '3004',
|
|
DATABASE_URL: (env) => env.MANADECK_DATABASE_URL,
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
APP_ID: (env) => env.MANADECK_APP_ID,
|
|
GOOGLE_GENAI_API_KEY: (env) => env.GOOGLE_GENAI_API_KEY,
|
|
},
|
|
},
|
|
|
|
// Manadeck Web
|
|
{
|
|
path: 'apps/manadeck/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_SUPABASE_URL: (env) => env.MANADECK_SUPABASE_URL,
|
|
PUBLIC_SUPABASE_ANON_KEY: (env) => env.MANADECK_SUPABASE_ANON_KEY,
|
|
PUBLIC_API_URL: (env) => `http://localhost:${env.MANADECK_BACKEND_PORT || '3004'}`,
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Picture Backend (NestJS)
|
|
{
|
|
path: 'apps/picture/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.PICTURE_BACKEND_PORT || '3006',
|
|
BACKEND_URL: (env) => env.PICTURE_BACKEND_URL || 'http://localhost:3006',
|
|
DATABASE_URL: (env) =>
|
|
env.PICTURE_DATABASE_URL || 'postgresql://manacore:devpassword@localhost:5432/picture',
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
DEV_BYPASS_AUTH: () => 'true',
|
|
DEV_USER_ID: (env) => env.DEV_USER_ID || '00000000-0000-0000-0000-000000000000',
|
|
REPLICATE_API_TOKEN: (env) => env.PICTURE_REPLICATE_API_TOKEN,
|
|
CORS_ORIGINS: (env) => env.CORS_ORIGINS,
|
|
// Storage configuration - use shared MinIO for local dev
|
|
STORAGE_MODE: (env) => env.PICTURE_STORAGE_MODE || 's3',
|
|
LOCAL_STORAGE_PATH: (env) => env.PICTURE_LOCAL_STORAGE_PATH || './uploads',
|
|
S3_ENDPOINT: (env) => env.S3_ENDPOINT || 'http://localhost:9000',
|
|
S3_REGION: (env) => env.S3_REGION || 'us-east-1',
|
|
S3_ACCESS_KEY: (env) => env.S3_ACCESS_KEY || 'minioadmin',
|
|
S3_SECRET_KEY: (env) => env.S3_SECRET_KEY || 'minioadmin',
|
|
S3_BUCKET: (env) => env.PICTURE_S3_BUCKET || 'picture-storage',
|
|
STORAGE_PUBLIC_URL: (env) =>
|
|
env.PICTURE_STORAGE_PUBLIC_URL || 'http://localhost:9000/picture-storage',
|
|
// Credit system (for staging)
|
|
APP_ID: (env) => env.PICTURE_APP_ID || 'picture-app',
|
|
MANA_CORE_SERVICE_KEY: (env) => env.PICTURE_MANA_CORE_SERVICE_KEY || '',
|
|
},
|
|
},
|
|
|
|
// Picture Mobile (Expo)
|
|
{
|
|
path: 'apps/picture/apps/mobile/.env',
|
|
vars: {
|
|
EXPO_PUBLIC_BACKEND_URL: (env) => env.PICTURE_BACKEND_URL || 'http://localhost:3003',
|
|
EXPO_PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Picture Web (SvelteKit) - No Supabase, uses Backend API
|
|
{
|
|
path: 'apps/picture/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_BACKEND_URL: (env) => env.PICTURE_BACKEND_URL || 'http://localhost:3003',
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
PUBLIC_GOOGLE_CLIENT_ID: (env) => env.PICTURE_GOOGLE_CLIENT_ID || '',
|
|
PUBLIC_APPLE_CLIENT_ID: (env) => env.PICTURE_APPLE_CLIENT_ID || '',
|
|
},
|
|
},
|
|
|
|
// Nutriphi Backend (NestJS)
|
|
{
|
|
path: 'apps/nutriphi/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.NUTRIPHI_BACKEND_PORT || '3002',
|
|
DATABASE_URL: (env) => env.NUTRIPHI_DATABASE_URL,
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
GEMINI_API_KEY: (env) => env.NUTRIPHI_GEMINI_API_KEY,
|
|
S3_ENDPOINT: (env) => env.NUTRIPHI_S3_ENDPOINT,
|
|
S3_ACCESS_KEY_ID: (env) => env.NUTRIPHI_S3_ACCESS_KEY_ID,
|
|
S3_SECRET_ACCESS_KEY: (env) => env.NUTRIPHI_S3_SECRET_ACCESS_KEY,
|
|
S3_BUCKET_NAME: (env) => env.NUTRIPHI_S3_BUCKET_NAME,
|
|
S3_REGION: (env) => env.NUTRIPHI_S3_REGION,
|
|
S3_PUBLIC_URL: (env) => env.NUTRIPHI_S3_PUBLIC_URL,
|
|
},
|
|
},
|
|
|
|
// Nutriphi Web (SvelteKit)
|
|
{
|
|
path: 'apps/nutriphi/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.NUTRIPHI_BACKEND_PORT || '3002'}`,
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
PUBLIC_MIDDLEWARE_APP_ID: (env) => env.NUTRIPHI_APP_ID || 'nutriphi',
|
|
},
|
|
},
|
|
|
|
// Zitare Backend (NestJS)
|
|
{
|
|
path: 'apps/zitare/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.ZITARE_BACKEND_PORT || '3007',
|
|
DATABASE_URL: (env) => env.ZITARE_DATABASE_URL,
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
DEV_BYPASS_AUTH: () => 'true',
|
|
DEV_USER_ID: (env) => env.DEV_USER_ID || '00000000-0000-0000-0000-000000000000',
|
|
CORS_ORIGINS: (env) => env.CORS_ORIGINS,
|
|
},
|
|
},
|
|
|
|
// Zitare Mobile (Expo)
|
|
{
|
|
path: 'apps/zitare/apps/mobile/.env',
|
|
vars: {
|
|
EXPO_PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.ZITARE_BACKEND_PORT || '3007'}`,
|
|
EXPO_PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Zitare Web (SvelteKit)
|
|
{
|
|
path: 'apps/zitare/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.ZITARE_BACKEND_PORT || '3007'}`,
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Presi Backend (NestJS)
|
|
{
|
|
path: 'apps/presi/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.PRESI_BACKEND_PORT || '3008',
|
|
DATABASE_URL: (env) => env.PRESI_DATABASE_URL,
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
DEV_BYPASS_AUTH: () => 'true',
|
|
DEV_USER_ID: (env) => env.DEV_USER_ID || '00000000-0000-0000-0000-000000000000',
|
|
JWT_PUBLIC_KEY: (env) => env.JWT_PUBLIC_KEY,
|
|
CORS_ORIGINS: (env) => env.CORS_ORIGINS,
|
|
},
|
|
},
|
|
|
|
// Presi Mobile (Expo)
|
|
{
|
|
path: 'apps/presi/apps/mobile/.env',
|
|
vars: {
|
|
EXPO_PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.PRESI_BACKEND_PORT || '3008'}`,
|
|
EXPO_PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Presi Web (SvelteKit)
|
|
{
|
|
path: 'apps/presi/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.PRESI_BACKEND_PORT || '3008'}`,
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// SkillTree Backend (NestJS)
|
|
{
|
|
path: 'apps/skilltree/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.SKILLTREE_BACKEND_PORT || '3024',
|
|
DATABASE_URL: (env) => env.SKILLTREE_DATABASE_URL,
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
DEV_BYPASS_AUTH: () => 'true',
|
|
DEV_USER_ID: (env) => env.DEV_USER_ID || '00000000-0000-0000-0000-000000000000',
|
|
JWT_PUBLIC_KEY: (env) => env.JWT_PUBLIC_KEY,
|
|
CORS_ORIGINS: (env) => env.CORS_ORIGINS,
|
|
},
|
|
},
|
|
|
|
// SkillTree Web (SvelteKit)
|
|
{
|
|
path: 'apps/skilltree/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.SKILLTREE_BACKEND_PORT || '3024'}`,
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Mana Games Backend (NestJS)
|
|
{
|
|
path: 'games/mana-games/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.MANA_GAMES_BACKEND_PORT || '3011',
|
|
// Google Gemini
|
|
GOOGLE_GENAI_API_KEY: (env) => env.MANA_GAMES_GOOGLE_GENAI_API_KEY,
|
|
// Anthropic Claude
|
|
ANTHROPIC_API_KEY: (env) => env.MANA_GAMES_ANTHROPIC_API_KEY,
|
|
// Azure OpenAI
|
|
AZURE_OPENAI_ENDPOINT: (env) => env.MANA_GAMES_AZURE_OPENAI_ENDPOINT,
|
|
AZURE_OPENAI_API_KEY: (env) => env.MANA_GAMES_AZURE_OPENAI_API_KEY,
|
|
AZURE_OPENAI_DEPLOYMENT: (env) => env.MANA_GAMES_AZURE_OPENAI_DEPLOYMENT || 'gpt-4o',
|
|
// GitHub
|
|
GITHUB_TOKEN: (env) => env.MANA_GAMES_GITHUB_TOKEN,
|
|
GITHUB_OWNER: (env) => env.MANA_GAMES_GITHUB_OWNER || 'tillschneider',
|
|
GITHUB_REPO: (env) => env.MANA_GAMES_GITHUB_REPO || 'mana-games',
|
|
CORS_ORIGINS: (env) => env.CORS_ORIGINS,
|
|
},
|
|
},
|
|
|
|
// Mana Games Web (Astro)
|
|
{
|
|
path: 'games/mana-games/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.MANA_GAMES_BACKEND_PORT || '3011'}`,
|
|
},
|
|
},
|
|
|
|
// Calendar Backend (NestJS)
|
|
{
|
|
path: 'apps/calendar/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.CALENDAR_BACKEND_PORT || '3014',
|
|
DATABASE_URL: (env) => env.CALENDAR_DATABASE_URL,
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
DEV_BYPASS_AUTH: () => 'true',
|
|
DEV_USER_ID: (env) => env.DEV_USER_ID || '00000000-0000-0000-0000-000000000000',
|
|
CORS_ORIGINS: (env) => env.CORS_ORIGINS,
|
|
},
|
|
},
|
|
|
|
// Calendar Mobile (Expo)
|
|
{
|
|
path: 'apps/calendar/apps/mobile/.env',
|
|
vars: {
|
|
EXPO_PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.CALENDAR_BACKEND_PORT || '3014'}`,
|
|
EXPO_PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Calendar Web (SvelteKit)
|
|
{
|
|
path: 'apps/calendar/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.CALENDAR_BACKEND_PORT || '3014'}`,
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
PUBLIC_TODO_BACKEND_URL: (env) =>
|
|
env.TODO_BACKEND_URL || `http://localhost:${env.TODO_BACKEND_PORT || '3018'}`,
|
|
// Cross-app integration: Contacts service for birthdays
|
|
PUBLIC_CONTACTS_API_URL: (env) => `http://localhost:${env.CONTACTS_BACKEND_PORT || '3015'}`,
|
|
PUBLIC_CONTACTS_WEB_URL: () => 'http://localhost:5184',
|
|
// Speech-to-Text Service
|
|
PUBLIC_STT_URL: (env) => env.STT_URL || 'http://localhost:3020',
|
|
},
|
|
},
|
|
|
|
// Contacts Backend (NestJS)
|
|
{
|
|
path: 'apps/contacts/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.CONTACTS_BACKEND_PORT || '3015',
|
|
DATABASE_URL: (env) => env.CONTACTS_DATABASE_URL,
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
DEV_BYPASS_AUTH: () => 'true',
|
|
DEV_USER_ID: (env) => env.DEV_USER_ID || '00000000-0000-0000-0000-000000000000',
|
|
S3_ENDPOINT: (env) => env.S3_ENDPOINT,
|
|
S3_REGION: (env) => env.S3_REGION,
|
|
S3_ACCESS_KEY: (env) => env.S3_ACCESS_KEY,
|
|
S3_SECRET_KEY: (env) => env.S3_SECRET_KEY,
|
|
S3_BUCKET: (env) => env.CONTACTS_S3_BUCKET || 'contacts-photos',
|
|
CORS_ORIGINS: (env) => env.CORS_ORIGINS,
|
|
// Google OAuth for contacts import
|
|
GOOGLE_CLIENT_ID: (env) => env.CONTACTS_GOOGLE_CLIENT_ID,
|
|
GOOGLE_CLIENT_SECRET: (env) => env.CONTACTS_GOOGLE_CLIENT_SECRET,
|
|
GOOGLE_REDIRECT_URI: (env) => env.CONTACTS_GOOGLE_REDIRECT_URI,
|
|
},
|
|
},
|
|
|
|
// Contacts Mobile (Expo)
|
|
{
|
|
path: 'apps/contacts/apps/mobile/.env',
|
|
vars: {
|
|
EXPO_PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.CONTACTS_BACKEND_PORT || '3015'}`,
|
|
EXPO_PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Contacts Web (SvelteKit)
|
|
{
|
|
path: 'apps/contacts/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.CONTACTS_BACKEND_PORT || '3015'}`,
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Storage Backend (NestJS)
|
|
{
|
|
path: 'apps/storage/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.STORAGE_BACKEND_PORT || '3016',
|
|
DATABASE_URL: (env) => env.STORAGE_DATABASE_URL,
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
DEV_BYPASS_AUTH: () => 'true',
|
|
DEV_USER_ID: (env) => env.DEV_USER_ID || '00000000-0000-0000-0000-000000000000',
|
|
S3_ENDPOINT: (env) => env.S3_ENDPOINT,
|
|
S3_REGION: (env) => env.S3_REGION,
|
|
S3_ACCESS_KEY: (env) => env.S3_ACCESS_KEY,
|
|
S3_SECRET_KEY: (env) => env.S3_SECRET_KEY,
|
|
STORAGE_S3_PUBLIC_URL: (env) => env.STORAGE_S3_PUBLIC_URL,
|
|
STORAGE_MAX_FILE_SIZE: (env) => env.STORAGE_MAX_FILE_SIZE || '104857600',
|
|
STORAGE_MAX_FILES_PER_UPLOAD: (env) => env.STORAGE_MAX_FILES_PER_UPLOAD || '10',
|
|
CORS_ORIGINS: (env) => env.CORS_ORIGINS,
|
|
},
|
|
},
|
|
|
|
// Storage Web (SvelteKit)
|
|
{
|
|
path: 'apps/storage/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.STORAGE_BACKEND_PORT || '3016'}`,
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Clock Backend (NestJS)
|
|
{
|
|
path: 'apps/clock/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.CLOCK_BACKEND_PORT || '3017',
|
|
DATABASE_URL: (env) => env.CLOCK_DATABASE_URL,
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
DEV_BYPASS_AUTH: () => 'true',
|
|
DEV_USER_ID: (env) => env.DEV_USER_ID || '00000000-0000-0000-0000-000000000000',
|
|
CORS_ORIGINS: (env) => env.CORS_ORIGINS,
|
|
},
|
|
},
|
|
|
|
// Clock Web (SvelteKit)
|
|
{
|
|
path: 'apps/clock/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.CLOCK_BACKEND_PORT || '3017'}`,
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Todo Backend (NestJS)
|
|
{
|
|
path: 'apps/todo/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.TODO_BACKEND_PORT || '3018',
|
|
DATABASE_URL: (env) => env.TODO_DATABASE_URL,
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
DEV_BYPASS_AUTH: () => 'true',
|
|
DEV_USER_ID: (env) => env.DEV_USER_ID || '00000000-0000-0000-0000-000000000000',
|
|
CORS_ORIGINS: (env) => env.CORS_ORIGINS,
|
|
},
|
|
},
|
|
|
|
// Todo Web (SvelteKit)
|
|
{
|
|
path: 'apps/todo/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.TODO_BACKEND_PORT || '3018'}`,
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Moodlit Backend (NestJS)
|
|
{
|
|
path: 'apps/moodlit/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.MOODLIT_BACKEND_PORT || '3012',
|
|
DATABASE_URL: (env) => env.MOODLIT_DATABASE_URL,
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
DEV_BYPASS_AUTH: () => 'true',
|
|
DEV_USER_ID: (env) => env.DEV_USER_ID || '00000000-0000-0000-0000-000000000000',
|
|
CORS_ORIGINS: (env) => env.CORS_ORIGINS,
|
|
},
|
|
},
|
|
|
|
// Moodlit Mobile (Expo)
|
|
{
|
|
path: 'apps/moodlit/apps/mobile/.env',
|
|
vars: {
|
|
EXPO_PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.MOODLIT_BACKEND_PORT || '3012'}`,
|
|
EXPO_PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Moodlit Web (SvelteKit)
|
|
{
|
|
path: 'apps/moodlit/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.MOODLIT_BACKEND_PORT || '3012'}`,
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Finance Backend (NestJS)
|
|
{
|
|
path: 'apps/finance/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.FINANCE_BACKEND_PORT || '3019',
|
|
DATABASE_URL: (env) => env.FINANCE_DATABASE_URL,
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
DEV_BYPASS_AUTH: () => 'true',
|
|
DEV_USER_ID: (env) => env.DEV_USER_ID || '00000000-0000-0000-0000-000000000000',
|
|
CORS_ORIGINS: (env) => env.CORS_ORIGINS,
|
|
},
|
|
},
|
|
|
|
// Finance Mobile (Expo)
|
|
{
|
|
path: 'apps/finance/apps/mobile/.env',
|
|
vars: {
|
|
EXPO_PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.FINANCE_BACKEND_PORT || '3019'}`,
|
|
EXPO_PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Finance Web (SvelteKit)
|
|
{
|
|
path: 'apps/finance/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.FINANCE_BACKEND_PORT || '3019'}`,
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Figgos Backend (NestJS)
|
|
{
|
|
path: 'apps/figgos/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.FIGGOS_BACKEND_PORT || '3025',
|
|
DATABASE_URL: (env) => env.FIGGOS_DATABASE_URL,
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
DEV_BYPASS_AUTH: () => 'true',
|
|
DEV_USER_ID: () => '00000000-0000-0000-0000-000000000000',
|
|
S3_ENDPOINT: (env) => env.S3_ENDPOINT || 'http://localhost:9000',
|
|
S3_REGION: (env) => env.S3_REGION || 'us-east-1',
|
|
S3_ACCESS_KEY: (env) => env.S3_ACCESS_KEY || 'minioadmin',
|
|
S3_SECRET_KEY: (env) => env.S3_SECRET_KEY || 'minioadmin',
|
|
S3_BUCKET: () => 'figgos-storage',
|
|
CORS_ORIGINS: () => 'http://localhost:5196,http://localhost:8081',
|
|
GEMINI_API_KEY: (env) => env.GEMINI_API_KEY,
|
|
FIGGOS_STORAGE_PUBLIC_URL: () => 'http://localhost:9000/figgos-storage',
|
|
},
|
|
},
|
|
|
|
// Figgos Mobile (Expo)
|
|
{
|
|
path: 'apps/figgos/apps/mobile/.env',
|
|
vars: {
|
|
EXPO_PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.FIGGOS_BACKEND_PORT || '3025'}`,
|
|
EXPO_PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
|
|
// Worldream Web (SvelteKit)
|
|
{
|
|
path: 'games/worldream/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_SUPABASE_URL: (env) => env.WORLDREAM_SUPABASE_URL,
|
|
PUBLIC_SUPABASE_ANON_KEY: (env) => env.WORLDREAM_SUPABASE_ANON_KEY,
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
OPENAI_API_KEY: (env) => env.WORLDREAM_OPENAI_API_KEY,
|
|
GEMINI_API_KEY: (env) => env.WORLDREAM_GEMINI_API_KEY,
|
|
REPLICATE_API_TOKEN: (env) => env.WORLDREAM_REPLICATE_API_TOKEN,
|
|
},
|
|
},
|
|
|
|
// TechBase Backend (NestJS)
|
|
{
|
|
path: 'apps/techbase/apps/backend/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.TECHBASE_BACKEND_PORT || '3021',
|
|
DATABASE_URL: (env) => env.TECHBASE_DATABASE_URL,
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
CORS_ORIGINS: () => 'http://localhost:4321,http://localhost:5173',
|
|
},
|
|
},
|
|
|
|
// TechBase Web (Astro)
|
|
{
|
|
path: 'apps/techbase/apps/web/.env',
|
|
vars: {
|
|
PUBLIC_BACKEND_URL: (env) => `http://localhost:${env.TECHBASE_BACKEND_PORT || '3021'}`,
|
|
},
|
|
},
|
|
|
|
// LLM Playground (SvelteKit)
|
|
{
|
|
path: 'services/llm-playground/.env',
|
|
vars: {
|
|
PUBLIC_MANA_LLM_URL: (env) => env.MANA_LLM_URL || 'http://localhost:3025',
|
|
PUBLIC_MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL || 'http://localhost:3001',
|
|
},
|
|
},
|
|
|
|
// Zitare Telegram Bot
|
|
{
|
|
path: 'services/telegram-zitare-bot/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.ZITARE_BOT_PORT || '3303',
|
|
TELEGRAM_BOT_TOKEN: (env) => env.ZITARE_BOT_TELEGRAM_TOKEN,
|
|
DATABASE_URL: (env) => env.ZITARE_BOT_DATABASE_URL,
|
|
},
|
|
},
|
|
|
|
// Todo Telegram Bot
|
|
{
|
|
path: 'services/telegram-todo-bot/.env',
|
|
vars: {
|
|
NODE_ENV: () => 'development',
|
|
PORT: (env) => env.TODO_BOT_PORT || '3304',
|
|
TELEGRAM_BOT_TOKEN: (env) => env.TODO_BOT_TELEGRAM_TOKEN,
|
|
DATABASE_URL: (env) => env.TODO_BOT_DATABASE_URL,
|
|
TODO_API_URL: (env) => env.TODO_BOT_API_URL || 'http://localhost:3018',
|
|
MANA_CORE_AUTH_URL: (env) => env.MANA_CORE_AUTH_URL,
|
|
},
|
|
},
|
|
];
|
|
|
|
function main() {
|
|
console.log('Generating environment files from .env.development...\n');
|
|
|
|
// Check if source file exists
|
|
if (!existsSync(ENV_FILE)) {
|
|
console.error(`Error: ${ENV_FILE} not found.`);
|
|
console.error('Please create .env.development from .env.development.example');
|
|
process.exit(1);
|
|
}
|
|
|
|
// Parse source env file
|
|
const sourceContent = readFileSync(ENV_FILE, 'utf-8');
|
|
const sourceEnv = parseEnvFile(sourceContent);
|
|
|
|
let generated = 0;
|
|
let skipped = 0;
|
|
|
|
for (const config of APP_CONFIGS) {
|
|
const targetPath = join(ROOT_DIR, config.path);
|
|
const targetDir = dirname(targetPath);
|
|
|
|
// Check if target directory exists
|
|
if (!existsSync(targetDir)) {
|
|
console.log(` Skipping ${config.path} (directory not found)`);
|
|
skipped++;
|
|
continue;
|
|
}
|
|
|
|
// Generate variables
|
|
const targetVars = {};
|
|
for (const [key, getter] of Object.entries(config.vars)) {
|
|
const value = getter(sourceEnv);
|
|
if (value !== undefined && value !== null) {
|
|
targetVars[key] = value;
|
|
}
|
|
}
|
|
|
|
// Write file
|
|
const content = generateEnvContent(targetVars);
|
|
writeFileSync(targetPath, content);
|
|
console.log(` Generated ${config.path}`);
|
|
generated++;
|
|
}
|
|
|
|
console.log(`\nDone! Generated ${generated} files, skipped ${skipped}.`);
|
|
console.log('\nNote: Generated .env files are gitignored. Only .env.development is committed.');
|
|
}
|
|
|
|
main();
|