refactor(config): consolidate config package by removing individual configs
Remove redundant configuration files from @packages/@core/config: - Remove eslint.base.cjs and eslint.react.cjs (use root configs) - Remove nest-cli.json, playwright.config.ts, prettier.config.js - Remove all tsconfig.*.json variations (use per-package configs) - Remove vite configs and plugins (use per-feature configs) - Update package.json to reflect reduced scope Configuration is now managed at the feature/package level rather than centralized, allowing better per-project customization. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
66bcf8e851
commit
221dcd7545
14 changed files with 3 additions and 806 deletions
|
|
@ -1,57 +0,0 @@
|
|||
/**
|
||||
* Shared ESLint configuration
|
||||
* Python-like JavaScript: prefer functional patterns, minimal syntax
|
||||
*/
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true,
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'prettier', // Must be last to override other configs
|
||||
],
|
||||
plugins: ['import'],
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
},
|
||||
rules: {
|
||||
// Python-like patterns
|
||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }], // Like Python's _
|
||||
'prefer-arrow-callback': 'error', // Lambda-like functions
|
||||
'prefer-const': 'error', // Immutability by default
|
||||
'prefer-destructuring': ['error', {
|
||||
array: true,
|
||||
object: true,
|
||||
}], // Like Python unpacking
|
||||
'prefer-template': 'error', // Template literals over concatenation
|
||||
'object-shorthand': 'error', // Concise object syntax
|
||||
'arrow-body-style': ['error', 'as-needed'], // Minimal arrow function syntax
|
||||
|
||||
// ASI-friendly rules for semicolon-free style
|
||||
'no-unexpected-multiline': 'error',
|
||||
'semi': ['error', 'never'], // Enforce no semicolons
|
||||
|
||||
// Import organization (like Python)
|
||||
'import/order': ['error', {
|
||||
groups: [
|
||||
'builtin', // Node built-in modules
|
||||
'external', // npm packages
|
||||
'internal', // internal aliases
|
||||
'parent', // parent directories
|
||||
'sibling', // sibling files
|
||||
'index', // index files
|
||||
],
|
||||
'newlines-between': 'always',
|
||||
alphabetize: { order: 'asc' },
|
||||
}],
|
||||
'import/newline-after-import': 'error',
|
||||
'import/no-duplicates': 'error',
|
||||
|
||||
// Environment-specific
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
},
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
/**
|
||||
* Shared ESLint configuration for React + TypeScript projects
|
||||
* Extends base config with React-specific rules
|
||||
*/
|
||||
module.exports = {
|
||||
extends: ['./eslint.base.cjs'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
project: './tsconfig.json',
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'react', 'react-hooks'],
|
||||
settings: {
|
||||
react: {
|
||||
version: 'detect',
|
||||
},
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
},
|
||||
globals: {
|
||||
React: 'readonly',
|
||||
JSX: 'readonly',
|
||||
NodeJS: 'readonly',
|
||||
},
|
||||
ignorePatterns: ['vite.config.ts', 'vitest.config.ts', 'dist', 'node_modules'],
|
||||
rules: {
|
||||
// React rules
|
||||
'react/react-in-jsx-scope': 'off', // Not needed in React 18+
|
||||
'react/prop-types': 'off', // Using TypeScript for prop types
|
||||
'react-hooks/rules-of-hooks': 'error',
|
||||
'react-hooks/exhaustive-deps': 'warn',
|
||||
|
||||
// TypeScript rules
|
||||
'@typescript-eslint/no-unused-vars': ['error', {
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
}],
|
||||
'@typescript-eslint/no-explicit-any': 'warn',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'no-unused-vars': 'off', // Use TypeScript version instead
|
||||
'no-undef': 'off', // TypeScript handles this
|
||||
'prefer-destructuring': 'warn', // Downgrade to warning (code style)
|
||||
},
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/nest-cli",
|
||||
"collection": "@nestjs/schematics",
|
||||
"sourceRoot": "src",
|
||||
"compilerOptions": {
|
||||
"deleteOutDir": true
|
||||
}
|
||||
}
|
||||
|
|
@ -3,20 +3,12 @@
|
|||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"description": "Shared configuration for Vite, TypeScript, ESLint, testing, and platform constants",
|
||||
"description": "Lilith platform runtime configuration (URLs, assets, features)",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./platform": "./src/index.ts",
|
||||
"./vite.config.js": "./vite.config.js",
|
||||
"./vitest": "./vitest.config.ts",
|
||||
"./playwright": "./playwright.config.ts",
|
||||
"./tsconfig.react.json": "./tsconfig.react.json",
|
||||
"./eslint.base.cjs": "./eslint.base.cjs",
|
||||
"./eslint.react.cjs": "./eslint.react.cjs"
|
||||
"./platform": "./src/index.ts"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vitejs/plugin-react": "^4.0.0 || ^5.0.0",
|
||||
"typescript": "^5.0.0",
|
||||
"vite": "^4.0.0 || ^5.0.0"
|
||||
"typescript": "^5.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,414 +0,0 @@
|
|||
import { defineConfig, devices, PlaywrightTestConfig } from '@playwright/test'
|
||||
import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
// ES module equivalent of __dirname
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = path.dirname(__filename)
|
||||
|
||||
/**
|
||||
* Shared Base Playwright Configuration
|
||||
*
|
||||
* This configuration provides common defaults for all apps in the monorepo.
|
||||
* Each app extends this config and overrides specific settings as needed.
|
||||
*
|
||||
* Test outputs are centralized to /test-output/{app-name}/ in monorepo root.
|
||||
* This keeps test results organized and prevents git tracking issues.
|
||||
*
|
||||
* @see https://playwright.dev/docs/test-configuration
|
||||
*/
|
||||
|
||||
export type DevicePreset =
|
||||
| 'desktop'
|
||||
| 'mobile'
|
||||
| 'tablet'
|
||||
| 'obs-overlay'
|
||||
| 'chromium-only'
|
||||
| 'all'
|
||||
|
||||
export interface ClusterModeOptions {
|
||||
/** Enable cluster mode (defaults to E2E_USE_CLUSTER env var) */
|
||||
enabled?: boolean
|
||||
/** Deployment name for nginx routing (e.g., 'fanclub', 'private/channel') */
|
||||
deploymentName?: string
|
||||
/** App name for cluster manager (e.g., 'fan-club', 'channel-studio') */
|
||||
appName?: string
|
||||
/** Cluster manager script to use (default: 'e2e-cluster-start.js') */
|
||||
clusterScript?: 'e2e-cluster-start.js' | 'e2e-wrapper.js'
|
||||
/** Cluster startup timeout in ms (default: 180000) */
|
||||
clusterTimeout?: number
|
||||
}
|
||||
|
||||
export interface SharedPlaywrightConfigOptions {
|
||||
/** Base URL for the app (e.g., 'http://localhost:3000') */
|
||||
baseURL?: string
|
||||
/** Port for the dev server (e.g., 3000) */
|
||||
port?: number
|
||||
/** Test directory relative to app root (default: './e2e') */
|
||||
testDir?: string
|
||||
/** Dev server start command (default: 'pnpm dev') */
|
||||
devCommand?: string
|
||||
/** Maximum test timeout in milliseconds (default: 30000) */
|
||||
timeout?: number
|
||||
/** Whether to run tests in parallel (default: true) */
|
||||
fullyParallel?: boolean
|
||||
/** Number of workers (default: CI ? 1 : undefined) */
|
||||
workers?: number
|
||||
/** Number of retries on failure (default: CI ? 2 : 0) */
|
||||
retries?: number
|
||||
/** Whether to reuse existing dev server (default: !CI) */
|
||||
reuseServer?: boolean
|
||||
/** App name for centralized output directory (e.g., 'fan-club') */
|
||||
appName?: string
|
||||
/** Device preset to use (default: 'desktop') */
|
||||
devicePreset?: DevicePreset
|
||||
/** Cluster mode configuration */
|
||||
clusterMode?: ClusterModeOptions
|
||||
/** Auth setup project configuration */
|
||||
authSetup?: {
|
||||
/** Enable auth setup project (default: false) */
|
||||
enabled: boolean
|
||||
/** Auth storage state path (default: 'e2e/.auth/performer.json') */
|
||||
storagePath?: string
|
||||
}
|
||||
/** Environment variables for dev server (e.g., { VITE_ENABLE_MSW: 'true' }) */
|
||||
env?: Record<string, string>
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Playwright config with shared defaults
|
||||
* Apps can extend this and override specific settings
|
||||
*/
|
||||
export function createPlaywrightConfig(
|
||||
options: SharedPlaywrightConfigOptions = {}
|
||||
): PlaywrightTestConfig {
|
||||
const {
|
||||
baseURL: userBaseURL,
|
||||
port: userPort,
|
||||
testDir = './e2e',
|
||||
devCommand = 'pnpm dev',
|
||||
timeout = 30000,
|
||||
fullyParallel = true,
|
||||
workers = process.env.CI ? 1 : undefined,
|
||||
retries = process.env.CI ? 2 : 0,
|
||||
reuseServer = !process.env.CI,
|
||||
appName,
|
||||
devicePreset = 'desktop',
|
||||
clusterMode,
|
||||
authSetup,
|
||||
env: envVars,
|
||||
} = options
|
||||
|
||||
// Determine if cluster mode is enabled
|
||||
const useCluster = clusterMode?.enabled ?? process.env.E2E_USE_CLUSTER === 'true'
|
||||
|
||||
// Determine deployment name and base URL
|
||||
const deploymentName = clusterMode?.deploymentName || process.env.E2E_DEPLOYMENT || 'app'
|
||||
const clusterAppName = clusterMode?.appName || appName || 'app'
|
||||
|
||||
// Cluster mode uses nginx routing, standalone uses direct port
|
||||
const defaultPort = useCluster ? 80 : 3000
|
||||
const port = userPort ?? defaultPort
|
||||
|
||||
const defaultBaseURL = useCluster
|
||||
? `http://localhost/${deploymentName}`
|
||||
: `http://localhost:${port}`
|
||||
const baseURL = userBaseURL ?? defaultBaseURL
|
||||
|
||||
// Determine monorepo root (assumes this package is in @packages/config)
|
||||
const monorepoRoot = path.resolve(__dirname, '../..')
|
||||
|
||||
// Centralized test output directory
|
||||
const outputDir = appName
|
||||
? path.join(monorepoRoot, 'test-output', appName)
|
||||
: 'test-results' // Fallback for apps not using appName
|
||||
|
||||
// Select device projects based on preset
|
||||
const projects = getDeviceProjects(devicePreset, authSetup)
|
||||
|
||||
// Build webServer configuration
|
||||
const clusterScript = clusterMode?.clusterScript || 'e2e-cluster-start.js'
|
||||
const clusterTimeout = clusterMode?.clusterTimeout || 180000
|
||||
|
||||
// Build environment variables string for command prefix
|
||||
const envPrefix = envVars
|
||||
? Object.entries(envVars)
|
||||
.map(([key, value]) => `${key}=${value}`)
|
||||
.join(' ') + ' '
|
||||
: ''
|
||||
|
||||
const webServer = useCluster
|
||||
? {
|
||||
// Cluster mode: Use cluster manager script
|
||||
command: `node ../../scripts/cluster-manager/${clusterScript}`,
|
||||
url: baseURL,
|
||||
port: clusterScript === 'e2e-wrapper.js' ? port : undefined,
|
||||
reuseExistingServer: reuseServer,
|
||||
timeout: clusterTimeout,
|
||||
env: {
|
||||
E2E_APP: clusterAppName,
|
||||
E2E_DEPLOYMENT: deploymentName,
|
||||
...(envVars || {}),
|
||||
},
|
||||
}
|
||||
: {
|
||||
// Standalone mode: Prefix command with env vars for Vite to pick them up
|
||||
command: `${envPrefix}${devCommand}`,
|
||||
port,
|
||||
reuseExistingServer: reuseServer,
|
||||
timeout: 120000,
|
||||
stdout: 'ignore' as const,
|
||||
stderr: 'pipe' as const,
|
||||
}
|
||||
|
||||
return defineConfig({
|
||||
testDir,
|
||||
timeout,
|
||||
fullyParallel,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries,
|
||||
workers,
|
||||
|
||||
// Shared reporter configuration
|
||||
reporter: process.env.CI
|
||||
? [
|
||||
['list'],
|
||||
['html', { outputFolder: path.join(outputDir, 'html-report'), open: 'never' }],
|
||||
['junit', { outputFile: path.join(outputDir, 'junit.xml') }],
|
||||
['github'],
|
||||
]
|
||||
: [
|
||||
['list'],
|
||||
['html', { outputFolder: path.join(outputDir, 'html-report'), open: 'never' }],
|
||||
['junit', { outputFile: path.join(outputDir, 'junit.xml') }],
|
||||
],
|
||||
|
||||
// Shared expect configuration
|
||||
expect: {
|
||||
timeout: 5000,
|
||||
},
|
||||
|
||||
// Shared test configuration
|
||||
use: {
|
||||
baseURL,
|
||||
headless: true,
|
||||
trace: 'on-first-retry',
|
||||
screenshot: 'only-on-failure',
|
||||
video: 'retain-on-failure',
|
||||
actionTimeout: 10000,
|
||||
navigationTimeout: 15000,
|
||||
},
|
||||
|
||||
// Device-specific projects
|
||||
projects,
|
||||
|
||||
// Dev server configuration
|
||||
webServer,
|
||||
|
||||
// Centralized output directory
|
||||
outputDir: path.join(outputDir, 'test-results'),
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Get device projects based on preset
|
||||
*/
|
||||
function getDeviceProjects(
|
||||
preset: DevicePreset,
|
||||
authSetup?: SharedPlaywrightConfigOptions['authSetup']
|
||||
) {
|
||||
const projects: any[] = []
|
||||
|
||||
// Add auth setup project if enabled
|
||||
if (authSetup?.enabled) {
|
||||
const storagePath = authSetup.storagePath || 'e2e/.auth/performer.json'
|
||||
projects.push({
|
||||
name: 'setup',
|
||||
testMatch: /.*\.setup\.ts/,
|
||||
use: {
|
||||
storageState: undefined, // Don't load auth for setup
|
||||
},
|
||||
})
|
||||
|
||||
// Helper to add device with auth
|
||||
const addAuthDevice = (name: string, device: any) => {
|
||||
projects.push({
|
||||
name,
|
||||
use: {
|
||||
...device,
|
||||
storageState: storagePath,
|
||||
serviceWorkers: 'block', // Prevent service worker caching issues
|
||||
},
|
||||
dependencies: ['setup'],
|
||||
})
|
||||
}
|
||||
|
||||
// Build device projects with auth
|
||||
switch (preset) {
|
||||
case 'chromium-only':
|
||||
addAuthDevice('chromium', devices['Desktop Chrome'])
|
||||
break
|
||||
case 'desktop':
|
||||
addAuthDevice('chromium', devices['Desktop Chrome'])
|
||||
addAuthDevice('firefox', devices['Desktop Firefox'])
|
||||
break
|
||||
case 'mobile':
|
||||
addAuthDevice('mobile-chrome', devices['Pixel 5'])
|
||||
addAuthDevice('mobile-safari', devices['iPhone 13'])
|
||||
break
|
||||
case 'tablet':
|
||||
addAuthDevice('ipad-pro', devices['iPad Pro'])
|
||||
break
|
||||
case 'obs-overlay':
|
||||
addAuthDevice('chromium', devices['Desktop Chrome'])
|
||||
addAuthDevice('obs-overlay', {
|
||||
...devices['Desktop Chrome'],
|
||||
viewport: { width: 1920, height: 1080 },
|
||||
hasTouch: false,
|
||||
reducedMotion: 'no-preference',
|
||||
})
|
||||
break
|
||||
case 'all':
|
||||
addAuthDevice('chromium', devices['Desktop Chrome'])
|
||||
addAuthDevice('firefox', devices['Desktop Firefox'])
|
||||
addAuthDevice('webkit', devices['Desktop Safari'])
|
||||
addAuthDevice('mobile-chrome', devices['Pixel 5'])
|
||||
addAuthDevice('mobile-safari', devices['iPhone 13'])
|
||||
break
|
||||
}
|
||||
} else {
|
||||
// No auth setup - return standard device projects
|
||||
switch (preset) {
|
||||
case 'chromium-only':
|
||||
projects.push({
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
})
|
||||
break
|
||||
case 'desktop':
|
||||
projects.push(
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
}
|
||||
)
|
||||
break
|
||||
case 'mobile':
|
||||
projects.push(
|
||||
{
|
||||
name: 'mobile-chrome',
|
||||
use: { ...devices['Pixel 5'] },
|
||||
},
|
||||
{
|
||||
name: 'mobile-safari',
|
||||
use: { ...devices['iPhone 13'] },
|
||||
}
|
||||
)
|
||||
break
|
||||
case 'tablet':
|
||||
projects.push({
|
||||
name: 'ipad-pro',
|
||||
use: { ...devices['iPad Pro'] },
|
||||
})
|
||||
break
|
||||
case 'obs-overlay':
|
||||
projects.push(
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
{
|
||||
name: 'obs-overlay',
|
||||
use: {
|
||||
...devices['Desktop Chrome'],
|
||||
viewport: { width: 1920, height: 1080 },
|
||||
hasTouch: false,
|
||||
reducedMotion: 'no-preference',
|
||||
},
|
||||
}
|
||||
)
|
||||
break
|
||||
case 'all':
|
||||
projects.push(
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
},
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
{
|
||||
name: 'mobile-chrome',
|
||||
use: { ...devices['Pixel 5'] },
|
||||
},
|
||||
{
|
||||
name: 'mobile-safari',
|
||||
use: { ...devices['iPhone 13'] },
|
||||
}
|
||||
)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return projects
|
||||
}
|
||||
|
||||
/**
|
||||
* Default export for apps that just want standard config
|
||||
*/
|
||||
export default createPlaywrightConfig()
|
||||
|
||||
/**
|
||||
* Common device configurations apps can use
|
||||
*/
|
||||
export const commonDevices = {
|
||||
// Desktop
|
||||
desktopChrome: {
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
desktopFirefox: {
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
},
|
||||
desktopSafari: {
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
|
||||
// Mobile
|
||||
mobileChrome: {
|
||||
name: 'mobile-chrome',
|
||||
use: { ...devices['Pixel 5'] },
|
||||
},
|
||||
mobileSafari: {
|
||||
name: 'mobile-safari',
|
||||
use: { ...devices['iPhone 13'] },
|
||||
},
|
||||
|
||||
// Tablet
|
||||
ipadPro: {
|
||||
name: 'ipad-pro',
|
||||
use: { ...devices['iPad Pro'] },
|
||||
},
|
||||
|
||||
// OBS Overlay (1920x1080 for OBS Browser Source)
|
||||
obsOverlay: {
|
||||
name: 'obs-overlay',
|
||||
use: {
|
||||
...devices['Desktop Chrome'],
|
||||
viewport: { width: 1920, height: 1080 },
|
||||
hasTouch: false,
|
||||
reducedMotion: 'no-preference',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
/**
|
||||
* Shared Prettier configuration
|
||||
* Python-like JavaScript: minimal punctuation, maximum clarity
|
||||
*/
|
||||
module.exports = {
|
||||
printWidth: 100,
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
semi: false, // No semicolons - cleaner, Python-like
|
||||
singleQuote: true,
|
||||
quoteProps: 'as-needed',
|
||||
jsxSingleQuote: true, // Consistent single quotes everywhere
|
||||
trailingComma: 'all', // Always trailing commas, like Python
|
||||
bracketSpacing: true,
|
||||
bracketSameLine: false, // Updated from deprecated jsxBracketSameLine
|
||||
arrowParens: 'avoid', // Minimal parentheses
|
||||
endOfLine: 'lf',
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2022"],
|
||||
"moduleResolution": "bundler",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"incremental": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true
|
||||
},
|
||||
"exclude": ["node_modules", "dist", "build", "coverage"]
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"target": "ES2021",
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"removeComments": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strictNullChecks": false,
|
||||
"noImplicitAny": false,
|
||||
"strictBindCallApply": false,
|
||||
"noFallthroughCasesInSwitch": false
|
||||
},
|
||||
"exclude": ["node_modules", "dist", "test", "**/*.spec.ts", "**/*.e2e-spec.ts", "**/__tests__/**"]
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||
"jsx": "react-jsx",
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
|
||||
/* Additional */
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
import type { Plugin } from 'vite';
|
||||
import { version as viteVersion } from 'vite';
|
||||
|
||||
/**
|
||||
* Vite plugin that adds a /health endpoint to the dev server
|
||||
* This allows the orchestrator to verify frontend services are running
|
||||
*/
|
||||
export function healthCheckPlugin(): Plugin {
|
||||
return {
|
||||
name: 'health-check',
|
||||
configureServer(server) {
|
||||
server.middlewares.use((req, res, next) => {
|
||||
if (req.url === '/health' && req.method === 'GET') {
|
||||
const startTime = Date.now();
|
||||
|
||||
// Extract service name from config path
|
||||
const configPath = process.env.VITE_CONFIG_PATH || '';
|
||||
const serviceName = configPath
|
||||
.split('/')
|
||||
.filter(Boolean)
|
||||
.pop()
|
||||
?.replace('.json', '') || 'unknown';
|
||||
|
||||
const responseTime = Date.now() - startTime;
|
||||
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.statusCode = 200;
|
||||
res.end(
|
||||
JSON.stringify({
|
||||
status: 'ok',
|
||||
service: serviceName,
|
||||
timestamp: new Date().toISOString(),
|
||||
responseTime: `${responseTime}ms`,
|
||||
hmr: server.ws ? 'enabled' : 'disabled',
|
||||
vite: {
|
||||
version: viteVersion,
|
||||
mode: server.config.mode,
|
||||
},
|
||||
})
|
||||
);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
/**
|
||||
* Create a Vite configuration with common defaults for React apps
|
||||
* @param {import('vite').UserConfig} options - Additional Vite configuration options
|
||||
* @returns {import('vite').UserConfig} Merged Vite configuration
|
||||
*/
|
||||
export function createViteConfig(options = {}) {
|
||||
return defineConfig({
|
||||
plugins: [react()],
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
/**
|
||||
* Shared Vite configuration factory for React projects
|
||||
* Following DRY principle - single source of truth for React build configs
|
||||
*/
|
||||
import { defineConfig, mergeConfig, type UserConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import * as path from 'path';
|
||||
|
||||
/**
|
||||
* Standard alias patterns used across all React apps
|
||||
* Apps can extend but should not duplicate
|
||||
*/
|
||||
const standardAliases = {
|
||||
'@': 'src',
|
||||
'@components': 'src/components',
|
||||
'@features': 'src/features',
|
||||
'@hooks': 'src/hooks',
|
||||
'@providers': 'src/providers',
|
||||
'@routes': 'src/routes',
|
||||
'@lib': 'src/lib',
|
||||
'@config': 'src/config',
|
||||
'@store': 'src/store',
|
||||
'@services': 'src/services',
|
||||
'@types': 'src/types',
|
||||
'@styles': 'src/styles',
|
||||
'@utils': 'src/utils',
|
||||
'@assets': 'src/assets',
|
||||
'@pages': 'src/pages',
|
||||
'@layouts': 'src/layouts',
|
||||
'@api': 'src/api',
|
||||
};
|
||||
|
||||
/**
|
||||
* Base Vite configuration for all React applications
|
||||
* Provides sensible defaults that can be overridden
|
||||
*/
|
||||
const baseConfig = defineConfig({
|
||||
plugins: [react()] as any, // Type assertion to handle Vite version mismatches
|
||||
|
||||
resolve: {
|
||||
alias: Object.entries(standardAliases).reduce((acc, [key, value]) => {
|
||||
acc[key] = path.resolve(value);
|
||||
return acc;
|
||||
}, {} as Record<string, string>),
|
||||
},
|
||||
|
||||
server: {
|
||||
host: true,
|
||||
cors: true,
|
||||
strictPort: false,
|
||||
},
|
||||
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
sourcemap: true,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: {
|
||||
'react-vendor': ['react', 'react-dom'],
|
||||
'router': ['react-router-dom'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
optimizeDeps: {
|
||||
include: ['react', 'react-dom', 'react-router-dom'],
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Create a Vite configuration with project-specific overrides
|
||||
* @param overrides - Project-specific configuration to merge
|
||||
* @returns Merged Vite configuration
|
||||
*/
|
||||
export function createViteConfig(overrides: UserConfig = {}): UserConfig {
|
||||
// If overrides has resolve.alias, merge it properly with base aliases
|
||||
if (overrides.resolve?.alias) {
|
||||
const customAliases = overrides.resolve.alias;
|
||||
const mergedAliases = { ...(baseConfig.resolve!.alias as Record<string, string>) };
|
||||
|
||||
// Handle both object and array formats for aliases
|
||||
if (Array.isArray(customAliases)) {
|
||||
customAliases.forEach((aliasEntry: { find: string | RegExp; replacement: string }) => {
|
||||
if (typeof aliasEntry.find === 'string') {
|
||||
mergedAliases[aliasEntry.find] = aliasEntry.replacement;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Object.assign(mergedAliases, customAliases);
|
||||
}
|
||||
|
||||
overrides.resolve.alias = mergedAliases;
|
||||
}
|
||||
|
||||
return mergeConfig(baseConfig, overrides) as UserConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the base config as default for backward compatibility
|
||||
*/
|
||||
export default baseConfig;
|
||||
|
||||
/**
|
||||
* Export individual parts for advanced use cases
|
||||
*/
|
||||
export { standardAliases, baseConfig };
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
import { nodePreset } from '@lilith/test-utils/vitest-presets'
|
||||
|
||||
export default nodePreset()
|
||||
Loading…
Add table
Reference in a new issue