Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Build & Run

**Prerequisites:** .NET 10 SDK, MongoDB 4.0+, .NET Aspire workload

```bash
dotnet workload install aspire
dotnet restore GrandNode.sln
dotnet build GrandNode.sln --configuration Release
```

**Run locally:** Set `Grand.Web` as the startup project in Visual Studio 2022+, or:
```bash
dotnet run --project src/Web/Grand.Web
```

**Run with .NET Aspire (orchestrated, includes MongoDB):**
```bash
dotnet run --project src/Aspire/Aspire.AppHost
```

## Testing

Tests require a running MongoDB instance on `localhost:27017`.

```bash
# Run all tests
dotnet test GrandNode.sln

# Run a single test project
dotnet test src/Tests/Grand.Business.Catalog.Tests/Grand.Business.Catalog.Tests.csproj

# Run with coverage
dotnet test --collect:"XPlat Code Coverage"
```

Test projects live in `src/Tests/`. Framework: MSTest + Moq + coverlet. Some tests use Verify.MSTest for snapshot testing.

## Architecture

### Layer Structure

```
Grand.Domain → Domain models (no dependencies on other layers)
Grand.SharedKernel → Base types, extension methods
Grand.Data → MongoDB repository abstractions + implementations
Grand.Infrastructure → DI wiring, caching, plugins, type search, startup pipeline
Grand.Mapping → AutoMapper profiles
Grand.Business.* → Business logic services (depend on Domain + Data)
Grand.Web.* → ASP.NET Core web apps (depend on Business)
src/Plugins/ → Optional extensions (payment, shipping, tax, etc.)
src/Modules/ → Core modules (API, Installer, Migration, ScheduledTasks)
```

### Startup Pipeline

`StartupBase.ConfigureServices` (called from `Program.cs`) orchestrates everything:
1. Registers config sections (`AppConfig`, `SecurityConfig`, `RedisConfig`, etc.)
2. Loads plugins via `PluginManager` and modules via `ModuleLoader`
3. Discovers all `IStartupApplication` implementations across all assemblies and calls them in priority order
4. Initializes AutoMapper by scanning for `IAutoMapperProfile` implementations
5. Registers MediatR handlers from all assemblies

Adding new startup logic: implement `IStartupApplication` with `BeforeConfigure`/`Priority` properties.

### Plugin & Module System

- **Plugins** (`src/Plugins/`): optional extensions loaded at runtime via `PluginManager`. Each plugin has its own `.csproj` and implements plugin-specific interfaces (e.g., `IPaymentProvider`, `IShippingRateComputationMethod`).
- **Modules** (`src/Modules/`): always-loaded core extensions (API, migrations, installer, scheduled tasks).
- Plugins are only active when listed in `App_Data/InstalledPlugins.json`.
- Both plugins and modules register their services via `IStartupApplication`.

### Data Access

- Primary database: MongoDB via `MongoDB.Driver`. Repositories are defined in `Grand.Data` and injected via interfaces.
- `DataSettingsManager` reads the connection string from `App_Data/DataSettings.json` (or environment variable `ConnectionStrings`).
- `LiteDB` is used as a fallback/embedded option.
- `DbProvider` enum controls which provider is active.

### CQRS / MediatR

Business operations use MediatR. Commands and queries are in `Grand.Business.Core` interfaces; handlers live in the specific `Grand.Business.*` projects. The web layer sends commands/queries through `IMediator`.

### Multi-Store / Multi-Tenant

Stores, languages, and currencies are first-class entities. Most business services accept a `storeId` parameter. `IWorkContext` (in `Grand.Web.Common`) provides current request context (store, customer, language, currency).

### Configuration Sections (appsettings.json)

Key sections bound to strongly-typed config objects:
- `Application` → `AppConfig`
- `Performance` → `PerformanceConfig`
- `Security` → `SecurityConfig`
- `Cache` → `CacheConfig`
- `Redis` → `RedisConfig`
- `BackendAPI` / `FrontendAPI` → respective config classes
- `Amazon` / `Azure` → cloud storage configs

## Key Directories

| Path | Purpose |
|------|---------|
| `src/Core/` | Domain, infrastructure, data, mapping |
| `src/Business/` | Business logic services |
| `src/Web/Grand.Web/` | Main web host (entry point) |
| `src/Web/Grand.Web.Admin/` | Admin panel controllers/views |
| `src/Web/Grand.Web.Store/` | Storefront controllers/views |
| `src/Web/Grand.Web.Vendor/` | Vendor portal |
| `src/Plugins/` | Optional plugin assemblies |
| `src/Modules/` | Core module assemblies |
| `src/Tests/` | Unit test projects |
| `src/Aspire/` | .NET Aspire host + service defaults |

