- 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.
4.2 KiB
4.2 KiB
Import Hygiene Guide (Domain)
Principles
- No deep imports: internal file layout is not part of the contract.
- Barrels define the public API: if it’s not exported from the entrypoint, it’s 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>, don’t import a deeper file. - If it’s provider-specific, use
@customer-portal/domain/<module>/providers(BFF-only). - If it’s 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,Typingnamespaces).
Naming conventions
- Module root:
Invoice,invoiceSchema,validateOrderBusinessRules - Providers:
Whmcs,Salesforce,Freebitnamespaces; raw shapes should be obviously integration-only.
PR checklist
- No
@customer-portal/domain/*/*imports (except exact.../<module>/providersin BFF). - Portal has zero
.../providersimports. - No wildcard subpath exports added to
packages/domain/package.json#exports.
Validation
After changes:
- Run
pnpm lint - Run
pnpm type-check - Run
pnpm build