plan/react-rewrite #1

Merged
gnezim merged 138 commits from plan/react-rewrite into main 2026-04-15 12:21:16 +03:00
Owner
No description provided.
gnezim added 138 commits 2026-04-15 12:21:04 +03:00
Captures the dual-mode Modern.js architecture, strangler-fig phasing,
parity contracts, and customer-requirement mapping so implementation
plans can be derived per phase without re-litigating architectural
decisions.
16 tasks covering URL corpus extraction, SEO + hreflang + VRT baseline
capture from Angular prod, PrimeNG/SCSS/i18n inventories, and the
customer confirmation checklist. Phase 0 is discovery-only; no
production change. Output is the fixture + inventory set Phase 1
sub-plans consume.
Index of 10 sub-plans (1A-1J) with dependency graph, exported contracts
between sub-plans, shared-file ownership table, spec-coverage matrix,
and global exit gate. Each sub-plan gets its own TDD-granular plan
document written on demand via the writing-plans skill.
Review and planning iterations commit frequently; asking for permission
on each commit added friction without safety benefit. Destructive git
operations still require explicit approval.
Scope: defer 1J parity harnesses to Phase 2 (design against real
feature); split 1A, 1F, 1G into smaller sub-plans; split Phase 0 gate
into hard blockers vs stub-allowed; add A9 for Node 24 availability.

Contracts: fix three-cache model (lru-cache v10 for byte-capped server
LRU), add undici RetryAgent retry config, generic useLiveFlights, CSP
nonce stream transform workaround for React #24883, type-only Logger
extraction to break HostContract plan cycle, error-to-HTTP mapper,
RemoteLoader for consuming other customer remotes, JsonLdRenderer.

Requirements: add runbook, responsive baseline assertions, A4-trigger
log format swap task, rename-pass rework rule, analytics stub sink.
@isaacs/ttlcache has no byte cap (only count). A 100MB hard limit needs
lru-cache v10's maxSize + sizeCalculation. Aligns design spec with
Phase 1 master plan contract revision.
TDD-granular plan with 12 tasks covering Node 24 pinning, TypeScript
strict config, baseline ESLint, Vitest setup, type-only seeds for
HostContract plan-cycle resolution, Zod-validated env reader, frozen
feature/UI barrels, and the A1 rename-pass rework stub.
Vitest 2 pulled Vite 5 + esbuild 0.21 (GHSA-67mh-4wv8-2f99). Bumping
vitest/@vitest/ui to v3 and adding vite ^6 as a direct dev dep forces
peer resolution onto Vite 6 + esbuild 0.25, which also clears the Vite
path-traversal advisory (GHSA-4w7w-66w2-5vf9). pnpm audit is now clean.
Align engines.node with the .nvmrc 24.2.0 pin so npm/pnpm warn on
mismatched local toolchains, move packageManager to the current
pnpm 9.15.3 patch, and ignore pnpm's local store and debug log so
stray artefacts never get committed.
Replaces the FlatCompat shim (which loaded .eslintrc.cjs via @eslint/eslintrc
and emitted deprecation warnings) with a native ESLint 9 flat config. Adds
typescript-eslint meta-package as the flat-config entrypoint and pins
@eslint/js to v9 to satisfy the eslint@9 peer range. Rule set is preserved
verbatim from the Phase 1A-1 plan (Task 4).
- Task 3: dotfile placeholder (src/.typecheck-placeholder.ts) is ignored
  by TypeScript's glob; use non-dotfile name.
- Task 4: replace legacy .eslintrc.cjs with ESLint 9 flat config.
  ESLint 9 requires flat config natively; the legacy format triggers
  deprecation warnings and needs a FlatCompat shim.
- Task 9: env impl cannot unconditionally assign undefined to optional
  fields under exactOptionalPropertyTypes; build base object then
  conditionally assign the three optional URL/header fields.
- Task 12 Step 5: defer coverage check to 1B, which owns the
  @vitest/coverage-v8 dep per the master plan shared-files table.
