Skip to content
Payment Emulator LabDocumentationOpen console

Getting started

Project structure

The repository is an npm workspace with three applications. They share alockfile, not source code. Their only runtime contract is HTTP.

4 min read

Índice / Index · Español

The repository is an npm workspace with three applications. They share a lockfile, not source code. Their only runtime contract is HTTP.

text
apps/
├── api/
│   ├── src/core/                  # reusable API runtime
│   ├── src/modules/               # bounded business/technical areas
│   ├── src/providers/             # provider behaviour and wire vocabulary
│   ├── src/infrastructure/database/
│   ├── scripts/                   # seed, scenario compiler, contract import
│   └── test/                      # unit, property, conformance, integration
├── console/
│   ├── app/core/                  # console gateway/table/format runtime
│   ├── app/modules/               # operator-facing feature definitions
│   ├── app/pages/                 # thin routed pages
│   └── server/                    # Nitro BFF and sealed console session
└── checkout/
    ├── app/core/                  # checkout gateway and kit resolution
    ├── app/components/            # provider-neutral checkout shell
    ├── app/pages/                 # provider-shaped buyer URLs
    ├── providers/                 # provider-specific visual kits
    └── server/                    # Nitro BFF and separate buyer session
contracts/                         # official provider contract imports
scenarios/                         # editable canonical JSON scenarios
scripts/                           # whole-stack acceptance smoke
docs/
├── README.md                     # bilingual documentation entry
├── en/                           # English guides, fidelity and history
└── es/                           # Spanish guides, fidelity and history
.agents/                           # binding architecture rules
graphify-out/                      # generated, historical discovery snapshot

#apps/api/src/core

Responsibility: behaviour that must be identical for every provider or every control-plane module.

Directory Owns
core/providers/ ProviderPlugin, registry, canonical errors and static conformance
core/idempotency/ request fingerprint, PostgreSQL advisory lock, replay/conflict
core/money/ decimal/minor-unit conversion and fee arithmetic
core/http/ app setup, list contract, pagination, provider exception shaping
core/security/ access-token hashing, callers, roles and redaction

Put code here only when it is genuinely shared runtime behaviour. A helper used by one module belongs to that module.

#apps/api/src/modules

Each directory owns one bounded area end to end. Important modules are:

Module Responsibility
gateway provider request orchestration in the mandated order
payments canonical intent lifecycle and the only payment write path
ledger payment accounting, entries/postings and settlement
applications tenants, one-time credentials, expiry and row scope
users people, passwords, sessions and roles
gateways installation-level enablement and accounting overrides
checkout public buyer view and optional customer identity
scenarios built-in/custom scenario matching and version resolution
webhooks transactional outbox records and control-plane inspection
traces redacted request timeline
banking synthetic wallet funding and transfers
banks the catalogue of institutions: prefix, digits, currencies
bank-accounts external counterparties owned by users, each at a bank
health unauthenticated health probe

Controllers declare routes and DTOs; services perform multi-step work and use MikroORM's EntityManager directly. Do not add repository interfaces, aggregates, domain events or an application/domain/infrastructure split: this project explicitly does not use DDD.

#Known layout deferral

The architecture binding describes future per-module models/, dto/, services/ and controllers/ folders. The current tree still keeps all entities centrally in src/infrastructure/database/entities/ and several modules are flat. This is recorded in .agents/README.md. Match the current owning module when adding behaviour; do not start a one-module folder migration as part of an unrelated feature.

#apps/api/src/providers

Provider-specific HTTP truth belongs here: routes, contract validation, credentials, state/error vocabulary, webhook format and the two canonical/wire translations. Plugins are plain objects with no database, ledger or queue dependency.

  • mercadopago/ and stripe/ are routed implementations.
  • paypal/ routes OAuth, Orders v2 and selected Payments v2 operations.

Adding a provider also requires a registry row, conformance coverage, a fidelity document and—when it has a buyer surface—a checkout kit. Follow Adding a provider.

#Database files

  • Entities: apps/api/src/infrastructure/database/entities/
  • Ordered migrations: apps/api/src/infrastructure/database/migrations/
  • Configuration: apps/api/src/infrastructure/database/mikro-orm.config.ts
  • CLI entrypoint: apps/api/src/cli/migrate.ts

Entities are the source model; migrations are explicit schema history. Never edit an already-applied migration to represent a new change.

#Nuxt console

apps/console/app/core/ is the console's reusable runtime. Pages and module components use createRestGateway, useEntityCollection and RTable instead of assembling API requests independently. Nitro routes under server/api/ are the only browser-to-API path and forward the signed-in person's sealed session.

Place a new operator feature in the closest app/modules/<area>/; add a thin page only when it needs a route, and expose the smallest matching Nitro endpoint. What each piece of core/ owns — and the accessibility traps it exists to avoid — is in the console.

#Nuxt checkout

Provider-neutral layout belongs in apps/checkout/app/components/. Provider identity and flow belong in apps/checkout/providers/<id>/. The route pages map provider URL shapes to a kit through app/core/kits.ts.

The checkout has its own Nitro session and secret. Do not import from the console or backend, and do not add PrimeVue here. See the checkout.

#Generated and historical files

  • apps/api/src/modules/scenarios/default-scenarios.ts is generated from scenarios/**/*.json; edit the JSON and run npm run scenario:compile.
  • dist/, .nuxt/, .output/, coverage output and node_modules/ are build artifacts, not source.
  • graphify-out/ is generated discovery output from an older tree. Do not copy its src/... paths into current documentation without verifying them.
  • Root src/ contains only an old empty migration directory and is not the API source tree; active backend code is under apps/api/src/.
Payment Emulator Lab · RonuSoftwareMIT