From 87ca5af765d2be237a2b396b8412d7906890d6a8 Mon Sep 17 00:00:00 2001 From: luciano Date: Wed, 29 Apr 2026 12:10:08 +0200 Subject: [PATCH] chore: initial monorepo scaffold Setup pnpm workspaces with apps/{web,api} placeholders and shared packages: tsconfig, eslint-config, shared, ui, db. Includes Prettier, ESLint, Husky pre-commit, lint-staged, EditorConfig, VSCode settings. Co-Authored-By: Claude Opus 4.7 (1M context) --- .editorconfig | 12 ++ .eslintrc.cjs | 14 ++ .gitattributes | 11 ++ .github/workflows/.gitkeep | 0 .gitignore | 41 ++++++ .husky/pre-commit | 1 + .npmrc | 3 + .nvmrc | 1 + .prettierignore | 14 ++ .prettierrc.json | 10 ++ .vscode/settings.json | 11 ++ CLAUDE.md | 208 ++++++++++++++++++++++++++++ README.md | 46 ++++++ apps/api/.gitkeep | 0 apps/web/.gitkeep | 0 docs/PRD_KetoPath.docx | Bin 0 -> 28597 bytes package.json | 48 +++++++ packages/db/.eslintrc.cjs | 5 + packages/db/package.json | 19 +++ packages/db/src/index.ts | 1 + packages/db/tsconfig.json | 10 ++ packages/eslint-config/index.cjs | 65 +++++++++ packages/eslint-config/nextjs.cjs | 8 ++ packages/eslint-config/node.cjs | 11 ++ packages/eslint-config/package.json | 14 ++ packages/shared/.eslintrc.cjs | 5 + packages/shared/package.json | 19 +++ packages/shared/src/index.ts | 1 + packages/shared/tsconfig.json | 10 ++ packages/tsconfig/base.json | 30 ++++ packages/tsconfig/nextjs.json | 12 ++ packages/tsconfig/node.json | 12 ++ packages/tsconfig/package.json | 10 ++ packages/ui/.eslintrc.cjs | 5 + packages/ui/package.json | 19 +++ packages/ui/src/index.ts | 1 + packages/ui/tsconfig.json | 12 ++ pnpm-lock.yaml | Bin 0 -> 85991 bytes pnpm-workspace.yaml | 3 + tsconfig.json | 8 ++ 40 files changed, 700 insertions(+) create mode 100644 .editorconfig create mode 100644 .eslintrc.cjs create mode 100644 .gitattributes create mode 100644 .github/workflows/.gitkeep create mode 100644 .gitignore create mode 100755 .husky/pre-commit create mode 100644 .npmrc create mode 100644 .nvmrc create mode 100644 .prettierignore create mode 100644 .prettierrc.json create mode 100644 .vscode/settings.json create mode 100644 CLAUDE.md create mode 100644 README.md create mode 100644 apps/api/.gitkeep create mode 100644 apps/web/.gitkeep create mode 100644 docs/PRD_KetoPath.docx create mode 100644 package.json create mode 100644 packages/db/.eslintrc.cjs create mode 100644 packages/db/package.json create mode 100644 packages/db/src/index.ts create mode 100644 packages/db/tsconfig.json create mode 100644 packages/eslint-config/index.cjs create mode 100644 packages/eslint-config/nextjs.cjs create mode 100644 packages/eslint-config/node.cjs create mode 100644 packages/eslint-config/package.json create mode 100644 packages/shared/.eslintrc.cjs create mode 100644 packages/shared/package.json create mode 100644 packages/shared/src/index.ts create mode 100644 packages/shared/tsconfig.json create mode 100644 packages/tsconfig/base.json create mode 100644 packages/tsconfig/nextjs.json create mode 100644 packages/tsconfig/node.json create mode 100644 packages/tsconfig/package.json create mode 100644 packages/ui/.eslintrc.cjs create mode 100644 packages/ui/package.json create mode 100644 packages/ui/src/index.ts create mode 100644 packages/ui/tsconfig.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 tsconfig.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8c52ff9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..6b74dc9 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,14 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: true, + extends: ['@ketopath/eslint-config'], + ignorePatterns: [ + 'node_modules/', + 'dist/', + 'build/', + '.next/', + 'out/', + 'coverage/', + 'pnpm-lock.yaml', + ], +}; diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..618169c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +* text=auto eol=lf + +*.docx binary +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.pdf binary + +pnpm-lock.yaml linguist-generated=true -diff diff --git a/.github/workflows/.gitkeep b/.github/workflows/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cb2b88a --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# Dependencies +node_modules/ +.pnpm-store/ + +# Build output +dist/ +build/ +.next/ +out/ +.turbo/ + +# Test / coverage +coverage/ +.nyc_output/ + +# Env files (NEVER commit) +.env +.env.* +!.env.example + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# OS +.DS_Store +Thumbs.db + +# Editor +.idea/ +*.swp +*.swo + +# TypeScript +*.tsbuildinfo + +# Misc +.cache/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..cb2c84d --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +pnpm lint-staged diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..c49db3b --- /dev/null +++ b/.npmrc @@ -0,0 +1,3 @@ +engine-strict=true +auto-install-peers=true +node-linker=isolated diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..2dbbe00 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20.11.1 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..1916473 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,14 @@ +node_modules/ +.pnpm-store/ +dist/ +build/ +.next/ +out/ +.turbo/ +coverage/ +pnpm-lock.yaml +*.docx +*.pdf + +# User-authored project doc — preserve exact formatting +CLAUDE.md diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..dea6315 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "singleQuote": true, + "semi": true, + "trailingComma": "all", + "printWidth": 100, + "tabWidth": 2, + "arrowParens": "always", + "endOfLine": "lf", + "plugins": ["prettier-plugin-tailwindcss"] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..063ad39 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "eslint.workingDirectories": [{ "pattern": "apps/*" }, { "pattern": "packages/*" }], + "typescript.tsdk": "node_modules/typescript/lib", + "typescript.enablePromptUseWorkspaceTsdk": true, + "files.eol": "\n" +} diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..2014ad2 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,208 @@ +# KetoPath + +> Web app responsive multi-utente per la gestione personalizzata di chetogenica e digiuno intermittente, con piani alimentari adattivi, tracking peso/progressi, gestione del digiuno e lista della spesa automatica. + +Questo file viene letto automaticamente da Claude Code a ogni sessione. Tienilo aggiornato con le decisioni architetturali e di prodotto. + +--- + +## Vision + +Trasformare la chetogenica e il digiuno intermittente da diete temporanee a stili di vita strutturati, accompagnando ogni utente dalla prima settimana di adattamento al mantenimento per la vita. + +Il documento di prodotto completo è in `docs/PRD_KetoPath.docx`. Quando devi prendere decisioni di prodotto non banali, leggilo prima di proporre soluzioni. + +--- + +## Tech stack + +**Frontend** +- Next.js 14 (App Router) + TypeScript strict mode +- Tailwind CSS + shadcn/ui per i componenti +- TanStack Query per data fetching client-side +- Zustand per stato globale leggero +- Zod per validazione form e tipi runtime + +**Backend** +- Node.js + Fastify + TypeScript +- Prisma come ORM +- Auth gestita via Clerk (no roll-your-own) + +**Database & infrastruttura** +- PostgreSQL 15+ come DB principale +- Redis per cache, sessioni e queue di job +- Cloudflare R2 per storage foto progress +- SendGrid per email transazionali +- Firebase Cloud Messaging per push web + +**Hosting & DevOps** +- Vercel per il frontend Next.js +- Render o Fly.io per il backend Fastify +- GitHub Actions per CI/CD +- PostHog (self-hosted) per analytics +- Sentry per error tracking + +--- + +## Repository structure + +``` +ketopath/ +├── apps/ +│ ├── web/ # Next.js frontend (App Router) +│ └── api/ # Fastify backend +├── packages/ +│ ├── db/ # Prisma schema, client, migrations +│ ├── shared/ # Tipi TS, utility e logica di dominio condivisa +│ └── ui/ # Componenti UI riusabili (estensione shadcn/ui) +├── docs/ +│ ├── PRD_KetoPath.docx +│ └── decisions/ # ADR (Architecture Decision Records) +├── .github/workflows/ +└── CLAUDE.md # questo file +``` + +Usa un monorepo con pnpm workspaces o Turborepo. Tutto in TypeScript. + +--- + +## Convenzioni di codice + +- **TypeScript strict mode** sempre. Mai `any` senza commento `// eslint-disable-next-line` motivato. +- **File**: `kebab-case.tsx` per i moduli, `PascalCase.tsx` per i componenti React esposti. +- **Componenti React**: function components + hooks, no class components. +- **Naming**: + - Variabili e funzioni: `camelCase` + - Componenti, tipi e interfacce: `PascalCase` + - Costanti globali: `SCREAMING_SNAKE_CASE` +- **Commit message**: Conventional Commits (`feat:`, `fix:`, `chore:`, `docs:`, ecc.). +- **Linting**: ESLint + Prettier, formattazione automatica al pre-commit con husky + lint-staged. +- **Test**: Vitest per unit test, Playwright per E2E. Coverage minima 70% sui moduli di dominio (calcoli BMR, macros, fasi). + +--- + +## Pattern di codice da preferire + +- **Server Components** di default in Next.js; `"use client"` solo dove serve interattività. +- **Server Actions** per mutazioni semplici di form, API routes per logica più complessa. +- **Suspense + Error Boundary** per ogni feature. +- **Form**: React Hook Form + Zod resolver. Mai validazione manuale. +- **Date**: usa `date-fns`. Mai `Date.parse` o stringhe ad-hoc. +- **DB queries**: Prisma client. Niente raw SQL se non strettamente necessario, e in quel caso commenta perché. +- **Optimistic updates** per le azioni utente frequenti (segnare un pasto come consumato, spuntare un articolo della lista spesa). + +--- + +## Conoscenza di dominio + +Il dominio dell'app ha alcuni concetti chiave che devi conoscere prima di scrivere codice: + +- **3 Fasi del percorso utente**: + - `INTENSIVE` (giorni 1-30/45) — deficit calorico aggressivo, IF stretto + - `TRANSITION` (giorni 31-90) — reverse dieting, calorie in salita + - `MAINTENANCE` (per sempre) — 14:10, regola 80/20, soglia di allarme +- **Calcolo calorie** con formula Mifflin-St Jeor: + - Uomini: `BMR = 10 × peso(kg) + 6.25 × altezza(cm) − 5 × età + 5` + - Donne: `BMR = 10 × peso(kg) + 6.25 × altezza(cm) − 5 × età − 161` + - TDEE = BMR × fattore attività (1.2 / 1.375 / 1.55 / 1.725) +- **Macros target per fase**: + - Carboidrati netti: 5-10% in Phase 1, sale in Phase 2-3 + - Proteine: 1.5-1.8 g/kg di peso ideale + - Grassi: il resto +- **Protocolli di digiuno**: enum `FASTING_PROTOCOL = 14_10 | 16_8 | 18_6 | 20_4 | ESE_24 | FIVE_TWO` +- **Esclusioni alimentari**: ogni `Ingredient` ha `exclusion_groups` (es. `lactose`, `fish`, `nuts`); ogni `Recipe` eredita le esclusioni dai suoi ingredienti + +Quando implementi una nuova funzionalità, mappa sempre prima a quale fase appartiene e quali macros/vincoli rispetta. + +--- + +## Comandi comuni + +```bash +# Sviluppo +pnpm dev # Avvia frontend + backend in parallelo +pnpm dev:web # Solo Next.js +pnpm dev:api # Solo Fastify + +# Build & deploy +pnpm build # Build di tutti i package +pnpm start # Avvia in production mode + +# Database +pnpm db:migrate # prisma migrate dev +pnpm db:studio # Apre Prisma Studio +pnpm db:seed # Popola DB con dati di test + +# Quality +pnpm lint # ESLint +pnpm format # Prettier +pnpm typecheck # tsc --noEmit +pnpm test # Vitest +pnpm test:e2e # Playwright +``` + +--- + +## Vincoli non negoziabili + +- **Lingua UI di default: italiano**. Tutti i testi user-facing in italiano. Predisporre i18n con `next-intl` per l'eventuale internazionalizzazione futura. +- **Mobile-first responsive**: ogni pagina deve essere progettata e testata prima a 375px di larghezza. +- **GDPR by design**: i dati di salute (peso, misure, foto, sintomi) rientrano nell'art. 9 GDPR. Crittografia at-rest sul DB, niente log dei dati sanitari, consenso esplicito. +- **Disclaimer medico** sempre visibile in onboarding, nelle pagine di calcolo calorico e nelle pagine di tracking. Testo da concordare con un medico advisor. +- **Privacy first**: niente tracking di terze parti senza consenso, no Google Analytics di default. Se proprio servono analytics, usa PostHog self-hosted con cookie-less mode. +- **Accessibilità WCAG 2.1 AA**: tutto il contenuto navigabile da tastiera, contrasto colori sufficiente, alt text sulle immagini, semantica HTML corretta. + +--- + +## Cosa NON fare mai + +- Salvare password in chiaro (Clerk gestisce auth, non implementarla a mano). +- Loggare dati di salute fuori dal DB cifrato. +- Usare `eval()` o `new Function()` con input utente. +- Disabilitare feature di sicurezza (CSP, CORS, rate limiting) per "comodità di sviluppo". +- Fare claim medici sui prodotti o suggerire farmaci/integratori specifici. +- Esportare dati utente in chiaro senza autenticazione e log dell'export. +- Fare commit di file `.env`, chiavi API, dump di database. +- Usare librerie deprecate o senza manutenzione attiva (controlla l'ultimo commit prima di aggiungere una dipendenza). + +--- + +## Workflow consigliato per Claude Code + +Quando ti chiedo una nuova funzionalità, segui questo flusso: + +1. **Domanda di chiarimento** se il task non è completamente specificato. +2. **Lettura preventiva**: leggi i file pertinenti prima di proporre modifiche, non scrivere codice "alla cieca". +3. **Plan mode** per task non banali: presentami un piano in 5-10 punti prima di toccare il codice. +4. **Implementazione progressiva**: feature piccole, commit frequenti, ogni commit verde (lint + test passano). +5. **Diff esplicito**: mostrami sempre i diff prima di applicare modifiche a file critici (`prisma/schema.prisma`, `package.json`, file di config). +6. **Test**: per ogni nuova logica di dominio (calcoli macros, fasi, vincoli) scrivi anche unit test. +7. **Documentazione**: aggiorna il README e questo CLAUDE.md quando introduci pattern nuovi o cambi decisioni architetturali. + +--- + +## Decisioni architetturali aperte (da prendere insieme) + +Queste decisioni non sono ancora finalizzate. Se le tocchi, aprire un ADR in `docs/decisions/`. + +- [ ] Stripe vs Lemon Squeezy per il payment provider +- [ ] PostHog self-hosted vs Mixpanel per analytics di prodotto +- [ ] Render vs Fly.io vs AWS ECS per l'hosting backend +- [ ] Strategia di seeding del database ricette (manuale vs scraping autorizzato vs LLM-assisted) +- [ ] Localizzazione: i18n da subito o solo italiano per MVP? +- [ ] App mobile nativa post-MVP: React Native o Expo? + +--- + +## Riferimenti + +- PRD completo: `docs/PRD_KetoPath.docx` +- Documentazione Next.js: https://nextjs.org/docs +- Documentazione Prisma: https://www.prisma.io/docs +- Documentazione Clerk: https://clerk.com/docs +- shadcn/ui: https://ui.shadcn.com +- GDPR e dati sanitari: https://www.garanteprivacy.it/ + +--- + +*Ultimo aggiornamento: aprile 2026. Modifica questo file ogni volta che cambia una decisione architetturale o un pattern di codice.* diff --git a/README.md b/README.md new file mode 100644 index 0000000..b0342d0 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# KetoPath + +Web app responsive multi-utente per la gestione personalizzata di chetogenica e digiuno intermittente. + +> Vedi `CLAUDE.md` per le convenzioni di progetto e `docs/PRD_KetoPath.docx` per il PRD completo. + +## Prerequisiti + +- Node.js `>=20.11` (vedi `.nvmrc`) +- pnpm `>=9` (`corepack enable && corepack prepare pnpm@latest --activate`) + +## Getting started + +```bash +pnpm install +pnpm typecheck +pnpm lint +pnpm format:check +``` + +## Struttura del monorepo + +``` +apps/ + web/ # Next.js 14 frontend (da scaffoldare) + api/ # Fastify backend (da scaffoldare) +packages/ + shared/ # Tipi e utility di dominio + ui/ # Componenti UI riusabili + db/ # Prisma client (da scaffoldare) + tsconfig/ # tsconfig presets condivisi + eslint-config/ # ESLint config condivisa +docs/ + PRD_KetoPath.docx +``` + +## Script disponibili + +- `pnpm dev` — avvia tutte le app in parallelo +- `pnpm dev:web` / `pnpm dev:api` — avvia singola app +- `pnpm build` — build di produzione +- `pnpm lint` / `pnpm lint:fix` — ESLint +- `pnpm format` / `pnpm format:check` — Prettier +- `pnpm typecheck` — `tsc -b` su tutto il monorepo +- `pnpm test` — Vitest (unit test) +- `pnpm test:e2e` — Playwright (E2E) diff --git a/apps/api/.gitkeep b/apps/api/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/apps/web/.gitkeep b/apps/web/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/PRD_KetoPath.docx b/docs/PRD_KetoPath.docx new file mode 100644 index 0000000000000000000000000000000000000000..ac8533276e4f53203c6831f3334a76df3971d371 GIT binary patch literal 28597 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 literal 0 HcmV?d00001 diff --git a/package.json b/package.json new file mode 100644 index 0000000..5293a18 --- /dev/null +++ b/package.json @@ -0,0 +1,48 @@ +{ + "name": "ketopath", + "version": "0.0.0", + "private": true, + "description": "KetoPath monorepo — web app per la gestione di chetogenica e digiuno intermittente", + "packageManager": "pnpm@9.12.0", + "engines": { + "node": ">=20.11", + "pnpm": ">=9" + }, + "scripts": { + "dev": "pnpm --parallel --filter \"./apps/*\" dev", + "dev:web": "pnpm --filter @ketopath/web dev", + "dev:api": "pnpm --filter @ketopath/api dev", + "build": "pnpm --filter \"./apps/*\" build", + "start": "pnpm --filter \"./apps/*\" start", + "lint": "eslint . --max-warnings=0", + "lint:fix": "eslint . --fix", + "format": "prettier --write .", + "format:check": "prettier --check .", + "typecheck": "tsc -b", + "test": "pnpm --filter \"./packages/*\" --filter \"./apps/*\" -r --if-present test", + "test:e2e": "pnpm --filter @ketopath/web test:e2e", + "prepare": "husky" + }, + "devDependencies": { + "@types/node": "^20.12.7", + "@typescript-eslint/eslint-plugin": "^7.7.0", + "@typescript-eslint/parser": "^7.7.0", + "eslint": "^8.57.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "husky": "^9.0.11", + "lint-staged": "^15.2.2", + "prettier": "^3.2.5", + "prettier-plugin-tailwindcss": "^0.5.14", + "typescript": "5.4.5" + }, + "lint-staged": { + "*.{ts,tsx,js,jsx,cjs,mjs}": [ + "eslint --fix --max-warnings=0", + "prettier --write" + ], + "*.{json,md,yml,yaml,css}": [ + "prettier --write" + ] + } +} diff --git a/packages/db/.eslintrc.cjs b/packages/db/.eslintrc.cjs new file mode 100644 index 0000000..2ad14cf --- /dev/null +++ b/packages/db/.eslintrc.cjs @@ -0,0 +1,5 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: true, + extends: ['@ketopath/eslint-config/node.cjs'], +}; diff --git a/packages/db/package.json b/packages/db/package.json new file mode 100644 index 0000000..ebdd467 --- /dev/null +++ b/packages/db/package.json @@ -0,0 +1,19 @@ +{ + "name": "@ketopath/db", + "version": "0.0.0", + "private": true, + "type": "module", + "main": "./src/index.ts", + "types": "./src/index.ts", + "exports": { + ".": "./src/index.ts" + }, + "scripts": { + "typecheck": "tsc --noEmit", + "lint": "eslint src --max-warnings=0" + }, + "devDependencies": { + "@ketopath/eslint-config": "workspace:*", + "@ketopath/tsconfig": "workspace:*" + } +} diff --git a/packages/db/src/index.ts b/packages/db/src/index.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/packages/db/src/index.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/db/tsconfig.json b/packages/db/tsconfig.json new file mode 100644 index 0000000..5100b45 --- /dev/null +++ b/packages/db/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@ketopath/tsconfig/node.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "composite": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/eslint-config/index.cjs b/packages/eslint-config/index.cjs new file mode 100644 index 0000000..e6c0688 --- /dev/null +++ b/packages/eslint-config/index.cjs @@ -0,0 +1,65 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: false, + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 2022, + sourceType: 'module', + }, + plugins: ['@typescript-eslint', 'import'], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:import/recommended', + 'plugin:import/typescript', + 'prettier', + ], + settings: { + 'import/resolver': { + typescript: { + alwaysTryTypes: true, + }, + node: true, + }, + }, + rules: { + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-unused-vars': [ + 'error', + { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }, + ], + '@typescript-eslint/consistent-type-imports': [ + 'error', + { prefer: 'type-imports', fixStyle: 'inline-type-imports' }, + ], + 'import/order': [ + 'error', + { + groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], + 'newlines-between': 'always', + alphabetize: { order: 'asc', caseInsensitive: true }, + }, + ], + 'import/no-default-export': 'off', + }, + overrides: [ + { + files: ['*.cjs', '*.config.js', '*.config.mjs'], + env: { node: true }, + rules: { + '@typescript-eslint/no-var-requires': 'off', + }, + }, + ], + ignorePatterns: [ + 'node_modules/', + 'dist/', + 'build/', + '.next/', + 'out/', + 'coverage/', + '*.config.js', + '*.config.cjs', + '*.config.mjs', + ], +}; diff --git a/packages/eslint-config/nextjs.cjs b/packages/eslint-config/nextjs.cjs new file mode 100644 index 0000000..921a567 --- /dev/null +++ b/packages/eslint-config/nextjs.cjs @@ -0,0 +1,8 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + extends: [require.resolve('./index.cjs'), 'next/core-web-vitals'], + rules: { + 'react/no-unescaped-entities': 'off', + '@next/next/no-html-link-for-pages': 'off', + }, +}; diff --git a/packages/eslint-config/node.cjs b/packages/eslint-config/node.cjs new file mode 100644 index 0000000..ccb5b24 --- /dev/null +++ b/packages/eslint-config/node.cjs @@ -0,0 +1,11 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + extends: [require.resolve('./index.cjs')], + env: { + node: true, + es2022: true, + }, + rules: { + 'no-console': ['warn', { allow: ['warn', 'error', 'info'] }], + }, +}; diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json new file mode 100644 index 0000000..9e54eb0 --- /dev/null +++ b/packages/eslint-config/package.json @@ -0,0 +1,14 @@ +{ + "name": "@ketopath/eslint-config", + "version": "0.0.0", + "private": true, + "main": "index.cjs", + "files": [ + "index.cjs", + "nextjs.cjs", + "node.cjs" + ], + "peerDependencies": { + "eslint": "^8.57.0" + } +} diff --git a/packages/shared/.eslintrc.cjs b/packages/shared/.eslintrc.cjs new file mode 100644 index 0000000..2aed780 --- /dev/null +++ b/packages/shared/.eslintrc.cjs @@ -0,0 +1,5 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: true, + extends: ['@ketopath/eslint-config'], +}; diff --git a/packages/shared/package.json b/packages/shared/package.json new file mode 100644 index 0000000..5fb63ef --- /dev/null +++ b/packages/shared/package.json @@ -0,0 +1,19 @@ +{ + "name": "@ketopath/shared", + "version": "0.0.0", + "private": true, + "type": "module", + "main": "./src/index.ts", + "types": "./src/index.ts", + "exports": { + ".": "./src/index.ts" + }, + "scripts": { + "typecheck": "tsc --noEmit", + "lint": "eslint src --max-warnings=0" + }, + "devDependencies": { + "@ketopath/eslint-config": "workspace:*", + "@ketopath/tsconfig": "workspace:*" + } +} diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/packages/shared/src/index.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json new file mode 100644 index 0000000..da4abf6 --- /dev/null +++ b/packages/shared/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@ketopath/tsconfig/base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "composite": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/tsconfig/base.json b/packages/tsconfig/base.json new file mode 100644 index 0000000..f654913 --- /dev/null +++ b/packages/tsconfig/base.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Base", + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "ESNext", + "moduleResolution": "Bundler", + "esModuleInterop": true, + "resolveJsonModule": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + + "strict": true, + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + "noImplicitOverride": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "incremental": true + } +} diff --git a/packages/tsconfig/nextjs.json b/packages/tsconfig/nextjs.json new file mode 100644 index 0000000..368cdea --- /dev/null +++ b/packages/tsconfig/nextjs.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Next.js", + "extends": "./base.json", + "compilerOptions": { + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "jsx": "preserve", + "allowJs": true, + "noEmit": true, + "plugins": [{ "name": "next" }] + } +} diff --git a/packages/tsconfig/node.json b/packages/tsconfig/node.json new file mode 100644 index 0000000..c946605 --- /dev/null +++ b/packages/tsconfig/node.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Node.js 20", + "extends": "./base.json", + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "NodeNext", + "moduleResolution": "NodeNext", + "types": ["node"] + } +} diff --git a/packages/tsconfig/package.json b/packages/tsconfig/package.json new file mode 100644 index 0000000..1483b34 --- /dev/null +++ b/packages/tsconfig/package.json @@ -0,0 +1,10 @@ +{ + "name": "@ketopath/tsconfig", + "version": "0.0.0", + "private": true, + "files": [ + "base.json", + "nextjs.json", + "node.json" + ] +} diff --git a/packages/ui/.eslintrc.cjs b/packages/ui/.eslintrc.cjs new file mode 100644 index 0000000..2aed780 --- /dev/null +++ b/packages/ui/.eslintrc.cjs @@ -0,0 +1,5 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: true, + extends: ['@ketopath/eslint-config'], +}; diff --git a/packages/ui/package.json b/packages/ui/package.json new file mode 100644 index 0000000..e73e505 --- /dev/null +++ b/packages/ui/package.json @@ -0,0 +1,19 @@ +{ + "name": "@ketopath/ui", + "version": "0.0.0", + "private": true, + "type": "module", + "main": "./src/index.ts", + "types": "./src/index.ts", + "exports": { + ".": "./src/index.ts" + }, + "scripts": { + "typecheck": "tsc --noEmit", + "lint": "eslint src --max-warnings=0" + }, + "devDependencies": { + "@ketopath/eslint-config": "workspace:*", + "@ketopath/tsconfig": "workspace:*" + } +} diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/packages/ui/src/index.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json new file mode 100644 index 0000000..43101dd --- /dev/null +++ b/packages/ui/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "@ketopath/tsconfig/base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "composite": true, + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "jsx": "preserve" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000000000000000000000000000000000000..885d59733c66e002e91adb5c2845132710a2656e GIT binary patch literal 85991 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 literal 0 HcmV?d00001 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..e9b0dad --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +packages: + - 'apps/*' + - 'packages/*' diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..2425989 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,8 @@ +{ + "files": [], + "references": [ + { "path": "./packages/shared" }, + { "path": "./packages/ui" }, + { "path": "./packages/db" } + ] +}