## Project Guides

Detailed per-layer guides live in `docs/guides/`. **Read the relevant guide before exploring or modifying code in that area.** Each guide covers: project responsibilities, key types, design patterns, dependencies, and how-to instructions for common tasks.

| Guide | When to read |
|-------|-------------|
| [`docs/guides/core-layer.md`](docs/guides/core-layer.md) | Working on Grand.SharedKernel, Grand.Domain, Grand.Data, Grand.Mapping, or Grand.Infrastructure |
| [`docs/guides/business-layer.md`](docs/guides/business-layer.md) | Working on any `Grand.Business.*` project — services, CQRS handlers, events |
| [`docs/guides/web-layer.md`](docs/guides/web-layer.md) | Working on Grand.Web, Grand.Web.Admin, Grand.Web.Store, Grand.Web.Vendor, or Grand.Web.Common |
| [`docs/guides/modules.md`](docs/guides/modules.md) | Working on Grand.Module.Api, Installer, Migration, or ScheduledTasks |
| [`docs/guides/plugins.md`](docs/guides/plugins.md) | Creating or modifying payment, shipping, tax, widget, or authentication plugins |
| [`docs/guides/testing.md`](docs/guides/testing.md) | Writing tests — patterns, test helpers, infrastructure |
| [`docs/guides/aspire.md`](docs/guides/aspire.md) | Using .NET Aspire for local orchestration or adding observability |
72 changes: 72 additions & 0 deletions docs/guides/aspire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Aspire Guide

Projects in `src/Aspire/`. .NET Aspire orchestration for local development and cloud-native observability.

## Projects

### Aspire.AppHost

**Path:** `src/Aspire/Aspire.AppHost/`

Orchestrates the entire application for local development. Run this instead of `Grand.Web` directly when you need a managed MongoDB instance.

**What it provisions:**
- MongoDB container on port 27017 with `ContainerLifetime.Persistent` (survives restarts, data is preserved)
- `Grand.Web` ASP.NET Core project on port 80

**Usage:**
```bash
dotnet run --project src/Aspire/Aspire.AppHost
```

The Aspire dashboard opens automatically and shows service health, logs, and traces.

**How MongoDB is wired:**
```csharp
var mongodb = builder.AddMongoDB("mongo")
.WithLifetime(ContainerLifetime.Persistent);

builder.ConfigureGrandWebProject(mongodb);
// ↑ Injects the MongoDB connection string into Grand.Web's environment
```

`ProjectConfiguration.cs` contains the `ConfigureGrandWebProject` extension method. Modify it to add new services (Redis, messaging, etc.) to the orchestrated environment.

**Adding a new service:**
1. Add the Aspire component package (e.g., `Aspire.Hosting.Redis`)
2. Call `builder.AddRedis("redis")` in `Program.cs`
3. Pass the resource reference to `ConfigureGrandWebProject` and inject it into `Grand.Web`

---

### Aspire.ServiceDefaults

**Path:** `src/Aspire/Aspire.ServiceDefaults/`

Shared observability and resilience defaults. Reference this project from any service you want to instrument.

**What it configures (single call):**
```csharp
builder.AddServiceDefaults();
```

| Feature | Detail |
|---------|--------|
| OpenTelemetry Logging | Structured logs with scopes and formatting |
| OpenTelemetry Metrics | ASP.NET Core, HTTP Client, .NET Runtime metrics |
| OpenTelemetry Tracing | ASP.NET Core + HTTP Client distributed tracing |
| OTLP Exporter | Sends telemetry to Aspire dashboard (or any OTLP backend) |
| Azure Monitor | Optional integration when `APPLICATIONINSIGHTS_CONNECTION_STRING` is set |
| Service Discovery | `AddServiceDiscovery()` for named service resolution |
| HTTP Resilience | `AddStandardResilienceHandler()` on all HTTP clients |
| Health Checks | `/health` (liveness) and `/alive` (readiness) endpoints |

**When to touch:** Adding a new telemetry source (e.g., a custom meter), changing resilience policy, or integrating a new observability backend.

## Relationship to Non-Aspire Startup

`Grand.Web` runs correctly both with and without Aspire:
- **With Aspire:** `Aspire.AppHost` injects `ConnectionStrings__mongo` environment variable, overriding `App_Data/DataSettings.json`
- **Without Aspire:** `DataSettingsManager` reads connection string from `App_Data/DataSettings.json` directly

No code changes are needed in `Grand.Web` to support both modes.
Loading