chore: pnpm workspace — landing, api, shared
apps/landing: Next.js 16 (App Router, standalone), Tailwind 4, ESLint с запретом импорта из api. apps/api: Hono + better-sqlite3, сборка tsup, /api/health. packages/shared: исходники TS без сборки. Vitest projects.
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "@kvarta/api",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "tsx watch src/index.ts",
|
||||||
|
"build": "tsup",
|
||||||
|
"start": "node dist/index.js",
|
||||||
|
"typecheck": "tsc -p ."
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@hono/node-server": "^2.1.5",
|
||||||
|
"better-sqlite3": "^13.0.3",
|
||||||
|
"hono": "^4.13.13"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@kvarta/shared": "workspace:*",
|
||||||
|
"@types/better-sqlite3": "^9.6.0",
|
||||||
|
"tsup": "^9.0.0",
|
||||||
|
"tsx": "^4.20.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { Hono } from 'hono';
|
||||||
|
|
||||||
|
export function createApp() {
|
||||||
|
const app = new Hono();
|
||||||
|
app.get('/api/health', (c) => c.json({ ok: true, version: process.env.APP_VERSION ?? 'dev' }));
|
||||||
|
return app;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { serve } from '@hono/node-server';
|
||||||
|
import { createApp } from './app.js';
|
||||||
|
|
||||||
|
const port = Number(process.env.PORT ?? 3001);
|
||||||
|
serve({ fetch: createApp().fetch, port }, (info) => {
|
||||||
|
console.log(`api listening on :${info.port}`);
|
||||||
|
});
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": { "types": ["node"] },
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { defineConfig } from 'tsup';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
entry: ['src/index.ts'],
|
||||||
|
format: ['esm'],
|
||||||
|
platform: 'node',
|
||||||
|
target: 'node22',
|
||||||
|
clean: true,
|
||||||
|
// shared поставляется исходниками — вшиваем; нативный better-sqlite3 остаётся внешним
|
||||||
|
noExternal: ['@kvarta/shared'],
|
||||||
|
external: ['better-sqlite3'],
|
||||||
|
});
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { defineConfig } from 'vitest/config';
|
||||||
|
|
||||||
|
export default defineConfig({ test: { name: 'api', environment: 'node' } });
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import next from 'eslint-config-next';
|
||||||
|
|
||||||
|
const config = [
|
||||||
|
...next,
|
||||||
|
{
|
||||||
|
rules: {
|
||||||
|
// лендинг не знает о бэкенде: общий код только через @kvarta/shared
|
||||||
|
'no-restricted-imports': ['error', { patterns: ['@kvarta/api', '**/apps/api/**'] }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default config;
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import path from 'node:path';
|
||||||
|
import type { NextConfig } from 'next';
|
||||||
|
|
||||||
|
const config: NextConfig = {
|
||||||
|
output: 'standalone',
|
||||||
|
outputFileTracingRoot: path.join(import.meta.dirname, '../..'),
|
||||||
|
transpilePackages: ['@kvarta/shared'],
|
||||||
|
poweredByHeader: false,
|
||||||
|
// в проде /api/ отдаёт nginx на контейнер api; локально проксируем на dev-сервер api
|
||||||
|
async rewrites() {
|
||||||
|
if (process.env.NODE_ENV === 'production') return [];
|
||||||
|
return [{ source: '/api/:path*', destination: 'http://127.0.0.1:3001/api/:path*' }];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "@kvarta/landing",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev -p 3000",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start -p 3000",
|
||||||
|
"typecheck": "tsc -p .",
|
||||||
|
"lint": "eslint ."
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"next": "^16.4.2",
|
||||||
|
"react": "^19.3.1",
|
||||||
|
"react-dom": "^19.3.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@kvarta/shared": "workspace:*",
|
||||||
|
"@tailwindcss/postcss": "^4.3.3",
|
||||||
|
"@types/react": "^19.3.0",
|
||||||
|
"@types/react-dom": "^19.2.0",
|
||||||
|
"eslint": "^9.39.0",
|
||||||
|
"eslint-config-next": "^16.4.2",
|
||||||
|
"tailwindcss": "^4.3.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
const config = { plugins: { '@tailwindcss/postcss': {} } };
|
||||||
|
|
||||||
|
export default config;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
@import 'tailwindcss';
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import type { Metadata } from 'next';
|
||||||
|
import './globals.css';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Кварта — свежая обжарка в Минске',
|
||||||
|
description: 'Обжариваем по четвергам, привозим по пятницам.',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<html lang="ru">
|
||||||
|
<body>{children}</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export default function Page() {
|
||||||
|
return <main>Кварта</main>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
||||||
|
"jsx": "preserve",
|
||||||
|
"allowJs": false,
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [{ "name": "next" }],
|
||||||
|
"paths": { "@/*": ["./src/*"] }
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "src", ".next/types/**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { defineConfig } from 'vitest/config';
|
||||||
|
|
||||||
|
export default defineConfig({ test: { name: 'landing', environment: 'node' } });
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "kvarta",
|
||||||
|
"private": true,
|
||||||
|
"packageManager": "pnpm@11.22.0",
|
||||||
|
"engines": { "node": ">=22" },
|
||||||
|
"scripts": {
|
||||||
|
"dev": "pnpm -r --parallel dev",
|
||||||
|
"build": "pnpm -r build",
|
||||||
|
"test": "vitest run",
|
||||||
|
"typecheck": "pnpm -r typecheck",
|
||||||
|
"lint": "pnpm -r lint"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^26.6.5",
|
||||||
|
"typescript": "~6.0.3",
|
||||||
|
"vitest": "^5.0.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "@kvarta/shared",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"exports": {
|
||||||
|
"./phone": "./src/phone.ts",
|
||||||
|
"./lead": "./src/lead.ts"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"typecheck": "tsc -p ."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{ "extends": "../../tsconfig.base.json", "include": ["src"] }
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { defineConfig } from 'vitest/config';
|
||||||
|
|
||||||
|
export default defineConfig({ test: { name: 'shared', environment: 'node' } });
|
||||||
Generated
+5579
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
|||||||
|
packages:
|
||||||
|
- apps/*
|
||||||
|
- packages/*
|
||||||
|
allowBuilds:
|
||||||
|
better-sqlite3: true
|
||||||
|
esbuild: true
|
||||||
|
sharp: true
|
||||||
|
unrs-resolver: true
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2023",
|
||||||
|
"lib": ["ES2023"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Bundler",
|
||||||
|
"strict": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"noEmit": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { defineConfig } from 'vitest/config';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
projects: ['packages/shared', 'apps/api', 'apps/landing'],
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user