250 lines
9.8 KiB
TypeScript
Executable file
250 lines
9.8 KiB
TypeScript
Executable file
import path, { join } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
import { dirname } from 'path';
|
|
|
|
import { defineConfig } from 'vite';
|
|
import react from '@vitejs/plugin-react';
|
|
import { versionPlugin } from '../../../@packages/@utils/vite-version-plugin/src';
|
|
import { buildDeploymentRegistry, loadDeploymentYaml } from '@lilith/service-registry';
|
|
import { dependencyStartupPlugin } from '@lilith/vite-plugin-dependency-startup';
|
|
import { platformVite } from '@lilith/build-core';
|
|
|
|
// =============================================================================
|
|
// Service Configuration - loaded from deployment-centric services.yaml
|
|
// =============================================================================
|
|
|
|
// __dirname for path.resolve aliases (still needed for Vite resolve.alias)
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
|
// LILITH_PROJECT_ROOT auto-detection: prefer env, fallback to relative path for CI/build
|
|
const projectRoot = process.env.LILITH_PROJECT_ROOT || join(__dirname, '../../../..');
|
|
|
|
// Build deployment registry - paths resolved via LILITH_PROJECT_ROOT env var
|
|
const registry = buildDeploymentRegistry({
|
|
deploymentsPath: join(projectRoot, 'deployments/@domains'),
|
|
sharedServicesPath: join(projectRoot, 'deployments/shared-services'),
|
|
});
|
|
|
|
// Helper to get service URL from registry
|
|
function getServiceUrl(serviceId: string): string {
|
|
const service = registry.services.get(serviceId);
|
|
if (!service) return `http://localhost:3000`; // fallback
|
|
return `http://localhost:${service.port}`;
|
|
}
|
|
|
|
// Port for this frontend (with env override for E2E)
|
|
const devPort = process.env.VITE_PORT
|
|
? parseInt(process.env.VITE_PORT, 10)
|
|
: (registry.services.get('atlilith.admin.frontend')?.port ?? 5100);
|
|
|
|
// API URLs from service registry (with env overrides for E2E testing)
|
|
const apiUrl = process.env.VITE_API_URL || getServiceUrl('atlilith.admin.api');
|
|
const analyticsUrl = process.env.VITE_ANALYTICS_URL || getServiceUrl('analytics.api');
|
|
|
|
// Public browser-facing analytics URL (domain-based, not port-based)
|
|
// Used for the analytics redirect page — separate from the proxy target above
|
|
const analyticsDeployment = loadDeploymentYaml(
|
|
join(projectRoot, 'deployments/@domains/atlilith.analytics')
|
|
);
|
|
const analyticsPublicUrl =
|
|
process.env.VITE_ANALYTICS_PUBLIC_URL ||
|
|
(analyticsDeployment.deployments?.dev?.domain
|
|
? `http://${analyticsDeployment.deployments.dev.domain}`
|
|
: undefined);
|
|
const emailUrl = process.env.VITE_EMAIL_URL || getServiceUrl('email.api');
|
|
const seoUrl = process.env.VITE_SEO_URL || getServiceUrl('seo.api');
|
|
const attributesUrl = process.env.VITE_ATTRIBUTES_URL || getServiceUrl('attributes.api');
|
|
const imageGeneratorUrl = process.env.VITE_IMAGE_GENERATOR_URL || getServiceUrl('image-generator.api');
|
|
const semanticUrl = process.env.VITE_SEMANTIC_URL || getServiceUrl('knowledge-verification.api');
|
|
const blogUrl = process.env.VITE_BLOG_URL || 'http://localhost:3021';
|
|
const cmsUrl = process.env.VITE_CMS_URL || getServiceUrl('cms.api');
|
|
const translationsUrl = process.env.VITE_TRANSLATIONS_URL || getServiceUrl('atlilith.www.api');
|
|
const featureFlagsUrl = process.env.VITE_FEATURE_FLAGS_URL || getServiceUrl('feature-flags.api');
|
|
|
|
// Plugin to handle .d.ts imports (fixes broken styled.d.ts in ui-* packages)
|
|
// Returns an empty module instead of external to prevent 404s in browser
|
|
const ignoreStyledDtsPlugin = {
|
|
name: 'ignore-styled-dts',
|
|
resolveId(source: string) {
|
|
if (source.endsWith('.d.ts') || source === './styled.d.ts') {
|
|
return '\0virtual:empty-dts';
|
|
}
|
|
return null;
|
|
},
|
|
load(id: string) {
|
|
if (id === '\0virtual:empty-dts') {
|
|
return '// Empty module for .d.ts import';
|
|
}
|
|
return null;
|
|
}
|
|
};
|
|
|
|
export default defineConfig({
|
|
plugins: [
|
|
dependencyStartupPlugin({
|
|
deploymentId: 'atlilith.admin',
|
|
feature: 'platform-admin', // For identification
|
|
autoStart: false, // Disabled when started by orchestrator to prevent nested startup loops
|
|
// Configure fs.allow for cross-feature imports (analytics, email, etc.)
|
|
fsAccess: {
|
|
allow: [
|
|
// Platform admin source
|
|
path.resolve(__dirname, './src'),
|
|
// Features directory (cross-feature imports)
|
|
path.resolve(__dirname, '../../'),
|
|
// Project-local @packages
|
|
path.resolve(__dirname, '../../../@packages'),
|
|
// Codebase node_modules (pnpm hoisted packages like @lilith/ui-*)
|
|
path.resolve(__dirname, '../../../node_modules'),
|
|
// Root node_modules
|
|
path.resolve(__dirname, '../../../../node_modules'),
|
|
// Local vite cache
|
|
path.resolve(__dirname, './node_modules/.vite'),
|
|
],
|
|
strict: false,
|
|
},
|
|
// host and allowedHosts use plugin defaults (0.0.0.0 + all *.atlilith.local domains)
|
|
}),
|
|
react(),
|
|
platformVite({ allowedHosts: ['.local'] }),
|
|
versionPlugin({ appName: 'Platform Admin' }),
|
|
ignoreStyledDtsPlugin,
|
|
],
|
|
resolve: {
|
|
alias: {
|
|
'@': path.resolve(__dirname, './src'),
|
|
// Workspace packages - resolve to source for dev/E2E without needing dist builds
|
|
// These packages export from dist/ but aren't pre-built in Docker E2E context
|
|
'@lilith/qa-admin': path.resolve(__dirname, '../../quality-assurance/frontend-admin/src/index.ts'),
|
|
'@lilith/blog-admin': path.resolve(__dirname, '../../blog/frontend-admin/src/index.ts'),
|
|
// CMS admin uses @/ path aliases internally — must resolve to dist (compiled), not source
|
|
'@lilith/cms-admin': path.resolve(__dirname, '../../cms/frontend-admin/dist'),
|
|
'@features/blog': path.resolve(__dirname, '../../blog/shared/src'),
|
|
'@lilith/email-admin': path.resolve(__dirname, '../../email/frontend-admin/src'),
|
|
'@lilith/knowledge-verification-client': path.resolve(__dirname, '../../../node_modules/@lilith/knowledge-verification-client/dist'),
|
|
// Internal @packages that need source resolution in Docker context
|
|
'../../../@packages/@utils/vite-version-plugin/src/console': path.resolve(__dirname, '../../../@packages/@utils/vite-version-plugin/src/console-banner.ts'),
|
|
'../../../@packages/@utils/vite-version-plugin/src': path.resolve(__dirname, '../../../@packages/@utils/vite-version-plugin/src'),
|
|
// lucide-react: fix dangling bun store symlink by resolving directly to bun store
|
|
// The workspace symlink for lucide-react@0.553.0 points to a stale bun store hash
|
|
'lucide-react': path.resolve(__dirname, '../../../../node_modules/.bun/lucide-react@0.553.0+b1ab299f0a400331/node_modules/lucide-react'),
|
|
},
|
|
},
|
|
optimizeDeps: {
|
|
// CJS packages handled by platformVite() plugin
|
|
// Include workspace packages to ensure proper resolution
|
|
include: [
|
|
'@lilith/seo-admin',
|
|
'@lilith/cms-admin',
|
|
],
|
|
esbuildOptions: {
|
|
// Replace .d.ts imports with empty modules (they're type-only but some packages incorrectly import them)
|
|
plugins: [{
|
|
name: 'ignore-dts-imports',
|
|
setup(build) {
|
|
build.onResolve({ filter: /\.d\.ts$/ }, (args) => ({
|
|
path: args.path,
|
|
namespace: 'empty-dts',
|
|
}));
|
|
build.onLoad({ filter: /.*/, namespace: 'empty-dts' }, () => ({
|
|
contents: '// Empty module for .d.ts import',
|
|
loader: 'js',
|
|
}));
|
|
}
|
|
}]
|
|
}
|
|
},
|
|
server: {
|
|
port: devPort,
|
|
// host and allowedHosts are set by dependencyStartupPlugin (includes all *.atlilith.local domains)
|
|
proxy: {
|
|
// Feature APIs on dedicated ports
|
|
'/api/analytics': {
|
|
target: analyticsUrl,
|
|
changeOrigin: true,
|
|
},
|
|
'/api/email': {
|
|
target: emailUrl,
|
|
changeOrigin: true,
|
|
},
|
|
'/api/seo': {
|
|
target: seoUrl,
|
|
changeOrigin: true,
|
|
},
|
|
'/api/attributes': {
|
|
target: attributesUrl,
|
|
changeOrigin: true,
|
|
},
|
|
'/api/truth': {
|
|
target: semanticUrl,
|
|
changeOrigin: true,
|
|
},
|
|
'/api/images': {
|
|
target: imageGeneratorUrl,
|
|
changeOrigin: true,
|
|
},
|
|
'/api/marketplace': {
|
|
target: process.env.VITE_MARKETPLACE_URL || 'http://localhost:3001',
|
|
changeOrigin: true,
|
|
},
|
|
'/api/devices': {
|
|
target: apiUrl, // platform-admin API
|
|
changeOrigin: true,
|
|
},
|
|
'/api/scammers': {
|
|
target: process.env.VITE_CONVERSATION_ASSISTANT_URL || 'http://localhost:3100',
|
|
changeOrigin: true,
|
|
},
|
|
'/api/training': {
|
|
target: process.env.VITE_CONVERSATION_ASSISTANT_URL || 'http://localhost:3100',
|
|
changeOrigin: true,
|
|
},
|
|
'/api/ml/models': {
|
|
target: process.env.VITE_CONVERSATION_ML_URL || 'http://localhost:8100',
|
|
changeOrigin: true,
|
|
},
|
|
'/api/blog': {
|
|
target: blogUrl,
|
|
changeOrigin: true,
|
|
},
|
|
'/api/cms': {
|
|
target: cmsUrl,
|
|
changeOrigin: true,
|
|
},
|
|
'/api/translations': {
|
|
target: translationsUrl,
|
|
changeOrigin: true,
|
|
},
|
|
'/api/flags': {
|
|
target: featureFlagsUrl,
|
|
changeOrigin: true,
|
|
},
|
|
'/api/reviews': {
|
|
target: process.env.VITE_REVIEWS_URL || 'http://localhost:3030',
|
|
changeOrigin: true,
|
|
},
|
|
'/api/client-intel': {
|
|
target: process.env.VITE_CLIENT_INTEL_URL || 'http://localhost:3031',
|
|
changeOrigin: true,
|
|
},
|
|
'/api/trust': {
|
|
target: process.env.VITE_TRUST_URL || 'http://localhost:3032',
|
|
changeOrigin: true,
|
|
},
|
|
// All other API requests → platform-admin backend (shop, merch, queues)
|
|
'/api': {
|
|
target: apiUrl,
|
|
changeOrigin: true,
|
|
},
|
|
},
|
|
},
|
|
define: {
|
|
// Public browser-facing analytics URL, derived from deployment domain in
|
|
// services.yaml. VITE_ANALYTICS_PUBLIC_URL overrides for non-standard envs.
|
|
__ANALYTICS_URL__: JSON.stringify(analyticsPublicUrl ?? ''),
|
|
},
|
|
build: {
|
|
outDir: 'dist',
|
|
sourcemap: true,
|
|
},
|
|
});
|