@revealui/setup 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -278,8 +278,8 @@ var OPTIONAL_ENV_VARS = [
278
278
  validator: validators.url
279
279
  },
280
280
  {
281
- name: "NEXT_PUBLIC_SUPABASE_ANON_KEY",
282
- description: "Supabase anonymous key",
281
+ name: "NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY",
282
+ description: "Supabase publishable key (sb_publishable_...)",
283
283
  required: false
284
284
  },
285
285
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/environment/generators.ts","../../src/environment/setup.ts","../../src/utils/logger.ts","../../src/validators/env.ts"],"sourcesContent":["/**\n * Environment secret and password generators\n */\n\nimport { randomBytes } from 'node:crypto'\n\n/**\n * Generates a secure random secret.\n *\n * @param length - Length in bytes (default: 32 bytes = 64 hex chars)\n * @returns Hex-encoded random secret\n *\n * @example\n * ```typescript\n * const secret = generateSecret() // 64 char hex string\n * ```\n */\nexport function generateSecret(length = 32): string {\n return randomBytes(length).toString('hex')\n}\n\n/**\n * Generates a secure password with alphanumeric and special characters.\n *\n * @param length - Password length (default: 16)\n * @returns Random password\n *\n * @example\n * ```typescript\n * const password = generatePassword(16) // e.g., \"aB3!xY9@pQ5#mN7$\"\n * ```\n */\nexport function generatePassword(length = 16): string {\n const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*'\n let password = ''\n const randomValues = randomBytes(length)\n for (let i = 0; i < length; i++) {\n password += chars[randomValues[i] % chars.length]\n }\n return password\n}\n\n/**\n * Updates a value in environment file content.\n *\n * @param content - Original env file content\n * @param key - Environment variable name\n * @param value - New value\n * @returns Updated env file content\n *\n * @example\n * ```typescript\n * const updated = updateEnvValue(content, 'DB_URL', 'postgresql://...')\n * ```\n */\nexport function updateEnvValue(content: string, key: string, value: string): string {\n const regex = new RegExp(`^${key}=.*$`, 'm')\n\n if (regex.test(content)) {\n // Replace existing value\n return content.replace(regex, `${key}=${value}`)\n }\n\n // Add new line at the end\n return `${content.trimEnd()}\\n${key}=${value}\\n`\n}\n\n/**\n * Parses environment file content into key-value pairs.\n *\n * @param content - Environment file content\n * @returns Parsed environment variables\n *\n * @example\n * ```typescript\n * const env = parseEnvContent('DB_URL=postgresql://...\\nAPI_KEY=abc123')\n * // { DB_URL: 'postgresql://...', API_KEY: 'abc123' }\n * ```\n */\nexport function parseEnvContent(content: string): Record<string, string> {\n const env: Record<string, string> = {}\n const lines = content.split('\\n')\n\n for (const line of lines) {\n // Skip comments and empty lines\n const trimmed = line.trim()\n if (!trimmed || trimmed.startsWith('#')) continue\n\n // Parse key=value\n const match = trimmed.match(/^([^=]+)=(.*)$/)\n if (match) {\n const [, key, value] = match\n env[key.trim()] = value.trim()\n }\n }\n\n return env\n}\n","/**\n * Environment setup orchestration\n */\n\nimport { copyFile, readFile, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport inquirer from 'inquirer'\nimport { createLogger } from '../utils/logger.js'\nimport { type EnvVariable, REQUIRED_ENV_VARS, validateEnv } from '../validators/env.js'\nimport { generateSecret, parseEnvContent, updateEnvValue } from './generators.js'\n\nexport interface SetupEnvironmentOptions {\n projectRoot: string\n templatePath?: string\n outputPath?: string\n force?: boolean\n generateOnly?: boolean\n interactive?: boolean\n customVariables?: EnvVariable[]\n logger?: ReturnType<typeof createLogger>\n}\n\nexport interface SetupEnvironmentResult {\n success: boolean\n envPath: string\n missing: string[]\n invalid: string[]\n}\n\n/**\n * Sets up environment variables for a project.\n *\n * @param options - Setup configuration options\n * @returns Setup result with validation info\n *\n * @example\n * ```typescript\n * const result = await setupEnvironment({\n * projectRoot: '/path/to/project',\n * interactive: true\n * })\n * ```\n */\nexport async function setupEnvironment(\n options: SetupEnvironmentOptions,\n): Promise<SetupEnvironmentResult> {\n const {\n projectRoot,\n templatePath = join(projectRoot, '.env.template'),\n outputPath = join(projectRoot, '.env.development.local'),\n force = false,\n generateOnly = false,\n interactive = true,\n customVariables,\n logger = createLogger({ prefix: 'Setup' }),\n } = options\n\n const requiredVars = customVariables || REQUIRED_ENV_VARS\n\n logger.header('Environment Setup')\n\n // Check if template exists\n try {\n await readFile(templatePath, 'utf-8')\n } catch {\n logger.error(`.env.template not found at: ${templatePath}`)\n logger.info('Please ensure .env.template exists in the project root.')\n return {\n success: false,\n envPath: outputPath,\n missing: requiredVars.map((v) => v.name),\n invalid: [],\n }\n }\n\n // Check if output file already exists\n let outputExists = false\n try {\n await readFile(outputPath, 'utf-8')\n outputExists = true\n } catch {\n // File doesn't exist, which is fine\n }\n\n if (outputExists && !force) {\n if (interactive) {\n logger.warn('.env.development.local already exists')\n const { overwrite } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'overwrite',\n message: 'Overwrite existing file?',\n default: false,\n },\n ])\n if (!overwrite) {\n logger.info('Setup cancelled. Use force: true to overwrite.')\n return {\n success: false,\n envPath: outputPath,\n missing: [],\n invalid: [],\n }\n }\n } else {\n // Non-interactive mode without force, don't overwrite\n logger.info('Output file exists. Set force: true to overwrite.')\n return {\n success: false,\n envPath: outputPath,\n missing: [],\n invalid: [],\n }\n }\n }\n\n // Copy template\n logger.info('Copying .env.template to .env.development.local...')\n await copyFile(templatePath, outputPath)\n logger.success('Template copied')\n\n if (generateOnly) {\n // Just generate secrets and update the file\n await generateSecrets(outputPath, logger)\n logger.success('Secrets generated')\n return {\n success: true,\n envPath: outputPath,\n missing: [],\n invalid: [],\n }\n }\n\n // Parse the template to get current values\n let envContent = await readFile(outputPath, 'utf-8')\n const currentEnv = parseEnvContent(envContent)\n\n // Check for missing required values\n const validation = validateEnv(requiredVars, currentEnv)\n\n if (interactive && (validation.missing.length > 0 || validation.invalid.length > 0)) {\n logger.info('Some required values need to be configured:')\n logger.divider()\n\n for (const varName of validation.missing) {\n const variable = requiredVars.find((v) => v.name === varName)\n if (!variable) continue\n\n logger.info(`${varName}: ${variable.description}`)\n\n if (varName === 'REVEALUI_SECRET') {\n // Auto-generate secret\n const secret = generateSecret(32)\n envContent = updateEnvValue(envContent, varName, secret)\n logger.success(`Generated ${varName}`)\n } else {\n // Prompt for value\n const { value } = await inquirer.prompt([\n {\n type: 'input',\n name: 'value',\n message: `Enter value for ${varName}:`,\n validate: (input: string) => {\n if (!input.trim()) {\n return 'Value cannot be empty (press Ctrl+C to skip)'\n }\n if (variable.validator && !variable.validator(input.trim())) {\n return `Invalid format for ${varName}`\n }\n return true\n },\n },\n ])\n\n if (value.trim()) {\n envContent = updateEnvValue(envContent, varName, value.trim())\n logger.success(`Set ${varName}`)\n }\n }\n }\n\n // Save updated content\n await writeFile(outputPath, envContent)\n logger.success('Environment file updated')\n } else if (!interactive && validation.missing.length > 0) {\n // Non-interactive mode with missing values - just generate secrets\n for (const varName of validation.missing) {\n if (varName === 'REVEALUI_SECRET') {\n const secret = generateSecret(32)\n envContent = updateEnvValue(envContent, varName, secret)\n logger.success(`Generated ${varName}`)\n }\n }\n await writeFile(outputPath, envContent)\n }\n\n // Final validation\n const finalContent = await readFile(outputPath, 'utf-8')\n const finalEnv = parseEnvContent(finalContent)\n const finalValidation = validateEnv(requiredVars, finalEnv)\n\n logger.divider()\n\n if (finalValidation.valid) {\n logger.success('Environment setup complete!')\n return {\n success: true,\n envPath: outputPath,\n missing: [],\n invalid: [],\n }\n }\n\n logger.warn('Setup incomplete - some variables still need to be configured:')\n for (const varName of finalValidation.missing) {\n logger.warn(` - ${varName}`)\n }\n logger.info('Edit .env.development.local to add missing values.')\n\n return {\n success: false,\n envPath: outputPath,\n missing: finalValidation.missing,\n invalid: finalValidation.invalid,\n }\n}\n\n/**\n * Generates secrets and updates the env file.\n */\nasync function generateSecrets(\n envPath: string,\n logger: ReturnType<typeof createLogger>,\n): Promise<void> {\n let content = await readFile(envPath, 'utf-8')\n\n // Generate REVEALUI_SECRET\n const secret = generateSecret(32)\n content = updateEnvValue(content, 'REVEALUI_SECRET', secret)\n\n await writeFile(envPath, content)\n logger.success('Generated REVEALUI_SECRET')\n}\n","/**\n * Unified Logger for RevealUI Scripts\n *\n * Provides consistent logging across all scripts with color support,\n * structured output, and log level filtering.\n */\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'\n\nexport interface LoggerOptions {\n level?: LogLevel\n prefix?: string\n colors?: boolean\n timestamps?: boolean\n}\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n}\n\ninterface ColorMap {\n reset: string\n red: string\n green: string\n yellow: string\n blue: string\n cyan: string\n magenta: string\n dim: string\n bold: string\n}\n\nfunction getColors(enabled: boolean): ColorMap {\n if (!enabled) {\n return {\n reset: '',\n red: '',\n green: '',\n yellow: '',\n blue: '',\n cyan: '',\n magenta: '',\n dim: '',\n bold: '',\n }\n }\n return {\n reset: '\\x1b[0m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n cyan: '\\x1b[36m',\n magenta: '\\x1b[35m',\n dim: '\\x1b[2m',\n bold: '\\x1b[1m',\n }\n}\n\nexport interface Logger {\n debug: (msg: string, ...args: unknown[]) => void\n info: (msg: string, ...args: unknown[]) => void\n warn: (msg: string, ...args: unknown[]) => void\n error: (msg: string, ...args: unknown[]) => void\n success: (msg: string, ...args: unknown[]) => void\n warning: (msg: string, ...args: unknown[]) => void\n header: (msg: string) => void\n divider: () => void\n table: (data: Record<string, unknown>[]) => void\n group: (label: string) => void\n groupEnd: () => void\n progress: (current: number, total: number, label?: string) => void\n}\n\n/**\n * Creates a logger instance with configurable options.\n *\n * @example\n * ```typescript\n * const logger = createLogger({ level: 'info', prefix: 'MyScript' })\n * logger.info('Starting process')\n * logger.success('Completed!')\n * ```\n */\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const {\n level = (process.env.LOG_LEVEL as LogLevel) || 'info',\n prefix = '',\n colors = process.env.FORCE_COLOR !== '0' && process.stdout.isTTY !== false,\n timestamps = false,\n } = options\n\n const currentLevel = LOG_LEVELS[level] ?? LOG_LEVELS.info\n const c = getColors(colors)\n\n function shouldLog(msgLevel: LogLevel): boolean {\n return LOG_LEVELS[msgLevel] >= currentLevel\n }\n\n function formatPrefix(): string {\n const parts: string[] = []\n if (timestamps) {\n parts.push(`${c.dim}[${new Date().toISOString()}]${c.reset}`)\n }\n if (prefix) {\n parts.push(`${c.cyan}[${prefix}]${c.reset}`)\n }\n return parts.length > 0 ? `${parts.join(' ')} ` : ''\n }\n\n function formatArgs(args: unknown[]): string {\n if (args.length === 0) return ''\n return (\n ' ' +\n args.map((arg) => (typeof arg === 'object' ? JSON.stringify(arg) : String(arg))).join(' ')\n )\n }\n\n return {\n debug(msg: string, ...args: unknown[]) {\n if (!shouldLog('debug')) return\n console.log(`${formatPrefix()}${c.dim}[DEBUG]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n info(msg: string, ...args: unknown[]) {\n if (!shouldLog('info')) return\n console.log(`${formatPrefix()}${c.blue}[INFO]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n warn(msg: string, ...args: unknown[]) {\n if (!shouldLog('warn')) return\n console.warn(`${formatPrefix()}${c.yellow}[WARN]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n error(msg: string, ...args: unknown[]) {\n if (!shouldLog('error')) return\n console.error(`${formatPrefix()}${c.red}[ERROR]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n success(msg: string, ...args: unknown[]) {\n if (!shouldLog('info')) return\n console.log(`${formatPrefix()}${c.green}[OK]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n warning(msg: string, ...args: unknown[]) {\n this.warn(msg, ...args)\n },\n\n header(msg: string) {\n if (!shouldLog('info')) return\n const line = '='.repeat(msg.length + 4)\n console.log(`\\n${c.cyan}${line}`)\n console.log(`| ${msg} |`)\n console.log(`${line}${c.reset}\\n`)\n },\n\n divider() {\n if (!shouldLog('info')) return\n console.log(`${c.dim}${'─'.repeat(60)}${c.reset}`)\n },\n\n table(data: Record<string, unknown>[]) {\n if (!shouldLog('info')) return\n console.table(data)\n },\n\n group(label: string) {\n if (!shouldLog('info')) return\n console.group(`${c.bold}${label}${c.reset}`)\n },\n\n groupEnd() {\n if (!shouldLog('info')) return\n console.groupEnd()\n },\n\n progress(current: number, total: number, label = '') {\n if (!shouldLog('info')) return\n const percent = Math.round((current / total) * 100)\n const filled = Math.round(percent / 5)\n const empty = 20 - filled\n const bar = `${'█'.repeat(filled)}${'░'.repeat(empty)}`\n const labelText = label ? ` ${label}` : ''\n process.stdout.write(`\\r${c.cyan}${bar}${c.reset} ${percent}%${labelText}`)\n if (current === total) {\n console.log() // New line when complete\n }\n },\n }\n}\n\n/**\n * Standardized error handler for AST parsing errors\n */\nexport function handleASTParseError(filePath: string, error: unknown, logger: Logger): void {\n const message = error instanceof Error ? error.message : String(error)\n logger.warning(`AST Parse Error in ${filePath}: ${message}`)\n}\n\n/**\n * Default logger instance for quick usage\n */\nexport const logger = createLogger()\n","/**\n * Environment variable validation\n */\n\nexport interface EnvVariable {\n name: string\n description: string\n required: boolean\n validator?: (value: string) => boolean\n}\n\nexport interface ValidationResult {\n valid: boolean\n missing: string[]\n invalid: string[]\n}\n\n/**\n * Validates environment variables against required schema.\n *\n * @param required - Array of required environment variable definitions\n * @param env - Environment variable object to validate\n * @returns Validation result\n *\n * @example\n * ```typescript\n * const result = validateEnv([\n * { name: 'DB_URL', description: 'Database URL', required: true }\n * ], process.env)\n * ```\n */\nexport function validateEnv(\n required: EnvVariable[],\n env: Record<string, string | undefined>,\n): ValidationResult {\n const missing: string[] = []\n const invalid: string[] = []\n\n for (const variable of required) {\n const value = env[variable.name]\n\n // Check if required variable is missing\n if (variable.required && (!value || value.trim() === '')) {\n missing.push(variable.name)\n continue\n }\n\n // Check if value passes custom validator\n if (value && variable.validator && !variable.validator(value)) {\n invalid.push(variable.name)\n }\n }\n\n return {\n valid: missing.length === 0 && invalid.length === 0,\n missing,\n invalid,\n }\n}\n\n/**\n * Common environment variable validators\n */\nexport const validators = {\n /**\n * Validates PostgreSQL connection string format\n */\n postgresUrl: (value: string): boolean => {\n try {\n const url = new URL(value)\n return url.protocol === 'postgresql:' || url.protocol === 'postgres:'\n } catch {\n return false\n }\n },\n\n /**\n * Validates Stripe secret key format\n */\n stripeSecretKey: (value: string): boolean => {\n return value.startsWith('sk_test_') || value.startsWith('sk_live_')\n },\n\n /**\n * Validates Stripe publishable key format\n */\n stripePublishableKey: (value: string): boolean => {\n return value.startsWith('pk_test_') || value.startsWith('pk_live_')\n },\n\n /**\n * Validates URL format\n */\n url: (value: string): boolean => {\n try {\n new URL(value)\n return true\n } catch {\n return false\n }\n },\n\n /**\n * Validates minimum length\n */\n minLength:\n (min: number) =>\n (value: string): boolean => {\n return value.length >= min\n },\n\n /**\n * Validates email format\n */\n email: (value: string): boolean => {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n },\n}\n\n/**\n * Common required environment variables for RevealUI\n */\nexport const REQUIRED_ENV_VARS: EnvVariable[] = [\n {\n name: 'REVEALUI_SECRET',\n description: 'Secret key for JWT tokens and session encryption (min 32 chars)',\n required: true,\n validator: validators.minLength(32),\n },\n {\n name: 'POSTGRES_URL',\n description: 'PostgreSQL connection string',\n required: true,\n validator: validators.postgresUrl,\n },\n {\n name: 'BLOB_READ_WRITE_TOKEN',\n description: 'Vercel Blob storage token',\n required: true,\n },\n {\n name: 'STRIPE_SECRET_KEY',\n description: 'Stripe secret key (sk_test_... or sk_live_...)',\n required: true,\n validator: validators.stripeSecretKey,\n },\n {\n name: 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY',\n description: 'Stripe publishable key (pk_test_... or pk_live_...)',\n required: true,\n validator: validators.stripePublishableKey,\n },\n]\n\n/**\n * Optional environment variables\n */\nexport const OPTIONAL_ENV_VARS: EnvVariable[] = [\n {\n name: 'STRIPE_WEBHOOK_SECRET',\n description: 'Stripe webhook secret (whsec_...)',\n required: false,\n },\n {\n name: 'NEXT_PUBLIC_SUPABASE_URL',\n description: 'Supabase project URL',\n required: false,\n validator: validators.url,\n },\n {\n name: 'NEXT_PUBLIC_SUPABASE_ANON_KEY',\n description: 'Supabase anonymous key',\n required: false,\n },\n {\n name: 'REVEALUI_ADMIN_EMAIL',\n description: 'Initial admin email',\n required: false,\n validator: validators.email,\n },\n {\n name: 'REVEALUI_ADMIN_PASSWORD',\n description: 'Initial admin password (min 12 chars)',\n required: false,\n validator: validators.minLength(12),\n },\n]\n"],"mappings":"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","names":["logger"]}
1
+ {"version":3,"sources":["../../src/environment/generators.ts","../../src/environment/setup.ts","../../src/utils/logger.ts","../../src/validators/env.ts"],"sourcesContent":["/**\n * Environment secret and password generators\n */\n\nimport { randomBytes } from 'node:crypto';\n\n/**\n * Generates a secure random secret.\n *\n * @param length - Length in bytes (default: 32 bytes = 64 hex chars)\n * @returns Hex-encoded random secret\n *\n * @example\n * ```typescript\n * const secret = generateSecret() // 64 char hex string\n * ```\n */\nexport function generateSecret(length = 32): string {\n return randomBytes(length).toString('hex');\n}\n\n/**\n * Generates a secure password with alphanumeric and special characters.\n *\n * @param length - Password length (default: 16)\n * @returns Random password\n *\n * @example\n * ```typescript\n * const password = generatePassword(16) // e.g., \"aB3!xY9@pQ5#mN7$\"\n * ```\n */\nexport function generatePassword(length = 16): string {\n const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*';\n let password = '';\n const randomValues = randomBytes(length);\n for (let i = 0; i < length; i++) {\n password += chars[randomValues[i] % chars.length];\n }\n return password;\n}\n\n/**\n * Updates a value in environment file content.\n *\n * @param content - Original env file content\n * @param key - Environment variable name\n * @param value - New value\n * @returns Updated env file content\n *\n * @example\n * ```typescript\n * const updated = updateEnvValue(content, 'DB_URL', 'postgresql://...')\n * ```\n */\nexport function updateEnvValue(content: string, key: string, value: string): string {\n const regex = new RegExp(`^${key}=.*$`, 'm');\n\n if (regex.test(content)) {\n // Replace existing value\n return content.replace(regex, `${key}=${value}`);\n }\n\n // Add new line at the end\n return `${content.trimEnd()}\\n${key}=${value}\\n`;\n}\n\n/**\n * Parses environment file content into key-value pairs.\n *\n * @param content - Environment file content\n * @returns Parsed environment variables\n *\n * @example\n * ```typescript\n * const env = parseEnvContent('DB_URL=postgresql://...\\nAPI_KEY=abc123')\n * // { DB_URL: 'postgresql://...', API_KEY: 'abc123' }\n * ```\n */\nexport function parseEnvContent(content: string): Record<string, string> {\n const env: Record<string, string> = {};\n const lines = content.split('\\n');\n\n for (const line of lines) {\n // Skip comments and empty lines\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n\n // Parse key=value\n const match = trimmed.match(/^([^=]+)=(.*)$/);\n if (match) {\n const [, key, value] = match;\n env[key.trim()] = value.trim();\n }\n }\n\n return env;\n}\n","/**\n * Environment setup orchestration\n */\n\nimport { copyFile, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport inquirer from 'inquirer';\nimport { createLogger } from '../utils/logger.js';\nimport { type EnvVariable, REQUIRED_ENV_VARS, validateEnv } from '../validators/env.js';\nimport { generateSecret, parseEnvContent, updateEnvValue } from './generators.js';\n\nexport interface SetupEnvironmentOptions {\n projectRoot: string;\n templatePath?: string;\n outputPath?: string;\n force?: boolean;\n generateOnly?: boolean;\n interactive?: boolean;\n customVariables?: EnvVariable[];\n logger?: ReturnType<typeof createLogger>;\n}\n\nexport interface SetupEnvironmentResult {\n success: boolean;\n envPath: string;\n missing: string[];\n invalid: string[];\n}\n\n/**\n * Sets up environment variables for a project.\n *\n * @param options - Setup configuration options\n * @returns Setup result with validation info\n *\n * @example\n * ```typescript\n * const result = await setupEnvironment({\n * projectRoot: '/path/to/project',\n * interactive: true\n * })\n * ```\n */\nexport async function setupEnvironment(\n options: SetupEnvironmentOptions,\n): Promise<SetupEnvironmentResult> {\n const {\n projectRoot,\n templatePath = join(projectRoot, '.env.template'),\n outputPath = join(projectRoot, '.env.development.local'),\n force = false,\n generateOnly = false,\n interactive = true,\n customVariables,\n logger = createLogger({ prefix: 'Setup' }),\n } = options;\n\n const requiredVars = customVariables || REQUIRED_ENV_VARS;\n\n logger.header('Environment Setup');\n\n // Check if template exists\n try {\n await readFile(templatePath, 'utf-8');\n } catch {\n logger.error(`.env.template not found at: ${templatePath}`);\n logger.info('Please ensure .env.template exists in the project root.');\n return {\n success: false,\n envPath: outputPath,\n missing: requiredVars.map((v) => v.name),\n invalid: [],\n };\n }\n\n // Check if output file already exists\n let outputExists = false;\n try {\n await readFile(outputPath, 'utf-8');\n outputExists = true;\n } catch {\n // File doesn't exist, which is fine\n }\n\n if (outputExists && !force) {\n if (interactive) {\n logger.warn('.env.development.local already exists');\n const { overwrite } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'overwrite',\n message: 'Overwrite existing file?',\n default: false,\n },\n ]);\n if (!overwrite) {\n logger.info('Setup cancelled. Use force: true to overwrite.');\n return {\n success: false,\n envPath: outputPath,\n missing: [],\n invalid: [],\n };\n }\n } else {\n // Non-interactive mode without force, don't overwrite\n logger.info('Output file exists. Set force: true to overwrite.');\n return {\n success: false,\n envPath: outputPath,\n missing: [],\n invalid: [],\n };\n }\n }\n\n // Copy template\n logger.info('Copying .env.template to .env.development.local...');\n await copyFile(templatePath, outputPath);\n logger.success('Template copied');\n\n if (generateOnly) {\n // Just generate secrets and update the file\n await generateSecrets(outputPath, logger);\n logger.success('Secrets generated');\n return {\n success: true,\n envPath: outputPath,\n missing: [],\n invalid: [],\n };\n }\n\n // Parse the template to get current values\n let envContent = await readFile(outputPath, 'utf-8');\n const currentEnv = parseEnvContent(envContent);\n\n // Check for missing required values\n const validation = validateEnv(requiredVars, currentEnv);\n\n if (interactive && (validation.missing.length > 0 || validation.invalid.length > 0)) {\n logger.info('Some required values need to be configured:');\n logger.divider();\n\n for (const varName of validation.missing) {\n const variable = requiredVars.find((v) => v.name === varName);\n if (!variable) continue;\n\n logger.info(`${varName}: ${variable.description}`);\n\n if (varName === 'REVEALUI_SECRET') {\n // Auto-generate secret\n const secret = generateSecret(32);\n envContent = updateEnvValue(envContent, varName, secret);\n logger.success(`Generated ${varName}`);\n } else {\n // Prompt for value\n const { value } = await inquirer.prompt([\n {\n type: 'input',\n name: 'value',\n message: `Enter value for ${varName}:`,\n validate: (input: string) => {\n if (!input.trim()) {\n return 'Value cannot be empty (press Ctrl+C to skip)';\n }\n if (variable.validator && !variable.validator(input.trim())) {\n return `Invalid format for ${varName}`;\n }\n return true;\n },\n },\n ]);\n\n if (value.trim()) {\n envContent = updateEnvValue(envContent, varName, value.trim());\n logger.success(`Set ${varName}`);\n }\n }\n }\n\n // Save updated content\n await writeFile(outputPath, envContent);\n logger.success('Environment file updated');\n } else if (!interactive && validation.missing.length > 0) {\n // Non-interactive mode with missing values - just generate secrets\n for (const varName of validation.missing) {\n if (varName === 'REVEALUI_SECRET') {\n const secret = generateSecret(32);\n envContent = updateEnvValue(envContent, varName, secret);\n logger.success(`Generated ${varName}`);\n }\n }\n await writeFile(outputPath, envContent);\n }\n\n // Final validation\n const finalContent = await readFile(outputPath, 'utf-8');\n const finalEnv = parseEnvContent(finalContent);\n const finalValidation = validateEnv(requiredVars, finalEnv);\n\n logger.divider();\n\n if (finalValidation.valid) {\n logger.success('Environment setup complete!');\n return {\n success: true,\n envPath: outputPath,\n missing: [],\n invalid: [],\n };\n }\n\n logger.warn('Setup incomplete - some variables still need to be configured:');\n for (const varName of finalValidation.missing) {\n logger.warn(` - ${varName}`);\n }\n logger.info('Edit .env.development.local to add missing values.');\n\n return {\n success: false,\n envPath: outputPath,\n missing: finalValidation.missing,\n invalid: finalValidation.invalid,\n };\n}\n\n/**\n * Generates secrets and updates the env file.\n */\nasync function generateSecrets(\n envPath: string,\n logger: ReturnType<typeof createLogger>,\n): Promise<void> {\n let content = await readFile(envPath, 'utf-8');\n\n // Generate REVEALUI_SECRET\n const secret = generateSecret(32);\n content = updateEnvValue(content, 'REVEALUI_SECRET', secret);\n\n await writeFile(envPath, content);\n logger.success('Generated REVEALUI_SECRET');\n}\n","/**\n * Unified Logger for RevealUI Scripts\n *\n * Provides consistent logging across all scripts with color support,\n * structured output, and log level filtering.\n */\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';\n\nexport interface LoggerOptions {\n level?: LogLevel;\n prefix?: string;\n colors?: boolean;\n timestamps?: boolean;\n}\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n};\n\ninterface ColorMap {\n reset: string;\n red: string;\n green: string;\n yellow: string;\n blue: string;\n cyan: string;\n magenta: string;\n dim: string;\n bold: string;\n}\n\nfunction getColors(enabled: boolean): ColorMap {\n if (!enabled) {\n return {\n reset: '',\n red: '',\n green: '',\n yellow: '',\n blue: '',\n cyan: '',\n magenta: '',\n dim: '',\n bold: '',\n };\n }\n return {\n reset: '\\x1b[0m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n cyan: '\\x1b[36m',\n magenta: '\\x1b[35m',\n dim: '\\x1b[2m',\n bold: '\\x1b[1m',\n };\n}\n\nexport interface Logger {\n debug: (msg: string, ...args: unknown[]) => void;\n info: (msg: string, ...args: unknown[]) => void;\n warn: (msg: string, ...args: unknown[]) => void;\n error: (msg: string, ...args: unknown[]) => void;\n success: (msg: string, ...args: unknown[]) => void;\n warning: (msg: string, ...args: unknown[]) => void;\n header: (msg: string) => void;\n divider: () => void;\n table: (data: Record<string, unknown>[]) => void;\n group: (label: string) => void;\n groupEnd: () => void;\n progress: (current: number, total: number, label?: string) => void;\n}\n\n/**\n * Creates a logger instance with configurable options.\n *\n * @example\n * ```typescript\n * const logger = createLogger({ level: 'info', prefix: 'MyScript' })\n * logger.info('Starting process')\n * logger.success('Completed!')\n * ```\n */\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const {\n level = (process.env.LOG_LEVEL as LogLevel) || 'info',\n prefix = '',\n colors = process.env.FORCE_COLOR !== '0' && process.stdout.isTTY !== false,\n timestamps = false,\n } = options;\n\n const currentLevel = LOG_LEVELS[level] ?? LOG_LEVELS.info;\n const c = getColors(colors);\n\n function shouldLog(msgLevel: LogLevel): boolean {\n return LOG_LEVELS[msgLevel] >= currentLevel;\n }\n\n function formatPrefix(): string {\n const parts: string[] = [];\n if (timestamps) {\n parts.push(`${c.dim}[${new Date().toISOString()}]${c.reset}`);\n }\n if (prefix) {\n parts.push(`${c.cyan}[${prefix}]${c.reset}`);\n }\n return parts.length > 0 ? `${parts.join(' ')} ` : '';\n }\n\n function formatArgs(args: unknown[]): string {\n if (args.length === 0) return '';\n return (\n ' ' +\n args.map((arg) => (typeof arg === 'object' ? JSON.stringify(arg) : String(arg))).join(' ')\n );\n }\n\n return {\n debug(msg: string, ...args: unknown[]) {\n if (!shouldLog('debug')) return;\n console.log(`${formatPrefix()}${c.dim}[DEBUG]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n info(msg: string, ...args: unknown[]) {\n if (!shouldLog('info')) return;\n console.log(`${formatPrefix()}${c.blue}[INFO]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n warn(msg: string, ...args: unknown[]) {\n if (!shouldLog('warn')) return;\n console.warn(`${formatPrefix()}${c.yellow}[WARN]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n error(msg: string, ...args: unknown[]) {\n if (!shouldLog('error')) return;\n console.error(`${formatPrefix()}${c.red}[ERROR]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n success(msg: string, ...args: unknown[]) {\n if (!shouldLog('info')) return;\n console.log(`${formatPrefix()}${c.green}[OK]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n warning(msg: string, ...args: unknown[]) {\n this.warn(msg, ...args);\n },\n\n header(msg: string) {\n if (!shouldLog('info')) return;\n const line = '='.repeat(msg.length + 4);\n console.log(`\\n${c.cyan}${line}`);\n console.log(`| ${msg} |`);\n console.log(`${line}${c.reset}\\n`);\n },\n\n divider() {\n if (!shouldLog('info')) return;\n console.log(`${c.dim}${'─'.repeat(60)}${c.reset}`);\n },\n\n table(data: Record<string, unknown>[]) {\n if (!shouldLog('info')) return;\n console.table(data);\n },\n\n group(label: string) {\n if (!shouldLog('info')) return;\n console.group(`${c.bold}${label}${c.reset}`);\n },\n\n groupEnd() {\n if (!shouldLog('info')) return;\n console.groupEnd();\n },\n\n progress(current: number, total: number, label = '') {\n if (!shouldLog('info')) return;\n const percent = Math.round((current / total) * 100);\n const filled = Math.round(percent / 5);\n const empty = 20 - filled;\n const bar = `${'█'.repeat(filled)}${'░'.repeat(empty)}`;\n const labelText = label ? ` ${label}` : '';\n process.stdout.write(`\\r${c.cyan}${bar}${c.reset} ${percent}%${labelText}`);\n if (current === total) {\n console.log(); // New line when complete\n }\n },\n };\n}\n\n/**\n * Standardized error handler for AST parsing errors\n */\nexport function handleASTParseError(filePath: string, error: unknown, logger: Logger): void {\n const message = error instanceof Error ? error.message : String(error);\n logger.warning(`AST Parse Error in ${filePath}: ${message}`);\n}\n\n/**\n * Default logger instance for quick usage\n */\nexport const logger = createLogger();\n","/**\n * Environment variable validation\n */\n\nexport interface EnvVariable {\n name: string;\n description: string;\n required: boolean;\n validator?: (value: string) => boolean;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n missing: string[];\n invalid: string[];\n}\n\n/**\n * Validates environment variables against required schema.\n *\n * @param required - Array of required environment variable definitions\n * @param env - Environment variable object to validate\n * @returns Validation result\n *\n * @example\n * ```typescript\n * const result = validateEnv([\n * { name: 'DB_URL', description: 'Database URL', required: true }\n * ], process.env)\n * ```\n */\nexport function validateEnv(\n required: EnvVariable[],\n env: Record<string, string | undefined>,\n): ValidationResult {\n const missing: string[] = [];\n const invalid: string[] = [];\n\n for (const variable of required) {\n const value = env[variable.name];\n\n // Check if required variable is missing\n if (variable.required && (!value || value.trim() === '')) {\n missing.push(variable.name);\n continue;\n }\n\n // Check if value passes custom validator\n if (value && variable.validator && !variable.validator(value)) {\n invalid.push(variable.name);\n }\n }\n\n return {\n valid: missing.length === 0 && invalid.length === 0,\n missing,\n invalid,\n };\n}\n\n/**\n * Common environment variable validators\n */\nexport const validators = {\n /**\n * Validates PostgreSQL connection string format\n */\n postgresUrl: (value: string): boolean => {\n try {\n const url = new URL(value);\n return url.protocol === 'postgresql:' || url.protocol === 'postgres:';\n } catch {\n return false;\n }\n },\n\n /**\n * Validates Stripe secret key format\n */\n stripeSecretKey: (value: string): boolean => {\n return value.startsWith('sk_test_') || value.startsWith('sk_live_');\n },\n\n /**\n * Validates Stripe publishable key format\n */\n stripePublishableKey: (value: string): boolean => {\n return value.startsWith('pk_test_') || value.startsWith('pk_live_');\n },\n\n /**\n * Validates URL format\n */\n url: (value: string): boolean => {\n try {\n new URL(value);\n return true;\n } catch {\n return false;\n }\n },\n\n /**\n * Validates minimum length\n */\n minLength:\n (min: number) =>\n (value: string): boolean => {\n return value.length >= min;\n },\n\n /**\n * Validates email format\n */\n email: (value: string): boolean => {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value);\n },\n};\n\n/**\n * Common required environment variables for RevealUI\n */\nexport const REQUIRED_ENV_VARS: EnvVariable[] = [\n {\n name: 'REVEALUI_SECRET',\n description: 'Secret key for JWT tokens and session encryption (min 32 chars)',\n required: true,\n validator: validators.minLength(32),\n },\n {\n name: 'POSTGRES_URL',\n description: 'PostgreSQL connection string',\n required: true,\n validator: validators.postgresUrl,\n },\n {\n name: 'BLOB_READ_WRITE_TOKEN',\n description: 'Vercel Blob storage token',\n required: true,\n },\n {\n name: 'STRIPE_SECRET_KEY',\n description: 'Stripe secret key (sk_test_... or sk_live_...)',\n required: true,\n validator: validators.stripeSecretKey,\n },\n {\n name: 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY',\n description: 'Stripe publishable key (pk_test_... or pk_live_...)',\n required: true,\n validator: validators.stripePublishableKey,\n },\n];\n\n/**\n * Optional environment variables\n */\nexport const OPTIONAL_ENV_VARS: EnvVariable[] = [\n {\n name: 'STRIPE_WEBHOOK_SECRET',\n description: 'Stripe webhook secret (whsec_...)',\n required: false,\n },\n {\n name: 'NEXT_PUBLIC_SUPABASE_URL',\n description: 'Supabase project URL',\n required: false,\n validator: validators.url,\n },\n {\n name: 'NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY',\n description: 'Supabase publishable key (sb_publishable_...)',\n required: false,\n },\n {\n name: 'REVEALUI_ADMIN_EMAIL',\n description: 'Initial admin email',\n required: false,\n validator: validators.email,\n },\n {\n name: 'REVEALUI_ADMIN_PASSWORD',\n description: 'Initial admin password (min 12 chars)',\n required: false,\n validator: validators.minLength(12),\n },\n];\n"],"mappings":"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","names":["logger"]}
package/dist/index.js CHANGED
@@ -282,8 +282,8 @@ var OPTIONAL_ENV_VARS = [
282
282
  validator: validators.url
283
283
  },
284
284
  {
285
- name: "NEXT_PUBLIC_SUPABASE_ANON_KEY",
286
- description: "Supabase anonymous key",
285
+ name: "NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY",
286
+ description: "Supabase publishable key (sb_publishable_...)",
287
287
  required: false
288
288
  },
289
289
  {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/environment/generators.ts","../src/environment/setup.ts","../src/utils/logger.ts","../src/validators/env.ts"],"sourcesContent":["/**\n * Environment secret and password generators\n */\n\nimport { randomBytes } from 'node:crypto'\n\n/**\n * Generates a secure random secret.\n *\n * @param length - Length in bytes (default: 32 bytes = 64 hex chars)\n * @returns Hex-encoded random secret\n *\n * @example\n * ```typescript\n * const secret = generateSecret() // 64 char hex string\n * ```\n */\nexport function generateSecret(length = 32): string {\n return randomBytes(length).toString('hex')\n}\n\n/**\n * Generates a secure password with alphanumeric and special characters.\n *\n * @param length - Password length (default: 16)\n * @returns Random password\n *\n * @example\n * ```typescript\n * const password = generatePassword(16) // e.g., \"aB3!xY9@pQ5#mN7$\"\n * ```\n */\nexport function generatePassword(length = 16): string {\n const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*'\n let password = ''\n const randomValues = randomBytes(length)\n for (let i = 0; i < length; i++) {\n password += chars[randomValues[i] % chars.length]\n }\n return password\n}\n\n/**\n * Updates a value in environment file content.\n *\n * @param content - Original env file content\n * @param key - Environment variable name\n * @param value - New value\n * @returns Updated env file content\n *\n * @example\n * ```typescript\n * const updated = updateEnvValue(content, 'DB_URL', 'postgresql://...')\n * ```\n */\nexport function updateEnvValue(content: string, key: string, value: string): string {\n const regex = new RegExp(`^${key}=.*$`, 'm')\n\n if (regex.test(content)) {\n // Replace existing value\n return content.replace(regex, `${key}=${value}`)\n }\n\n // Add new line at the end\n return `${content.trimEnd()}\\n${key}=${value}\\n`\n}\n\n/**\n * Parses environment file content into key-value pairs.\n *\n * @param content - Environment file content\n * @returns Parsed environment variables\n *\n * @example\n * ```typescript\n * const env = parseEnvContent('DB_URL=postgresql://...\\nAPI_KEY=abc123')\n * // { DB_URL: 'postgresql://...', API_KEY: 'abc123' }\n * ```\n */\nexport function parseEnvContent(content: string): Record<string, string> {\n const env: Record<string, string> = {}\n const lines = content.split('\\n')\n\n for (const line of lines) {\n // Skip comments and empty lines\n const trimmed = line.trim()\n if (!trimmed || trimmed.startsWith('#')) continue\n\n // Parse key=value\n const match = trimmed.match(/^([^=]+)=(.*)$/)\n if (match) {\n const [, key, value] = match\n env[key.trim()] = value.trim()\n }\n }\n\n return env\n}\n","/**\n * Environment setup orchestration\n */\n\nimport { copyFile, readFile, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport inquirer from 'inquirer'\nimport { createLogger } from '../utils/logger.js'\nimport { type EnvVariable, REQUIRED_ENV_VARS, validateEnv } from '../validators/env.js'\nimport { generateSecret, parseEnvContent, updateEnvValue } from './generators.js'\n\nexport interface SetupEnvironmentOptions {\n projectRoot: string\n templatePath?: string\n outputPath?: string\n force?: boolean\n generateOnly?: boolean\n interactive?: boolean\n customVariables?: EnvVariable[]\n logger?: ReturnType<typeof createLogger>\n}\n\nexport interface SetupEnvironmentResult {\n success: boolean\n envPath: string\n missing: string[]\n invalid: string[]\n}\n\n/**\n * Sets up environment variables for a project.\n *\n * @param options - Setup configuration options\n * @returns Setup result with validation info\n *\n * @example\n * ```typescript\n * const result = await setupEnvironment({\n * projectRoot: '/path/to/project',\n * interactive: true\n * })\n * ```\n */\nexport async function setupEnvironment(\n options: SetupEnvironmentOptions,\n): Promise<SetupEnvironmentResult> {\n const {\n projectRoot,\n templatePath = join(projectRoot, '.env.template'),\n outputPath = join(projectRoot, '.env.development.local'),\n force = false,\n generateOnly = false,\n interactive = true,\n customVariables,\n logger = createLogger({ prefix: 'Setup' }),\n } = options\n\n const requiredVars = customVariables || REQUIRED_ENV_VARS\n\n logger.header('Environment Setup')\n\n // Check if template exists\n try {\n await readFile(templatePath, 'utf-8')\n } catch {\n logger.error(`.env.template not found at: ${templatePath}`)\n logger.info('Please ensure .env.template exists in the project root.')\n return {\n success: false,\n envPath: outputPath,\n missing: requiredVars.map((v) => v.name),\n invalid: [],\n }\n }\n\n // Check if output file already exists\n let outputExists = false\n try {\n await readFile(outputPath, 'utf-8')\n outputExists = true\n } catch {\n // File doesn't exist, which is fine\n }\n\n if (outputExists && !force) {\n if (interactive) {\n logger.warn('.env.development.local already exists')\n const { overwrite } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'overwrite',\n message: 'Overwrite existing file?',\n default: false,\n },\n ])\n if (!overwrite) {\n logger.info('Setup cancelled. Use force: true to overwrite.')\n return {\n success: false,\n envPath: outputPath,\n missing: [],\n invalid: [],\n }\n }\n } else {\n // Non-interactive mode without force, don't overwrite\n logger.info('Output file exists. Set force: true to overwrite.')\n return {\n success: false,\n envPath: outputPath,\n missing: [],\n invalid: [],\n }\n }\n }\n\n // Copy template\n logger.info('Copying .env.template to .env.development.local...')\n await copyFile(templatePath, outputPath)\n logger.success('Template copied')\n\n if (generateOnly) {\n // Just generate secrets and update the file\n await generateSecrets(outputPath, logger)\n logger.success('Secrets generated')\n return {\n success: true,\n envPath: outputPath,\n missing: [],\n invalid: [],\n }\n }\n\n // Parse the template to get current values\n let envContent = await readFile(outputPath, 'utf-8')\n const currentEnv = parseEnvContent(envContent)\n\n // Check for missing required values\n const validation = validateEnv(requiredVars, currentEnv)\n\n if (interactive && (validation.missing.length > 0 || validation.invalid.length > 0)) {\n logger.info('Some required values need to be configured:')\n logger.divider()\n\n for (const varName of validation.missing) {\n const variable = requiredVars.find((v) => v.name === varName)\n if (!variable) continue\n\n logger.info(`${varName}: ${variable.description}`)\n\n if (varName === 'REVEALUI_SECRET') {\n // Auto-generate secret\n const secret = generateSecret(32)\n envContent = updateEnvValue(envContent, varName, secret)\n logger.success(`Generated ${varName}`)\n } else {\n // Prompt for value\n const { value } = await inquirer.prompt([\n {\n type: 'input',\n name: 'value',\n message: `Enter value for ${varName}:`,\n validate: (input: string) => {\n if (!input.trim()) {\n return 'Value cannot be empty (press Ctrl+C to skip)'\n }\n if (variable.validator && !variable.validator(input.trim())) {\n return `Invalid format for ${varName}`\n }\n return true\n },\n },\n ])\n\n if (value.trim()) {\n envContent = updateEnvValue(envContent, varName, value.trim())\n logger.success(`Set ${varName}`)\n }\n }\n }\n\n // Save updated content\n await writeFile(outputPath, envContent)\n logger.success('Environment file updated')\n } else if (!interactive && validation.missing.length > 0) {\n // Non-interactive mode with missing values - just generate secrets\n for (const varName of validation.missing) {\n if (varName === 'REVEALUI_SECRET') {\n const secret = generateSecret(32)\n envContent = updateEnvValue(envContent, varName, secret)\n logger.success(`Generated ${varName}`)\n }\n }\n await writeFile(outputPath, envContent)\n }\n\n // Final validation\n const finalContent = await readFile(outputPath, 'utf-8')\n const finalEnv = parseEnvContent(finalContent)\n const finalValidation = validateEnv(requiredVars, finalEnv)\n\n logger.divider()\n\n if (finalValidation.valid) {\n logger.success('Environment setup complete!')\n return {\n success: true,\n envPath: outputPath,\n missing: [],\n invalid: [],\n }\n }\n\n logger.warn('Setup incomplete - some variables still need to be configured:')\n for (const varName of finalValidation.missing) {\n logger.warn(` - ${varName}`)\n }\n logger.info('Edit .env.development.local to add missing values.')\n\n return {\n success: false,\n envPath: outputPath,\n missing: finalValidation.missing,\n invalid: finalValidation.invalid,\n }\n}\n\n/**\n * Generates secrets and updates the env file.\n */\nasync function generateSecrets(\n envPath: string,\n logger: ReturnType<typeof createLogger>,\n): Promise<void> {\n let content = await readFile(envPath, 'utf-8')\n\n // Generate REVEALUI_SECRET\n const secret = generateSecret(32)\n content = updateEnvValue(content, 'REVEALUI_SECRET', secret)\n\n await writeFile(envPath, content)\n logger.success('Generated REVEALUI_SECRET')\n}\n","/**\n * Unified Logger for RevealUI Scripts\n *\n * Provides consistent logging across all scripts with color support,\n * structured output, and log level filtering.\n */\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'\n\nexport interface LoggerOptions {\n level?: LogLevel\n prefix?: string\n colors?: boolean\n timestamps?: boolean\n}\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n}\n\ninterface ColorMap {\n reset: string\n red: string\n green: string\n yellow: string\n blue: string\n cyan: string\n magenta: string\n dim: string\n bold: string\n}\n\nfunction getColors(enabled: boolean): ColorMap {\n if (!enabled) {\n return {\n reset: '',\n red: '',\n green: '',\n yellow: '',\n blue: '',\n cyan: '',\n magenta: '',\n dim: '',\n bold: '',\n }\n }\n return {\n reset: '\\x1b[0m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n cyan: '\\x1b[36m',\n magenta: '\\x1b[35m',\n dim: '\\x1b[2m',\n bold: '\\x1b[1m',\n }\n}\n\nexport interface Logger {\n debug: (msg: string, ...args: unknown[]) => void\n info: (msg: string, ...args: unknown[]) => void\n warn: (msg: string, ...args: unknown[]) => void\n error: (msg: string, ...args: unknown[]) => void\n success: (msg: string, ...args: unknown[]) => void\n warning: (msg: string, ...args: unknown[]) => void\n header: (msg: string) => void\n divider: () => void\n table: (data: Record<string, unknown>[]) => void\n group: (label: string) => void\n groupEnd: () => void\n progress: (current: number, total: number, label?: string) => void\n}\n\n/**\n * Creates a logger instance with configurable options.\n *\n * @example\n * ```typescript\n * const logger = createLogger({ level: 'info', prefix: 'MyScript' })\n * logger.info('Starting process')\n * logger.success('Completed!')\n * ```\n */\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const {\n level = (process.env.LOG_LEVEL as LogLevel) || 'info',\n prefix = '',\n colors = process.env.FORCE_COLOR !== '0' && process.stdout.isTTY !== false,\n timestamps = false,\n } = options\n\n const currentLevel = LOG_LEVELS[level] ?? LOG_LEVELS.info\n const c = getColors(colors)\n\n function shouldLog(msgLevel: LogLevel): boolean {\n return LOG_LEVELS[msgLevel] >= currentLevel\n }\n\n function formatPrefix(): string {\n const parts: string[] = []\n if (timestamps) {\n parts.push(`${c.dim}[${new Date().toISOString()}]${c.reset}`)\n }\n if (prefix) {\n parts.push(`${c.cyan}[${prefix}]${c.reset}`)\n }\n return parts.length > 0 ? `${parts.join(' ')} ` : ''\n }\n\n function formatArgs(args: unknown[]): string {\n if (args.length === 0) return ''\n return (\n ' ' +\n args.map((arg) => (typeof arg === 'object' ? JSON.stringify(arg) : String(arg))).join(' ')\n )\n }\n\n return {\n debug(msg: string, ...args: unknown[]) {\n if (!shouldLog('debug')) return\n console.log(`${formatPrefix()}${c.dim}[DEBUG]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n info(msg: string, ...args: unknown[]) {\n if (!shouldLog('info')) return\n console.log(`${formatPrefix()}${c.blue}[INFO]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n warn(msg: string, ...args: unknown[]) {\n if (!shouldLog('warn')) return\n console.warn(`${formatPrefix()}${c.yellow}[WARN]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n error(msg: string, ...args: unknown[]) {\n if (!shouldLog('error')) return\n console.error(`${formatPrefix()}${c.red}[ERROR]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n success(msg: string, ...args: unknown[]) {\n if (!shouldLog('info')) return\n console.log(`${formatPrefix()}${c.green}[OK]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n warning(msg: string, ...args: unknown[]) {\n this.warn(msg, ...args)\n },\n\n header(msg: string) {\n if (!shouldLog('info')) return\n const line = '='.repeat(msg.length + 4)\n console.log(`\\n${c.cyan}${line}`)\n console.log(`| ${msg} |`)\n console.log(`${line}${c.reset}\\n`)\n },\n\n divider() {\n if (!shouldLog('info')) return\n console.log(`${c.dim}${'─'.repeat(60)}${c.reset}`)\n },\n\n table(data: Record<string, unknown>[]) {\n if (!shouldLog('info')) return\n console.table(data)\n },\n\n group(label: string) {\n if (!shouldLog('info')) return\n console.group(`${c.bold}${label}${c.reset}`)\n },\n\n groupEnd() {\n if (!shouldLog('info')) return\n console.groupEnd()\n },\n\n progress(current: number, total: number, label = '') {\n if (!shouldLog('info')) return\n const percent = Math.round((current / total) * 100)\n const filled = Math.round(percent / 5)\n const empty = 20 - filled\n const bar = `${'█'.repeat(filled)}${'░'.repeat(empty)}`\n const labelText = label ? ` ${label}` : ''\n process.stdout.write(`\\r${c.cyan}${bar}${c.reset} ${percent}%${labelText}`)\n if (current === total) {\n console.log() // New line when complete\n }\n },\n }\n}\n\n/**\n * Standardized error handler for AST parsing errors\n */\nexport function handleASTParseError(filePath: string, error: unknown, logger: Logger): void {\n const message = error instanceof Error ? error.message : String(error)\n logger.warning(`AST Parse Error in ${filePath}: ${message}`)\n}\n\n/**\n * Default logger instance for quick usage\n */\nexport const logger = createLogger()\n","/**\n * Environment variable validation\n */\n\nexport interface EnvVariable {\n name: string\n description: string\n required: boolean\n validator?: (value: string) => boolean\n}\n\nexport interface ValidationResult {\n valid: boolean\n missing: string[]\n invalid: string[]\n}\n\n/**\n * Validates environment variables against required schema.\n *\n * @param required - Array of required environment variable definitions\n * @param env - Environment variable object to validate\n * @returns Validation result\n *\n * @example\n * ```typescript\n * const result = validateEnv([\n * { name: 'DB_URL', description: 'Database URL', required: true }\n * ], process.env)\n * ```\n */\nexport function validateEnv(\n required: EnvVariable[],\n env: Record<string, string | undefined>,\n): ValidationResult {\n const missing: string[] = []\n const invalid: string[] = []\n\n for (const variable of required) {\n const value = env[variable.name]\n\n // Check if required variable is missing\n if (variable.required && (!value || value.trim() === '')) {\n missing.push(variable.name)\n continue\n }\n\n // Check if value passes custom validator\n if (value && variable.validator && !variable.validator(value)) {\n invalid.push(variable.name)\n }\n }\n\n return {\n valid: missing.length === 0 && invalid.length === 0,\n missing,\n invalid,\n }\n}\n\n/**\n * Common environment variable validators\n */\nexport const validators = {\n /**\n * Validates PostgreSQL connection string format\n */\n postgresUrl: (value: string): boolean => {\n try {\n const url = new URL(value)\n return url.protocol === 'postgresql:' || url.protocol === 'postgres:'\n } catch {\n return false\n }\n },\n\n /**\n * Validates Stripe secret key format\n */\n stripeSecretKey: (value: string): boolean => {\n return value.startsWith('sk_test_') || value.startsWith('sk_live_')\n },\n\n /**\n * Validates Stripe publishable key format\n */\n stripePublishableKey: (value: string): boolean => {\n return value.startsWith('pk_test_') || value.startsWith('pk_live_')\n },\n\n /**\n * Validates URL format\n */\n url: (value: string): boolean => {\n try {\n new URL(value)\n return true\n } catch {\n return false\n }\n },\n\n /**\n * Validates minimum length\n */\n minLength:\n (min: number) =>\n (value: string): boolean => {\n return value.length >= min\n },\n\n /**\n * Validates email format\n */\n email: (value: string): boolean => {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n },\n}\n\n/**\n * Common required environment variables for RevealUI\n */\nexport const REQUIRED_ENV_VARS: EnvVariable[] = [\n {\n name: 'REVEALUI_SECRET',\n description: 'Secret key for JWT tokens and session encryption (min 32 chars)',\n required: true,\n validator: validators.minLength(32),\n },\n {\n name: 'POSTGRES_URL',\n description: 'PostgreSQL connection string',\n required: true,\n validator: validators.postgresUrl,\n },\n {\n name: 'BLOB_READ_WRITE_TOKEN',\n description: 'Vercel Blob storage token',\n required: true,\n },\n {\n name: 'STRIPE_SECRET_KEY',\n description: 'Stripe secret key (sk_test_... or sk_live_...)',\n required: true,\n validator: validators.stripeSecretKey,\n },\n {\n name: 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY',\n description: 'Stripe publishable key (pk_test_... or pk_live_...)',\n required: true,\n validator: validators.stripePublishableKey,\n },\n]\n\n/**\n * Optional environment variables\n */\nexport const OPTIONAL_ENV_VARS: EnvVariable[] = [\n {\n name: 'STRIPE_WEBHOOK_SECRET',\n description: 'Stripe webhook secret (whsec_...)',\n required: false,\n },\n {\n name: 'NEXT_PUBLIC_SUPABASE_URL',\n description: 'Supabase project URL',\n required: false,\n validator: validators.url,\n },\n {\n name: 'NEXT_PUBLIC_SUPABASE_ANON_KEY',\n description: 'Supabase anonymous key',\n required: false,\n },\n {\n name: 'REVEALUI_ADMIN_EMAIL',\n description: 'Initial admin email',\n required: false,\n validator: validators.email,\n },\n {\n name: 'REVEALUI_ADMIN_PASSWORD',\n description: 'Initial admin password (min 12 chars)',\n required: false,\n validator: validators.minLength(12),\n },\n]\n"],"mappings":"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","names":["logger","logger"]}
1
+ {"version":3,"sources":["../src/environment/generators.ts","../src/environment/setup.ts","../src/utils/logger.ts","../src/validators/env.ts"],"sourcesContent":["/**\n * Environment secret and password generators\n */\n\nimport { randomBytes } from 'node:crypto';\n\n/**\n * Generates a secure random secret.\n *\n * @param length - Length in bytes (default: 32 bytes = 64 hex chars)\n * @returns Hex-encoded random secret\n *\n * @example\n * ```typescript\n * const secret = generateSecret() // 64 char hex string\n * ```\n */\nexport function generateSecret(length = 32): string {\n return randomBytes(length).toString('hex');\n}\n\n/**\n * Generates a secure password with alphanumeric and special characters.\n *\n * @param length - Password length (default: 16)\n * @returns Random password\n *\n * @example\n * ```typescript\n * const password = generatePassword(16) // e.g., \"aB3!xY9@pQ5#mN7$\"\n * ```\n */\nexport function generatePassword(length = 16): string {\n const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*';\n let password = '';\n const randomValues = randomBytes(length);\n for (let i = 0; i < length; i++) {\n password += chars[randomValues[i] % chars.length];\n }\n return password;\n}\n\n/**\n * Updates a value in environment file content.\n *\n * @param content - Original env file content\n * @param key - Environment variable name\n * @param value - New value\n * @returns Updated env file content\n *\n * @example\n * ```typescript\n * const updated = updateEnvValue(content, 'DB_URL', 'postgresql://...')\n * ```\n */\nexport function updateEnvValue(content: string, key: string, value: string): string {\n const regex = new RegExp(`^${key}=.*$`, 'm');\n\n if (regex.test(content)) {\n // Replace existing value\n return content.replace(regex, `${key}=${value}`);\n }\n\n // Add new line at the end\n return `${content.trimEnd()}\\n${key}=${value}\\n`;\n}\n\n/**\n * Parses environment file content into key-value pairs.\n *\n * @param content - Environment file content\n * @returns Parsed environment variables\n *\n * @example\n * ```typescript\n * const env = parseEnvContent('DB_URL=postgresql://...\\nAPI_KEY=abc123')\n * // { DB_URL: 'postgresql://...', API_KEY: 'abc123' }\n * ```\n */\nexport function parseEnvContent(content: string): Record<string, string> {\n const env: Record<string, string> = {};\n const lines = content.split('\\n');\n\n for (const line of lines) {\n // Skip comments and empty lines\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n\n // Parse key=value\n const match = trimmed.match(/^([^=]+)=(.*)$/);\n if (match) {\n const [, key, value] = match;\n env[key.trim()] = value.trim();\n }\n }\n\n return env;\n}\n","/**\n * Environment setup orchestration\n */\n\nimport { copyFile, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport inquirer from 'inquirer';\nimport { createLogger } from '../utils/logger.js';\nimport { type EnvVariable, REQUIRED_ENV_VARS, validateEnv } from '../validators/env.js';\nimport { generateSecret, parseEnvContent, updateEnvValue } from './generators.js';\n\nexport interface SetupEnvironmentOptions {\n projectRoot: string;\n templatePath?: string;\n outputPath?: string;\n force?: boolean;\n generateOnly?: boolean;\n interactive?: boolean;\n customVariables?: EnvVariable[];\n logger?: ReturnType<typeof createLogger>;\n}\n\nexport interface SetupEnvironmentResult {\n success: boolean;\n envPath: string;\n missing: string[];\n invalid: string[];\n}\n\n/**\n * Sets up environment variables for a project.\n *\n * @param options - Setup configuration options\n * @returns Setup result with validation info\n *\n * @example\n * ```typescript\n * const result = await setupEnvironment({\n * projectRoot: '/path/to/project',\n * interactive: true\n * })\n * ```\n */\nexport async function setupEnvironment(\n options: SetupEnvironmentOptions,\n): Promise<SetupEnvironmentResult> {\n const {\n projectRoot,\n templatePath = join(projectRoot, '.env.template'),\n outputPath = join(projectRoot, '.env.development.local'),\n force = false,\n generateOnly = false,\n interactive = true,\n customVariables,\n logger = createLogger({ prefix: 'Setup' }),\n } = options;\n\n const requiredVars = customVariables || REQUIRED_ENV_VARS;\n\n logger.header('Environment Setup');\n\n // Check if template exists\n try {\n await readFile(templatePath, 'utf-8');\n } catch {\n logger.error(`.env.template not found at: ${templatePath}`);\n logger.info('Please ensure .env.template exists in the project root.');\n return {\n success: false,\n envPath: outputPath,\n missing: requiredVars.map((v) => v.name),\n invalid: [],\n };\n }\n\n // Check if output file already exists\n let outputExists = false;\n try {\n await readFile(outputPath, 'utf-8');\n outputExists = true;\n } catch {\n // File doesn't exist, which is fine\n }\n\n if (outputExists && !force) {\n if (interactive) {\n logger.warn('.env.development.local already exists');\n const { overwrite } = await inquirer.prompt([\n {\n type: 'confirm',\n name: 'overwrite',\n message: 'Overwrite existing file?',\n default: false,\n },\n ]);\n if (!overwrite) {\n logger.info('Setup cancelled. Use force: true to overwrite.');\n return {\n success: false,\n envPath: outputPath,\n missing: [],\n invalid: [],\n };\n }\n } else {\n // Non-interactive mode without force, don't overwrite\n logger.info('Output file exists. Set force: true to overwrite.');\n return {\n success: false,\n envPath: outputPath,\n missing: [],\n invalid: [],\n };\n }\n }\n\n // Copy template\n logger.info('Copying .env.template to .env.development.local...');\n await copyFile(templatePath, outputPath);\n logger.success('Template copied');\n\n if (generateOnly) {\n // Just generate secrets and update the file\n await generateSecrets(outputPath, logger);\n logger.success('Secrets generated');\n return {\n success: true,\n envPath: outputPath,\n missing: [],\n invalid: [],\n };\n }\n\n // Parse the template to get current values\n let envContent = await readFile(outputPath, 'utf-8');\n const currentEnv = parseEnvContent(envContent);\n\n // Check for missing required values\n const validation = validateEnv(requiredVars, currentEnv);\n\n if (interactive && (validation.missing.length > 0 || validation.invalid.length > 0)) {\n logger.info('Some required values need to be configured:');\n logger.divider();\n\n for (const varName of validation.missing) {\n const variable = requiredVars.find((v) => v.name === varName);\n if (!variable) continue;\n\n logger.info(`${varName}: ${variable.description}`);\n\n if (varName === 'REVEALUI_SECRET') {\n // Auto-generate secret\n const secret = generateSecret(32);\n envContent = updateEnvValue(envContent, varName, secret);\n logger.success(`Generated ${varName}`);\n } else {\n // Prompt for value\n const { value } = await inquirer.prompt([\n {\n type: 'input',\n name: 'value',\n message: `Enter value for ${varName}:`,\n validate: (input: string) => {\n if (!input.trim()) {\n return 'Value cannot be empty (press Ctrl+C to skip)';\n }\n if (variable.validator && !variable.validator(input.trim())) {\n return `Invalid format for ${varName}`;\n }\n return true;\n },\n },\n ]);\n\n if (value.trim()) {\n envContent = updateEnvValue(envContent, varName, value.trim());\n logger.success(`Set ${varName}`);\n }\n }\n }\n\n // Save updated content\n await writeFile(outputPath, envContent);\n logger.success('Environment file updated');\n } else if (!interactive && validation.missing.length > 0) {\n // Non-interactive mode with missing values - just generate secrets\n for (const varName of validation.missing) {\n if (varName === 'REVEALUI_SECRET') {\n const secret = generateSecret(32);\n envContent = updateEnvValue(envContent, varName, secret);\n logger.success(`Generated ${varName}`);\n }\n }\n await writeFile(outputPath, envContent);\n }\n\n // Final validation\n const finalContent = await readFile(outputPath, 'utf-8');\n const finalEnv = parseEnvContent(finalContent);\n const finalValidation = validateEnv(requiredVars, finalEnv);\n\n logger.divider();\n\n if (finalValidation.valid) {\n logger.success('Environment setup complete!');\n return {\n success: true,\n envPath: outputPath,\n missing: [],\n invalid: [],\n };\n }\n\n logger.warn('Setup incomplete - some variables still need to be configured:');\n for (const varName of finalValidation.missing) {\n logger.warn(` - ${varName}`);\n }\n logger.info('Edit .env.development.local to add missing values.');\n\n return {\n success: false,\n envPath: outputPath,\n missing: finalValidation.missing,\n invalid: finalValidation.invalid,\n };\n}\n\n/**\n * Generates secrets and updates the env file.\n */\nasync function generateSecrets(\n envPath: string,\n logger: ReturnType<typeof createLogger>,\n): Promise<void> {\n let content = await readFile(envPath, 'utf-8');\n\n // Generate REVEALUI_SECRET\n const secret = generateSecret(32);\n content = updateEnvValue(content, 'REVEALUI_SECRET', secret);\n\n await writeFile(envPath, content);\n logger.success('Generated REVEALUI_SECRET');\n}\n","/**\n * Unified Logger for RevealUI Scripts\n *\n * Provides consistent logging across all scripts with color support,\n * structured output, and log level filtering.\n */\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';\n\nexport interface LoggerOptions {\n level?: LogLevel;\n prefix?: string;\n colors?: boolean;\n timestamps?: boolean;\n}\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n};\n\ninterface ColorMap {\n reset: string;\n red: string;\n green: string;\n yellow: string;\n blue: string;\n cyan: string;\n magenta: string;\n dim: string;\n bold: string;\n}\n\nfunction getColors(enabled: boolean): ColorMap {\n if (!enabled) {\n return {\n reset: '',\n red: '',\n green: '',\n yellow: '',\n blue: '',\n cyan: '',\n magenta: '',\n dim: '',\n bold: '',\n };\n }\n return {\n reset: '\\x1b[0m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n cyan: '\\x1b[36m',\n magenta: '\\x1b[35m',\n dim: '\\x1b[2m',\n bold: '\\x1b[1m',\n };\n}\n\nexport interface Logger {\n debug: (msg: string, ...args: unknown[]) => void;\n info: (msg: string, ...args: unknown[]) => void;\n warn: (msg: string, ...args: unknown[]) => void;\n error: (msg: string, ...args: unknown[]) => void;\n success: (msg: string, ...args: unknown[]) => void;\n warning: (msg: string, ...args: unknown[]) => void;\n header: (msg: string) => void;\n divider: () => void;\n table: (data: Record<string, unknown>[]) => void;\n group: (label: string) => void;\n groupEnd: () => void;\n progress: (current: number, total: number, label?: string) => void;\n}\n\n/**\n * Creates a logger instance with configurable options.\n *\n * @example\n * ```typescript\n * const logger = createLogger({ level: 'info', prefix: 'MyScript' })\n * logger.info('Starting process')\n * logger.success('Completed!')\n * ```\n */\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const {\n level = (process.env.LOG_LEVEL as LogLevel) || 'info',\n prefix = '',\n colors = process.env.FORCE_COLOR !== '0' && process.stdout.isTTY !== false,\n timestamps = false,\n } = options;\n\n const currentLevel = LOG_LEVELS[level] ?? LOG_LEVELS.info;\n const c = getColors(colors);\n\n function shouldLog(msgLevel: LogLevel): boolean {\n return LOG_LEVELS[msgLevel] >= currentLevel;\n }\n\n function formatPrefix(): string {\n const parts: string[] = [];\n if (timestamps) {\n parts.push(`${c.dim}[${new Date().toISOString()}]${c.reset}`);\n }\n if (prefix) {\n parts.push(`${c.cyan}[${prefix}]${c.reset}`);\n }\n return parts.length > 0 ? `${parts.join(' ')} ` : '';\n }\n\n function formatArgs(args: unknown[]): string {\n if (args.length === 0) return '';\n return (\n ' ' +\n args.map((arg) => (typeof arg === 'object' ? JSON.stringify(arg) : String(arg))).join(' ')\n );\n }\n\n return {\n debug(msg: string, ...args: unknown[]) {\n if (!shouldLog('debug')) return;\n console.log(`${formatPrefix()}${c.dim}[DEBUG]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n info(msg: string, ...args: unknown[]) {\n if (!shouldLog('info')) return;\n console.log(`${formatPrefix()}${c.blue}[INFO]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n warn(msg: string, ...args: unknown[]) {\n if (!shouldLog('warn')) return;\n console.warn(`${formatPrefix()}${c.yellow}[WARN]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n error(msg: string, ...args: unknown[]) {\n if (!shouldLog('error')) return;\n console.error(`${formatPrefix()}${c.red}[ERROR]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n success(msg: string, ...args: unknown[]) {\n if (!shouldLog('info')) return;\n console.log(`${formatPrefix()}${c.green}[OK]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n warning(msg: string, ...args: unknown[]) {\n this.warn(msg, ...args);\n },\n\n header(msg: string) {\n if (!shouldLog('info')) return;\n const line = '='.repeat(msg.length + 4);\n console.log(`\\n${c.cyan}${line}`);\n console.log(`| ${msg} |`);\n console.log(`${line}${c.reset}\\n`);\n },\n\n divider() {\n if (!shouldLog('info')) return;\n console.log(`${c.dim}${'─'.repeat(60)}${c.reset}`);\n },\n\n table(data: Record<string, unknown>[]) {\n if (!shouldLog('info')) return;\n console.table(data);\n },\n\n group(label: string) {\n if (!shouldLog('info')) return;\n console.group(`${c.bold}${label}${c.reset}`);\n },\n\n groupEnd() {\n if (!shouldLog('info')) return;\n console.groupEnd();\n },\n\n progress(current: number, total: number, label = '') {\n if (!shouldLog('info')) return;\n const percent = Math.round((current / total) * 100);\n const filled = Math.round(percent / 5);\n const empty = 20 - filled;\n const bar = `${'█'.repeat(filled)}${'░'.repeat(empty)}`;\n const labelText = label ? ` ${label}` : '';\n process.stdout.write(`\\r${c.cyan}${bar}${c.reset} ${percent}%${labelText}`);\n if (current === total) {\n console.log(); // New line when complete\n }\n },\n };\n}\n\n/**\n * Standardized error handler for AST parsing errors\n */\nexport function handleASTParseError(filePath: string, error: unknown, logger: Logger): void {\n const message = error instanceof Error ? error.message : String(error);\n logger.warning(`AST Parse Error in ${filePath}: ${message}`);\n}\n\n/**\n * Default logger instance for quick usage\n */\nexport const logger = createLogger();\n","/**\n * Environment variable validation\n */\n\nexport interface EnvVariable {\n name: string;\n description: string;\n required: boolean;\n validator?: (value: string) => boolean;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n missing: string[];\n invalid: string[];\n}\n\n/**\n * Validates environment variables against required schema.\n *\n * @param required - Array of required environment variable definitions\n * @param env - Environment variable object to validate\n * @returns Validation result\n *\n * @example\n * ```typescript\n * const result = validateEnv([\n * { name: 'DB_URL', description: 'Database URL', required: true }\n * ], process.env)\n * ```\n */\nexport function validateEnv(\n required: EnvVariable[],\n env: Record<string, string | undefined>,\n): ValidationResult {\n const missing: string[] = [];\n const invalid: string[] = [];\n\n for (const variable of required) {\n const value = env[variable.name];\n\n // Check if required variable is missing\n if (variable.required && (!value || value.trim() === '')) {\n missing.push(variable.name);\n continue;\n }\n\n // Check if value passes custom validator\n if (value && variable.validator && !variable.validator(value)) {\n invalid.push(variable.name);\n }\n }\n\n return {\n valid: missing.length === 0 && invalid.length === 0,\n missing,\n invalid,\n };\n}\n\n/**\n * Common environment variable validators\n */\nexport const validators = {\n /**\n * Validates PostgreSQL connection string format\n */\n postgresUrl: (value: string): boolean => {\n try {\n const url = new URL(value);\n return url.protocol === 'postgresql:' || url.protocol === 'postgres:';\n } catch {\n return false;\n }\n },\n\n /**\n * Validates Stripe secret key format\n */\n stripeSecretKey: (value: string): boolean => {\n return value.startsWith('sk_test_') || value.startsWith('sk_live_');\n },\n\n /**\n * Validates Stripe publishable key format\n */\n stripePublishableKey: (value: string): boolean => {\n return value.startsWith('pk_test_') || value.startsWith('pk_live_');\n },\n\n /**\n * Validates URL format\n */\n url: (value: string): boolean => {\n try {\n new URL(value);\n return true;\n } catch {\n return false;\n }\n },\n\n /**\n * Validates minimum length\n */\n minLength:\n (min: number) =>\n (value: string): boolean => {\n return value.length >= min;\n },\n\n /**\n * Validates email format\n */\n email: (value: string): boolean => {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value);\n },\n};\n\n/**\n * Common required environment variables for RevealUI\n */\nexport const REQUIRED_ENV_VARS: EnvVariable[] = [\n {\n name: 'REVEALUI_SECRET',\n description: 'Secret key for JWT tokens and session encryption (min 32 chars)',\n required: true,\n validator: validators.minLength(32),\n },\n {\n name: 'POSTGRES_URL',\n description: 'PostgreSQL connection string',\n required: true,\n validator: validators.postgresUrl,\n },\n {\n name: 'BLOB_READ_WRITE_TOKEN',\n description: 'Vercel Blob storage token',\n required: true,\n },\n {\n name: 'STRIPE_SECRET_KEY',\n description: 'Stripe secret key (sk_test_... or sk_live_...)',\n required: true,\n validator: validators.stripeSecretKey,\n },\n {\n name: 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY',\n description: 'Stripe publishable key (pk_test_... or pk_live_...)',\n required: true,\n validator: validators.stripePublishableKey,\n },\n];\n\n/**\n * Optional environment variables\n */\nexport const OPTIONAL_ENV_VARS: EnvVariable[] = [\n {\n name: 'STRIPE_WEBHOOK_SECRET',\n description: 'Stripe webhook secret (whsec_...)',\n required: false,\n },\n {\n name: 'NEXT_PUBLIC_SUPABASE_URL',\n description: 'Supabase project URL',\n required: false,\n validator: validators.url,\n },\n {\n name: 'NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY',\n description: 'Supabase publishable key (sb_publishable_...)',\n required: false,\n },\n {\n name: 'REVEALUI_ADMIN_EMAIL',\n description: 'Initial admin email',\n required: false,\n validator: validators.email,\n },\n {\n name: 'REVEALUI_ADMIN_PASSWORD',\n description: 'Initial admin password (min 12 chars)',\n required: false,\n validator: validators.minLength(12),\n },\n];\n"],"mappings":"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","names":["logger","logger"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/logger.ts"],"sourcesContent":["/**\n * Unified Logger for RevealUI Scripts\n *\n * Provides consistent logging across all scripts with color support,\n * structured output, and log level filtering.\n */\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'\n\nexport interface LoggerOptions {\n level?: LogLevel\n prefix?: string\n colors?: boolean\n timestamps?: boolean\n}\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n}\n\ninterface ColorMap {\n reset: string\n red: string\n green: string\n yellow: string\n blue: string\n cyan: string\n magenta: string\n dim: string\n bold: string\n}\n\nfunction getColors(enabled: boolean): ColorMap {\n if (!enabled) {\n return {\n reset: '',\n red: '',\n green: '',\n yellow: '',\n blue: '',\n cyan: '',\n magenta: '',\n dim: '',\n bold: '',\n }\n }\n return {\n reset: '\\x1b[0m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n cyan: '\\x1b[36m',\n magenta: '\\x1b[35m',\n dim: '\\x1b[2m',\n bold: '\\x1b[1m',\n }\n}\n\nexport interface Logger {\n debug: (msg: string, ...args: unknown[]) => void\n info: (msg: string, ...args: unknown[]) => void\n warn: (msg: string, ...args: unknown[]) => void\n error: (msg: string, ...args: unknown[]) => void\n success: (msg: string, ...args: unknown[]) => void\n warning: (msg: string, ...args: unknown[]) => void\n header: (msg: string) => void\n divider: () => void\n table: (data: Record<string, unknown>[]) => void\n group: (label: string) => void\n groupEnd: () => void\n progress: (current: number, total: number, label?: string) => void\n}\n\n/**\n * Creates a logger instance with configurable options.\n *\n * @example\n * ```typescript\n * const logger = createLogger({ level: 'info', prefix: 'MyScript' })\n * logger.info('Starting process')\n * logger.success('Completed!')\n * ```\n */\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const {\n level = (process.env.LOG_LEVEL as LogLevel) || 'info',\n prefix = '',\n colors = process.env.FORCE_COLOR !== '0' && process.stdout.isTTY !== false,\n timestamps = false,\n } = options\n\n const currentLevel = LOG_LEVELS[level] ?? LOG_LEVELS.info\n const c = getColors(colors)\n\n function shouldLog(msgLevel: LogLevel): boolean {\n return LOG_LEVELS[msgLevel] >= currentLevel\n }\n\n function formatPrefix(): string {\n const parts: string[] = []\n if (timestamps) {\n parts.push(`${c.dim}[${new Date().toISOString()}]${c.reset}`)\n }\n if (prefix) {\n parts.push(`${c.cyan}[${prefix}]${c.reset}`)\n }\n return parts.length > 0 ? `${parts.join(' ')} ` : ''\n }\n\n function formatArgs(args: unknown[]): string {\n if (args.length === 0) return ''\n return (\n ' ' +\n args.map((arg) => (typeof arg === 'object' ? JSON.stringify(arg) : String(arg))).join(' ')\n )\n }\n\n return {\n debug(msg: string, ...args: unknown[]) {\n if (!shouldLog('debug')) return\n console.log(`${formatPrefix()}${c.dim}[DEBUG]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n info(msg: string, ...args: unknown[]) {\n if (!shouldLog('info')) return\n console.log(`${formatPrefix()}${c.blue}[INFO]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n warn(msg: string, ...args: unknown[]) {\n if (!shouldLog('warn')) return\n console.warn(`${formatPrefix()}${c.yellow}[WARN]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n error(msg: string, ...args: unknown[]) {\n if (!shouldLog('error')) return\n console.error(`${formatPrefix()}${c.red}[ERROR]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n success(msg: string, ...args: unknown[]) {\n if (!shouldLog('info')) return\n console.log(`${formatPrefix()}${c.green}[OK]${c.reset} ${msg}${formatArgs(args)}`)\n },\n\n warning(msg: string, ...args: unknown[]) {\n this.warn(msg, ...args)\n },\n\n header(msg: string) {\n if (!shouldLog('info')) return\n const line = '='.repeat(msg.length + 4)\n console.log(`\\n${c.cyan}${line}`)\n console.log(`| ${msg} |`)\n console.log(`${line}${c.reset}\\n`)\n },\n\n divider() {\n if (!shouldLog('info')) return\n console.log(`${c.dim}${'─'.repeat(60)}${c.reset}`)\n },\n\n table(data: Record<string, unknown>[]) {\n if (!shouldLog('info')) return\n console.table(data)\n },\n\n group(label: string) {\n if (!shouldLog('info')) return\n console.group(`${c.bold}${label}${c.reset}`)\n },\n\n groupEnd() {\n if (!shouldLog('info')) return\n console.groupEnd()\n },\n\n progress(current: number, total: number, label = '') {\n if (!shouldLog('info')) return\n const percent = Math.round((current / total) * 100)\n const filled = Math.round(percent / 5)\n const empty = 20 - filled\n const bar = `${'█'.repeat(filled)}${'░'.repeat(empty)}`\n const labelText = label ? ` ${label}` : ''\n process.stdout.write(`\\r${c.cyan}${bar}${c.reset} ${percent}%${labelText}`)\n if (current === total) {\n console.log() // New line when complete\n }\n },\n }\n}\n\n/**\n * Standardized error handler for AST parsing errors\n */\nexport function handleASTParseError(filePath: string, error: unknown, logger: Logger): void {\n const message = error instanceof Error ? error.message : String(error)\n logger.warning(`AST Parse Error in ${filePath}: ${message}`)\n}\n\n/**\n * Default logger instance for quick usage\n */\nexport const logger = createLogger()\n"],"mappings":"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","names":["logger"]}
1
+ {"version":3,"sources":["../../src/utils/logger.ts"],"sourcesContent":["/**\n * Unified Logger for RevealUI Scripts\n *\n * Provides consistent logging across all scripts with color support,\n * structured output, and log level filtering.\n */\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';\n\nexport interface LoggerOptions {\n level?: LogLevel;\n prefix?: string;\n colors?: boolean;\n timestamps?: boolean;\n}\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n};\n\ninterface ColorMap {\n reset: string;\n red: string;\n green: string;\n yellow: string;\n blue: string;\n cyan: string;\n magenta: string;\n dim: string;\n bold: string;\n}\n\nfunction getColors(enabled: boolean): ColorMap {\n if (!enabled) {\n return {\n reset: '',\n red: '',\n green: '',\n yellow: '',\n blue: '',\n cyan: '',\n magenta: '',\n dim: '',\n bold: '',\n };\n }\n return {\n reset: '\\x1b[0m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n cyan: '\\x1b[36m',\n magenta: '\\x1b[35m',\n dim: '\\x1b[2m',\n bold: '\\x1b[1m',\n };\n}\n\nexport interface Logger {\n debug: (msg: string, ...args: unknown[]) => void;\n info: (msg: string, ...args: unknown[]) => void;\n warn: (msg: string, ...args: unknown[]) => void;\n error: (msg: string, ...args: unknown[]) => void;\n success: (msg: string, ...args: unknown[]) => void;\n warning: (msg: string, ...args: unknown[]) => void;\n header: (msg: string) => void;\n divider: () => void;\n table: (data: Record<string, unknown>[]) => void;\n group: (label: string) => void;\n groupEnd: () => void;\n progress: (current: number, total: number, label?: string) => void;\n}\n\n/**\n * Creates a logger instance with configurable options.\n *\n * @example\n * ```typescript\n * const logger = createLogger({ level: 'info', prefix: 'MyScript' })\n * logger.info('Starting process')\n * logger.success('Completed!')\n * ```\n */\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const {\n level = (process.env.LOG_LEVEL as LogLevel) || 'info',\n prefix = '',\n colors = process.env.FORCE_COLOR !== '0' && process.stdout.isTTY !== false,\n timestamps = false,\n } = options;\n\n const currentLevel = LOG_LEVELS[level] ?? LOG_LEVELS.info;\n const c = getColors(colors);\n\n function shouldLog(msgLevel: LogLevel): boolean {\n return LOG_LEVELS[msgLevel] >= currentLevel;\n }\n\n function formatPrefix(): string {\n const parts: string[] = [];\n if (timestamps) {\n parts.push(`${c.dim}[${new Date().toISOString()}]${c.reset}`);\n }\n if (prefix) {\n parts.push(`${c.cyan}[${prefix}]${c.reset}`);\n }\n return parts.length > 0 ? `${parts.join(' ')} ` : '';\n }\n\n function formatArgs(args: unknown[]): string {\n if (args.length === 0) return '';\n return (\n ' ' +\n args.map((arg) => (typeof arg === 'object' ? JSON.stringify(arg) : String(arg))).join(' ')\n );\n }\n\n return {\n debug(msg: string, ...args: unknown[]) {\n if (!shouldLog('debug')) return;\n console.log(`${formatPrefix()}${c.dim}[DEBUG]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n info(msg: string, ...args: unknown[]) {\n if (!shouldLog('info')) return;\n console.log(`${formatPrefix()}${c.blue}[INFO]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n warn(msg: string, ...args: unknown[]) {\n if (!shouldLog('warn')) return;\n console.warn(`${formatPrefix()}${c.yellow}[WARN]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n error(msg: string, ...args: unknown[]) {\n if (!shouldLog('error')) return;\n console.error(`${formatPrefix()}${c.red}[ERROR]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n success(msg: string, ...args: unknown[]) {\n if (!shouldLog('info')) return;\n console.log(`${formatPrefix()}${c.green}[OK]${c.reset} ${msg}${formatArgs(args)}`);\n },\n\n warning(msg: string, ...args: unknown[]) {\n this.warn(msg, ...args);\n },\n\n header(msg: string) {\n if (!shouldLog('info')) return;\n const line = '='.repeat(msg.length + 4);\n console.log(`\\n${c.cyan}${line}`);\n console.log(`| ${msg} |`);\n console.log(`${line}${c.reset}\\n`);\n },\n\n divider() {\n if (!shouldLog('info')) return;\n console.log(`${c.dim}${'─'.repeat(60)}${c.reset}`);\n },\n\n table(data: Record<string, unknown>[]) {\n if (!shouldLog('info')) return;\n console.table(data);\n },\n\n group(label: string) {\n if (!shouldLog('info')) return;\n console.group(`${c.bold}${label}${c.reset}`);\n },\n\n groupEnd() {\n if (!shouldLog('info')) return;\n console.groupEnd();\n },\n\n progress(current: number, total: number, label = '') {\n if (!shouldLog('info')) return;\n const percent = Math.round((current / total) * 100);\n const filled = Math.round(percent / 5);\n const empty = 20 - filled;\n const bar = `${'█'.repeat(filled)}${'░'.repeat(empty)}`;\n const labelText = label ? ` ${label}` : '';\n process.stdout.write(`\\r${c.cyan}${bar}${c.reset} ${percent}%${labelText}`);\n if (current === total) {\n console.log(); // New line when complete\n }\n },\n };\n}\n\n/**\n * Standardized error handler for AST parsing errors\n */\nexport function handleASTParseError(filePath: string, error: unknown, logger: Logger): void {\n const message = error instanceof Error ? error.message : String(error);\n logger.warning(`AST Parse Error in ${filePath}: ${message}`);\n}\n\n/**\n * Default logger instance for quick usage\n */\nexport const logger = createLogger();\n"],"mappings":"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","names":["logger"]}
@@ -110,8 +110,8 @@ var OPTIONAL_ENV_VARS = [
110
110
  validator: validators.url
111
111
  },
112
112
  {
113
- name: "NEXT_PUBLIC_SUPABASE_ANON_KEY",
114
- description: "Supabase anonymous key",
113
+ name: "NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY",
114
+ description: "Supabase publishable key (sb_publishable_...)",
115
115
  required: false
116
116
  },
117
117
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/validators/env.ts"],"sourcesContent":["/**\n * Environment variable validation\n */\n\nexport interface EnvVariable {\n name: string\n description: string\n required: boolean\n validator?: (value: string) => boolean\n}\n\nexport interface ValidationResult {\n valid: boolean\n missing: string[]\n invalid: string[]\n}\n\n/**\n * Validates environment variables against required schema.\n *\n * @param required - Array of required environment variable definitions\n * @param env - Environment variable object to validate\n * @returns Validation result\n *\n * @example\n * ```typescript\n * const result = validateEnv([\n * { name: 'DB_URL', description: 'Database URL', required: true }\n * ], process.env)\n * ```\n */\nexport function validateEnv(\n required: EnvVariable[],\n env: Record<string, string | undefined>,\n): ValidationResult {\n const missing: string[] = []\n const invalid: string[] = []\n\n for (const variable of required) {\n const value = env[variable.name]\n\n // Check if required variable is missing\n if (variable.required && (!value || value.trim() === '')) {\n missing.push(variable.name)\n continue\n }\n\n // Check if value passes custom validator\n if (value && variable.validator && !variable.validator(value)) {\n invalid.push(variable.name)\n }\n }\n\n return {\n valid: missing.length === 0 && invalid.length === 0,\n missing,\n invalid,\n }\n}\n\n/**\n * Common environment variable validators\n */\nexport const validators = {\n /**\n * Validates PostgreSQL connection string format\n */\n postgresUrl: (value: string): boolean => {\n try {\n const url = new URL(value)\n return url.protocol === 'postgresql:' || url.protocol === 'postgres:'\n } catch {\n return false\n }\n },\n\n /**\n * Validates Stripe secret key format\n */\n stripeSecretKey: (value: string): boolean => {\n return value.startsWith('sk_test_') || value.startsWith('sk_live_')\n },\n\n /**\n * Validates Stripe publishable key format\n */\n stripePublishableKey: (value: string): boolean => {\n return value.startsWith('pk_test_') || value.startsWith('pk_live_')\n },\n\n /**\n * Validates URL format\n */\n url: (value: string): boolean => {\n try {\n new URL(value)\n return true\n } catch {\n return false\n }\n },\n\n /**\n * Validates minimum length\n */\n minLength:\n (min: number) =>\n (value: string): boolean => {\n return value.length >= min\n },\n\n /**\n * Validates email format\n */\n email: (value: string): boolean => {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n },\n}\n\n/**\n * Common required environment variables for RevealUI\n */\nexport const REQUIRED_ENV_VARS: EnvVariable[] = [\n {\n name: 'REVEALUI_SECRET',\n description: 'Secret key for JWT tokens and session encryption (min 32 chars)',\n required: true,\n validator: validators.minLength(32),\n },\n {\n name: 'POSTGRES_URL',\n description: 'PostgreSQL connection string',\n required: true,\n validator: validators.postgresUrl,\n },\n {\n name: 'BLOB_READ_WRITE_TOKEN',\n description: 'Vercel Blob storage token',\n required: true,\n },\n {\n name: 'STRIPE_SECRET_KEY',\n description: 'Stripe secret key (sk_test_... or sk_live_...)',\n required: true,\n validator: validators.stripeSecretKey,\n },\n {\n name: 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY',\n description: 'Stripe publishable key (pk_test_... or pk_live_...)',\n required: true,\n validator: validators.stripePublishableKey,\n },\n]\n\n/**\n * Optional environment variables\n */\nexport const OPTIONAL_ENV_VARS: EnvVariable[] = [\n {\n name: 'STRIPE_WEBHOOK_SECRET',\n description: 'Stripe webhook secret (whsec_...)',\n required: false,\n },\n {\n name: 'NEXT_PUBLIC_SUPABASE_URL',\n description: 'Supabase project URL',\n required: false,\n validator: validators.url,\n },\n {\n name: 'NEXT_PUBLIC_SUPABASE_ANON_KEY',\n description: 'Supabase anonymous key',\n required: false,\n },\n {\n name: 'REVEALUI_ADMIN_EMAIL',\n description: 'Initial admin email',\n required: false,\n validator: validators.email,\n },\n {\n name: 'REVEALUI_ADMIN_PASSWORD',\n description: 'Initial admin password (min 12 chars)',\n required: false,\n validator: validators.minLength(12),\n },\n]\n"],"mappings":";AA+BO,SAAS,YACd,UACA,KACkB;AAClB,QAAM,UAAoB,CAAC;AAC3B,QAAM,UAAoB,CAAC;AAE3B,aAAW,YAAY,UAAU;AAC/B,UAAM,QAAQ,IAAI,SAAS,IAAI;AAG/B,QAAI,SAAS,aAAa,CAAC,SAAS,MAAM,KAAK,MAAM,KAAK;AACxD,cAAQ,KAAK,SAAS,IAAI;AAC1B;AAAA,IACF;AAGA,QAAI,SAAS,SAAS,aAAa,CAAC,SAAS,UAAU,KAAK,GAAG;AAC7D,cAAQ,KAAK,SAAS,IAAI;AAAA,IAC5B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,QAAQ,WAAW,KAAK,QAAQ,WAAW;AAAA,IAClD;AAAA,IACA;AAAA,EACF;AACF;AAKO,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA,EAIxB,aAAa,CAAC,UAA2B;AACvC,QAAI;AACF,YAAM,MAAM,IAAI,IAAI,KAAK;AACzB,aAAO,IAAI,aAAa,iBAAiB,IAAI,aAAa;AAAA,IAC5D,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,CAAC,UAA2B;AAC3C,WAAO,MAAM,WAAW,UAAU,KAAK,MAAM,WAAW,UAAU;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAKA,sBAAsB,CAAC,UAA2B;AAChD,WAAO,MAAM,WAAW,UAAU,KAAK,MAAM,WAAW,UAAU;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,CAAC,UAA2B;AAC/B,QAAI;AACF,UAAI,IAAI,KAAK;AACb,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,WACE,CAAC,QACD,CAAC,UAA2B;AAC1B,WAAO,MAAM,UAAU;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKF,OAAO,CAAC,UAA2B;AACjC,WAAO,6BAA6B,KAAK,KAAK;AAAA,EAChD;AACF;AAKO,IAAM,oBAAmC;AAAA,EAC9C;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,WAAW,UAAU,EAAE;AAAA,EACpC;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,WAAW;AAAA,EACxB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,WAAW;AAAA,EACxB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,WAAW;AAAA,EACxB;AACF;AAKO,IAAM,oBAAmC;AAAA,EAC9C;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,WAAW;AAAA,EACxB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,WAAW;AAAA,EACxB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,WAAW,UAAU,EAAE;AAAA,EACpC;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/validators/env.ts"],"sourcesContent":["/**\n * Environment variable validation\n */\n\nexport interface EnvVariable {\n name: string;\n description: string;\n required: boolean;\n validator?: (value: string) => boolean;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n missing: string[];\n invalid: string[];\n}\n\n/**\n * Validates environment variables against required schema.\n *\n * @param required - Array of required environment variable definitions\n * @param env - Environment variable object to validate\n * @returns Validation result\n *\n * @example\n * ```typescript\n * const result = validateEnv([\n * { name: 'DB_URL', description: 'Database URL', required: true }\n * ], process.env)\n * ```\n */\nexport function validateEnv(\n required: EnvVariable[],\n env: Record<string, string | undefined>,\n): ValidationResult {\n const missing: string[] = [];\n const invalid: string[] = [];\n\n for (const variable of required) {\n const value = env[variable.name];\n\n // Check if required variable is missing\n if (variable.required && (!value || value.trim() === '')) {\n missing.push(variable.name);\n continue;\n }\n\n // Check if value passes custom validator\n if (value && variable.validator && !variable.validator(value)) {\n invalid.push(variable.name);\n }\n }\n\n return {\n valid: missing.length === 0 && invalid.length === 0,\n missing,\n invalid,\n };\n}\n\n/**\n * Common environment variable validators\n */\nexport const validators = {\n /**\n * Validates PostgreSQL connection string format\n */\n postgresUrl: (value: string): boolean => {\n try {\n const url = new URL(value);\n return url.protocol === 'postgresql:' || url.protocol === 'postgres:';\n } catch {\n return false;\n }\n },\n\n /**\n * Validates Stripe secret key format\n */\n stripeSecretKey: (value: string): boolean => {\n return value.startsWith('sk_test_') || value.startsWith('sk_live_');\n },\n\n /**\n * Validates Stripe publishable key format\n */\n stripePublishableKey: (value: string): boolean => {\n return value.startsWith('pk_test_') || value.startsWith('pk_live_');\n },\n\n /**\n * Validates URL format\n */\n url: (value: string): boolean => {\n try {\n new URL(value);\n return true;\n } catch {\n return false;\n }\n },\n\n /**\n * Validates minimum length\n */\n minLength:\n (min: number) =>\n (value: string): boolean => {\n return value.length >= min;\n },\n\n /**\n * Validates email format\n */\n email: (value: string): boolean => {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value);\n },\n};\n\n/**\n * Common required environment variables for RevealUI\n */\nexport const REQUIRED_ENV_VARS: EnvVariable[] = [\n {\n name: 'REVEALUI_SECRET',\n description: 'Secret key for JWT tokens and session encryption (min 32 chars)',\n required: true,\n validator: validators.minLength(32),\n },\n {\n name: 'POSTGRES_URL',\n description: 'PostgreSQL connection string',\n required: true,\n validator: validators.postgresUrl,\n },\n {\n name: 'BLOB_READ_WRITE_TOKEN',\n description: 'Vercel Blob storage token',\n required: true,\n },\n {\n name: 'STRIPE_SECRET_KEY',\n description: 'Stripe secret key (sk_test_... or sk_live_...)',\n required: true,\n validator: validators.stripeSecretKey,\n },\n {\n name: 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY',\n description: 'Stripe publishable key (pk_test_... or pk_live_...)',\n required: true,\n validator: validators.stripePublishableKey,\n },\n];\n\n/**\n * Optional environment variables\n */\nexport const OPTIONAL_ENV_VARS: EnvVariable[] = [\n {\n name: 'STRIPE_WEBHOOK_SECRET',\n description: 'Stripe webhook secret (whsec_...)',\n required: false,\n },\n {\n name: 'NEXT_PUBLIC_SUPABASE_URL',\n description: 'Supabase project URL',\n required: false,\n validator: validators.url,\n },\n {\n name: 'NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY',\n description: 'Supabase publishable key (sb_publishable_...)',\n required: false,\n },\n {\n name: 'REVEALUI_ADMIN_EMAIL',\n description: 'Initial admin email',\n required: false,\n validator: validators.email,\n },\n {\n name: 'REVEALUI_ADMIN_PASSWORD',\n description: 'Initial admin password (min 12 chars)',\n required: false,\n validator: validators.minLength(12),\n },\n];\n"],"mappings":";AA+BO,SAAS,YACd,UACA,KACkB;AAClB,QAAM,UAAoB,CAAC;AAC3B,QAAM,UAAoB,CAAC;AAE3B,aAAW,YAAY,UAAU;AAC/B,UAAM,QAAQ,IAAI,SAAS,IAAI;AAG/B,QAAI,SAAS,aAAa,CAAC,SAAS,MAAM,KAAK,MAAM,KAAK;AACxD,cAAQ,KAAK,SAAS,IAAI;AAC1B;AAAA,IACF;AAGA,QAAI,SAAS,SAAS,aAAa,CAAC,SAAS,UAAU,KAAK,GAAG;AAC7D,cAAQ,KAAK,SAAS,IAAI;AAAA,IAC5B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,QAAQ,WAAW,KAAK,QAAQ,WAAW;AAAA,IAClD;AAAA,IACA;AAAA,EACF;AACF;AAKO,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA,EAIxB,aAAa,CAAC,UAA2B;AACvC,QAAI;AACF,YAAM,MAAM,IAAI,IAAI,KAAK;AACzB,aAAO,IAAI,aAAa,iBAAiB,IAAI,aAAa;AAAA,IAC5D,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,CAAC,UAA2B;AAC3C,WAAO,MAAM,WAAW,UAAU,KAAK,MAAM,WAAW,UAAU;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAKA,sBAAsB,CAAC,UAA2B;AAChD,WAAO,MAAM,WAAW,UAAU,KAAK,MAAM,WAAW,UAAU;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,CAAC,UAA2B;AAC/B,QAAI;AACF,UAAI,IAAI,KAAK;AACb,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,WACE,CAAC,QACD,CAAC,UAA2B;AAC1B,WAAO,MAAM,UAAU;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKF,OAAO,CAAC,UAA2B;AACjC,WAAO,6BAA6B,KAAK,KAAK;AAAA,EAChD;AACF;AAKO,IAAM,oBAAmC;AAAA,EAC9C;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,WAAW,UAAU,EAAE;AAAA,EACpC;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,WAAW;AAAA,EACxB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,WAAW;AAAA,EACxB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,WAAW;AAAA,EACxB;AACF;AAKO,IAAM,oBAAmC;AAAA,EAC9C;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,WAAW;AAAA,EACxB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,WAAW;AAAA,EACxB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW,WAAW,UAAU,EAAE;AAAA,EACpC;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revealui/setup",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Setup utilities for RevealUI projects - environment, database, and configuration management",
5
5
  "keywords": [
6
6
  "cli",
@@ -18,22 +18,21 @@
18
18
  "license": "MIT",
19
19
  "author": "RevealUI Team",
20
20
  "dependencies": {
21
- "chalk": "^5.6.2",
22
21
  "execa": "^9.0.0",
23
22
  "inquirer": "^12.0.0",
24
23
  "ora": "^8.0.1",
25
- "zod": "^4.3.5",
26
- "@revealui/config": "0.2.0"
24
+ "zod": "^4.3.6",
25
+ "@revealui/config": "0.3.0"
27
26
  },
28
27
  "devDependencies": {
29
28
  "@types/inquirer": "^9.0.7",
30
29
  "@types/node": "^25.3.0",
31
30
  "tsup": "^8.0.0",
32
- "typescript": "^5.7.2",
31
+ "typescript": "^5.9.3",
33
32
  "vitest": "^4.0.18"
34
33
  },
35
34
  "engines": {
36
- "node": ">=24.12.0"
35
+ "node": ">=24.13.0"
37
36
  },
38
37
  "exports": {
39
38
  ".": {
@@ -69,7 +68,7 @@
69
68
  "dev": "tsup --watch",
70
69
  "lint": "biome check .",
71
70
  "test": "vitest",
72
- "test:coverage": "vitest --coverage",
71
+ "test:coverage": "vitest --coverage --coverage.reporter=json-summary --coverage.reporter=html --coverage.reporter=text",
73
72
  "typecheck": "tsc --noEmit"
74
73
  }
75
74
  }