diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml index c5db83fbc9..63c516074f 100644 --- a/.github/workflows/build-and-test.yaml +++ b/.github/workflows/build-and-test.yaml @@ -208,6 +208,9 @@ jobs: - name: Install dependencies run: pnpm install --frozen-lockfile + - name: Build modules + run: pnpm -r --filter "./modules/**" run build + - name: Setup playwright uses: ./.github/actions/setup-playwright with: diff --git a/modules/.eslintrc.cjs b/modules/.eslintrc.cjs index b8b9794a3c..70d522d844 100644 --- a/modules/.eslintrc.cjs +++ b/modules/.eslintrc.cjs @@ -2,7 +2,7 @@ module.exports = { plugins: ["matrix-org", "eslint-plugin-react-compiler"], extends: ["plugin:matrix-org/typescript", "plugin:matrix-org/react", "plugin:matrix-org/a11y"], parserOptions: { - project: ["./tsconfig.json"], + project: true, }, env: { browser: true, diff --git a/modules/banner/package.json b/modules/banner/package.json index ae038ca28c..caf25854d9 100644 --- a/modules/banner/package.json +++ b/modules/banner/package.json @@ -7,12 +7,7 @@ "license": "SEE LICENSE IN README.md", "scripts": { "build": "vite build", - "lint": "pnpm lint:types && pnpm lint:js", - "lint:types": "tsc --noEmit", - "lint:js": "eslint --max-warnings 0 src -c ../.eslintrc.cjs", - "test:playwright": "playwright test -c ../playwright.config.ts", - "test:playwright:open": "yarn test:playwright -c ../playwright.config.ts --ui", - "test:playwright:screenshots": "playwright-screenshots yarn test:playwright --update-snapshots --grep @screenshot" + "lint:types": "tsc --noEmit" }, "devDependencies": { "@arcmantle/vite-plugin-import-css-sheet": "^1.0.12", @@ -24,7 +19,6 @@ "matrix-web-i18n": "^3.6.0", "matrix-widget-api": "^1.17.0", "react": "catalog:", - "rollup-plugin-external-globals": "^0.13.0", "typescript": "catalog:", "vite": "catalog:", "vite-plugin-node-polyfills": "catalog:", diff --git a/modules/banner/vite.config.ts b/modules/banner/vite.config.ts index e2ee02eaa2..a5f7d1c139 100644 --- a/modules/banner/vite.config.ts +++ b/modules/banner/vite.config.ts @@ -7,16 +7,16 @@ Please see LICENSE files in the repository root for full details. import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { defineConfig, esmExternalRequirePlugin } from "vite"; +import { mergeConfig } from "vite"; import react from "@vitejs/plugin-react"; import { nodePolyfills } from "vite-plugin-node-polyfills"; -import externalGlobals from "rollup-plugin-external-globals"; import svgr from "vite-plugin-svgr"; import { importCSSSheet } from "@arcmantle/vite-plugin-import-css-sheet"; +import baseConfig from "@element-hq/element-web-module-api/vite.base.ts"; const __dirname = dirname(fileURLToPath(import.meta.url)); -export default defineConfig({ +export default mergeConfig(baseConfig, { build: { lib: { entry: resolve(__dirname, "src/index.tsx"), @@ -24,22 +24,6 @@ export default defineConfig({ fileName: "index", formats: ["es"], }, - outDir: "lib", - target: "esnext", - sourcemap: true, - rolldownOptions: { - plugins: [ - esmExternalRequirePlugin({ - external: ["react"], - }), - ], - output: { - globals: { - // Reuse React from the host app - react: "window.React", - }, - }, - }, }, plugins: [ importCSSSheet(), @@ -48,15 +32,5 @@ export default defineConfig({ nodePolyfills({ include: ["events"], }), - externalGlobals({ - // Reuse React from the host app - react: "window.React", - }), ], - define: { - // Use production mode for the build as it is tested against production builds of Element Web, - // this is required for React JSX versions to be compatible. - "process.env.NODE_ENV": "'production'", - "process": { env: { NODE_ENV: "production" } }, - }, }); diff --git a/modules/package.json b/modules/package.json new file mode 100644 index 0000000000..6e5ec59c17 --- /dev/null +++ b/modules/package.json @@ -0,0 +1,24 @@ +{ + "name": "element-web-modules", + "version": "0.0.0", + "type": "module", + "scripts": { + "lint:js": "eslint --max-warnings 0 */src -c ./.eslintrc.cjs", + "lint:ts": "tsc --noEmit", + "test:playwright": "playwright test -c ./playwright.config.ts", + "test:playwright:open": "yarn test:playwright -c ./playwright.config.ts --ui", + "test:playwright:screenshots": "playwright-screenshots yarn test:playwright --update-snapshots --grep @screenshot" + }, + "devDependencies": { + "@element-hq/element-web-playwright-common": "workspace:*", + "eslint": "8", + "eslint-config-google": "^0.14.0", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-jsx-a11y": "^6.10.2", + "eslint-plugin-matrix-org": "^3.0.0", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-compiler": "^19.1.0-rc.2", + "eslint-plugin-unicorn": "^56.0.0" + }, + "private": true +} diff --git a/modules/restricted-guests/package.json b/modules/restricted-guests/package.json index 8a87b5a343..a1aa9afcac 100644 --- a/modules/restricted-guests/package.json +++ b/modules/restricted-guests/package.json @@ -7,12 +7,7 @@ "license": "SEE LICENSE IN README.md", "scripts": { "build": "vite build", - "lint": "pnpm lint:types && pnpm lint:js", - "lint:types": "tsc --noEmit", - "lint:js": "eslint --max-warnings 0 src -c ../.eslintrc.cjs", - "test:playwright": "playwright test -c ../playwright.config.ts", - "test:playwright:open": "yarn test:playwright -c ../playwright.config.ts --ui", - "test:playwright:screenshots": "playwright-screenshots yarn test:playwright --update-snapshots --grep @screenshot" + "lint:types": "tsc --noEmit" }, "devDependencies": { "@arcmantle/vite-plugin-import-css-sheet": "^1.0.12", @@ -21,7 +16,6 @@ "@types/react": "catalog:", "@vitejs/plugin-react": "catalog:", "react": "catalog:", - "rollup-plugin-external-globals": "^0.13.0", "typescript": "catalog:", "vite": "catalog:", "vite-plugin-node-polyfills": "catalog:" diff --git a/modules/restricted-guests/vite.config.ts b/modules/restricted-guests/vite.config.ts index 9dfdb5dbed..8049efcc95 100644 --- a/modules/restricted-guests/vite.config.ts +++ b/modules/restricted-guests/vite.config.ts @@ -7,15 +7,15 @@ Please see LICENSE files in the repository root for full details. import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { defineConfig, esmExternalRequirePlugin } from "vite"; +import { mergeConfig } from "vite"; import react from "@vitejs/plugin-react"; import { nodePolyfills } from "vite-plugin-node-polyfills"; -import externalGlobals from "rollup-plugin-external-globals"; import { importCSSSheet } from "@arcmantle/vite-plugin-import-css-sheet"; +import baseConfig from "@element-hq/element-web-module-api/vite.base.ts"; const __dirname = dirname(fileURLToPath(import.meta.url)); -export default defineConfig({ +export default mergeConfig(baseConfig, { build: { lib: { entry: resolve(__dirname, "src/index.tsx"), @@ -23,22 +23,6 @@ export default defineConfig({ fileName: "index", formats: ["es"], }, - outDir: "lib", - target: "esnext", - sourcemap: true, - rolldownOptions: { - plugins: [ - esmExternalRequirePlugin({ - external: ["react"], - }), - ], - output: { - globals: { - // Reuse React from the host app - react: "window.React", - }, - }, - }, }, plugins: [ importCSSSheet(), @@ -46,15 +30,5 @@ export default defineConfig({ nodePolyfills({ include: ["events"], }), - externalGlobals({ - // Reuse React from the host app - react: "window.React", - }), ], - define: { - // Use production mode for the build as it is tested against production builds of Element Web, - // this is required for React JSX versions to be compatible. - "process.env.NODE_ENV": "'production'", - "process": { env: { NODE_ENV: "production" } }, - }, }); diff --git a/modules/widget-lifecycle/package.json b/modules/widget-lifecycle/package.json index 534af61d9e..f9e3bf644a 100644 --- a/modules/widget-lifecycle/package.json +++ b/modules/widget-lifecycle/package.json @@ -7,12 +7,7 @@ "license": "SEE LICENSE IN README.md", "scripts": { "build": "vite build", - "lint": "pnpm lint:types && pnpm lint:js", - "lint:types": "tsc --noEmit", - "lint:js": "eslint --max-warnings 0 src -c ../.eslintrc.cjs", - "test:playwright": "playwright test -c ../playwright.config.ts", - "test:playwright:open": "yarn test:playwright -c ../playwright.config.ts --ui", - "test:playwright:screenshots": "playwright-screenshots yarn test:playwright --update-snapshots --grep @screenshot" + "lint:types": "tsc --noEmit" }, "devDependencies": { "@element-hq/element-web-module-api": "workspace:*", diff --git a/modules/widget-lifecycle/vite.config.ts b/modules/widget-lifecycle/vite.config.ts index 66bd04e4e1..3683872b2b 100644 --- a/modules/widget-lifecycle/vite.config.ts +++ b/modules/widget-lifecycle/vite.config.ts @@ -7,11 +7,12 @@ Please see LICENSE files in the repository root for full details. import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { defineConfig } from "vitest/config"; +import { mergeConfig } from "vitest/config"; +import baseConfig from "@element-hq/element-web-module-api/vite.base.ts"; const __dirname = dirname(fileURLToPath(import.meta.url)); -export default defineConfig({ +export default mergeConfig(baseConfig, { build: { lib: { entry: resolve(__dirname, "src/index.ts"), @@ -19,10 +20,6 @@ export default defineConfig({ fileName: "index", formats: ["es"], }, - outDir: "lib", - target: "esnext", - sourcemap: true, - minify: false, }, test: { include: ["tests/**/*.test.ts"], @@ -31,7 +28,7 @@ export default defineConfig({ coverage: { provider: "v8", include: ["src/**/*.ts"], - reporter: [["lcov", { projectRoot: "../../../" }], "text"], + reporter: [["lcov", { projectRoot: "../../" }], "text"], }, }, }); diff --git a/modules/widget-toggles/package.json b/modules/widget-toggles/package.json index 172f73135b..2e32e5b064 100644 --- a/modules/widget-toggles/package.json +++ b/modules/widget-toggles/package.json @@ -7,13 +7,8 @@ "license": "SEE LICENSE IN README.md", "scripts": { "build": "vite build", - "lint": "pnpm lint:types && pnpm lint:js", "lint:types": "tsc --noEmit", - "lint:js": "eslint --max-warnings 0 src -c ../.eslintrc.cjs", - "test": "vitest run --coverage", - "test:playwright": "playwright test -c ../playwright.config.ts", - "test:playwright:open": "yarn test:playwright -c ../playwright.config.ts --ui", - "test:playwright:screenshots": "playwright-screenshots yarn test:playwright --update-snapshots --grep @screenshot" + "test": "vitest run --coverage" }, "devDependencies": { "@arcmantle/vite-plugin-import-css-sheet": "^1.0.12", @@ -28,7 +23,6 @@ "@vitest/coverage-v8": "catalog:", "react": "catalog:", "typescript": "catalog:", - "rollup-plugin-external-globals": "^0.13.0", "vite": "catalog:", "vite-plugin-node-polyfills": "catalog:", "vite-plugin-svgr": "catalog:", diff --git a/modules/widget-toggles/vite.config.ts b/modules/widget-toggles/vite.config.ts index af7dd703b9..403f9ccdf4 100644 --- a/modules/widget-toggles/vite.config.ts +++ b/modules/widget-toggles/vite.config.ts @@ -7,18 +7,17 @@ Please see LICENSE files in the repository root for full details. import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { esmExternalRequirePlugin } from "vite"; import react from "@vitejs/plugin-react"; import { nodePolyfills } from "vite-plugin-node-polyfills"; -import externalGlobals from "rollup-plugin-external-globals"; import svgr from "vite-plugin-svgr"; import { importCSSSheet } from "@arcmantle/vite-plugin-import-css-sheet"; -import { defineConfig } from "vitest/config"; +import { mergeConfig } from "vitest/config"; import { playwright } from "@vitest/browser-playwright"; +import baseConfig from "@element-hq/element-web-module-api/vite.base.ts"; const __dirname = dirname(fileURLToPath(import.meta.url)); -export default defineConfig({ +export default mergeConfig(baseConfig, { build: { lib: { entry: resolve(__dirname, "src/index.tsx"), @@ -26,22 +25,6 @@ export default defineConfig({ fileName: "index", formats: ["es"], }, - outDir: "lib", - target: "esnext", - sourcemap: true, - rolldownOptions: { - plugins: [ - esmExternalRequirePlugin({ - external: ["react"], - }), - ], - output: { - globals: { - // Reuse React from the host app - react: "window.React", - }, - }, - }, }, plugins: [ importCSSSheet(), @@ -50,17 +33,7 @@ export default defineConfig({ nodePolyfills({ include: ["events"], }), - externalGlobals({ - // Reuse React from the host app - react: "window.React", - }), ], - define: { - // Use production mode for the build as it is tested against production builds of Element Web, - // this is required for React JSX versions to be compatible. - "process.env.NODE_ENV": "'production'", - "process": { env: { NODE_ENV: "production" } }, - }, test: { include: ["tests/**/*.test.{ts,tsx}"], exclude: ["./e2e/**/*", "./node_modules/**/*"], @@ -68,7 +41,7 @@ export default defineConfig({ coverage: { provider: "v8", include: ["src/**/*.ts"], - reporter: [["lcov", { projectRoot: "../../../" }], "text"], + reporter: [["lcov", { projectRoot: "../../" }], "text"], }, browser: { enabled: true, diff --git a/package.json b/package.json index 967d43c316..b74c1433dc 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "devDependencies": { "@action-validator/cli": "^0.6.0", "@action-validator/core": "^0.6.0", - "@element-hq/element-web-playwright-common": "workspace:*", "@nx-tools/nx-container": "^7.2.1", "@playwright/test": "catalog:", "@types/node": "22", diff --git a/packages/module-api/package.json b/packages/module-api/package.json index 925f03e2b7..1ea9ac4c65 100644 --- a/packages/module-api/package.json +++ b/packages/module-api/package.json @@ -19,10 +19,15 @@ "types": "./lib/element-web-module-api-alpha.d.ts", "import": "./lib/element-web-plugin-engine.js", "require": "./lib/element-web-plugin-engine.umd.cjs" + }, + "./vite.base.ts": { + "types": "./vite.base.ts", + "import": "./vite.base.ts" } }, "files": [ - "lib" + "lib", + "vite.base.ts" ], "scripts": { "prepack": "nx build", diff --git a/packages/module-api/vite.base.ts b/packages/module-api/vite.base.ts new file mode 100644 index 0000000000..4be510c587 --- /dev/null +++ b/packages/module-api/vite.base.ts @@ -0,0 +1,46 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +/** + * Base vite config for building Element modules + */ + +import { defineConfig, esmExternalRequirePlugin } from "vite"; +import externalGlobals from "rollup-plugin-external-globals"; + +export default defineConfig({ + build: { + outDir: "lib", + target: "esnext", + sourcemap: true, + rolldownOptions: { + plugins: [ + esmExternalRequirePlugin({ + external: ["react"], + }), + ], + output: { + globals: { + // Reuse React from the host app + react: "window.React", + }, + }, + }, + }, + plugins: [ + externalGlobals({ + // Reuse React from the host app + react: "window.React", + }), + ], + define: { + // Use production mode for the build as it is tested against production builds of Element Web, + // this is required for React JSX versions to be compatible. + "process.env.NODE_ENV": "'production'", + "process": { env: { NODE_ENV: "production" } }, + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6be5199799..96bc551804 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -309,9 +309,6 @@ importers: '@action-validator/core': specifier: ^0.6.0 version: 0.6.0 - '@element-hq/element-web-playwright-common': - specifier: workspace:* - version: link:packages/playwright-common '@nx-tools/nx-container': specifier: ^7.2.1 version: 7.2.3(@nx/devkit@22.6.5(nx@22.7.5))(@nx/js@22.6.5(@babel/traverse@7.29.7)(nx@22.7.5))(dotenv@17.4.2)(nx@22.7.5)(tslib@2.8.1) @@ -1098,6 +1095,36 @@ importers: specifier: 2.8.4 version: 2.8.4 + modules: + devDependencies: + '@element-hq/element-web-playwright-common': + specifier: workspace:* + version: link:../packages/playwright-common + eslint: + specifier: '8' + version: 8.57.1 + eslint-config-google: + specifier: ^0.14.0 + version: 0.14.0(eslint@8.57.1) + eslint-config-prettier: + specifier: ^10.1.8 + version: 10.1.8(eslint@8.57.1) + eslint-plugin-jsx-a11y: + specifier: ^6.10.2 + version: 6.10.2(eslint@8.57.1) + eslint-plugin-matrix-org: + specifier: ^3.0.0 + version: 3.0.0(dd8c44dac078085b4cf5561606e117de) + eslint-plugin-react: + specifier: ^7.37.5 + version: 7.37.5(eslint@8.57.1) + eslint-plugin-react-compiler: + specifier: ^19.1.0-rc.2 + version: 19.1.0-rc.2(eslint@8.57.1) + eslint-plugin-unicorn: + specifier: ^56.0.0 + version: 56.0.1(eslint@8.57.1) + modules/banner: dependencies: '@radix-ui/react-dialog': @@ -1146,9 +1173,6 @@ importers: react: specifier: 'catalog:' version: 19.2.6 - rollup-plugin-external-globals: - specifier: ^0.13.0 - version: 0.13.0(rollup@4.60.1) typescript: specifier: 'catalog:' version: 6.0.3 @@ -1195,9 +1219,6 @@ importers: react: specifier: 'catalog:' version: 19.2.6 - rollup-plugin-external-globals: - specifier: ^0.13.0 - version: 0.13.0(rollup@4.60.1) typescript: specifier: 'catalog:' version: 6.0.3 @@ -1284,9 +1305,6 @@ importers: react: specifier: 'catalog:' version: 19.2.6 - rollup-plugin-external-globals: - specifier: ^0.13.0 - version: 0.13.0(rollup@4.60.1) typescript: specifier: 'catalog:' version: 6.0.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 0780d0f307..d03667db45 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -5,6 +5,7 @@ ignoreWorkspaceRootCheck: true packages: - "apps/*" - "packages/*" + - "modules" - "modules/*" catalog: