diff --git a/apps/web/src/app/app.config.ts b/apps/web/src/app/app.config.ts index 70001db7b..1fc0d8950 100644 --- a/apps/web/src/app/app.config.ts +++ b/apps/web/src/app/app.config.ts @@ -30,7 +30,7 @@ import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { PORTAL_EXTERNAL_PLAYBACK, PORTAL_PLAYER, -} from '@iptvnator/portal/shared/util'; +} from '@iptvnator/portal/shared/util/tokens'; import { STALKER_PLAYLIST_CONNECTION_EDITOR } from '@iptvnator/playlist/shared/ui/stalker-connection-editor'; import { provideXtreamDataSource } from '@iptvnator/portal/xtream/data-access'; import { diff --git a/apps/web/src/app/services/electron.service.ts b/apps/web/src/app/services/electron.service.ts index dd5be4f0b..ec2c7e85f 100644 --- a/apps/web/src/app/services/electron.service.ts +++ b/apps/web/src/app/services/electron.service.ts @@ -36,7 +36,7 @@ import { createLogger, createPortalDebugRequestContext, logPortalDebugEvent, -} from '@iptvnator/portal/shared/util'; +} from '@iptvnator/portal/shared/util/logger'; interface PlayerLaunchPayload { readonly headers?: Record; diff --git a/apps/web/src/app/services/portal-playback-positions.service.ts b/apps/web/src/app/services/portal-playback-positions.service.ts index bcc29b73b..8ffe27383 100644 --- a/apps/web/src/app/services/portal-playback-positions.service.ts +++ b/apps/web/src/app/services/portal-playback-positions.service.ts @@ -2,7 +2,7 @@ import { Injectable, inject } from '@angular/core'; import { PORTAL_PLAYBACK_POSITIONS, PortalPlaybackPositions, -} from '@iptvnator/portal/shared/util'; +} from '@iptvnator/portal/shared/util/tokens'; import { PlaybackPositionRuntimeBridgeService, RuntimeCapabilitiesService, diff --git a/apps/web/src/app/services/pwa.service.ts b/apps/web/src/app/services/pwa.service.ts index 497e07e65..2dc932a75 100644 --- a/apps/web/src/app/services/pwa.service.ts +++ b/apps/web/src/app/services/pwa.service.ts @@ -34,7 +34,7 @@ import { logPortalDebugEvent, logPortalDebugRequest, createLogger, -} from '@iptvnator/portal/shared/util'; +} from '@iptvnator/portal/shared/util/logger'; import { getRuntimeBackendUrl } from './runtime-config'; /** diff --git a/apps/web/src/app/services/workspace-shell-actions.service.ts b/apps/web/src/app/services/workspace-shell-actions.service.ts index a110883a6..3e7dc0921 100644 --- a/apps/web/src/app/services/workspace-shell-actions.service.ts +++ b/apps/web/src/app/services/workspace-shell-actions.service.ts @@ -1,7 +1,7 @@ import { inject, Injectable, Provider } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { Router } from '@angular/router'; -import { PORTAL_SHELL_ACTIONS } from '@iptvnator/portal/shared/util'; +import { PORTAL_SHELL_ACTIONS } from '@iptvnator/portal/shared/util/tokens'; import { WORKSPACE_SHELL_ACTIONS, WorkspaceAccountInfoData, diff --git a/apps/web/src/app/settings/settings-backup.facade.spec.ts b/apps/web/src/app/settings/settings-backup.facade.spec.ts index a14201475..0fcce600a 100644 --- a/apps/web/src/app/settings/settings-backup.facade.spec.ts +++ b/apps/web/src/app/settings/settings-backup.facade.spec.ts @@ -5,7 +5,7 @@ import { selectIsEpgAvailable, } from '@iptvnator/m3u-state'; import { XtreamStore } from '@iptvnator/portal/xtream/data-access'; -import { PlaylistBackupService } from '@iptvnator/services'; +import { PlaylistBackupService } from '@iptvnator/services/playlist-backup'; import { provideMockStore } from '@ngrx/store/testing'; import { TranslateModule } from '@ngx-translate/core'; import { MockProvider } from 'ng-mocks'; diff --git a/apps/web/src/app/settings/settings-backup.facade.ts b/apps/web/src/app/settings/settings-backup.facade.ts index bebfc6004..91ed0d714 100644 --- a/apps/web/src/app/settings/settings-backup.facade.ts +++ b/apps/web/src/app/settings/settings-backup.facade.ts @@ -3,11 +3,11 @@ import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; import { PlaylistActions } from '@iptvnator/m3u-state'; import { XtreamStore } from '@iptvnator/portal/xtream/data-access'; +import { RuntimeCapabilitiesService } from '@iptvnator/services'; import { PlaylistBackupImportSummary, PlaylistBackupService, - RuntimeCapabilitiesService, -} from '@iptvnator/services'; +} from '@iptvnator/services/playlist-backup'; import { SettingsSnackbarService } from './settings-snackbar.service'; @Injectable() diff --git a/apps/web/src/app/settings/test-stubs/settings-test-harness.stub.ts b/apps/web/src/app/settings/test-stubs/settings-test-harness.stub.ts index 7c7925187..9d1af7ba8 100644 --- a/apps/web/src/app/settings/test-stubs/settings-test-harness.stub.ts +++ b/apps/web/src/app/settings/test-stubs/settings-test-harness.stub.ts @@ -34,9 +34,9 @@ import { import { DatabaseService, DataService, - PlaylistBackupService, PlaylistsService, } from '@iptvnator/services'; +import { PlaylistBackupService } from '@iptvnator/services/playlist-backup'; import { ELECTRON_BRIDGE_APP_UPDATE_STATUSES, ElectronBridgeAppUpdateStatus, diff --git a/docs/architecture/nx-workspace-boundaries.md b/docs/architecture/nx-workspace-boundaries.md index 05b48e61e..86daacfcb 100644 --- a/docs/architecture/nx-workspace-boundaries.md +++ b/docs/architecture/nx-workspace-boundaries.md @@ -237,7 +237,10 @@ reason: the main `workspace-shell-util` barrel is imported eagerly, and the settings search index must stay in the lazy settings and shell chunks. `@iptvnator/workspace/shell/util/settings-context` keeps `SettingsContextService`, which only the lazy settings page and settings -context panel use, out of that barrel for the same reason. +context panel use, out of that barrel for the same reason, and +`@iptvnator/services/playlist-backup` keeps `PlaylistBackupService` (about +22 KB, used only by the lazy settings page) out of the `@iptvnator/services` +barrel. The web app's root shell (`app.component.ts`, `app.config.ts` and the services they construct) is on the renderer's initial path, where a barrel costs its @@ -260,7 +263,19 @@ PIN dialog and the Stalker step of the parental-lock enforcement, which runs only while a Stalker route is open). A local file, not the library alias, is the dynamic-import target because `@nx/enforce-module-boundaries` forbids static imports of a library the same -project also loads dynamically. `renderer.initialBytes` in +project also loads dynamically. + +A barrel the initial path imports also costs code it never runs itself: +code splitting places a module in the chunk shared by every entry point +that reaches it, so a helper that only lazy routes use, but that an eager +file can reach through a barrel's re-export, lands in an initial chunk even +though tree shaking would drop it from a single bundle. The eager Xtream +data layer and root shell therefore import `@iptvnator/portal/shared/util/logger` +and `@iptvnator/portal/shared/util/tokens` (the portal DI tokens), not the +`@iptvnator/portal/shared/util` barrel, whose navigation, keyboard-shortcut +and download helpers (about 45 KB) belong to the lazy portal routes. A +type-only import of a barrel uses `import type`, so it can never keep the +barrel reachable. `renderer.initialBytes` in [performance journeys](performance-journeys.md) guards the result; to see why a module is eager, build with `pnpm nx build web --stats-json` and follow the static imports in `dist/apps/web/stats.json` from `apps/web/src/main.ts`. diff --git a/docs/architecture/parental-lock.md b/docs/architecture/parental-lock.md index e54d6fcad..331645296 100644 --- a/docs/architecture/parental-lock.md +++ b/docs/architecture/parental-lock.md @@ -419,8 +419,10 @@ opens, so a relock there runs the step synchronously; if it is not loaded yet (still fetching, or it cannot load — a stale PWA page after a deployment) the step fails closed at once by navigating to `/workspace/sources`: leaving the Stalker route clears its selection and -stops its playback, and the Xtream step still runs. The feature costs about 30 KB of -`renderer.initialBytes`. +stops its playback, and the Xtream step still runs. The feature costs about 35 KB of +`renderer.initialBytes`; the baseline was not raised for it, the growth was +offset by moving lazy-only barrel re-exports (backup/restore and the portal +helpers) off the initial path. ## Lock store lifetime diff --git a/libs/portal/shared/util/src/tokens.ts b/libs/portal/shared/util/src/tokens.ts new file mode 100644 index 000000000..3595e3a5f --- /dev/null +++ b/libs/portal/shared/util/src/tokens.ts @@ -0,0 +1,7 @@ +// Dependency-free entry for the DI tokens the web app's root shell and the +// eager Xtream data layer provide or inject. The main barrel would put every +// portal helper that lazy routes use onto the renderer's initial path. +export * from './lib/portal-external-playback'; +export * from './lib/portal-playback-positions'; +export * from './lib/portal-player'; +export * from './lib/portal-shell-actions'; diff --git a/libs/portal/xtream/data-access/src/lib/data-sources/pwa-xtream-data-source.ts b/libs/portal/xtream/data-access/src/lib/data-sources/pwa-xtream-data-source.ts index 252836900..1d3bf56e2 100644 --- a/libs/portal/xtream/data-access/src/lib/data-sources/pwa-xtream-data-source.ts +++ b/libs/portal/xtream/data-access/src/lib/data-sources/pwa-xtream-data-source.ts @@ -11,7 +11,7 @@ import { XtreamSerieItem, XtreamVodStream, } from '@iptvnator/shared/interfaces'; -import { createLogger } from '@iptvnator/portal/shared/util'; +import { createLogger } from '@iptvnator/portal/shared/util/logger'; import { CategoryType, StreamType, diff --git a/libs/portal/xtream/data-access/src/lib/services/epg-queue.service.ts b/libs/portal/xtream/data-access/src/lib/services/epg-queue.service.ts index eccc81f8b..11cb26476 100644 --- a/libs/portal/xtream/data-access/src/lib/services/epg-queue.service.ts +++ b/libs/portal/xtream/data-access/src/lib/services/epg-queue.service.ts @@ -8,7 +8,7 @@ import { import { EpgSourceSettingsService, SettingsStore } from '@iptvnator/services'; import { XtreamApiService, XtreamCredentials } from './xtream-api.service'; import { XtreamXmltvFallbackService } from './xtream-xmltv-fallback.service'; -import { createLogger } from '@iptvnator/portal/shared/util'; +import { createLogger } from '@iptvnator/portal/shared/util/logger'; interface CacheEntry { data: EpgItem[]; diff --git a/libs/portal/xtream/data-access/src/lib/services/xtream-api.service.ts b/libs/portal/xtream/data-access/src/lib/services/xtream-api.service.ts index 55ea8fa58..3a05889a5 100644 --- a/libs/portal/xtream/data-access/src/lib/services/xtream-api.service.ts +++ b/libs/portal/xtream/data-access/src/lib/services/xtream-api.service.ts @@ -1,6 +1,6 @@ import { inject, Injectable } from '@angular/core'; import { DataService } from '@iptvnator/services'; -import { createLogger } from '@iptvnator/portal/shared/util'; +import { createLogger } from '@iptvnator/portal/shared/util/logger'; import { EpgItem, XtreamCategory, diff --git a/libs/portal/xtream/data-access/src/lib/services/xtream-xmltv-fallback.service.ts b/libs/portal/xtream/data-access/src/lib/services/xtream-xmltv-fallback.service.ts index de0b42676..9f5d115cd 100644 --- a/libs/portal/xtream/data-access/src/lib/services/xtream-xmltv-fallback.service.ts +++ b/libs/portal/xtream/data-access/src/lib/services/xtream-xmltv-fallback.service.ts @@ -4,7 +4,7 @@ import { EpgProgram, epgProviderClockMs, } from '@iptvnator/shared/interfaces'; -import { createLogger } from '@iptvnator/portal/shared/util'; +import { createLogger } from '@iptvnator/portal/shared/util/logger'; import { EpgSourceSettingsService, SettingsStore } from '@iptvnator/services'; type ElectronEpgBridge = { diff --git a/libs/portal/xtream/data-access/src/lib/stores/features/with-content.feature.ts b/libs/portal/xtream/data-access/src/lib/stores/features/with-content.feature.ts index 9ed5a7bb0..0b8c0874a 100644 --- a/libs/portal/xtream/data-access/src/lib/stores/features/with-content.feature.ts +++ b/libs/portal/xtream/data-access/src/lib/stores/features/with-content.feature.ts @@ -16,7 +16,7 @@ import { measureRendererPerformancePhase, RENDERER_PERFORMANCE_PHASE, } from '@iptvnator/shared/logging'; -import { createLogger } from '@iptvnator/portal/shared/util'; +import { createLogger } from '@iptvnator/portal/shared/util/logger'; import { DataService, DatabaseService, diff --git a/libs/portal/xtream/data-access/src/lib/stores/features/with-epg.feature.ts b/libs/portal/xtream/data-access/src/lib/stores/features/with-epg.feature.ts index 024f7b32e..da0dc7f3c 100644 --- a/libs/portal/xtream/data-access/src/lib/stores/features/with-epg.feature.ts +++ b/libs/portal/xtream/data-access/src/lib/stores/features/with-epg.feature.ts @@ -22,7 +22,7 @@ import { XtreamCredentials, } from '../../services/xtream-api.service'; import { XtreamXmltvFallbackService } from '../../services/xtream-xmltv-fallback.service'; -import { createLogger } from '@iptvnator/portal/shared/util'; +import { createLogger } from '@iptvnator/portal/shared/util/logger'; /** * EPG state for managing Electronic Program Guide data diff --git a/libs/portal/xtream/data-access/src/lib/stores/features/with-player.feature.ts b/libs/portal/xtream/data-access/src/lib/stores/features/with-player.feature.ts index dd12bdebc..2b85a6807 100644 --- a/libs/portal/xtream/data-access/src/lib/stores/features/with-player.feature.ts +++ b/libs/portal/xtream/data-access/src/lib/stores/features/with-player.feature.ts @@ -5,7 +5,7 @@ import { withMethods, withState, } from '@ngrx/signals'; -import { PORTAL_PLAYER } from '@iptvnator/portal/shared/util'; +import { PORTAL_PLAYER } from '@iptvnator/portal/shared/util/tokens'; import { XtreamSerieEpisode, XtreamVodDetails, diff --git a/libs/portal/xtream/data-access/src/lib/stores/features/with-portal.feature.ts b/libs/portal/xtream/data-access/src/lib/stores/features/with-portal.feature.ts index 3f2737c79..69532df62 100644 --- a/libs/portal/xtream/data-access/src/lib/stores/features/with-portal.feature.ts +++ b/libs/portal/xtream/data-access/src/lib/stores/features/with-portal.feature.ts @@ -14,7 +14,7 @@ import { XtreamCredentials, } from '../../services/xtream-api.service'; import { PortalStatusType } from '../../xtream-state'; -import { createLogger } from '@iptvnator/portal/shared/util'; +import { createLogger } from '@iptvnator/portal/shared/util/logger'; import { resolveXtreamPortalStatus, resolveXtreamServerTimezone, diff --git a/libs/portal/xtream/data-access/src/lib/stores/features/with-search.feature.ts b/libs/portal/xtream/data-access/src/lib/stores/features/with-search.feature.ts index ed1a038b9..c2ebcebbc 100644 --- a/libs/portal/xtream/data-access/src/lib/stores/features/with-search.feature.ts +++ b/libs/portal/xtream/data-access/src/lib/stores/features/with-search.feature.ts @@ -14,7 +14,7 @@ import { XTREAM_DATA_SOURCE, XtreamContentItem, } from '../../data-sources/xtream-data-source.interface'; -import { createLogger } from '@iptvnator/portal/shared/util'; +import { createLogger } from '@iptvnator/portal/shared/util/logger'; import { XtreamSearchResultItem } from '../../xtream-state'; /** diff --git a/libs/portal/xtream/data-access/src/lib/stores/xtream.store.ts b/libs/portal/xtream/data-access/src/lib/stores/xtream.store.ts index fe8ca8df9..1c21edae4 100644 --- a/libs/portal/xtream/data-access/src/lib/stores/xtream.store.ts +++ b/libs/portal/xtream/data-access/src/lib/stores/xtream.store.ts @@ -12,7 +12,7 @@ import { XTREAM_DATA_SOURCE } from '../data-sources/xtream-data-source.interface import { XtreamApiService } from '../services/xtream-api.service'; import { TmdbEnrichmentService } from '@iptvnator/services'; -import { createLogger } from '@iptvnator/portal/shared/util'; +import { createLogger } from '@iptvnator/portal/shared/util/logger'; import { withContent, withEpg, diff --git a/libs/portal/xtream/data-access/src/lib/with-favorites.feature.ts b/libs/portal/xtream/data-access/src/lib/with-favorites.feature.ts index 49c3168f9..4bcadd4fe 100644 --- a/libs/portal/xtream/data-access/src/lib/with-favorites.feature.ts +++ b/libs/portal/xtream/data-access/src/lib/with-favorites.feature.ts @@ -5,7 +5,7 @@ import { withMethods, withState, } from '@ngrx/signals'; -import { createLogger } from '@iptvnator/portal/shared/util'; +import { createLogger } from '@iptvnator/portal/shared/util/logger'; import { XTREAM_DATA_SOURCE } from './data-sources/xtream-data-source.interface'; export const withFavorites = function () { diff --git a/libs/portal/xtream/data-access/src/lib/with-recent-items.ts b/libs/portal/xtream/data-access/src/lib/with-recent-items.ts index c420bdce1..7bfa11129 100644 --- a/libs/portal/xtream/data-access/src/lib/with-recent-items.ts +++ b/libs/portal/xtream/data-access/src/lib/with-recent-items.ts @@ -15,7 +15,7 @@ import { Playlist, PortalRecentItem, } from '@iptvnator/shared/interfaces'; -import { createLogger } from '@iptvnator/portal/shared/util'; +import { createLogger } from '@iptvnator/portal/shared/util/logger'; import { XTREAM_DATA_SOURCE } from './data-sources/xtream-data-source.interface'; export interface RecentlyViewedItem extends PortalRecentItem { diff --git a/libs/services/src/index.ts b/libs/services/src/index.ts index 1e3e0d47a..7eaa9165c 100644 --- a/libs/services/src/index.ts +++ b/libs/services/src/index.ts @@ -10,7 +10,6 @@ export * from './lib/playback-position.service'; export * from './lib/playlist-delete-cleanup.token'; export * from './lib/playlist-delete-action.service'; export * from './lib/parental-lock'; -export * from './lib/playlist-backup.service'; export * from './lib/playlist-cross-context-lock'; export * from './lib/playlist-refresh.service'; export * from './lib/playlists.service'; diff --git a/libs/workspace/shell/util/src/lib/navigation/workspace-shell-route.utils.ts b/libs/workspace/shell/util/src/lib/navigation/workspace-shell-route.utils.ts index 3515d722d..d3e923c23 100644 --- a/libs/workspace/shell/util/src/lib/navigation/workspace-shell-route.utils.ts +++ b/libs/workspace/shell/util/src/lib/navigation/workspace-shell-route.utils.ts @@ -1,4 +1,4 @@ -import { +import type { PortalProvider, PortalRailSection, } from '@iptvnator/portal/shared/util'; diff --git a/tsconfig.base.json b/tsconfig.base.json index c0213ec59..7bcd05ff4 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -32,6 +32,12 @@ "@iptvnator/portal/shared/util": [ "libs/portal/shared/util/src/index.ts" ], + "@iptvnator/portal/shared/util/logger": [ + "libs/portal/shared/util/src/lib/logger.ts" + ], + "@iptvnator/portal/shared/util/tokens": [ + "libs/portal/shared/util/src/tokens.ts" + ], "@iptvnator/epg/data-access": ["libs/epg/data-access/src/index.ts"], "@iptvnator/playback/util": ["libs/playback/util/src/index.ts"], "@iptvnator/playlist/shared/ui": [ @@ -112,6 +118,9 @@ "libs/shared/host-health/src/index.ts" ], "@iptvnator/services": ["libs/services/src/index.ts"], + "@iptvnator/services/playlist-backup": [ + "libs/services/src/lib/playlist-backup.service.ts" + ], "@iptvnator/shared/interfaces": [ "libs/shared/interfaces/src/index.ts" ],