feat: добавить базовые сервисы image-platform
- добавлены backend, admin, gateway и worker skeleton - добавлены Drizzle schema, database package и initial migration - добавлены shared packages для RabbitMQ topology и S3 helpers - обновлены dev-инфраструктура, env example, scripts и dependencies - обновлена документация под versioned image URLs и read-through flow
This commit is contained in:
12
apps/admin/index.html
Normal file
12
apps/admin/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Image Platform Admin</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
24
apps/admin/package.json
Normal file
24
apps/admin/package.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "@image-platform/admin",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc -b && vite build",
|
||||
"dev": "vite --host 0.0.0.0 --port 5173",
|
||||
"preview": "vite preview --host 0.0.0.0 --port 5173",
|
||||
"typecheck": "tsc -b"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^19.2.5",
|
||||
"react-dom": "^19.2.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.12.2",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^6.0.1",
|
||||
"typescript": "^5.9.3",
|
||||
"vite": "^8.0.10"
|
||||
}
|
||||
}
|
||||
111
apps/admin/src/App.css
Normal file
111
apps/admin/src/App.css
Normal file
@@ -0,0 +1,111 @@
|
||||
:root {
|
||||
color: #171411;
|
||||
background: #f7f4ee;
|
||||
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
margin: 0;
|
||||
background:
|
||||
radial-gradient(circle at 18% 18%, rgba(123, 76, 255, 0.18), transparent 30rem),
|
||||
#f7f4ee;
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.app-shell {
|
||||
min-height: 100vh;
|
||||
padding: 48px 24px;
|
||||
}
|
||||
|
||||
.hero {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 40px;
|
||||
border: 1px solid #e4ded4;
|
||||
border-radius: 32px;
|
||||
background: rgba(255, 255, 255, 0.82);
|
||||
box-shadow: 0 22px 80px rgba(40, 32, 21, 0.08);
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
margin: 0 0 16px;
|
||||
color: #7b4cff;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.22em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
h1 {
|
||||
max-width: 760px;
|
||||
margin: 0;
|
||||
font-size: clamp(40px, 7vw, 76px);
|
||||
line-height: 0.92;
|
||||
letter-spacing: -0.06em;
|
||||
}
|
||||
|
||||
.lead {
|
||||
max-width: 680px;
|
||||
margin: 24px 0 0;
|
||||
color: #73695d;
|
||||
font-size: 18px;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
max-width: 960px;
|
||||
margin: 24px auto 0;
|
||||
}
|
||||
|
||||
.card {
|
||||
min-height: 150px;
|
||||
padding: 24px;
|
||||
border: 1px solid #e4ded4;
|
||||
border-radius: 24px;
|
||||
background: rgba(255, 255, 255, 0.76);
|
||||
}
|
||||
|
||||
.card h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.card p {
|
||||
margin: 12px 0 0;
|
||||
color: #73695d;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.app-shell {
|
||||
padding: 24px 16px;
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 28px;
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
.cards {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
40
apps/admin/src/App.tsx
Normal file
40
apps/admin/src/App.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import "./App.css"
|
||||
|
||||
const cards = [
|
||||
{
|
||||
title: "Assets",
|
||||
description: "Каталог исходных изображений и связанной metadata.",
|
||||
},
|
||||
{
|
||||
title: "Variants",
|
||||
description: "Будущие AVIF/WebP/JPEG variants, presets и статусы генерации.",
|
||||
},
|
||||
{
|
||||
title: "Storage",
|
||||
description: "PostgreSQL как source of truth, S3/MinIO как хранилище bytes.",
|
||||
},
|
||||
]
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
<main className="app-shell">
|
||||
<section className="hero">
|
||||
<p className="eyebrow">Image Platform Admin</p>
|
||||
<h1>чистый Vite React TS app</h1>
|
||||
<p className="lead">
|
||||
Это стартовая админка без UI-фреймворков. Дальше сюда добавим управление allowed hosts,
|
||||
assets, variants и presets.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="cards" aria-label="Будущие разделы">
|
||||
{cards.map((card) => (
|
||||
<article className="card" key={card.title}>
|
||||
<h2>{card.title}</h2>
|
||||
<p>{card.description}</p>
|
||||
</article>
|
||||
))}
|
||||
</section>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
10
apps/admin/src/main.tsx
Normal file
10
apps/admin/src/main.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import { StrictMode } from "react"
|
||||
import { createRoot } from "react-dom/client"
|
||||
|
||||
import { App } from "./App"
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
)
|
||||
22
apps/admin/tsconfig.app.json
Normal file
22
apps/admin/tsconfig.app.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"target": "ES2022",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
11
apps/admin/tsconfig.json
Normal file
11
apps/admin/tsconfig.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
18
apps/admin/tsconfig.node.json
Normal file
18
apps/admin/tsconfig.node.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
"target": "ES2023",
|
||||
"lib": ["ES2023"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
6
apps/admin/vite.config.ts
Normal file
6
apps/admin/vite.config.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import react from "@vitejs/plugin-react"
|
||||
import { defineConfig } from "vite"
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
})
|
||||
Reference in New Issue
Block a user