diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e417447d21..713de84910 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -49,8 +49,32 @@ jobs: - name: Setup E2E Environment uses: ./.github/actions/setup-e2e - - name: Install Playwright Browsers - run: npx playwright install --with-deps + - name: Resolve Playwright version + id: playwright-version + run: echo "version=$(node -p "require('@playwright/test/package.json').version")" >> "$GITHUB_OUTPUT" + + - name: Cache Playwright browsers + id: playwright-cache + uses: actions/cache@v4 + with: + path: ~/.cache/ms-playwright + key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }} + + - name: Install Playwright browsers and system deps + if: steps.playwright-cache.outputs.cache-hit != 'true' + timeout-minutes: 15 + env: + DEBIAN_FRONTEND: noninteractive + NEEDRESTART_MODE: a + run: npx playwright install --with-deps chromium + + - name: Install Playwright system deps only + if: steps.playwright-cache.outputs.cache-hit == 'true' + timeout-minutes: 15 + env: + DEBIAN_FRONTEND: noninteractive + NEEDRESTART_MODE: a + run: npx playwright install-deps chromium - name: Run Playwright tests run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} diff --git a/Gruntfile.js b/Gruntfile.js index 5a00c46bd3..df01cef35c 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -55,7 +55,7 @@ module.exports = function(grunt) { // them too. Invokes gettext.js's shipped po2json CLI directly so we don't have to depend on // @superdesk/build-tools at runtime (it's a devDependency and may not be installed when this // Gruntfile is consumed from another project). - grunt.registerTask('po-to-json', 'Compile po/*.po to dist/languages/*.json', function() { + grunt.registerTask('po-to-json', 'Compile po/*.po to dist/languages/*.json', () => { var fs = require('fs'); var distDir = grunt.config.get('distDir'); var poDir = path.join(__dirname, 'po'); @@ -68,7 +68,7 @@ module.exports = function(grunt) { fs.mkdirSync(jsonDir, {recursive: true}); - fs.readdirSync(poDir).forEach(function(filename) { + fs.readdirSync(poDir).forEach((filename) => { var poFile = path.join(poDir, filename); if (!filename.endsWith('.po') || fs.statSync(poFile).isDirectory()) { @@ -86,19 +86,19 @@ module.exports = function(grunt) { // from a fresh checkout without needing an external wrapper command. Each task // requires @superdesk/build-tools lazily inside the action so a missing dep doesn't // break Gruntfile load for callers that don't need these tasks. - grunt.registerTask('install-extensions', 'Install each loaded extension', function() { + grunt.registerTask('install-extensions', 'Install each loaded extension', () => { var installExtensions = require('@superdesk/build-tools/src/extensions/install-extensions'); installExtensions(process.cwd()); }); - grunt.registerTask('namespace-css', 'Generate the namespaced extension stylesheet', function() { + grunt.registerTask('namespace-css', 'Generate the namespaced extension stylesheet', () => { var {namespaceCSS} = require('@superdesk/build-tools/src/extensions/css'); namespaceCSS(process.cwd()); }); - grunt.registerTask('merge-extension-translations', 'Merge translations from loaded extensions', function() { + grunt.registerTask('merge-extension-translations', 'Merge translations from loaded extensions', () => { var {mergeTranslationsFromExtensions} = require('@superdesk/build-tools/src/extensions/translations'); mergeTranslationsFromExtensions(process.cwd()); diff --git a/e2e/client/package-lock.json b/e2e/client/package-lock.json index b2798caf4a..e62b46ea20 100644 --- a/e2e/client/package-lock.json +++ b/e2e/client/package-lock.json @@ -9,7 +9,7 @@ "superdesk-core": "file:../../" }, "devDependencies": { - "@playwright/test": "~1.58.0", + "@playwright/test": "^1.60.0", "@types/request": "^2.48.12", "grunt": "1.3.0", "http-server": "14.1.1", @@ -63,7 +63,6 @@ "eslint": "^8.57.1", "eslint-plugin-react": "^7.37.0", "file-loader": "^6.2.0", - "fork-ts-checker-webpack-plugin": "^9.0.0", "gettext.js": "0.9.0", "git-rev-sync": "1.10.0", "gridster": "github:superdesk/gridster.js#885d0c9", @@ -15539,13 +15538,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.58.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.0.tgz", - "integrity": "sha512-fWza+Lpbj6SkQKCrU6si4iu+fD2dD3gxNHFhUPxsfXBPhnv3rRSQVd0NtBUT9Z/RhF/boCBcuUaMUSTRTopjZg==", + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.60.0.tgz", + "integrity": "sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.58.0" + "playwright": "1.60.0" }, "bin": { "playwright": "cli.js" @@ -17458,13 +17457,13 @@ } }, "node_modules/playwright": { - "version": "1.58.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.0.tgz", - "integrity": "sha512-2SVA0sbPktiIY/MCOPX8e86ehA/e+tDNq+e5Y8qjKYti2Z/JG7xnronT/TXTIkKbYGWlCbuucZ6dziEgkoEjQQ==", + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz", + "integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.58.0" + "playwright-core": "1.60.0" }, "bin": { "playwright": "cli.js" @@ -17477,9 +17476,9 @@ } }, "node_modules/playwright-core": { - "version": "1.58.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.0.tgz", - "integrity": "sha512-aaoB1RWrdNi3//rOeKuMiS65UCcgOVljU46At6eFcOFPFHWtd2weHRRow6z/n+Lec0Lvu0k9ZPKJSjPugikirw==", + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz", + "integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/e2e/client/package.json b/e2e/client/package.json index e0a10a1653..482e18c99c 100644 --- a/e2e/client/package.json +++ b/e2e/client/package.json @@ -5,7 +5,7 @@ "@superdesk/build-tools": "file:../../build-tools" }, "devDependencies": { - "@playwright/test": "~1.58.0", + "@playwright/test": "^1.60.0", "@types/request": "^2.48.12", "grunt": "1.3.0", "http-server": "14.1.1", diff --git a/package-lock.json b/package-lock.json index ecc9f2ff42..4243c9ca37 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,7 +48,6 @@ "eslint": "^8.57.1", "eslint-plugin-react": "^7.37.0", "file-loader": "^6.2.0", - "fork-ts-checker-webpack-plugin": "^9.0.0", "gettext.js": "0.9.0", "git-rev-sync": "1.10.0", "gridster": "github:superdesk/gridster.js#885d0c9", @@ -167,20 +166,6 @@ "node": ">= 10" } }, - "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", @@ -4058,32 +4043,6 @@ "node": ">= 0.10" } }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "license": "MIT", - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/create-ecdh": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", @@ -4544,15 +4503,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "license": "MIT" }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/default-browser": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.4.0.tgz", @@ -5285,15 +5235,6 @@ "errno": "cli.js" } }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, "node_modules/es-abstract": { "version": "1.24.1", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", @@ -6421,128 +6362,6 @@ "node": "*" } }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.1.0.tgz", - "integrity": "sha512-mpafl89VFPJmhnJ1ssH+8wmM2b50n+Rew5x42NeI2U78aRWgtkEtGmctp7iT16UjquJTjorEmIfESj3DxdW84Q==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.16.7", - "chalk": "^4.1.2", - "chokidar": "^4.0.1", - "cosmiconfig": "^8.2.0", - "deepmerge": "^4.2.2", - "fs-extra": "^10.0.0", - "memfs": "^3.4.1", - "minimatch": "^3.0.4", - "node-abort-controller": "^3.0.1", - "schema-utils": "^3.1.1", - "semver": "^7.3.5", - "tapable": "^2.2.1" - }, - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "typescript": ">3.6.0", - "webpack": "^5.11.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "license": "Unlicense", - "dependencies": { - "fs-monkey": "^1.0.4" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", - "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", @@ -6597,12 +6416,6 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, - "node_modules/fs-monkey": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.1.0.tgz", - "integrity": "sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==", - "license": "Unlicense" - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -8687,12 +8500,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "license": "MIT" - }, "node_modules/is-async-function": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", @@ -9915,12 +9722,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "license": "MIT" - }, "node_modules/load-grunt-config": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/load-grunt-config/-/load-grunt-config-4.0.1.tgz", @@ -10677,12 +10478,6 @@ "lower-case": "^1.1.1" } }, - "node_modules/node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", - "license": "MIT" - }, "node_modules/node-addon-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", @@ -11257,24 +11052,6 @@ "node": ">=0.8" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -11446,15 +11223,6 @@ "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "license": "MIT" }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/pbkdf2": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", diff --git a/package.json b/package.json index b47f18cd9d..17f14b32f7 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ "eslint": "^8.57.1", "eslint-plugin-react": "^7.37.0", "file-loader": "^6.2.0", - "fork-ts-checker-webpack-plugin": "^9.0.0", "gettext.js": "0.9.0", "git-rev-sync": "1.10.0", "gridster": "github:superdesk/gridster.js#885d0c9", @@ -169,10 +168,11 @@ "gettext-next-batch": "node ./tasks/gettext-next-batch.js", "gettext-update-po": "node ./tasks/gettext-update-po.js", "postinstall": "node ./tasks/patch-package.js && node tasks/generate-placeholder-file-for-extension-styles.js", - "test": "npm run lint && npm run unit && npm run verify-client-api-changes", + "test": "npm run lint && npm run typecheck && npm run unit && npm run verify-client-api-changes", "debug-unit-tests": "karma start --reporters=progress --browsers=Chrome", "unit": "karma start --single-run", - "lint": "python3 ./grep-lint.py && tsc -p scripts --noEmit && eslint --quiet --parser=@typescript-eslint/parser --ext .js --ext .jsx --ext .ts --ext .tsx scripts e2e/client tasks", + "lint": "python3 ./grep-lint.py && eslint --quiet --parser=@typescript-eslint/parser --ext .js --ext .jsx --ext .ts --ext .tsx scripts e2e/client tasks", + "typecheck": "node tasks/typecheck.js", "lint-fix": "eslint --fix --parser=@typescript-eslint/parser --ext .js --ext .jsx --ext .ts --ext .tsx scripts e2e/client tasks", "verify-client-api-changes": "node tasks/verify-client-api-changes.js" }, diff --git a/scripts/extensions/datetimeField/src/editor.tsx b/scripts/extensions/datetimeField/src/editor.tsx index 4975aa76d3..300be5007f 100644 --- a/scripts/extensions/datetimeField/src/editor.tsx +++ b/scripts/extensions/datetimeField/src/editor.tsx @@ -1,8 +1,6 @@ import {IEditorComponentProps} from 'superdesk-api'; import * as React from 'react'; -import set from 'date-fns/set'; -import format from 'date-fns/format'; -import addMinutes from 'date-fns/addMinutes'; +import {set, format, addMinutes} from 'date-fns'; import {DatePickerISO, TimePicker, Button, Switch} from 'superdesk-ui-framework/react'; import {superdesk} from './superdesk'; import {IConfig, IValueOperational} from './interfaces'; diff --git a/scripts/extensions/videoEditor/src/VideoTimeline/BarIcon.tsx b/scripts/extensions/videoEditor/src/VideoTimeline/BarIcon.tsx index 8824b47c6c..30c11d162b 100644 --- a/scripts/extensions/videoEditor/src/VideoTimeline/BarIcon.tsx +++ b/scripts/extensions/videoEditor/src/VideoTimeline/BarIcon.tsx @@ -11,7 +11,7 @@ export class BarIcon extends React.PureComponent { width="24" height="30" viewBox="0 0 24 24" - style={{position: 'absolute', top: -14}} + style={{position: 'absolute', insetBlockStart: -14}} > { />
@@ -274,7 +274,7 @@ export class VideoTimeline extends React.Component {
entry.isDirectory() && !SKIP.has(entry.name)) + .map((entry) => { + const root = path.join(EXTENSIONS_DIR, entry.name); + const tsconfig = [ + path.join(root, 'src', 'tsconfig.json'), + path.join(root, 'tsconfig.json'), + ].find((candidate) => fs.existsSync(candidate)); + + return {name: entry.name, root, tsconfig}; + }) + .filter(({root, tsconfig}) => tsconfig != null && buildsFromTypeScript(root)); +} + +function check({name, tsconfig}) { + process.stdout.write(`\n# ${name} (${path.relative(ROOT, tsconfig)})\n`); + + const {status} = spawnSync( + process.execPath, + [TSC, '--project', tsconfig, '--noEmit', '--pretty'], + {cwd: ROOT, stdio: 'inherit'} + ); + + return status === 0; +} + +const targets = [ + {name: 'core', tsconfig: path.join(ROOT, 'scripts', 'tsconfig.json')}, + ...extensionTargets(), +]; + +const failed = targets.filter((target) => !check(target)).map(({name}) => name); + +process.stdout.write(`\n${'='.repeat(60)}\n`); + +if (failed.length > 0) { + process.stdout.write(`Type-check FAILED: ${failed.join(', ')}\n`); + process.exit(1); // eslint-disable-line no-process-exit +} + +process.stdout.write(`Type-check passed (${targets.length} project${targets.length === 1 ? '' : 's'}).\n`); diff --git a/webpack.config.js b/webpack.config.js index 74b20e8acc..bb63a6845c 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -4,43 +4,8 @@ var lodash = require('lodash'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const NodePolyfillPlugin = require('node-polyfill-webpack-plugin'); -const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); const fs = require('fs'); -// Discover loaded extensions that still build from TypeScript sources so each -// one can get its own ForkTsCheckerWebpackPlugin instance. We start from the -// same loaded-extension set used by installExtensions, ignore unloaded -// extensions to avoid noise from optional per-extension deps, and treat an -// extension as migrated when its package.json `main` points to .ts or .tsx. -const getExtensionDirectoriesSync = require('./build-tools/src/extensions/get-extension-directories-sync'); - -// Only consumers (templates) ship superdesk.config.js; running webpack directly -// in superdesk-client-core (e.g. for tests) has no extensions to discover. -const loadedExtensions = fs.existsSync(path.join(process.cwd(), 'superdesk.config.js')) - ? getExtensionDirectoriesSync(process.cwd()) - : []; - -const migratedExtensionTsConfigs = loadedExtensions - .filter(({extensionRootPath}) => { - const pkgPath = path.join(extensionRootPath, 'package.json'); - - if (!fs.existsSync(pkgPath)) { - return false; - } - - const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')); - - return typeof pkg.main === 'string' && /\.(ts|tsx)$/.test(pkg.main); - }) - .map(({extensionRootPath}) => { - // Resolve the extension's tsconfig.json, checking src/ first then the package root. - return [ - path.join(extensionRootPath, 'src/tsconfig.json'), - path.join(extensionRootPath, 'tsconfig.json'), - ].find((candidate) => fs.existsSync(candidate)); - }) - .filter(Boolean); - function getModuleDir(moduleName) { return path.join( require.resolve( @@ -139,7 +104,7 @@ function applyDefaults(appConfig) { } } -// makeConfig creates a new configuration file based on the passed options. +// makeConfig creates a new webpack configuration. module.exports = function makeConfig(grunt) { var appConfigPath = path.join(process.cwd(), 'superdesk.config.js'); @@ -209,30 +174,6 @@ module.exports = function makeConfig(grunt) { new NodePolyfillPlugin({ excludeAliases: ['console'], }), - - // Type-check the core scripts tree. Extensions are checked by their - // own ForkTsCheckerWebpackPlugin instances below, and because - // ts-loader runs with transpileOnly: true, this is what makes core - // type errors fail the webpack build. - new ForkTsCheckerWebpackPlugin({ - typescript: { - configFile: path.join(__dirname, 'scripts/tsconfig.json'), - }, - }), - - // Give each loaded migrated extension its own checker, using the - // tsconfig discovered above. We silence its success logger to avoid - // one "No typescript errors found" line per extension; actual issues - // still flow through webpack's normal reporting. - ...migratedExtensionTsConfigs.map((absPath) => new ForkTsCheckerWebpackPlugin({ - typescript: { - configFile: absPath, - }, - logger: { - log: () => {}, // eslint-disable-line no-empty-function - error: (message) => process.stderr.write(String(message) + '\n'), - }, - })), ], resolve: {