diff --git a/webapp/.gitignore b/webapp/.gitignore index ab63914836c..168dd48d1ca 100644 --- a/webapp/.gitignore +++ b/webapp/.gitignore @@ -13,4 +13,4 @@ platform/*/dist platform/*/lib config.override.mk -build +build/test-results*.xml diff --git a/webapp/channels/jest.config.channels.js b/webapp/channels/jest.config.channels.js index a42e5650089..0ad1fa9a15d 100644 --- a/webapp/channels/jest.config.channels.js +++ b/webapp/channels/jest.config.channels.js @@ -20,10 +20,6 @@ const config = { '/node_modules/', 'src/packages/mattermost-redux/', ], - reporters: [ - 'default', - ['jest-junit', {outputDirectory: 'build', outputName: 'test-results-channels.xml'}], - ], }; module.exports = config; diff --git a/webapp/channels/jest.config.js b/webapp/channels/jest.config.js index 55d4932803d..fdfa7733183 100644 --- a/webapp/channels/jest.config.js +++ b/webapp/channels/jest.config.js @@ -32,10 +32,6 @@ const config = { }, moduleDirectories: ['src', 'node_modules'], moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'], - reporters: [ - 'default', - ['jest-junit', {outputDirectory: 'build', outputName: 'test-results.xml'}], - ], transformIgnorePatterns: [ 'node_modules/(?!react-native|react-router|pdfjs-dist|p-queue|p-timeout|@mattermost/compass-icons|cidr-regex|ip-regex|serialize-error)', ], diff --git a/webapp/channels/jest.config.mattermost-redux.js b/webapp/channels/jest.config.mattermost-redux.js index 137034128ef..72233af6247 100644 --- a/webapp/channels/jest.config.mattermost-redux.js +++ b/webapp/channels/jest.config.mattermost-redux.js @@ -18,10 +18,6 @@ const config = { '/node_modules/', 'src/packages/mattermost-redux/src/selectors/create_selector', ], - reporters: [ - 'default', - ['jest-junit', {outputDirectory: 'build', outputName: 'test-results-mattermost-redux.xml'}], - ], }; module.exports = config; diff --git a/webapp/channels/package.json b/webapp/channels/package.json index fb3030b5bac..fc5eb73bc1a 100644 --- a/webapp/channels/package.json +++ b/webapp/channels/package.json @@ -152,7 +152,6 @@ "jest-canvas-mock": "2.5.0", "jest-cli": "30.1.3", "jest-environment-jsdom": "30.1.0", - "jest-junit": "16.0.0", "jest-watch-typeahead": "3.0.1", "nock": "13.2.8", "node-fetch": "2.7.0", diff --git a/webapp/channels/src/plugins/export.ts b/webapp/channels/src/plugins/export.ts index b4a623f6b2c..eb2d571bfc5 100644 --- a/webapp/channels/src/plugins/export.ts +++ b/webapp/channels/src/plugins/export.ts @@ -30,6 +30,7 @@ import {useWebSocket, useWebSocketClient, WebSocketContext} from 'utils/use_webs import {imageURLForUser} from 'utils/utils'; import {openInteractiveDialog} from './interactive_dialog'; // This import has intentional side effects. Do not remove without research. +import {loadSharedDependency} from './shared_dependencies'; import Textbox from './textbox'; // Note: We can't directly use the hook here, but we can create a function that opens the external pricing page @@ -73,6 +74,7 @@ interface WindowWithLibraries { canPopout: typeof canPopout; }; }; + loadSharedDependency(request: string): unknown; openPricingModal: () => void; Components: { Textbox: typeof Textbox; @@ -150,6 +152,7 @@ window.WebappUtils = { canPopout, }, }; +window.loadSharedDependency = loadSharedDependency; // For plugins, we provide a simple function that always tries to open the external pricing page // This won't respect air-gapped status, but plugins shouldn't be calling this in air-gapped environments diff --git a/webapp/channels/src/plugins/shared_dependencies.ts b/webapp/channels/src/plugins/shared_dependencies.ts new file mode 100644 index 00000000000..beeef4ed896 --- /dev/null +++ b/webapp/channels/src/plugins/shared_dependencies.ts @@ -0,0 +1,16 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// Every module exported from the @mattermost/shared package must be added to this map +const sharedDependencies = new Map([ + ['@mattermost/shared/components/emoji', () => import('@mattermost/shared/components/emoji')], +]); + +export function loadSharedDependency(request: string) { + const loader = sharedDependencies.get(request); + if (loader) { + return loader(); + } + + throw new Error(`A plugin attempted to load ${request} which couldn't be found.`); +} diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 4f91749317b..d66cd2ba344 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -206,7 +206,6 @@ "jest-canvas-mock": "2.5.0", "jest-cli": "30.1.3", "jest-environment-jsdom": "30.1.0", - "jest-junit": "16.0.0", "jest-watch-typeahead": "3.0.1", "nock": "13.2.8", "node-fetch": "2.7.0", @@ -17105,39 +17104,6 @@ "fsevents": "^2.3.3" } }, - "node_modules/jest-junit": { - "version": "16.0.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "mkdirp": "^1.0.4", - "strip-ansi": "^6.0.1", - "uuid": "^8.3.2", - "xml": "^1.0.1" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/jest-junit/node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-junit/node_modules/uuid": { - "version": "8.3.2", - "dev": true, - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/jest-leak-detector": { "version": "30.1.0", "dev": true, @@ -19171,8 +19137,8 @@ }, "node_modules/mkdirp": { "version": "1.0.4", - "devOptional": true, "license": "MIT", + "optional": true, "bin": { "mkdirp": "bin/cmd.js" }, @@ -25788,11 +25754,6 @@ "xtend": "^4.0.0" } }, - "node_modules/xml": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, "node_modules/xml-name-validator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", diff --git a/webapp/platform/client/tsconfig.json b/webapp/platform/client/tsconfig.json index d7493b53621..5aa1bb8d98f 100644 --- a/webapp/platform/client/tsconfig.json +++ b/webapp/platform/client/tsconfig.json @@ -11,6 +11,7 @@ "esModuleInterop": true, "allowSyntheticDefaultImports": true, "jsx": "react", + "preserveConstEnums": true, "outDir": "./lib", "rootDir": "./src", "composite": true, diff --git a/webapp/platform/mattermost-redux/tsconfig.json b/webapp/platform/mattermost-redux/tsconfig.json index 5ef64e71bdd..884751b2c99 100644 --- a/webapp/platform/mattermost-redux/tsconfig.json +++ b/webapp/platform/mattermost-redux/tsconfig.json @@ -14,6 +14,7 @@ "esModuleInterop": true, "allowSyntheticDefaultImports": true, "jsx": "react", + "preserveConstEnums": true, "outDir": "./lib", "rootDir": "../../channels/src/packages/mattermost-redux/src", "composite": true, diff --git a/webapp/platform/shared/.parcelrc b/webapp/platform/shared/.parcelrc index c755243d01f..edc4652c9b3 100644 --- a/webapp/platform/shared/.parcelrc +++ b/webapp/platform/shared/.parcelrc @@ -1,5 +1,5 @@ { "extends": "@parcel/config-default", "bundler": "@parcel/bundler-library", - "namers": ["./parcel-namer-shared", "..."] + "namers": ["./build/parcel-namer-shared", "..."] } diff --git a/webapp/platform/shared/parcel-namer-shared.ts b/webapp/platform/shared/build/parcel-namer-shared.ts similarity index 100% rename from webapp/platform/shared/parcel-namer-shared.ts rename to webapp/platform/shared/build/parcel-namer-shared.ts diff --git a/webapp/platform/shared/build/webpack-web-app-externals.cjs b/webapp/platform/shared/build/webpack-web-app-externals.cjs new file mode 100644 index 00000000000..58cace444ed --- /dev/null +++ b/webapp/platform/shared/build/webpack-web-app-externals.cjs @@ -0,0 +1,31 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// This script is intended to be used by Mattermost plugins to set up their Webpack externals to share their +// dependencies with the web app. It includes both third party dependencies (React, etc) and the MM Shared package. + +const windowExternals = { + react: 'React', + 'react-dom': 'ReactDOM', + redux: 'Redux', + luxon: 'Luxon', + 'react-redux': 'ReactRedux', + 'prop-types': 'PropTypes', + 'react-bootstrap': 'ReactBootstrap', + 'react-router-dom': 'ReactRouterDom', + 'react-intl': 'ReactIntl', +}; + +function webAppExternals() { + return [ + windowExternals, + ({request}, callback) => { + if ((/^@mattermost\/shared\//).test(request)) { + return callback(null, `promise globalThis.loadSharedDependency('${request}')`); + } + + return callback(); + }, + ]; +} +module.exports = webAppExternals; diff --git a/webapp/platform/shared/package.json b/webapp/platform/shared/package.json index b2402045b0e..3f923eeea1c 100644 --- a/webapp/platform/shared/package.json +++ b/webapp/platform/shared/package.json @@ -8,6 +8,7 @@ "homepage": "https://github.com/mattermost/mattermost/tree/master/webapp/platform/shared#readme", "license": "MIT", "files": [ + "build/webpack-web-app-externals.cjs", "dist", "src" ], @@ -32,6 +33,10 @@ "import": "./dist/module.js", "require": "./dist/main.js" }, + "./build/webpack-web-app-externals": { + "source": "./build/webpack-web-app-externals.cjs", + "require": "./build/webpack-web-app-externals.cjs" + }, "./*": { "types": [ "./src/*/index.ts",