10 tasks led by a timeboxed Modern.js + MF 2.0 spike that pins
versions and validates the dual-build approach before committing to
it. Covers module-federation.config.ts with 4 feature exposes, React
18 singleton, BUILD_TARGET branching in modern.config.ts, and a
typed loadRemoteModule wrapper around @module-federation/enhanced
runtime for consuming other customer remotes in Phase 2+.
5 tasks: install eslint-plugin-boundaries, configure layered dependency
rules matching design spec §1.2, add no-restricted-imports for OTel
SDK, react-i18next, SignalR SSR, localStorage. Each rule has a
fabricated-violation test asserting it fires.
Fix eslint.config.js: add import/resolver settings so boundaries plugin
can resolve .ts/.tsx imports, and merge no-restricted-imports blocks to
prevent ESLint 9 flat config from overriding earlier rule definitions.
6 tasks: port 9 locale JSONs, TDD resolver with Language type, TDD
createI18nInstance factory with ICU, TDD SSR↔client hydration
serializer, I18nProvider with useTranslation re-export.
7 tasks: TDD error classes, circuit breaker, three cache types
(request-scoped, client TTL, server byte-capped LRU via lru-cache),
ApiClient with retry+timeout, CachedApiClient decorator, provider.
6 tasks: TDD LoggerImpl, ConsoleTransport, JsonLinesHttpTransport
with batching/backpressure/redaction, createRootLogger factory with
env-based transport selection, LoggerProvider React context.
Root layout wraps children with LoggerProvider, ApiClientProvider, and
ErrorBoundary. Locale layout validates lang param against 9 supported
languages and provides a request-scoped I18nProvider.
Reference-counted connection management with grace period,
dynamic import to keep @microsoft/signalr out of SSR bundle,
and singleton sharing via getSharedConnection.
Generic hook wrapping SignalR subscription with SSR guard
(typeof window check). Includes tests for subscribe, data
updates, cleanup, and SSR path.
Remove unused imports, eliminate non-null assertions,
drop invalid eslint-disable comment for missing rule.
Standalone SSR image (Node 24 slim) and remote MF static image (nginx alpine),
coexisting with legacy ASP.NET Dockerfile.
Stub workflow triggered on push to main: build, test, Docker image build.
Registry URLs and deployment targets are placeholders pending customer config.
healthMiddleware returns 200 if upstream was reachable within 60s, 503 otherwise.
Exports a factory function — registration in modern.config.ts is a future step.
registerGracefulShutdown drains in-flight requests for 30s on SIGTERM,
flushes logs, then exits cleanly. Force-exits with code 1 on timeout.
Covers incident decision tree, canary rollout, rollback procedures,
health-check interpretation, log query cookbook, and 6 known-failure
playbooks per master plan requirements.
Use proper type-safe interfaces instead of Node.js http types for the
health handler, and avoid vi.spyOn type issues in shutdown tests by
directly intercepting process.on.
Covers data model types, datetime utilities, dictionary hook,
and flight display components for the online board feature.
Port Angular flight types (ISimpleFlight, IFlightLeg, ITimesSet, etc.)
to minimal React-friendly interfaces. Add formatDuration/formatTime/
formatDate/isDayChange as pure functions. Stub useCityName hook as
passthrough pending customer dictionary API endpoint.
StationDisplay, TimeGroup, FlightStatus, DurationDisplay compose into
FlightCard; FlightList renders a list of cards with skeleton loading.
All components are props-driven with no data fetching.
TDD plan for porting Angular OnlineBoardUrlBuilder/Parser to pure
TypeScript functions covering all 6 URL types (start, flight, departure,
arrival, route, details) with roundtrip and edge case tests.
Pure TypeScript port of Angular OnlineBoardUrlBuilder/Parser covering
all 6 URL types (start, flight, departure, arrival, route, details).
Includes roundtrip parity tests and edge cases for suffixed flights,
variable-length flight numbers, time ranges, and 3-char carriers.
Pure API functions (searchFlights, getFlightDetails, getCalendarDays)
with dependency-injected ApiClient, plus three thin React hooks
(useOnlineBoard, useFlightDetails, useCalendarDays) for search,
details, and calendar pages. 17 TDD tests for API layer covering
URL construction, response mapping, and error handling.
Two thin composition hooks that connect the generic SignalR hook (1E)
to board-specific channels: useLiveBoardSearch for search pages
(SubscribeDate channel) and useLiveFlightDetails for the details page
(Subscribe channel). Both are SSR-safe and client-only.
Covers 6 route pages, 3 feature components, barrel updates, and MF expose.
OnlineBoardSearchPage (shared by all 4 search routes),
OnlineBoardStartPage (search form landing), and
OnlineBoardDetailsPage (flight detail view with legs).
All wired to existing hooks from 2C/2D. 21 tests passing.
Start page, flight/departure/arrival/route search pages,
and flight details page. Each route is thin: parses URL
params, lazy-loads the feature component with Suspense.
- Feature barrel now exports OnlineBoardStartPage, OnlineBoardSearchPage,
  OnlineBoardDetailsPage
- MF expose renders start page via React.lazy + Suspense
- Fix exactOptionalPropertyTypes issues with suffix param
- Remove unused import
SEO builder pure functions for all 6 Online Board route types,
each returning SeoHeadProps with title, description, canonical,
hreflang, OG, and Twitter card. Populated empty EN locale SEO
keys with English translations matching the Russian pattern.
TDD-driven schema.org JSON-LD builders using schema-dts types.
buildFlightJsonLd maps ISimpleFlight to Flight schema with
airports, times, and provider. buildFlightListJsonLd wraps
search results as an ItemList of ListItems.
Each route page now renders <SeoHead> with title, description,
canonical, hreflang, OG, and Twitter card from the SEO builders.
Search pages render <JsonLdRenderer> with ItemList of Flight
schemas. Details page renders Flight JSON-LD. Barrel exports
updated with 2F SEO and JSON-LD functions.
Defines tasks for URL parity harness (table-driven + fast-check fuzz),
SEO parity harness, and Online Board registration against both.
Generic URL parity harness (table-driven + property-based roundtrip)
and SEO parity harness (shape/completeness validation) registered for
Online Board. 170 tests covering all 6 route types with 200-iteration
fast-check fuzz runs ensuring no serialization asymmetry.
Defines scope, test inventory, mocking strategy, and exit criteria
for component-level integration tests of the Online Board feature.
Install @testing-library/jest-dom, add tests/**/*.test.tsx to vitest
include and tsconfig include patterns.
6 test files covering start page, flight search, flight details,
URL round-tripping, error handling, and SEO output verification.
All tests use mocked API and SignalR layers with jsdom environment.
Use ISimpleFlight union type for setupWithFlight parameter to accept
both IDirectFlight and IMultiLegFlight fixtures.
Covers one-way search, round-trip search, multi-flight details (catch-all),
and airport-code-interleaved details format. Reuses online-board's flight
param parser for individual flight segments.
POST schedule/1 for search, GET schedule/details with indexed query
params, GET days/.../schedule/v1 for calendar. Three hooks wrap the
API functions with loading/error state management.
Four Modern.js routes: start page, one-way search, round-trip search,
and catch-all multi-flight details. Components wire hooks for data
fetching and render flight results with calendar navigation.
Tests cover start page, search, and details SEO builders plus
Flight/ItemList JSON-LD schema generation for schedule pages.
Registers schedule URL serializer in parity harness with 18-entry fixture
corpus and fast-check fuzz. 10 URL round-trip integration tests, 6 SEO/
JSON-LD integration tests. Updates barrel and MF expose from stub to real.
Phase 4A: Define IFlightRoute, IMapMarker, IMapPolyline types; implement
searchDestinations and getFlightsMapCalendar API functions with 11 tests;
add useFlightsMapSearch, useFlightsMapCalendar hooks; add FEATURE_FLIGHTS_MAP
env var for feature flag gating.
Phase 4B: MapCanvas.tsx is the sole Leaflet consumer in the codebase.
Renders markers (blue/orange), polylines (solid/dashed) with great-circle
arcs, popups and tooltips. Accepts all data as props (stateless).
ClientOnly.tsx provides SSR safety by deferring render until mount.
Phase 4C: FlightsMapStartPage manages filter state and drives search/calendar
hooks. FlightsMapFilter provides departure/arrival/connections/domestic/
international controls. Route page gates on flightsMap feature flag, rendering
404 when disabled.
Phase 4D: buildFlightsMapSeo generates meta tags, canonical, hreflang, OG
and Twitter Card props. buildFlightsMapJsonLd produces a schema.org WebPage
object for structured data. 10 tests cover both builders.
Populate the feature barrel with all 4A-4D exports. Replace the
FlightsMap MF expose stub with lazy-loaded FlightsMapStartPage,
gated by the flightsMap feature flag.
Write the flights-map master plan covering sub-plans 4A-4D.
Add leaflet + @types/leaflet to support the map canvas component.
Add explicit undefined to optional properties for exactOptionalPropertyTypes
compatibility. Remove unused import. Fix non-null assertions with proper
null guards. Remove invalid eslint-disable comment.
Documents the Angular feature analysis and sub-plan breakdown for
porting popular-requests to React with useSearchHistory hook.
Ports Angular PopularRequestsApiService and IPopularRequest types
to React with pure API function + React hook pattern matching
existing features (online-board, schedule).
PopularRequestsPanel renders up to 4 popular request items in a
grid. MF expose upgraded from stub to real component. Route page
at /{lang}/popular provides standalone access.
Persists search history to localStorage via @/shared/storage with
language-scoped keys (afl_history_{lang}). Supports dedup by URL,
max 10 items, and clear functionality.
Covers all 5 request modes, loading/error states, keyboard
accessibility, and the 4-item display limit.
Remove unused type alias, unused variable, add jsdom environment
directive, and use container.textContent for cross-element text
assertions.
Comprehensive operational procedure for the Angular-to-React traffic
cutover: pre-cutover gates, proxy config templates (nginx/HAProxy),
72-hour traffic ramp schedule, monitoring checklist, rollback procedure,
1-week soak criteria, and Angular decommission steps. Also adds Phase 6
cross-reference sections to the Phase 1 runbook.
Replace the 1A-2 placeholder with a loader redirect matching Angular's
default routing: bare `/` sends users to `/ru/onlineboard`.
Ignore @mf-types.zip, @mf-types/ directory, and .mf/ cache directory
that are generated during MF builds.
gnezim merged commit 1a01b31f91 into main 2026-04-15 12:21:16 +03:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: gnezim/flights_web#1