2.8 KiB
Nx Workspace Boundaries
This document records the current monorepo boundary conventions for IPTVnator.
Fresh Worktree Bootstrap
Install dependencies before using Nx discovery or targets:
pnpm install --frozen-lockfile
pnpm nx show projects
pnpm nx show projects depends on the workspace-local Nx packages under
node_modules. In a fresh worktree without dependencies it will fail before it
can inspect project metadata.
Project Tags
Every Nx project should carry three tag families in project.json:
scope:*- ownership area, for examplescope:portal,scope:workspace,scope:shared,scope:electron,scope:e2e, orscope:dev-tools.domain:*- product/runtime domain, for exampledomain:xtream,domain:stalker,domain:m3u,domain:playback,domain:web, ordomain:shared-runtime.type:*- architectural role, for exampletype:app,type:e2e,type:dev-app,type:feature,type:ui,type:data-access,type:util,type:tool, ortype:website.
eslint.config.mjs uses these tags with @nx/enforce-module-boundaries.
When adding a project, choose tags before adding imports so dependency direction
is clear from the start.
Import Aliases
Use scoped @iptvnator/* aliases from tsconfig.base.json.
Examples:
import { SettingsStore } from '@iptvnator/services';
import { Playlist } from '@iptvnator/shared/interfaces';
import { DialogService } from '@iptvnator/ui/components';
Do not introduce legacy bare aliases such as:
componentsm3u-statem3u-utilsservicesshared-interfacesshared-portalsremote-controldatabasedatabase-schemadatabase-path-utilsworkspace-dashboard-featureworkspace-dashboard-data-access
The lint config blocks these aliases so new code uses the same visible namespace and ownership convention.
Buildable libraries that have a local package.json should use the same public
name as their scoped alias. Nx uses package.json.name when it rewrites
buildable dependency paths to dist/ during @nx/js:tsc builds.
Dependency Direction
type:featuremay usetype:feature,type:ui,type:data-access, andtype:util.type:uimay usetype:ui,type:data-access, andtype:util.type:data-accessmay usetype:data-accessandtype:util.type:utilmay use onlytype:util.
If a change needs a dependency in the opposite direction, move the shared contract into a lower-level library instead of weakening boundaries.
Portal collection orchestration that reads/writes favorites, recent items, live
playback, or EPG data belongs in libs/portal/shared/data-access, not
libs/portal/shared/util. That keeps pure collection helpers importable by
Xtream/Stalker data-access libraries while allowing shared UI to use
provider-specific collection services without creating cycles.