Assist_Design/docs/development/domain/import-hygiene.md
barsa 465a62a3e8 Refactor Domain Mappings and Update Import Paths
- Removed the domain mappings module, consolidating related types and schemas into the id-mappings feature.
- Updated import paths across the BFF to reflect the new structure, ensuring compliance with import hygiene rules.
- Cleaned up unused files and optimized the codebase for better maintainability and clarity.
2025-12-26 17:27:22 +09:00

4.2 KiB
Raw Blame History

Import Hygiene Guide (Domain)

Principles

  • No deep imports: internal file layout is not part of the contract.
  • Barrels define the public API: if its not exported from the entrypoint, its not public.
  • Providers are integration-only: Portal must never import provider adapters/types.

Allowed import levels

  • Default (Portal + BFF):
    • @customer-portal/domain/<module>
    • @customer-portal/domain/toolkit
  • BFF-only (integration/infrastructure):
    • @customer-portal/domain/<module>/providers

Domain-internal helpers (for domain code only)

Sometimes provider helpers need to be shared across multiple domain mappers without becoming part of the public contract (and without enabling deep imports).

In those cases, keep the helpers in a stable internal location (e.g. packages/domain/common/providers/whmcs-utils/) and import them via relative imports from within packages/domain/**.

  • Allowed: inside packages/domain/** only
  • Never: imported from apps/**
  • Purpose: share provider-only helpers (parsing, encoding/serialization, provider quirks) across multiple domain mappers while keeping the app-facing API surface clean.

Quick Reference

Context Import Pattern Example
Portal/BFF domain types @customer-portal/domain/<module> import { Invoice } from "@customer-portal/domain/billing"
BFF provider adapters .../<module>/providers import { Whmcs } from "@customer-portal/domain/billing/providers"
Toolkit utilities @customer-portal/domain/toolkit import { Formatting } from "@customer-portal/domain/toolkit"

Architecture Diagram

graph TD
    subgraph Portal [Portal App]
        PC[PortalComponents]
    end

    subgraph BFF [BFF App]
        BC[BFFControllers]
        BI[BFFIntegrations]
    end

    subgraph Domain [Domain Package]
        DM[ModuleEntrypoints]
        DP[ProviderEntrypoints]
        DT[Toolkit]
    end

    PC -->|allowed| DM
    PC -->|allowed| DT
    PC -.->|BLOCKED| DP

    BC -->|allowed| DM
    BC -->|allowed| DT
    BI -->|allowed| DM
    BI -->|allowed| DP
    BI -->|allowed| DT

Never

  • @customer-portal/domain/<module>/** (anything deeper than the module entrypoint)
  • @customer-portal/domain/<module>/providers/** (anything deeper than /providers)
  • apps/portal/** importing any @customer-portal/domain/*/providers

Rule of thumb

Import from the highest stable entrypoint that contains what you need.

  • If it exists in @customer-portal/domain/<module>, dont import a deeper file.
  • If its provider-specific, use @customer-portal/domain/<module>/providers (BFF-only).
  • If its cross-domain utility, use @customer-portal/domain/toolkit.

When to create a new explicit entrypoint (instead of deep-importing)

Create/adjust exports when:

  • The symbol is used in 2+ apps (Portal + BFF), or many call sites.
  • The symbol is part of a workflow that should remain stable (pagination, formatting, shared validation helpers).

Where to export it:

  • Module root (@customer-portal/domain/<module>): normalized domain types/models, schemas, provider-agnostic helpers.
  • Providers entrypoint (.../<module>/providers): provider adapters, mapper/query builder logic, raw provider shapes (if truly needed).
  • Toolkit (@customer-portal/domain/toolkit): shared utilities (Formatting, Validation, Typing namespaces).

Naming conventions

  • Module root: Invoice, invoiceSchema, validateOrderBusinessRules
  • Providers: Whmcs, Salesforce, Freebit namespaces; raw shapes should be obviously integration-only.

PR checklist

  • No @customer-portal/domain/*/* imports (except exact .../<module>/providers in BFF).
  • Portal has zero .../providers imports.
  • No wildcard subpath exports added to packages/domain/package.json#exports.

Validation

After changes:

  1. Run pnpm lint
  2. Run pnpm type-check
  3. Run pnpm build