feat: sase.tr v2 full application implementation
Complete rewrite of sase.tr VIN lookup platform with modern stack: Backend (NestJS 10 + Drizzle ORM + PostgreSQL + Redis + BullMQ): - 34 DB models (core + PL24 + EMEX schemas) - Auth via Better Auth (email/password + social) - Brands, Plans, Subscriptions, Payments (iyzico + EFT) - VIN decode orchestration (Corgi + PL24 + EMEX + NHTSA) - Interactive schema viewer backend (MinIO storage) - EMEX scraping integration (Puppeteer + BullMQ workers) - Translation module (EN→TR automotive dictionary) - Admin dashboard API (stats, user mgmt, payment approval) - Rate limiting, Helmet security, file upload validation Frontend (Next.js 15 + Tailwind v4 + shadcn/ui + TanStack Query + Zustand): - 20 routes: auth, dashboard, VIN search, schema viewer, admin - Interactive schema viewer with zoom/pan/hotspot highlighting - Subscription management with brand selector - Payment flow (iyzico 3D Secure + EFT with receipt upload) - i18n support (TR/EN) - Error boundaries, loading skeletons, 404 page Infrastructure: - 85 tests (52 backend + 33 frontend, Vitest) - CI/CD (GitHub Actions: lint, typecheck, test, build, deploy) - Zero-downtime deploy script (PM2) - Env validation script Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
26
packages/config/package.json
Normal file
26
packages/config/package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "@sase/config",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc --watch",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"zod": "^3.24.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.0.0",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
56
packages/config/src/index.ts
Normal file
56
packages/config/src/index.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const envSchema = z.object({
|
||||
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
|
||||
PORT: z.coerce.number().default(4000),
|
||||
|
||||
DATABASE_URL: z.string().url(),
|
||||
|
||||
REDIS_HOST: z.string().default("127.0.0.1"),
|
||||
REDIS_PORT: z.coerce.number().default(6379),
|
||||
REDIS_PASSWORD: z.string(),
|
||||
|
||||
BETTER_AUTH_SECRET: z.string().min(32),
|
||||
BETTER_AUTH_URL: z.string().url(),
|
||||
|
||||
MINIO_ENDPOINT: z.string(),
|
||||
MINIO_ACCESS_KEY: z.string(),
|
||||
MINIO_SECRET_KEY: z.string(),
|
||||
MINIO_BUCKET_NAME: z.string().default("sase-schemas"),
|
||||
MINIO_PUBLIC_URL: z.string(),
|
||||
MINIO_USE_SSL: z
|
||||
.string()
|
||||
.transform((v) => v === "true")
|
||||
.default("false"),
|
||||
|
||||
CORS_ORIGIN: z.string().default("http://localhost:3000"),
|
||||
|
||||
IYZICO_API_KEY: z.string().optional(),
|
||||
IYZICO_SECRET_KEY: z.string().optional(),
|
||||
IYZICO_BASE_URL: z.string().optional(),
|
||||
|
||||
PL24_API_URL: z.string().optional(),
|
||||
PL24_USERNAME: z.string().optional(),
|
||||
PL24_PASSWORD: z.string().optional(),
|
||||
|
||||
EMEX_USERNAME: z.string().optional(),
|
||||
EMEX_PASSWORD: z.string().optional(),
|
||||
|
||||
ML_PREDICTION_ENABLED: z
|
||||
.string()
|
||||
.transform((v) => v === "true")
|
||||
.default("false"),
|
||||
});
|
||||
|
||||
export type Env = z.infer<typeof envSchema>;
|
||||
|
||||
export function validateEnv(env: Record<string, unknown> = process.env as Record<string, unknown>): Env {
|
||||
const result = envSchema.safeParse(env);
|
||||
if (!result.success) {
|
||||
const formatted = result.error.format();
|
||||
console.error("Environment validation failed:");
|
||||
console.error(JSON.stringify(formatted, null, 2));
|
||||
throw new Error("Invalid environment variables");
|
||||
}
|
||||
return result.data;
|
||||
}
|
||||
20
packages/config/tsconfig.json
Normal file
20
packages/config/tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "Node16",
|
||||
"moduleResolution": "Node16",
|
||||
"lib": ["ES2022"],
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
Reference in New Issue
Block a user