FranciscoKloganB cursor-demo .cursorrules file for Go

# Cursor Rules

Assume the role of a Golang programmer using [Encore framework](https://encore.dev/docs/go).

- The project will follow uses domain driven design and hexagonal architecture.

## Folder structure for example module using domain driven design and hexagonal architecture

```
alarms
├── application
│   ├── commands
│   │   ├── create_alarm_command_handler.go
│   │   └── create_alarm_command.go
│   ├── events
│   │   └── alarm_created_event_handler.go
│   ├── queries
│   │   ├── list_alarms_query.go
│   │   └── list_alarms_query_handler.go
│   ├── ports
│   │   ├── create_alarm_repository_port.go
│   │   ├── find_alarms_repository_port.go
│   │   └── upsert_materialized_alarm_repository_port.go
│   └── alarms_facade.go
│   └── alarms_factory.go
├── domain
│   ├── aggregates
│   │   └── alarm_aggregate.go
│   ├── events
│   │   └── alarm_created_event.go
│   ├── models
│   │   └── alarm_read_model.go
│   ├── valueobjects
│   │   └── alarm_severity.go
│   ├── entities
│   │   └── alarm.go
│   │   └── alarm_item.go
├── infrastructure
│   └── persistence
│       ├── entities
│       │   ├── alarm_entity.go
│       │   └── alarm_item_entity.go
│       ├── mappers
│       │   └── alarm_mapper.go
│       ├── repositories
│       │   ├── migrations
│       │   │   └── 1_create_foo_table.sql
│       │   │   └── 2_create_bar_table.sql
│       │   │   └── 3_add_column_x_on_foo_table.sql
│       │   ├── create_alarm_repository.go
│       │   ├── find_alarms_repository.go
│       │   └── upsert_materialized_alarm_repository.go
│       └── schemas
│           └── materialized_alarm_view_schema.go
└── presentation
    └── http
        ├── dto
        │   └── create_alarm_dto.go
        └── alarms_controller.go
```

## Hexagonal Architecture Specifications

### Presentation Layer

- The presentation layer contains user facing-components, such has controllers, gateways and other APIs.
- The presentation layer commands to forward data to application services (e.g., facades).
- The presentation layer queries to forward data to application services (e.g., facades).

### Application Layer

- The applicational layer contains application services (e.g., facades, handlers).
- The applicational exposes primary ports and secondary ports.
- The applicational primary ports include commands and query structs and applicational service interfaces.
- The applicational secondary ports (a.k.a. adapters) are implemented on the infrastructure layer.
- The application layer can access the infrastructure layer via secondary port interfaces.
- The application layer can access the domain layer through aggregates that are exposed by the domain layer.
- The application layer can access the domain layer through domain objects only on simple (e.g., little or no business logic, data-reads).
- The application layer can not access anything from the presentation layer, not even data transfer objects.
- Commands should be concrete classes or structs.
- Commands define payloads that the application layer to uses to start data-write procedures, with or without CQRS implementation.
- Queries should be concrete classes or structs.
- Queries define payloads that the application layer to uses to start data-read procedures, with or without CQRS implementation.
- Applicational services should always expose an abstract class or interfaces.
- Applicational service interfaces will be used in module initialization.
- Secondary ports should always be interfaces.
- Secondary ports are implemented by Adapters at the infrastructure layer (e.g., ICreateAlarmRepository from application layer is implemented in CreateAlarmRepository and/or CreateAlarmRepositoryV2 at infrastructure layer).

### Domain Layer

- The domain layer contains domain models, value objects, events and other domain specific components that represent the business.
- The domain layer can only be accessed from the applicational layer.

### Infrastructure layer

- The infrastructure layer contains data access components, such as message brokers, repositories and clients to external system.
- The infrastructure layer implements the secondary (ports) defined by the application layer called adapters (e.g., concrete repository).
- The infrastructure layer can only be accessed from the applicational layer.
- Adapters use mapper classes to ensure domain or value objects, are returned its methods.
- Adapters can reference domain classes and value objects, but should not operate or modify them.

## Domain Driven Design Specifications (considering Hexagonal Architecture)

### Core Concepts

- Value objects must be immutable and have no identifiers (ID).
- Value objects should be immutable and side-effect free.
- Entities must have unique identifiers (ID) and can be mutable.
- Entities are represented by domain objects on the domain layer.
- Entities are represented by sqlc objects (entity or models) on the infrastructure layer.
- Aggregates are clusters of domain objects treated as single units for consistency.
- Aggregates changes occur in memory and are persisted via together through transactions.
- Domain objects within aggregates can only be changed through aggregates public interface.

### Factories

- Use factories to handle struct validation and initialization logic.
- Use factories to hide implementation details behind complex object creation.
- Use factories to keep domain models focused on business logic

### Services

- Use applicational services (e.g., facades, usecases) to coordinate and fullfil applicational commands and queries.
- Use applicational services to communicate with the infrastructure and domain layers from the application layer.
- Use domain services (aggregates) to coordinate changes across multiple domain objects and/or value-objects.
- Use domain services (root aggregates) for logic that does not belong to a single aggregate.
- Root aggregates and aggregates should only be created when they contain actual business logic, not just getters/setters.
- Avoid creating domain services for any other purpose other than the highlighted ones.

### Repositories

- Repositories should be used to effectuate persisting/retrieving of entity objects.
- Repositories should return domain objects.
- Repositories should use mappers to convert domain objects to entity objects.
- Repositories should use mappers to convert objects objects to domain objects.
- Repositories should convert entity objects to SQLC parameters inline when performing queries.
- Repositories should hide implementation details of the underlying storage (sql, nosql, cache, in-memory).

### Events

- Domain events should represent domain state changes that have been persisted.
- Domain events should be emitted from domain layer.
- Domain events should be declared and handled in application layer.
- Domain events handlers that are declared in the application layer can access infrastructure layer.
- Domain events handlers can be declared and handled in domain layer for ponctual and only for pure business policy reactions.
- Domain events handlers that are declared in the domain layer can not access infrastructure layer.
- Integration events should be for cross-service communication (e.g., separate module boundary).
- Integration events should be lighter than domain events.

### CQRS

- Separate read and write operations
- Write side handles commands and state updates
- Read side handles events and read model updates
- Eventual consistency between read/write models
- Best for read-heavy systems

## Golang Specifications

### Basic Principles

- Always write code and documentation in English.
- Prompt requirements should be followed carefully.
- Prompt requirements should have priority over rules outlined in this document.
- Add logs often and frequently using Encore logger (package: encore.dev/rlog).
- Add logs with debug, info, warn, error and fatal levels as appropriate.
- Add middleware to handle Cross-cutting concerns (e.g., catch-all error handling and logging, authentication, etc.).
- Comments should be added to every exported (public) functions or variables.
- Comments should not be added to unexported (private) functions or variables, unless prompted.
- Consider Encore framework intricacies when writting code.
- Rest endpoints should authentication/authorization as appropriate,
- Rest endpoints should implement basic validation using Encore Validation mechanism.
- Rest endpoints should implement rate limiting as appropriate.
- Rest endpoints should return appropriate status codes.
- Rest endpoints should return json.
- Domain aggregates should implement business concern validations using spec functions inspired by Domain Driven Desing.
- Include necessary imports, package declarations, and any required setup code.
- Inform me when the setup code requires me to install a go or 3rd party package.

### Nomenclature

- Use PascalCase for public variables, functions, interfaces and structs.
- Use camelCase for package private variables, functions, interfaces and structs.
- Use camelCase for block-scoped variables.
- Use UPPERCASE for constant and environment variables.
- Use lowcase for directory names.
- Use snake_case for file names.
- Use snake_case specifiers after the actual file name, before the file extension (e.g., 'settings_controller.go').
- Use verbs such has `is`, `has` and `can` to denote Booleanish variables (e.g., isLoading, hasError, canDelete).
- Use complete words instead of abbreviations. The following exceptions are made:
    - i, j denoting iterated values or indexes in loops
    - args denoting arguments
    - ctx denoting context
    - err denoting error
    - next denoting next middleware
    - params denoting parameters
    - req denoting request
    - res denoting response
    - Db denoting Database
    - Api denoting Access Pointer Interface
    - Url denoting Unique Resource Locator
    - Http denoting Hyper Text Transfer Protocol

### Errors and Exceptions

- Errors should be handled often to fix recoverable problems, log or add context.
- Errors should be bubbled up if we can not do anything useful with them.
- It is okay to use `defer` and `recovery` to handle some `panic` events at the top level of the application.

### Functions Specifics

- Functions should have names that start with a verb (e.g., CreateFlag, DeactivateUser).
- Functions should be short, concise and side-effect free.
- Functions should accept no more than four parameters.
- Functions should accept interfaces when they absolutly need a large quantity of parameters.
- Functions should avoid deeply nested blocks.
- Functions should not validate parameters unless asked as part of prompted requirements.

### Testing

- Test can use official Golang, `go-resty/resty` and `stretchr/testify` packages.
- Test names should be concise.
- Test names should start with a verb. Example: TestReturnsFooBar
- Test names should not contain redudant (implied) verbs such has "should", "must" and "check".
- Tests blocks the Arrange-Act-Assert convention for tests.
- Test variable names should follow the convention: inputX, mockX, actualX, expectedX, etc.
- Unit tests should be written for pure functions that are publicly exposed by modules.
- Unit tests should be written methods of controllers, facades, factories, mappers, services, repositories, etc.
- Unit tests should use mocks, stubs, spies and doubles to simulate dependencies unless prompted otherwise.
- Acceptance (API or E2E) tests should be written for api endpoints or application entry points.
go
golang
less
nestjs
react
rest-api
shell

First Time Repository

Go

Languages:

Go: 132.8KB
Shell: 1.1KB
Created: 1/7/2025
Updated: 1/7/2025

All Repositories (1)