From 5283ca54b46b82e599306891a7561c957b472b60 Mon Sep 17 00:00:00 2001 From: Jesse Hallam Date: Mon, 1 Jun 2026 11:12:44 -0300 Subject: [PATCH 1/5] add PushNotification.Transport and related const (#36829) * add PushNotification.Transport and related const Supporting change for https://github.com/mattermost/mattermost-plugin-calls/pull/1189, originally in https://github.com/mattermost/mattermost/pull/36726. * updated API docs to match --- api/v4/source/definitions.yaml | 14 ++++++ server/public/model/push_notification.go | 63 ++++++++++++++---------- 2 files changed, 50 insertions(+), 27 deletions(-) diff --git a/api/v4/source/definitions.yaml b/api/v4/source/definitions.yaml index 5339ea721bd..52f17c70214 100644 --- a/api/v4/source/definitions.yaml +++ b/api/v4/source/definitions.yaml @@ -3289,6 +3289,15 @@ components: type: string type: type: string + sub_type: + type: string + description: Additional message type information for mobile clients. Use "calls" for Calls plugin notifications. + transport: + type: string + description: Delivery path for the push proxy. Use "voip" for VoIP (CallKit) notifications; omit for standard delivery. + enum: + - "" + - voip sender_id: type: string sender_name: @@ -3301,8 +3310,13 @@ components: type: string version: type: string + is_crt_enabled: + type: boolean + description: Whether Collapsed Reply Threads is enabled for the recipient. is_id_loaded: type: boolean + signature: + type: string PluginStatus: type: object properties: diff --git a/server/public/model/push_notification.go b/server/public/model/push_notification.go index addc91022b6..fc7688c7701 100644 --- a/server/public/model/push_notification.go +++ b/server/public/model/push_notification.go @@ -50,6 +50,14 @@ type PushSubType string // PushSubTypeCalls is used by the Calls plugin const PushSubTypeCalls PushSubType = "calls" +// PushTransport selects which delivery path the push proxy uses. +type PushTransport string + +const ( + PushTransportStandard PushTransport = "" + PushTransportVoIP PushTransport = "voip" +) + type PushNotificationAck struct { Id string `json:"id"` ClientReceivedAt int64 `json:"received_at"` @@ -60,33 +68,34 @@ type PushNotificationAck struct { } type PushNotification struct { - AckId string `json:"ack_id"` - Platform string `json:"platform"` - ServerId string `json:"server_id"` - DeviceId string `json:"device_id"` - PostId string `json:"post_id"` - Category string `json:"category,omitempty"` - Sound string `json:"sound,omitempty"` - Message string `json:"message,omitempty"` - Badge int `json:"badge,omitempty"` - ContentAvailable int `json:"cont_ava,omitempty"` - TeamId string `json:"team_id,omitempty"` - ChannelId string `json:"channel_id,omitempty"` - RootId string `json:"root_id,omitempty"` - ChannelName string `json:"channel_name,omitempty"` - Type string `json:"type,omitempty"` - SubType PushSubType `json:"sub_type,omitempty"` - SenderId string `json:"sender_id,omitempty"` - SenderName string `json:"sender_name,omitempty"` - OverrideUsername string `json:"override_username,omitempty"` - OverrideIconURL string `json:"override_icon_url,omitempty"` - FromWebhook string `json:"from_webhook,omitempty"` - Version string `json:"version,omitempty"` - IsCRTEnabled bool `json:"is_crt_enabled"` - IsIdLoaded bool `json:"is_id_loaded"` - PostType string `json:"-"` - ChannelType ChannelType `json:"-"` - Signature string `json:"signature"` + AckId string `json:"ack_id"` + Platform string `json:"platform"` + ServerId string `json:"server_id"` + DeviceId string `json:"device_id"` + PostId string `json:"post_id"` + Category string `json:"category,omitempty"` + Sound string `json:"sound,omitempty"` + Message string `json:"message,omitempty"` + Badge int `json:"badge,omitempty"` + ContentAvailable int `json:"cont_ava,omitempty"` + TeamId string `json:"team_id,omitempty"` + ChannelId string `json:"channel_id,omitempty"` + RootId string `json:"root_id,omitempty"` + ChannelName string `json:"channel_name,omitempty"` + Type string `json:"type,omitempty"` + SubType PushSubType `json:"sub_type,omitempty"` + Transport PushTransport `json:"transport,omitempty"` + SenderId string `json:"sender_id,omitempty"` + SenderName string `json:"sender_name,omitempty"` + OverrideUsername string `json:"override_username,omitempty"` + OverrideIconURL string `json:"override_icon_url,omitempty"` + FromWebhook string `json:"from_webhook,omitempty"` + Version string `json:"version,omitempty"` + IsCRTEnabled bool `json:"is_crt_enabled"` + IsIdLoaded bool `json:"is_id_loaded"` + PostType string `json:"-"` + ChannelType ChannelType `json:"-"` + Signature string `json:"signature"` } func (pn *PushNotification) DeepCopy() *PushNotification { From da48051967a28bbb0ccd063b46792d581532bb7d Mon Sep 17 00:00:00 2001 From: Christopher Poile Date: Mon, 1 Jun 2026 11:42:26 -0400 Subject: [PATCH 2/5] Upgrade "@mattermost/compass-icons" to 0.1.61 (#36831) This is the first compass-icons version to actually reach the npm registry since 0.1.53. Releases 0.1.54-0.1.60 all failed the publish.yml workflow after trusted publishing was introduced; 0.1.61 adds the package.json repository field needed for sigstore provenance validation. Brings in shield-lock-outline, shield-check, file-help-outline-large, and other icons added upstream between 2026-01 and 2026-06. --- webapp/package-lock.json | 10 +++++----- webapp/package.json | 2 +- webapp/platform/components/package.json | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 8c29ab2a7bc..bb4dda12068 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -16,7 +16,7 @@ "platform/types" ], "dependencies": { - "@mattermost/compass-icons": "0.1.53", + "@mattermost/compass-icons": "0.1.61", "react-intl": "7.1.14", "typescript": "5.6.3" }, @@ -6089,9 +6089,9 @@ "link": true }, "node_modules/@mattermost/compass-icons": { - "version": "0.1.53", - "resolved": "https://registry.npmjs.org/@mattermost/compass-icons/-/compass-icons-0.1.53.tgz", - "integrity": "sha512-MPcwJ9bKWxOxppxoqYCK5BW/a9qkaozxQr/fTdu55TLBjV5t0W6EPVa+msnFLr2iStYsYVnHwEo3fArsX0Bnew==", + "version": "0.1.61", + "resolved": "https://registry.npmjs.org/@mattermost/compass-icons/-/compass-icons-0.1.61.tgz", + "integrity": "sha512-Xq7QHyxq7NPljgqlzwRp6tWGe5sD49tWTzG41q9+sYsI+DdymJmteezupkfO3NxNxYXJiDD+q2kF0Ai2he1Mcg==", "license": "MIT", "peer": true }, @@ -27929,7 +27929,7 @@ }, "peerDependencies": { "@babel/runtime-corejs3": "^7.17.8", - "@mattermost/compass-icons": "0.1.53", + "@mattermost/compass-icons": "0.1.61", "@mattermost/shared": "11.8.0", "classnames": "^2.3.1", "lodash": "^4.17.21", diff --git a/webapp/package.json b/webapp/package.json index 94c1cc5cf0f..6549cec1013 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -23,7 +23,7 @@ "check-external-links": "node scripts/check-external-links.mjs" }, "dependencies": { - "@mattermost/compass-icons": "0.1.53", + "@mattermost/compass-icons": "0.1.61", "react-intl": "7.1.14", "typescript": "5.6.3" }, diff --git a/webapp/platform/components/package.json b/webapp/platform/components/package.json index ed1c0e28aaa..da8d073967a 100644 --- a/webapp/platform/components/package.json +++ b/webapp/platform/components/package.json @@ -40,7 +40,7 @@ }, "peerDependencies": { "@babel/runtime-corejs3": "^7.17.8", - "@mattermost/compass-icons": "0.1.53", + "@mattermost/compass-icons": "0.1.61", "@mattermost/shared": "11.8.0", "classnames": "^2.3.1", "lodash": "^4.17.21", From ea6ac3f229a82d61c4124998d8af26287b66d29b Mon Sep 17 00:00:00 2001 From: Maria A Nunez Date: Mon, 1 Jun 2026 11:58:17 -0400 Subject: [PATCH 3/5] MM-68983: Tighten OAuth token issuance and cleanup on user deactivation (#36743) Reject OAuth grants for users with DeleteAt != 0 across the implicit, authorization code, and refresh token paths, and purge stored OAuth access data for the user during deactivation. Co-authored-by: Cursor --- server/channels/app/oauth.go | 8 +++ server/channels/app/oauth_test.go | 110 ++++++++++++++++++++++++++++++ server/channels/app/user.go | 4 ++ server/channels/app/user_test.go | 68 ++++++++++++++++++ 4 files changed, 190 insertions(+) diff --git a/server/channels/app/oauth.go b/server/channels/app/oauth.go index 740a8b2ad27..c02fbff1a46 100644 --- a/server/channels/app/oauth.go +++ b/server/channels/app/oauth.go @@ -285,6 +285,10 @@ func (a *App) GetOAuthAccessTokenForImplicitFlow(rctx request.CTX, userID string return nil, err } + if user.DeleteAt != 0 { + return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.expired_code.app_error", nil, "", http.StatusForbidden) + } + session, err := a.newSession(rctx, oauthApp, user) if err != nil { return nil, err @@ -408,6 +412,10 @@ func (a *App) handleRefreshTokenGrant(rctx request.CTX, oauthApp *model.OAuthApp return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.internal_user.app_error", nil, "", http.StatusNotFound).Wrap(nErr) } + if user.DeleteAt != 0 { + return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.expired_code.app_error", nil, "", http.StatusForbidden) + } + audience := accessData.Audience // Default to existing audience if resource != "" { // Validate the resource parameter per RFC 8707 diff --git a/server/channels/app/oauth_test.go b/server/channels/app/oauth_test.go index 6945f4ba11d..41f929bd00d 100644 --- a/server/channels/app/oauth_test.go +++ b/server/channels/app/oauth_test.go @@ -1459,6 +1459,116 @@ func TestGetOAuthAccessTokenForCodeFlow(t *testing.T) { require.Equal(t, http.StatusBadRequest, appErr.StatusCode) }) } + +func TestOAuthRefreshTokenGrantRejectsDeactivatedUser(t *testing.T) { + mainHelper.Parallel(t) + th := Setup(t).InitBasic(t) + + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true }) + + oapp := &model.OAuthApp{ + Name: "RefreshGrantDeactivated_" + model.NewRandomString(10), + CreatorId: th.BasicUser2.Id, + Homepage: "https://nowhere.com", + Description: "test", + CallbackUrls: []string{"https://example.com/callback"}, + ClientSecret: model.NewId(), + } + oapp, appErr := th.App.CreateOAuthApp(oapp) + require.Nil(t, appErr) + + user := th.CreateUser(t) + + authRequest := &model.AuthorizeRequest{ + ResponseType: model.AuthCodeResponseType, + ClientId: oapp.Id, + RedirectURI: oapp.CallbackUrls[0], + Scope: "user", + State: "test_state", + } + + redirectURL, appErr := th.App.AllowOAuthAppAccessToUser(th.Context, user.Id, authRequest) + require.Nil(t, appErr) + + uri, parseErr := url.Parse(redirectURL) + require.NoError(t, parseErr) + code := uri.Query().Get("code") + require.NotEmpty(t, code) + + tokenResp, appErr := th.App.GetOAuthAccessTokenForCodeFlow( + th.Context, + oapp.Id, + model.AccessTokenGrantType, + oapp.CallbackUrls[0], + code, + oapp.ClientSecret, + "", + "", + "", + ) + require.Nil(t, appErr) + require.NotEmpty(t, tokenResp.AccessToken) + require.NotEmpty(t, tokenResp.RefreshToken) + + require.NoError(t, th.App.Srv().Store().Session().Remove(tokenResp.AccessToken)) + + _, appErr = th.App.UpdateActive(th.Context, user, false) + require.Nil(t, appErr) + + refreshResp, appErr := th.App.GetOAuthAccessTokenForCodeFlow( + th.Context, + oapp.Id, + model.RefreshTokenGrantType, + oapp.CallbackUrls[0], + "", + oapp.ClientSecret, + tokenResp.RefreshToken, + "", + "", + ) + require.NotNil(t, appErr, "refresh token grant must fail for an inactive user") + require.Nil(t, refreshResp) +} + +func TestOAuthImplicitGrantRejectsDeactivatedUser(t *testing.T) { + mainHelper.Parallel(t) + th := Setup(t).InitBasic(t) + + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true }) + + oapp := &model.OAuthApp{ + Name: "ImplicitGrantDeactivated_" + model.NewRandomString(10), + CreatorId: th.BasicUser2.Id, + Homepage: "https://nowhere.com", + Description: "test", + CallbackUrls: []string{"https://example.com/callback"}, + ClientSecret: model.NewId(), + } + oapp, appErr := th.App.CreateOAuthApp(oapp) + require.Nil(t, appErr) + + user := th.CreateUser(t) + + _, appErr = th.App.UpdateActive(th.Context, user, false) + require.Nil(t, appErr) + + authRequest := &model.AuthorizeRequest{ + ResponseType: model.ImplicitResponseType, + ClientId: oapp.Id, + RedirectURI: oapp.CallbackUrls[0], + Scope: "user", + State: "test_state", + } + + session, appErr := th.App.GetOAuthAccessTokenForImplicitFlow(th.Context, user.Id, authRequest) + require.NotNil(t, appErr, "implicit grant must fail for an inactive user") + require.Nil(t, session) + + accessData, sErr := th.App.Srv().Store().OAuth().GetAccessDataByUserForApp(user.Id, oapp.Id) + require.NoError(t, sErr) + require.Empty(t, accessData, "no access data may be persisted for an inactive user") +} + func TestParseOAuthStateTokenExtra(t *testing.T) { t.Run("valid token with normal values", func(t *testing.T) { email, action, cookie, err := parseOAuthStateTokenExtra("user@example.com:email_to_sso:randomcookie123") diff --git a/server/channels/app/user.go b/server/channels/app/user.go index 22060540f07..5567168f3ca 100644 --- a/server/channels/app/user.go +++ b/server/channels/app/user.go @@ -1149,6 +1149,10 @@ func (a *App) userDeactivated(rctx request.CTX, userID string) *model.AppError { rctx.Logger().Warn("unable to remove auth data by user id", mlog.Err(nErr)) } + if nErr := a.Srv().Store().OAuth().PermanentDeleteAuthDataByUser(userID); nErr != nil { + rctx.Logger().Warn("unable to remove oauth access data by user id", mlog.Err(nErr)) + } + return nil } diff --git a/server/channels/app/user_test.go b/server/channels/app/user_test.go index f82cd9915c6..5723f9dec31 100644 --- a/server/channels/app/user_test.go +++ b/server/channels/app/user_test.go @@ -11,6 +11,7 @@ import ( _ "image/jpeg" _ "image/png" "net/http" + "net/url" "path/filepath" "strings" "testing" @@ -477,6 +478,73 @@ func TestUpdateActiveBotsSideEffect(t *testing.T) { require.Nil(t, appErr) } +func TestUserDeactivationRevokesOAuthAccessTokens(t *testing.T) { + mainHelper.Parallel(t) + th := Setup(t).InitBasic(t) + + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true }) + + oapp := &model.OAuthApp{ + Name: "DeactivationCleanup_" + model.NewRandomString(10), + CreatorId: th.BasicUser2.Id, + Homepage: "https://nowhere.com", + Description: "test", + CallbackUrls: []string{"https://example.com/callback"}, + ClientSecret: model.NewId(), + } + oapp, appErr := th.App.CreateOAuthApp(oapp) + require.Nil(t, appErr) + + user := th.CreateUser(t) + + authRequest := &model.AuthorizeRequest{ + ResponseType: model.AuthCodeResponseType, + ClientId: oapp.Id, + RedirectURI: oapp.CallbackUrls[0], + Scope: "user", + State: "test_state", + } + + redirectURL, appErr := th.App.AllowOAuthAppAccessToUser(th.Context, user.Id, authRequest) + require.Nil(t, appErr) + + uri, parseErr := url.Parse(redirectURL) + require.NoError(t, parseErr) + code := uri.Query().Get("code") + require.NotEmpty(t, code) + + tokenResp, appErr := th.App.GetOAuthAccessTokenForCodeFlow( + th.Context, + oapp.Id, + model.AccessTokenGrantType, + oapp.CallbackUrls[0], + code, + oapp.ClientSecret, + "", + "", + "", + ) + require.Nil(t, appErr) + require.NotEmpty(t, tokenResp.AccessToken) + require.NotEmpty(t, tokenResp.RefreshToken) + + require.NoError(t, th.App.Srv().Store().Session().Remove(tokenResp.AccessToken)) + + preDeactivation, sErr := th.App.Srv().Store().OAuth().GetAccessDataByUserForApp(user.Id, oapp.Id) + require.NoError(t, sErr) + require.NotEmpty(t, preDeactivation) + + _, appErr = th.App.UpdateActive(th.Context, user, false) + require.Nil(t, appErr) + + postDeactivation, sErr := th.App.Srv().Store().OAuth().GetAccessDataByUserForApp(user.Id, oapp.Id) + require.NoError(t, sErr) + require.Empty(t, postDeactivation, "oauth access tokens for an inactive user must be removed") + + _, sErr = th.App.Srv().Store().OAuth().GetAccessDataByRefreshToken(tokenResp.RefreshToken) + require.Error(t, sErr, "refresh token row for an inactive user must be removed") +} + func TestUpdateOAuthUserAttrs(t *testing.T) { mainHelper.Parallel(t) th := Setup(t) From a57695daa3e9dab5c6a798ae1cf107a91384e5d1 Mon Sep 17 00:00:00 2001 From: Harrison Healey Date: Mon, 1 Jun 2026 12:03:05 -0400 Subject: [PATCH 4/5] MM-69002 Convert ESLint configs to flat config (#36750) * MM-68153 Migrate all ESLint configuration to flat config files * Use shared ESLint plugin and ESLint configuration to lint shared ESLint plugin and ESLint configuration as well as non-shared ESLint configuration --- webapp/channels/.eslintrc.json | 78 --- webapp/channels/eslint.config.mjs | 86 +++ webapp/channels/package.json | 4 +- webapp/platform/client/.eslintrc.json | 22 - webapp/platform/client/eslint.config.mjs | 23 + webapp/platform/client/package.json | 3 +- webapp/platform/components/.eslintrc.json | 6 - webapp/platform/components/eslint.config.mjs | 8 + webapp/platform/components/package.json | 3 +- .../configs/.eslintrc-react.json | 171 ----- .../eslint-plugin/configs/.eslintrc.json | 595 ----------------- webapp/platform/eslint-plugin/configs/base.js | 624 ++++++++++++++++++ .../platform/eslint-plugin/configs/react.js | 192 ++++++ .../platform/eslint-plugin/eslint.config.mjs | 8 + webapp/platform/eslint-plugin/index.js | 27 +- webapp/platform/eslint-plugin/package.json | 11 +- webapp/platform/eslint-plugin/rules/index.js | 10 + .../rules/no-dispatch-getstate.js | 2 +- .../eslint-plugin/rules/use-external-link.js | 12 +- webapp/platform/shared/.eslintrc.json | 20 - webapp/platform/shared/eslint.config.mjs | 26 + webapp/platform/shared/package.json | 4 +- webapp/platform/types/.eslintrc.json | 6 - webapp/platform/types/eslint.config.mjs | 8 + webapp/platform/types/package.json | 3 +- 25 files changed, 1020 insertions(+), 932 deletions(-) delete mode 100644 webapp/channels/.eslintrc.json create mode 100644 webapp/channels/eslint.config.mjs delete mode 100644 webapp/platform/client/.eslintrc.json create mode 100644 webapp/platform/client/eslint.config.mjs delete mode 100644 webapp/platform/components/.eslintrc.json create mode 100644 webapp/platform/components/eslint.config.mjs delete mode 100644 webapp/platform/eslint-plugin/configs/.eslintrc-react.json delete mode 100644 webapp/platform/eslint-plugin/configs/.eslintrc.json create mode 100644 webapp/platform/eslint-plugin/configs/base.js create mode 100644 webapp/platform/eslint-plugin/configs/react.js create mode 100644 webapp/platform/eslint-plugin/eslint.config.mjs create mode 100644 webapp/platform/eslint-plugin/rules/index.js delete mode 100644 webapp/platform/shared/.eslintrc.json create mode 100644 webapp/platform/shared/eslint.config.mjs delete mode 100644 webapp/platform/types/.eslintrc.json create mode 100644 webapp/platform/types/eslint.config.mjs diff --git a/webapp/channels/.eslintrc.json b/webapp/channels/.eslintrc.json deleted file mode 100644 index 0505b4e282b..00000000000 --- a/webapp/channels/.eslintrc.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "root": true, - "extends": [ - "plugin:@mattermost/react" - ], - "plugins": [ - "formatjs", - "no-only-tests" - ], - "settings": { - "import/resolver": "webpack", - "formatjs": { - "additionalFunctionNames": ["localizeMessage", "defineMessage"] - } - }, - "rules": { - "react/prop-types": [ - 2, - { - "ignore": [ - "location", - "history", - "component" - ] - } - ], - "react/no-unknown-property": [ - 2, - { - "ignore": [ - "mask-type" - ] - } - ], - "react/style-prop-object": [2, { - "allow": ["Timestamp"] - }], - "formatjs/enforce-default-message": 2, - "formatjs/enforce-id": 2, - "formatjs/enforce-placeholders": 2, - "formatjs/no-invalid-icu": 2, - "formatjs/no-multiple-plurals": 1, - "formatjs/no-multiple-whitespaces": 2, - "formatjs/no-literal-string-in-jsx": 1, - "formatjs/prefer-formatted-message": 1, - "formatjs/no-useless-message": 1, - "formatjs/prefer-pound-in-plural": 0, - "react/jsx-fragments": ["error", "syntax"] - }, - "overrides": [ - { - "files": ["*.test.*", "src/tests/**"], - "rules": { - "no-only-tests/no-only-tests": ["error", {"focus": ["only", "skip"]}] - } - }, - { - "files": ["*"], - "excludedFiles": ["src/packages/mattermost-redux/**"], - "rules": { - "@typescript-eslint/no-restricted-imports": [ - "error", - { - "paths": [{ - "name": "mattermost-redux/types/actions", - "importNames": ["DispatchFunc", "GetStateFunc", "ActionFunc", "ActionFuncAsync", "ThunkActionFunc"], - "message": "Use the web app version of it from types/store" - }], - "patterns": [{ - "group": ["@mattermost/client/src/*", "@mattermost/components/src/*", "@mattermost/types/src/*"], - "message": "Don't include the src folder when importing from packages in webapp/platform" - }] - } - ] - } - } - ] -} diff --git a/webapp/channels/eslint.config.mjs b/webapp/channels/eslint.config.mjs new file mode 100644 index 00000000000..c18cb3130c5 --- /dev/null +++ b/webapp/channels/eslint.config.mjs @@ -0,0 +1,86 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import formatjsPlugin from 'eslint-plugin-formatjs'; +import noOnlyTestsPlugin from 'eslint-plugin-no-only-tests'; + +import eslintPlugin from '@mattermost/eslint-plugin'; + +export default [ + ...eslintPlugin.configs.react, + { + plugins: { + formatjs: formatjsPlugin, + }, + rules: { + 'react/prop-types': [ + 2, + { + ignore: [ + 'location', + 'history', + 'component', + ], + }, + ], + 'react/no-unknown-property': [ + 2, + { + ignore: [ + 'mask-type', + ], + }, + ], + 'react/style-prop-object': [2, { + allow: ['Timestamp'], + }], + 'formatjs/enforce-default-message': 2, + 'formatjs/enforce-id': 2, + 'formatjs/enforce-placeholders': 2, + 'formatjs/no-invalid-icu': 2, + 'formatjs/no-multiple-plurals': 1, + 'formatjs/no-multiple-whitespaces': 2, + 'formatjs/no-literal-string-in-jsx': 1, + 'formatjs/prefer-formatted-message': 1, + 'formatjs/no-useless-message': 1, + 'formatjs/prefer-pound-in-plural': 0, + 'react/jsx-fragments': ['error', 'syntax'], + }, + }, + { + files: ['**/*.test.js', '**/*.test.jsx', '**/*.test.ts', '**/*.test.tsx'], + plugins: { + 'no-only-tests': noOnlyTestsPlugin, + }, + rules: { + 'no-only-tests/no-only-tests': ['error', {focus: ['only', 'skip']}], + }, + }, + { + ignores: ['src/packages/mattermost-redux/**'], + rules: { + '@typescript-eslint/no-restricted-imports': [ + 'error', + { + paths: [{ + name: 'mattermost-redux/types/actions', + importNames: ['DispatchFunc', 'GetStateFunc', 'ActionFunc', 'ActionFuncAsync', 'ThunkActionFunc'], + message: 'Use the web app version of it from types/store', + }], + patterns: [{ + group: ['@mattermost/client/src/*', '@mattermost/components/src/*', '@mattermost/types/src/*'], + message: "Don't include the src folder when importing from packages in webapp/platform", + }], + }, + ], + }, + }, + { + settings: { + 'import/resolver': 'webpack', + formatjs: { + additionalFunctionNames: ['localizeMessage', 'defineMessage'], + }, + }, + }, +]; diff --git a/webapp/channels/package.json b/webapp/channels/package.json index 75ab58946d9..3b205b33fff 100644 --- a/webapp/channels/package.json +++ b/webapp/channels/package.json @@ -171,9 +171,9 @@ }, "scripts": { "check": "npm run check:eslint && npm run check:stylelint", - "check:eslint": "eslint --ext .js,.jsx,.tsx,.ts ./src --quiet --cache", + "check:eslint": "eslint ./src eslint.config.mjs --quiet --cache", "check:stylelint": "stylelint \"**/*.{css,scss}\" --cache", - "fix": "eslint --ext .js,.jsx,.tsx,.ts ./src --quiet --fix --cache && stylelint \"**/*.{css,scss}\" --fix --cache", + "fix": "eslint ./src eslint.config.mjs --quiet --fix --cache && stylelint \"**/*.{css,scss}\" --fix --cache", "build": "cross-env NODE_ENV=production webpack", "run": "webpack --progress --watch", "dev-server": "webpack serve --mode development", diff --git a/webapp/platform/client/.eslintrc.json b/webapp/platform/client/.eslintrc.json deleted file mode 100644 index 87330aa3d46..00000000000 --- a/webapp/platform/client/.eslintrc.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "root": true, - "extends": [ - "plugin:@mattermost/base" - ], - "rules": { - - // window isn't defined when using this package in a Node.js app, so prevent people from using it by default - "no-restricted-globals": [ - "error", - "window" - ] - }, - "overrides": [ - { - "files": "*.test.*", - "rules": { - "no-restricted-globals": ["off"] - } - } - ] -} diff --git a/webapp/platform/client/eslint.config.mjs b/webapp/platform/client/eslint.config.mjs new file mode 100644 index 00000000000..21f6e0c9bcf --- /dev/null +++ b/webapp/platform/client/eslint.config.mjs @@ -0,0 +1,23 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import eslintPlugin from '@mattermost/eslint-plugin'; + +export default [ + ...eslintPlugin.configs.base, + { + files: ['**/*.js', '**/*.mjs', '**/*.ts'], + rules: { + 'no-restricted-globals': [ + 'error', + 'window', + ], + }, + }, + { + files: ['**/*.test.js', '**/*.test.ts'], + rules: { + 'no-restricted-globals': 'off', + }, + }, +]; diff --git a/webapp/platform/client/package.json b/webapp/platform/client/package.json index 9122c0c7b02..72fc8cb85bc 100644 --- a/webapp/platform/client/package.json +++ b/webapp/platform/client/package.json @@ -37,7 +37,8 @@ }, "scripts": { "build": "tsc --build tsconfig.build.json --verbose", - "check": "eslint --ext .js,.jsx,.tsx,.ts ./src --quiet", + "check": "eslint ./src eslint.config.mjs --quiet", + "fix": "eslint ./src eslint.config.mjs --quiet --fix", "run": "tsc --watch --preserveWatchOutput", "test": "jest", "test-ci": "jest --ci --forceExit --detectOpenHandles --maxWorkers=100% --logHeapUsage", diff --git a/webapp/platform/components/.eslintrc.json b/webapp/platform/components/.eslintrc.json deleted file mode 100644 index f8c36a3bed9..00000000000 --- a/webapp/platform/components/.eslintrc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "root": true, - "extends": [ - "plugin:@mattermost/base" - ] -} diff --git a/webapp/platform/components/eslint.config.mjs b/webapp/platform/components/eslint.config.mjs new file mode 100644 index 00000000000..0abcb26bfe7 --- /dev/null +++ b/webapp/platform/components/eslint.config.mjs @@ -0,0 +1,8 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import eslintPlugin from '@mattermost/eslint-plugin'; + +export default [ + ...eslintPlugin.configs.base, +]; diff --git a/webapp/platform/components/package.json b/webapp/platform/components/package.json index da8d073967a..0d7bef3b846 100644 --- a/webapp/platform/components/package.json +++ b/webapp/platform/components/package.json @@ -7,8 +7,9 @@ "styles": "dist/index.esm.css", "scripts": { "build": "rollup -c", - "check": "eslint --ext .js,.jsx,.tsx,.ts ./src --quiet", + "check": "eslint ./src eslint.config.mjs --quiet", "check-types": "tsc -b", + "fix": "eslint ./src eslint.config.mjs --quiet --fix", "run": "rollup -c --watch", "test": "cross-env TZ=Etc/UTC jest", "test:updatesnapshot": "cross-env TZ=Etc/UTC jest --updateSnapshot", diff --git a/webapp/platform/eslint-plugin/configs/.eslintrc-react.json b/webapp/platform/eslint-plugin/configs/.eslintrc-react.json deleted file mode 100644 index 5d938cd8c64..00000000000 --- a/webapp/platform/eslint-plugin/configs/.eslintrc-react.json +++ /dev/null @@ -1,171 +0,0 @@ -{ - "extends": [ - "plugin:react/recommended", - "plugin:react-hooks/recommended" - ], - "plugins": [ - "jsx-a11y", - "react" - ], - "settings": { - "react": { - "pragma": "React", - "version": "detect" - } - }, - "rules": { - "jsx-a11y/alt-text": "warn", - "jsx-a11y/anchor-has-content": "error", - "jsx-a11y/anchor-is-valid": "warn", - "jsx-a11y/aria-activedescendant-has-tabindex": "error", - "jsx-a11y/aria-props": "error", - "jsx-a11y/aria-proptypes": "error", - "jsx-a11y/aria-role": "error", - "jsx-a11y/aria-unsupported-elements": "error", - "jsx-a11y/autocomplete-valid": "error", - "jsx-a11y/click-events-have-key-events": "warn", - "jsx-a11y/heading-has-content": "error", - "jsx-a11y/html-has-lang": "error", - "jsx-a11y/iframe-has-title": "error", - "jsx-a11y/img-redundant-alt": "warn", - "jsx-a11y/interactive-supports-focus": "warn", - "jsx-a11y/label-has-associated-control": "error", - "jsx-a11y/media-has-caption": "warn", - "jsx-a11y/mouse-events-have-key-events": "off", - "jsx-a11y/no-access-key": "error", - "jsx-a11y/no-aria-hidden-on-focusable": "error", - "jsx-a11y/no-autofocus": "warn", - "jsx-a11y/no-distracting-elements": "error", - "jsx-a11y/no-interactive-element-to-noninteractive-role": "error", - "jsx-a11y/no-noninteractive-element-interactions": "warn", - "jsx-a11y/no-noninteractive-element-to-interactive-role": "warn", - "jsx-a11y/no-noninteractive-tabindex": "warn", - "jsx-a11y/no-redundant-roles": "warn", - "jsx-a11y/no-static-element-interactions": "warn", - "jsx-a11y/role-has-required-aria-props": "warn", - "jsx-a11y/role-supports-aria-props": "warn", - "jsx-a11y/scope": "error", - "jsx-a11y/tabindex-no-positive": "warn", - "react/display-name": [ - 0, - { - "ignoreTranspilerName": false - } - ], - "react/forbid-component-props": 0, - "react/forbid-elements": [ - 2, - { - "forbid": [ - "embed" - ] - } - ], - "react/jsx-boolean-value": [ - 2, - "always" - ], - "react/jsx-closing-bracket-location": [ - 2, - { - "location": "tag-aligned" - } - ], - "react/jsx-curly-spacing": [ - 2, - "never" - ], - "react/jsx-equals-spacing": [ - 2, - "never" - ], - "react/jsx-filename-extension": [ - 2, - { - "extensions": [ - ".jsx", - ".tsx" - ] - } - ], - "react/jsx-first-prop-new-line": [ - 2, - "multiline" - ], - "react/jsx-handler-names": 0, - "react/jsx-indent": [ - 2, - 4 - ], - "react/jsx-indent-props": [ - 2, - 4 - ], - "react/jsx-key": 2, - "react/jsx-max-props-per-line": [ - 2, - { - "maximum": 1 - } - ], - "react/jsx-no-bind": 0, - "react/jsx-no-comment-textnodes": 2, - "react/jsx-no-duplicate-props": [ - 2, - { - "ignoreCase": false - } - ], - "react/jsx-no-literals": 2, - "react/jsx-no-target-blank": 2, - "react/jsx-no-undef": 2, - "react/jsx-pascal-case": 2, - "react/jsx-tag-spacing": [ - 2, - { - "closingSlash": "never", - "beforeSelfClosing": "never", - "afterOpening": "never" - } - ], - "react/jsx-uses-react": 2, - "react/jsx-uses-vars": 2, - "react/jsx-wrap-multilines": 2, - "react/no-array-index-key": 1, - "react/no-children-prop": 2, - "react/no-danger": 0, - "react/no-danger-with-children": 2, - "react/no-deprecated": 1, - "react/no-did-mount-set-state": 2, - "react/no-did-update-set-state": 2, - "react/no-direct-mutation-state": 2, - "react/no-find-dom-node": 1, - "react/no-is-mounted": 2, - "react/no-multi-comp": [ - 2, - { - "ignoreStateless": true - } - ], - "react/no-render-return-value": 2, - "react/no-set-state": 0, - "react/no-string-refs": 2, - "react/no-unescaped-entities": 2, - "react/no-unknown-property": 2, - "react/no-unused-prop-types": [ - 1, - { - "skipShapeProps": true - } - ], - "react/prefer-es6-class": 2, - "react/prefer-stateless-function": 0, - "react/prop-types": 2, - "react/require-default-props": 0, - "react/require-optimization": 1, - "react/require-render-return": 2, - "react/self-closing-comp": 2, - "react/sort-comp": 0, - "react/style-prop-object": 2 - } -} diff --git a/webapp/platform/eslint-plugin/configs/.eslintrc.json b/webapp/platform/eslint-plugin/configs/.eslintrc.json deleted file mode 100644 index 232e20ae4cb..00000000000 --- a/webapp/platform/eslint-plugin/configs/.eslintrc.json +++ /dev/null @@ -1,595 +0,0 @@ -{ - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended" - ], - "parserOptions": { - "ecmaVersion": 8, - "sourceType": "module", - "ecmaFeatures": { - "jsx": true, - "impliedStrict": true, - "modules": true - } - }, - "parser": "@typescript-eslint/parser", - "plugins": [ - "@mattermost", - "@typescript-eslint", - "header", - "import" - ], - "env": { - "browser": true, - "node": true, - "jquery": true, - "es6": true - }, - "rules": { - "@mattermost/no-dispatch-getstate": 2, - "@mattermost/use-external-link": 2, - "@typescript-eslint/array-type": [2, {"default": "array-simple"}], - "@typescript-eslint/consistent-type-imports": ["error", {"disallowTypeAnnotations": false}], - "@typescript-eslint/explicit-function-return-type": 0, - "@typescript-eslint/explicit-module-boundary-types": 0, - "@typescript-eslint/indent": [ - 2, - 4, - { - "SwitchCase": 0 - } - ], - "@typescript-eslint/member-delimiter-style": 2, - "@typescript-eslint/naming-convention": [ - 2, - { - "selector": "function", - "format": ["camelCase", "PascalCase"] - }, - { - "selector": "variable", - "format": ["camelCase", "PascalCase", "UPPER_CASE"] - }, - { - "selector": "parameter", - "format": ["camelCase", "PascalCase"], - "leadingUnderscore": "allow" - }, - { - "selector": "typeLike", - "format": ["PascalCase"] - } - ], - "@typescript-eslint/no-dupe-class-members": 2, - "@typescript-eslint/no-empty-function": 0, - "@typescript-eslint/no-explicit-any": "warn", - "@typescript-eslint/no-unused-vars": [ - 2, - { - "vars": "all", - "args": "after-used" - } - ], - "@typescript-eslint/no-use-before-define": [ - 2, - { - "classes": false, - "functions": false, - "variables": false - } - ], - "@typescript-eslint/no-var-requires": 0, - "@typescript-eslint/type-annotation-spacing": 2, - "array-bracket-spacing": [ - 2, - "never" - ], - "array-callback-return": 2, - "arrow-body-style": 0, - "arrow-parens": [ - 2, - "always" - ], - "arrow-spacing": [ - 2, - { - "before": true, - "after": true - } - ], - "block-scoped-var": 2, - "brace-style": [ - 2, - "1tbs", - { - "allowSingleLine": false - } - ], - "camelcase": 0, // Handled by @typescript-eslint/naming-convention - "capitalized-comments": 0, - "class-methods-use-this": 0, - "comma-dangle": [ - 2, - "always-multiline" - ], - "comma-spacing": [ - 2, - { - "before": false, - "after": true - } - ], - "comma-style": [ - 2, - "last" - ], - "complexity": [ - 0, - 10 - ], - "computed-property-spacing": [ - 2, - "never" - ], - "consistent-return": 2, - "consistent-this": [ - 2, - "self" - ], - "constructor-super": 2, - "curly": [ - 2, - "all" - ], - "dot-location": [ - 2, - "object" - ], - "dot-notation": 2, - "eol-last": ["error", "always"], - "eqeqeq": [ - 2, - "smart" - ], - "func-call-spacing": [ - 2, - "never" - ], - "func-name-matching": 0, - "func-names": 2, - "func-style": [ - 2, - "declaration", - { - "allowArrowFunctions": true - } - ], - "generator-star-spacing": [ - 2, - { - "before": false, - "after": true - } - ], - "global-require": 2, - "guard-for-in": 2, - "header/header": [ - 2, - "line", - " Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.\n See LICENSE.txt for license information.", - 2 - ], - "id-blacklist": 0, - "import/no-duplicates": 2, - "import/no-unresolved": 0, // Handled better by TS - "import/order": [ - 2, - { - "newlines-between": "always", - "groups": [ - "builtin", - "external", - "internal", - "sibling", - "parent", - "index" - ], - "pathGroups": [ - { - "pattern": "@mattermost/**", - "group": "external", - "position": "after" - }, - { - "pattern": "mattermost-redux/**", - "group": "external", - "position": "after" - }, - { - "pattern": "@(selectors|actions|stores|store|reducers){,/**}", - "group": "external", - "position": "after" - }, - { - "pattern": "components/**", - "group": "external", - "position": "after" - }, - { - "pattern": "types{,/**}", - "group": "internal", - "position": "after" - } - ], - "alphabetize": { - "order": "asc", - "caseInsensitive": true - }, - "distinctGroup": true, - "pathGroupsExcludedImportTypes": ["builtin"] - } - ], - "indent": 0, // Handled by @typescript-eslint/indent - "jsx-quotes": [ - 2, - "prefer-single" - ], - "key-spacing": [ - 2, - { - "beforeColon": false, - "afterColon": true, - "mode": "strict" - } - ], - "keyword-spacing": [ - 2, - { - "before": true, - "after": true, - "overrides": {} - } - ], - "line-comment-position": 0, - "linebreak-style": 2, - "lines-around-comment": [ - 2, - { - "beforeBlockComment": true, - "beforeLineComment": true, - "allowBlockStart": true, - "allowBlockEnd": true - } - ], - "max-lines": [ - "warn", - { - "max": 800, - "skipBlankLines": true, - "skipComments": false - } - ], - "max-nested-callbacks": ["error", 10], - "max-statements-per-line": [ - 2, - { - "max": 1 - } - ], - "multiline-ternary": [ - 1, - "never" - ], - "new-cap": 2, - "new-parens": 2, - "newline-before-return": 0, - "newline-per-chained-call": 0, - "no-alert": 2, - "no-array-constructor": 2, - "no-await-in-loop": 2, - "no-caller": 2, - "no-case-declarations": 2, - "no-class-assign": 2, - "no-compare-neg-zero": 2, - "no-cond-assign": [ - 2, - "except-parens" - ], - "no-confusing-arrow": 2, - "no-console": 2, - "no-const-assign": 2, - "no-constant-binary-expression": 2, - "no-constant-condition": 2, - "no-debugger": 2, - "no-div-regex": 2, - "no-dupe-args": 2, - "no-dupe-class-members": 0, // Handled by @typescript-eslint/no-dupe-class-members - "no-dupe-keys": 2, - "no-duplicate-case": 2, - "no-duplicate-imports": 0, // Handled by import/no-duplicates - "no-else-return": 2, - "no-empty": 2, - "no-empty-function": 0, - "no-empty-pattern": 2, - "no-eval": 2, - "no-ex-assign": 2, - "no-extend-native": 2, - "no-extra-bind": 2, - "no-extra-label": 2, - "no-extra-parens": 0, - "no-extra-semi": 2, - "no-fallthrough": 2, - "no-floating-decimal": 2, - "no-func-assign": 2, - "no-global-assign": 2, - "no-implicit-coercion": 2, - "no-implicit-globals": 0, - "no-implied-eval": 2, - "no-inner-declarations": 0, - "no-invalid-regexp": 2, - "no-irregular-whitespace": 2, - "no-iterator": 2, - "no-labels": 2, - "no-lone-blocks": 2, - "no-lonely-if": 2, - "no-loop-func": 2, - "no-magic-numbers": 0, - "no-mixed-operators": [ - 2, - { - "allowSamePrecedence": false - } - ], - "no-mixed-spaces-and-tabs": 2, - "no-multi-assign": 2, - "no-multi-spaces": [ - 2, - { - "exceptions": { - "Property": false - } - } - ], - "no-multi-str": 0, - "no-multiple-empty-lines": [ - 2, - { - "max": 1 - } - ], - "no-native-reassign": 2, - "no-negated-condition": 2, - "no-nested-ternary": 2, - "no-new": 2, - "no-new-func": 2, - "no-new-object": 2, - "no-new-symbol": 2, - "no-new-wrappers": 2, - "no-octal-escape": 2, - "no-param-reassign": 2, - "no-process-env": 2, - "no-process-exit": 2, - "no-proto": 2, - "no-prototype-builtins": 2, - "no-restricted-imports": [ - "error", - { - "paths": [ - { - "name": "redux", - "importNames": ["DeepPartial"], - "message": "Use DeepPartial from '@mattermost/types/utilities instead." - }, - { - "name": "lodash", - "message": "Import individual functions from lodash/ instead." - } - ] - } - ], - "no-return-assign": [ - 2, - "always" - ], - "no-return-await": 2, - "no-script-url": 2, - "no-self-assign": [ - 2, - { - "props": true - } - ], - "no-self-compare": 2, - "no-sequences": 2, - "no-shadow": 0, // This isn't currently enabled, but it probably should be - "no-shadow-restricted-names": 2, - "no-spaced-func": 2, - "no-tabs": 0, - "no-template-curly-in-string": 2, - "no-ternary": 0, - "no-this-before-super": 2, - "no-throw-literal": 2, - "no-trailing-spaces": [ - 2, - { - "skipBlankLines": false - } - ], - "no-undef-init": 2, - "no-undefined": 0, - "no-underscore-dangle": 2, - "no-unexpected-multiline": 2, - "no-unmodified-loop-condition": 2, - "no-unneeded-ternary": [ - 2, - { - "defaultAssignment": false - } - ], - "no-unreachable": 2, - "no-unsafe-finally": 2, - "no-unsafe-negation": 2, - "no-unused-expressions": 2, - "no-unused-vars": 0, // Handled by @typescript-eslint/no-unused-vars - "no-use-before-define": 0, // Handled by @typescript-eslint/no-use-before-define - "no-useless-computed-key": 2, - "no-useless-concat": 2, - "no-useless-constructor": 2, - "no-useless-escape": 2, - "no-useless-rename": 2, - "no-useless-return": 2, - "no-var": 0, - "no-void": 2, - "no-warning-comments": 1, - "no-whitespace-before-property": 2, - "no-with": 2, - "object-curly-newline": 0, - "object-curly-spacing": [ - 2, - "never" - ], - "object-property-newline": [ - 2, - { - "allowMultiplePropertiesPerLine": true - } - ], - "object-shorthand": [ - 2, - "always" - ], - "one-var": [ - 2, - "never" - ], - "one-var-declaration-per-line": 0, - "operator-assignment": [ - 2, - "always" - ], - "operator-linebreak": [ - 2, - "after" - ], - "padded-blocks": [ - 2, - "never" - ], - "prefer-arrow-callback": 2, - "prefer-const": 2, - "prefer-destructuring": 0, - "prefer-numeric-literals": 2, - "prefer-promise-reject-errors": 2, - "prefer-rest-params": 2, - "prefer-spread": 2, - "prefer-template": 0, - "quote-props": [ - 2, - "as-needed" - ], - "quotes": [ - 2, - "single", - "avoid-escape" - ], - "radix": 2, - "require-yield": 2, - "rest-spread-spacing": [ - 2, - "never" - ], - "semi": [ - 2, - "always" - ], - "semi-spacing": [ - 2, - { - "before": false, - "after": true - } - ], - "sort-imports": 0, - "sort-keys": 0, - "space-before-blocks": [ - 2, - "always" - ], - "space-before-function-paren": [ - 2, - { - "anonymous": "never", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - 2, - "never" - ], - "space-infix-ops": 2, - "space-unary-ops": [ - 2, - { - "words": true, - "nonwords": false - } - ], - "symbol-description": 2, - "template-curly-spacing": [ - 2, - "never" - ], - "valid-typeof": [ - 2, - { - "requireStringLiterals": false - } - ], - "vars-on-top": 0, - "wrap-iife": [ - 2, - "outside" - ], - "wrap-regex": 2, - "yoda": [ - 2, - "never", - { - "exceptRange": false, - "onlyEquality": false - } - ] - }, - "overrides": [ - { - "files": ["*.test.*", "src/tests/**"], - "env": { - "jest": true - }, - "globals": { - "after": true, - "afterAll": true, - "afterEach": true, - "before": true, - "beforeAll": true, - "beforeEach": true, - "describe": true, - "expect": true, - "it": true, - "jest": true, - "test": true - }, - "rules": { - "func-names": 0, - "global-require": 0, - "no-console": 0, - "no-import-assign": 0, - "max-lines": 0, - "max-nested-callbacks": 0, - "new-cap": 0, - "prefer-arrow-callback": 0 - } - } - ] -} diff --git a/webapp/platform/eslint-plugin/configs/base.js b/webapp/platform/eslint-plugin/configs/base.js new file mode 100644 index 00000000000..2b935d6ebe9 --- /dev/null +++ b/webapp/platform/eslint-plugin/configs/base.js @@ -0,0 +1,624 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import path from 'path'; +import {fileURLToPath} from 'url'; + +import {FlatCompat} from '@eslint/eslintrc'; +import js from '@eslint/js'; +import typescriptPlugin from '@typescript-eslint/eslint-plugin'; +import typescriptParser from '@typescript-eslint/parser'; +import headerPlugin from 'eslint-plugin-header'; +import importPlugin from 'eslint-plugin-import'; +import globals from 'globals'; + +import rules from '../rules/index.js'; + +const filename = fileURLToPath(import.meta.url); +const dirname = path.dirname(filename); + +const compat = new FlatCompat({ + baseDirectory: dirname, +}); + +const base = { + files: ['**/*.js', '**/*.jsx', '**/*.mjs', '**/*.ts', '**/*.tsx'], + languageOptions: { + ecmaVersion: 8, + globals: { + ...globals.browser, + ...globals.node, + ...globals.es6, + }, + parser: typescriptParser, + parserOptions: { + ecmaFeatures: { + jsx: true, + impliedStrict: true, + modules: true, + }, + }, + sourceType: 'module', + }, + plugins: { + '@mattermost': { + rules, + }, + typescript: typescriptPlugin, + header: headerPlugin, + import: importPlugin, + }, + rules: { + + // '@mattermost/no-dispatch-getstate': 2, + // '@mattermost/use-external-link': 2, + '@typescript-eslint/array-type': [2, {default: 'array-simple'}], + '@typescript-eslint/consistent-type-imports': ['error', {disallowTypeAnnotations: false}], + '@typescript-eslint/explicit-function-return-type': 0, + '@typescript-eslint/explicit-module-boundary-types': 0, + '@typescript-eslint/indent': [ + 2, + 4, + { + SwitchCase: 0, + }, + ], + '@typescript-eslint/member-delimiter-style': 2, + '@typescript-eslint/naming-convention': [ + 2, + { + selector: 'function', + format: ['camelCase', 'PascalCase'], + }, + { + selector: 'variable', + format: ['camelCase', 'PascalCase', 'UPPER_CASE'], + }, + { + selector: 'parameter', + format: ['camelCase', 'PascalCase'], + leadingUnderscore: 'allow', + }, + { + selector: 'typeLike', + format: ['PascalCase'], + }, + ], + '@typescript-eslint/no-dupe-class-members': 2, + '@typescript-eslint/no-empty-function': 0, + '@typescript-eslint/no-explicit-any': 'warn', + '@typescript-eslint/no-unused-vars': [ + 2, + { + vars: 'all', + args: 'after-used', + }, + ], + '@typescript-eslint/no-use-before-define': [ + 2, + { + classes: false, + functions: false, + variables: false, + }, + ], + '@typescript-eslint/no-var-requires': 0, + '@typescript-eslint/type-annotation-spacing': 2, + 'array-bracket-spacing': [ + 2, + 'never', + ], + 'array-callback-return': 2, + 'arrow-body-style': 0, + 'arrow-parens': [ + 2, + 'always', + ], + 'arrow-spacing': [ + 2, + { + before: true, + after: true, + }, + ], + 'block-scoped-var': 2, + 'brace-style': [ + 2, + '1tbs', + { + allowSingleLine: false, + }, + ], + camelcase: 0, // Handled by @typescript-eslint/naming-convention + 'capitalized-comments': 0, + 'class-methods-use-this': 0, + 'comma-dangle': [ + 2, + 'always-multiline', + ], + 'comma-spacing': [ + 2, + { + before: false, + after: true, + }, + ], + 'comma-style': [ + 2, + 'last', + ], + complexity: [ + 0, + 10, + ], + 'computed-property-spacing': [ + 2, + 'never', + ], + 'consistent-return': 2, + 'consistent-this': [ + 2, + 'self', + ], + 'constructor-super': 2, + curly: [ + 2, + 'all', + ], + 'dot-location': [ + 2, + 'object', + ], + 'dot-notation': 2, + 'eol-last': ['error', 'always'], + eqeqeq: [ + 2, + 'smart', + ], + 'func-call-spacing': [ + 2, + 'never', + ], + 'func-name-matching': 0, + 'func-names': 2, + 'func-style': [ + 2, + 'declaration', + { + allowArrowFunctions: true, + }, + ], + 'generator-star-spacing': [ + 2, + { + before: false, + after: true, + }, + ], + 'global-require': 2, + 'guard-for-in': 2, + 'header/header': [ + 2, + 'line', + ' Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.\n See LICENSE.txt for license information.', + 2, + ], + 'id-blacklist': 0, + 'import/no-duplicates': 2, + 'import/no-unresolved': 0, // Handled better by TS + 'import/order': [ + 2, + { + 'newlines-between': 'always', + groups: [ + 'builtin', + 'external', + 'internal', + 'sibling', + 'parent', + 'index', + ], + pathGroups: [ + { + pattern: '@mattermost/**', + group: 'external', + position: 'after', + }, + { + pattern: 'mattermost-redux/**', + group: 'external', + position: 'after', + }, + { + pattern: '@(selectors|actions|stores|store|reducers){,/**}', + group: 'external', + position: 'after', + }, + { + pattern: 'components/**', + group: 'external', + position: 'after', + }, + { + pattern: 'types{,/**}', + group: 'internal', + position: 'after', + }, + ], + alphabetize: { + order: 'asc', + caseInsensitive: true, + }, + distinctGroup: true, + pathGroupsExcludedImportTypes: ['builtin'], + }, + ], + indent: 0, // Handled by @typescript-eslint/indent + 'jsx-quotes': [ + 2, + 'prefer-single', + ], + 'key-spacing': [ + 2, + { + beforeColon: false, + afterColon: true, + mode: 'strict', + }, + ], + 'keyword-spacing': [ + 2, + { + before: true, + after: true, + overrides: {}, + }, + ], + 'line-comment-position': 0, + 'linebreak-style': 2, + 'lines-around-comment': [ + 2, + { + beforeBlockComment: true, + beforeLineComment: true, + allowBlockStart: true, + allowBlockEnd: true, + }, + ], + 'max-lines': [ + 'warn', + { + max: 800, + skipBlankLines: true, + skipComments: false, + }, + ], + 'max-nested-callbacks': ['error', 10], + 'max-statements-per-line': [ + 2, + { + max: 1, + }, + ], + 'multiline-ternary': [ + 1, + 'never', + ], + 'new-cap': 2, + 'new-parens': 2, + 'newline-before-return': 0, + 'newline-per-chained-call': 0, + 'no-alert': 2, + 'no-array-constructor': 2, + 'no-await-in-loop': 2, + 'no-caller': 2, + 'no-case-declarations': 2, + 'no-class-assign': 2, + 'no-compare-neg-zero': 2, + 'no-cond-assign': [ + 2, + 'except-parens', + ], + 'no-confusing-arrow': 2, + 'no-console': 2, + 'no-const-assign': 2, + 'no-constant-binary-expression': 2, + 'no-constant-condition': 2, + 'no-debugger': 2, + 'no-div-regex': 2, + 'no-dupe-args': 2, + 'no-dupe-class-members': 0, // Handled by @typescript-eslint/no-dupe-class-members + 'no-dupe-keys': 2, + 'no-duplicate-case': 2, + 'no-duplicate-imports': 0, // Handled by import/no-duplicates + 'no-else-return': 2, + 'no-empty': 2, + 'no-empty-function': 0, + 'no-empty-pattern': 2, + 'no-eval': 2, + 'no-ex-assign': 2, + 'no-extend-native': 2, + 'no-extra-bind': 2, + 'no-extra-label': 2, + 'no-extra-parens': 0, + 'no-extra-semi': 2, + 'no-fallthrough': 2, + 'no-floating-decimal': 2, + 'no-func-assign': 2, + 'no-global-assign': 2, + 'no-implicit-coercion': 2, + 'no-implicit-globals': 0, + 'no-implied-eval': 2, + 'no-inner-declarations': 0, + 'no-invalid-regexp': 2, + 'no-irregular-whitespace': 2, + 'no-iterator': 2, + 'no-labels': 2, + 'no-lone-blocks': 2, + 'no-lonely-if': 2, + 'no-loop-func': 2, + 'no-magic-numbers': 0, + 'no-mixed-operators': [ + 2, + { + allowSamePrecedence: false, + }, + ], + 'no-mixed-spaces-and-tabs': 2, + 'no-multi-assign': 2, + 'no-multi-spaces': [ + 2, + { + exceptions: { + Property: false, + }, + }, + ], + 'no-multi-str': 0, + 'no-multiple-empty-lines': [ + 2, + { + max: 1, + }, + ], + 'no-native-reassign': 2, + 'no-negated-condition': 2, + 'no-nested-ternary': 2, + 'no-new': 2, + 'no-new-func': 2, + 'no-new-object': 2, + 'no-new-symbol': 2, + 'no-new-wrappers': 2, + 'no-octal-escape': 2, + 'no-param-reassign': 2, + 'no-process-env': 2, + 'no-process-exit': 2, + 'no-proto': 2, + 'no-prototype-builtins': 2, + 'no-restricted-imports': [ + 'error', + { + paths: [ + { + name: 'redux', + importNames: ['DeepPartial'], + message: 'Use DeepPartial from @mattermost/types/utilities instead.', + }, + { + name: 'lodash', + message: 'Import individual functions from lodash/ instead.', + }, + ], + }, + ], + 'no-return-assign': [ + 2, + 'always', + ], + 'no-return-await': 2, + 'no-script-url': 2, + 'no-self-assign': [ + 2, + { + props: true, + }, + ], + 'no-self-compare': 2, + 'no-sequences': 2, + 'no-shadow': 0, // This isn't currently enabled, but it probably should be + 'no-shadow-restricted-names': 2, + 'no-spaced-func': 2, + 'no-tabs': 0, + 'no-template-curly-in-string': 2, + 'no-ternary': 0, + 'no-this-before-super': 2, + 'no-throw-literal': 2, + 'no-trailing-spaces': [ + 2, + { + skipBlankLines: false, + }, + ], + 'no-undef-init': 2, + 'no-undefined': 0, + 'no-underscore-dangle': 2, + 'no-unexpected-multiline': 2, + 'no-unmodified-loop-condition': 2, + 'no-unneeded-ternary': [ + 2, + { + defaultAssignment: false, + }, + ], + 'no-unreachable': 2, + 'no-unsafe-finally': 2, + 'no-unsafe-negation': 2, + 'no-unused-expressions': 2, + 'no-unused-vars': 0, // Handled by @typescript-eslint/no-unused-vars + 'no-use-before-define': 0, // Handled by @typescript-eslint/no-use-before-define + 'no-useless-computed-key': 2, + 'no-useless-concat': 2, + 'no-useless-constructor': 2, + 'no-useless-escape': 2, + 'no-useless-rename': 2, + 'no-useless-return': 2, + 'no-var': 0, + 'no-void': 2, + 'no-warning-comments': 1, + 'no-whitespace-before-property': 2, + 'no-with': 2, + 'object-curly-newline': 0, + 'object-curly-spacing': [ + 2, + 'never', + ], + 'object-property-newline': [ + 2, + { + allowMultiplePropertiesPerLine: true, + }, + ], + 'object-shorthand': [ + 2, + 'always', + ], + 'one-var': [ + 2, + 'never', + ], + 'one-var-declaration-per-line': 0, + 'operator-assignment': [ + 2, + 'always', + ], + 'operator-linebreak': [ + 2, + 'after', + ], + 'padded-blocks': [ + 2, + 'never', + ], + 'prefer-arrow-callback': 2, + 'prefer-const': 2, + 'prefer-destructuring': 0, + 'prefer-numeric-literals': 2, + 'prefer-promise-reject-errors': 2, + 'prefer-rest-params': 2, + 'prefer-spread': 2, + 'prefer-template': 0, + 'quote-props': [ + 2, + 'as-needed', + ], + quotes: [ + 2, + 'single', + 'avoid-escape', + ], + radix: 2, + 'require-yield': 2, + 'rest-spread-spacing': [ + 2, + 'never', + ], + semi: [ + 2, + 'always', + ], + 'semi-spacing': [ + 2, + { + before: false, + after: true, + }, + ], + 'sort-imports': 0, + 'sort-keys': 0, + 'space-before-blocks': [ + 2, + 'always', + ], + 'space-before-function-paren': [ + 2, + { + anonymous: 'never', + named: 'never', + asyncArrow: 'always', + }, + ], + 'space-in-parens': [ + 2, + 'never', + ], + 'space-infix-ops': 2, + 'space-unary-ops': [ + 2, + { + words: true, + nonwords: false, + }, + ], + 'symbol-description': 2, + 'template-curly-spacing': [ + 2, + 'never', + ], + 'valid-typeof': [ + 2, + { + requireStringLiterals: false, + }, + ], + 'vars-on-top': 0, + 'wrap-iife': [ + 2, + 'outside', + ], + 'wrap-regex': 2, + yoda: [ + 2, + 'never', + { + exceptRange: false, + onlyEquality: false, + }, + ], + }, +}; + +const testOverrides = { + files: ['**/*.test.js', '**/*.test.jsx', '**/*.test.ts', '**/*.test.tsx', 'src/tests/**'], + languageOptions: { + globals: { + after: true, + afterAll: true, + afterEach: true, + before: true, + beforeAll: true, + beforeEach: true, + describe: true, + expect: true, + it: true, + jest: true, + test: true, + }, + }, + rules: { + 'func-names': 0, + 'global-require': 0, + 'no-console': 0, + 'no-import-assign': 0, + 'max-lines': 0, + 'max-nested-callbacks': 0, + 'new-cap': 0, + 'prefer-arrow-callback': 0, + }, +}; + +export default [ + js.configs.recommended, + ...compat.extends('plugin:@typescript-eslint/recommended'), + base, + testOverrides, +]; diff --git a/webapp/platform/eslint-plugin/configs/react.js b/webapp/platform/eslint-plugin/configs/react.js new file mode 100644 index 00000000000..57198055f2b --- /dev/null +++ b/webapp/platform/eslint-plugin/configs/react.js @@ -0,0 +1,192 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import path from 'path'; +import {fileURLToPath} from 'url'; + +import {FlatCompat} from '@eslint/eslintrc'; +import jsxA11yPlugin from 'eslint-plugin-jsx-a11y'; + +import base from './base.js'; + +const filename = fileURLToPath(import.meta.url); +const dirname = path.dirname(filename); + +const compat = new FlatCompat({ + baseDirectory: dirname, +}); + +const react = { + files: ['**/*.jsx', '**/*.tsx'], + rules: { + 'jsx-a11y/alt-text': 'warn', + 'jsx-a11y/anchor-has-content': 'error', + 'jsx-a11y/anchor-is-valid': 'warn', + 'jsx-a11y/aria-activedescendant-has-tabindex': 'error', + 'jsx-a11y/aria-props': 'error', + 'jsx-a11y/aria-proptypes': 'error', + 'jsx-a11y/aria-role': 'error', + 'jsx-a11y/aria-unsupported-elements': 'error', + 'jsx-a11y/autocomplete-valid': 'error', + 'jsx-a11y/click-events-have-key-events': 'warn', + 'jsx-a11y/heading-has-content': 'error', + 'jsx-a11y/html-has-lang': 'error', + 'jsx-a11y/iframe-has-title': 'error', + 'jsx-a11y/img-redundant-alt': 'warn', + 'jsx-a11y/interactive-supports-focus': 'warn', + 'jsx-a11y/label-has-associated-control': 'error', + 'jsx-a11y/media-has-caption': 'warn', + 'jsx-a11y/mouse-events-have-key-events': 'off', + 'jsx-a11y/no-access-key': 'error', + 'jsx-a11y/no-aria-hidden-on-focusable': 'error', + 'jsx-a11y/no-autofocus': 'warn', + 'jsx-a11y/no-distracting-elements': 'error', + 'jsx-a11y/no-interactive-element-to-noninteractive-role': 'error', + 'jsx-a11y/no-noninteractive-element-interactions': 'warn', + 'jsx-a11y/no-noninteractive-element-to-interactive-role': 'warn', + 'jsx-a11y/no-noninteractive-tabindex': 'warn', + 'jsx-a11y/no-redundant-roles': 'warn', + 'jsx-a11y/no-static-element-interactions': 'warn', + 'jsx-a11y/role-has-required-aria-props': 'warn', + 'jsx-a11y/role-supports-aria-props': 'warn', + 'jsx-a11y/scope': 'error', + 'jsx-a11y/tabindex-no-positive': 'warn', + 'react/display-name': [ + 0, + { + ignoreTranspilerName: false, + }, + ], + 'react/forbid-component-props': 0, + 'react/forbid-elements': [ + 2, + { + forbid: [ + 'embed', + ], + }, + ], + 'react/jsx-boolean-value': [ + 2, + 'always', + ], + 'react/jsx-closing-bracket-location': [ + 2, + { + location: 'tag-aligned', + }, + ], + 'react/jsx-curly-spacing': [ + 2, + 'never', + ], + 'react/jsx-equals-spacing': [ + 2, + 'never', + ], + 'react/jsx-filename-extension': [ + 2, + { + extensions: [ + '.jsx', + '.tsx', + ], + }, + ], + 'react/jsx-first-prop-new-line': [ + 2, + 'multiline', + ], + 'react/jsx-handler-names': 0, + 'react/jsx-indent': [ + 2, + 4, + ], + 'react/jsx-indent-props': [ + 2, + 4, + ], + 'react/jsx-key': 2, + 'react/jsx-max-props-per-line': [ + 2, + { + maximum: 1, + }, + ], + 'react/jsx-no-bind': 0, + 'react/jsx-no-comment-textnodes': 2, + 'react/jsx-no-duplicate-props': [ + 2, + { + ignoreCase: false, + }, + ], + 'react/jsx-no-literals': 2, + 'react/jsx-no-target-blank': 2, + 'react/jsx-no-undef': 2, + 'react/jsx-pascal-case': 2, + 'react/jsx-tag-spacing': [ + 2, + { + closingSlash: 'never', + beforeSelfClosing: 'never', + afterOpening: 'never', + }, + ], + 'react/jsx-uses-react': 2, + 'react/jsx-uses-vars': 2, + 'react/jsx-wrap-multilines': 2, + 'react/no-array-index-key': 1, + 'react/no-children-prop': 2, + 'react/no-danger': 0, + 'react/no-danger-with-children': 2, + 'react/no-deprecated': 1, + 'react/no-did-mount-set-state': 2, + 'react/no-did-update-set-state': 2, + 'react/no-direct-mutation-state': 2, + 'react/no-find-dom-node': 1, + 'react/no-is-mounted': 2, + 'react/no-multi-comp': [ + 2, + { + ignoreStateless: true, + }, + ], + 'react/no-render-return-value': 2, + 'react/no-set-state': 0, + 'react/no-string-refs': 2, + 'react/no-unescaped-entities': 2, + 'react/no-unknown-property': 2, + 'react/no-unused-prop-types': [ + 1, + { + skipShapeProps: true, + }, + ], + 'react/prefer-es6-class': 2, + 'react/prefer-stateless-function': 0, + 'react/prop-types': 2, + 'react/require-default-props': 0, + 'react/require-optimization': 1, + 'react/require-render-return': 2, + 'react/self-closing-comp': 2, + 'react/sort-comp': 0, + 'react/style-prop-object': 2, + }, +}; + +export default [ + ...base, + jsxA11yPlugin.flatConfigs.recommended, + ...compat.extends('plugin:react/recommended'), + ...compat.extends('plugin:react-hooks/recommended'), + react, + { + settings: { + react: { + pragma: 'React', + version: 'detect', + }, + }, + }, +]; diff --git a/webapp/platform/eslint-plugin/eslint.config.mjs b/webapp/platform/eslint-plugin/eslint.config.mjs new file mode 100644 index 00000000000..0abcb26bfe7 --- /dev/null +++ b/webapp/platform/eslint-plugin/eslint.config.mjs @@ -0,0 +1,8 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import eslintPlugin from '@mattermost/eslint-plugin'; + +export default [ + ...eslintPlugin.configs.base, +]; diff --git a/webapp/platform/eslint-plugin/index.js b/webapp/platform/eslint-plugin/index.js index 4618d061350..bbc7cdb1f1e 100644 --- a/webapp/platform/eslint-plugin/index.js +++ b/webapp/platform/eslint-plugin/index.js @@ -1,21 +1,14 @@ -"use strict"; +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. -module.exports = { +import base from './configs/base.js'; +import react from './configs/react.js'; +import rules from './rules/index.js'; + +export default { configs: { - base: { - extends: [ - require.resolve('./configs/.eslintrc.json'), - ], - }, - react: { - extends: [ - require.resolve('./configs/.eslintrc.json'), - require.resolve('./configs/.eslintrc-react.json'), - ], - }, - }, - rules: { - 'no-dispatch-getstate': require('./rules/no-dispatch-getstate'), - 'use-external-link': require('./rules/use-external-link'), + base, + react, }, + rules, }; diff --git a/webapp/platform/eslint-plugin/package.json b/webapp/platform/eslint-plugin/package.json index e6c62cc5a5d..c38205b7ad7 100644 --- a/webapp/platform/eslint-plugin/package.json +++ b/webapp/platform/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@mattermost/eslint-plugin", - "version": "1.1.0", + "version": "2.0.0", "description": "ESLint configuration and custom rules used by Mattermost", "repository": { "type": "git", @@ -10,7 +10,12 @@ "author": "Mattermost, Inc.", "license": "Apache 2.0", "homepage": "https://github.com/mattermost/mattermost/tree/master/webapp/platform/eslint-plugin#readme", - "main": "index.js", + "type": "module", + "exports": { + ".": { + "import": "./index.js" + } + }, "dependencies": { "@typescript-eslint/eslint-plugin": "^7.1.0", "@typescript-eslint/parser": "^7.1.0", @@ -32,6 +37,8 @@ } }, "scripts": { + "check": "eslint . --quiet", + "fix": "eslint . --quiet --fix", "clean": "rm -rf node_modules" } } diff --git a/webapp/platform/eslint-plugin/rules/index.js b/webapp/platform/eslint-plugin/rules/index.js new file mode 100644 index 00000000000..f7c527f68fe --- /dev/null +++ b/webapp/platform/eslint-plugin/rules/index.js @@ -0,0 +1,10 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import noDispatchGetState from './no-dispatch-getstate.js'; +import useExternalLink from './use-external-link.js'; + +export default { + 'no-dispatch-getstate': noDispatchGetState, + 'use-external-link': useExternalLink, +}; diff --git a/webapp/platform/eslint-plugin/rules/no-dispatch-getstate.js b/webapp/platform/eslint-plugin/rules/no-dispatch-getstate.js index 69f26cb5d2c..fdf44ebbd04 100644 --- a/webapp/platform/eslint-plugin/rules/no-dispatch-getstate.js +++ b/webapp/platform/eslint-plugin/rules/no-dispatch-getstate.js @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -module.exports = { +export default { meta: { type: 'problem', fixable: 'code', diff --git a/webapp/platform/eslint-plugin/rules/use-external-link.js b/webapp/platform/eslint-plugin/rules/use-external-link.js index a55bea884fc..5f072cb7bea 100644 --- a/webapp/platform/eslint-plugin/rules/use-external-link.js +++ b/webapp/platform/eslint-plugin/rules/use-external-link.js @@ -1,22 +1,20 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -const astUtils = require('jsx-ast-utils') -const getElementType = require('eslint-plugin-jsx-a11y/lib/util/getElementType') +import astUtils from 'jsx-ast-utils'; -module.exports = { +export default { meta: { docs: { description: 'Enforce all anchors with target="_blank" to use ExternalLink component', }, }, create: (context) => { - const elementType = getElementType(context); return { JSXOpeningElement: (node) => { - const { attributes } = node; const typeCheck = 'a'; - const nodeType = elementType(node); + const nodeType = astUtils.elementType(node); + // Only check anchor elements if (!nodeType || typeCheck !== nodeType) { return; @@ -24,6 +22,7 @@ module.exports = { const propsToValidate = ['target']; const values = propsToValidate.map((prop) => astUtils.getPropValue(astUtils.getProp(node.attributes, prop))); + // Checks if the target attribute is set to _blank (ie, is an external link) const hasBlankTarget = values.some((value) => value != null && value === '_blank'); @@ -36,7 +35,6 @@ module.exports = { node, message: 'Use ExternalLink component (components/external_link) for _blank target link-outs', }); - return }, }; }, diff --git a/webapp/platform/shared/.eslintrc.json b/webapp/platform/shared/.eslintrc.json deleted file mode 100644 index f3d1e542a79..00000000000 --- a/webapp/platform/shared/.eslintrc.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "root": true, - "extends": [ - "plugin:@mattermost/react" - ], - "plugins": [ - "formatjs", - "no-only-tests" - ], - "rules": { - }, - "overrides": [ - { - "files": ["*.test.*", "src/tests/**"], - "rules": { - "no-only-tests/no-only-tests": ["error", {"focus": ["only", "skip"]}] - } - } - ] -} diff --git a/webapp/platform/shared/eslint.config.mjs b/webapp/platform/shared/eslint.config.mjs new file mode 100644 index 00000000000..e771018e040 --- /dev/null +++ b/webapp/platform/shared/eslint.config.mjs @@ -0,0 +1,26 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import formatjsPlugin from 'eslint-plugin-formatjs'; +import noOnlyTestsPlugin from 'eslint-plugin-no-only-tests'; + +import eslintPlugin from '@mattermost/eslint-plugin'; + +export default [ + ...eslintPlugin.configs.react, + { + files: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'], + plugins: { + formatjs: formatjsPlugin, + }, + }, + { + files: ['**/*.test.js', '**/*.test.jsx', '**/*.test.ts', '**/*.test.tsx'], + plugins: { + 'no-only-tests': noOnlyTestsPlugin, + }, + rules: { + 'no-only-tests/no-only-tests': ['error', {focus: ['only', 'skip']}], + }, + }, +]; diff --git a/webapp/platform/shared/package.json b/webapp/platform/shared/package.json index 0e94cfd16b1..28559c9431c 100644 --- a/webapp/platform/shared/package.json +++ b/webapp/platform/shared/package.json @@ -100,10 +100,10 @@ "scripts": { "build": "parcel build --no-optimize", "check": "npm run check:eslint && npm run check:stylelint", - "check:eslint": "eslint --ext .js,.jsx,.tsx,.ts ./src --quiet", + "check:eslint": "eslint ./src eslint.config.mjs --quiet", "check:stylelint": "stylelint \"**/*.{css,scss}\"", "check-types": "tsc -b", - "fix": "eslint --ext .js,.jsx,.tsx,.ts ./src --quiet --fix && stylelint \"**/*.{css,scss}\" --fix", + "fix": "eslint ./src eslint.config.mjs --quiet --fix && stylelint \"**/*.{css,scss}\" --fix", "run": "parcel watch --watch-dir .", "test": "jest", "test-ci": "jest --ci --forceExit --detectOpenHandles --maxWorkers=100% --logHeapUsage", diff --git a/webapp/platform/types/.eslintrc.json b/webapp/platform/types/.eslintrc.json deleted file mode 100644 index f8c36a3bed9..00000000000 --- a/webapp/platform/types/.eslintrc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "root": true, - "extends": [ - "plugin:@mattermost/base" - ] -} diff --git a/webapp/platform/types/eslint.config.mjs b/webapp/platform/types/eslint.config.mjs new file mode 100644 index 00000000000..0abcb26bfe7 --- /dev/null +++ b/webapp/platform/types/eslint.config.mjs @@ -0,0 +1,8 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import eslintPlugin from '@mattermost/eslint-plugin'; + +export default [ + ...eslintPlugin.configs.base, +]; diff --git a/webapp/platform/types/package.json b/webapp/platform/types/package.json index 2e259b85fcc..b8386aee3dc 100644 --- a/webapp/platform/types/package.json +++ b/webapp/platform/types/package.json @@ -40,7 +40,8 @@ }, "scripts": { "build": "tsc --build --verbose", - "check": "eslint --ext .js,.jsx,.tsx,.ts ./src --quiet", + "check": "eslint ./src eslint.config.mjs --quiet", + "fix": "eslint ./src eslint.config.mjs --quiet --fix", "run": "tsc --watch --preserveWatchOutput", "clean": "rm -rf lib node_modules *.tsbuildinfo" } From e9f62a663918f1587d711d4beb1656208aca5c43 Mon Sep 17 00:00:00 2001 From: Harrison Healey Date: Mon, 1 Jun 2026 14:29:38 -0400 Subject: [PATCH 5/5] MM-69003 Replace eslint-plugin-header with eslint-plugin-headers (#36766) * MM-69003 Replace eslint-plugin-header with eslint-plugin-headers * Run prettier --fix * Fix early merge * Update ESLint plugin version in package-lock.json --- e2e-tests/cypress/eslint.config.mjs | 20 +- e2e-tests/cypress/package-lock.json | 239 ++++-------------- e2e-tests/cypress/package.json | 2 +- .../Ignore-X-Frame-headers/background.js | 2 +- .../tests/support/keycloak_commands.ts | 1 - e2e-tests/cypress/tests/utils/index.js | 2 - e2e-tests/playwright/eslint.config.mjs | 21 +- e2e-tests/playwright/package-lock.json | 35 +-- e2e-tests/playwright/package.json | 2 +- .../mattermost-redux/src/utils/deep_freeze.ts | 4 +- .../mattermost-redux/src/utils/key_mirror.ts | 3 +- webapp/package-lock.json | 19 +- webapp/platform/eslint-plugin/configs/base.js | 17 +- webapp/platform/eslint-plugin/package.json | 2 +- 14 files changed, 120 insertions(+), 249 deletions(-) diff --git a/e2e-tests/cypress/eslint.config.mjs b/e2e-tests/cypress/eslint.config.mjs index fe9128a900e..b8029623c69 100644 --- a/e2e-tests/cypress/eslint.config.mjs +++ b/e2e-tests/cypress/eslint.config.mjs @@ -1,3 +1,6 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + import typescriptEslint from '@typescript-eslint/eslint-plugin'; import globals from 'globals'; import tsParser from '@typescript-eslint/parser'; @@ -5,7 +8,7 @@ import path from 'node:path'; import {fileURLToPath} from 'node:url'; import js from '@eslint/js'; import {FlatCompat} from '@eslint/eslintrc'; -import eslintPluginHeader from 'eslint-plugin-header'; +import headers from 'eslint-plugin-headers'; import pluginCypress from 'eslint-plugin-cypress'; import noOnlyTest from 'eslint-plugin-no-only-tests'; @@ -17,8 +20,6 @@ const compat = new FlatCompat({ allConfig: js.configs.all, }); -eslintPluginHeader.rules.header.meta.schema = false; - export default [ { ignores: ['**/node_modules', '**/logs', '**/results'], @@ -33,7 +34,7 @@ export default [ files: ['**/*.ts', '**/*.js'], plugins: { '@typescript-eslint': typescriptEslint, - header: eslintPluginHeader, + headers, cypress: pluginCypress, 'no-only-tests': noOnlyTest, }, @@ -73,11 +74,14 @@ export default [ '@typescript-eslint/no-require-imports': 'off', '@typescript-eslint/no-unused-expressions': 'off', '@typescript-eslint/no-var-requires': 'off', - 'header/header': [ + 'headers/header-format': [ 'error', - 'line', - ' Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.\n See LICENSE.txt for license information.', - 2, + { + source: 'string', + style: 'line', + content: 'Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.\nSee LICENSE.txt for license information.', + trailingNewlines: 2, + }, ], 'import/no-duplicates': 2, 'import/order': [ diff --git a/e2e-tests/cypress/package-lock.json b/e2e-tests/cypress/package-lock.json index c90726d3326..9dad492a047 100644 --- a/e2e-tests/cypress/package-lock.json +++ b/e2e-tests/cypress/package-lock.json @@ -49,7 +49,7 @@ "eslint": "9.39.3", "eslint-import-resolver-webpack": "0.13.11", "eslint-plugin-cypress": "6.3.1", - "eslint-plugin-header": "3.1.1", + "eslint-plugin-headers": "^1.3.4", "eslint-plugin-import": "2.32.0", "eslint-plugin-mattermost": "github:mattermost/eslint-plugin-mattermost#5b0c972eacf19286e4c66221b39113bf8728a99e", "eslint-plugin-no-only-tests": "3.3.0", @@ -310,6 +310,7 @@ "integrity": "sha512-sgGb4ub0JXnHaXnok5td7A1KGwENFPwOrwgzvpkeWq9w16Sl7x2KhYtVl+Fdd/7LAvaEtm3HqrYtNmm2d0OXmQ==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", @@ -1030,7 +1031,6 @@ "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -1073,6 +1073,7 @@ "integrity": "sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", @@ -1109,7 +1110,6 @@ "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", @@ -1127,7 +1127,6 @@ "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/types": "^7.27.3" }, @@ -1141,7 +1140,6 @@ "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", @@ -1159,7 +1157,6 @@ "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.28.5", @@ -1182,7 +1179,6 @@ "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "regexpu-core": "^6.3.1", @@ -1201,7 +1197,6 @@ "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", @@ -1219,7 +1214,6 @@ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -1230,7 +1224,6 @@ "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5" @@ -1245,7 +1238,6 @@ "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" @@ -1260,7 +1252,6 @@ "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", @@ -1279,7 +1270,6 @@ "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/types": "^7.27.1" }, @@ -1293,7 +1283,6 @@ "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -1304,7 +1293,6 @@ "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-wrap-function": "^7.27.1", @@ -1323,7 +1311,6 @@ "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", @@ -1342,7 +1329,6 @@ "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" @@ -1357,7 +1343,6 @@ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -1378,7 +1363,6 @@ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -1389,7 +1373,6 @@ "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", @@ -1405,7 +1388,6 @@ "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.29.0" @@ -1420,7 +1402,6 @@ "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/types": "^7.29.0" }, @@ -1437,7 +1418,6 @@ "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.28.5" @@ -1455,7 +1435,6 @@ "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1472,7 +1451,6 @@ "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1489,7 +1467,6 @@ "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", @@ -1508,7 +1485,6 @@ "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/traverse": "^7.28.6" @@ -1526,7 +1502,6 @@ "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" }, @@ -1540,7 +1515,6 @@ "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, @@ -1557,7 +1531,6 @@ "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, @@ -1574,7 +1547,6 @@ "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -1592,7 +1564,6 @@ "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1609,7 +1580,6 @@ "integrity": "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1", @@ -1628,7 +1598,6 @@ "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", @@ -1647,7 +1616,6 @@ "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1664,7 +1632,6 @@ "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, @@ -1681,7 +1648,6 @@ "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" @@ -1699,7 +1665,6 @@ "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" @@ -1717,7 +1682,6 @@ "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-compilation-targets": "^7.28.6", @@ -1739,7 +1703,6 @@ "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/template": "^7.28.6" @@ -1757,7 +1720,6 @@ "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.28.5" @@ -1775,7 +1737,6 @@ "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" @@ -1793,7 +1754,6 @@ "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1810,7 +1770,6 @@ "integrity": "sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" @@ -1828,7 +1787,6 @@ "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1845,7 +1803,6 @@ "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/plugin-transform-destructuring": "^7.28.5" @@ -1863,7 +1820,6 @@ "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, @@ -1880,7 +1836,6 @@ "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1897,7 +1852,6 @@ "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" @@ -1915,7 +1869,6 @@ "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-compilation-targets": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", @@ -1934,7 +1887,6 @@ "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, @@ -1951,7 +1903,6 @@ "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1968,7 +1919,6 @@ "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, @@ -1985,7 +1935,6 @@ "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -2002,7 +1951,6 @@ "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -2020,7 +1968,6 @@ "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" @@ -2038,7 +1985,6 @@ "integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", @@ -2058,7 +2004,6 @@ "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -2076,7 +2021,6 @@ "integrity": "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" @@ -2094,7 +2038,6 @@ "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -2111,7 +2054,6 @@ "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, @@ -2128,7 +2070,6 @@ "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, @@ -2145,7 +2086,6 @@ "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", @@ -2166,7 +2106,6 @@ "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1" @@ -2184,7 +2123,6 @@ "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, @@ -2201,7 +2139,6 @@ "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" @@ -2219,7 +2156,6 @@ "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -2236,7 +2172,6 @@ "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" @@ -2254,7 +2189,6 @@ "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.6", @@ -2273,7 +2207,6 @@ "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -2290,7 +2223,6 @@ "integrity": "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, @@ -2307,7 +2239,6 @@ "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" @@ -2325,7 +2256,6 @@ "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -2342,7 +2272,6 @@ "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -2359,7 +2288,6 @@ "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" @@ -2377,7 +2305,6 @@ "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -2394,7 +2321,6 @@ "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -2411,7 +2337,6 @@ "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -2428,7 +2353,6 @@ "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -2445,7 +2369,6 @@ "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" @@ -2463,7 +2386,6 @@ "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -2481,7 +2403,6 @@ "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" @@ -2585,7 +2506,6 @@ "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -2611,7 +2531,6 @@ "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", @@ -2627,7 +2546,6 @@ "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -2647,7 +2565,6 @@ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" @@ -3162,7 +3079,6 @@ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" @@ -3174,7 +3090,6 @@ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -3186,7 +3101,6 @@ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.0.0" } @@ -3197,7 +3111,6 @@ "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -3208,8 +3121,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", @@ -3217,7 +3129,6 @@ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -3245,6 +3156,7 @@ "integrity": "sha512-8vAzjjIJV/NIyKMB5tVRDQF9Uc58t6jCvZ7kOPR+JYHuW/8CPKBJkWmx2hqvgQ8h0b+otPLUqksGKp3LevGF7A==", "dev": true, "license": "MIT", + "peer": true, "peerDependencies": { "typescript": "^4.3.0 || ^5.0.0" }, @@ -4377,7 +4289,6 @@ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -4389,7 +4300,6 @@ "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -4670,6 +4580,7 @@ "integrity": "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.58.2", "@typescript-eslint/types": "8.58.2", @@ -4887,7 +4798,6 @@ "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" @@ -4898,24 +4808,21 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.13.2", @@ -4923,7 +4830,6 @@ "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", @@ -4935,8 +4841,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.14.1", @@ -4944,7 +4849,6 @@ "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -4958,7 +4862,6 @@ "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -4969,7 +4872,6 @@ "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -4979,8 +4881,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.14.1", @@ -4988,7 +4889,6 @@ "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -5006,7 +4906,6 @@ "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", @@ -5021,7 +4920,6 @@ "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -5035,7 +4933,6 @@ "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", @@ -5051,7 +4948,6 @@ "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" @@ -5062,16 +4958,14 @@ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", "dev": true, - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true, - "license": "Apache-2.0", - "peer": true + "license": "Apache-2.0" }, "node_modules/accepts": { "version": "2.0.0", @@ -5093,6 +4987,7 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5106,7 +5001,6 @@ "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.13.0" }, @@ -5161,7 +5055,6 @@ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ajv": "^8.0.0" }, @@ -5180,7 +5073,6 @@ "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5197,8 +5089,7 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/ansi-colors": { "version": "4.1.3", @@ -5692,7 +5583,6 @@ "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-define-polyfill-provider": "^0.6.8", @@ -5708,7 +5598,6 @@ "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.8", "core-js-compat": "^3.48.0" @@ -5723,7 +5612,6 @@ "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.8" }, @@ -5768,7 +5656,6 @@ "integrity": "sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "baseline-browser-mapping": "dist/cli.cjs" }, @@ -6083,8 +5970,7 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/buffer-xor": { "version": "1.0.3", @@ -6219,8 +6105,7 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "CC-BY-4.0", - "peer": true + "license": "CC-BY-4.0" }, "node_modules/caseless": { "version": "0.12.0", @@ -6284,7 +6169,6 @@ "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.0" } @@ -6624,8 +6508,7 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/cookie": { "version": "0.7.2", @@ -6653,7 +6536,6 @@ "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "browserslist": "^4.28.1" }, @@ -6800,6 +6682,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "@cypress/request": "^3.0.10", "@cypress/xvfb": "^1.2.4", @@ -7351,8 +7234,7 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.338.tgz", "integrity": "sha512-KVQQ3xko9/coDX3qXLUEEbqkKT8L+1DyAovrtu0Khtrt9wjSZ+7CZV4GVzxFy9Oe1NbrIU1oVXCwHJruIA1PNg==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/elliptic": { "version": "6.6.1", @@ -7424,6 +7306,7 @@ "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -7554,8 +7437,7 @@ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/es-object-atoms": { "version": "1.1.1", @@ -7653,6 +7535,7 @@ "integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -7864,14 +7747,17 @@ "eslint": ">=9" } }, - "node_modules/eslint-plugin-header": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz", - "integrity": "sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg==", + "node_modules/eslint-plugin-headers": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-headers/-/eslint-plugin-headers-1.3.4.tgz", + "integrity": "sha512-sfgmrq+geMaB7yilx1wbbzSHTmLRPm+hX6kxJhb6LQQwmF00CqZ8d3ks2ZADlDdREhP31THPHgRhcQuDogVZ4w==", "dev": true, - "license": "MIT", + "license": "ISC", + "engines": { + "node": "^16.0.0 || >= 18.0.0" + }, "peerDependencies": { - "eslint": ">=7.7.0" + "eslint": ">=7" } }, "node_modules/eslint-plugin-import": { @@ -7880,6 +7766,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -8609,8 +8496,7 @@ "url": "https://opencollective.com/fastify" } ], - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/fast-xml-builder": { "version": "1.1.4", @@ -9022,7 +8908,6 @@ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -9190,8 +9075,7 @@ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true, - "license": "BSD-2-Clause", - "peer": true + "license": "BSD-2-Clause" }, "node_modules/glob/node_modules/balanced-match": { "version": "1.0.2", @@ -10248,7 +10132,6 @@ "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -10264,6 +10147,7 @@ "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "dev": true, "license": "MIT", + "peer": true, "bin": { "jiti": "lib/jiti-cli.mjs" } @@ -10301,7 +10185,6 @@ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "license": "MIT", - "peer": true, "bin": { "jsesc": "bin/jsesc" }, @@ -10350,7 +10233,6 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "json5": "lib/cli.js" }, @@ -10604,7 +10486,6 @@ "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.11.5" }, @@ -10651,8 +10532,7 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lodash.intersection": { "version": "4.4.0", @@ -10874,7 +10754,6 @@ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "yallist": "^3.0.2" } @@ -11147,6 +11026,7 @@ "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "browser-stdout": "^1.3.1", "chokidar": "^4.0.1", @@ -11671,8 +11551,7 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/node-exports-info": { "version": "1.6.0", @@ -11728,8 +11607,7 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz", "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/node-stdlib-browser": { "version": "1.3.1", @@ -13036,8 +12914,7 @@ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/regenerate-unicode-properties": { "version": "10.2.2", @@ -13045,7 +12922,6 @@ "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "regenerate": "^1.4.2" }, @@ -13080,7 +12956,6 @@ "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.2", @@ -13098,8 +12973,7 @@ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/regjsparser": { "version": "0.13.1", @@ -13107,7 +12981,6 @@ "integrity": "sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "jsesc": "~3.1.0" }, @@ -13141,7 +13014,6 @@ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -13434,7 +13306,6 @@ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -13473,7 +13344,6 @@ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -13486,8 +13356,7 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/semver": { "version": "6.3.1", @@ -13562,6 +13431,7 @@ "integrity": "sha512-b0IrY3b1gVMsWvJppCf19g1p3JSnS0hQi6xu4Hi40CIhf0Lx8pQHcvBL+xunShpmOiQzg1NOia812NAWdSaShw==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@servie/events": "^1.0.0", "byte-length": "^1.0.2", @@ -13866,7 +13736,6 @@ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -13878,7 +13747,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -14307,7 +14175,6 @@ "integrity": "sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", @@ -14327,7 +14194,6 @@ "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", @@ -14361,8 +14227,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/thirty-two": { "version": "0.0.2", @@ -14468,6 +14333,7 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -14876,6 +14742,7 @@ "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -14940,7 +14807,6 @@ "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=4" } @@ -14951,7 +14817,6 @@ "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -14966,7 +14831,6 @@ "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=4" } @@ -14977,7 +14841,6 @@ "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=4" } @@ -15032,7 +14895,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" @@ -15162,7 +15024,6 @@ "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -15226,7 +15087,6 @@ "integrity": "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.13.0" } @@ -15237,7 +15097,6 @@ "integrity": "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" @@ -15252,7 +15111,6 @@ "integrity": "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" }, @@ -15491,8 +15349,7 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/yargs": { "version": "18.0.0", diff --git a/e2e-tests/cypress/package.json b/e2e-tests/cypress/package.json index 8123158f16b..da3b35f8329 100644 --- a/e2e-tests/cypress/package.json +++ b/e2e-tests/cypress/package.json @@ -44,7 +44,7 @@ "eslint": "9.39.3", "eslint-import-resolver-webpack": "0.13.11", "eslint-plugin-cypress": "6.3.1", - "eslint-plugin-header": "3.1.1", + "eslint-plugin-headers": "^1.3.4", "eslint-plugin-import": "2.32.0", "eslint-plugin-mattermost": "github:mattermost/eslint-plugin-mattermost#5b0c972eacf19286e4c66221b39113bf8728a99e", "eslint-plugin-no-only-tests": "3.3.0", diff --git a/e2e-tests/cypress/tests/extensions/Ignore-X-Frame-headers/background.js b/e2e-tests/cypress/tests/extensions/Ignore-X-Frame-headers/background.js index 669713fe06a..84888349c0e 100644 --- a/e2e-tests/cypress/tests/extensions/Ignore-X-Frame-headers/background.js +++ b/e2e-tests/cypress/tests/extensions/Ignore-X-Frame-headers/background.js @@ -1,4 +1,4 @@ -/* eslint-disable header/header */ +/* eslint-disable headers/header-format */ // taken from https://github.com/guilryder/chrome-extensions/tree/master/xframe_ignore diff --git a/e2e-tests/cypress/tests/support/keycloak_commands.ts b/e2e-tests/cypress/tests/support/keycloak_commands.ts index 59ecbb3a0d6..a113c40a85a 100644 --- a/e2e-tests/cypress/tests/support/keycloak_commands.ts +++ b/e2e-tests/cypress/tests/support/keycloak_commands.ts @@ -1,7 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. - import * as TIMEOUTS from '../fixtures/timeouts'; import {LdapUser} from './ldap_server_commands'; diff --git a/e2e-tests/cypress/tests/utils/index.js b/e2e-tests/cypress/tests/utils/index.js index efb10b4401e..9e09d947c15 100644 --- a/e2e-tests/cypress/tests/utils/index.js +++ b/e2e-tests/cypress/tests/utils/index.js @@ -1,8 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. - - import {v4 as uuidv4} from 'uuid'; import messageMenusData from '../fixtures/hooks/message_menus.json'; diff --git a/e2e-tests/playwright/eslint.config.mjs b/e2e-tests/playwright/eslint.config.mjs index e20e8141f5c..fa24f9fb50e 100644 --- a/e2e-tests/playwright/eslint.config.mjs +++ b/e2e-tests/playwright/eslint.config.mjs @@ -1,3 +1,6 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + import typescriptEslint from '@typescript-eslint/eslint-plugin'; import globals from 'globals'; import tsParser from '@typescript-eslint/parser'; @@ -5,7 +8,7 @@ import path from 'node:path'; import {fileURLToPath} from 'node:url'; import js from '@eslint/js'; import {FlatCompat} from '@eslint/eslintrc'; -import eslintPluginHeader from 'eslint-plugin-header'; +import headers from 'eslint-plugin-headers'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -15,8 +18,6 @@ const compat = new FlatCompat({ allConfig: js.configs.all, }); -eslintPluginHeader.rules.header.meta.schema = false; - export default [ { ignores: ['**/node_modules', '**/dist', '**/playwright-report', '**/test-results', '**/results'], @@ -31,7 +32,7 @@ export default [ files: ['**/*.ts', '**/*.js'], plugins: { '@typescript-eslint': typescriptEslint, - header: eslintPluginHeader, + headers, }, languageOptions: { globals: { @@ -52,11 +53,15 @@ export default [ '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-var-requires': 'off', 'no-console': 'error', - 'header/header': [ + 'headers/header-format': [ 'error', - 'line', - ' Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.\n See LICENSE.txt for license information.', - 2, + { + source: 'string', + style: 'line', + content: + 'Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.\nSee LICENSE.txt for license information.', + trailingNewlines: 2, + }, ], 'import/order': [ 'error', diff --git a/e2e-tests/playwright/package-lock.json b/e2e-tests/playwright/package-lock.json index f256a203cdf..eb6d9fd0f4a 100644 --- a/e2e-tests/playwright/package-lock.json +++ b/e2e-tests/playwright/package-lock.json @@ -22,7 +22,7 @@ "dayjs": "1.11.20", "eslint": "9.39.2", "eslint-import-resolver-typescript": "4.4.4", - "eslint-plugin-header": "3.1.1", + "eslint-plugin-headers": "^1.3.4", "eslint-plugin-import": "2.32.0", "glob": "13.0.6", "luxon": "3.7.2", @@ -863,6 +863,7 @@ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.59.1.tgz", "integrity": "sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==", "license": "Apache-2.0", + "peer": true, "dependencies": { "playwright": "1.59.1" }, @@ -1415,7 +1416,6 @@ "integrity": "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.58.2", "@typescript-eslint/types": "8.58.2", @@ -1441,7 +1441,6 @@ "integrity": "sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/types": "8.58.2", "@typescript-eslint/visitor-keys": "8.58.2" @@ -1460,7 +1459,6 @@ "integrity": "sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/types": "8.58.2", "eslint-visitor-keys": "^5.0.0" @@ -1479,7 +1477,6 @@ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" }, @@ -1493,7 +1490,6 @@ "integrity": "sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.58.2", "@typescript-eslint/types": "^8.58.2", @@ -1548,7 +1544,6 @@ "integrity": "sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -1672,7 +1667,6 @@ "integrity": "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -1687,7 +1681,6 @@ "integrity": "sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/project-service": "8.58.2", "@typescript-eslint/tsconfig-utils": "8.58.2", @@ -1716,7 +1709,6 @@ "integrity": "sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/types": "8.58.2", "eslint-visitor-keys": "^5.0.0" @@ -1735,7 +1727,6 @@ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" }, @@ -2168,6 +2159,7 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3071,6 +3063,7 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -3259,14 +3252,17 @@ "ms": "^2.1.1" } }, - "node_modules/eslint-plugin-header": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz", - "integrity": "sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg==", + "node_modules/eslint-plugin-headers": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-headers/-/eslint-plugin-headers-1.3.4.tgz", + "integrity": "sha512-sfgmrq+geMaB7yilx1wbbzSHTmLRPm+hX6kxJhb6LQQwmF00CqZ8d3ks2ZADlDdREhP31THPHgRhcQuDogVZ4w==", "dev": true, - "license": "MIT", + "license": "ISC", + "engines": { + "node": "^16.0.0 || >= 18.0.0" + }, "peerDependencies": { - "eslint": ">=7.7.0" + "eslint": ">=7" } }, "node_modules/eslint-plugin-import": { @@ -3275,6 +3271,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -5406,6 +5403,7 @@ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz", "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==", "license": "Apache-2.0", + "peer": true, "bin": { "playwright-core": "cli.js" }, @@ -5673,6 +5671,7 @@ "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -6360,6 +6359,7 @@ "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6411,6 +6411,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" }, diff --git a/e2e-tests/playwright/package.json b/e2e-tests/playwright/package.json index 6ebb54a091b..9bb8d74e9cb 100644 --- a/e2e-tests/playwright/package.json +++ b/e2e-tests/playwright/package.json @@ -41,7 +41,7 @@ "dayjs": "1.11.20", "eslint": "9.39.2", "eslint-import-resolver-typescript": "4.4.4", - "eslint-plugin-header": "3.1.1", + "eslint-plugin-headers": "^1.3.4", "eslint-plugin-import": "2.32.0", "glob": "13.0.6", "luxon": "3.7.2", diff --git a/webapp/channels/src/packages/mattermost-redux/src/utils/deep_freeze.ts b/webapp/channels/src/packages/mattermost-redux/src/utils/deep_freeze.ts index 67209265862..dcaee7b4265 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/utils/deep_freeze.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/utils/deep_freeze.ts @@ -1,3 +1,5 @@ +/* eslint-disable headers/header-format */ + /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. @@ -8,8 +10,6 @@ * */ -/* eslint-disable header/header */ - /** * If your application is accepting different values for the same field over * time and is doing a diff on them, you can either (1) create a copy or diff --git a/webapp/channels/src/packages/mattermost-redux/src/utils/key_mirror.ts b/webapp/channels/src/packages/mattermost-redux/src/utils/key_mirror.ts index 84b585e2030..9fd31d20dce 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/utils/key_mirror.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/utils/key_mirror.ts @@ -1,3 +1,5 @@ +/* eslint-disable headers/header-format */ + /** * Copyright (c) 2013-present, Facebook, Inc. * All rights reserved. @@ -7,7 +9,6 @@ * of patent rights can be found in the PATENTS file in the same directory. * */ -/* eslint-disable header/header */ /** * Constructs an enumeration with keys equal to their value. diff --git a/webapp/package-lock.json b/webapp/package-lock.json index bb4dda12068..ec1b06a5a75 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -14706,13 +14706,16 @@ "dev": true, "license": "0BSD" }, - "node_modules/eslint-plugin-header": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz", - "integrity": "sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg==", - "license": "MIT", + "node_modules/eslint-plugin-headers": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-headers/-/eslint-plugin-headers-1.3.4.tgz", + "integrity": "sha512-sfgmrq+geMaB7yilx1wbbzSHTmLRPm+hX6kxJhb6LQQwmF00CqZ8d3ks2ZADlDdREhP31THPHgRhcQuDogVZ4w==", + "license": "ISC", + "engines": { + "node": "^16.0.0 || >= 18.0.0" + }, "peerDependencies": { - "eslint": ">=7.7.0" + "eslint": ">=7" } }, "node_modules/eslint-plugin-import": { @@ -28090,12 +28093,12 @@ }, "platform/eslint-plugin": { "name": "@mattermost/eslint-plugin", - "version": "1.1.0", + "version": "2.0.0", "license": "Apache 2.0", "dependencies": { "@typescript-eslint/eslint-plugin": "^7.1.0", "@typescript-eslint/parser": "^7.1.0", - "eslint-plugin-header": "^3.1.1", + "eslint-plugin-headers": "1.3.4", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsx-a11y": "^6.7.1", "jsx-ast-utils": "^3.3.3" diff --git a/webapp/platform/eslint-plugin/configs/base.js b/webapp/platform/eslint-plugin/configs/base.js index 2b935d6ebe9..36661daf361 100644 --- a/webapp/platform/eslint-plugin/configs/base.js +++ b/webapp/platform/eslint-plugin/configs/base.js @@ -8,7 +8,7 @@ import {FlatCompat} from '@eslint/eslintrc'; import js from '@eslint/js'; import typescriptPlugin from '@typescript-eslint/eslint-plugin'; import typescriptParser from '@typescript-eslint/parser'; -import headerPlugin from 'eslint-plugin-header'; +import headersPlugin from 'eslint-plugin-headers'; import importPlugin from 'eslint-plugin-import'; import globals from 'globals'; @@ -45,7 +45,7 @@ const base = { rules, }, typescript: typescriptPlugin, - header: headerPlugin, + headers: headersPlugin, import: importPlugin, }, rules: { @@ -197,11 +197,14 @@ const base = { ], 'global-require': 2, 'guard-for-in': 2, - 'header/header': [ - 2, - 'line', - ' Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.\n See LICENSE.txt for license information.', - 2, + 'headers/header-format': [ + 'error', + { + source: 'string', + style: 'line', + content: 'Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.\nSee LICENSE.txt for license information.', + trailingNewlines: 2, + }, ], 'id-blacklist': 0, 'import/no-duplicates': 2, diff --git a/webapp/platform/eslint-plugin/package.json b/webapp/platform/eslint-plugin/package.json index c38205b7ad7..a5dac6babaf 100644 --- a/webapp/platform/eslint-plugin/package.json +++ b/webapp/platform/eslint-plugin/package.json @@ -19,7 +19,7 @@ "dependencies": { "@typescript-eslint/eslint-plugin": "^7.1.0", "@typescript-eslint/parser": "^7.1.0", - "eslint-plugin-header": "^3.1.1", + "eslint-plugin-headers": "1.3.4", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsx-a11y": "^6.7.1", "jsx-ast-utils": "^3.3.3"