Modernize stack - #196
Open
paranoidi wants to merge 22 commits into
Open
Conversation
- Node 12.x (EOL) → 20.x in ci.yml and release.yml - actions/checkout@v2 → @v4 throughout - actions/setup-node@v1 → @v4 with built-in yarn cache (drops separate cache step) - codecov/codecov-action@v1 → @v4 - deliverybot/deployment-status@v1 (archived) → chrnorm/deployment-status@v2 - actions/github-script@0.9.0 → @v7; Octokit API: github.repos → github.rest.repos
- typescript ^4.1 → ^5.5 (installed 5.9.3) - prettier ^2.2 → ^3.0 (installed 3.9.1) - Remove parser: 'typescript' from prettier.config.js (removed in Prettier 3) - Add allowSyntheticDefaultImports: true to tsconfig.json (required explicitly in TS5) - Fix fetch-mock imports: default import → import * as (export= modules need import* in TS5) - Fix duplicate [TraktFields.ID] key in movies.ts (genuine bug, now caught by TS5) - Fix Autocomplete generic constraint: boolean → boolean | undefined - Fix PaperWrapper styled type to accept elevation prop (emotion v10 + TS5 union narrowing) - Reformat all source files with Prettier 3 (trailing-comma, arrow-parens semantics)
Combined because Router v5 types are incompatible with @types/react@18. - React 18: createRoot, explicit children props on FC, @types/react pinned to ~18.2 - Formik bumped to 2.4.9 for React 18 type compat - react-hot-loader + @hot-loader/react-dom removed from 10 files + webpack config - Router v6: Switch→Routes, component→element, useHistory→useNavigate, useRouteMatch→useHref, Redirect→Navigate, PrivateRoute rewritten - Emotion v10 and react-virtualized/react-monaco-editor styled components cast to FC<any> as interim bridge; will be replaced in Phase 5 and Phase 7
- Upgrade jest to ^29, ts-jest to ^29, @testing-library/react to ^14,
@testing-library/jest-dom to ^6, @testing-library/user-event to ^14
- Replace faker with @faker-js/faker in 3 fixture files
- Remove enzyme, enzyme-adapter-react-16, enzyme-to-json, react-hot-loader/babel
- Rewrite jest.config.js: ts-jest transform format, jest-extended/all,
testEnvironmentOptions, updated serializers and setupFilesAfterEnv
- Update tsconfig.jest.json: module commonjs for fetch-mock default import;
add tsconfig.json spec exclude to prevent TS1192 errors
- Fix all 34 spec files: fetchMock default import (prototype chain fix)
- Rewrite 5 Enzyme spec files to RTL (StatusBar, ErrorStatus, InfoStatus,
LoadingBar, AppBar)
- Update 9 snapshots to Jest 29 format (Object { -> {)
- Fix LoginCard.spec: form role + async login state assertion
- Fix Routes.spec: remove double MemoryRouter, fix navigate effect dependency
(RR v6 useNavigate is unstable across locations; use [] not [navigate])
- Fix Config.spec: correct waitFor URL and async button queries
- Add src/types/testing.d.ts for jest-dom + jest-extended type references
Dependencies:
- Remove: @material-ui/{core,icons,lab,styles}, jss, jss-preset-default,
@emotion/core, emotion-theming, @emotion/babel-preset-css-prop, jest-emotion,
eslint-plugin-emotion
- Add: @mui/material@^5, @mui/icons-material@^5, @emotion/react@^11,
@emotion/styled@^11, @emotion/babel-plugin, @emotion/jest, @emotion/eslint-plugin
Import renames (92 + 48 files via sed):
- @material-ui/core → @mui/material
- @material-ui/icons → @mui/icons-material
- @material-ui/lab → @mui/material (Alert, Skeleton, SpeedDial, Autocomplete graduated to core)
- @emotion/core → @emotion/react
- emotion-theming → @emotion/react
Theme (src/core/theme/index.ts):
- createMuiTheme → createTheme (alias import), PaletteType → PaletteMode
- palette.type → palette.mode, props → components.defaultProps
- Remove palette.text.hint/icon (not in v5 types)
ThemeProvider (src/core/theme/ThemeProvider.tsx):
- Collapse MuiThemeProvider + EmotionThemeProvider → single MuiThemeProvider
(MUI v5 auto-feeds theme into emotion context)
Emotion theme typing (src/types/emotion.d.ts, NEW):
- Module augmentation: @emotion/react Theme extends MuiTheme
MUI Mixin types (src/types/theme.d.ts):
- Augment @mui/material/styles (not @material-ui/core/styles/createMixins)
styled (src/common/styles.tsx):
- Remove CreateStyled<Theme> cast; emotion v11 picks up theme via augmentation
- Remove as unknown as React.FC<...> casts (not needed in v11)
Autocomplete (src/common/inputs/formik/Autocomplete.tsx):
- Remove removed UseAutocompleteSingleProps/UseAutocompleteMultipleProps
- Use AutocompleteProps<T, Multiple, false, false> generic directly
Palette: editor.tsx, LogTable.tsx: palette.type → palette.mode
Build: babel.config.js: @emotion/babel-preset-css-prop → @emotion/babel-plugin
Tests: jest.config.js: jest-emotion → @emotion/jest/serializer
ESLint: .eslintrc.js: emotion → @emotion plugin + rule prefix rename
Spec fixes:
- FilterNav.spec: Convert react-test-renderer → RTL (MUI v5 Select calls focus()
in effects, crashes without real DOM)
- Operations.spec: Remove { selector: 'span' } (MUI v5 removed inner span in Button)
- 8 snapshots updated (serializer format changed)
Dependencies removed: - react-monaco-editor, worker-loader, url-loader, file-loader, ts-loader, @babel/node - webpack@4, webpack-cli@3, webpack-dev-server@3 - html-webpack-plugin@3, mini-css-extract-plugin@0.9, css-loader@3, style-loader@1 - fork-ts-checker-webpack-plugin@4, webpack-bundle-analyzer@3 - monaco-editor@0.19, monaco-yaml@2 Dependencies added: - monaco-editor@^0.50, monaco-yaml@^5, @monaco-editor/react@^4.6 - webpack@^5, webpack-cli@^5, webpack-dev-server@^5 - html-webpack-plugin@^5, mini-css-extract-plugin@^2, css-loader@^7, style-loader@^4 - fork-ts-checker-webpack-plugin@^9, webpack-bundle-analyzer@^4 - monaco-editor-webpack-plugin, @pmmmwh/react-refresh-webpack-plugin, react-refresh webpack.config.js (full rewrite): - ts-loader removed; babel-loader handles all .tsx? (already configured) - url-loader/file-loader → webpack 5 asset modules (asset/resource, asset) - worker-loader removed; monaco-editor-webpack-plugin handles workers - HotModuleReplacementPlugin removed; ReactRefreshWebpackPlugin replaces it - MiniCssExtractPlugin: remove deprecated allChunks option - ForkTsCheckerWebpackPlugin v9: tsconfig → typescript.configFile - devServer config inlined (historyApiFallback, hot, proxy) - MonacoEditorWebpackPlugin added (languages: ['yaml']) server.js: deleted (replaced by webpack devServer config) package.json: start/build scripts no longer use babel-node or server.js src/plugins/config/monaco.ts: deleted (v0.19-era manual ESM feature import) src/plugins/config/Editor.tsx: rewritten - Remove react-monaco-editor, worker-loader imports, manual MonacoEnvironment - Replace with @monaco-editor/react + useMonaco hook - monaco-yaml v5: yaml?.yamlDefaults.setDiagnosticsOptions → configureMonacoYaml(monaco, ...) with proper IDisposable cleanup src/plugins/config/types.ts: remove hand-rolled YamlLanguage/LanguageServiceDefaults (monaco-yaml v5 exports its own types) src/types/webpack.d.ts: remove worker-loader! module declaration Jest mocks (monaco-editor is ESM-only, ts-jest can't transform node_modules): - jest.config.js: moduleNameMapper adds monaco-editor/*, monaco-yaml, @monaco-editor/react - src/__mocks__/monaco-editor.ts: stub editor.defineTheme + languages - src/__mocks__/monacoYaml.ts: stub configureMonacoYaml - src/__mocks__/monacoEditor.tsx: stub MonacoEditor component + useMonaco - setupFiles.ts: remove manual jest.mock() (superseded by moduleNameMapper)
- Replace .eslintrc.js with eslint.config.js (flat config format) - Upgrade to ESLint 9, typescript-eslint v8, eslint-plugin-react v7.37 - Add jest/testing-library/jest-dom plugins in flat config - Migrate .eslintignore patterns to ignores array - Add .nvmrc pinning Node 20 (matches CI) - Add Taskfile.yml with setup/dev/build/test/lint/typecheck/clean tasks - Fix unused catch binding in fetch.ts (bare catch clause)
- Taskfile: load .env so SERVER var is picked up by task dev - .env.example: document SERVER for pointing dev server at a remote FlexGet host
task's default /bin/sh doesn't inherit fish's PATH, so yarn wasn't found. Switch all node tasks to fish -c which loads fish config/PATH. Setup task: bash -c for nvm (fish doesn't source nvm.sh natively) with a clear error if nvm install fails due to network issues.
Replace fish -c with bash -c sourcing nvm.sh — works for any shell (bash, zsh, fish, etc). After task setup installs the nvm-managed node, nvm use --silent activates it before each yarn command.
Drop all nvm-sourcing from tasks — that's the developer's environment concern. Instead: setup installs yarn via npm (whichever npm is active), then yarn install. All other tasks just call yarn, which works once the developer has run 'nvm use' in their shell. - task setup: precondition checks npm in PATH; installs yarn + deps - All tasks: plain yarn commands, no shell-specific wiring - package.json: add packageManager field for corepack compatibility
Babel: - Add api.cache(true) to babel.config.js (required by newer @babel/core) - Add @babel/preset-typescript to main presets (was only in release env) - Switch @babel/preset-react to automatic runtime with @emotion/react source TypeScript: - tsconfig.json: jsx react-jsx + jsxImportSource @emotion/react (enables css prop types on all JSX elements, replaces classic import React) - Remove now-unused `import React` default from 75 files - const enum → enum across 37 declarations (Babel cannot inline const enums) MUI v5 API: - theme.spacing() returns "8px" (string) in v5; wrap with parseFloat() wherever passed to pxToRem() — 50+ call sites via sed - Skeleton variant="rect" → "rectangular" - TablePagination: onChangePage → onPageChange, onChangeRowsPerPage → onRowsPerPageChange - Tabs scrollButtons="on" → scrollButtons (boolean) - Tab: removed fullWidth and wrapped props (use Tabs variant="fullWidth") Webpack: - Add fullySpecified: false rule for .mjs files (@babel/runtime ESM helpers) Monaco: - Remove obsolete monaco-yaml/esm/monaco.contribution pre-import (v5 API) - Editor: filter schemas without fileMatch before passing to configureMonacoYaml
Without this, the remote server sees Host: localhost:8080 and may reject the request. changeOrigin rewrites Host to match the proxy target.
…eact webpack entry lacked core-js/regenerator-runtime imports required by babel's useBuiltIns:'entry' setting, causing "regeneratorRuntime is not defined" at runtime. yarn.lock also had @babel/preset-react pinned to 7.8.3, which predates the 'automatic' JSX runtime option and silently fell back to the classic transform, causing "React is not defined".
@monaco-editor/react's loader defaults to fetching monaco-editor from jsdelivr CDN, bypassing the locally webpack-bundled instance entirely. That CDN copy's MonacoEnvironment has no yaml worker registered, so monaco-yaml's validation/hover/folding RPCs fail shortly after the editor's initial paint. Point the loader at the local monaco-editor instance so it picks up the yaml worker registered via MonacoEditorWebpackPlugin's customLanguages option (per monaco-yaml's own docs for this plugin), which was otherwise unused.
webpack-dev-server's compress:true (the default) puts the compression middleware ahead of the /api proxy, which buffers response bytes before flushing. That breaks the chunked JSON stream oboe uses for the live server log, so it never sees a first byte and the log page hangs forever instead of connecting.
PaperWrapper zeroed out top padding at desktop widths (only consumer is the Log page), so the header row sat flush against the top edge. The filter icon and menu icon were also visually off-center against the input box because align-items: center centered them against the TextField's full height including its permanent helper text below.
History opts out of the layout's global padding via NoPaddingWrapper (needed for edge-to-edge infinite scroll) but never restored it for its filter toolbar, unlike Config and the list pages which already follow this convention - leaving the fields flush against the top. Padding is now applied once on the Toolbar itself rather than per field. Sort By/Group By were also truncating to "Ti..." because their fixed 7.5rem width was too narrow for MUI's Select chrome.
A filtered or unfiltered query with zero results previously rendered nothing at all, giving no feedback that the search actually ran.
Tabs used the default primary-colored selected state, which matched the AppBar's primary background exactly.
DialogContent had no spacing between stacked TextFields. Added a shared dialogFields flex-gap style instead of relying on TextField's own margin, since DialogContent's top padding isn't zeroed here (the Formik <Form> breaks MUI's title-adjacent-sibling CSS reset), and per-field margin would have doubled up with it.
Ratings from lookup providers can have many decimal digits (e.g. 6.938); round to one for display.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation for changes:
I'm tired updating yaml
Detailed changes: