Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20e8382ae0 | ||
|
|
224df3a4b7 | ||
|
|
0282a21298 | ||
|
|
adf007b379 | ||
|
|
65c680da5b | ||
|
|
85a6c0d795 | ||
|
|
a119950806 | ||
|
|
2fe1062106 | ||
|
|
bf6f98d83b | ||
|
|
5ef90c3676 | ||
|
|
dce22c0ced | ||
|
|
ce95ae33b6 | ||
|
|
5e446df042 |
@@ -13,7 +13,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
token: ${{ secrets.RELEASE_TOKEN || gitea.token }}
|
token: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
persist-credentials: true
|
persist-credentials: true
|
||||||
|
|
||||||
- name: Create next tag from config/version.yaml
|
- name: Create next tag from config/version.yaml
|
||||||
|
|||||||
116
CLAUDE.md
116
CLAUDE.md
@@ -1,6 +1,69 @@
|
|||||||
# Coltura
|
# Coltura
|
||||||
|
|
||||||
CRM/ERP. Monorepo Symfony 8 (API Platform 4) + Nuxt 4.
|
CRM/ERP. Monorepo Symfony 8 (API Platform 4) + Nuxt 4. **Architecture DDD (Domain-Driven Design).**
|
||||||
|
|
||||||
|
## Architecture DDD
|
||||||
|
|
||||||
|
Le projet suit une architecture DDD cote backend ET frontend. Le code est organise par **domaine metier** (Bounded Context), pas par type technique.
|
||||||
|
|
||||||
|
### Backend — Organisation par domaine
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
Domain/ # Couche domaine (logique metier pure, aucune dependance framework)
|
||||||
|
{BoundedContext}/ # Ex: Customer, Sales, Catalog, Invoice...
|
||||||
|
Entity/ # Entites et Aggregates du domaine
|
||||||
|
ValueObject/ # Value Objects (Money, Address, Email...)
|
||||||
|
Repository/ # Interfaces des repositories (ports)
|
||||||
|
Service/ # Services domaine (logique metier)
|
||||||
|
Event/ # Domain Events
|
||||||
|
Exception/ # Exceptions metier
|
||||||
|
Application/ # Couche application (cas d'usage, orchestration)
|
||||||
|
{BoundedContext}/
|
||||||
|
Command/ # Commands (write) + Handlers
|
||||||
|
Query/ # Queries (read) + Handlers
|
||||||
|
DTO/ # Data Transfer Objects
|
||||||
|
Infrastructure/ # Couche infrastructure (implementations techniques)
|
||||||
|
{BoundedContext}/
|
||||||
|
Repository/ # Implementations Doctrine des repositories
|
||||||
|
Persistence/ # Mapping Doctrine (si XML/YAML)
|
||||||
|
Shared/ # Services techniques partages (mail, storage, etc.)
|
||||||
|
Api/ # Couche API (exposition HTTP)
|
||||||
|
{BoundedContext}/
|
||||||
|
Resource/ # ApiResource API Platform
|
||||||
|
State/ # Providers & Processors API Platform
|
||||||
|
```
|
||||||
|
|
||||||
|
**Regles DDD backend :**
|
||||||
|
- Le domaine (`Domain/`) ne depend de RIEN (pas de Doctrine, pas de Symfony, pas d'API Platform)
|
||||||
|
- Les repositories dans `Domain/` sont des **interfaces** ; les implementations Doctrine sont dans `Infrastructure/`
|
||||||
|
- Les entites API Platform (`Api/Resource/`) sont decouples des entites domaine si necessaire
|
||||||
|
- Chaque Bounded Context est autonome — pas d'import croise entre contextes (communiquer via events ou services application)
|
||||||
|
- `User` et `Auth` restent dans `src/` (hors DDD) car c'est du framework pur (Security Bundle)
|
||||||
|
|
||||||
|
### Frontend — Organisation par domaine
|
||||||
|
|
||||||
|
```
|
||||||
|
frontend/
|
||||||
|
domains/ # Modules metier
|
||||||
|
{bounded-context}/ # Ex: customer, sales, catalog, invoice...
|
||||||
|
components/ # Composants Vue specifiques au domaine
|
||||||
|
composables/ # Composables specifiques au domaine
|
||||||
|
services/ # Services API du domaine
|
||||||
|
dto/ # Types TypeScript du domaine
|
||||||
|
pages/ # Pages du domaine (optionnel, ou dans pages/)
|
||||||
|
stores/ # Store Pinia du domaine (si necessaire)
|
||||||
|
components/ # Composants UI partages (non lies a un domaine)
|
||||||
|
composables/ # Composables partages (useApi, useAppVersion)
|
||||||
|
stores/ # Stores globaux (auth, ui)
|
||||||
|
services/ # Services partages
|
||||||
|
```
|
||||||
|
|
||||||
|
**Regles DDD frontend :**
|
||||||
|
- Chaque domaine est un dossier autonome dans `frontend/domains/`
|
||||||
|
- Un domaine ne doit pas importer depuis un autre domaine — utiliser les composables/stores partages
|
||||||
|
- Les composants, services et types partages restent a la racine (`components/`, `composables/`, etc.)
|
||||||
|
- Les pages peuvent etre dans `frontend/pages/` (routing Nuxt) et importer les composants du domaine
|
||||||
|
|
||||||
## Stack
|
## Stack
|
||||||
|
|
||||||
@@ -12,26 +75,37 @@ CRM/ERP. Monorepo Symfony 8 (API Platform 4) + Nuxt 4.
|
|||||||
## Structure
|
## Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
src/Entity/ # Entites Doctrine (User)
|
src/
|
||||||
src/ApiResource/ # Ressources API Platform decouples (AppVersion)
|
Domain/{Context}/Entity/ # Entites domaine
|
||||||
src/State/ # Providers et Processors API Platform (MeProvider, AppVersionProvider, UserPasswordHasherProcessor)
|
Domain/{Context}/ValueObject/ # Value Objects
|
||||||
src/Service/ # Services metier
|
Domain/{Context}/Repository/ # Interfaces repositories
|
||||||
src/Repository/ # Repositories Doctrine
|
Domain/{Context}/Service/ # Services domaine
|
||||||
src/DataFixtures/ # Fixtures
|
Domain/{Context}/Event/ # Domain Events
|
||||||
config/ # Config Symfony (security, api_platform, lexik_jwt, nelmio_cors, doctrine)
|
Application/{Context}/Command/ # Commands + Handlers
|
||||||
config/jwt/ # Cles JWT (private.pem, public.pem)
|
Application/{Context}/Query/ # Queries + Handlers
|
||||||
migrations/ # Migrations Doctrine
|
Application/{Context}/DTO/ # Data Transfer Objects
|
||||||
infra/dev/ # Config Docker dev (Dockerfile, nginx, php.ini, xdebug)
|
Infrastructure/{Context}/Repository/ # Implementations Doctrine
|
||||||
infra/prod/ # Config Docker prod (Dockerfile multi-stage, nginx, php-prod.ini)
|
Api/{Context}/Resource/ # ApiResource API Platform
|
||||||
frontend/ # App Nuxt 4
|
Api/{Context}/State/ # Providers & Processors
|
||||||
frontend/pages/ # Pages (index, login)
|
Entity/ # Entites framework (User)
|
||||||
frontend/layouts/ # Layouts (default)
|
DataFixtures/ # Fixtures
|
||||||
frontend/components/ # Composants Vue
|
config/ # Config Symfony
|
||||||
frontend/composables/# Composables (useApi, useAppVersion)
|
config/jwt/ # Cles JWT
|
||||||
frontend/stores/ # Stores Pinia (auth, ui)
|
migrations/ # Migrations Doctrine
|
||||||
frontend/services/ # Services API (auth)
|
infra/dev/ # Docker dev
|
||||||
frontend/services/dto/ # Types TypeScript
|
infra/prod/ # Docker prod (multi-stage)
|
||||||
frontend/i18n/locales/ # Fichiers de traduction
|
frontend/
|
||||||
|
domains/{context}/components/ # Composants du domaine
|
||||||
|
domains/{context}/composables/ # Composables du domaine
|
||||||
|
domains/{context}/services/ # Services API du domaine
|
||||||
|
domains/{context}/dto/ # Types TS du domaine
|
||||||
|
domains/{context}/stores/ # Store Pinia du domaine
|
||||||
|
components/ # Composants UI partages
|
||||||
|
composables/ # Composables partages (useApi, useAppVersion)
|
||||||
|
stores/ # Stores globaux (auth, ui)
|
||||||
|
pages/ # Pages (routing Nuxt)
|
||||||
|
layouts/ # Layouts
|
||||||
|
i18n/locales/ # Traductions
|
||||||
```
|
```
|
||||||
|
|
||||||
## Commandes
|
## Commandes
|
||||||
|
|||||||
11149
composer.lock
generated
Normal file
11149
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
1911
config/reference.php
Normal file
1911
config/reference.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,2 @@
|
|||||||
parameters:
|
parameters:
|
||||||
app.version: '0.1.2'
|
app.version: '0.1.8'
|
||||||
|
|||||||
0
frontend/domains/.gitkeep
Normal file
0
frontend/domains/.gitkeep
Normal file
@@ -74,13 +74,13 @@ RUN cd frontend && npm ci && npm run build:dist && rm -rf node_modules
|
|||||||
RUN chown -R www-data:www-data /var/www/html/var /var/www/html/frontend/dist
|
RUN chown -R www-data:www-data /var/www/html/var /var/www/html/frontend/dist
|
||||||
|
|
||||||
# PHP prod config
|
# PHP prod config
|
||||||
COPY infra/deploy/php-prod.ini /usr/local/etc/php/php.ini
|
COPY infra/prod/php-prod.ini /usr/local/etc/php/php.ini
|
||||||
|
|
||||||
EXPOSE 9000
|
EXPOSE 9000
|
||||||
|
|
||||||
# ── Nginx stage ──
|
# ── Nginx stage ──
|
||||||
FROM nginx:1.27-alpine AS nginx
|
FROM nginx:1.27-alpine AS nginx
|
||||||
|
|
||||||
COPY infra/deploy/nginx.conf /etc/nginx/conf.d/default.conf
|
COPY infra/prod/nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
COPY --from=php-base /var/www/html/public /var/www/html/public
|
COPY --from=php-base /var/www/html/public /var/www/html/public
|
||||||
COPY --from=php-base /var/www/html/frontend/dist /var/www/html/frontend/dist
|
COPY --from=php-base /var/www/html/frontend/dist /var/www/html/frontend/dist
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\State;
|
namespace App\Api\Auth\State;
|
||||||
|
|
||||||
use ApiPlatform\Metadata\Operation;
|
use ApiPlatform\Metadata\Operation;
|
||||||
use ApiPlatform\State\ProviderInterface;
|
use ApiPlatform\State\ProviderInterface;
|
||||||
@@ -2,11 +2,12 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\State;
|
namespace App\Api\Auth\State;
|
||||||
|
|
||||||
use ApiPlatform\Metadata\Operation;
|
use ApiPlatform\Metadata\Operation;
|
||||||
use ApiPlatform\State\ProcessorInterface;
|
use ApiPlatform\State\ProcessorInterface;
|
||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,7 +16,7 @@ use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
|||||||
class UserPasswordHasherProcessor implements ProcessorInterface
|
class UserPasswordHasherProcessor implements ProcessorInterface
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
/** @var ProcessorInterface<User, User> */
|
#[Autowire(service: 'api_platform.doctrine.orm.state.persist_processor')]
|
||||||
private readonly ProcessorInterface $persistProcessor,
|
private readonly ProcessorInterface $persistProcessor,
|
||||||
private readonly UserPasswordHasherInterface $passwordHasher,
|
private readonly UserPasswordHasherInterface $passwordHasher,
|
||||||
) {}
|
) {}
|
||||||
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\ApiResource;
|
namespace App\Api\Shared\Resource;
|
||||||
|
|
||||||
use ApiPlatform\Metadata\ApiResource;
|
use ApiPlatform\Metadata\ApiResource;
|
||||||
use ApiPlatform\Metadata\Get;
|
use ApiPlatform\Metadata\Get;
|
||||||
use App\State\AppVersionProvider;
|
use App\Api\Shared\State\AppVersionProvider;
|
||||||
|
|
||||||
#[ApiResource(
|
#[ApiResource(
|
||||||
operations: [
|
operations: [
|
||||||
@@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\State;
|
namespace App\Api\Shared\State;
|
||||||
|
|
||||||
use ApiPlatform\Metadata\Operation;
|
use ApiPlatform\Metadata\Operation;
|
||||||
use ApiPlatform\State\ProviderInterface;
|
use ApiPlatform\State\ProviderInterface;
|
||||||
|
use App\Api\Shared\Resource\AppVersion;
|
||||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,6 +21,6 @@ class AppVersionProvider implements ProviderInterface
|
|||||||
|
|
||||||
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object
|
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object
|
||||||
{
|
{
|
||||||
return new \App\ApiResource\AppVersion($this->appVersion);
|
return new AppVersion($this->appVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0
src/Application/.gitkeep
Normal file
0
src/Application/.gitkeep
Normal file
0
src/Domain/.gitkeep
Normal file
0
src/Domain/.gitkeep
Normal file
@@ -10,9 +10,9 @@ use ApiPlatform\Metadata\Get;
|
|||||||
use ApiPlatform\Metadata\GetCollection;
|
use ApiPlatform\Metadata\GetCollection;
|
||||||
use ApiPlatform\Metadata\Patch;
|
use ApiPlatform\Metadata\Patch;
|
||||||
use ApiPlatform\Metadata\Post;
|
use ApiPlatform\Metadata\Post;
|
||||||
|
use App\Api\Auth\State\MeProvider;
|
||||||
|
use App\Api\Auth\State\UserPasswordHasherProcessor;
|
||||||
use App\Repository\UserRepository;
|
use App\Repository\UserRepository;
|
||||||
use App\State\MeProvider;
|
|
||||||
use App\State\UserPasswordHasherProcessor;
|
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
||||||
|
|||||||
0
src/Infrastructure/Shared/.gitkeep
Normal file
0
src/Infrastructure/Shared/.gitkeep
Normal file
Reference in New Issue
Block a user