Fixathon: Web app dependency updates part 1 (#29036)

* Ensure all packages remove a node_modules in their folder when cleaning

* Upgrade typescript to 5.6.3 and move to root package.json

Note that this currently fails to build the types package due to
@types/node which I'm going to try to remove

* Update @types/node to 20.11 to match .nvmrc

* Upgrade zen-observable to 0.10.0

It looks like localforage-observable uses its own version
of zen-observable because it hasn't been updated in years.
This seems like something we probably should remove.

* Update yargs to 17.7.2

* Update webpack-dev-server to 5.1.0

* Remove webpack-bundle-analyzer since we haven't used it in years

* Update webpack to 5.95.0

* Update web-vitals to 4.2.4

* Update turndown to 7.2.0

* Update tinycolor2 to 1.6.0

* Update timezones.json to 1.7.0

* Update stylelint to 16.10.0, stylelint-config-recommended-scss to 14.1.0, and stylelint-scss to 6.8.1

* Update webpack-cli to 5.1.4

* Update style-loader to 4.0.0

* Change all Webpack scripts to be ES modules

* Update strip-ansi to 7.1.0

This is a build script dependency

* Update chalk to 5.3.0

This is a build script dependency

* Update concurrently to 9.0.1

This is a build script dependency

* Update smooth-scroll-into-view-if-needed to 2.0.2

* MM-48205 Update serialize-error to 11.0.3

We didn't update this before because it's an ES module which caused Jest to complain. We can fix that by making Jest transform the it

* Update semver to 7.6.3

* Update types for semver, tinycolor2, turndown, and webpack

* Fix type issues: change Props to a type

* Fix type issues: invalid HTML attributes

* Remove unneeded option from Webpack config
This commit is contained in:
Harrison Healey
2024-11-06 13:40:19 -05:00
committed by GitHub
parent 2117a4ed30
commit 4136343476
27 changed files with 2561 additions and 864 deletions

View File

@@ -41,7 +41,7 @@ const config = {
['jest-junit', {outputDirectory: 'build', outputName: 'test-results.xml'}],
],
transformIgnorePatterns: [
'node_modules/(?!react-native|react-router|pdfjs-dist|p-queue|p-timeout|@mattermost/compass-components|@mattermost/compass-icons|cidr-regex|ip-regex)',
'node_modules/(?!react-native|react-router|pdfjs-dist|p-queue|p-timeout|@mattermost/compass-components|@mattermost/compass-icons|cidr-regex|ip-regex|serialize-error)',
],
transform: {
'^.+\\.(js|jsx|ts|tsx|mjs)$': 'babel-jest',

View File

@@ -21,7 +21,7 @@
"@tanstack/react-table": "8.10.7",
"@tippyjs/react": "4.2.6",
"@types/color-hash": "1.0.2",
"@types/turndown": "5.0.1",
"@types/turndown": "5.0.5",
"bootstrap": "3.4.1",
"buffer": "6.0.3",
"chart.js": "3.8.2",
@@ -87,18 +87,17 @@
"redux-thunk": "2.4.2",
"regenerator-runtime": "0.13.10",
"rudder-sdk-js": "1.0.16",
"semver": "7.5.2",
"serialize-error": "8.0.1",
"semver": "7.6.3",
"serialize-error": "11.0.3",
"shallow-equals": "1.0.0",
"smooth-scroll-into-view-if-needed": "1.1.33",
"smooth-scroll-into-view-if-needed": "2.0.2",
"stream-browserify": "3.0.0",
"styled-components": "5.3.6",
"timezones.json": "1.6.1",
"tinycolor2": "1.4.2",
"turndown": "7.1.1",
"typescript": "5.5.4",
"web-vitals": "4.2.0",
"zen-observable": "0.9.0"
"timezones.json": "1.7.1",
"tinycolor2": "1.6.0",
"turndown": "7.2.0",
"web-vitals": "4.2.4",
"zen-observable": "0.10.0"
},
"devDependencies": {
"@deanwhillier/jest-matchmedia-mock": "1.2.0",
@@ -121,7 +120,6 @@
"@types/luxon": "3.0.2",
"@types/mark.js": "8.11.6",
"@types/marked": "0.7.4",
"@types/node": "18.19.59",
"@types/react": "17.0.83",
"@types/react-beautiful-dnd": "13.1.2",
"@types/react-bootstrap": "0.32.35",
@@ -138,10 +136,10 @@
"@types/react-window": "1.8.5",
"@types/react-window-infinite-loader": "1.0.6",
"@types/redux-mock-store": "1.0.3",
"@types/semver": "7.3.9",
"@types/semver": "7.5.8",
"@types/shallow-equals": "1.0.3",
"@types/styled-components": "5.1.32",
"@types/tinycolor2": "1.4.3",
"@types/tinycolor2": "1.4.6",
"copy-webpack-plugin": "11.0.0",
"emoji-datasource": "6.1.1",
"emoji-datasource-apple": "6.1.1",
@@ -169,14 +167,13 @@
"react-router-enzyme-context": "1.2.0",
"redux-mock-store": "1.5.4",
"redux-persist-node-storage": "2.0.0",
"stylelint": "16.2.1",
"stylelint": "16.10.0",
"stylelint-config-idiomatic-order": "10.0.0",
"stylelint-config-recommended-scss": "14.0.0",
"stylelint-config-recommended-scss": "14.1.0",
"stylelint-order": "6.0.4",
"stylelint-scss": "6.1.0",
"webpack-bundle-analyzer": "4.7.0",
"stylelint-scss": "6.8.1",
"webpack-pwa-manifest": "4.3.0",
"yargs": "16.2.0"
"yargs": "17.7.2"
},
"overrides": {
"@mattermost/desktop-api": {

View File

@@ -376,7 +376,6 @@ exports[`components/SettingItemMin should match snapshot, profile picture on fil
className="img-preview__image"
>
<div
alt="profile image preview"
className="profile-img-preview"
style={
Object {
@@ -626,7 +625,6 @@ exports[`components/SettingItemMin should match snapshot, team icon on file 1`]
className="img-preview__image"
>
<div
alt="team image preview"
className="team-img-preview"
style={
Object {

View File

@@ -8,9 +8,9 @@ import ChannelsList from 'components/admin_console/team_channel_settings/channel
import AdminHeader from 'components/widgets/admin_console/admin_header';
import AdminPanel from 'components/widgets/admin_console/admin_panel';
interface Props {
type Props = {
siteName?: string;
}
};
export const ChannelsSettings = ({siteName}: Props) => {
return (

View File

@@ -13,7 +13,7 @@ import {Constants, ModalIdentifiers} from 'utils/constants';
import type {PropsFromRedux} from './index';
interface Props extends PropsFromRedux {
type Props = PropsFromRedux & {
/**
* Object with info about user
@@ -34,7 +34,7 @@ interface Props extends PropsFromRedux {
* Use for test selector
*/
id?: string;
}
};
const LeaveChannel = ({
isDefault = true,

View File

@@ -20,13 +20,13 @@ export interface Match {
export type MatchAndHistory = Pick<Props, 'match' | 'history'>
interface Props {
type Props = {
match: Match;
actions: {
onChannelByIdentifierEnter: (props: MatchAndHistory) => any;
};
history: any;
}
};
export default class ChannelIdentifierRouter extends React.PureComponent<Props> {
constructor(props: Props) {

View File

@@ -29,7 +29,7 @@ import FilenameOverlay from './filename_overlay';
import type {PropsFromRedux} from './index';
interface Props extends PropsFromRedux {
type Props = PropsFromRedux & {
/*
* File detailed information
@@ -52,7 +52,7 @@ interface Props extends PropsFromRedux {
compactDisplay?: boolean;
disablePreview?: boolean;
handleFileDropdownOpened?: (open: boolean) => void;
}
};
export default function FileAttachment(props: Props) {
const mounted = useRef(true);

View File

@@ -8,10 +8,10 @@ import GetLinkModal from 'components/get_link_modal';
import type {PropsFromRedux} from './index';
interface Props extends PropsFromRedux {
type Props = PropsFromRedux & {
onExited: () => void;
fileId: string;
}
};
const GetPublicLinkModal = ({
actions,

View File

@@ -39,13 +39,13 @@ import type {GlobalState} from 'types/store';
import {removePostCloseRHSDeleteDraft} from './actions';
import PostComponent from './post_component';
interface OwnProps {
type OwnProps = {
post?: Post | UserActivityPost;
previousPostId?: string;
postId?: string;
shouldHighlight?: boolean;
location: keyof typeof Locations;
}
};
function isFirstReply(post: Post, previousPost?: Post | null): boolean {
if (post.root_id) {

View File

@@ -10,11 +10,6 @@ export interface Props {
name: string;
imageUrl: string;
}
declare module 'react' {
interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {
alt?: string;
}
}
const PostEmoji = ({children, name, imageUrl}: Props) => {
const emojiText = `:${name}:`;
@@ -33,7 +28,6 @@ const PostEmoji = ({children, name, imageUrl}: Props) => {
placement='top'
>
<span
alt={emojiText}
className='emoticon'
data-testid={`postEmoji.${emojiText}`}
style={{backgroundImage: backgroundImageUrl}}

View File

@@ -6,13 +6,13 @@ import {FormattedMessage} from 'react-intl';
import type {FileInfo} from '@mattermost/types/files';
interface Props {
type Props = {
/*
* An array of file metadata for the parent post
*/
fileInfos?: FileInfo[];
}
};
const CommentedOnFilesMessage = ({
fileInfos,

View File

@@ -43,11 +43,11 @@ export const isChannelLoading = (params: RouteViewParams, channel?: Channel, tea
return true;
};
interface RouteViewParams {
type RouteViewParams = {
team?: string;
identifier?: string;
postid?: string;
}
};
type Props = {channelId: string} & RouteComponentProps<RouteViewParams>

View File

@@ -9,13 +9,13 @@ import {Preferences} from 'utils/constants';
import PostList from './post_list';
interface Props {
type Props = {
lastViewedAt?: number;
channelLoading: boolean;
channelId: string;
focusedPostId?: string;
unreadScrollPosition: string;
}
};
interface State {
unreadChunkTimeStamp?: number;

View File

@@ -19,7 +19,7 @@ import {RHSStates} from 'utils/constants';
import type {RhsState} from 'types/store/rhs';
interface Props extends WrappedComponentProps {
type Props = WrappedComponentProps & {
isExpanded: boolean;
isMobileView: boolean;
rootPostId: string;
@@ -40,7 +40,7 @@ interface Props extends WrappedComponentProps {
closeRightHandSide: (e?: React.MouseEvent) => void;
toggleRhsExpanded: (e: React.MouseEvent) => void;
setThreadFollow: (userId: string, teamId: string, threadId: string, newState: boolean) => void;
}
};
class RhsHeaderPost extends React.PureComponent<Props> {
handleBack = (e: React.MouseEvent) => {

View File

@@ -172,7 +172,6 @@ export default class SettingPicture extends Component<Props, State> {
<div className={`${imageContext}-img-preview`}>
<div className='img-preview__image'>
<div
alt={`${imageContext} image preview`}
style={imageStyles}
className={`${imageContext}-img-preview`}
/>

View File

@@ -78,7 +78,6 @@ const TeamPictureSection = ({team, file, teamName, disabled, onFileChange, onRem
return (
<div
id='teamIconImage'
alt='team image preview'
style={imageStyles}
className='team-img-preview'
onClick={handleInputFile}

View File

@@ -10,10 +10,15 @@ import MenuWrapperAnimation from './menu_wrapper_animation';
import './menu_wrapper.scss';
declare module 'react' {
interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {
// This isn't a valid HTML attribute, but we use it in enough places now that it'll require some work to remove it
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface HTMLAttributes<T> {
disabled?: boolean;
}
}
type Props = {
children?: React.ReactNode;
className: string;

View File

@@ -14,8 +14,6 @@ const webpack = require('webpack');
const {ModuleFederationPlugin} = require('webpack').container;
const WebpackPwaManifest = require('webpack-pwa-manifest');
// const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer');
const packageJson = require('./package.json');
const NPM_TARGET = process.env.npm_lifecycle_event;
@@ -141,7 +139,6 @@ var config = {
crypto: require.resolve('crypto-browserify'),
stream: require.resolve('stream-browserify'),
buffer: require.resolve('buffer/'),
process: require.resolve('process/browser.js'),
},
},
performance: {
@@ -266,13 +263,6 @@ var config = {
sizes: '96x96',
}],
}),
// Disabling this plugin until we come up with better bundle analysis ci
// new BundleAnalyzerPlugin({
// analyzerMode: 'disabled',
// generateStatsFile: true,
// statsFilename: 'bundlestats.json',
// }),
],
};
@@ -407,16 +397,21 @@ if (targetIsDevServer) {
devtool: 'eval-cheap-module-source-map',
devServer: {
liveReload: true,
proxy: {
// Forward these requests to the server
'/api': {
proxy: [
{
context: '/api',
...proxyToServer,
ws: true,
},
'/plugins': proxyToServer,
'/static/plugins': proxyToServer,
},
{
context: '/plugins',
...proxyToServer,
},
{
context: '/static/plugins',
...proxyToServer,
},
],
port: 9005,
devMiddleware: {
writeToDisk: false,

3221
webapp/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,9 +7,9 @@
},
"scripts": {
"postinstall": "patch-package && npm run build --workspace=platform/types --workspace=platform/client --workspace=platform/components",
"build": "node scripts/build.js",
"run": "node scripts/run.js",
"dev-server": "node scripts/dev-server.js",
"build": "node scripts/build.mjs",
"run": "node scripts/run.mjs",
"dev-server": "node scripts/dev-server.mjs",
"test": "npm run test --workspaces --if-present",
"test:updatesnapshot": "npm run test:updatesnapshot --workspaces --if-present",
"test-ci": "npm run test-ci --workspaces --if-present",
@@ -19,21 +19,23 @@
"clean": "npm run clean --workspaces --if-present"
},
"dependencies": {
"react-intl": "6.6.2"
"react-intl": "6.6.2",
"typescript": "5.6.3"
},
"devDependencies": {
"@babel/core": "7.22.0",
"@babel/preset-env": "7.21.5",
"@babel/preset-react": "7.18.6",
"@babel/preset-typescript": "7.21.5",
"@types/webpack-env": "1.18.1",
"@types/node": "20.11.30",
"@types/webpack-env": "1.18.5",
"babel-loader": "9.1.2",
"babel-plugin-formatjs": "10.5.1",
"babel-plugin-styled-components": "2.1.1",
"babel-plugin-typescript-to-proptypes": "2.1.0",
"blessed": "0.1.81",
"chalk": "4.1.2",
"concurrently": "7.6.0",
"chalk": "5.3.0",
"concurrently": "9.0.1",
"cross-env": "7.0.3",
"css-loader": "6.7.3",
"eslint": "8.57.0",
@@ -45,11 +47,11 @@
"patch-package": "8.0.0",
"sass": "1.71.1",
"sass-loader": "14.1.1",
"strip-ansi": "6.0.1",
"style-loader": "3.3.2",
"webpack": "5.81.0",
"webpack-cli": "5.0.2",
"webpack-dev-server": "4.13.3"
"strip-ansi": "7.1.0",
"style-loader": "4.0.0",
"webpack": "5.95.0",
"webpack-cli": "5.1.4",
"webpack-dev-server": "5.1.0"
},
"overrides": {
"@floating-ui/react": {

View File

@@ -30,5 +30,8 @@
"eslint-plugin-react-hooks": {
"optional": true
}
},
"scripts": {
"clean": "rm -rf node_modules"
}
}

View File

@@ -40,6 +40,6 @@
"build": "tsc --build --verbose",
"check": "eslint --ext .js,.jsx,.tsx,.ts ./src --quiet",
"run": "tsc --watch --preserveWatchOutput",
"clean": "rm -rf lib *.tsbuildinfo"
"clean": "rm -rf lib node_modules *.tsbuildinfo"
}
}

View File

@@ -3,10 +3,10 @@
/* eslint-disable no-console */
const chalk = require('chalk');
const concurrently = require('concurrently');
import chalk from 'chalk';
import concurrently from 'concurrently';
const {getExitCode, getPlatformCommands} = require('./utils.js');
import {getExitCode, getPlatformCommands} from './utils.mjs';
async function buildAll() {
console.log(chalk.inverse.bold('Building subpackages...') + '\n');

View File

@@ -3,10 +3,10 @@
/* eslint-disable no-console */
const chalk = require('chalk');
const concurrently = require('concurrently');
import chalk from 'chalk';
import concurrently from 'concurrently';
const {getPlatformCommands} = require('./utils.js');
import {getPlatformCommands} from './utils.mjs';
async function watchAllWithDevServer() {
console.log(chalk.inverse.bold('Watching web app and all subpackages...'));

View File

@@ -3,11 +3,11 @@
/* eslint-disable no-console, no-process-env */
const chalk = require('chalk');
const concurrently = require('concurrently');
import chalk from 'chalk';
import concurrently from 'concurrently';
const {makeRunner} = require('./runner.js');
const {getExitCode, getPlatformCommands} = require('./utils.js');
import {makeRunner} from './runner.mjs';
import {getExitCode, getPlatformCommands} from './utils.mjs';
async function watchAll(useRunner) {
if (!useRunner) {

View File

@@ -1,10 +1,10 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
const {Writable} = require('stream');
import {Writable} from 'node:stream';
const blessed = require('blessed');
const stripAnsi = require('strip-ansi');
import blessed from 'blessed';
import stripAnsi from 'strip-ansi';
class Runner {
commands;
@@ -228,11 +228,10 @@ class Runner {
}
}
function makeRunner(commands) {
export function makeRunner(commands) {
const runner = new Runner(commands);
runner.renderUi();
return runner;
}
exports.makeRunner = makeRunner;

View File

@@ -1,13 +1,15 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
const path = require('path');
import fs from 'node:fs';
import path from 'node:path';
const chalk = require('chalk');
const packageJson = require('../package.json');
import chalk from 'chalk';
function getWorkspaces() {
const packageFile = fs.readFileSync('package.json');
const packageJson = JSON.parse(packageFile, 'utf8');
return packageJson.workspaces;
}
@@ -17,8 +19,8 @@ function getPlatformPackagesContainingCommand(scriptName) {
return false;
}
// eslint-disable-next-line global-require
const workspacePackageJson = require(path.join(__dirname, '..', workspace, 'package.json'));
const workspacePackageFile = fs.readFileSync(path.join(workspace, 'package.json'));
const workspacePackageJson = JSON.parse(workspacePackageFile, 'utf8');
return workspacePackageJson?.scripts?.[scriptName];
});
@@ -27,7 +29,7 @@ function getPlatformPackagesContainingCommand(scriptName) {
/**
* Returns an array of concurrently commands to run a given script on every platform workspace that contains it.
*/
function getPlatformCommands(scriptName) {
export function getPlatformCommands(scriptName) {
return getPlatformPackagesContainingCommand(scriptName).map((workspace) => ({
command: `npm:${scriptName} --workspace=${workspace}`,
name: workspace.substring(workspace.lastIndexOf('/') + 1),
@@ -46,7 +48,7 @@ function getColorForWorkspace(workspace) {
* @param {import("concurrently").CloseEvent[]} closeEvents - An array of CloseEvents thrown by concurrently when waiting on a result
* @param {number} codeOnSignal - Which error code to return when the process is interrupted
*/
function getExitCode(closeEvents, codeOnSignal = 1) {
export function getExitCode(closeEvents, codeOnSignal = 1) {
const exitCode = closeEvents.find((event) => !event.killed && event.exitCode > 0)?.exitCode;
if (typeof exitCode === 'string') {
@@ -55,8 +57,3 @@ function getExitCode(closeEvents, codeOnSignal = 1) {
return exitCode;
}
}
module.exports = {
getExitCode,
getPlatformCommands,
};