mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 04:32:32 +00:00
Web upgrade: Next 16 + React 19 + MSAL v4 (#114)
* chore(web): bump to next 16, react 19, msal-browser 4, msal-react 3 react 19.2 aligns the declared dependency with the React the app router has been running all along (Next-vendored 19 canary). msal-react 3.0.29 is the React-19-compatible bridge that only needs msal-browser 4 — deliberately NOT msal v5, whose COOP redirect bridge requires new bridge pages per origin plus app-registration changes (separate project). The react-leaflet peer overrides are gone: react 19 satisfies react-leaflet 5 natively. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(web): react 19 / msal v4 / next 16 code adaptations - msalConfig: allowNativeBroker -> allowPlatformBroker (v4 rename); storeAuthStateInCookie stays (deprecated in v4, removed only in v5) - zero-arg useRef() removed in @types/react 19: GlobalSearch (2x), dashboard autoLoadTimerRef - React.MutableRefObject -> React.RefObject in 5 session/progress hooks (all refs are mutable in 19 types) - layout: data-scroll-behavior="smooth" opt-in so route changes keep jumping instead of animating (Next 16 stopped suppressing CSS smooth-scroll during navigation) - next.config: analyzer comment - Turbopack default build skips the webpack-only analyzer, use --webpack for ANALYZE runs Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore(web): untrack Next-managed next-env.d.ts, generate types in CI Next 16 rewrites next-env.d.ts on every dev/build run and the routes import inside flips between .next/types and .next/dev/types (vercel/ next.js#86001) - official guidance is to gitignore it. CI now runs `next typegen` before tsc so the type stubs exist on a fresh checkout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore(web): migrate lint script to eslint CLI (next lint removed in 16) Minimal flat config from eslint-config-next@16 (core-web-vitals + typescript) with build-output ignores. Lint stays out of CI as before; the 264 pre-existing findings are untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
committed by
GitHub
parent
1593232898
commit
cf45911b69
@@ -69,6 +69,11 @@ jobs:
|
||||
|
||||
- run: npm ci
|
||||
|
||||
# next-env.d.ts + .next type stubs are gitignored (Next-managed since
|
||||
# v16); typegen generates them so tsc sees the same types as a build.
|
||||
- name: Generate Next.js types
|
||||
run: npx next typegen
|
||||
|
||||
- name: Typecheck
|
||||
run: npx tsc --noEmit
|
||||
|
||||
|
||||
@@ -53,6 +53,9 @@ __azurite_db*__.json
|
||||
node_modules/
|
||||
.next/
|
||||
out/
|
||||
# Managed by Next.js since v16 (regenerated by next dev/build/typegen; path
|
||||
# inside flips between .next/types and .next/dev/types) — must not be tracked.
|
||||
next-env.d.ts
|
||||
build/
|
||||
dist/
|
||||
!rules/dist/
|
||||
|
||||
@@ -232,7 +232,7 @@ function HomeContent() {
|
||||
|
||||
// Auto-load ALL remaining sessions when search is active and local results are insufficient.
|
||||
// Uses a 500ms debounce so rapid typing doesn't trigger unnecessary loads.
|
||||
const autoLoadTimerRef = useRef<ReturnType<typeof setTimeout>>();
|
||||
const autoLoadTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
|
||||
useEffect(() => {
|
||||
if (autoLoadTimerRef.current) clearTimeout(autoLoadTimerRef.current);
|
||||
|
||||
|
||||
@@ -113,8 +113,11 @@ export default function RootLayout({
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
// data-scroll-behavior: Next 16 no longer auto-suppresses CSS smooth-scroll
|
||||
// during route navigation; without the opt-in, globals.css's
|
||||
// `scroll-behavior: smooth` would animate every route change to top.
|
||||
return (
|
||||
<html lang="en">
|
||||
<html lang="en" data-scroll-behavior="smooth">
|
||||
<body className={inter.className}>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
|
||||
@@ -25,7 +25,7 @@ interface UseProgressEventsParams {
|
||||
export interface UseProgressEventsReturn {
|
||||
events: EnrollmentEvent[];
|
||||
setEvents: React.Dispatch<React.SetStateAction<EnrollmentEvent[]>>;
|
||||
sessionRef: React.MutableRefObject<Session | null>;
|
||||
sessionRef: React.RefObject<Session | null>;
|
||||
scheduleFetchEvents: (delayMs?: number) => void;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ interface SignalRApi {
|
||||
|
||||
interface UseProgressSignalRParams {
|
||||
session: Session | null;
|
||||
sessionRef: React.MutableRefObject<Session | null>;
|
||||
sessionRef: React.RefObject<Session | null>;
|
||||
signalR: SignalRApi;
|
||||
scheduleFetchEvents: (delayMs?: number) => void;
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@ export interface UseSessionDetailReturn {
|
||||
setLoading: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
fetchSessionDetails: () => Promise<void>;
|
||||
resolveEffectiveTenantId: () => string | null;
|
||||
sessionRef: React.MutableRefObject<Session | null>;
|
||||
sessionIdRef: React.MutableRefObject<string>;
|
||||
sessionRef: React.RefObject<Session | null>;
|
||||
sessionIdRef: React.RefObject<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -63,7 +63,7 @@ interface UseSessionEventsParams {
|
||||
sessionTenantId: string | null;
|
||||
sessionStatus: string | null | undefined;
|
||||
resolveEffectiveTenantId: () => string | null;
|
||||
sessionRef: React.MutableRefObject<Session | null>;
|
||||
sessionRef: React.RefObject<Session | null>;
|
||||
fetchSessionDetails: () => Promise<void>;
|
||||
setLoading: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
isConnected: boolean;
|
||||
|
||||
@@ -20,8 +20,8 @@ interface UseSessionSignalRParams {
|
||||
tenantId: string;
|
||||
sessionTenantIdFromSession: string | undefined;
|
||||
globalAdminMode: boolean;
|
||||
sessionIdRef: React.MutableRefObject<string>;
|
||||
sessionRef: React.MutableRefObject<Session | null>;
|
||||
sessionIdRef: React.RefObject<string>;
|
||||
sessionRef: React.RefObject<Session | null>;
|
||||
resolveEffectiveTenantId: () => string | null;
|
||||
signalR: SignalRApi;
|
||||
scheduleFetchEvents: (delayMs?: number) => void;
|
||||
|
||||
@@ -29,8 +29,8 @@ export default function GlobalSearch() {
|
||||
const mobileInputRef = useRef<HTMLInputElement>(null);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const mobileContainerRef = useRef<HTMLDivElement>(null);
|
||||
const debounceRef = useRef<ReturnType<typeof setTimeout>>();
|
||||
const abortRef = useRef<AbortController>();
|
||||
const debounceRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
|
||||
const abortRef = useRef<AbortController | undefined>(undefined);
|
||||
const router = useRouter();
|
||||
const { getAccessToken } = useAuth();
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Flat ESLint config (Next 16 removed `next lint`; run via `npm run lint`).
|
||||
// Not wired into CI — kept runnable for local/spot use only.
|
||||
import nextVitals from "eslint-config-next/core-web-vitals";
|
||||
import nextTs from "eslint-config-next/typescript";
|
||||
|
||||
const config = [
|
||||
{
|
||||
ignores: [
|
||||
".next/**",
|
||||
"out/**",
|
||||
"build/**",
|
||||
"next-env.d.ts",
|
||||
"node_modules/**",
|
||||
"utils/page-lastmod.generated.ts",
|
||||
],
|
||||
},
|
||||
...nextVitals,
|
||||
...nextTs,
|
||||
];
|
||||
|
||||
export default config;
|
||||
@@ -31,6 +31,8 @@ export const msalConfig: Configuration = {
|
||||
},
|
||||
cache: {
|
||||
cacheLocation: "sessionStorage", // Using sessionStorage for better XSS protection
|
||||
// Deprecated in msal-browser v4 (console warning expected) but still functional;
|
||||
// removed only in v5 — keep until the msal v5 / redirect-bridge migration.
|
||||
storeAuthStateInCookie: true, // Required for Safari ITP compatibility during auth redirects
|
||||
},
|
||||
system: {
|
||||
@@ -59,7 +61,7 @@ export const msalConfig: Configuration = {
|
||||
logLevel: LogLevel.Info,
|
||||
piiLoggingEnabled: false,
|
||||
},
|
||||
allowNativeBroker: false, // Disables WAM Broker
|
||||
allowPlatformBroker: false, // Disables WAM Broker (renamed from allowNativeBroker in msal-browser v4)
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference path="./.next/types/routes.d.ts" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||
@@ -83,8 +83,10 @@ const nextConfig: NextConfig = {
|
||||
: {}),
|
||||
};
|
||||
|
||||
// Run `ANALYZE=1 npm run build` to emit interactive treemaps of the
|
||||
// client/server bundles into .next/analyze/ for bundle-size investigation.
|
||||
// Run `ANALYZE=1 npm run build -- --webpack` to emit interactive treemaps of
|
||||
// the client/server bundles into .next/analyze/ for bundle-size investigation.
|
||||
// (Next 16 builds with Turbopack by default; the analyzer is webpack-only and
|
||||
// no-ops with a warning under Turbopack, so analyzer runs need --webpack.)
|
||||
export default withBundleAnalyzer({ enabled: process.env.ANALYZE === "1" })(
|
||||
nextConfig,
|
||||
);
|
||||
|
||||
+624
-213
File diff suppressed because it is too large
Load Diff
@@ -11,12 +11,12 @@
|
||||
"sync-error-codes": "node scripts/sync-error-codes.js",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
"lint": "eslint .",
|
||||
"test": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/msal-browser": "^3.28.0",
|
||||
"@azure/msal-react": "^2.1.3",
|
||||
"@azure/msal-browser": "^4.30.0",
|
||||
"@azure/msal-react": "^3.0.29",
|
||||
"@microsoft/applicationinsights-web": "^3.4.3",
|
||||
"@microsoft/signalr": "^10.0.0",
|
||||
"@types/leaflet": "^1.9.21",
|
||||
@@ -24,9 +24,9 @@
|
||||
"dagre": "^0.8.5",
|
||||
"fflate": "^0.8.3",
|
||||
"leaflet": "^1.9.4",
|
||||
"next": "^15.5.22",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"next": "^16.2.12",
|
||||
"react": "^19.2.8",
|
||||
"react-dom": "^19.2.8",
|
||||
"react-leaflet": "^5.0.0",
|
||||
"recharts": "^2.15.4"
|
||||
},
|
||||
@@ -34,11 +34,11 @@
|
||||
"@next/bundle-analyzer": "^16.2.12",
|
||||
"@types/dagre": "^0.7.54",
|
||||
"@types/node": "^22.20.1",
|
||||
"@types/react": "^18.2.48",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"autoprefixer": "^10.5.4",
|
||||
"eslint": "^9.39.5",
|
||||
"eslint-config-next": "^15.5.22",
|
||||
"eslint-config-next": "^16.2.12",
|
||||
"postcss": "^8.5.12",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"typescript": "^5.7.3",
|
||||
@@ -50,14 +50,6 @@
|
||||
"overrides": {
|
||||
"postcss": "^8.5.12",
|
||||
"@nevware21/ts-utils": "^0.14.0",
|
||||
"sharp": "^0.35.0",
|
||||
"react-leaflet": {
|
||||
"react": "$react",
|
||||
"react-dom": "$react-dom"
|
||||
},
|
||||
"@react-leaflet/core": {
|
||||
"react": "$react",
|
||||
"react-dom": "$react-dom"
|
||||
}
|
||||
"sharp": "^0.35.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"jsx": "react-jsx",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
@@ -32,7 +32,8 @@
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts"
|
||||
".next/types/**/*.ts",
|
||||
".next/dev/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
* Run: node scripts/generate-lastmod.js
|
||||
*/
|
||||
export const PAGE_LASTMOD: Record<string, string> = {
|
||||
"/": "2026-07-30T16:37:13+02:00",
|
||||
"/about": "2026-07-30T18:48:00+02:00",
|
||||
"/": "2026-07-30T22:21:18+02:00",
|
||||
"/about": "2026-07-30T22:21:18+02:00",
|
||||
"/roadmap": "2026-07-06T18:31:00+02:00",
|
||||
"/changelog": "2026-07-06T18:12:31+02:00",
|
||||
"/privacy": "2026-07-30T18:48:00+02:00",
|
||||
"/terms": "2026-07-30T18:48:00+02:00",
|
||||
"/privacy": "2026-07-30T22:21:18+02:00",
|
||||
"/terms": "2026-07-30T22:21:18+02:00",
|
||||
"/docs": "2026-07-06T18:12:31+02:00",
|
||||
"/docs/private-preview": "2026-07-06T18:12:31+02:00",
|
||||
"/docs/overview": "2026-07-06T18:12:31+02:00",
|
||||
|
||||
Reference in New Issue
Block a user