Files
iptvnator/package.json
4grayandClaude Fable 5.1 e6ef8cdd54 perf(web): take Angular Material off the startup path (#1931)
Takes Angular Material off the renderer's startup path: renderer.initialBytes
1,596,201 -> 1,344,067 bytes (-252,134, 15.8%) at the branch point; merged with
master, where #1928 lands the form-field defaults per component, the branch
measures 1,345,807 (-188,797, 12.3% against master's baseline). The bundler
keeps each module in one chunk, so one eager import of any export carries the
module's whole code; each item removes the last eager importer of one Material
module.

- EPG progress and update panels: eager host + `@defer (when visible)` view
  with an `@error` notice; the startup spinner is static markup copied from
  mat-spinner.
- LazyMatDialog: the confirm dialog service, player service, parental lock
  prompt and shell actions resolve MatDialog on first use.
- The theme emits tokens for the 21 imported components only, through a
  `$material-components` list and meta.apply; tools/nx/check-material-theme-scope.mjs
  (CI) keeps it in step with the imports in both directions.
- No provideAnimations(): Material 22 animates with CSS and reads
  prefers-reduced-motion itself; apps/electron-backend-e2e/src/material-motion.e2e.ts
  proves dialogs, selects, menus, snack-bars and tooltips animate in and out and
  stop under reduced motion. Its renderer had deferred every DOM removal to the
  end of the tick, so the catalog list now tracks the grid offset from scroll
  events and the player settings panel decides "focus was inside" in a
  microtask, both with specs that detach the view first.
- The snack-bar stays, and with it button, the icon-button chunk and the CDK
  overlay (about 190 KB): root services inject it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-14 00:08:58 +02:00

343 lines
18 KiB
JSON

{
"name": "iptvnator",
"version": "0.25.0",
"engines": {
"node": "^22.22.3 || ^24.15.0"
},
"license": "MIT",
"description": "IPTV player application.",
"homepage": "https://github.com/4gray/iptvnator",
"author": {
"name": "4gray",
"email": "fourgray@proton.me"
},
"keywords": [
"angular",
"electron",
"typescript",
"m3u",
"m3u8",
"player",
"iptv",
"video",
"tv"
],
"scripts": {
"postinstall": "electron-builder install-app-deps",
"build:frontend": "nx build web",
"build:frontend:pwa": "nx build web --configuration=pwa",
"build:backend": "nx build electron-backend --configuration=production",
"serve:frontend": "nx serve web --no-tui",
"serve:frontend:pwa": "nx serve web --configuration=pwa --no-tui",
"serve:backend": "nx serve electron-backend",
"serve:marketing-demo": "nx run-many --target=serve --projects=xtream-mock-server,electron-backend --parallel=2",
"serve:marketing-demo:web": "nx run-many --target=serve --projects=xtream-mock-server,web --parallel=2",
"test:frontend": "nx test web",
"test:backend": "nx test electron-backend",
"test:unit:all": "nx run-many --target=test --all --parallel=3",
"test:unit:ci": "nx run-many --target=test --all --parallel=3 --output-style=static",
"deps:nx:test": "node --test tools/dependencies/check-nx-version-sync.test.mjs",
"deps:nx:check": "node tools/dependencies/check-nx-version-sync.mjs",
"deps:nx:validate": "pnpm run deps:nx:test && pnpm run deps:nx:check",
"deps:vite:test": "node --test tools/dependencies/vite-transform-filter.test.mjs",
"deps:electron-builder:test": "node --test tools/dependencies/app-builder-lib-keychain-password.test.mjs",
"styles:font-weights:test": "node --test tools/nx/check-font-weights.test.mjs",
"styles:font-weights:check": "node tools/nx/check-font-weights.mjs",
"styles:font-weights:validate": "pnpm run styles:font-weights:test && pnpm run styles:font-weights:check",
"styles:inputs:test": "node --test tools/nx/check-stylesheet-inputs.test.mjs",
"styles:inputs:check": "node tools/nx/check-stylesheet-inputs.mjs",
"styles:inputs:validate": "pnpm run styles:inputs:test && pnpm run styles:inputs:check",
"styles:material-tokens:test": "node --test tools/nx/check-material-token-overrides.test.mjs",
"styles:material-tokens:check": "node tools/nx/check-material-token-overrides.mjs",
"styles:material-tokens:validate": "pnpm run styles:material-tokens:test && pnpm run styles:material-tokens:check",
"styles:focus-visible:test": "node --test tools/nx/check-focus-visible.test.mjs tools/nx/check-focus-ring-colour.test.mjs",
"styles:focus-visible:check": "node tools/nx/check-focus-visible.mjs && node tools/nx/check-focus-ring-colour.mjs",
"styles:focus-visible:validate": "pnpm run styles:focus-visible:test && pnpm run styles:focus-visible:check",
"styles:icon-ligatures:test": "node --test tools/nx/check-icon-ligatures.test.mjs",
"styles:icon-ligatures:check": "node tools/nx/check-icon-ligatures.mjs",
"styles:icon-ligatures:validate": "pnpm run styles:icon-ligatures:test && pnpm run styles:icon-ligatures:check",
"styles:theme-references:test": "node --test tools/nx/check-theme-references.test.mjs",
"styles:theme-references:check": "node tools/nx/check-theme-references.mjs",
"styles:theme-references:validate": "pnpm run styles:theme-references:test && pnpm run styles:theme-references:check",
"a11y:icon-buttons:test": "node --test tools/nx/check-icon-button-names.test.mjs",
"a11y:icon-buttons:check": "node tools/nx/check-icon-button-names.mjs",
"a11y:icon-buttons:validate": "pnpm run a11y:icon-buttons:test && pnpm run a11y:icon-buttons:check",
"ui:form-field-defaults:test": "node --test tools/nx/check-form-field-defaults.test.mjs",
"ui:form-field-defaults:check": "node tools/nx/check-form-field-defaults.mjs",
"ui:form-field-defaults:validate": "pnpm run ui:form-field-defaults:test && pnpm run ui:form-field-defaults:check",
"styles:material-theme-scope:test": "node --test tools/nx/check-material-theme-scope.test.mjs",
"styles:material-theme-scope:check": "node tools/nx/check-material-theme-scope.mjs",
"styles:material-theme-scope:validate": "pnpm run styles:material-theme-scope:test && pnpm run styles:material-theme-scope:check",
"e2e:task-graphs:test": "node --test tools/nx/check-e2e-task-graphs.test.mjs",
"e2e:task-graphs:check": "node tools/nx/check-e2e-task-graphs.mjs",
"e2e:task-graphs:validate": "pnpm run e2e:task-graphs:test && pnpm run e2e:task-graphs:check",
"coverage:tools:test": "node --test tools/coverage/coverage-integrity.test.mjs tools/coverage/e2e-shard-reports.test.mjs tools/coverage/coverage-run-pool.test.mjs tools/coverage/unit-coverage-scope.test.mjs",
"coverage:unit:ci": "node tools/coverage/run-tier-a-coverage.mjs",
"coverage:merge": "node tools/coverage/merge-coverage.mjs",
"coverage:health": "node tools/coverage/coverage-health.mjs",
"coverage:policy:check": "node tools/coverage/check-coverage-policy.mjs",
"coverage:ci": "pnpm run coverage:tools:test && pnpm run coverage:policy:check && pnpm run coverage:unit:ci && pnpm run coverage:merge && node tools/coverage/coverage-health.mjs --require-report",
"coverage:e2e:summary": "node tools/coverage/e2e-semantic-summary.mjs",
"coverage:e2e:v8:web": "node tools/coverage/e2e-v8-web.mjs",
"typecheck:web": "tsc -p apps/web/tsconfig.app.json --noEmit",
"typecheck:backend": "tsc -p apps/electron-backend/tsconfig.app.json --noEmit",
"typecheck:ci": "pnpm run typecheck:web && pnpm run typecheck:backend",
"typecheck:spec": "node tools/typecheck/spec-typecheck.mjs",
"typecheck:spec:test": "node --test tools/typecheck/spec-typecheck.test.mjs",
"verify:package-layout": "node tools/packaging/verify-electron-package-layout.mjs",
"embedded-mpv:build-native:homebrew": "IPTVNATOR_EMBEDDED_MPV_ALLOW_HOMEBREW=1 nx run electron-backend:build-embedded-mpv",
"embedded-mpv:build-runtime": "node tools/embedded-mpv/build-macos-runtime.mjs",
"embedded-mpv:build-runtime:linux": "node tools/embedded-mpv/build-linux-runtime.mjs",
"embedded-mpv:stage-runtime": "node tools/embedded-mpv/stage-runtime.mjs",
"embedded-mpv:stage-runtime:macos": "node tools/embedded-mpv/stage-macos-runtime.mjs",
"embedded-mpv:stage-runtime:windows-archive": "node tools/embedded-mpv/stage-windows-runtime-archive.mjs",
"embedded-mpv:windows-runtime-pin:check": "node tools/embedded-mpv/windows-runtime-pin.mjs",
"embedded-mpv:windows-runtime-pin:refresh": "node tools/embedded-mpv/update-windows-runtime-pin.mjs",
"serve:backend:embedded-mpv": "pnpm embedded-mpv:build-native:homebrew && IPTVNATOR_EMBEDDED_MPV_ALLOW_HOMEBREW=1 IPTVNATOR_ENABLE_EMBEDDED_MPV_EXPERIMENT=1 pnpm serve:backend",
"package:app": "nx run electron-backend:make --prepackageOnly",
"make:app": "nx run electron-backend:make",
"smoke:packaged": "node tools/testing/launch-packaged-electron.mjs",
"serve:website": "nx serve website",
"build:website": "nx build website",
"i18n:check": "node tools/i18n/check-drift.mjs && node tools/i18n/check-usage.mjs",
"i18n:test": "node --test tools/i18n/check-drift.test.mjs tools/i18n/check-usage.test.mjs tools/i18n/check-duplicates.test.mjs",
"i18n:usage": "node tools/i18n/check-usage.mjs",
"i18n:duplicates": "node tools/i18n/check-duplicates.mjs",
"i18n:validate": "pnpm run i18n:test && pnpm run i18n:check",
"i18n:baseline:update": "node tools/i18n/check-drift.mjs --update-baseline",
"perf:initial-bytes": "node tools/performance/measure-initial-bytes.mjs",
"perf:initial-bytes:check": "node tools/performance/measure-initial-bytes.mjs --summary dist/performance/initial-bytes.summary.json && node tools/performance/check-journey-ratchet.mjs --summary dist/performance/initial-bytes.summary.json --only launch/renderer.initialBytes",
"perf:journeys": "nx run electron-backend-e2e:journeys",
"perf:compositing": "nx run electron-backend-e2e:compositing-report",
"perf:ratchet:check": "node tools/performance/check-journey-ratchet.mjs --summary dist/performance/journey-summary.json",
"perf:tools:test": "node --test tools/performance/measure-initial-bytes.test.mjs tools/performance/check-journey-ratchet.test.mjs tools/performance/check-baseline-direction.test.mjs tools/performance/tighten-baselines.test.mjs",
"agents:validate": "node tools/skills/validate-agent-guidance.mjs",
"skills:validate": "node tools/skills/validate-repository-skills.mjs",
"release:artwork:dry-run": "tsx --tsconfig tsconfig.base.json tools/release/generate-marketing-artwork.ts --dry-run",
"release:artwork:manifest": "tsx --tsconfig tsconfig.base.json tools/release/generate-marketing-artwork.ts --manifest",
"release:artwork:generate": "tsx --tsconfig tsconfig.base.json tools/release/generate-marketing-artwork.ts --generate",
"release:artwork:validate": "tsx --tsconfig tsconfig.base.json tools/release/generate-marketing-artwork.ts --validate",
"release:notes:validate": "node tools/release/build-release-notes.mjs --validate",
"release:notes:github": "node tools/release/build-release-notes.mjs --format github",
"release:notes:changelog": "node tools/release/build-release-notes.mjs --format changelog",
"release:notes:blog": "node tools/release/build-release-notes.mjs --format blog",
"release:notes:telegram": "node tools/release/build-release-notes.mjs --format telegram",
"release:notes:reddit": "node tools/release/build-release-notes.mjs --format reddit",
"release:verify:draft": "node tools/release/verify-draft-release.mjs",
"release:cards:dry-run": "node tools/release/generate-highlight-cards.mjs --dry-run",
"release:cards:generate": "node tools/release/generate-highlight-cards.mjs --generate",
"release:screenshots": "tsx tools/release/capture-release-screenshots.ts",
"lint": "nx run-many --target=lint --all",
"build": "nx build electron-backend"
},
"private": true,
"packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319",
"dependencies": {
"@angular/animations": "22.1.6",
"@angular/cdk": "22.1.6",
"@angular/common": "22.1.6",
"@angular/compiler": "22.1.6",
"@angular/core": "22.1.6",
"@angular/forms": "22.1.6",
"@angular/material": "22.1.6",
"@angular/platform-browser": "22.1.6",
"@angular/platform-browser-dynamic": "22.1.6",
"@angular/router": "22.1.6",
"@ngrx/effects": "22.0.1",
"@ngrx/entity": "22.0.1",
"@ngrx/router-store": "22.0.1",
"@ngrx/signals": "22.0.1",
"@ngrx/store": "22.0.1",
"@ngrx/store-devtools": "22.0.1",
"@ngx-pwa/local-storage": "22.0.0",
"@yangkghjh/videojs-aspect-ratio-panel": "0.0.1",
"angularx-qrcode": "22.0.1",
"artplayer": "5.4.0",
"axios": "1.20.0",
"better-sqlite3": "13.0.3",
"date-fns": "4.4.0",
"drizzle-orm": "0.45.2",
"electron-conf": "1.3.0",
"electron-updater": "6.8.9",
"epg-parser": "^0.5.0",
"hls.js": "1.7.1",
"iptv-playlist-parser": "github:4gray/iptv-playlist-parser#v0.15.2-iptvnator.2",
"marked": "18.0.11",
"mpegts.js": "1.8.2",
"ms": "2.1.3",
"ngx-indexed-db": "22.0.0",
"ngx-skeleton-loader": "11.3.0",
"proxy-from-env": "2.1.0",
"rxjs": "7.8.2",
"saxes": "6.0.0",
"shaka-player": "5.2.12",
"shell-path": "3.1.0",
"video.js": "8.24.0",
"videojs-contrib-quality-levels": "4.1.0",
"videojs-quality-selector-hls": "1.1.1",
"zone.js": "0.16.3"
},
"devDependencies": {
"@angular-devkit/core": "22.1.8",
"@angular-devkit/schematics": "22.1.8",
"@angular-eslint/builder": "22.5.0",
"@angular-eslint/eslint-plugin": "22.5.0",
"@angular-eslint/eslint-plugin-template": "22.5.0",
"@angular-eslint/schematics": "22.5.0",
"@angular-eslint/template-parser": "22.5.0",
"@angular/build": "22.1.8",
"@angular/cli": "22.1.8",
"@angular/common": "22.1.6",
"@angular/compiler": "22.1.6",
"@angular/compiler-cli": "22.1.6",
"@angular/core": "22.1.6",
"@angular/forms": "22.1.6",
"@angular/language-service": "22.1.6",
"@angular/platform-browser": "22.1.6",
"@angular/platform-browser-dynamic": "22.1.6",
"@angular/router": "22.1.6",
"@angular/service-worker": "22.1.6",
"@astrojs/mdx": "7.0.7",
"@astrojs/sitemap": "3.7.4",
"@babel/core": "7.29.7",
"@electron/asar": "3.4.1",
"@eslint/eslintrc": "3.3.7",
"@eslint/js": "^9.38.0",
"@faker-js/faker": "10.6.0",
"@fontsource-variable/bricolage-grotesque": "5.3.0",
"@fontsource/dm-sans": "5.3.0",
"@fontsource/ibm-plex-mono": "5.3.0",
"@fontsource/jetbrains-mono": "5.3.0",
"@fontsource/roboto": "5.3.0",
"@ngrx/eslint-plugin": "22.0.1",
"@ngx-translate/core": "16.0.4",
"@ngx-translate/http-loader": "16.0.1",
"@nx/angular": "23.2.1",
"@nx/devkit": "23.2.1",
"@nx/esbuild": "23.2.1",
"@nx/eslint": "23.2.1",
"@nx/eslint-plugin": "23.2.1",
"@nx/jest": "23.2.1",
"@nx/js": "23.2.1",
"@nx/playwright": "23.2.1",
"@nx/web": "23.2.1",
"@nx/workspace": "23.2.1",
"@playwright/test": "^1.62.1",
"@schematics/angular": "22.1.8",
"@swc-node/register": "1.12.1",
"@swc/core": "1.16.1",
"@swc/helpers": "0.5.23",
"@tailwindcss/typography": "0.5.20",
"@types/better-sqlite3": "^9.6.0",
"@types/cors": "2.8.19",
"@types/express": "5.0.6",
"@types/jest": "^30.0.0",
"@types/jsdom": "21.1.7",
"@types/mocha": "9.0.0",
"@types/node": "20.19.9",
"@types/proxy-from-env": "1.0.4",
"@types/video.js": "7.3.58",
"@typescript-eslint/eslint-plugin": "^8.69.0",
"@typescript-eslint/parser": "^8.69.0",
"@typescript-eslint/utils": "^8.69.0",
"angular-eslint": "22.5.0",
"astro": "7.2.10",
"autoprefixer": "10.5.4",
"axe-core": "4.13.0",
"cookie": "2.0.1",
"cors": "2.8.6",
"drizzle-kit": "0.31.10",
"electron": "^43.3.0",
"electron-builder": "^26.15.7",
"electron-playwright-helpers": "1.8.2",
"esbuild": "0.28.2",
"eslint": "^9.8.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-import": "2.32.0",
"eslint-plugin-playwright": "^1.6.2",
"express": "5.2.1",
"github-slugger": "2.0.0",
"globals": "15.9.0",
"html-escaper": "3.0.3",
"istanbul-lib-coverage": "3.2.2",
"istanbul-lib-report": "3.0.1",
"istanbul-reports": "3.2.0",
"jest": "^30.5.1",
"jest-environment-jsdom": "^30.5.1",
"jest-environment-node": "^30.5.1",
"jest-preset-angular": "17.0.0",
"jest-util": "^30.5.1",
"jsdom": "26.1.0",
"jsonc-eslint-parser": "^2.1.0",
"material-design-icons-iconfont": "6.7.0",
"mrmime": "2.0.1",
"ng-mocks": "14.17.6",
"node-gyp": "12.4.0",
"nx": "23.2.1",
"nx-electron": "22.0.0",
"parse-srcset": "1.0.2",
"parse5": "8.0.1",
"prettier": "^3.9.6",
"sharp": "0.35.5",
"tailwindcss": "^3.4.19",
"ts-jest": "^29.4.12",
"ts-node": "10.9.2",
"tslib": "^2.8.1",
"tsx": "4.23.13",
"typescript": "6.0.3",
"typescript-eslint": "^8.69.0",
"yaml": "2.9.0",
"zod": "4.5.4"
},
"pnpm": {
"overrides": {
"@esbuild-kit/core-utils>esbuild": "0.25.12",
"@hono/node-server@1.19.9": "1.19.17",
"@humanfs/node@0.16.7": "0.16.8",
"@xmldom/xmldom@0.8.11": "0.8.15",
"ajv@6.12.6": "6.14.0",
"ajv@8.17.1": "8.20.0",
"brace-expansion@1.1.12": "1.1.18",
"browserslist@4.28.1": "4.28.8",
"defu@6.1.4": "6.1.6",
"devalue@5.6.2": "5.6.4",
"express-rate-limit@8.2.1": "8.3.0",
"fast-uri@3.1.0": "3.1.6",
"flatted@3.3.3": "3.4.2",
"follow-redirects@1.15.11": "1.16.0",
"form-data@4.0.5": "4.0.6",
"h3@1.15.5": "1.15.10",
"hono@4.12.0": "4.13.5",
"immutable@5.1.4": "5.1.9",
"ip-address@10.1.0": "10.5.0",
"js-yaml@4.1.1": "4.3.2",
"js-yaml@4.3.0": "4.3.2",
"jsdom>ws": "8.21.3",
"lodash-es@4.17.22": "4.18.1",
"minimatch@3.1.2": "3.1.5",
"node-forge@1.3.3": "1.4.0",
"path-to-regexp@0.1.12": "0.1.13",
"picomatch@2.3.1": "2.3.2",
"picomatch@4.0.3": "4.0.7",
"postcss-selector-parser@6.1.2": "6.1.4",
"postcss@8.5.6": "8.5.26",
"qs@6.14.1": "6.15.3",
"rollup@4.52.3": "4.59.0",
"serialize-javascript@6.0.2": "7.1.0",
"smol-toml@1.6.0": "1.7.1",
"smol-toml@1.6.1": "1.7.1",
"svgo@3.3.2": "3.3.3",
"svgo@4.0.0": "4.1.0",
"svgo@4.0.2": "4.1.0",
"undici@7.28.0": "7.29.0",
"uuid@8.3.2": "11.1.1",
"yaml@1.10.2": "1.10.3"
},
"patchedDependencies": {
"nx-electron@22.0.0": "patches/nx-electron@22.0.0.patch",
"app-builder-lib@26.15.7": "patches/app-builder-lib@26.15.7.patch",
"vite@8.1.5": "patches/vite@8.1.5.patch"
}
}
}