From 35aa34e6ac95c9af4d7446a06544ff9f94e31927 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Thu, 25 Jun 2026 06:20:53 +0200 Subject: [PATCH 01/12] Prepare TypeScript migration (#1502) --- .github/workflows/build.yaml | 39 +++ .github/workflows/testing_apps.yml | 4 + .gitignore | 1 + .oxfmtrc.json | 7 +- CHANGELOG.md | 4 + eslint.config.js | 16 +- lib/WebpackConfig.js | 2 +- lib/config-generator.js | 2 +- ...ile-extension.js => get-file-extension.ts} | 2 +- .../{regexp-escaper.js => regexp-escaper.ts} | 5 +- .../{string-escaper.js => string-escaper.ts} | 5 +- package.json | 25 +- pnpm-lock.yaml | 315 +++++++++++++++--- test/bin/encore.js | 32 +- test/helpers/assert.js | 2 +- test/utils/get-file-extension.js | 2 +- test/utils/regexp-escaper.js | 2 +- test/utils/string-escaper.js | 2 +- tsconfig.json | 33 ++ 19 files changed, 415 insertions(+), 85 deletions(-) create mode 100644 .github/workflows/build.yaml rename lib/utils/{get-file-extension.js => get-file-extension.ts} (89%) rename lib/utils/{regexp-escaper.js => regexp-escaper.ts} (83%) rename lib/utils/{string-escaper.js => string-escaper.ts} (85%) create mode 100644 tsconfig.json diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 00000000..ef2e63cc --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,39 @@ +name: Build + +on: [push, pull_request] + +jobs: + build: + name: Type-check & build + runs-on: ubuntu-latest + permissions: {} + env: + # We don't want Puppeteer to automatically download a browser when dependencies are being installed + PUPPETEER_SKIP_DOWNLOAD: 'true' + + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + with: + persist-credentials: false + + - name: Install pnpm + uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 + + - name: Node ${{matrix.node-versions}} + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e + with: + node-version: '22.13.0' + cache: pnpm + + - name: Install pnpm Dependencies + run: pnpm install --frozen-lockfile + + - name: Type-check + run: pnpm type-check + + - name: Build (emit JS + type declarations) + run: pnpm build + + - name: Ensure type declarations were generated + run: test -f dist/index.d.ts diff --git a/.github/workflows/testing_apps.yml b/.github/workflows/testing_apps.yml index d9fe33e2..35afa68a 100644 --- a/.github/workflows/testing_apps.yml +++ b/.github/workflows/testing_apps.yml @@ -139,6 +139,10 @@ jobs: cache: ${{ matrix.app.pkg_manager }} cache-dependency-path: ${{ matrix.app.working_directory }}/${{ env.LOCKFILE }} + - name: Installing dependencies + run: | + pnpm install --frozen-lockfile + - name: Packing Encore run: pnpm pack --out webpack-encore.tgz diff --git a/.gitignore b/.gitignore index 6ea7c3a9..b7bbd660 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ node_modules/ npm-debug.log* /test_tmp +/dist webpack-encore.tgz diff --git a/.oxfmtrc.json b/.oxfmtrc.json index 9d9e7918..fd93ee22 100644 --- a/.oxfmtrc.json +++ b/.oxfmtrc.json @@ -1,6 +1,11 @@ { "$schema": "./node_modules/oxfmt/configuration_schema.json", - "ignorePatterns": [".github/PULL_REQUEST_TEMPLATE.md", "fixtures/**", "test_apps/**"], + "ignorePatterns": [ + ".github/PULL_REQUEST_TEMPLATE.md", + "fixtures/**", + "test_apps/**", + "dist/**" + ], "singleQuote": true, "semi": true, "trailingComma": "es5", diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a5ccc48..4165291d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 7.2.0 + +- Migrate internal code to TypeScript, ship package with type definitions (better DX and IDE support!) + ## 7.1.0 - Add support for `sass-loader` ^17.0.0 diff --git a/eslint.config.js b/eslint.config.js index 592109cf..c7045d6c 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -13,6 +13,7 @@ import jsdoc from 'eslint-plugin-jsdoc'; import nodePlugin from 'eslint-plugin-n'; import vitestPlugin from 'eslint-plugin-vitest'; import globals from 'globals'; +import tseslint from 'typescript-eslint'; export default [ js.configs.recommended, @@ -58,7 +59,6 @@ export default [ ], 'n/no-unsupported-features/node-builtins': ['error'], 'n/no-deprecated-api': 'error', - 'n/no-missing-import': 'error', 'n/no-missing-require': 'off', 'n/no-unpublished-bin': 'error', 'n/no-unpublished-import': 'error', @@ -84,6 +84,20 @@ file that was distributed with this source code.`, }, }, }, + { + files: ['**/*.ts'], + languageOptions: { + parser: tseslint.parser, + }, + rules: { + // The TypeScript compiler reports unused symbols; the core rule + // produces false positives on type-only syntax. + 'no-unused-vars': 'off', + // In TypeScript files, types live in the signature, not in JSDoc. + 'jsdoc/require-param': 'off', + 'jsdoc/require-returns': 'off', + }, + }, { files: ['test/**/*'], languageOptions: { diff --git a/lib/WebpackConfig.js b/lib/WebpackConfig.js index 11bebd07..98bb8606 100644 --- a/lib/WebpackConfig.js +++ b/lib/WebpackConfig.js @@ -43,7 +43,7 @@ import path from 'path'; import pathUtil from './config/path-util.js'; import featuresHelper from './features.js'; import logger from './logger.js'; -import regexpEscaper from './utils/regexp-escaper.js'; +import regexpEscaper from './utils/regexp-escaper.ts'; /** * @param {RuntimeConfig|null} runtimeConfig diff --git a/lib/config-generator.js b/lib/config-generator.js index b484cf4e..553a7e40 100644 --- a/lib/config-generator.js +++ b/lib/config-generator.js @@ -46,7 +46,7 @@ import vuePluginUtil from './plugins/vue.js'; import applyOptionsCallback from './utils/apply-options-callback.js'; import copyEntryTmpName from './utils/copyEntryTmpName.js'; import getVueVersion from './utils/get-vue-version.js'; -import stringEscaper from './utils/string-escaper.js'; +import stringEscaper from './utils/string-escaper.ts'; class ConfigGenerator { /** diff --git a/lib/utils/get-file-extension.js b/lib/utils/get-file-extension.ts similarity index 89% rename from lib/utils/get-file-extension.js rename to lib/utils/get-file-extension.ts index 04523418..2488d235 100644 --- a/lib/utils/get-file-extension.js +++ b/lib/utils/get-file-extension.ts @@ -10,7 +10,7 @@ import path from 'path'; import url from 'url'; -export default function (filename) { +export default function (filename: string): string { const parsedFilename = new url.URL(filename, 'http://foo'); const extension = path.extname(parsedFilename.pathname); return extension ? extension.slice(1) : ''; diff --git a/lib/utils/regexp-escaper.js b/lib/utils/regexp-escaper.ts similarity index 83% rename from lib/utils/regexp-escaper.js rename to lib/utils/regexp-escaper.ts index 1b5aa17a..6078d8c8 100644 --- a/lib/utils/regexp-escaper.js +++ b/lib/utils/regexp-escaper.ts @@ -11,10 +11,7 @@ * Function that escapes a string so it can be used in a RegExp. * * See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping - * - * @param {string} str - * @returns {string} */ -export default function regexpEscaper(str) { +export default function regexpEscaper(str: string): string { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } diff --git a/lib/utils/string-escaper.js b/lib/utils/string-escaper.ts similarity index 85% rename from lib/utils/string-escaper.js rename to lib/utils/string-escaper.ts index c02d073d..b997e5b4 100644 --- a/lib/utils/string-escaper.js +++ b/lib/utils/string-escaper.ts @@ -13,10 +13,7 @@ * * This is imperfect - is used to escape a filename (so, mostly, * it needs to escape the Window path slashes). - * - * @param {string} str - * @returns {string} */ -export default function stringEscaper(str) { +export default function stringEscaper(str: string): string { return str.replace(/\\/g, '\\\\').replace(/\x27/g, '\\\x27'); } diff --git a/package.json b/package.json index 4fd1d0db..45e2358d 100644 --- a/package.json +++ b/package.json @@ -3,18 +3,30 @@ "version": "7.1.0", "description": "Webpack Encore is a simpler way to integrate Webpack into your application", "type": "module", + "types": "./dist/index.d.ts", "exports": { - ".": "./index.js", - "./lib/plugins/plugin-priorities.js": "./lib/plugins/plugin-priorities.js" + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./lib/plugins/plugin-priorities.js": { + "types": "./dist/lib/plugins/plugin-priorities.d.ts", + "default": "./dist/lib/plugins/plugin-priorities.js" + } }, "scripts": { + "build": "rm -fr dist/ && tsc", + "type-check": "tsc --noEmit", + "prepare": "pnpm build", + "prepublishOnly": "pnpm type-check", + "pretest": "pnpm build", "test": "vitest run", "lint": "eslint lib test index.js eslint.config.js --report-unused-disable-directives --max-warnings=0", "fmt": "oxfmt", "fmt:check": "oxfmt --check" }, "bin": { - "encore": "bin/encore.js" + "encore": "dist/bin/encore.js" }, "repository": { "type": "git", @@ -57,6 +69,8 @@ "@hotwired/stimulus": "^3.0.0", "@symfony/mock-module": "file:fixtures/stimulus/mock-module", "@symfony/stimulus-bridge": "^3.0.0 || ^4.0.0", + "@tsconfig/node22": "^22.0.5", + "@types/node": "^22.18.0", "@vue/babel-plugin-jsx": "^3.0.0", "@vue/compiler-sfc": "^3.2.14", "autoprefixer": "^10.2.0", @@ -95,6 +109,7 @@ "svelte-loader": "^3.1.0", "ts-loader": "^9.0.0", "typescript": "^5.0.0 || ^6.0.0", + "typescript-eslint": "^8.39.0", "vitest": "^4.1.2", "vue": "^3.2.14", "vue-loader": "^17.0.0", @@ -243,9 +258,7 @@ } }, "files": [ - "lib/", - "bin/", - "index.js" + "dist/" ], "packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1df4afe7..ffc05200 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -84,6 +84,12 @@ importers: '@symfony/stimulus-bridge': specifier: ^3.0.0 || ^4.0.0 version: 4.0.1(@hotwired/stimulus@3.2.2) + '@tsconfig/node22': + specifier: ^22.0.5 + version: 22.0.5 + '@types/node': + specifier: ^22.18.0 + version: 22.20.0 '@vue/babel-plugin-jsx': specifier: ^3.0.0 version: 3.0.0(@babel/core@8.0.1) @@ -107,7 +113,7 @@ importers: version: 1.3.4(eslint@9.39.4(jiti@2.7.0)) eslint-plugin-import: specifier: ^2.32.0 - version: 2.32.0(eslint@9.39.4(jiti@2.7.0)) + version: 2.32.0(@typescript-eslint/parser@8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.4(jiti@2.7.0)) eslint-plugin-jsdoc: specifier: ^50.8.0 version: 50.8.0(eslint@9.39.4(jiti@2.7.0)) @@ -116,7 +122,7 @@ importers: version: 17.24.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) eslint-plugin-vitest: specifier: ^0.5.4 - version: 0.5.4(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.6(@types/node@25.8.0)(vite@8.0.13(@types/node@25.8.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1))) + version: 0.5.4(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.6(@types/node@22.20.0)(vite@8.0.13(@types/node@22.20.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1))) fork-ts-checker-webpack-plugin: specifier: ^7.0.0 || ^8.0.0 || ^9.0.0 version: 9.1.0(typescript@6.0.3)(webpack@5.106.2) @@ -188,19 +194,22 @@ importers: version: 8.1.3(stylus@0.63.0)(webpack@5.106.2) svelte: specifier: ^3.50.0 || ^4.2.2 || ^5.0.0 - version: 5.55.7(@typescript-eslint/types@8.59.3) + version: 5.55.7(@typescript-eslint/types@8.62.0) svelte-loader: specifier: ^3.1.0 - version: 3.2.4(svelte@5.55.7(@typescript-eslint/types@8.59.3)) + version: 3.2.4(svelte@5.55.7(@typescript-eslint/types@8.62.0)) ts-loader: specifier: ^9.0.0 version: 9.5.7(typescript@6.0.3)(webpack@5.106.2) typescript: specifier: ^5.0.0 || ^6.0.0 version: 6.0.3 + typescript-eslint: + specifier: ^8.39.0 + version: 8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) vitest: specifier: ^4.1.2 - version: 4.1.6(@types/node@25.8.0)(vite@8.0.13(@types/node@25.8.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1)) + version: 4.1.6(@types/node@22.20.0)(vite@8.0.13(@types/node@22.20.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1)) vue: specifier: ^3.2.14 version: 3.5.34(typescript@6.0.3) @@ -1587,6 +1596,9 @@ packages: peerDependencies: '@hotwired/stimulus': ^3.0 + '@tsconfig/node22@22.0.5': + resolution: {integrity: sha512-hLf2ld+sYN/BtOJjHUWOk568dvjFQkHnLNa6zce25GIH+vxKfvTgm3qpaH6ToF5tu/NN0IH66s+Bb5wElHrLcw==} + '@tybys/wasm-util@0.10.2': resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} @@ -1647,8 +1659,8 @@ packages: '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - '@types/node@25.8.0': - resolution: {integrity: sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ==} + '@types/node@22.20.0': + resolution: {integrity: sha512-QWlFW2wf3nTjC13/DqRnBpR4ZO36VJH/JVBkA/vcnmbTBNQIlnObqyqZE1tUR7+Ni23Lda8R1BxMfbXRpCUx5g==} '@types/qs@6.15.1': resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==} @@ -1683,10 +1695,48 @@ packages: '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@typescript-eslint/eslint-plugin@8.62.0': + resolution: {integrity: sha512-o+mpz7EYiMzXoySXiKmzlabIvTVqUuK5yLrAedRPRDA0IpPFMUV1IXt6OqljIxX/kumN6EjUYp41Hqelh6p/Dw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.62.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/parser@8.62.0': + resolution: {integrity: sha512-dzHeT2gySzZtLDsuqxU9AkYgIsQoHAHtRBpOqM+Ofzx1Bwrd2RcCjQJ+6iQbsHOIR6NS33bF2W1k3blN1zLDrA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/project-service@8.62.0': + resolution: {integrity: sha512-wexnCqiTg7BOGtbLDftYpRWlmLq4xfoMd7BKFR6Y75sZS3QmRKLdN3yWLhmIYgqMmP/OXWpj3H8odkb5nGURCQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/scope-manager@7.18.0': resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/scope-manager@8.62.0': + resolution: {integrity: sha512-1lX38kNxXIRb8mEc3lbq5mdHq1Pf2+U0nFU65KfT18mtPxxl0fvjuEE92mHuXPuCtElJhOrddOpyMlM3Z0umEA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.62.0': + resolution: {integrity: sha512-y2GAdB6ykaXUvuspbYnizQc4oDDz0Tz/Yc7iWrXf9mx8vm/L/0vLHCe0tS2boG96Zy+DivnVDQ9ZUEWoHqqx1g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/type-utils@8.62.0': + resolution: {integrity: sha512-+g5O3j0w2ldzC86Pv6fvbO/xhAonbJFIdf/MKQ1d30gndlsVzUOE83ldfSE15Qrl9fhFjK6AovHs5Wpp6vx86w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/types@7.18.0': resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} engines: {node: ^18.18.0 || >=20.0.0} @@ -1695,6 +1745,10 @@ packages: resolution: {integrity: sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.62.0': + resolution: {integrity: sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@7.18.0': resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} engines: {node: ^18.18.0 || >=20.0.0} @@ -1704,16 +1758,33 @@ packages: typescript: optional: true + '@typescript-eslint/typescript-estree@8.62.0': + resolution: {integrity: sha512-+hVbNxtW64pIcZWDPGbyaKF7vp2IBTVY5ma1blwwksrjdsbdqqEKvJWMGbBofei4F6Dovx1M0RJgoFeNu2279A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/utils@7.18.0': resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 + '@typescript-eslint/utils@8.62.0': + resolution: {integrity: sha512-82r66fi9zYwZ+mTq3vKgwjbZ1PVk/DJzrXFLpG6RnBbdvH8TEGVHIs9H4d2drhkOzf0syZuD/OZvvlu6GDbP4g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/visitor-keys@7.18.0': resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/visitor-keys@8.62.0': + resolution: {integrity: sha512-CY3uyFSRbcQv3nnSv8S0+lDftMVz6P963PoRlxrV7ew/Md564g9ut60PYzdLM5qW4jFn93GBF+Soi90ISAN+GQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@vitest/expect@4.1.6': resolution: {integrity: sha512-7EHDquPthALSV0jhhjgEW8FXaviMx7rSqu8W6oqCoAuOhKov814P99QDV1pxMA3QPv21YudvJngIhjrNI4opLg==} @@ -2029,6 +2100,10 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + bare-events@2.8.3: resolution: {integrity: sha512-HdUm8EMQBLaJvGUdidNNbqpA1kYkwNcb+MYxkxCLAPJGQzlv9J0C24h8V65Z4c5GLd/JEALDvpFCQgpLJqc0zw==} peerDependencies: @@ -2108,6 +2183,10 @@ packages: brace-expansion@2.1.0: resolution: {integrity: sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==} + brace-expansion@5.0.6: + resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} + engines: {node: 18 || 20 || >=22} + braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} @@ -3055,6 +3134,10 @@ packages: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + image-size@0.5.5: resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} engines: {node: '>=0.10.0'} @@ -3553,6 +3636,10 @@ packages: minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} + minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} @@ -4531,6 +4618,12 @@ packages: peerDependencies: typescript: '>=4.2.0' + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + ts-declaration-location@1.0.7: resolution: {integrity: sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==} peerDependencies: @@ -4583,6 +4676,13 @@ packages: typed-query-selector@2.12.2: resolution: {integrity: sha512-EOPFbyIub4ngnEdqi2yOcNeDLaX/0jcE1JoAXQDDMIthap7FoN795lc/SHfIq2d416VufXpM8z/lD+WRm2gfOQ==} + typescript-eslint@8.62.0: + resolution: {integrity: sha512-8QxXi+ZACKX0kaqO4gY8kn0RSD9gFfaHDWwjqtEN48aWCBkX4MJaufWN+c3BzlrXLOxfywDL8CaoqUwcRq4j4Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + typescript@6.0.3: resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} engines: {node: '>=14.17'} @@ -4597,8 +4697,8 @@ packages: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} - undici-types@7.24.6: - resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} unicode-canonical-property-names-ecmascript@2.0.1: resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} @@ -6252,6 +6352,8 @@ snapshots: loader-utils: 3.3.1 schema-utils: 4.3.3 + '@tsconfig/node22@22.0.5': {} + '@tybys/wasm-util@0.10.2': dependencies: tslib: 2.8.1 @@ -6260,11 +6362,11 @@ snapshots: '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 25.8.0 + '@types/node': 22.20.0 '@types/bonjour@3.5.13': dependencies: - '@types/node': 25.8.0 + '@types/node': 22.20.0 '@types/chai@5.2.3': dependencies: @@ -6274,11 +6376,11 @@ snapshots: '@types/connect-history-api-fallback@1.5.4': dependencies: '@types/express-serve-static-core': 4.19.8 - '@types/node': 25.8.0 + '@types/node': 22.20.0 '@types/connect@3.4.38': dependencies: - '@types/node': 25.8.0 + '@types/node': 22.20.0 '@types/deep-eql@4.0.2': {} @@ -6298,7 +6400,7 @@ snapshots: '@types/express-serve-static-core@4.19.8': dependencies: - '@types/node': 25.8.0 + '@types/node': 22.20.0 '@types/qs': 6.15.1 '@types/range-parser': 1.2.7 '@types/send': 1.2.1 @@ -6316,7 +6418,7 @@ snapshots: '@types/http-proxy@1.17.17': dependencies: - '@types/node': 25.8.0 + '@types/node': 22.20.0 '@types/jsesc@2.5.1': {} @@ -6326,9 +6428,9 @@ snapshots: '@types/mime@1.3.5': {} - '@types/node@25.8.0': + '@types/node@22.20.0': dependencies: - undici-types: 7.24.6 + undici-types: 6.21.0 '@types/qs@6.15.1': {} @@ -6339,11 +6441,11 @@ snapshots: '@types/send@0.17.6': dependencies: '@types/mime': 1.3.5 - '@types/node': 25.8.0 + '@types/node': 22.20.0 '@types/send@1.2.1': dependencies: - '@types/node': 25.8.0 + '@types/node': 22.20.0 '@types/serve-index@1.9.4': dependencies: @@ -6352,12 +6454,12 @@ snapshots: '@types/serve-static@1.15.10': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 25.8.0 + '@types/node': 22.20.0 '@types/send': 0.17.6 '@types/sockjs@0.3.36': dependencies: - '@types/node': 25.8.0 + '@types/node': 22.20.0 '@types/trusted-types@2.0.7': {} @@ -6365,17 +6467,77 @@ snapshots: '@types/ws@8.18.1': dependencies: - '@types/node': 25.8.0 + '@types/node': 22.20.0 + + '@typescript-eslint/eslint-plugin@8.62.0(@typescript-eslint/parser@8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.62.0 + '@typescript-eslint/type-utils': 8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/utils': 8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.62.0 + eslint: 9.39.4(jiti@2.7.0) + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.62.0 + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/typescript-estree': 8.62.0(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.62.0 + debug: 4.4.3 + eslint: 9.39.4(jiti@2.7.0) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.62.0(typescript@6.0.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@6.0.3) + '@typescript-eslint/types': 8.62.0 + debug: 4.4.3 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color '@typescript-eslint/scope-manager@7.18.0': dependencies: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/visitor-keys': 7.18.0 + '@typescript-eslint/scope-manager@8.62.0': + dependencies: + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/visitor-keys': 8.62.0 + + '@typescript-eslint/tsconfig-utils@8.62.0(typescript@6.0.3)': + dependencies: + typescript: 6.0.3 + + '@typescript-eslint/type-utils@8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/typescript-estree': 8.62.0(typescript@6.0.3) + '@typescript-eslint/utils': 8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) + debug: 4.4.3 + eslint: 9.39.4(jiti@2.7.0) + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/types@7.18.0': {} '@typescript-eslint/types@8.59.3': {} + '@typescript-eslint/types@8.62.0': {} + '@typescript-eslint/typescript-estree@7.18.0(typescript@6.0.3)': dependencies: '@typescript-eslint/types': 7.18.0 @@ -6391,6 +6553,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.62.0(typescript@6.0.3)': + dependencies: + '@typescript-eslint/project-service': 8.62.0(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@6.0.3) + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/visitor-keys': 8.62.0 + debug: 4.4.3 + minimatch: 10.2.5 + semver: 7.8.0 + tinyglobby: 0.2.16 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@7.18.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.7.0)) @@ -6402,11 +6579,27 @@ snapshots: - supports-color - typescript + '@typescript-eslint/utils@8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.7.0)) + '@typescript-eslint/scope-manager': 8.62.0 + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/typescript-estree': 8.62.0(typescript@6.0.3) + eslint: 9.39.4(jiti@2.7.0) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/visitor-keys@7.18.0': dependencies: '@typescript-eslint/types': 7.18.0 eslint-visitor-keys: 3.4.3 + '@typescript-eslint/visitor-keys@8.62.0': + dependencies: + '@typescript-eslint/types': 8.62.0 + eslint-visitor-keys: 5.0.1 + '@vitest/expect@4.1.6': dependencies: '@standard-schema/spec': 1.1.0 @@ -6416,13 +6609,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.6(vite@8.0.13(@types/node@25.8.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1))': + '@vitest/mocker@4.1.6(vite@8.0.13(@types/node@22.20.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1))': dependencies: '@vitest/spy': 4.1.6 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.13(@types/node@25.8.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1) + vite: 8.0.13(@types/node@22.20.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1) '@vitest/pretty-format@4.1.6': dependencies: @@ -6811,6 +7004,8 @@ snapshots: balanced-match@1.0.2: {} + balanced-match@4.0.4: {} + bare-events@2.8.3: {} bare-fs@4.7.1: @@ -6892,6 +7087,10 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.6: + dependencies: + balanced-match: 4.0.4 + braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -7389,10 +7588,11 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(eslint-import-resolver-node@0.3.10)(eslint@9.39.4(jiti@2.7.0)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint@9.39.4(jiti@2.7.0)): dependencies: debug: 3.2.7 optionalDependencies: + '@typescript-eslint/parser': 8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) eslint: 9.39.4(jiti@2.7.0) eslint-import-resolver-node: 0.3.10 transitivePeerDependencies: @@ -7409,7 +7609,7 @@ snapshots: dependencies: eslint: 9.39.4(jiti@2.7.0) - eslint-plugin-import@2.32.0(eslint@9.39.4(jiti@2.7.0)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.4(jiti@2.7.0)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -7420,7 +7620,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.39.4(jiti@2.7.0) eslint-import-resolver-node: 0.3.10 - eslint-module-utils: 2.12.1(eslint-import-resolver-node@0.3.10)(eslint@9.39.4(jiti@2.7.0)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint@9.39.4(jiti@2.7.0)) hasown: 2.0.3 is-core-module: 2.16.2 is-glob: 4.0.3 @@ -7431,6 +7631,8 @@ snapshots: semver: 6.3.1 string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -7467,12 +7669,12 @@ snapshots: transitivePeerDependencies: - typescript - eslint-plugin-vitest@0.5.4(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.6(@types/node@25.8.0)(vite@8.0.13(@types/node@25.8.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1))): + eslint-plugin-vitest@0.5.4(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.6(@types/node@22.20.0)(vite@8.0.13(@types/node@22.20.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1))): dependencies: '@typescript-eslint/utils': 7.18.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) eslint: 9.39.4(jiti@2.7.0) optionalDependencies: - vitest: 4.1.6(@types/node@25.8.0)(vite@8.0.13(@types/node@25.8.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1)) + vitest: 4.1.6(@types/node@22.20.0)(vite@8.0.13(@types/node@22.20.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1)) transitivePeerDependencies: - supports-color - typescript @@ -7553,11 +7755,11 @@ snapshots: dependencies: estraverse: 5.3.0 - esrap@2.2.8(@typescript-eslint/types@8.59.3): + esrap@2.2.8(@typescript-eslint/types@8.62.0): dependencies: '@jridgewell/sourcemap-codec': 1.5.5 optionalDependencies: - '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/types': 8.62.0 esrecurse@4.3.0: dependencies: @@ -7984,6 +8186,8 @@ snapshots: ignore@5.3.2: {} + ignore@7.0.5: {} + image-size@0.5.5: optional: true @@ -8186,7 +8390,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 25.8.0 + '@types/node': 22.20.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -8420,6 +8624,10 @@ snapshots: minimalistic-assert@1.0.1: {} + minimatch@10.2.5: + dependencies: + brace-expansion: 5.0.6 + minimatch@3.1.5: dependencies: brace-expansion: 1.1.14 @@ -9368,18 +9576,18 @@ snapshots: svelte-dev-helper@1.1.9: {} - svelte-hmr@0.14.12(svelte@5.55.7(@typescript-eslint/types@8.59.3)): + svelte-hmr@0.14.12(svelte@5.55.7(@typescript-eslint/types@8.62.0)): dependencies: - svelte: 5.55.7(@typescript-eslint/types@8.59.3) + svelte: 5.55.7(@typescript-eslint/types@8.62.0) - svelte-loader@3.2.4(svelte@5.55.7(@typescript-eslint/types@8.59.3)): + svelte-loader@3.2.4(svelte@5.55.7(@typescript-eslint/types@8.62.0)): dependencies: loader-utils: 2.0.4 - svelte: 5.55.7(@typescript-eslint/types@8.59.3) + svelte: 5.55.7(@typescript-eslint/types@8.62.0) svelte-dev-helper: 1.1.9 - svelte-hmr: 0.14.12(svelte@5.55.7(@typescript-eslint/types@8.59.3)) + svelte-hmr: 0.14.12(svelte@5.55.7(@typescript-eslint/types@8.62.0)) - svelte@5.55.7(@typescript-eslint/types@8.59.3): + svelte@5.55.7(@typescript-eslint/types@8.62.0): dependencies: '@jridgewell/remapping': 2.3.5 '@jridgewell/sourcemap-codec': 1.5.5 @@ -9392,7 +9600,7 @@ snapshots: clsx: 2.1.1 devalue: 5.8.1 esm-env: 1.2.2 - esrap: 2.2.8(@typescript-eslint/types@8.59.3) + esrap: 2.2.8(@typescript-eslint/types@8.62.0) is-reference: 3.0.3 locate-character: 3.0.0 magic-string: 0.30.21 @@ -9492,6 +9700,10 @@ snapshots: dependencies: typescript: 6.0.3 + ts-api-utils@2.5.0(typescript@6.0.3): + dependencies: + typescript: 6.0.3 + ts-declaration-location@1.0.7(typescript@6.0.3): dependencies: picomatch: 4.0.4 @@ -9566,6 +9778,17 @@ snapshots: typed-query-selector@2.12.2: {} + typescript-eslint@8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.62.0(@typescript-eslint/parser@8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/parser': 8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.62.0(typescript@6.0.3) + '@typescript-eslint/utils': 8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) + eslint: 9.39.4(jiti@2.7.0) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + typescript@6.0.3: {} uglify-js@3.19.3: @@ -9578,7 +9801,7 @@ snapshots: has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 - undici-types@7.24.6: {} + undici-types@6.21.0: {} unicode-canonical-property-names-ecmascript@2.0.1: {} @@ -9621,7 +9844,7 @@ snapshots: vary@1.1.2: {} - vite@8.0.13(@types/node@25.8.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1): + vite@8.0.13(@types/node@22.20.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 @@ -9629,7 +9852,7 @@ snapshots: rolldown: 1.0.1 tinyglobby: 0.2.16 optionalDependencies: - '@types/node': 25.8.0 + '@types/node': 22.20.0 esbuild: 0.28.1 fsevents: 2.3.3 jiti: 2.7.0 @@ -9638,10 +9861,10 @@ snapshots: stylus: 0.63.0 terser: 5.47.1 - vitest@4.1.6(@types/node@25.8.0)(vite@8.0.13(@types/node@25.8.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1)): + vitest@4.1.6(@types/node@22.20.0)(vite@8.0.13(@types/node@22.20.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1)): dependencies: '@vitest/expect': 4.1.6 - '@vitest/mocker': 4.1.6(vite@8.0.13(@types/node@25.8.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1)) + '@vitest/mocker': 4.1.6(vite@8.0.13(@types/node@22.20.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1)) '@vitest/pretty-format': 4.1.6 '@vitest/runner': 4.1.6 '@vitest/snapshot': 4.1.6 @@ -9658,10 +9881,10 @@ snapshots: tinyexec: 1.1.2 tinyglobby: 0.2.16 tinyrainbow: 3.1.0 - vite: 8.0.13(@types/node@25.8.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1) + vite: 8.0.13(@types/node@22.20.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.4)(sass@1.99.0)(stylus@0.63.0)(terser@5.47.1) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 25.8.0 + '@types/node': 22.20.0 transitivePeerDependencies: - msw diff --git a/test/bin/encore.js b/test/bin/encore.js index 08c32c14..9b3b5275 100644 --- a/test/bin/encore.js +++ b/test/bin/encore.js @@ -39,7 +39,7 @@ describe.sequential('bin/encore.js', function () { fs.writeFileSync( path.join(testDir, 'webpack.config.js'), ` -import Encore from '../../index.js'; +import Encore from '../../dist/index.js'; Encore .enableSingleRuntimeChunk() .setOutputPath('build/') @@ -51,7 +51,7 @@ export default await Encore.getWebpackConfig(); ` ); - const binPath = path.resolve(import.meta.dirname, '../', '../', 'bin', 'encore.js'); + const binPath = path.resolve(projectDir, 'dist', 'bin', 'encore.js'); const { stdout } = await exec(`node ${binPath} dev --context=${testDir}`, { cwd: testDir }); expect(stdout).toContain('Compiled successfully'); @@ -67,7 +67,7 @@ export default await Encore.getWebpackConfig(); fs.writeFileSync( path.join(testDir, 'webpack.config.js'), ` -import Encore from '../../index.js'; +import Encore from '../../dist/index.js'; Encore .enableSingleRuntimeChunk() .setOutputPath('build/') @@ -79,7 +79,7 @@ export default await Encore.getWebpackConfig(); ` ); - const binPath = path.resolve(import.meta.dirname, '../', '../', 'bin', 'encore.js'); + const binPath = path.resolve(projectDir, 'dist', 'bin', 'encore.js'); const { stdout } = await exec(`node ${binPath} dev --json --context=${testDir}`, { cwd: testDir, }); @@ -108,7 +108,7 @@ export default await Encore.getWebpackConfig(); fs.writeFileSync( path.join(testDir, 'webpack.config.js'), ` -import Encore from '../../index.js'; +import Encore from '../../dist/index.js'; Encore .enableSingleRuntimeChunk() .setOutputPath('build/') @@ -120,7 +120,7 @@ export default await Encore.getWebpackConfig(); ` ); - const binPath = path.resolve(import.meta.dirname, '../', '../', 'bin', 'encore.js'); + const binPath = path.resolve(projectDir, 'dist', 'bin', 'encore.js'); const { stdout } = await exec(`node ${binPath} dev --profile --context=${testDir}`, { cwd: testDir, }); @@ -137,7 +137,7 @@ export default await Encore.getWebpackConfig(); fs.writeFileSync( path.join(testDir, 'webpack.config.js'), ` -import Encore from '../../index.js'; +import Encore from '../../dist/index.js'; Encore .enableSingleRuntimeChunk() .setOutputPath('build/') @@ -149,7 +149,7 @@ export default await Encore.getWebpackConfig(); ` ); - const binPath = path.resolve(import.meta.dirname, '../', '../', 'bin', 'encore.js'); + const binPath = path.resolve(projectDir, 'dist', 'bin', 'encore.js'); const { stdout } = await exec( `node ${binPath} dev --keep-public-path --context=${testDir}`, { cwd: testDir } @@ -173,7 +173,7 @@ export default await Encore.getWebpackConfig(); fs.writeFileSync( path.join(testDir, 'webpack.config.js'), ` -import Encore from '../../index.js'; +import Encore from '../../dist/index.js'; Encore .enableSingleRuntimeChunk() .setOutputPath('build/') @@ -186,7 +186,7 @@ export default await Encore.getWebpackConfig(); ` ); - const binPath = path.resolve(import.meta.dirname, '../', '../', 'bin', 'encore.js'); + const binPath = path.resolve(projectDir, 'dist', 'bin', 'encore.js'); try { await exec(`node ${binPath} dev --context=${testDir}`, { cwd: testDir }); } catch (err) { @@ -216,7 +216,7 @@ export default await Encore.getWebpackConfig(); fs.writeFileSync( path.join(testDir, 'webpack.config.js'), ` -import Encore from '../../index.js'; +import Encore from '../../dist/index.js'; Encore .enableSingleRuntimeChunk() .setOutputPath('build/') @@ -228,7 +228,7 @@ export default await Encore.getWebpackConfig(); ` ); - const binPath = path.resolve(import.meta.dirname, '../', '../', 'bin', 'encore.js'); + const binPath = path.resolve(projectDir, 'dist', 'bin', 'encore.js'); const port = await getPort(); const abortController = new AbortController(); @@ -287,7 +287,7 @@ export default await Encore.getWebpackConfig(); fs.writeFileSync( path.join(testDir, 'webpack.config.js'), ` -import Encore from '../../index.js'; +import Encore from '../../dist/index.js'; Encore .enableSingleRuntimeChunk() .setOutputPath('build/') @@ -299,7 +299,7 @@ export default await Encore.getWebpackConfig(); ` ); - const binPath = path.resolve(import.meta.dirname, '../', '../', 'bin', 'encore.js'); + const binPath = path.resolve(projectDir, 'dist', 'bin', 'encore.js'); const port = await getPort(); const abortController = new AbortController(); @@ -375,7 +375,7 @@ export default await Encore.getWebpackConfig(); fs.writeFileSync( path.join(testDir, 'webpack.config.js'), ` -import Encore from '../../index.js'; +import Encore from '../../dist/index.js'; Encore .enableSingleRuntimeChunk() .setOutputPath('build/') @@ -387,7 +387,7 @@ export default await Encore.getWebpackConfig(); ` ); - const binPath = path.resolve(projectDir, 'bin', 'encore.js'); + const binPath = path.resolve(projectDir, 'dist', 'bin', 'encore.js'); const port = await getPort(); try { diff --git a/test/helpers/assert.js b/test/helpers/assert.js index 29cc96bf..010d7137 100644 --- a/test/helpers/assert.js +++ b/test/helpers/assert.js @@ -12,7 +12,7 @@ import path from 'path'; import { expect } from 'vitest'; -import regexEscaper from '../../lib/utils/regexp-escaper.js'; +import regexEscaper from '../../lib/utils/regexp-escaper.ts'; const loadManifest = function (webpackConfig) { return JSON.parse( diff --git a/test/utils/get-file-extension.js b/test/utils/get-file-extension.js index 218ed150..c9433d57 100644 --- a/test/utils/get-file-extension.js +++ b/test/utils/get-file-extension.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import getFileExtension from '../../lib/utils/get-file-extension.js'; +import getFileExtension from '../../lib/utils/get-file-extension.ts'; describe('get-file-extension', function () { it('returns the extension of simple filenames', function () { diff --git a/test/utils/regexp-escaper.js b/test/utils/regexp-escaper.js index 4975713d..d6140dc3 100644 --- a/test/utils/regexp-escaper.js +++ b/test/utils/regexp-escaper.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import regexpEscaper from '../../lib/utils/regexp-escaper.js'; +import regexpEscaper from '../../lib/utils/regexp-escaper.ts'; describe('regexp-escaper', function () { it('escapes things properly', function () { diff --git a/test/utils/string-escaper.js b/test/utils/string-escaper.js index 3fb5d228..bbfd8c3b 100644 --- a/test/utils/string-escaper.js +++ b/test/utils/string-escaper.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import stringEscaper from '../../lib/utils/string-escaper.js'; +import stringEscaper from '../../lib/utils/string-escaper.ts'; function expectEvaledStringToEqual(str, expectedStr) { // put the string in quotes & eval it: should match original diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..9a4b7cea --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,33 @@ +{ + // Inspired by https://www.totaltypescript.com/tsconfig-cheat-sheet + "extends": "@tsconfig/node22/tsconfig.json", + "compilerOptions": { + // Base options + "esModuleInterop": true, + "skipLibCheck": true, + "allowJs": true, + "resolveJsonModule": true, + "moduleDetection": "force", + "isolatedModules": true, + "verbatimModuleSyntax": true, + "erasableSyntaxOnly": true, + "allowImportingTsExtensions": true, + "rewriteRelativeImportExtensions": true, + + // Library build + "rootDir": ".", + "outDir": "dist", + "declaration": true, + "noEmitOnError": true, + + // Strictness + "strict": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + + // Types + "types": ["node"] + }, + "include": ["index.ts", "index.js", "lib/**/*.ts", "lib/**/*.js", "bin/**/*.ts", "bin/**/*.js"], + "exclude": ["node_modules", "dist", "test", "test_apps", "fixtures", "test_tmp"] +} From cfc1f0c5d67d6deb41b333fbe951599c88a9592b Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Thu, 25 Jun 2026 07:03:40 +0200 Subject: [PATCH 02/12] [TypeScript] Migrate `lib/utils/*` (#1504) --- eslint.config.js | 5 +++++ lib/EncoreProxy.js | 2 +- lib/config-generator.js | 6 ++--- lib/config/parse-runtime.js | 2 +- .../transformers/missing-loader.js | 2 +- lib/loaders/babel.js | 2 +- lib/loaders/css-extract.js | 2 +- lib/loaders/css.js | 2 +- lib/loaders/handlebars.js | 2 +- lib/loaders/less.js | 2 +- lib/loaders/sass.js | 2 +- lib/loaders/stylus.js | 2 +- lib/loaders/typescript.js | 2 +- lib/loaders/vue.js | 4 ++-- lib/plugins/css-minimizer.js | 4 ++-- lib/plugins/define.js | 2 +- lib/plugins/delete-unused-entries.js | 2 +- lib/plugins/forked-ts-types.js | 2 +- lib/plugins/friendly-errors.js | 2 +- lib/plugins/js-minimizer.js | 4 ++-- lib/plugins/manifest.js | 6 ++--- lib/plugins/mini-css-extract.js | 2 +- lib/plugins/notifier.js | 2 +- ...-callback.js => apply-options-callback.ts} | 22 +++++++++---------- ...opyEntryTmpName.js => copyEntryTmpName.ts} | 0 ...{get-vue-version.js => get-vue-version.ts} | 11 ++-------- ...elper.js => manifest-key-prefix-helper.ts} | 9 ++------ .../{minifier-check.js => minifier-check.ts} | 14 ++++-------- lib/utils/{package-up.js => package-up.ts} | 22 +++++++------------ .../{pretty-error.js => pretty-error.ts} | 18 ++++++--------- lib/webpack/entry-points-plugin.js | 2 +- package.json | 1 + pnpm-lock.yaml | 8 +++++++ test/functional.js | 2 +- test/plugins/css-minimizer.js | 2 +- test/plugins/js-minimizer.js | 2 +- test/utils/apply-options-callback.js | 2 +- test/utils/get-vue-version.js | 2 +- test/utils/minifier-check.js | 2 +- test/utils/package-up.js | 2 +- 40 files changed, 84 insertions(+), 100 deletions(-) rename lib/utils/{apply-options-callback.js => apply-options-callback.ts} (53%) rename lib/utils/{copyEntryTmpName.js => copyEntryTmpName.ts} (100%) rename lib/utils/{get-vue-version.js => get-vue-version.ts} (87%) rename lib/utils/{manifest-key-prefix-helper.js => manifest-key-prefix-helper.ts} (81%) rename lib/utils/{minifier-check.js => minifier-check.ts} (87%) rename lib/utils/{package-up.js => package-up.ts} (64%) rename lib/utils/{pretty-error.js => pretty-error.ts} (66%) diff --git a/eslint.config.js b/eslint.config.js index c7045d6c..854037f5 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -96,6 +96,11 @@ file that was distributed with this source code.`, // In TypeScript files, types live in the signature, not in JSDoc. 'jsdoc/require-param': 'off', 'jsdoc/require-returns': 'off', + // tsc owns module resolution for `.ts` files (strict, build fails on + // a missing import). eslint-plugin-n is not TS-aware: from a `.ts` + // file it rewrites `.js` -> `.ts` and cannot resolve imports of + // not-yet-migrated `.js` modules. `.js` files keep the rule. + 'n/no-missing-import': 'off', }, }, { diff --git a/lib/EncoreProxy.js b/lib/EncoreProxy.js index c11f8250..2de1f339 100644 --- a/lib/EncoreProxy.js +++ b/lib/EncoreProxy.js @@ -10,7 +10,7 @@ import levenshtein from 'fastest-levenshtein'; import pc from 'picocolors'; -import prettyError from './utils/pretty-error.js'; +import prettyError from './utils/pretty-error.ts'; // Public methods that were removed. We show an explicit migration message instead of relying on // the generic "did you mean" suggestion below, whose closest Levenshtein match would be misleading. diff --git a/lib/config-generator.js b/lib/config-generator.js index 553a7e40..35a47112 100644 --- a/lib/config-generator.js +++ b/lib/config-generator.js @@ -43,9 +43,9 @@ import notifierPluginUtil from './plugins/notifier.js'; import PluginPriorities from './plugins/plugin-priorities.js'; import variableProviderPluginUtil from './plugins/variable-provider.js'; import vuePluginUtil from './plugins/vue.js'; -import applyOptionsCallback from './utils/apply-options-callback.js'; -import copyEntryTmpName from './utils/copyEntryTmpName.js'; -import getVueVersion from './utils/get-vue-version.js'; +import applyOptionsCallback from './utils/apply-options-callback.ts'; +import copyEntryTmpName from './utils/copyEntryTmpName.ts'; +import getVueVersion from './utils/get-vue-version.ts'; import stringEscaper from './utils/string-escaper.ts'; class ConfigGenerator { diff --git a/lib/config/parse-runtime.js b/lib/config/parse-runtime.js index 33d3cfb3..d3b77ad2 100644 --- a/lib/config/parse-runtime.js +++ b/lib/config/parse-runtime.js @@ -9,7 +9,7 @@ import path from 'path'; -import packageUp from '../utils/package-up.js'; +import packageUp from '../utils/package-up.ts'; import RuntimeConfig from './RuntimeConfig.js'; /** diff --git a/lib/friendly-errors/transformers/missing-loader.js b/lib/friendly-errors/transformers/missing-loader.js index 2b0e5df3..afff0045 100644 --- a/lib/friendly-errors/transformers/missing-loader.js +++ b/lib/friendly-errors/transformers/missing-loader.js @@ -7,7 +7,7 @@ * file that was distributed with this source code. */ -import getVueVersion from '../../utils/get-vue-version.js'; +import getVueVersion from '../../utils/get-vue-version.ts'; const TYPE = 'loader-not-enabled'; diff --git a/lib/loaders/babel.js b/lib/loaders/babel.js index 34df4368..2044f16e 100644 --- a/lib/loaders/babel.js +++ b/lib/loaders/babel.js @@ -14,7 +14,7 @@ import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; export default { /** diff --git a/lib/loaders/css-extract.js b/lib/loaders/css-extract.js index b26282cd..52b48085 100644 --- a/lib/loaders/css-extract.js +++ b/lib/loaders/css-extract.js @@ -15,7 +15,7 @@ import { fileURLToPath } from 'url'; import MiniCssExtractPlugin from 'mini-css-extract-plugin'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; export default { /** diff --git a/lib/loaders/css.js b/lib/loaders/css.js index b146c4e8..0723d1d2 100644 --- a/lib/loaders/css.js +++ b/lib/loaders/css.js @@ -14,7 +14,7 @@ import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; export default { /** diff --git a/lib/loaders/handlebars.js b/lib/loaders/handlebars.js index 3ea12d9e..264f439e 100644 --- a/lib/loaders/handlebars.js +++ b/lib/loaders/handlebars.js @@ -14,7 +14,7 @@ import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; export default { /** diff --git a/lib/loaders/less.js b/lib/loaders/less.js index 16216fe8..3f7bc129 100644 --- a/lib/loaders/less.js +++ b/lib/loaders/less.js @@ -14,7 +14,7 @@ import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; import cssLoader from './css.js'; export default { diff --git a/lib/loaders/sass.js b/lib/loaders/sass.js index 516a6cbc..8c24fbd9 100644 --- a/lib/loaders/sass.js +++ b/lib/loaders/sass.js @@ -14,7 +14,7 @@ import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; import cssLoader from './css.js'; export default { diff --git a/lib/loaders/stylus.js b/lib/loaders/stylus.js index 3dc143be..a908c84f 100644 --- a/lib/loaders/stylus.js +++ b/lib/loaders/stylus.js @@ -14,7 +14,7 @@ import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; import cssLoader from './css.js'; export default { diff --git a/lib/loaders/typescript.js b/lib/loaders/typescript.js index 95a3014a..a27048fa 100644 --- a/lib/loaders/typescript.js +++ b/lib/loaders/typescript.js @@ -14,7 +14,7 @@ import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; import babelLoader from './babel.js'; export default { diff --git a/lib/loaders/vue.js b/lib/loaders/vue.js index 9b811a23..aaf1cdc4 100644 --- a/lib/loaders/vue.js +++ b/lib/loaders/vue.js @@ -14,8 +14,8 @@ import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; -import getVueVersion from '../utils/get-vue-version.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import getVueVersion from '../utils/get-vue-version.ts'; export default { /** diff --git a/lib/plugins/css-minimizer.js b/lib/plugins/css-minimizer.js index 92068b7e..3a0f5313 100644 --- a/lib/plugins/css-minimizer.js +++ b/lib/plugins/css-minimizer.js @@ -13,8 +13,8 @@ import MinimizerPlugin from 'minimizer-webpack-plugin'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; -import { checkCssMinifierPackages } from '../utils/minifier-check.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import { checkCssMinifierPackages } from '../utils/minifier-check.ts'; /** * @param {WebpackConfig} webpackConfig diff --git a/lib/plugins/define.js b/lib/plugins/define.js index da5998c4..bae4f5a5 100644 --- a/lib/plugins/define.js +++ b/lib/plugins/define.js @@ -13,7 +13,7 @@ import webpack from 'webpack'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; import PluginPriorities from './plugin-priorities.js'; /** diff --git a/lib/plugins/delete-unused-entries.js b/lib/plugins/delete-unused-entries.js index 79287400..c0a02e60 100644 --- a/lib/plugins/delete-unused-entries.js +++ b/lib/plugins/delete-unused-entries.js @@ -11,7 +11,7 @@ * @import WebpackConfig from '../WebpackConfig.js' */ -import copyEntryTmpName from '../utils/copyEntryTmpName.js'; +import copyEntryTmpName from '../utils/copyEntryTmpName.ts'; import DeleteUnusedEntriesJSPlugin from '../webpack/delete-unused-entries-js-plugin.js'; import PluginPriorities from './plugin-priorities.js'; diff --git a/lib/plugins/forked-ts-types.js b/lib/plugins/forked-ts-types.js index b8574f25..ad4e7c4f 100644 --- a/lib/plugins/forked-ts-types.js +++ b/lib/plugins/forked-ts-types.js @@ -13,7 +13,7 @@ import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; import PluginPriorities from './plugin-priorities.js'; /** diff --git a/lib/plugins/friendly-errors.js b/lib/plugins/friendly-errors.js index 2a6057d5..967ac5d1 100644 --- a/lib/plugins/friendly-errors.js +++ b/lib/plugins/friendly-errors.js @@ -19,7 +19,7 @@ import missingPostCssConfigFormatter from '../friendly-errors/formatters/missing import missingCssFileTransformer from '../friendly-errors/transformers/missing-css-file.js'; import missingLoaderTransformerFactory from '../friendly-errors/transformers/missing-loader.js'; import missingPostCssConfigTransformer from '../friendly-errors/transformers/missing-postcss-config.js'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; /** * @param {WebpackConfig} webpackConfig diff --git a/lib/plugins/js-minimizer.js b/lib/plugins/js-minimizer.js index 99184ae9..15ccd842 100644 --- a/lib/plugins/js-minimizer.js +++ b/lib/plugins/js-minimizer.js @@ -13,8 +13,8 @@ import MinimizerPlugin from 'minimizer-webpack-plugin'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; -import { checkJsMinifierPackages } from '../utils/minifier-check.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import { checkJsMinifierPackages } from '../utils/minifier-check.ts'; /** * @param {WebpackConfig} webpackConfig diff --git a/lib/plugins/manifest.js b/lib/plugins/manifest.js index 94ab2df7..d86fc1f6 100644 --- a/lib/plugins/manifest.js +++ b/lib/plugins/manifest.js @@ -13,9 +13,9 @@ import { WebpackManifestPlugin } from 'webpack-manifest-plugin'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; -import copyEntryTmpName from '../utils/copyEntryTmpName.js'; -import manifestKeyPrefixHelper from '../utils/manifest-key-prefix-helper.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import copyEntryTmpName from '../utils/copyEntryTmpName.ts'; +import manifestKeyPrefixHelper from '../utils/manifest-key-prefix-helper.ts'; import PluginPriorities from './plugin-priorities.js'; /** diff --git a/lib/plugins/mini-css-extract.js b/lib/plugins/mini-css-extract.js index 2fb84864..bf0bbecb 100644 --- a/lib/plugins/mini-css-extract.js +++ b/lib/plugins/mini-css-extract.js @@ -13,7 +13,7 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; import PluginPriorities from './plugin-priorities.js'; /** diff --git a/lib/plugins/notifier.js b/lib/plugins/notifier.js index 885d440f..abd9ed3f 100644 --- a/lib/plugins/notifier.js +++ b/lib/plugins/notifier.js @@ -12,7 +12,7 @@ */ import pluginFeatures from '../features.js'; -import applyOptionsCallback from '../utils/apply-options-callback.js'; +import applyOptionsCallback from '../utils/apply-options-callback.ts'; import PluginPriorities from './plugin-priorities.js'; /** diff --git a/lib/utils/apply-options-callback.js b/lib/utils/apply-options-callback.ts similarity index 53% rename from lib/utils/apply-options-callback.js rename to lib/utils/apply-options-callback.ts index ac28bc97..befbba7e 100644 --- a/lib/utils/apply-options-callback.js +++ b/lib/utils/apply-options-callback.ts @@ -7,19 +7,17 @@ * file that was distributed with this source code. */ -/** - * @typedef {function(this: T, T, ...*): T|void} OptionsCallback - * @template {object} T - */ +export type OptionsCallback = ( + this: T, + options: T, + ...extraArgs: any[] +) => T | void; -/** - * @template {object} T - * @param {OptionsCallback} optionsCallback - * @param {T} options - * @param {...*} extraArgs Forwarded to the callback after `options` - * @returns {T} - */ -export default function (optionsCallback, options, ...extraArgs) { +export default function ( + optionsCallback: OptionsCallback, + options: T, + ...extraArgs: any[] +): T { const result = optionsCallback.call(options, options, ...extraArgs); if (typeof result === 'object') { diff --git a/lib/utils/copyEntryTmpName.js b/lib/utils/copyEntryTmpName.ts similarity index 100% rename from lib/utils/copyEntryTmpName.js rename to lib/utils/copyEntryTmpName.ts diff --git a/lib/utils/get-vue-version.js b/lib/utils/get-vue-version.ts similarity index 87% rename from lib/utils/get-vue-version.js rename to lib/utils/get-vue-version.ts index f0c56a47..4deb4bd2 100644 --- a/lib/utils/get-vue-version.js +++ b/lib/utils/get-vue-version.ts @@ -7,20 +7,13 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import semver from 'semver'; import logger from '../logger.js'; import packageHelper from '../package-helper.js'; +import type WebpackConfig from '../WebpackConfig.js'; -/** - * @param {WebpackConfig} webpackConfig - * @returns {number|string|null} - */ -export default function (webpackConfig) { +export default function (webpackConfig: WebpackConfig): number | string | null { if (webpackConfig.vueOptions.version !== null) { return webpackConfig.vueOptions.version; } diff --git a/lib/utils/manifest-key-prefix-helper.js b/lib/utils/manifest-key-prefix-helper.ts similarity index 81% rename from lib/utils/manifest-key-prefix-helper.js rename to lib/utils/manifest-key-prefix-helper.ts index aeb173bb..e638cc28 100644 --- a/lib/utils/manifest-key-prefix-helper.js +++ b/lib/utils/manifest-key-prefix-helper.ts @@ -7,17 +7,12 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ +import type WebpackConfig from '../WebpackConfig.js'; /** * Helper for determining the manifest.json key prefix. - * - * @param {WebpackConfig} webpackConfig - * @returns {string} */ -export default function (webpackConfig) { +export default function (webpackConfig: WebpackConfig): string { let manifestPrefix = webpackConfig.manifestKeyPrefix; if (null === manifestPrefix) { if (null === webpackConfig.publicPath) { diff --git a/lib/utils/minifier-check.js b/lib/utils/minifier-check.ts similarity index 87% rename from lib/utils/minifier-check.js rename to lib/utils/minifier-check.ts index 1a73ea0b..f2f90687 100644 --- a/lib/utils/minifier-check.js +++ b/lib/utils/minifier-check.ts @@ -11,13 +11,13 @@ import MinimizerPlugin from 'minimizer-webpack-plugin'; import Features from '../features.js'; -const JS_MINIFIER_FEATURES = new Map([ +const JS_MINIFIER_FEATURES = new Map([ [MinimizerPlugin.esbuildMinify, 'minify-js-esbuild'], [MinimizerPlugin.swcMinify, 'minify-js-swc'], [MinimizerPlugin.uglifyJsMinify, 'minify-js-uglify'], ]); -const CSS_MINIFIER_FEATURES = new Map([ +const CSS_MINIFIER_FEATURES = new Map([ [MinimizerPlugin.lightningCssMinify, 'minify-css-lightningcss'], [MinimizerPlugin.cssnanoMinify, 'minify-css-cssnano'], [MinimizerPlugin.cssoMinify, 'minify-css-csso'], @@ -26,10 +26,7 @@ const CSS_MINIFIER_FEATURES = new Map([ [MinimizerPlugin.swcMinifyCss, 'minify-css-swc'], ]); -/** - * @param {Function} minifyFn - */ -export function checkJsMinifierPackages(minifyFn) { +export function checkJsMinifierPackages(minifyFn: Function): void { const feature = JS_MINIFIER_FEATURES.get(minifyFn); if (!feature) { // terserMinify (bundled) or a custom function: nothing to install @@ -39,10 +36,7 @@ export function checkJsMinifierPackages(minifyFn) { Features.ensurePackagesExistAndAreCorrectVersion(feature); } -/** - * @param {Function|undefined} minifyFn - */ -export function checkCssMinifierPackages(minifyFn) { +export function checkCssMinifierPackages(minifyFn: Function | undefined): void { if (!minifyFn) { throw new Error( 'CSS minification is enabled but no CSS minifier is configured. ' + diff --git a/lib/utils/package-up.js b/lib/utils/package-up.ts similarity index 64% rename from lib/utils/package-up.js rename to lib/utils/package-up.ts index 92a27a26..39a830b2 100644 --- a/lib/utils/package-up.js +++ b/lib/utils/package-up.ts @@ -14,31 +14,25 @@ import { fileURLToPath } from 'url'; /** * Inlined version of the package "package-up" (ESM only). * - * @param {object} options - * @param {string} options.cwd The directory to start searching from. - * @returns {string|undefined} The path to the nearest package.json file or undefined if not found. + * Returns the path to the nearest package.json file, or undefined if not found. */ -export default function ({ cwd }) { +export default function ({ cwd }: { cwd: string }): string | undefined { return findUpSync('package.json', { cwd }); } -/** - * @param {string|URL} urlOrPath - * @returns {string} - */ -function toPath(urlOrPath) { +function toPath(urlOrPath: string | URL): string { return urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath; } /** * Inlined and simplified version of the package "find-up-simple" (ESM only). * - * @param {string} name The name of the file to find - * @param {object} options - * @param {string=} options.cwd The directory to start searching from. - * @returns {string|undefined} The path to the file found or undefined if not found. + * Returns the path to the file found, or undefined if not found. */ -function findUpSync(name, { cwd = process.cwd() } = {}) { +function findUpSync( + name: string, + { cwd = process.cwd() }: { cwd?: string } = {} +): string | undefined { let directory = path.resolve(toPath(cwd) || ''); const { root } = path.parse(directory); diff --git a/lib/utils/pretty-error.js b/lib/utils/pretty-error.ts similarity index 66% rename from lib/utils/pretty-error.js rename to lib/utils/pretty-error.ts index db0d0b5a..ec11d9a6 100644 --- a/lib/utils/pretty-error.js +++ b/lib/utils/pretty-error.ts @@ -15,18 +15,14 @@ const PrettyError = require('pretty-error'); /** * Render a pretty version of the given error. * - * Supported options: - * - {Function} skipTrace - * An optional callback that defines whether - * or not each line of the eventual stacktrace - * should be kept. First argument is the content - * of the line, second argument is the line number. - * - * @param {*} error - * @param {object} options - * @returns {void} + * The optional `skipTrace` callback defines whether or not each line of the + * eventual stacktrace should be kept. First argument is the content of the + * line, second argument is the line number. */ -export default function (error, options = {}) { +export default function ( + error: unknown, + options: { skipTrace?: (line: string, lineNumber: number) => boolean } = {} +): void { const pe = new PrettyError(); // Use the default terminal's color diff --git a/lib/webpack/entry-points-plugin.js b/lib/webpack/entry-points-plugin.js index 130da5c3..163443d2 100644 --- a/lib/webpack/entry-points-plugin.js +++ b/lib/webpack/entry-points-plugin.js @@ -11,7 +11,7 @@ import crypto from 'crypto'; import fs from 'fs'; import path from 'path'; -import copyEntryTmpName from '../utils/copyEntryTmpName.js'; +import copyEntryTmpName from '../utils/copyEntryTmpName.ts'; /** * Return the file extension from a filename, without the leading dot and without the query string (if any). diff --git a/package.json b/package.json index 45e2358d..469350a1 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "@symfony/stimulus-bridge": "^3.0.0 || ^4.0.0", "@tsconfig/node22": "^22.0.5", "@types/node": "^22.18.0", + "@types/semver": "^7.7.1", "@vue/babel-plugin-jsx": "^3.0.0", "@vue/compiler-sfc": "^3.2.14", "autoprefixer": "^10.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ffc05200..55230ea7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -90,6 +90,9 @@ importers: '@types/node': specifier: ^22.18.0 version: 22.20.0 + '@types/semver': + specifier: ^7.7.1 + version: 7.7.1 '@vue/babel-plugin-jsx': specifier: ^3.0.0 version: 3.0.0(@babel/core@8.0.1) @@ -1671,6 +1674,9 @@ packages: '@types/retry@0.12.2': resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} + '@types/semver@7.7.1': + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} + '@types/send@0.17.6': resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} @@ -6438,6 +6444,8 @@ snapshots: '@types/retry@0.12.2': {} + '@types/semver@7.7.1': {} + '@types/send@0.17.6': dependencies: '@types/mime': 1.3.5 diff --git a/test/functional.js b/test/functional.js index e29b16e9..39e5fc52 100644 --- a/test/functional.js +++ b/test/functional.js @@ -17,7 +17,7 @@ import semver from 'semver'; import { afterAll, beforeAll, chai, describe, expect, it } from 'vitest'; import packageHelper from '../lib/package-helper.js'; -import getVueVersion from '../lib/utils/get-vue-version.js'; +import getVueVersion from '../lib/utils/get-vue-version.ts'; import { assertWarning } from './helpers/logger-assert.js'; import * as testSetup from './helpers/setup.js'; diff --git a/test/plugins/css-minimizer.js b/test/plugins/css-minimizer.js index 8486b695..d795f160 100644 --- a/test/plugins/css-minimizer.js +++ b/test/plugins/css-minimizer.js @@ -17,7 +17,7 @@ const { checkCssMinifierPackages } = vi.hoisted(() => ({ checkCssMinifierPackages: vi.fn(), })); -vi.mock('../../lib/utils/minifier-check.js', () => ({ +vi.mock('../../lib/utils/minifier-check.ts', () => ({ checkJsMinifierPackages: vi.fn(), checkCssMinifierPackages, })); diff --git a/test/plugins/js-minimizer.js b/test/plugins/js-minimizer.js index 3132429c..bf6a1b07 100644 --- a/test/plugins/js-minimizer.js +++ b/test/plugins/js-minimizer.js @@ -17,7 +17,7 @@ const { checkJsMinifierPackages } = vi.hoisted(() => ({ checkJsMinifierPackages: vi.fn(), })); -vi.mock('../../lib/utils/minifier-check.js', () => ({ +vi.mock('../../lib/utils/minifier-check.ts', () => ({ checkJsMinifierPackages, checkCssMinifierPackages: vi.fn(), })); diff --git a/test/utils/apply-options-callback.js b/test/utils/apply-options-callback.js index e52cd06c..cd6501d2 100644 --- a/test/utils/apply-options-callback.js +++ b/test/utils/apply-options-callback.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import applyOptionsCallback from '../../lib/utils/apply-options-callback.js'; +import applyOptionsCallback from '../../lib/utils/apply-options-callback.ts'; describe('utils/apply-options-callback', function () { it('mutates and returns the options object', function () { diff --git a/test/utils/get-vue-version.js b/test/utils/get-vue-version.js index 0a76b5b8..f322bab7 100644 --- a/test/utils/get-vue-version.js +++ b/test/utils/get-vue-version.js @@ -11,7 +11,7 @@ import { vi, describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; import packageHelper from '../../lib/package-helper.js'; -import getVueVersion from '../../lib/utils/get-vue-version.js'; +import getVueVersion from '../../lib/utils/get-vue-version.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; const createWebpackConfig = function () { diff --git a/test/utils/minifier-check.js b/test/utils/minifier-check.js index 925edf07..99f2fcab 100644 --- a/test/utils/minifier-check.js +++ b/test/utils/minifier-check.js @@ -19,7 +19,7 @@ vi.mock('../../lib/features.js', () => ({ })); const { checkJsMinifierPackages, checkCssMinifierPackages } = - await import('../../lib/utils/minifier-check.js'); + await import('../../lib/utils/minifier-check.ts'); describe('utils/minifier-check', function () { beforeEach(() => ensurePackagesExistAndAreCorrectVersion.mockReset()); diff --git a/test/utils/package-up.js b/test/utils/package-up.js index 367f0976..b2db048b 100644 --- a/test/utils/package-up.js +++ b/test/utils/package-up.js @@ -11,7 +11,7 @@ import { resolve as resolvePath } from 'path'; import { describe, it, expect } from 'vitest'; -import packageUp from '../../lib/utils/package-up.js'; +import packageUp from '../../lib/utils/package-up.ts'; describe('package-up', function () { it.each([ From 3340473184e1e2028de5eb6ac06eb55282c5a831 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Thu, 25 Jun 2026 11:39:37 +0200 Subject: [PATCH 03/12] [TypeScript] Migrate `lib/plugins/*` (#1505) --- lib/config-generator.js | 26 ++++++++-------- lib/loaders/typescript.js | 8 ++--- ...put-display.js => asset-output-display.ts} | 22 +++++-------- .../{css-minimizer.js => css-minimizer.ts} | 11 ++----- lib/plugins/{define.js => define.ts} | 17 ++++------ ...ed-entries.js => delete-unused-entries.ts} | 17 ++++------ ...es-manifest.js => entry-files-manifest.ts} | 17 ++++------ ...{forked-ts-types.js => forked-ts-types.ts} | 13 ++------ ...{friendly-errors.js => friendly-errors.ts} | 11 ++----- .../{js-minimizer.js => js-minimizer.ts} | 11 ++----- lib/plugins/{manifest.js => manifest.ts} | 31 ++++++++++--------- ...ini-css-extract.js => mini-css-extract.ts} | 24 ++++++-------- lib/plugins/{notifier.js => notifier.ts} | 17 ++++------ ...gin-priorities.js => plugin-priorities.ts} | 0 ...iable-provider.js => variable-provider.ts} | 17 ++++------ lib/plugins/{vue.js => vue.ts} | 17 ++++------ lib/utils/minifier-check.ts | 6 +++- test/plugins/css-minimizer.js | 2 +- test/plugins/define.js | 2 +- test/plugins/forked-ts-types.js | 2 +- test/plugins/friendly-errors.js | 2 +- test/plugins/js-minimizer.js | 2 +- test/plugins/manifest.js | 2 +- test/plugins/mini-css-extract.js | 2 +- test/plugins/notifier.js | 2 +- 25 files changed, 110 insertions(+), 171 deletions(-) rename lib/plugins/{asset-output-display.js => asset-output-display.ts} (64%) rename lib/plugins/{css-minimizer.js => css-minimizer.ts} (81%) rename lib/plugins/{define.js => define.ts} (73%) rename lib/plugins/{delete-unused-entries.js => delete-unused-entries.ts} (73%) rename lib/plugins/{entry-files-manifest.js => entry-files-manifest.ts} (70%) rename lib/plugins/{forked-ts-types.js => forked-ts-types.ts} (74%) rename lib/plugins/{friendly-errors.js => friendly-errors.ts} (89%) rename lib/plugins/{js-minimizer.js => js-minimizer.ts} (82%) rename lib/plugins/{manifest.js => manifest.ts} (75%) rename lib/plugins/{mini-css-extract.js => mini-css-extract.ts} (80%) rename lib/plugins/{notifier.js => notifier.ts} (76%) rename lib/plugins/{plugin-priorities.js => plugin-priorities.ts} (100%) rename lib/plugins/{variable-provider.js => variable-provider.ts} (66%) rename lib/plugins/{vue.js => vue.ts} (64%) diff --git a/lib/config-generator.js b/lib/config-generator.js index 35a47112..cadeb05a 100644 --- a/lib/config-generator.js +++ b/lib/config-generator.js @@ -30,19 +30,19 @@ import tsLoaderUtil from './loaders/typescript.js'; import vueLoaderUtil from './loaders/vue.js'; import logger from './logger.js'; // plugins utils -import assetOutputDisplay from './plugins/asset-output-display.js'; -import cssMinimizerPluginUtil from './plugins/css-minimizer.js'; -import definePluginUtil from './plugins/define.js'; -import deleteUnusedEntriesPluginUtil from './plugins/delete-unused-entries.js'; -import entryFilesManifestPlugin from './plugins/entry-files-manifest.js'; -import friendlyErrorPluginUtil from './plugins/friendly-errors.js'; -import jsMinimizerPluginUtil from './plugins/js-minimizer.js'; -import manifestPluginUtil from './plugins/manifest.js'; -import miniCssExtractPluginUtil from './plugins/mini-css-extract.js'; -import notifierPluginUtil from './plugins/notifier.js'; -import PluginPriorities from './plugins/plugin-priorities.js'; -import variableProviderPluginUtil from './plugins/variable-provider.js'; -import vuePluginUtil from './plugins/vue.js'; +import assetOutputDisplay from './plugins/asset-output-display.ts'; +import cssMinimizerPluginUtil from './plugins/css-minimizer.ts'; +import definePluginUtil from './plugins/define.ts'; +import deleteUnusedEntriesPluginUtil from './plugins/delete-unused-entries.ts'; +import entryFilesManifestPlugin from './plugins/entry-files-manifest.ts'; +import friendlyErrorPluginUtil from './plugins/friendly-errors.ts'; +import jsMinimizerPluginUtil from './plugins/js-minimizer.ts'; +import manifestPluginUtil from './plugins/manifest.ts'; +import miniCssExtractPluginUtil from './plugins/mini-css-extract.ts'; +import notifierPluginUtil from './plugins/notifier.ts'; +import PluginPriorities from './plugins/plugin-priorities.ts'; +import variableProviderPluginUtil from './plugins/variable-provider.ts'; +import vuePluginUtil from './plugins/vue.ts'; import applyOptionsCallback from './utils/apply-options-callback.ts'; import copyEntryTmpName from './utils/copyEntryTmpName.ts'; import getVueVersion from './utils/get-vue-version.ts'; diff --git a/lib/loaders/typescript.js b/lib/loaders/typescript.js index a27048fa..086d842b 100644 --- a/lib/loaders/typescript.js +++ b/lib/loaders/typescript.js @@ -39,10 +39,10 @@ export default { // force transpileOnly to speed up config.transpileOnly = true; - // add forked ts types plugin to the stack - const { default: forkedTypesPluginUtil } = - await import('../plugins/forked-ts-types.js'); - forkedTypesPluginUtil(webpackConfig); + // add forked ts types plugin to the stack. + // eslint-disable-next-line n/no-missing-import -- this `.js` file dynamically imports a migrated `.ts` plugin; eslint-plugin-n can't resolve it and rewriteRelativeImportExtensions does not rewrite dynamic import() in `.js`. Remove once this loader is migrated to TS. + const forkedTs = await import('../plugins/forked-ts-types.js'); + forkedTs.default(webpackConfig); } // allow to import .vue files diff --git a/lib/plugins/asset-output-display.js b/lib/plugins/asset-output-display.ts similarity index 64% rename from lib/plugins/asset-output-display.js rename to lib/plugins/asset-output-display.ts index 44ef837d..24a34970 100644 --- a/lib/plugins/asset-output-display.js +++ b/lib/plugins/asset-output-display.ts @@ -7,27 +7,21 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - -/** - * @import FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin' - */ +import type FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin'; import pathUtil from '../config/path-util.js'; import AssetOutputDisplayPlugin from '../friendly-errors/asset-output-display-plugin.js'; -import PluginPriorities from './plugin-priorities.js'; +import type WebpackConfig from '../WebpackConfig.js'; +import PluginPriorities from './plugin-priorities.ts'; /** * Updates plugins array passed adding AssetOutputDisplayPlugin instance - * - * @param {Array} plugins - * @param {WebpackConfig} webpackConfig - * @param {FriendlyErrorsWebpackPlugin} friendlyErrorsPlugin - * @returns {void} */ -export default function (plugins, webpackConfig, friendlyErrorsPlugin) { +export default function ( + plugins: Array<{ plugin: object; priority: number }>, + webpackConfig: WebpackConfig, + friendlyErrorsPlugin: FriendlyErrorsWebpackPlugin +): void { if (webpackConfig.useDevServer()) { return; } diff --git a/lib/plugins/css-minimizer.js b/lib/plugins/css-minimizer.ts similarity index 81% rename from lib/plugins/css-minimizer.js rename to lib/plugins/css-minimizer.ts index 3a0f5313..a9ff0cab 100644 --- a/lib/plugins/css-minimizer.js +++ b/lib/plugins/css-minimizer.ts @@ -7,20 +7,13 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import MinimizerPlugin from 'minimizer-webpack-plugin'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import { checkCssMinifierPackages } from '../utils/minifier-check.ts'; +import type WebpackConfig from '../WebpackConfig.js'; -/** - * @param {WebpackConfig} webpackConfig - * @returns {object} - */ -export default function (webpackConfig) { +export default function (webpackConfig: WebpackConfig) { const minimizerPluginOptions = { test: /\.css(\?.*)?$/i, }; diff --git a/lib/plugins/define.js b/lib/plugins/define.ts similarity index 73% rename from lib/plugins/define.js rename to lib/plugins/define.ts index bae4f5a5..0a326c95 100644 --- a/lib/plugins/define.js +++ b/lib/plugins/define.ts @@ -7,21 +7,16 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import webpack from 'webpack'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; -import PluginPriorities from './plugin-priorities.js'; +import type WebpackConfig from '../WebpackConfig.js'; +import PluginPriorities from './plugin-priorities.ts'; -/** - * @param {Array} plugins - * @param {WebpackConfig} webpackConfig - * @returns {void} - */ -export default function (plugins, webpackConfig) { +export default function ( + plugins: Array<{ plugin: object; priority: number }>, + webpackConfig: WebpackConfig +): void { const definePluginOptions = { 'process.env.NODE_ENV': webpackConfig.isProduction() ? '"production"' : '"development"', }; diff --git a/lib/plugins/delete-unused-entries.js b/lib/plugins/delete-unused-entries.ts similarity index 73% rename from lib/plugins/delete-unused-entries.js rename to lib/plugins/delete-unused-entries.ts index c0a02e60..8b954f82 100644 --- a/lib/plugins/delete-unused-entries.js +++ b/lib/plugins/delete-unused-entries.ts @@ -7,20 +7,15 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import copyEntryTmpName from '../utils/copyEntryTmpName.ts'; import DeleteUnusedEntriesJSPlugin from '../webpack/delete-unused-entries-js-plugin.js'; -import PluginPriorities from './plugin-priorities.js'; +import type WebpackConfig from '../WebpackConfig.js'; +import PluginPriorities from './plugin-priorities.ts'; -/** - * @param {Array} plugins - * @param {WebpackConfig} webpackConfig - * @returns {void} - */ -export default function (plugins, webpackConfig) { +export default function ( + plugins: Array<{ plugin: object; priority: number }>, + webpackConfig: WebpackConfig +): void { const entries = [...webpackConfig.styleEntries.keys()]; if (webpackConfig.copyFilesConfigs.length > 0) { diff --git a/lib/plugins/entry-files-manifest.js b/lib/plugins/entry-files-manifest.ts similarity index 70% rename from lib/plugins/entry-files-manifest.js rename to lib/plugins/entry-files-manifest.ts index a391c21f..7d9644d8 100644 --- a/lib/plugins/entry-files-manifest.js +++ b/lib/plugins/entry-files-manifest.ts @@ -7,19 +7,14 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import { EntryPointsPlugin } from '../webpack/entry-points-plugin.js'; -import PluginPriorities from './plugin-priorities.js'; +import type WebpackConfig from '../WebpackConfig.js'; +import PluginPriorities from './plugin-priorities.ts'; -/** - * @param {Array} plugins - * @param {WebpackConfig} webpackConfig - * @returns {void} - */ -export default function (plugins, webpackConfig) { +export default function ( + plugins: Array<{ plugin: object; priority: number }>, + webpackConfig: WebpackConfig +): void { plugins.push({ plugin: new EntryPointsPlugin({ publicPath: webpackConfig.getRealPublicPath(), diff --git a/lib/plugins/forked-ts-types.js b/lib/plugins/forked-ts-types.ts similarity index 74% rename from lib/plugins/forked-ts-types.js rename to lib/plugins/forked-ts-types.ts index ad4e7c4f..52e37026 100644 --- a/lib/plugins/forked-ts-types.js +++ b/lib/plugins/forked-ts-types.ts @@ -7,20 +7,13 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; -import PluginPriorities from './plugin-priorities.js'; +import type WebpackConfig from '../WebpackConfig.js'; +import PluginPriorities from './plugin-priorities.ts'; -/** - * @param {WebpackConfig} webpackConfig - * @returns {void} - */ -export default function (webpackConfig) { +export default function (webpackConfig: WebpackConfig): void { const config = {}; webpackConfig.addPlugin( diff --git a/lib/plugins/friendly-errors.js b/lib/plugins/friendly-errors.ts similarity index 89% rename from lib/plugins/friendly-errors.js rename to lib/plugins/friendly-errors.ts index 967ac5d1..1342f411 100644 --- a/lib/plugins/friendly-errors.js +++ b/lib/plugins/friendly-errors.ts @@ -7,10 +7,6 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin'; import missingCssFileFormatter from '../friendly-errors/formatters/missing-css-file.js'; @@ -20,12 +16,9 @@ import missingCssFileTransformer from '../friendly-errors/transformers/missing-c import missingLoaderTransformerFactory from '../friendly-errors/transformers/missing-loader.js'; import missingPostCssConfigTransformer from '../friendly-errors/transformers/missing-postcss-config.js'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import type WebpackConfig from '../WebpackConfig.js'; -/** - * @param {WebpackConfig} webpackConfig - * @returns {FriendlyErrorsWebpackPlugin} - */ -export default function (webpackConfig) { +export default function (webpackConfig: WebpackConfig) { const friendlyErrorsPluginOptions = { clearConsole: false, additionalTransformers: [ diff --git a/lib/plugins/js-minimizer.js b/lib/plugins/js-minimizer.ts similarity index 82% rename from lib/plugins/js-minimizer.js rename to lib/plugins/js-minimizer.ts index 15ccd842..3dc466e8 100644 --- a/lib/plugins/js-minimizer.js +++ b/lib/plugins/js-minimizer.ts @@ -7,20 +7,13 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import MinimizerPlugin from 'minimizer-webpack-plugin'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import { checkJsMinifierPackages } from '../utils/minifier-check.ts'; +import type WebpackConfig from '../WebpackConfig.js'; -/** - * @param {WebpackConfig} webpackConfig - * @returns {object} - */ -export default function (webpackConfig) { +export default function (webpackConfig: WebpackConfig) { const minimizerPluginOptions = { parallel: true, minify: MinimizerPlugin.terserMinify, diff --git a/lib/plugins/manifest.js b/lib/plugins/manifest.ts similarity index 75% rename from lib/plugins/manifest.js rename to lib/plugins/manifest.ts index d86fc1f6..28931b3e 100644 --- a/lib/plugins/manifest.js +++ b/lib/plugins/manifest.ts @@ -7,24 +7,27 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import { WebpackManifestPlugin } from 'webpack-manifest-plugin'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import copyEntryTmpName from '../utils/copyEntryTmpName.ts'; import manifestKeyPrefixHelper from '../utils/manifest-key-prefix-helper.ts'; -import PluginPriorities from './plugin-priorities.js'; +import type WebpackConfig from '../WebpackConfig.js'; +import PluginPriorities from './plugin-priorities.ts'; -/** - * @param {Array} plugins - * @param {WebpackConfig} webpackConfig - * @returns {void} - */ -export default function (plugins, webpackConfig) { - let manifestPluginOptions = { +type ManifestPluginOptions = { + seed: object; + basePath: string; + writeToFileEmit: boolean; + filter: (file: any) => boolean; + map?: (file: any) => any; +}; + +export default function ( + plugins: Array<{ plugin: object; priority: number }>, + webpackConfig: WebpackConfig +): void { + let manifestPluginOptions: ManifestPluginOptions = { seed: {}, basePath: manifestKeyPrefixHelper(webpackConfig), // always write a manifest.json file, even with webpack-dev-server @@ -38,10 +41,10 @@ export default function (plugins, webpackConfig) { }, }; - manifestPluginOptions = applyOptionsCallback( + manifestPluginOptions = applyOptionsCallback( webpackConfig.manifestPluginOptionsCallback, manifestPluginOptions - ); + ) as ManifestPluginOptions; const userMapOption = manifestPluginOptions.map; manifestPluginOptions.map = (file) => { diff --git a/lib/plugins/mini-css-extract.js b/lib/plugins/mini-css-extract.ts similarity index 80% rename from lib/plugins/mini-css-extract.js rename to lib/plugins/mini-css-extract.ts index bf0bbecb..18b08075 100644 --- a/lib/plugins/mini-css-extract.js +++ b/lib/plugins/mini-css-extract.ts @@ -7,21 +7,16 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; -import PluginPriorities from './plugin-priorities.js'; +import type WebpackConfig from '../WebpackConfig.js'; +import PluginPriorities from './plugin-priorities.ts'; -/** - * @param {Array} plugins - * @param {WebpackConfig} webpackConfig - * @returns {void} - */ -export default function (plugins, webpackConfig) { +export default function ( + plugins: Array<{ plugin: object; priority: number }>, + webpackConfig: WebpackConfig +): void { // Don't add the plugin if CSS extraction is disabled if (!webpackConfig.extractCss) { return; @@ -37,14 +32,15 @@ export default function (plugins, webpackConfig) { // This is related to setting optimization.runtimeChunk = 'single'; // See https://github.com/webpack/webpack/issues/6598 let chunkFilename = webpackConfig.useVersioning ? '[name].[contenthash:8].css' : '[name].css'; - if (webpackConfig.configuredFilenames.css) { - filename = webpackConfig.configuredFilenames.css; + const configuredCssFilename = (webpackConfig.configuredFilenames as { css?: string }).css; + if (configuredCssFilename) { + filename = configuredCssFilename; // see above: originally we did NOT set this, because this was // only for split chunks. But now, sometimes the "entry" CSS chunk // will use chunkFilename. So, we need to always respect the // user's wishes - chunkFilename = webpackConfig.configuredFilenames.css; + chunkFilename = configuredCssFilename; } const miniCssPluginOptions = { diff --git a/lib/plugins/notifier.js b/lib/plugins/notifier.ts similarity index 76% rename from lib/plugins/notifier.js rename to lib/plugins/notifier.ts index abd9ed3f..8cad3923 100644 --- a/lib/plugins/notifier.js +++ b/lib/plugins/notifier.ts @@ -7,20 +7,15 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import pluginFeatures from '../features.js'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; -import PluginPriorities from './plugin-priorities.js'; +import type WebpackConfig from '../WebpackConfig.js'; +import PluginPriorities from './plugin-priorities.ts'; -/** - * @param {Array} plugins - * @param {WebpackConfig} webpackConfig - * @returns {Promise} - */ -export default async function (plugins, webpackConfig) { +export default async function ( + plugins: Array<{ plugin: object; priority: number }>, + webpackConfig: WebpackConfig +): Promise { if (!webpackConfig.useWebpackNotifier) { return; } diff --git a/lib/plugins/plugin-priorities.js b/lib/plugins/plugin-priorities.ts similarity index 100% rename from lib/plugins/plugin-priorities.js rename to lib/plugins/plugin-priorities.ts diff --git a/lib/plugins/variable-provider.js b/lib/plugins/variable-provider.ts similarity index 66% rename from lib/plugins/variable-provider.js rename to lib/plugins/variable-provider.ts index 3e206c05..158a6fdc 100644 --- a/lib/plugins/variable-provider.js +++ b/lib/plugins/variable-provider.ts @@ -7,20 +7,15 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import webpack from 'webpack'; -import PluginPriorities from './plugin-priorities.js'; +import type WebpackConfig from '../WebpackConfig.js'; +import PluginPriorities from './plugin-priorities.ts'; -/** - * @param {Array} plugins - * @param {WebpackConfig} webpackConfig - * @returns {void} - */ -export default function (plugins, webpackConfig) { +export default function ( + plugins: Array<{ plugin: object; priority: number }>, + webpackConfig: WebpackConfig +): void { if (Object.keys(webpackConfig.providedVariables).length > 0) { plugins.push({ plugin: new webpack.ProvidePlugin(webpackConfig.providedVariables), diff --git a/lib/plugins/vue.js b/lib/plugins/vue.ts similarity index 64% rename from lib/plugins/vue.js rename to lib/plugins/vue.ts index b11eddc1..0633cd68 100644 --- a/lib/plugins/vue.js +++ b/lib/plugins/vue.ts @@ -7,18 +7,13 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - -import PluginPriorities from './plugin-priorities.js'; +import type WebpackConfig from '../WebpackConfig.js'; +import PluginPriorities from './plugin-priorities.ts'; -/** - * @param {Array} plugins - * @param {WebpackConfig} webpackConfig - * @returns {Promise} - */ -export default async function (plugins, webpackConfig) { +export default async function ( + plugins: Array<{ plugin: object; priority: number }>, + webpackConfig: WebpackConfig +): Promise { if (!webpackConfig.useVueLoader) { return; } diff --git a/lib/utils/minifier-check.ts b/lib/utils/minifier-check.ts index f2f90687..a4cd40ac 100644 --- a/lib/utils/minifier-check.ts +++ b/lib/utils/minifier-check.ts @@ -26,7 +26,11 @@ const CSS_MINIFIER_FEATURES = new Map([ [MinimizerPlugin.swcMinifyCss, 'minify-css-swc'], ]); -export function checkJsMinifierPackages(minifyFn: Function): void { +export function checkJsMinifierPackages(minifyFn: Function | undefined): void { + if (!minifyFn) { + return; + } + const feature = JS_MINIFIER_FEATURES.get(minifyFn); if (!feature) { // terserMinify (bundled) or a custom function: nothing to install diff --git a/test/plugins/css-minimizer.js b/test/plugins/css-minimizer.js index d795f160..92865737 100644 --- a/test/plugins/css-minimizer.js +++ b/test/plugins/css-minimizer.js @@ -22,7 +22,7 @@ vi.mock('../../lib/utils/minifier-check.ts', () => ({ checkCssMinifierPackages, })); -const { default: cssMinimizerPluginUtil } = await import('../../lib/plugins/css-minimizer.js'); +const { default: cssMinimizerPluginUtil } = await import('../../lib/plugins/css-minimizer.ts'); function createConfig(environment = 'production') { const runtimeConfig = new RuntimeConfig(); diff --git a/test/plugins/define.js b/test/plugins/define.js index 46fbd136..7de9f7fc 100644 --- a/test/plugins/define.js +++ b/test/plugins/define.js @@ -11,7 +11,7 @@ import { describe, it, expect } from 'vitest'; import webpack from 'webpack'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import definePluginUtil from '../../lib/plugins/define.js'; +import definePluginUtil from '../../lib/plugins/define.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig(environment = 'production') { diff --git a/test/plugins/forked-ts-types.js b/test/plugins/forked-ts-types.js index 7205ed80..17dbcbbb 100644 --- a/test/plugins/forked-ts-types.js +++ b/test/plugins/forked-ts-types.js @@ -12,7 +12,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; import tsLoader from '../../lib/loaders/typescript.js'; -import tsTypeChecker from '../../lib/plugins/forked-ts-types.js'; +import tsTypeChecker from '../../lib/plugins/forked-ts-types.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { diff --git a/test/plugins/friendly-errors.js b/test/plugins/friendly-errors.js index 7428c7a2..3236c667 100644 --- a/test/plugins/friendly-errors.js +++ b/test/plugins/friendly-errors.js @@ -11,7 +11,7 @@ import FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin'; import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import friendlyErrorsPluginUtil from '../../lib/plugins/friendly-errors.js'; +import friendlyErrorsPluginUtil from '../../lib/plugins/friendly-errors.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { diff --git a/test/plugins/js-minimizer.js b/test/plugins/js-minimizer.js index bf6a1b07..fe47b889 100644 --- a/test/plugins/js-minimizer.js +++ b/test/plugins/js-minimizer.js @@ -22,7 +22,7 @@ vi.mock('../../lib/utils/minifier-check.ts', () => ({ checkCssMinifierPackages: vi.fn(), })); -const { default: jsMinimizerPluginUtil } = await import('../../lib/plugins/js-minimizer.js'); +const { default: jsMinimizerPluginUtil } = await import('../../lib/plugins/js-minimizer.ts'); function createConfig(environment = 'production') { const runtimeConfig = new RuntimeConfig(); diff --git a/test/plugins/manifest.js b/test/plugins/manifest.js index 09a83c6f..ddc34596 100644 --- a/test/plugins/manifest.js +++ b/test/plugins/manifest.js @@ -11,7 +11,7 @@ import { describe, it, expect } from 'vitest'; import { WebpackManifestPlugin } from 'webpack-manifest-plugin'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import manifestPluginUtil from '../../lib/plugins/manifest.js'; +import manifestPluginUtil from '../../lib/plugins/manifest.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { diff --git a/test/plugins/mini-css-extract.js b/test/plugins/mini-css-extract.js index 5be82822..7c16560b 100644 --- a/test/plugins/mini-css-extract.js +++ b/test/plugins/mini-css-extract.js @@ -11,7 +11,7 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import miniCssExtractPluginUtil from '../../lib/plugins/mini-css-extract.js'; +import miniCssExtractPluginUtil from '../../lib/plugins/mini-css-extract.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { diff --git a/test/plugins/notifier.js b/test/plugins/notifier.js index c9af5e5b..73df61f6 100644 --- a/test/plugins/notifier.js +++ b/test/plugins/notifier.js @@ -11,7 +11,7 @@ import { describe, it, expect } from 'vitest'; import WebpackNotifier from 'webpack-notifier'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import notifierPluginUtil from '../../lib/plugins/notifier.js'; +import notifierPluginUtil from '../../lib/plugins/notifier.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { From 8d6bf77d23ed10b8a3059fcd2b910c79f6de23ef Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Thu, 25 Jun 2026 21:29:38 +0200 Subject: [PATCH 04/12] [TypeScript] Migrate `lib/loaders/*` (#1506) --- lib/config-generator.js | 18 +++++------ lib/loaders/{babel.js => babel.ts} | 29 ++++++------------ .../{css-extract.js => css-extract.ts} | 11 ++----- lib/loaders/{css.js => css.ts} | 17 ++--------- lib/loaders/{handlebars.js => handlebars.ts} | 11 ++----- lib/loaders/{less.js => less.ts} | 14 ++------- lib/loaders/{sass.js => sass.ts} | 14 ++------- lib/loaders/{stylus.js => stylus.ts} | 14 ++------- lib/loaders/{typescript.js => typescript.ts} | 30 ++++++++----------- lib/loaders/{vue.js => vue.ts} | 11 ++----- test/loaders/babel.js | 2 +- test/loaders/css-extract.js | 2 +- test/loaders/css.js | 2 +- test/loaders/handlebars.js | 2 +- test/loaders/less.js | 4 +-- test/loaders/sass.js | 4 +-- test/loaders/stylus.js | 4 +-- test/loaders/typescript.js | 2 +- test/loaders/vue.js | 2 +- test/plugins/forked-ts-types.js | 2 +- 20 files changed, 62 insertions(+), 133 deletions(-) rename lib/loaders/{babel.js => babel.ts} (90%) rename lib/loaders/{css-extract.js => css-extract.ts} (84%) rename lib/loaders/{css.js => css.ts} (84%) rename lib/loaders/{handlebars.js => handlebars.ts} (79%) rename lib/loaders/{less.js => less.ts} (74%) rename lib/loaders/{sass.js => sass.ts} (86%) rename lib/loaders/{stylus.js => stylus.ts} (74%) rename lib/loaders/{typescript.js => typescript.ts} (62%) rename lib/loaders/{vue.js => vue.ts} (80%) diff --git a/lib/config-generator.js b/lib/config-generator.js index cadeb05a..e578ecad 100644 --- a/lib/config-generator.js +++ b/lib/config-generator.js @@ -18,16 +18,16 @@ import { fileURLToPath } from 'url'; import tmp from 'tmp'; import pathUtil from './config/path-util.js'; -import babelLoaderUtil from './loaders/babel.js'; -import cssExtractLoaderUtil from './loaders/css-extract.js'; +import babelLoaderUtil from './loaders/babel.ts'; +import cssExtractLoaderUtil from './loaders/css-extract.ts'; // loaders utils -import cssLoaderUtil from './loaders/css.js'; -import handlebarsLoaderUtil from './loaders/handlebars.js'; -import lessLoaderUtil from './loaders/less.js'; -import sassLoaderUtil from './loaders/sass.js'; -import stylusLoaderUtil from './loaders/stylus.js'; -import tsLoaderUtil from './loaders/typescript.js'; -import vueLoaderUtil from './loaders/vue.js'; +import cssLoaderUtil from './loaders/css.ts'; +import handlebarsLoaderUtil from './loaders/handlebars.ts'; +import lessLoaderUtil from './loaders/less.ts'; +import sassLoaderUtil from './loaders/sass.ts'; +import stylusLoaderUtil from './loaders/stylus.ts'; +import tsLoaderUtil from './loaders/typescript.ts'; +import vueLoaderUtil from './loaders/vue.ts'; import logger from './logger.js'; // plugins utils import assetOutputDisplay from './plugins/asset-output-display.ts'; diff --git a/lib/loaders/babel.js b/lib/loaders/babel.ts similarity index 90% rename from lib/loaders/babel.js rename to lib/loaders/babel.ts index 2044f16e..e46e7554 100644 --- a/lib/loaders/babel.js +++ b/lib/loaders/babel.ts @@ -7,22 +7,15 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import type WebpackConfig from '../WebpackConfig.js'; export default { - /** - * @param {WebpackConfig} webpackConfig - * @returns {Promise} of loaders to use for Babel - */ - async getLoaders(webpackConfig) { - let babelConfig = { + async getLoaders(webpackConfig: WebpackConfig) { + let babelConfig: Record = { // improves performance by caching babel compiles // this option is always added but is set to FALSE in // production to avoid cache invalidation issues caused @@ -39,7 +32,7 @@ export default { // configure babel (unless the user is specifying .babelrc) // todo - add a sanity check for their babelrc contents if (!(await webpackConfig.doesBabelRcFileExist())) { - let presetEnvOptions = { + let presetEnvOptions: Record = { // modules don't need to be transformed - webpack will parse // the modules for us. This is a performance improvement // https://babeljs.io/docs/en/babel-preset-env#modules @@ -49,10 +42,10 @@ export default { corejs: webpackConfig.babelOptions.corejs, }; - presetEnvOptions = applyOptionsCallback( + presetEnvOptions = applyOptionsCallback( webpackConfig.babelPresetEnvOptionsCallback, presetEnvOptions - ); + ) as Record; if (presetEnvOptions.useBuiltIns !== false) { throw new Error( @@ -117,10 +110,10 @@ export default { ); } - babelConfig = applyOptionsCallback( + babelConfig = applyOptionsCallback( webpackConfig.babelConfigurationCallback, babelConfig - ); + ) as Record; } return [ @@ -131,11 +124,7 @@ export default { ]; }, - /** - * @param {WebpackConfig} webpackConfig - * @returns {RegExp} to use for the Babel loader `test` rule - */ - getTest(webpackConfig) { + getTest(webpackConfig: WebpackConfig) { const extensions = [ 'm?jsx?', // match .js and .jsx and .mjs ]; diff --git a/lib/loaders/css-extract.js b/lib/loaders/css-extract.ts similarity index 84% rename from lib/loaders/css-extract.js rename to lib/loaders/css-extract.ts index 52b48085..ad2df858 100644 --- a/lib/loaders/css-extract.js +++ b/lib/loaders/css-extract.ts @@ -7,25 +7,18 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import { fileURLToPath } from 'url'; import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import type WebpackConfig from '../WebpackConfig.js'; export default { /** * Prepends loaders with MiniCssExtractPlugin.loader - * - * @param {WebpackConfig} webpackConfig - * @param {Array} loaders An array of some style loaders - * @returns {Array} */ - prependLoaders(webpackConfig, loaders) { + prependLoaders(webpackConfig: WebpackConfig, loaders: object[]) { if (!webpackConfig.extractCss) { const options = {}; diff --git a/lib/loaders/css.js b/lib/loaders/css.ts similarity index 84% rename from lib/loaders/css.js rename to lib/loaders/css.ts index 0723d1d2..e7d0c874 100644 --- a/lib/loaders/css.js +++ b/lib/loaders/css.ts @@ -7,28 +7,17 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import type WebpackConfig from '../WebpackConfig.js'; export default { - /** - * @param {WebpackConfig} webpackConfig - * @param {boolean} useCssModules - * @returns {Array} of loaders to use for CSS files - */ - getLoaders(webpackConfig, useCssModules = false) { + getLoaders(webpackConfig: WebpackConfig, useCssModules = false) { const usePostCssLoader = webpackConfig.usePostCssLoader; - /** - * @type {boolean|object} - */ - let modulesConfig = false; + let modulesConfig: boolean | object = false; if (useCssModules) { modulesConfig = { localIdentName: '[local]_[hash:base64:5]', diff --git a/lib/loaders/handlebars.js b/lib/loaders/handlebars.ts similarity index 79% rename from lib/loaders/handlebars.js rename to lib/loaders/handlebars.ts index 264f439e..8e7122bf 100644 --- a/lib/loaders/handlebars.js +++ b/lib/loaders/handlebars.ts @@ -7,21 +7,14 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import type WebpackConfig from '../WebpackConfig.js'; export default { - /** - * @param {WebpackConfig} webpackConfig - * @returns {Array} of loaders to use for Handlebars - */ - getLoaders(webpackConfig) { + getLoaders(webpackConfig: WebpackConfig) { loaderFeatures.ensurePackagesExistAndAreCorrectVersion('handlebars'); const options = {}; diff --git a/lib/loaders/less.js b/lib/loaders/less.ts similarity index 74% rename from lib/loaders/less.js rename to lib/loaders/less.ts index 3f7bc129..b91036e6 100644 --- a/lib/loaders/less.js +++ b/lib/loaders/less.ts @@ -7,23 +7,15 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; -import cssLoader from './css.js'; +import type WebpackConfig from '../WebpackConfig.js'; +import cssLoader from './css.ts'; export default { - /** - * @param {WebpackConfig} webpackConfig - * @param {boolean} useCssModules - * @returns {Array} of loaders to use for Less files - */ - getLoaders(webpackConfig, useCssModules = false) { + getLoaders(webpackConfig: WebpackConfig, useCssModules = false) { loaderFeatures.ensurePackagesExistAndAreCorrectVersion('less'); const config = { diff --git a/lib/loaders/sass.js b/lib/loaders/sass.ts similarity index 86% rename from lib/loaders/sass.js rename to lib/loaders/sass.ts index 8c24fbd9..2833cdd0 100644 --- a/lib/loaders/sass.js +++ b/lib/loaders/sass.ts @@ -7,23 +7,15 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; -import cssLoader from './css.js'; +import type WebpackConfig from '../WebpackConfig.js'; +import cssLoader from './css.ts'; export default { - /** - * @param {WebpackConfig} webpackConfig - * @param {boolean} useCssModules - * @returns {Array} of loaders to use for Sass files - */ - getLoaders(webpackConfig, useCssModules = false) { + getLoaders(webpackConfig: WebpackConfig, useCssModules = false) { loaderFeatures.ensurePackagesExistAndAreCorrectVersion('sass'); const sassLoaders = [...cssLoader.getLoaders(webpackConfig, useCssModules)]; diff --git a/lib/loaders/stylus.js b/lib/loaders/stylus.ts similarity index 74% rename from lib/loaders/stylus.js rename to lib/loaders/stylus.ts index a908c84f..f69f7428 100644 --- a/lib/loaders/stylus.js +++ b/lib/loaders/stylus.ts @@ -7,23 +7,15 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; -import cssLoader from './css.js'; +import type WebpackConfig from '../WebpackConfig.js'; +import cssLoader from './css.ts'; export default { - /** - * @param {WebpackConfig} webpackConfig - * @param {boolean} useCssModules - * @returns {Array} of loaders to use for Stylus files - */ - getLoaders(webpackConfig, useCssModules = false) { + getLoaders(webpackConfig: WebpackConfig, useCssModules = false) { loaderFeatures.ensurePackagesExistAndAreCorrectVersion('stylus'); const config = { diff --git a/lib/loaders/typescript.js b/lib/loaders/typescript.ts similarity index 62% rename from lib/loaders/typescript.js rename to lib/loaders/typescript.ts index 086d842b..ab7e77a2 100644 --- a/lib/loaders/typescript.js +++ b/lib/loaders/typescript.ts @@ -7,31 +7,27 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; -import babelLoader from './babel.js'; +import type WebpackConfig from '../WebpackConfig.js'; +import babelLoader from './babel.ts'; export default { - /** - * @param {WebpackConfig} webpackConfig - * @returns {Promise} of loaders to use for TypeScript - */ - async getLoaders(webpackConfig) { + async getLoaders(webpackConfig: WebpackConfig) { loaderFeatures.ensurePackagesExistAndAreCorrectVersion('typescript'); // some defaults - let config = { + let config: Record = { silent: true, }; // allow for ts-loader config to be controlled - config = applyOptionsCallback(webpackConfig.tsConfigurationCallback, config); + config = applyOptionsCallback( + webpackConfig.tsConfigurationCallback, + config + ) as Record; // fork-ts-checker-webpack-plugin integration if (webpackConfig.useForkedTypeScriptTypeChecking) { @@ -39,10 +35,10 @@ export default { // force transpileOnly to speed up config.transpileOnly = true; - // add forked ts types plugin to the stack. - // eslint-disable-next-line n/no-missing-import -- this `.js` file dynamically imports a migrated `.ts` plugin; eslint-plugin-n can't resolve it and rewriteRelativeImportExtensions does not rewrite dynamic import() in `.js`. Remove once this loader is migrated to TS. - const forkedTs = await import('../plugins/forked-ts-types.js'); - forkedTs.default(webpackConfig); + // add forked ts types plugin to the stack + const { default: forkedTypesPluginUtil } = + await import('../plugins/forked-ts-types.js'); + forkedTypesPluginUtil(webpackConfig); } // allow to import .vue files @@ -52,7 +48,7 @@ export default { // use ts alongside with babel // @see https://github.com/TypeStrong/ts-loader/blob/master/README.md#babel - let loaders = await babelLoader.getLoaders(webpackConfig); + const loaders = await babelLoader.getLoaders(webpackConfig); return loaders.concat([ { loader: fileURLToPath(import.meta.resolve('ts-loader')), diff --git a/lib/loaders/vue.js b/lib/loaders/vue.ts similarity index 80% rename from lib/loaders/vue.js rename to lib/loaders/vue.ts index aaf1cdc4..f6c42a71 100644 --- a/lib/loaders/vue.js +++ b/lib/loaders/vue.ts @@ -7,22 +7,15 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - import { fileURLToPath } from 'url'; import loaderFeatures from '../features.js'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import getVueVersion from '../utils/get-vue-version.ts'; +import type WebpackConfig from '../WebpackConfig.js'; export default { - /** - * @param {WebpackConfig} webpackConfig - * @returns {Array} of loaders to use for Vue files - */ - getLoaders(webpackConfig) { + getLoaders(webpackConfig: WebpackConfig) { const vueVersion = getVueVersion(webpackConfig); loaderFeatures.ensurePackagesExistAndAreCorrectVersion('vue' + vueVersion); diff --git a/test/loaders/babel.js b/test/loaders/babel.js index d9353e60..0ceef884 100644 --- a/test/loaders/babel.js +++ b/test/loaders/babel.js @@ -12,7 +12,7 @@ import { fileURLToPath } from 'url'; import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import babelLoader from '../../lib/loaders/babel.js'; +import babelLoader from '../../lib/loaders/babel.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { diff --git a/test/loaders/css-extract.js b/test/loaders/css-extract.js index 8c0cc347..0600a416 100644 --- a/test/loaders/css-extract.js +++ b/test/loaders/css-extract.js @@ -11,7 +11,7 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import cssExtractLoader from '../../lib/loaders/css-extract.js'; +import cssExtractLoader from '../../lib/loaders/css-extract.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { diff --git a/test/loaders/css.js b/test/loaders/css.js index 583f7b2a..238885cc 100644 --- a/test/loaders/css.js +++ b/test/loaders/css.js @@ -10,7 +10,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import cssLoader from '../../lib/loaders/css.js'; +import cssLoader from '../../lib/loaders/css.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { diff --git a/test/loaders/handlebars.js b/test/loaders/handlebars.js index 26a43c3f..4c67ea8c 100644 --- a/test/loaders/handlebars.js +++ b/test/loaders/handlebars.js @@ -10,7 +10,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import handlebarsLoader from '../../lib/loaders/handlebars.js'; +import handlebarsLoader from '../../lib/loaders/handlebars.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { diff --git a/test/loaders/less.js b/test/loaders/less.js index 3d1ff024..c873216d 100644 --- a/test/loaders/less.js +++ b/test/loaders/less.js @@ -10,8 +10,8 @@ import { vi, describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import cssLoader from '../../lib/loaders/css.js'; -import lessLoader from '../../lib/loaders/less.js'; +import cssLoader from '../../lib/loaders/css.ts'; +import lessLoader from '../../lib/loaders/less.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { diff --git a/test/loaders/sass.js b/test/loaders/sass.js index 142eebe3..c141e8c7 100644 --- a/test/loaders/sass.js +++ b/test/loaders/sass.js @@ -10,8 +10,8 @@ import { vi, describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import cssLoader from '../../lib/loaders/css.js'; -import sassLoader from '../../lib/loaders/sass.js'; +import cssLoader from '../../lib/loaders/css.ts'; +import sassLoader from '../../lib/loaders/sass.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { diff --git a/test/loaders/stylus.js b/test/loaders/stylus.js index 4555fd92..8eac4434 100644 --- a/test/loaders/stylus.js +++ b/test/loaders/stylus.js @@ -10,8 +10,8 @@ import { vi, describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import cssLoader from '../../lib/loaders/css.js'; -import stylusLoader from '../../lib/loaders/stylus.js'; +import cssLoader from '../../lib/loaders/css.ts'; +import stylusLoader from '../../lib/loaders/stylus.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { diff --git a/test/loaders/typescript.js b/test/loaders/typescript.js index 09b3cc29..3a52512a 100644 --- a/test/loaders/typescript.js +++ b/test/loaders/typescript.js @@ -10,7 +10,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import tsLoader from '../../lib/loaders/typescript.js'; +import tsLoader from '../../lib/loaders/typescript.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { diff --git a/test/loaders/vue.js b/test/loaders/vue.js index 21d16838..eb2d8629 100644 --- a/test/loaders/vue.js +++ b/test/loaders/vue.js @@ -10,7 +10,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import vueLoader from '../../lib/loaders/vue.js'; +import vueLoader from '../../lib/loaders/vue.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { diff --git a/test/plugins/forked-ts-types.js b/test/plugins/forked-ts-types.js index 17dbcbbb..529ff1a0 100644 --- a/test/plugins/forked-ts-types.js +++ b/test/plugins/forked-ts-types.js @@ -11,7 +11,7 @@ import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import tsLoader from '../../lib/loaders/typescript.js'; +import tsLoader from '../../lib/loaders/typescript.ts'; import tsTypeChecker from '../../lib/plugins/forked-ts-types.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; From 58df3253b78a0dd9c1a501a4a66e225fc59c9752 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Thu, 25 Jun 2026 22:34:21 +0200 Subject: [PATCH 05/12] [TypeScript] Migrate `lib/plugins/*` (#1507) --- .../asset-output-display-plugin.js | 31 -------------- .../asset-output-display-plugin.ts | 41 +++++++++++++++++++ ...issing-css-file.js => missing-css-file.ts} | 13 ++++-- .../{missing-loader.js => missing-loader.ts} | 23 +++++++---- ...ss-config.js => missing-postcss-config.ts} | 7 ++-- ...issing-css-file.js => missing-css-file.ts} | 8 ++-- .../{missing-loader.js => missing-loader.ts} | 25 ++++++----- ...ss-config.js => missing-postcss-config.ts} | 6 ++- lib/plugins/asset-output-display.ts | 2 +- lib/plugins/friendly-errors.ts | 12 +++--- .../formatters/missing-css-file.js | 2 +- .../formatters/missing-loader.js | 2 +- .../transformers/missing-css-file.js | 2 +- .../transformers/missing-loader.js | 2 +- 14 files changed, 104 insertions(+), 72 deletions(-) delete mode 100644 lib/friendly-errors/asset-output-display-plugin.js create mode 100644 lib/friendly-errors/asset-output-display-plugin.ts rename lib/friendly-errors/formatters/{missing-css-file.js => missing-css-file.ts} (70%) rename lib/friendly-errors/formatters/{missing-loader.js => missing-loader.ts} (75%) rename lib/friendly-errors/formatters/{missing-postcss-config.js => missing-postcss-config.ts} (85%) rename lib/friendly-errors/transformers/{missing-css-file.js => missing-css-file.ts} (78%) rename lib/friendly-errors/transformers/{missing-loader.js => missing-loader.ts} (73%) rename lib/friendly-errors/transformers/{missing-postcss-config.js => missing-postcss-config.ts} (75%) diff --git a/lib/friendly-errors/asset-output-display-plugin.js b/lib/friendly-errors/asset-output-display-plugin.js deleted file mode 100644 index 2b380bca..00000000 --- a/lib/friendly-errors/asset-output-display-plugin.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of the Symfony Webpack Encore package. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import pc from 'picocolors'; - -function AssetOutputDisplayPlugin(outputPath, friendlyErrorsPlugin) { - this.outputPath = outputPath; - this.friendlyErrorsPlugin = friendlyErrorsPlugin; -} - -AssetOutputDisplayPlugin.prototype.apply = function (compiler) { - const emit = (compilation, callback) => { - // completely reset messages key to avoid adding more and more messages - // when using watch - this.friendlyErrorsPlugin.compilationSuccessInfo.messages = [ - `${pc.yellow(Object.keys(compilation.assets).length)} files written to ${pc.yellow(this.outputPath)}`, - ]; - - callback(); - }; - - compiler.hooks.emit.tapAsync({ name: 'AssetOutputDisplayPlugin' }, emit); -}; - -export default AssetOutputDisplayPlugin; diff --git a/lib/friendly-errors/asset-output-display-plugin.ts b/lib/friendly-errors/asset-output-display-plugin.ts new file mode 100644 index 00000000..974cbf87 --- /dev/null +++ b/lib/friendly-errors/asset-output-display-plugin.ts @@ -0,0 +1,41 @@ +/* + * This file is part of the Symfony Webpack Encore package. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import type FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin'; +import pc from 'picocolors'; +import type { Compilation, Compiler } from 'webpack'; + +class AssetOutputDisplayPlugin { + outputPath: string; + friendlyErrorsPlugin: FriendlyErrorsWebpackPlugin; + + constructor(outputPath: string, friendlyErrorsPlugin: FriendlyErrorsWebpackPlugin) { + this.outputPath = outputPath; + this.friendlyErrorsPlugin = friendlyErrorsPlugin; + } + + apply(compiler: Compiler): void { + const emit = (compilation: Compilation, callback: () => void) => { + // completely reset messages key to avoid adding more and more messages + // when using watch + const plugin = this.friendlyErrorsPlugin as FriendlyErrorsWebpackPlugin & { + compilationSuccessInfo: { messages: string[] }; + }; + plugin.compilationSuccessInfo.messages = [ + `${pc.yellow(Object.keys(compilation.assets).length)} files written to ${pc.yellow(this.outputPath)}`, + ]; + + callback(); + }; + + compiler.hooks.emit.tapAsync({ name: 'AssetOutputDisplayPlugin' }, emit); + } +} + +export default AssetOutputDisplayPlugin; diff --git a/lib/friendly-errors/formatters/missing-css-file.js b/lib/friendly-errors/formatters/missing-css-file.ts similarity index 70% rename from lib/friendly-errors/formatters/missing-css-file.js rename to lib/friendly-errors/formatters/missing-css-file.ts index a98568ba..2061909b 100644 --- a/lib/friendly-errors/formatters/missing-css-file.js +++ b/lib/friendly-errors/formatters/missing-css-file.ts @@ -7,17 +7,22 @@ * file that was distributed with this source code. */ +import type { FriendlyError } from '@kocal/friendly-errors-webpack-plugin'; import pc from 'picocolors'; -function formatErrors(errors) { +interface MissingCssFileError extends FriendlyError { + ref?: string; +} + +function formatErrors(errors: MissingCssFileError[]): string[] { if (errors.length === 0) { return []; } - let messages = []; + const messages: string[] = []; messages.push(pc.red('Module build failed: Module not found:')); - for (let error of errors) { + for (const error of errors) { messages.push(`"${error.file}" contains a reference to the file "${error.ref}".`); messages.push( 'This file can not be found, please check it for typos or update it if the file got moved.' @@ -28,7 +33,7 @@ function formatErrors(errors) { return messages; } -function format(errors) { +function format(errors: FriendlyError[]): string[] { return formatErrors(errors.filter((e) => e.type === 'missing-css-file')); } diff --git a/lib/friendly-errors/formatters/missing-loader.js b/lib/friendly-errors/formatters/missing-loader.ts similarity index 75% rename from lib/friendly-errors/formatters/missing-loader.js rename to lib/friendly-errors/formatters/missing-loader.ts index 94409050..87d1d26e 100644 --- a/lib/friendly-errors/formatters/missing-loader.js +++ b/lib/friendly-errors/formatters/missing-loader.ts @@ -7,22 +7,29 @@ * file that was distributed with this source code. */ +import type { FriendlyError } from '@kocal/friendly-errors-webpack-plugin'; import pc from 'picocolors'; import loaderFeatures from '../../features.js'; -function formatErrors(errors) { +interface MissingLoaderError extends FriendlyError { + loaderName?: string; + isVueLoader?: boolean; + origin?: string; +} + +function formatErrors(errors: MissingLoaderError[]): string[] { if (errors.length === 0) { return []; } - let messages = []; + let messages: string[] = []; - for (let error of errors) { - const fixes = []; + for (const error of errors) { + const fixes: string[] = []; if (error.loaderName) { - let neededCode = `Encore.${loaderFeatures.getFeatureMethod(error.loaderName)}`; + const neededCode = `Encore.${loaderFeatures.getFeatureMethod(error.loaderName)}`; fixes.push(`Add ${pc.green(neededCode)} to your Webpack config file.`); const packageRecommendations = loaderFeatures.getMissingPackageRecommendations( @@ -43,7 +50,7 @@ function formatErrors(errors) { // vue hides their filenames (via a stacktrace) inside error.origin if (error.isVueLoader) { messages.push(error.message); - messages.push(error.origin); + messages.push(error.origin ?? ''); messages.push(''); } else { messages = messages.concat([pc.red(`Error loading ${pc.yellow(error.file)}`), '']); @@ -58,7 +65,7 @@ function formatErrors(errors) { } let index = 0; - for (let fix of fixes) { + for (const fix of fixes) { messages.push(` ${++index}. ${fix}`); } @@ -68,7 +75,7 @@ function formatErrors(errors) { return messages; } -function format(errors) { +function format(errors: FriendlyError[]): string[] { return formatErrors(errors.filter((e) => e.type === 'loader-not-enabled')); } diff --git a/lib/friendly-errors/formatters/missing-postcss-config.js b/lib/friendly-errors/formatters/missing-postcss-config.ts similarity index 85% rename from lib/friendly-errors/formatters/missing-postcss-config.js rename to lib/friendly-errors/formatters/missing-postcss-config.ts index 879213e1..68d0ec14 100644 --- a/lib/friendly-errors/formatters/missing-postcss-config.js +++ b/lib/friendly-errors/formatters/missing-postcss-config.ts @@ -7,14 +7,15 @@ * file that was distributed with this source code. */ +import type { FriendlyError } from '@kocal/friendly-errors-webpack-plugin'; import pc from 'picocolors'; -function formatErrors(errors) { +function formatErrors(errors: FriendlyError[]): string[] { if (errors.length === 0) { return []; } - let messages = []; + const messages: string[] = []; // there will be an error for *every* file, but showing // the error over and over again is not helpful @@ -50,7 +51,7 @@ module.exports = { return messages; } -function format(errors) { +function format(errors: FriendlyError[]): string[] { return formatErrors(errors.filter((e) => e.type === 'missing-postcss-config')); } diff --git a/lib/friendly-errors/transformers/missing-css-file.js b/lib/friendly-errors/transformers/missing-css-file.ts similarity index 78% rename from lib/friendly-errors/transformers/missing-css-file.js rename to lib/friendly-errors/transformers/missing-css-file.ts index 867c64fe..0d095109 100644 --- a/lib/friendly-errors/transformers/missing-css-file.js +++ b/lib/friendly-errors/transformers/missing-css-file.ts @@ -7,9 +7,11 @@ * file that was distributed with this source code. */ +import type { FriendlyError } from '@kocal/friendly-errors-webpack-plugin'; + const TYPE = 'missing-css-file'; -function isMissingConfigError(e) { +function isMissingConfigError(e: FriendlyError): boolean { if (e.name !== 'ModuleNotFoundError') { return false; } @@ -21,14 +23,14 @@ function isMissingConfigError(e) { return true; } -function getReference(error) { +function getReference(error: FriendlyError): string { const index = error.message.indexOf("Can't resolve '") + 15; const endIndex = error.message.indexOf("' in '"); return error.message.substring(index, endIndex); } -function transform(error) { +function transform(error: FriendlyError): FriendlyError { if (!isMissingConfigError(error)) { return error; } diff --git a/lib/friendly-errors/transformers/missing-loader.js b/lib/friendly-errors/transformers/missing-loader.ts similarity index 73% rename from lib/friendly-errors/transformers/missing-loader.js rename to lib/friendly-errors/transformers/missing-loader.ts index afff0045..238a8ac7 100644 --- a/lib/friendly-errors/transformers/missing-loader.js +++ b/lib/friendly-errors/transformers/missing-loader.ts @@ -7,11 +7,14 @@ * file that was distributed with this source code. */ +import type { FriendlyError, Transformer } from '@kocal/friendly-errors-webpack-plugin'; + import getVueVersion from '../../utils/get-vue-version.ts'; +import type WebpackConfig from '../../WebpackConfig.js'; const TYPE = 'loader-not-enabled'; -function isMissingLoaderError(e) { +function isMissingLoaderError(e: FriendlyError): boolean { if (e.name !== 'ModuleParseError') { return false; } @@ -23,7 +26,7 @@ function isMissingLoaderError(e) { return true; } -function isErrorFromVueLoader(filename) { +function isErrorFromVueLoader(filename: string): boolean { // vue3 if (/vue-loader\/dist(\/index\.js)?\?\?/.test(filename)) { return true; @@ -37,7 +40,7 @@ function isErrorFromVueLoader(filename) { return false; } -function getFileExtension(filename) { +function getFileExtension(filename: string): string { // ??vue-loader-options if (isErrorFromVueLoader(filename)) { // vue is strange, the "filename" is reported as something like @@ -54,18 +57,20 @@ function getFileExtension(filename) { const str = filename.replace(/\?.*/, ''); const split = str.split('.'); - return split.pop(); + return split.pop() ?? ''; } -function transform(error, webpackConfig) { +function transform(error: FriendlyError, webpackConfig: WebpackConfig): FriendlyError { if (!isMissingLoaderError(error)) { return error; } error = Object.assign({}, error); - error.isVueLoader = isErrorFromVueLoader(error.file); - const extension = getFileExtension(error.file); + const filename = error.file ?? ''; + error.isVueLoader = isErrorFromVueLoader(filename); + + const extension = getFileExtension(filename); switch (extension) { case 'sass': case 'scss': @@ -78,7 +83,7 @@ function transform(error, webpackConfig) { error.loaderName = 'react'; break; case 'vue': - error.loaderName = 'vue' + getVueVersion(webpackConfig); + error.loaderName = `vue${getVueVersion(webpackConfig)}`; break; case 'tsx': case 'ts': @@ -99,8 +104,8 @@ function transform(error, webpackConfig) { /* * Returns a factory to get the function. */ -export default function (webpackConfig) { - return function (error) { +export default function (webpackConfig: WebpackConfig): Transformer { + return function (error: FriendlyError): FriendlyError { return transform(error, webpackConfig); }; } diff --git a/lib/friendly-errors/transformers/missing-postcss-config.js b/lib/friendly-errors/transformers/missing-postcss-config.ts similarity index 75% rename from lib/friendly-errors/transformers/missing-postcss-config.js rename to lib/friendly-errors/transformers/missing-postcss-config.ts index f0471ee1..df8633a0 100644 --- a/lib/friendly-errors/transformers/missing-postcss-config.js +++ b/lib/friendly-errors/transformers/missing-postcss-config.ts @@ -7,9 +7,11 @@ * file that was distributed with this source code. */ +import type { FriendlyError } from '@kocal/friendly-errors-webpack-plugin'; + const TYPE = 'missing-postcss-config'; -function isMissingConfigError(e) { +function isMissingConfigError(e: FriendlyError): boolean { if (!e.message || !e.message.includes('No PostCSS Config found')) { return false; } @@ -17,7 +19,7 @@ function isMissingConfigError(e) { return true; } -function transform(error) { +function transform(error: FriendlyError): FriendlyError { if (!isMissingConfigError(error)) { return error; } diff --git a/lib/plugins/asset-output-display.ts b/lib/plugins/asset-output-display.ts index 24a34970..824e8737 100644 --- a/lib/plugins/asset-output-display.ts +++ b/lib/plugins/asset-output-display.ts @@ -10,7 +10,7 @@ import type FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin'; import pathUtil from '../config/path-util.js'; -import AssetOutputDisplayPlugin from '../friendly-errors/asset-output-display-plugin.js'; +import AssetOutputDisplayPlugin from '../friendly-errors/asset-output-display-plugin.ts'; import type WebpackConfig from '../WebpackConfig.js'; import PluginPriorities from './plugin-priorities.ts'; diff --git a/lib/plugins/friendly-errors.ts b/lib/plugins/friendly-errors.ts index 1342f411..07b3bf6d 100644 --- a/lib/plugins/friendly-errors.ts +++ b/lib/plugins/friendly-errors.ts @@ -9,12 +9,12 @@ import FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin'; -import missingCssFileFormatter from '../friendly-errors/formatters/missing-css-file.js'; -import missingLoaderFormatter from '../friendly-errors/formatters/missing-loader.js'; -import missingPostCssConfigFormatter from '../friendly-errors/formatters/missing-postcss-config.js'; -import missingCssFileTransformer from '../friendly-errors/transformers/missing-css-file.js'; -import missingLoaderTransformerFactory from '../friendly-errors/transformers/missing-loader.js'; -import missingPostCssConfigTransformer from '../friendly-errors/transformers/missing-postcss-config.js'; +import missingCssFileFormatter from '../friendly-errors/formatters/missing-css-file.ts'; +import missingLoaderFormatter from '../friendly-errors/formatters/missing-loader.ts'; +import missingPostCssConfigFormatter from '../friendly-errors/formatters/missing-postcss-config.ts'; +import missingCssFileTransformer from '../friendly-errors/transformers/missing-css-file.ts'; +import missingLoaderTransformerFactory from '../friendly-errors/transformers/missing-loader.ts'; +import missingPostCssConfigTransformer from '../friendly-errors/transformers/missing-postcss-config.ts'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import type WebpackConfig from '../WebpackConfig.js'; diff --git a/test/friendly-errors/formatters/missing-css-file.js b/test/friendly-errors/formatters/missing-css-file.js index 20dd294c..7c1a2d9c 100644 --- a/test/friendly-errors/formatters/missing-css-file.js +++ b/test/friendly-errors/formatters/missing-css-file.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import formatter from '../../../lib/friendly-errors/formatters/missing-css-file.js'; +import formatter from '../../../lib/friendly-errors/formatters/missing-css-file.ts'; describe('formatters/missing-css-file', function () { describe('test format()', function () { diff --git a/test/friendly-errors/formatters/missing-loader.js b/test/friendly-errors/formatters/missing-loader.js index cf5e2022..2da33891 100644 --- a/test/friendly-errors/formatters/missing-loader.js +++ b/test/friendly-errors/formatters/missing-loader.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import formatter from '../../../lib/friendly-errors/formatters/missing-loader.js'; +import formatter from '../../../lib/friendly-errors/formatters/missing-loader.ts'; describe('formatters/missing-loader', function () { describe('test format()', function () { diff --git a/test/friendly-errors/transformers/missing-css-file.js b/test/friendly-errors/transformers/missing-css-file.js index c2dbef08..4bf1ec4d 100644 --- a/test/friendly-errors/transformers/missing-css-file.js +++ b/test/friendly-errors/transformers/missing-css-file.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import transform from '../../../lib/friendly-errors/transformers/missing-css-file.js'; +import transform from '../../../lib/friendly-errors/transformers/missing-css-file.ts'; describe('transform/missing-css-file', function () { describe('test transform', function () { diff --git a/test/friendly-errors/transformers/missing-loader.js b/test/friendly-errors/transformers/missing-loader.js index bd757935..69572c15 100644 --- a/test/friendly-errors/transformers/missing-loader.js +++ b/test/friendly-errors/transformers/missing-loader.js @@ -10,7 +10,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../../lib/config/RuntimeConfig.js'; -import transformFactory from '../../../lib/friendly-errors/transformers/missing-loader.js'; +import transformFactory from '../../../lib/friendly-errors/transformers/missing-loader.ts'; import WebpackConfig from '../../../lib/WebpackConfig.js'; const runtimeConfig = new RuntimeConfig(); From 540384bb0a08e7935ad2a921fd4a194b78391234 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Sat, 27 Jun 2026 22:17:01 +0200 Subject: [PATCH 06/12] [TypeScript] Improve "too weak" types --- lib/loaders/css-extract.ts | 3 ++- lib/plugins/asset-output-display.ts | 3 ++- lib/plugins/define.ts | 2 +- lib/plugins/delete-unused-entries.ts | 4 +++- lib/plugins/entry-files-manifest.ts | 4 +++- lib/plugins/manifest.ts | 3 ++- lib/plugins/mini-css-extract.ts | 3 ++- lib/plugins/notifier.ts | 4 +++- lib/plugins/variable-provider.ts | 2 +- lib/plugins/vue.ts | 4 +++- 10 files changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/loaders/css-extract.ts b/lib/loaders/css-extract.ts index ad2df858..66695c9a 100644 --- a/lib/loaders/css-extract.ts +++ b/lib/loaders/css-extract.ts @@ -10,6 +10,7 @@ import { fileURLToPath } from 'url'; import MiniCssExtractPlugin from 'mini-css-extract-plugin'; +import type { RuleSetUseItem } from 'webpack'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import type WebpackConfig from '../WebpackConfig.js'; @@ -18,7 +19,7 @@ export default { /** * Prepends loaders with MiniCssExtractPlugin.loader */ - prependLoaders(webpackConfig: WebpackConfig, loaders: object[]) { + prependLoaders(webpackConfig: WebpackConfig, loaders: RuleSetUseItem[]): RuleSetUseItem[] { if (!webpackConfig.extractCss) { const options = {}; diff --git a/lib/plugins/asset-output-display.ts b/lib/plugins/asset-output-display.ts index 824e8737..41bc909e 100644 --- a/lib/plugins/asset-output-display.ts +++ b/lib/plugins/asset-output-display.ts @@ -8,6 +8,7 @@ */ import type FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin'; +import type { WebpackPluginInstance } from 'webpack'; import pathUtil from '../config/path-util.js'; import AssetOutputDisplayPlugin from '../friendly-errors/asset-output-display-plugin.ts'; @@ -18,7 +19,7 @@ import PluginPriorities from './plugin-priorities.ts'; * Updates plugins array passed adding AssetOutputDisplayPlugin instance */ export default function ( - plugins: Array<{ plugin: object; priority: number }>, + plugins: Array<{ plugin: WebpackPluginInstance; priority: number }>, webpackConfig: WebpackConfig, friendlyErrorsPlugin: FriendlyErrorsWebpackPlugin ): void { diff --git a/lib/plugins/define.ts b/lib/plugins/define.ts index 0a326c95..bf119feb 100644 --- a/lib/plugins/define.ts +++ b/lib/plugins/define.ts @@ -14,7 +14,7 @@ import type WebpackConfig from '../WebpackConfig.js'; import PluginPriorities from './plugin-priorities.ts'; export default function ( - plugins: Array<{ plugin: object; priority: number }>, + plugins: Array<{ plugin: webpack.WebpackPluginInstance; priority: number }>, webpackConfig: WebpackConfig ): void { const definePluginOptions = { diff --git a/lib/plugins/delete-unused-entries.ts b/lib/plugins/delete-unused-entries.ts index 8b954f82..37bbdbe0 100644 --- a/lib/plugins/delete-unused-entries.ts +++ b/lib/plugins/delete-unused-entries.ts @@ -7,13 +7,15 @@ * file that was distributed with this source code. */ +import type { WebpackPluginInstance } from 'webpack'; + import copyEntryTmpName from '../utils/copyEntryTmpName.ts'; import DeleteUnusedEntriesJSPlugin from '../webpack/delete-unused-entries-js-plugin.js'; import type WebpackConfig from '../WebpackConfig.js'; import PluginPriorities from './plugin-priorities.ts'; export default function ( - plugins: Array<{ plugin: object; priority: number }>, + plugins: Array<{ plugin: WebpackPluginInstance; priority: number }>, webpackConfig: WebpackConfig ): void { const entries = [...webpackConfig.styleEntries.keys()]; diff --git a/lib/plugins/entry-files-manifest.ts b/lib/plugins/entry-files-manifest.ts index 7d9644d8..8abfc5ef 100644 --- a/lib/plugins/entry-files-manifest.ts +++ b/lib/plugins/entry-files-manifest.ts @@ -7,12 +7,14 @@ * file that was distributed with this source code. */ +import type { WebpackPluginInstance } from 'webpack'; + import { EntryPointsPlugin } from '../webpack/entry-points-plugin.js'; import type WebpackConfig from '../WebpackConfig.js'; import PluginPriorities from './plugin-priorities.ts'; export default function ( - plugins: Array<{ plugin: object; priority: number }>, + plugins: Array<{ plugin: WebpackPluginInstance; priority: number }>, webpackConfig: WebpackConfig ): void { plugins.push({ diff --git a/lib/plugins/manifest.ts b/lib/plugins/manifest.ts index 28931b3e..721c2b64 100644 --- a/lib/plugins/manifest.ts +++ b/lib/plugins/manifest.ts @@ -7,6 +7,7 @@ * file that was distributed with this source code. */ +import type { WebpackPluginInstance } from 'webpack'; import { WebpackManifestPlugin } from 'webpack-manifest-plugin'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; @@ -24,7 +25,7 @@ type ManifestPluginOptions = { }; export default function ( - plugins: Array<{ plugin: object; priority: number }>, + plugins: Array<{ plugin: WebpackPluginInstance; priority: number }>, webpackConfig: WebpackConfig ): void { let manifestPluginOptions: ManifestPluginOptions = { diff --git a/lib/plugins/mini-css-extract.ts b/lib/plugins/mini-css-extract.ts index 18b08075..8fad7df9 100644 --- a/lib/plugins/mini-css-extract.ts +++ b/lib/plugins/mini-css-extract.ts @@ -8,13 +8,14 @@ */ import MiniCssExtractPlugin from 'mini-css-extract-plugin'; +import type { WebpackPluginInstance } from 'webpack'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import type WebpackConfig from '../WebpackConfig.js'; import PluginPriorities from './plugin-priorities.ts'; export default function ( - plugins: Array<{ plugin: object; priority: number }>, + plugins: Array<{ plugin: WebpackPluginInstance; priority: number }>, webpackConfig: WebpackConfig ): void { // Don't add the plugin if CSS extraction is disabled diff --git a/lib/plugins/notifier.ts b/lib/plugins/notifier.ts index 8cad3923..aea854bf 100644 --- a/lib/plugins/notifier.ts +++ b/lib/plugins/notifier.ts @@ -7,13 +7,15 @@ * file that was distributed with this source code. */ +import type { WebpackPluginInstance } from 'webpack'; + import pluginFeatures from '../features.js'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import type WebpackConfig from '../WebpackConfig.js'; import PluginPriorities from './plugin-priorities.ts'; export default async function ( - plugins: Array<{ plugin: object; priority: number }>, + plugins: Array<{ plugin: WebpackPluginInstance; priority: number }>, webpackConfig: WebpackConfig ): Promise { if (!webpackConfig.useWebpackNotifier) { diff --git a/lib/plugins/variable-provider.ts b/lib/plugins/variable-provider.ts index 158a6fdc..8f683a95 100644 --- a/lib/plugins/variable-provider.ts +++ b/lib/plugins/variable-provider.ts @@ -13,7 +13,7 @@ import type WebpackConfig from '../WebpackConfig.js'; import PluginPriorities from './plugin-priorities.ts'; export default function ( - plugins: Array<{ plugin: object; priority: number }>, + plugins: Array<{ plugin: webpack.WebpackPluginInstance; priority: number }>, webpackConfig: WebpackConfig ): void { if (Object.keys(webpackConfig.providedVariables).length > 0) { diff --git a/lib/plugins/vue.ts b/lib/plugins/vue.ts index 0633cd68..78de88dd 100644 --- a/lib/plugins/vue.ts +++ b/lib/plugins/vue.ts @@ -7,11 +7,13 @@ * file that was distributed with this source code. */ +import type { WebpackPluginInstance } from 'webpack'; + import type WebpackConfig from '../WebpackConfig.js'; import PluginPriorities from './plugin-priorities.ts'; export default async function ( - plugins: Array<{ plugin: object; priority: number }>, + plugins: Array<{ plugin: WebpackPluginInstance; priority: number }>, webpackConfig: WebpackConfig ): Promise { if (!webpackConfig.useVueLoader) { From 61d7078f51797f5770743468692af3b616b50923 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Tue, 30 Jun 2026 08:18:37 +0200 Subject: [PATCH 07/12] [TypeScript] Migrate `lib/config/*` (#1508) --- bin/encore.js | 2 +- index.js | 4 +-- lib/WebpackConfig.js | 2 +- lib/config-generator.js | 2 +- .../{RuntimeConfig.js => RuntimeConfig.ts} | 21 ++++++++++++ .../{parse-runtime.js => parse-runtime.ts} | 16 ++++----- lib/config/{path-util.js => path-util.ts} | 34 +++++-------------- lib/config/{validator.js => validator.ts} | 26 ++++++-------- lib/plugins/asset-output-display.ts | 2 +- package.json | 1 + pnpm-lock.yaml | 8 +++++ test/WebpackConfig.js | 2 +- test/config-generator.js | 2 +- test/config/parse-runtime.js | 2 +- test/config/path-util.js | 4 +-- test/config/validator.js | 4 +-- .../transformers/missing-loader.js | 2 +- test/helpers/setup.js | 4 +-- test/loaders/babel.js | 2 +- test/loaders/css-extract.js | 2 +- test/loaders/css.js | 2 +- test/loaders/handlebars.js | 2 +- test/loaders/less.js | 2 +- test/loaders/sass.js | 2 +- test/loaders/stylus.js | 2 +- test/loaders/typescript.js | 2 +- test/loaders/vue.js | 2 +- test/plugins/css-minimizer.js | 2 +- test/plugins/define.js | 2 +- test/plugins/forked-ts-types.js | 2 +- test/plugins/friendly-errors.js | 2 +- test/plugins/js-minimizer.js | 2 +- test/plugins/manifest.js | 2 +- test/plugins/mini-css-extract.js | 2 +- test/plugins/notifier.js | 2 +- test/utils/get-vue-version.js | 2 +- 36 files changed, 92 insertions(+), 82 deletions(-) rename lib/config/{RuntimeConfig.js => RuntimeConfig.ts} (63%) rename lib/config/{parse-runtime.js => parse-runtime.ts} (84%) rename lib/config/{path-util.js => path-util.ts} (90%) rename lib/config/{validator.js => validator.ts} (87%) diff --git a/bin/encore.js b/bin/encore.js index 3eb69f3a..593e3dbd 100755 --- a/bin/encore.js +++ b/bin/encore.js @@ -11,7 +11,7 @@ import pc from 'picocolors'; import yargsParser from 'yargs-parser'; -import parseRuntime from '../lib/config/parse-runtime.js'; +import parseRuntime from '../lib/config/parse-runtime.ts'; import context from '../lib/context.js'; import featuresHelper from '../lib/features.js'; import logger from '../lib/logger.js'; diff --git a/index.js b/index.js index 725419a0..4188afc6 100644 --- a/index.js +++ b/index.js @@ -26,8 +26,8 @@ import yargsParser from 'yargs-parser'; import configGenerator from './lib/config-generator.js'; -import parseRuntime from './lib/config/parse-runtime.js'; -import validator from './lib/config/validator.js'; +import parseRuntime from './lib/config/parse-runtime.ts'; +import validator from './lib/config/validator.ts'; import context from './lib/context.js'; import EncoreProxy from './lib/EncoreProxy.js'; import WebpackConfig from './lib/WebpackConfig.js'; diff --git a/lib/WebpackConfig.js b/lib/WebpackConfig.js index 98bb8606..616682bd 100644 --- a/lib/WebpackConfig.js +++ b/lib/WebpackConfig.js @@ -40,7 +40,7 @@ import crypto from 'crypto'; import fs from 'fs'; import path from 'path'; -import pathUtil from './config/path-util.js'; +import pathUtil from './config/path-util.ts'; import featuresHelper from './features.js'; import logger from './logger.js'; import regexpEscaper from './utils/regexp-escaper.ts'; diff --git a/lib/config-generator.js b/lib/config-generator.js index e578ecad..32c94cbd 100644 --- a/lib/config-generator.js +++ b/lib/config-generator.js @@ -17,7 +17,7 @@ import { fileURLToPath } from 'url'; import tmp from 'tmp'; -import pathUtil from './config/path-util.js'; +import pathUtil from './config/path-util.ts'; import babelLoaderUtil from './loaders/babel.ts'; import cssExtractLoaderUtil from './loaders/css-extract.ts'; // loaders utils diff --git a/lib/config/RuntimeConfig.js b/lib/config/RuntimeConfig.ts similarity index 63% rename from lib/config/RuntimeConfig.js rename to lib/config/RuntimeConfig.ts index b20531fa..9008b7b5 100644 --- a/lib/config/RuntimeConfig.js +++ b/lib/config/RuntimeConfig.ts @@ -8,6 +8,27 @@ */ class RuntimeConfig { + command: string | number | null; + context: string | null; + isValidCommand: boolean; + environment: string; + + useDevServer: boolean; + devServerServerType: string | null; + // see config-generator - getWebpackConfig() + devServerFinalIsHttps: boolean | null; + devServerHost: string | null; + devServerPort: string | number | null; + devServerPublic: string | null; + devServerKeepPublicPath: boolean; + outputJson: boolean; + profile: boolean; + + babelRcFileExists: boolean | null; + + helpRequested: boolean; + verbose: boolean; + constructor() { this.command = null; this.context = null; diff --git a/lib/config/parse-runtime.js b/lib/config/parse-runtime.ts similarity index 84% rename from lib/config/parse-runtime.js rename to lib/config/parse-runtime.ts index d3b77ad2..35650dfe 100644 --- a/lib/config/parse-runtime.js +++ b/lib/config/parse-runtime.ts @@ -9,17 +9,17 @@ import path from 'path'; +import type { Arguments } from 'yargs-parser'; + import packageUp from '../utils/package-up.ts'; +// .js (not .ts): RuntimeConfig is exposed in this module's emitted .d.ts, and +// rewriteRelativeImportExtensions does NOT rewrite .ts -> .js inside .d.ts files +// (only in emitted .js). tsc still resolves .js -> the .ts source here. import RuntimeConfig from './RuntimeConfig.js'; -/** - * @param {object} argv - * @param {string} cwd - * @returns {RuntimeConfig} - */ -export default function (argv, cwd) { +export default function (argv: Arguments, cwd: string): RuntimeConfig { const runtimeConfig = new RuntimeConfig(); - runtimeConfig.command = argv._[0]; + runtimeConfig.command = argv._[0] ?? null; switch (runtimeConfig.command) { case 'dev': @@ -59,7 +59,7 @@ export default function (argv, cwd) { if (typeof runtimeConfig.context === 'undefined') { const packagesPath = packageUp({ cwd }); - if (null === packagesPath) { + if (undefined === packagesPath) { throw new Error( 'Cannot determine webpack context. (Are you executing webpack from a directory outside of your project?). Try passing the --context option.' ); diff --git a/lib/config/path-util.js b/lib/config/path-util.ts similarity index 90% rename from lib/config/path-util.js rename to lib/config/path-util.ts index 464873f8..f08fc42e 100644 --- a/lib/config/path-util.js +++ b/lib/config/path-util.ts @@ -7,26 +7,20 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - -/** - * @import RuntimeConfig from './RuntimeConfig.js' - */ - import path from 'path'; import logger from '../logger.js'; +import type WebpackConfig from '../WebpackConfig.js'; +// .js (not .ts): RuntimeConfig is exposed in this module's emitted .d.ts, and +// rewriteRelativeImportExtensions does NOT rewrite .ts -> .js inside .d.ts files +// (only in emitted .js). tsc still resolves .js -> the .ts source here. +import type RuntimeConfig from './RuntimeConfig.js'; export default { /** * Determines the "contentBase" to use for the devServer. - * - * @param {WebpackConfig} webpackConfig - * @returns {string} */ - getContentBase(webpackConfig) { + getContentBase(webpackConfig: WebpackConfig): string { // strip trailing slash (for Unix or Windows) const outputPath = webpackConfig.outputPath.replace(/\/$/, '').replace(/\\$/, ''); // use the manifestKeyPrefix if available @@ -66,11 +60,8 @@ export default { /** * Returns the output path, but as a relative string (e.g. web/build) - * - * @param {WebpackConfig} webpackConfig - * @returns {string} */ - getRelativeOutputPath(webpackConfig) { + getRelativeOutputPath(webpackConfig: WebpackConfig): string { return webpackConfig.outputPath.replace(webpackConfig.getContext() + path.sep, ''); }, @@ -79,11 +70,8 @@ export default { * * Most importantly, this runs some sanity checks to make sure that it's * ok to use the publicPath as the manifestKeyPrefix. - * - * @param {WebpackConfig} webpackConfig - * @returns {void} */ - validatePublicPathAndManifestKeyPrefix(webpackConfig) { + validatePublicPathAndManifestKeyPrefix(webpackConfig: WebpackConfig): void { if (webpackConfig.manifestKeyPrefix !== null) { // nothing to check - they have manually set the key prefix return; @@ -131,11 +119,7 @@ export default { } }, - /** - * @param {RuntimeConfig} runtimeConfig - * @returns {string} - */ - calculateDevServerUrl(runtimeConfig) { + calculateDevServerUrl(runtimeConfig: RuntimeConfig): string { if (runtimeConfig.devServerFinalIsHttps === null) { logger.warning( 'The final devServerFinalHttpsConfig was never calculated. This may cause some paths to incorrectly use or not use https and could be a bug.' diff --git a/lib/config/validator.js b/lib/config/validator.ts similarity index 87% rename from lib/config/validator.js rename to lib/config/validator.ts index 44295b5b..165d210f 100644 --- a/lib/config/validator.js +++ b/lib/config/validator.ts @@ -7,22 +7,18 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from '../WebpackConfig.js' - */ - +import type WebpackConfig from '../WebpackConfig.js'; import logger from './../logger.js'; -import pathUtil from './path-util.js'; +import pathUtil from './path-util.ts'; class Validator { - /** - * @param {WebpackConfig} webpackConfig - */ - constructor(webpackConfig) { + webpackConfig: WebpackConfig; + + constructor(webpackConfig: WebpackConfig) { this.webpackConfig = webpackConfig; } - validate() { + validate(): void { this._validateBasic(); this._validatePublicPathAndManifestKeyPrefix(); @@ -32,7 +28,7 @@ class Validator { this._validateCacheGroupNames(); } - _validateBasic() { + _validateBasic(): void { if (this.webpackConfig.outputPath === null) { throw new Error( 'Missing output path: Call setOutputPath() to control where the files will be written.' @@ -57,11 +53,11 @@ class Validator { } } - _validatePublicPathAndManifestKeyPrefix() { + _validatePublicPathAndManifestKeyPrefix(): void { pathUtil.validatePublicPathAndManifestKeyPrefix(this.webpackConfig); } - _validateDevServer() { + _validateDevServer(): void { if (!this.webpackConfig.useDevServer()) { return; } @@ -86,7 +82,7 @@ class Validator { } } - _validateCacheGroupNames() { + _validateCacheGroupNames(): void { for (const groupName of Object.keys(this.webpackConfig.cacheGroups)) { if (['defaultVendors', 'default'].includes(groupName)) { logger.warning( @@ -97,7 +93,7 @@ class Validator { } } -export default function (webpackConfig) { +export default function (webpackConfig: WebpackConfig): void { const validator = new Validator(webpackConfig); validator.validate(); diff --git a/lib/plugins/asset-output-display.ts b/lib/plugins/asset-output-display.ts index 41bc909e..d7bdc234 100644 --- a/lib/plugins/asset-output-display.ts +++ b/lib/plugins/asset-output-display.ts @@ -10,7 +10,7 @@ import type FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin'; import type { WebpackPluginInstance } from 'webpack'; -import pathUtil from '../config/path-util.js'; +import pathUtil from '../config/path-util.ts'; import AssetOutputDisplayPlugin from '../friendly-errors/asset-output-display-plugin.ts'; import type WebpackConfig from '../WebpackConfig.js'; import PluginPriorities from './plugin-priorities.ts'; diff --git a/package.json b/package.json index 469350a1..298cf40a 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "@tsconfig/node22": "^22.0.5", "@types/node": "^22.18.0", "@types/semver": "^7.7.1", + "@types/yargs-parser": "21.0.3", "@vue/babel-plugin-jsx": "^3.0.0", "@vue/compiler-sfc": "^3.2.14", "autoprefixer": "^10.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 55230ea7..117d81d0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -93,6 +93,9 @@ importers: '@types/semver': specifier: ^7.7.1 version: 7.7.1 + '@types/yargs-parser': + specifier: 21.0.3 + version: 21.0.3 '@vue/babel-plugin-jsx': specifier: ^3.0.0 version: 3.0.0(@babel/core@8.0.1) @@ -1701,6 +1704,9 @@ packages: '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + '@typescript-eslint/eslint-plugin@8.62.0': resolution: {integrity: sha512-o+mpz7EYiMzXoySXiKmzlabIvTVqUuK5yLrAedRPRDA0IpPFMUV1IXt6OqljIxX/kumN6EjUYp41Hqelh6p/Dw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -6477,6 +6483,8 @@ snapshots: dependencies: '@types/node': 22.20.0 + '@types/yargs-parser@21.0.3': {} + '@typescript-eslint/eslint-plugin@8.62.0(@typescript-eslint/parser@8.62.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 diff --git a/test/WebpackConfig.js b/test/WebpackConfig.js index f384f346..8c78e8d9 100644 --- a/test/WebpackConfig.js +++ b/test/WebpackConfig.js @@ -13,7 +13,7 @@ import path from 'path'; import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import webpack from 'webpack'; -import RuntimeConfig from '../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../lib/config/RuntimeConfig.ts'; import logger from '../lib/logger.js'; import WebpackConfig from '../lib/WebpackConfig.js'; diff --git a/test/config-generator.js b/test/config-generator.js index 2c8688b1..b9da1e2b 100644 --- a/test/config-generator.js +++ b/test/config-generator.js @@ -16,7 +16,7 @@ import webpack from 'webpack'; import { WebpackManifestPlugin } from 'webpack-manifest-plugin'; import configGenerator from '../lib/config-generator.js'; -import RuntimeConfig from '../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../lib/config/RuntimeConfig.ts'; import logger from '../lib/logger.js'; import WebpackConfig from '../lib/WebpackConfig.js'; diff --git a/test/config/parse-runtime.js b/test/config/parse-runtime.js index c917eac7..441a54a9 100644 --- a/test/config/parse-runtime.js +++ b/test/config/parse-runtime.js @@ -13,7 +13,7 @@ import fs from 'fs-extra'; import { describe, it, expect } from 'vitest'; import yargsParser from 'yargs-parser'; -import parseArgv from '../../lib/config/parse-runtime.js'; +import parseArgv from '../../lib/config/parse-runtime.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; import * as testSetup from '../helpers/setup.js'; diff --git a/test/config/path-util.js b/test/config/path-util.js index 449409a9..5a773992 100644 --- a/test/config/path-util.js +++ b/test/config/path-util.js @@ -12,8 +12,8 @@ import process from 'process'; import { describe, it, expect } from 'vitest'; import configGenerator from '../../lib/config-generator.js'; -import pathUtil from '../../lib/config/path-util.js'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import pathUtil from '../../lib/config/path-util.ts'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; function createConfig() { diff --git a/test/config/validator.js b/test/config/validator.js index 7ec40dca..39d3ff21 100644 --- a/test/config/validator.js +++ b/test/config/validator.js @@ -9,8 +9,8 @@ import { describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; -import validator from '../../lib/config/validator.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; +import validator from '../../lib/config/validator.ts'; import logger from '../../lib/logger.js'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/friendly-errors/transformers/missing-loader.js b/test/friendly-errors/transformers/missing-loader.js index 69572c15..230d3f74 100644 --- a/test/friendly-errors/transformers/missing-loader.js +++ b/test/friendly-errors/transformers/missing-loader.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../../lib/config/RuntimeConfig.ts'; import transformFactory from '../../../lib/friendly-errors/transformers/missing-loader.ts'; import WebpackConfig from '../../../lib/WebpackConfig.js'; diff --git a/test/helpers/setup.js b/test/helpers/setup.js index dbeb0e19..2f37795d 100644 --- a/test/helpers/setup.js +++ b/test/helpers/setup.js @@ -14,8 +14,8 @@ import httpServer from 'http-server'; import webpack from 'webpack'; import configGenerator from '../../lib/config-generator.js'; -import parseRuntime from '../../lib/config/parse-runtime.js'; -import validator from '../../lib/config/validator.js'; +import parseRuntime from '../../lib/config/parse-runtime.ts'; +import validator from '../../lib/config/validator.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; import { Assert } from './assert.js'; diff --git a/test/loaders/babel.js b/test/loaders/babel.js index 0ceef884..fa180589 100644 --- a/test/loaders/babel.js +++ b/test/loaders/babel.js @@ -11,7 +11,7 @@ import { fileURLToPath } from 'url'; import { describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import babelLoader from '../../lib/loaders/babel.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/loaders/css-extract.js b/test/loaders/css-extract.js index 0600a416..6c60c010 100644 --- a/test/loaders/css-extract.js +++ b/test/loaders/css-extract.js @@ -10,7 +10,7 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import { describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import cssExtractLoader from '../../lib/loaders/css-extract.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/loaders/css.js b/test/loaders/css.js index 238885cc..734ba403 100644 --- a/test/loaders/css.js +++ b/test/loaders/css.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import cssLoader from '../../lib/loaders/css.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/loaders/handlebars.js b/test/loaders/handlebars.js index 4c67ea8c..faa04d73 100644 --- a/test/loaders/handlebars.js +++ b/test/loaders/handlebars.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import handlebarsLoader from '../../lib/loaders/handlebars.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/loaders/less.js b/test/loaders/less.js index c873216d..c5c06a99 100644 --- a/test/loaders/less.js +++ b/test/loaders/less.js @@ -9,7 +9,7 @@ import { vi, describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import cssLoader from '../../lib/loaders/css.ts'; import lessLoader from '../../lib/loaders/less.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/loaders/sass.js b/test/loaders/sass.js index c141e8c7..124cb786 100644 --- a/test/loaders/sass.js +++ b/test/loaders/sass.js @@ -9,7 +9,7 @@ import { vi, describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import cssLoader from '../../lib/loaders/css.ts'; import sassLoader from '../../lib/loaders/sass.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/loaders/stylus.js b/test/loaders/stylus.js index 8eac4434..925d836c 100644 --- a/test/loaders/stylus.js +++ b/test/loaders/stylus.js @@ -9,7 +9,7 @@ import { vi, describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import cssLoader from '../../lib/loaders/css.ts'; import stylusLoader from '../../lib/loaders/stylus.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/loaders/typescript.js b/test/loaders/typescript.js index 3a52512a..99d4a324 100644 --- a/test/loaders/typescript.js +++ b/test/loaders/typescript.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import tsLoader from '../../lib/loaders/typescript.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/loaders/vue.js b/test/loaders/vue.js index eb2d8629..3c9828c1 100644 --- a/test/loaders/vue.js +++ b/test/loaders/vue.js @@ -9,7 +9,7 @@ import { describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import vueLoader from '../../lib/loaders/vue.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/plugins/css-minimizer.js b/test/plugins/css-minimizer.js index 92865737..a2d63aa8 100644 --- a/test/plugins/css-minimizer.js +++ b/test/plugins/css-minimizer.js @@ -10,7 +10,7 @@ import MinimizerPlugin from 'minimizer-webpack-plugin'; import { describe, it, expect, vi, beforeEach } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; const { checkCssMinifierPackages } = vi.hoisted(() => ({ diff --git a/test/plugins/define.js b/test/plugins/define.js index 7de9f7fc..c2c14bff 100644 --- a/test/plugins/define.js +++ b/test/plugins/define.js @@ -10,7 +10,7 @@ import { describe, it, expect } from 'vitest'; import webpack from 'webpack'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import definePluginUtil from '../../lib/plugins/define.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/plugins/forked-ts-types.js b/test/plugins/forked-ts-types.js index 529ff1a0..c10a12fb 100644 --- a/test/plugins/forked-ts-types.js +++ b/test/plugins/forked-ts-types.js @@ -10,7 +10,7 @@ import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; import { describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import tsLoader from '../../lib/loaders/typescript.ts'; import tsTypeChecker from '../../lib/plugins/forked-ts-types.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/plugins/friendly-errors.js b/test/plugins/friendly-errors.js index 3236c667..c4bf9941 100644 --- a/test/plugins/friendly-errors.js +++ b/test/plugins/friendly-errors.js @@ -10,7 +10,7 @@ import FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin'; import { describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import friendlyErrorsPluginUtil from '../../lib/plugins/friendly-errors.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/plugins/js-minimizer.js b/test/plugins/js-minimizer.js index fe47b889..e8bcd3be 100644 --- a/test/plugins/js-minimizer.js +++ b/test/plugins/js-minimizer.js @@ -10,7 +10,7 @@ import MinimizerPlugin from 'minimizer-webpack-plugin'; import { describe, it, expect, vi, beforeEach } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; const { checkJsMinifierPackages } = vi.hoisted(() => ({ diff --git a/test/plugins/manifest.js b/test/plugins/manifest.js index ddc34596..30115827 100644 --- a/test/plugins/manifest.js +++ b/test/plugins/manifest.js @@ -10,7 +10,7 @@ import { describe, it, expect } from 'vitest'; import { WebpackManifestPlugin } from 'webpack-manifest-plugin'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import manifestPluginUtil from '../../lib/plugins/manifest.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/plugins/mini-css-extract.js b/test/plugins/mini-css-extract.js index 7c16560b..6529630f 100644 --- a/test/plugins/mini-css-extract.js +++ b/test/plugins/mini-css-extract.js @@ -10,7 +10,7 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import { describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import miniCssExtractPluginUtil from '../../lib/plugins/mini-css-extract.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/plugins/notifier.js b/test/plugins/notifier.js index 73df61f6..a50c423e 100644 --- a/test/plugins/notifier.js +++ b/test/plugins/notifier.js @@ -10,7 +10,7 @@ import { describe, it, expect } from 'vitest'; import WebpackNotifier from 'webpack-notifier'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import notifierPluginUtil from '../../lib/plugins/notifier.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; diff --git a/test/utils/get-vue-version.js b/test/utils/get-vue-version.js index f322bab7..a305de04 100644 --- a/test/utils/get-vue-version.js +++ b/test/utils/get-vue-version.js @@ -9,7 +9,7 @@ import { vi, describe, it, expect } from 'vitest'; -import RuntimeConfig from '../../lib/config/RuntimeConfig.js'; +import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import packageHelper from '../../lib/package-helper.js'; import getVueVersion from '../../lib/utils/get-vue-version.ts'; import WebpackConfig from '../../lib/WebpackConfig.js'; From a575001bfb3a1ee3de7a9a114a6abd7585f934d9 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Tue, 30 Jun 2026 09:53:53 +0200 Subject: [PATCH 08/12] [TypeScript] Migrate `lib/webpack/*` (#1509) --- eslint.config.js | 6 ++ lib/config-generator.js | 9 ++- lib/plugins/delete-unused-entries.ts | 2 +- lib/plugins/entry-files-manifest.ts | 2 +- ...y-files-loader.js => copy-files-loader.ts} | 44 ++++++++--- ....js => delete-unused-entries-js-plugin.ts} | 47 +++++++----- ...oints-plugin.js => entry-points-plugin.ts} | 75 +++++++++++-------- 7 files changed, 118 insertions(+), 67 deletions(-) rename lib/webpack/{copy-files-loader.js => copy-files-loader.ts} (78%) rename lib/webpack/{delete-unused-entries-js-plugin.js => delete-unused-entries-js-plugin.ts} (65%) rename lib/webpack/{entry-points-plugin.js => entry-points-plugin.ts} (66%) diff --git a/eslint.config.js b/eslint.config.js index 854037f5..8620fdf3 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -94,8 +94,14 @@ file that was distributed with this source code.`, // produces false positives on type-only syntax. 'no-unused-vars': 'off', // In TypeScript files, types live in the signature, not in JSDoc. + // JSDoc is kept only for prose descriptions, so neither the tags nor + // their types are required, and parameter names (e.g. destructured + // option bags) are validated by tsc rather than the JSDoc plugin. 'jsdoc/require-param': 'off', + 'jsdoc/require-param-type': 'off', 'jsdoc/require-returns': 'off', + 'jsdoc/require-returns-type': 'off', + 'jsdoc/check-param-names': 'off', // tsc owns module resolution for `.ts` files (strict, build fails on // a missing import). eslint-plugin-n is not TS-aware: from a `.ts` // file it rewrites `.js` -> `.ts` and cannot resolve imports of diff --git a/lib/config-generator.js b/lib/config-generator.js index 32c94cbd..f2f5794e 100644 --- a/lib/config-generator.js +++ b/lib/config-generator.js @@ -253,9 +253,16 @@ class ConfigGenerator { : '[path][name].[ext]'; } - const copyFilesLoaderPath = fileURLToPath( + // The loader path is handed to webpack, which require()s it + // directly. The published package ships the compiled `.js` + // (in dist/); when running from the `lib/` sources only the + // `.ts` exists, so fall back to it (Node strips the types). + let copyFilesLoaderPath = fileURLToPath( import.meta.resolve('./webpack/copy-files-loader.js') ); + if (!fs.existsSync(copyFilesLoaderPath)) { + copyFilesLoaderPath = copyFilesLoaderPath.replace(/\.js$/, '.ts'); + } const copyFilesLoaderConfig = `${copyFilesLoaderPath}?${JSON.stringify({ context: entry.context ? path.resolve(this.webpackConfig.getContext(), entry.context) diff --git a/lib/plugins/delete-unused-entries.ts b/lib/plugins/delete-unused-entries.ts index 37bbdbe0..f724310f 100644 --- a/lib/plugins/delete-unused-entries.ts +++ b/lib/plugins/delete-unused-entries.ts @@ -10,7 +10,7 @@ import type { WebpackPluginInstance } from 'webpack'; import copyEntryTmpName from '../utils/copyEntryTmpName.ts'; -import DeleteUnusedEntriesJSPlugin from '../webpack/delete-unused-entries-js-plugin.js'; +import DeleteUnusedEntriesJSPlugin from '../webpack/delete-unused-entries-js-plugin.ts'; import type WebpackConfig from '../WebpackConfig.js'; import PluginPriorities from './plugin-priorities.ts'; diff --git a/lib/plugins/entry-files-manifest.ts b/lib/plugins/entry-files-manifest.ts index 8abfc5ef..8de96756 100644 --- a/lib/plugins/entry-files-manifest.ts +++ b/lib/plugins/entry-files-manifest.ts @@ -9,7 +9,7 @@ import type { WebpackPluginInstance } from 'webpack'; -import { EntryPointsPlugin } from '../webpack/entry-points-plugin.js'; +import { EntryPointsPlugin } from '../webpack/entry-points-plugin.ts'; import type WebpackConfig from '../WebpackConfig.js'; import PluginPriorities from './plugin-priorities.ts'; diff --git a/lib/webpack/copy-files-loader.js b/lib/webpack/copy-files-loader.ts similarity index 78% rename from lib/webpack/copy-files-loader.js rename to lib/webpack/copy-files-loader.ts index d29c8d07..8ab0b233 100644 --- a/lib/webpack/copy-files-loader.js +++ b/lib/webpack/copy-files-loader.ts @@ -9,6 +9,16 @@ import path from 'path'; +import type { AssetInfo, LoaderContext } from 'webpack'; + +interface CopyFilesLoaderOptions { + context: string; + filename: string; + regExp?: RegExp; + patternSource: string; + patternFlags: string; +} + export const raw = true; // Needed to avoid corrupted binary files /** @@ -20,14 +30,21 @@ export const raw = true; // Needed to avoid corrupted binary files * - [path]: relative directory path from context, with trailing slash * - [hash:N] or [contenthash:N]: content hash, optionally truncated to N characters * - * @param {string} template - The filename template (e.g., '[path][name].[hash:8].[ext]') - * @param {object} data - * @param {string} data.resourcePath - Absolute path to the resource - * @param {string} data.context - Context directory for computing relative paths - * @param {string} data.contentHash - Pre-computed content hash - * @returns {string} The interpolated filename + * @param template The filename template (e.g., '[path][name].[hash:8].[ext]') + * @param data + * @param data.resourcePath Absolute path to the resource + * @param data.context Context directory for computing relative paths + * @param data.contentHash Pre-computed content hash + * @returns The interpolated filename */ -function interpolateName(template, { resourcePath, context, contentHash }) { +function interpolateName( + template: string, + { + resourcePath, + context, + contentHash, + }: { resourcePath: string; context: string; contentHash: string } +): string { const parsed = path.parse(resourcePath); const ext = parsed.ext.slice(1); // Remove leading dot for file-loader compatibility const name = parsed.name; @@ -57,10 +74,13 @@ function interpolateName(template, { resourcePath, context, contentHash }) { * native this.emitFile() API. It supports filtering files by pattern * and customizing output paths using template placeholders. * - * @param {Buffer} source - The raw file content - * @returns {string} An ESM module that exports the public URL of the copied file + * @param source The raw file content + * @returns An ESM module that exports the public URL of the copied file */ -export default function loader(source) { +export default function loader( + this: LoaderContext, + source: Buffer +): string { const options = this.getOptions(); // Retrieve the real path of the resource, relative @@ -99,7 +119,7 @@ export default function loader(source) { }); // Build asset info for webpack - const assetInfo = { + const assetInfo: AssetInfo = { sourceFilename: path.relative(this.rootContext, resourcePath).replace(/\\/g, '/'), }; @@ -109,7 +129,7 @@ export default function loader(source) { } // Emit the file to the output directory - this.emitFile(outputPath, source, null, assetInfo); + this.emitFile(outputPath, source, undefined, assetInfo); // Return a module that exports the public URL return `export default __webpack_public_path__ + ${JSON.stringify(outputPath)};`; diff --git a/lib/webpack/delete-unused-entries-js-plugin.js b/lib/webpack/delete-unused-entries-js-plugin.ts similarity index 65% rename from lib/webpack/delete-unused-entries-js-plugin.js rename to lib/webpack/delete-unused-entries-js-plugin.ts index 0cdb17ca..46bfce86 100644 --- a/lib/webpack/delete-unused-entries-js-plugin.js +++ b/lib/webpack/delete-unused-entries-js-plugin.ts @@ -7,16 +7,25 @@ * file that was distributed with this source code. */ -function DeleteUnusedEntriesJSPlugin(entriesToDelete = []) { - this.entriesToDelete = entriesToDelete; -} -DeleteUnusedEntriesJSPlugin.prototype.apply = function (compiler) { - const deleteEntries = (compilation) => { - // loop over output chunks - compilation.chunks.forEach((chunk) => { - // see of this chunk is one that needs its .js deleted - if (this.entriesToDelete.includes(chunk.name)) { - const removedFiles = []; +import type { Compilation, Compiler } from 'webpack'; + +export default class DeleteUnusedEntriesJSPlugin { + entriesToDelete: string[]; + + constructor(entriesToDelete: string[] = []) { + this.entriesToDelete = entriesToDelete; + } + + apply(compiler: Compiler): void { + const deleteEntries = (compilation: Compilation): void => { + // loop over output chunks + compilation.chunks.forEach((chunk) => { + // see of this chunk is one that needs its .js deleted + if (typeof chunk.name !== 'string' || !this.entriesToDelete.includes(chunk.name)) { + return; + } + + const removedFiles: string[] = []; // look for main files to delete first for (const filename of Array.from(chunk.files)) { @@ -48,15 +57,13 @@ DeleteUnusedEntriesJSPlugin.prototype.apply = function (compiler) { `Problem deleting JS entry for ${chunk.name}: ${removedFiles.length} files were deleted (${removedFiles.join(', ')})` ); } - } - }); - }; + }); + }; - compiler.hooks.compilation.tap('DeleteUnusedEntriesJSPlugin', function (compilation) { - compilation.hooks.additionalAssets.tap('DeleteUnusedEntriesJsPlugin', function () { - deleteEntries(compilation); + compiler.hooks.compilation.tap('DeleteUnusedEntriesJSPlugin', function (compilation) { + compilation.hooks.additionalAssets.tap('DeleteUnusedEntriesJsPlugin', function () { + deleteEntries(compilation); + }); }); - }); -}; - -export default DeleteUnusedEntriesJSPlugin; + } +} diff --git a/lib/webpack/entry-points-plugin.js b/lib/webpack/entry-points-plugin.ts similarity index 66% rename from lib/webpack/entry-points-plugin.js rename to lib/webpack/entry-points-plugin.ts index 163443d2..014c844c 100644 --- a/lib/webpack/entry-points-plugin.js +++ b/lib/webpack/entry-points-plugin.ts @@ -11,39 +11,52 @@ import crypto from 'crypto'; import fs from 'fs'; import path from 'path'; +import type webpack from 'webpack'; + import copyEntryTmpName from '../utils/copyEntryTmpName.ts'; +interface EntryPointsManifest { + entrypoints: Record>; + integrity?: Record; +} + /** * Return the file extension from a filename, without the leading dot and without the query string (if any). - * - * @param {string} filename - * @returns {string} */ -function getFileExtension(filename) { - return path.extname(filename).slice(1).split('?')[0]; +function getFileExtension(filename: string): string { + return path.extname(filename).slice(1).split('?')[0]!; } export class EntryPointsPlugin { + publicPath: string; + outputPath: string; + integrityAlgorithms: string[]; + /** - * @param {object} options - * @param {string} options.publicPath The public path of the assets, from where they are served - * @param {string} options.outputPath The output path of the assets, from where they are saved - * @param {Array} options.integrityAlgorithms The algorithms to use for the integrity hash + * @param options + * @param options.publicPath The public path of the assets, from where they are served + * @param options.outputPath The output path of the assets, from where they are saved + * @param options.integrityAlgorithms The algorithms to use for the integrity hash */ - constructor({ publicPath, outputPath, integrityAlgorithms }) { + constructor({ + publicPath, + outputPath, + integrityAlgorithms, + }: { + publicPath: string; + outputPath: string; + integrityAlgorithms: string[]; + }) { this.publicPath = publicPath; this.outputPath = outputPath; this.integrityAlgorithms = integrityAlgorithms; } - /** - * @param {import('webpack').Compiler} compiler - */ - apply(compiler) { + apply(compiler: webpack.Compiler): void { compiler.hooks.afterEmit.tapAsync( { name: 'EntryPointsPlugin' }, (compilation, callback) => { - const manifest = { + const manifest: EntryPointsManifest = { entrypoints: {}, }; @@ -59,15 +72,16 @@ export class EntryPointsPlugin { errorDetails: false, }); - for (const [entryName, entry] of Object.entries(stats.entrypoints)) { + for (const [entryName, entry] of Object.entries(stats.entrypoints ?? {})) { // We don't want to include the temporary entry in the manifest if (entryName === copyEntryTmpName) { continue; } - manifest.entrypoints[entryName] = {}; + const entrypoint: Record = {}; + manifest.entrypoints[entryName] = entrypoint; - for (const asset of entry.assets) { + for (const asset of entry.assets ?? []) { // We don't want to include hot-update files in the manifest if (asset.name.includes('.hot-update.')) { continue; @@ -79,29 +93,26 @@ export class EntryPointsPlugin { ? `${this.publicPath}${asset.name}` : `${this.publicPath}/${asset.name}`; - if (!(fileExtension in manifest.entrypoints[entryName])) { - manifest.entrypoints[entryName][fileExtension] = []; - } - - manifest.entrypoints[entryName][fileExtension].push(assetPath); + (entrypoint[fileExtension] ??= []).push(assetPath); } } if (this.integrityAlgorithms.length > 0) { - manifest.integrity = {}; + const integrity: Record = {}; + manifest.integrity = integrity; - for (const entryName in manifest.entrypoints) { - for (const fileType in manifest.entrypoints[entryName]) { - for (const asset of manifest.entrypoints[entryName][fileType]) { - if (asset in manifest.integrity) { + for (const fileTypes of Object.values(manifest.entrypoints)) { + for (const assets of Object.values(fileTypes)) { + for (const asset of assets) { + if (asset in integrity) { continue; } // Drop query string if any const assetNormalized = asset.includes('?') - ? asset.split('?')[0] + ? asset.split('?')[0]! : asset; - if (assetNormalized in manifest.integrity) { + if (assetNormalized in integrity) { continue; } @@ -111,7 +122,7 @@ export class EntryPointsPlugin { ); if (fs.existsSync(filePath)) { - const fileHashes = []; + const fileHashes: string[] = []; for (const algorithm of this.integrityAlgorithms) { const hash = crypto.createHash(algorithm); @@ -121,7 +132,7 @@ export class EntryPointsPlugin { fileHashes.push(`${algorithm}-${hash.digest('base64')}`); } - manifest.integrity[asset] = fileHashes.join(' '); + integrity[asset] = fileHashes.join(' '); } } } From 326a5050a42029ce5326e17aa0897fa65ccf2751 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Wed, 1 Jul 2026 08:11:14 +0200 Subject: [PATCH 09/12] [TypeScript] Migrate `lib/*` (#1510) --- bin/encore.js | 6 +- index.js | 8 +- lib/{EncoreProxy.js => EncoreProxy.ts} | 27 +- lib/{WebpackConfig.js => WebpackConfig.ts} | 566 +++++++++--------- ...onfig-generator.js => config-generator.ts} | 136 ++--- lib/config/path-util.ts | 14 +- lib/config/validator.ts | 4 +- lib/{context.js => context.ts} | 4 +- lib/{features.js => features.ts} | 35 +- .../formatters/missing-loader.ts | 2 +- lib/loaders/babel.ts | 2 +- lib/loaders/css.ts | 2 +- lib/loaders/handlebars.ts | 2 +- lib/loaders/less.ts | 2 +- lib/loaders/sass.ts | 2 +- lib/loaders/stylus.ts | 2 +- lib/loaders/typescript.ts | 2 +- lib/loaders/vue.ts | 2 +- lib/{logger.js => logger.ts} | 37 +- lib/{package-helper.js => package-helper.ts} | 79 ++- lib/plugins/entry-files-manifest.ts | 2 +- lib/plugins/notifier.ts | 2 +- lib/utils/get-vue-version.ts | 4 +- lib/utils/minifier-check.ts | 2 +- package.json | 1 + pnpm-lock.yaml | 8 + test/WebpackConfig.js | 4 +- test/config-generator.js | 6 +- test/config/parse-runtime.js | 2 +- test/config/path-util.js | 4 +- test/config/validator.js | 4 +- .../transformers/missing-loader.js | 2 +- test/functional.js | 2 +- test/helpers/logger-assert.js | 2 +- test/helpers/setup.js | 4 +- test/loaders/babel.js | 2 +- test/loaders/css-extract.js | 2 +- test/loaders/css.js | 2 +- test/loaders/handlebars.js | 2 +- test/loaders/less.js | 2 +- test/loaders/sass.js | 2 +- test/loaders/stylus.js | 2 +- test/loaders/typescript.js | 2 +- test/loaders/vue.js | 2 +- test/logger.js | 4 +- test/package-helper.js | 2 +- test/plugins/css-minimizer.js | 2 +- test/plugins/define.js | 2 +- test/plugins/forked-ts-types.js | 2 +- test/plugins/friendly-errors.js | 2 +- test/plugins/js-minimizer.js | 2 +- test/plugins/manifest.js | 2 +- test/plugins/mini-css-extract.js | 2 +- test/plugins/notifier.js | 2 +- test/utils/get-vue-version.js | 4 +- test/utils/minifier-check.js | 2 +- test/vitest-setup.js | 2 +- 57 files changed, 554 insertions(+), 477 deletions(-) rename lib/{EncoreProxy.js => EncoreProxy.ts} (84%) rename lib/{WebpackConfig.js => WebpackConfig.ts} (72%) rename lib/{config-generator.js => config-generator.ts} (87%) rename lib/{context.js => context.ts} (75%) rename lib/{features.js => features.ts} (89%) rename lib/{logger.js => logger.ts} (66%) rename lib/{package-helper.js => package-helper.ts} (69%) diff --git a/bin/encore.js b/bin/encore.js index 593e3dbd..7cab1b30 100755 --- a/bin/encore.js +++ b/bin/encore.js @@ -12,9 +12,9 @@ import pc from 'picocolors'; import yargsParser from 'yargs-parser'; import parseRuntime from '../lib/config/parse-runtime.ts'; -import context from '../lib/context.js'; -import featuresHelper from '../lib/features.js'; -import logger from '../lib/logger.js'; +import context from '../lib/context.ts'; +import featuresHelper from '../lib/features.ts'; +import logger from '../lib/logger.ts'; const runtimeConfig = parseRuntime(yargsParser(process.argv.slice(2)), process.cwd()); context.runtimeConfig = runtimeConfig; diff --git a/index.js b/index.js index 4188afc6..bbd3e6d6 100644 --- a/index.js +++ b/index.js @@ -25,12 +25,12 @@ import yargsParser from 'yargs-parser'; -import configGenerator from './lib/config-generator.js'; +import configGenerator from './lib/config-generator.ts'; import parseRuntime from './lib/config/parse-runtime.ts'; import validator from './lib/config/validator.ts'; -import context from './lib/context.js'; -import EncoreProxy from './lib/EncoreProxy.js'; -import WebpackConfig from './lib/WebpackConfig.js'; +import context from './lib/context.ts'; +import EncoreProxy from './lib/EncoreProxy.ts'; +import WebpackConfig from './lib/WebpackConfig.ts'; let runtimeConfig = context.runtimeConfig; let webpackConfig = runtimeConfig ? new WebpackConfig(runtimeConfig) : null; diff --git a/lib/EncoreProxy.js b/lib/EncoreProxy.ts similarity index 84% rename from lib/EncoreProxy.js rename to lib/EncoreProxy.ts index 2de1f339..cd034bf3 100644 --- a/lib/EncoreProxy.js +++ b/lib/EncoreProxy.ts @@ -14,22 +14,24 @@ import prettyError from './utils/pretty-error.ts'; // Public methods that were removed. We show an explicit migration message instead of relying on // the generic "did you mean" suggestion below, whose closest Levenshtein match would be misleading. -const removedMethods = { +const removedMethods: Record = { configureTerserPlugin: 'Encore.configureTerserPlugin() was removed. Use Encore.configureJsMinimizerPlugin() instead (it takes the same callback).', }; export default { - createProxy: (Encore) => { + createProxy: (Encore: T): T => { const EncoreProxy = new Proxy(Encore, { get: (target, prop) => { if (typeof prop !== 'string') { // Only care about strings there since prop // could also be a number or a symbol - return target[prop]; + return Reflect.get(target, prop); } - if (typeof target[prop] === 'function') { + const targetValue = Reflect.get(target, prop); + + if (typeof targetValue === 'function') { // These methods of the public API can be called even if the // webpackConfig object hasn't been initialized yet. const safeMethods = [ @@ -46,9 +48,12 @@ export default { // Either a safe method has been called or the webpackConfig // object is already available. In this case act as a passthrough. - return (...parameters) => { + return (...parameters: unknown[]) => { try { - const res = target[prop](...parameters); + const res = (targetValue as (...args: unknown[]) => unknown).apply( + target, + parameters + ); // If the method returns a Promise (e.g. getWebpackConfig()), // attach a .catch() so that async rejections are also @@ -56,10 +61,10 @@ export default { if ( res !== null && typeof res === 'object' && - typeof res.then === 'function' && + typeof (res as { then?: unknown }).then === 'function' && res !== target ) { - return res.catch((error) => { + return (res as Promise).catch((error: unknown) => { prettyError(error); process.exit(1); // eslint-disable-line }); @@ -73,7 +78,7 @@ export default { }; } - if (typeof target[prop] === 'undefined') { + if (typeof targetValue === 'undefined') { if (Object.hasOwn(removedMethods, prop)) { prettyError(new Error(removedMethods[prop]), { skipTrace: (traceLine, lineNumber) => lineNumber !== 1, @@ -83,7 +88,7 @@ export default { } // Find the property with the closest Levenshtein distance - let similarProperty; + let similarProperty: string | undefined; let minDistance = Number.MAX_VALUE; const encorePrototype = Object.getPrototypeOf(Encore); @@ -116,7 +121,7 @@ export default { process.exit(1); // eslint-disable-line } - return target[prop]; + return targetValue; }, }); diff --git a/lib/WebpackConfig.js b/lib/WebpackConfig.ts similarity index 72% rename from lib/WebpackConfig.js rename to lib/WebpackConfig.ts index 616682bd..a60c4b4f 100644 --- a/lib/WebpackConfig.js +++ b/lib/WebpackConfig.ts @@ -7,49 +7,59 @@ * file that was distributed with this source code. */ -/** - * @import RuntimeConfig from './config/RuntimeConfig.js' - */ - -/** - * @import webpack from 'webpack' - */ - -/** - * @import { OptionsCallback } from './utils/apply-options-callback.js' - */ - -/** - * @import { CopyFilesOptions } from '../index.js' - */ - -/** - * @typedef {import('minimizer-webpack-plugin').BasePluginOptions & import('minimizer-webpack-plugin').DefinedDefaultMinimizerAndOptions} MinimizerPluginOptions - */ - -/** - * Callback used to configure the minimizer-webpack-plugin. It receives the options object - * (also bound as `this`) and the `MinimizerPlugin` class, so you can select a minifier - * (e.g. `MinimizerPlugin.lightningCssMinify`) without importing `minimizer-webpack-plugin` - * yourself (which is a transitive dependency of Encore and may not be resolvable, e.g. under pnpm). - * - * @typedef {(this: MinimizerPluginOptions, options: MinimizerPluginOptions, MinimizerPlugin: typeof import('minimizer-webpack-plugin').default) => (MinimizerPluginOptions | void)} MinimizerOptionsCallback - */ - import crypto from 'crypto'; import fs from 'fs'; import path from 'path'; +import type webpack from 'webpack'; + +import type { CopyFilesOptions } from '../index.js'; import pathUtil from './config/path-util.ts'; -import featuresHelper from './features.js'; -import logger from './logger.js'; +import type RuntimeConfig from './config/RuntimeConfig.js'; +import featuresHelper from './features.ts'; +import logger from './logger.ts'; +import type { OptionsCallback } from './utils/apply-options-callback.js'; import regexpEscaper from './utils/regexp-escaper.ts'; -/** - * @param {RuntimeConfig|null} runtimeConfig - * @returns {void} - */ -function validateRuntimeConfig(runtimeConfig) { +export type MinimizerPluginOptions = import('minimizer-webpack-plugin').BasePluginOptions & + import('minimizer-webpack-plugin').DefinedDefaultMinimizerAndOptions< + import('minimizer-webpack-plugin').CustomOptions + >; + +// Callback used to configure the minimizer-webpack-plugin. It receives the options object +// (also bound as `this`) and the `MinimizerPlugin` class, so you can select a minifier +// (e.g. `MinimizerPlugin.lightningCssMinify`) without importing `minimizer-webpack-plugin` +// yourself (which is a transitive dependency of Encore and may not be resolvable, e.g. under pnpm). +export type MinimizerOptionsCallback = ( + this: MinimizerPluginOptions, + options: MinimizerPluginOptions, + MinimizerPlugin: typeof import('minimizer-webpack-plugin') +) => MinimizerPluginOptions | void; + +interface AssetRuleOptions { + filename: string; + maxSize: number | null; + type: string; + enabled: boolean; +} + +interface CacheGroupOptions { + test?: RegExp; + node_modules?: string[]; + [key: string]: unknown; +} + +interface ResolvedCopyFilesConfig { + from: string; + pattern: RegExp | string; + to: string | null; + includeSubdirectories: boolean; + context: string | null; +} + +function validateRuntimeConfig( + runtimeConfig: RuntimeConfig | null +): asserts runtimeConfig is RuntimeConfig { // if you're using the encore executable, these things should never happen if (null === runtimeConfig) { throw new Error('RuntimeConfig must be initialized'); @@ -61,7 +71,99 @@ function validateRuntimeConfig(runtimeConfig) { } class WebpackConfig { - constructor(runtimeConfig) { + runtimeConfig: RuntimeConfig; + entries: Map; + styleEntries: Map; + plugins: Array<{ plugin: webpack.WebpackPluginInstance; priority: number }>; + loaders: webpack.RuleSetRule[]; + outputPath: string | null; + publicPath: string | null; + manifestKeyPrefix: string | null; + cacheGroups: Record; + providedVariables: Record; + configuredFilenames: { js?: string; css?: string; assets?: string }; + aliases: Record; + externals: webpack.ExternalItem[]; + integrityAlgorithms: string[]; + shouldUseSingleRuntimeChunk: boolean | null; + shouldSplitEntryChunks: boolean; + useVersioning: boolean; + useSourceMaps: boolean; + cleanupOutput: boolean; + usePersistentCache: boolean; + extractCss: boolean; + usePostCssLoader: boolean; + useLessLoader: boolean; + useStylusLoader: boolean; + useSassLoader: boolean; + useReact: boolean; + usePreact: boolean; + useVueLoader: boolean; + useTypeScriptLoader: boolean; + useForkedTypeScriptTypeChecking: boolean; + useBabelTypeScriptPreset: boolean; + useWebpackNotifier: boolean; + useHandlebarsLoader: boolean; + useSvelte: boolean; + imageRuleOptions: AssetRuleOptions; + fontRuleOptions: AssetRuleOptions; + copyFilesConfigs: ResolvedCopyFilesConfig[]; + sassOptions: { resolveUrlLoader: boolean; resolveUrlLoaderOptions: object }; + preactOptions: { preactCompat: boolean }; + babelOptions: { + exclude: webpack.RuleSetCondition; + useBuiltIns: 'usage' | 'entry' | false; + corejs: number | string | { version: string; proposals: boolean } | null; + }; + babelTypeScriptPresetOptions: object; + vueOptions: { useJsx: boolean; version: number | null; runtimeCompilerBuild: boolean | null }; + persistentCacheBuildDependencies: Record; + imageRuleCallback: OptionsCallback; + fontRuleCallback: OptionsCallback; + postCssLoaderOptionsCallback: OptionsCallback; + sassLoaderOptionsCallback: OptionsCallback; + lessLoaderOptionsCallback: OptionsCallback; + stylusLoaderOptionsCallback: OptionsCallback; + babelConfigurationCallback: OptionsCallback; + babelPresetEnvOptionsCallback: OptionsCallback; + babelReactPresetOptionsCallback: OptionsCallback; + cssLoaderConfigurationCallback: OptionsCallback; + styleLoaderConfigurationCallback: OptionsCallback; + splitChunksConfigurationCallback: OptionsCallback; + devServerOptionsConfigurationCallback: OptionsCallback; + vueLoaderOptionsCallback: OptionsCallback; + tsConfigurationCallback: OptionsCallback; + handlebarsConfigurationCallback: OptionsCallback; + forkedTypeScriptTypesCheckOptionsCallback: OptionsCallback; + friendlyErrorsPluginOptionsCallback: OptionsCallback; + manifestPluginOptionsCallback: OptionsCallback; + notifierPluginOptionsCallback: OptionsCallback; + watchOptionsConfigurationCallback: OptionsCallback< + Exclude + >; + miniCssExtractLoaderConfigurationCallback: OptionsCallback< + import('mini-css-extract-plugin').LoaderOptions + >; + miniCssExtractPluginConfigurationCallback: OptionsCallback< + import('mini-css-extract-plugin').PluginOptions + >; + loaderConfigurationCallbacks: Record>; + cleanOptionsCallback: OptionsCallback< + Exclude[0], undefined> + >; + definePluginOptionsCallback: OptionsCallback< + ConstructorParameters[0] + >; + minimizerPluginJsOptionsCallback: OptionsCallback; + minimizerPluginCssOptionsCallback: OptionsCallback; + cssMinimizerExplicitlyConfigured: boolean; + persistentCacheCallback: OptionsCallback; + _babelRcFileExists?: boolean; + _babelConfigureOptions?: object; + _configureBabelCalled: boolean; + _configureBabelPresetEnvCalled: boolean; + + constructor(runtimeConfig: RuntimeConfig | null) { validateRuntimeConfig(runtimeConfig); if (runtimeConfig.verbose) { @@ -93,14 +195,12 @@ class WebpackConfig { this.cleanupOutput = false; this.usePersistentCache = false; this.extractCss = true; - /** @type {{filename: string, maxSize: number|null, type: string, enabled: boolean}} */ this.imageRuleOptions = { type: 'asset/resource', maxSize: null, filename: 'images/[name].[hash:8][ext]', enabled: true, }; - /** @type {{filename: string, maxSize: number|null, type: string, enabled: boolean}} */ this.fontRuleOptions = { type: 'asset/resource', maxSize: null, @@ -123,9 +223,6 @@ class WebpackConfig { // Features/Loaders options this.copyFilesConfigs = []; - /** - * @type {{resolveUrlLoader: boolean, resolveUrlLoaderOptions: object}} - */ this.sassOptions = { resolveUrlLoader: true, resolveUrlLoaderOptions: {}, @@ -133,7 +230,6 @@ class WebpackConfig { this.preactOptions = { preactCompat: false, }; - /** @type {{exclude: webpack.RuleSetCondition, useBuiltIns: 'usage'|'entry'|false, corejs: number|string|{ version: string, proposals: boolean }|null}} */ this.babelOptions = { exclude: /(node_modules|bower_components)/, useBuiltIns: false, @@ -145,51 +241,30 @@ class WebpackConfig { version: null, runtimeCompilerBuild: null, }; - /** @type {Record} */ this.persistentCacheBuildDependencies = {}; // Features/Loaders options callbacks - /** @type {OptionsCallback} */ this.imageRuleCallback = () => {}; - /** @type {OptionsCallback} */ this.fontRuleCallback = () => {}; - /** @type {OptionsCallback} */ this.postCssLoaderOptionsCallback = () => {}; - /** @type {OptionsCallback} */ this.sassLoaderOptionsCallback = () => {}; - /** @type {OptionsCallback} */ this.lessLoaderOptionsCallback = () => {}; - /** @type {OptionsCallback} */ this.stylusLoaderOptionsCallback = () => {}; - /** @type {OptionsCallback} */ this.babelConfigurationCallback = () => {}; this._configureBabelCalled = false; - /** @type {OptionsCallback} */ this.babelPresetEnvOptionsCallback = () => {}; this._configureBabelPresetEnvCalled = false; - /** @type {OptionsCallback} */ this.babelReactPresetOptionsCallback = () => {}; - /** @type {OptionsCallback} */ this.cssLoaderConfigurationCallback = () => {}; - /** @type {OptionsCallback} */ this.styleLoaderConfigurationCallback = () => {}; - /** @type {OptionsCallback} */ this.splitChunksConfigurationCallback = () => {}; - /** @type {OptionsCallback>} */ this.watchOptionsConfigurationCallback = () => {}; - /** @type {OptionsCallback} */ this.devServerOptionsConfigurationCallback = () => {}; - /** @type {OptionsCallback} */ this.vueLoaderOptionsCallback = () => {}; - /** @type {OptionsCallback} */ this.tsConfigurationCallback = () => {}; - /** @type {OptionsCallback} */ this.handlebarsConfigurationCallback = () => {}; - /** @type {OptionsCallback} */ this.miniCssExtractLoaderConfigurationCallback = () => {}; - /** @type {OptionsCallback} */ this.miniCssExtractPluginConfigurationCallback = () => {}; - /** @type {Record>} */ this.loaderConfigurationCallbacks = { javascript: () => {}, css: () => {}, @@ -205,30 +280,20 @@ class WebpackConfig { }; // Plugins callbacks - /** @type {OptionsCallback[0], undefined>>} */ this.cleanOptionsCallback = () => {}; - /** @type {OptionsCallback[0]>} */ this.definePluginOptionsCallback = () => {}; - /** @type {OptionsCallback} */ this.forkedTypeScriptTypesCheckOptionsCallback = () => {}; - /** @type {OptionsCallback} */ this.friendlyErrorsPluginOptionsCallback = () => {}; - /** @type {OptionsCallback} */ this.manifestPluginOptionsCallback = () => {}; - /** @type {OptionsCallback>} */ this.minimizerPluginJsOptionsCallback = () => {}; - /** @type {OptionsCallback>} */ this.minimizerPluginCssOptionsCallback = () => {}; - /** @type {boolean} */ this.cssMinimizerExplicitlyConfigured = false; - /** @type {OptionsCallback} */ this.notifierPluginOptionsCallback = () => {}; - /** @type {OptionsCallback} */ this.persistentCacheCallback = () => {}; } - getContext() { - return this.runtimeConfig.context; + getContext(): string { + return this.runtimeConfig.context!; } /** @@ -236,10 +301,8 @@ class WebpackConfig { * If runtimeConfig.babelRcFileExists was explicitly set (not null), * that value is used directly. Otherwise, uses * babel.loadPartialConfigAsync() and caches the result. - * - * @returns {Promise} */ - async doesBabelRcFileExist() { + async doesBabelRcFileExist(): Promise { if (this._babelRcFileExists === undefined) { if (this.runtimeConfig.babelRcFileExists !== null) { this._babelRcFileExists = this.runtimeConfig.babelRcFileExists; @@ -249,13 +312,13 @@ class WebpackConfig { filename: path.resolve(this.getContext(), 'webpack.config.js'), root: this.getContext(), }); - this._babelRcFileExists = partialConfig.hasFilesystemConfig(); + this._babelRcFileExists = partialConfig!.hasFilesystemConfig(); } } - return this._babelRcFileExists; + return this._babelRcFileExists!; } - setOutputPath(outputPath) { + setOutputPath(outputPath: string) { if (!path.isAbsolute(outputPath)) { outputPath = path.resolve(this.getContext(), outputPath); } @@ -288,7 +351,7 @@ class WebpackConfig { this.outputPath = outputPath; } - setPublicPath(publicPath) { + setPublicPath(publicPath: string) { if (publicPath.includes('://') === false && publicPath.indexOf('/') !== 0) { // technically, not starting with "/" is legal, but not // what you want in most cases. Let's warn the user that @@ -305,7 +368,7 @@ class WebpackConfig { this.publicPath = publicPath; } - setManifestKeyPrefix(manifestKeyPrefix) { + setManifestKeyPrefix(manifestKeyPrefix: string) { /* * Normally, we make sure that the manifest keys don't start * with an opening "/" ever... for consistency. If you need @@ -329,10 +392,11 @@ class WebpackConfig { this.manifestKeyPrefix = manifestKeyPrefix; } - /** - * @param {OptionsCallback[0]>} definePluginOptionsCallback - */ - configureDefinePlugin(definePluginOptionsCallback = () => {}) { + configureDefinePlugin( + definePluginOptionsCallback: OptionsCallback< + ConstructorParameters[0] + > = () => {} + ) { if (typeof definePluginOptionsCallback !== 'function') { throw new Error('Argument 1 to configureDefinePlugin() must be a callback function'); } @@ -340,10 +404,9 @@ class WebpackConfig { this.definePluginOptionsCallback = definePluginOptionsCallback; } - /** - * @param {OptionsCallback} friendlyErrorsPluginOptionsCallback - */ - configureFriendlyErrorsPlugin(friendlyErrorsPluginOptionsCallback = () => {}) { + configureFriendlyErrorsPlugin( + friendlyErrorsPluginOptionsCallback: OptionsCallback = () => {} + ) { if (typeof friendlyErrorsPluginOptionsCallback !== 'function') { throw new Error( 'Argument 1 to configureFriendlyErrorsPlugin() must be a callback function' @@ -353,10 +416,7 @@ class WebpackConfig { this.friendlyErrorsPluginOptionsCallback = friendlyErrorsPluginOptionsCallback; } - /** - * @param {OptionsCallback} manifestPluginOptionsCallback - */ - configureManifestPlugin(manifestPluginOptionsCallback = () => {}) { + configureManifestPlugin(manifestPluginOptionsCallback: OptionsCallback = () => {}) { if (typeof manifestPluginOptionsCallback !== 'function') { throw new Error('Argument 1 to configureManifestPlugin() must be a callback function'); } @@ -366,10 +426,8 @@ class WebpackConfig { /** * Configures the options passed to the minimizer-webpack-plugin for JS minimization. - * - * @param {MinimizerOptionsCallback} jsOptionsCallback */ - configureJsMinimizerPlugin(jsOptionsCallback = () => {}) { + configureJsMinimizerPlugin(jsOptionsCallback: MinimizerOptionsCallback = () => {}) { if (typeof jsOptionsCallback !== 'function') { throw new Error( 'Argument 1 to configureJsMinimizerPlugin() must be a callback function.' @@ -381,10 +439,10 @@ class WebpackConfig { /** * Configures the options passed to the minimizer-webpack-plugin for CSS minimization. - * - * @param {MinimizerOptionsCallback} cssMinimizerPluginOptionsCallback */ - configureCssMinimizerPlugin(cssMinimizerPluginOptionsCallback = () => {}) { + configureCssMinimizerPlugin( + cssMinimizerPluginOptionsCallback: MinimizerOptionsCallback = () => {} + ) { if (typeof cssMinimizerPluginOptionsCallback !== 'function') { throw new Error( 'Argument 1 to configureCssMinimizerPlugin() must be a callback function' @@ -398,20 +456,18 @@ class WebpackConfig { /** * Returns the value that should be used as the publicPath, * which can be overridden by enabling the webpackDevServer - * - * @returns {string} */ - getRealPublicPath() { + getRealPublicPath(): string { if (!this.useDevServer()) { - return this.publicPath; + return this.publicPath!; } if (this.runtimeConfig.devServerKeepPublicPath) { - return this.publicPath; + return this.publicPath!; } - if (this.publicPath.includes('://')) { - return this.publicPath; + if (this.publicPath!.includes('://')) { + return this.publicPath!; } const devServerUrl = pathUtil.calculateDevServerUrl(this.runtimeConfig); @@ -420,7 +476,7 @@ class WebpackConfig { return devServerUrl.replace(/\/$/, '') + this.publicPath; } - addEntry(name, src) { + addEntry(name: string, src: string | string[]) { this.validateNameIsNewEntry(name); this.entries.set(name, src); @@ -428,11 +484,8 @@ class WebpackConfig { /** * Provide a has of entries at once, as an alternative to calling `addEntry` several times. - * - * @param {Record} entries - * @returns {void} */ - addEntries(entries = {}) { + addEntries(entries: Record = {}) { if (typeof entries !== 'object') { throw new Error('Argument 1 to addEntries() must be an object.'); } @@ -440,13 +493,13 @@ class WebpackConfig { Object.entries(entries).forEach((entry) => this.addEntry(entry[0], entry[1])); } - addStyleEntry(name, src) { + addStyleEntry(name: string, src: string | string[]) { this.validateNameIsNewEntry(name); this.styleEntries.set(name, src); } - addPlugin(plugin, priority = 0) { + addPlugin(plugin: webpack.WebpackPluginInstance, priority = 0) { if (typeof priority !== 'number') { throw new Error('Argument 2 to addPlugin() must be a number.'); } @@ -457,11 +510,11 @@ class WebpackConfig { }); } - addLoader(loader) { + addLoader(loader: webpack.RuleSetRule) { this.loaders.push(loader); } - addAliases(aliases = {}) { + addAliases(aliases: Record = {}) { if (typeof aliases !== 'object') { throw new Error('Argument 1 to addAliases() must be an object.'); } @@ -469,10 +522,7 @@ class WebpackConfig { Object.assign(this.aliases, aliases); } - /** - * @param {webpack.Externals} externals - */ - addExternals(externals = []) { + addExternals(externals: webpack.ExternalItem | webpack.ExternalItem[] = []) { if (!Array.isArray(externals)) { externals = [externals]; } @@ -488,11 +538,15 @@ class WebpackConfig { this.useSourceMaps = enabled; } - /** - * @param {OptionsCallback|null} callback - * @param {{exclude?: webpack.RuleSetCondition, includeNodeModules?: string[], useBuiltIns?: 'usage' | 'entry' | false, corejs?: number|string|{ version: string, proposals: boolean }|null}} options - */ - configureBabel(callback, options = {}) { + configureBabel( + callback: OptionsCallback | null, + options: { + exclude?: webpack.RuleSetCondition; + includeNodeModules?: string[]; + useBuiltIns?: 'usage' | 'entry' | false; + corejs?: number | string | { version: string; proposals: boolean } | null; + } = {} + ) { if (callback) { if (typeof callback !== 'function') { throw new Error( @@ -534,22 +588,22 @@ class WebpackConfig { ); } - if (!Array.isArray(options[optionKey])) { + if (!Array.isArray((options as Record)[optionKey])) { throw new Error( 'Option "includeNodeModules" passed to configureBabel() must be an Array.' ); } - this.babelOptions['exclude'] = (filePath) => { + this.babelOptions['exclude'] = (filePath: string) => { // Don't exclude modules outside of node_modules/bower_components if (!/(node_modules|bower_components)/.test(filePath)) { return false; } // Don't exclude whitelisted Node modules - const whitelistedModules = options[optionKey].map( - (module) => path.join('node_modules', module) + path.sep - ); + const whitelistedModules = ( + (options as Record)[optionKey] as string[] + ).map((module: string) => path.join('node_modules', module) + path.sep); for (const modulePath of whitelistedModules) { if (filePath.includes(modulePath)) { @@ -576,15 +630,14 @@ class WebpackConfig { `The "${optionKey}" option of configureBabel() will not be used because your app already provides an external Babel configuration (e.g. a ".babelrc" or "babel.config.js" file or "babel" key in "package.json").` ); } - this.babelOptions[optionKey] = options[optionKey]; + (this.babelOptions as Record)[optionKey] = ( + options as Record + )[optionKey]; } } } - /** - * @param {OptionsCallback} callback - */ - configureBabelPresetEnv(callback) { + configureBabelPresetEnv(callback: OptionsCallback) { if (typeof callback !== 'function') { throw new Error('Argument 1 to configureBabelPresetEnv() must be a callback function.'); } @@ -603,10 +656,7 @@ class WebpackConfig { this._configureBabelPresetEnvCalled = true; } - /** - * @param {OptionsCallback} callback - */ - configureCssLoader(callback) { + configureCssLoader(callback: OptionsCallback) { if (typeof callback !== 'function') { throw new Error('Argument 1 to configureCssLoader() must be a callback function.'); } @@ -614,10 +664,7 @@ class WebpackConfig { this.cssLoaderConfigurationCallback = callback; } - /** - * @param {OptionsCallback} callback - */ - configureStyleLoader(callback) { + configureStyleLoader(callback: OptionsCallback) { if (typeof callback !== 'function') { throw new Error('Argument 1 to configureStyleLoader() must be a callback function.'); } @@ -625,11 +672,12 @@ class WebpackConfig { this.styleLoaderConfigurationCallback = callback; } - /** - * @param {OptionsCallback} loaderOptionsCallback - * @param {OptionsCallback} pluginOptionsCallback - */ - configureMiniCssExtractPlugin(loaderOptionsCallback, pluginOptionsCallback = () => {}) { + configureMiniCssExtractPlugin( + loaderOptionsCallback: OptionsCallback, + pluginOptionsCallback: OptionsCallback< + import('mini-css-extract-plugin').PluginOptions + > = () => {} + ) { if (typeof loaderOptionsCallback !== 'function') { throw new Error( 'Argument 1 to configureMiniCssExtractPluginLoader() must be a callback function.' @@ -658,10 +706,7 @@ class WebpackConfig { this.shouldSplitEntryChunks = true; } - /** - * @param {OptionsCallback} callback - */ - configureSplitChunks(callback) { + configureSplitChunks(callback: OptionsCallback) { if (typeof callback !== 'function') { throw new Error('Argument 1 to configureSplitChunks() must be a callback function.'); } @@ -669,10 +714,9 @@ class WebpackConfig { this.splitChunksConfigurationCallback = callback; } - /** - * @param {OptionsCallback>} callback - */ - configureWatchOptions(callback) { + configureWatchOptions( + callback: OptionsCallback> + ) { if (typeof callback !== 'function') { throw new Error('Argument 1 to configureWatchOptions() must be a callback function.'); } @@ -680,10 +724,7 @@ class WebpackConfig { this.watchOptionsConfigurationCallback = callback; } - /** - * @param {OptionsCallback} callback - */ - configureDevServerOptions(callback) { + configureDevServerOptions(callback: OptionsCallback) { featuresHelper.ensurePackagesExistAndAreCorrectVersion('webpack-dev-server'); if (typeof callback !== 'function') { @@ -695,11 +736,7 @@ class WebpackConfig { this.devServerOptionsConfigurationCallback = callback; } - /** - * @param {string} name - * @param {object} options - */ - addCacheGroup(name, options) { + addCacheGroup(name: string, options: CacheGroupOptions) { if (typeof name !== 'string') { throw new Error('Argument 1 to addCacheGroup() must be a string.'); } @@ -731,10 +768,7 @@ class WebpackConfig { this.cacheGroups[name] = options; } - /** - * @param {CopyFilesOptions|CopyFilesOptions[]} configs - */ - copyFiles(configs = []) { + copyFiles(configs: CopyFilesOptions | CopyFilesOptions[] = []) { if (!Array.isArray(configs)) { configs = [configs]; } @@ -746,11 +780,11 @@ class WebpackConfig { } const defaultConfig = { - from: null, - pattern: /.*/, - to: null, + from: null as string | null, + pattern: /.*/ as RegExp | string, + to: null as string | null, includeSubdirectories: true, - context: null, + context: null as string | null, }; for (const config of configs) { @@ -784,14 +818,13 @@ class WebpackConfig { } } - this.copyFilesConfigs.push(Object.assign({}, defaultConfig, config)); + this.copyFilesConfigs.push( + Object.assign({}, defaultConfig, config) as ResolvedCopyFilesConfig + ); } } - /** - * @param {OptionsCallback} postCssLoaderOptionsCallback - */ - enablePostCssLoader(postCssLoaderOptionsCallback = () => {}) { + enablePostCssLoader(postCssLoaderOptionsCallback: OptionsCallback = () => {}) { this.usePostCssLoader = true; if (typeof postCssLoaderOptionsCallback !== 'function') { @@ -801,11 +834,10 @@ class WebpackConfig { this.postCssLoaderOptionsCallback = postCssLoaderOptionsCallback; } - /** - * @param {OptionsCallback} sassLoaderOptionsCallback - * @param {{resolveUrlLoader?: boolean, resolveUrlLoaderOptions?: object}} options - */ - enableSassLoader(sassLoaderOptionsCallback = () => {}, options = {}) { + enableSassLoader( + sassLoaderOptionsCallback: OptionsCallback = () => {}, + options: { resolveUrlLoader?: boolean; resolveUrlLoaderOptions?: object } = {} + ) { this.useSassLoader = true; if (typeof sassLoaderOptionsCallback !== 'function') { @@ -821,14 +853,13 @@ class WebpackConfig { ); } - this.sassOptions[optionKey] = options[optionKey]; + (this.sassOptions as Record)[optionKey] = ( + options as Record + )[optionKey]; } } - /** - * @param {OptionsCallback} lessLoaderOptionsCallback - */ - enableLessLoader(lessLoaderOptionsCallback = () => {}) { + enableLessLoader(lessLoaderOptionsCallback: OptionsCallback = () => {}) { this.useLessLoader = true; if (typeof lessLoaderOptionsCallback !== 'function') { @@ -838,10 +869,7 @@ class WebpackConfig { this.lessLoaderOptionsCallback = lessLoaderOptionsCallback; } - /** - * @param {OptionsCallback} stylusLoaderOptionsCallback - */ - enableStylusLoader(stylusLoaderOptionsCallback = () => {}) { + enableStylusLoader(stylusLoaderOptionsCallback: OptionsCallback = () => {}) { this.useStylusLoader = true; if (typeof stylusLoaderOptionsCallback !== 'function') { @@ -851,17 +879,19 @@ class WebpackConfig { this.stylusLoaderOptionsCallback = stylusLoaderOptionsCallback; } - enableStimulusBridge(controllerJsonPath) { + enableStimulusBridge(controllerJsonPath: string) { if (!fs.existsSync(controllerJsonPath)) { throw new Error(`File "${controllerJsonPath}" could not be found.`); } // Add configured entrypoints - const controllersData = JSON.parse(fs.readFileSync(controllerJsonPath, 'utf8')); + const controllersData = JSON.parse(fs.readFileSync(controllerJsonPath, 'utf8')) as { + entrypoints: Record; + }; const rootDir = path.dirname(path.resolve(controllerJsonPath)); - for (let name in controllersData.entrypoints) { - this.addEntry(name, rootDir + '/' + controllersData.entrypoints[name]); + for (const name in controllersData.entrypoints) { + this.addEntry(name, rootDir + '/' + controllersData.entrypoints[name]!); } this.addAliases({ @@ -869,11 +899,10 @@ class WebpackConfig { }); } - /** - * @param {Record} buildDependencies - * @param {OptionsCallback} callback - */ - enableBuildCache(buildDependencies, callback = (cache) => {}) { + enableBuildCache( + buildDependencies: Record, + callback: OptionsCallback = (cache) => {} + ) { if (typeof buildDependencies !== 'object') { throw new Error('Argument 1 to enableBuildCache() must be an object.'); } @@ -894,10 +923,7 @@ class WebpackConfig { this.persistentCacheCallback = callback; } - /** - * @param {OptionsCallback} callback - */ - enableReactPreset(callback = () => {}) { + enableReactPreset(callback: OptionsCallback = () => {}) { if (typeof callback !== 'function') { throw new Error('Argument 1 to enableReactPreset() must be a callback function.'); } @@ -906,7 +932,7 @@ class WebpackConfig { this.babelReactPresetOptionsCallback = callback; } - enablePreactPreset(options = {}) { + enablePreactPreset(options: { preactCompat?: boolean } = {}) { this.usePreact = true; for (const optionKey of Object.keys(options)) { @@ -916,7 +942,9 @@ class WebpackConfig { ); } - this.preactOptions[optionKey] = options[optionKey]; + (this.preactOptions as Record)[optionKey] = ( + options as Record + )[optionKey]; } } @@ -924,10 +952,7 @@ class WebpackConfig { this.useSvelte = true; } - /** - * @param {OptionsCallback} callback - */ - enableTypeScriptLoader(callback = () => {}) { + enableTypeScriptLoader(callback: OptionsCallback = () => {}) { if (this.useBabelTypeScriptPreset) { throw new Error( 'Encore.enableTypeScriptLoader() can not be called when Encore.enableBabelTypeScriptPreset() has been called.' @@ -943,10 +968,9 @@ class WebpackConfig { this.tsConfigurationCallback = callback; } - /** - * @param {OptionsCallback} forkedTypeScriptTypesCheckOptionsCallback - */ - enableForkedTypeScriptTypesChecking(forkedTypeScriptTypesCheckOptionsCallback = () => {}) { + enableForkedTypeScriptTypesChecking( + forkedTypeScriptTypesCheckOptionsCallback: OptionsCallback = () => {} + ) { if (this.useBabelTypeScriptPreset) { throw new Error( 'Encore.enableForkedTypeScriptTypesChecking() can not be called when Encore.enableBabelTypeScriptPreset() has been called.' @@ -963,7 +987,7 @@ class WebpackConfig { this.forkedTypeScriptTypesCheckOptionsCallback = forkedTypeScriptTypesCheckOptionsCallback; } - enableBabelTypeScriptPreset(options = {}) { + enableBabelTypeScriptPreset(options: object = {}) { if (this.useTypeScriptLoader) { throw new Error( 'Encore.enableBabelTypeScriptPreset() can not be called when Encore.enableTypeScriptLoader() has been called.' @@ -980,11 +1004,14 @@ class WebpackConfig { this.babelTypeScriptPresetOptions = options; } - /** - * @param {OptionsCallback} vueLoaderOptionsCallback - * @param {object} vueOptions - */ - enableVueLoader(vueLoaderOptionsCallback = () => {}, vueOptions = {}) { + enableVueLoader( + vueLoaderOptionsCallback: OptionsCallback = () => {}, + vueOptions: { + useJsx?: boolean; + version?: number | null; + runtimeCompilerBuild?: boolean | null; + } = {} + ) { this.useVueLoader = true; if (typeof vueLoaderOptionsCallback !== 'function') { @@ -1003,22 +1030,23 @@ class WebpackConfig { if (key === 'version') { const validVersions = [3]; - if (!validVersions.includes(vueOptions.version)) { + if (!validVersions.includes(vueOptions.version as number)) { throw new Error( `"${vueOptions.version}" is not a valid value for the "version" option passed to enableVueLoader(). Valid versions are: ${validVersions.join(', ')}.` ); } } - this.vueOptions[key] = vueOptions[key]; + (this.vueOptions as Record)[key] = ( + vueOptions as Record + )[key]; } } - /** - * @param {boolean} enabled - * @param {OptionsCallback} notifierPluginOptionsCallback - */ - enableBuildNotifications(enabled = true, notifierPluginOptionsCallback = () => {}) { + enableBuildNotifications( + enabled = true, + notifierPluginOptionsCallback: OptionsCallback = () => {} + ) { if (typeof notifierPluginOptionsCallback !== 'function') { throw new Error( 'Argument 2 to enableBuildNotifications() must be a callback function.' @@ -1029,10 +1057,7 @@ class WebpackConfig { this.notifierPluginOptionsCallback = notifierPluginOptionsCallback; } - /** - * @param {OptionsCallback} callback - */ - enableHandlebarsLoader(callback = () => {}) { + enableHandlebarsLoader(callback: OptionsCallback = () => {}) { this.useHandlebarsLoader = true; if (typeof callback !== 'function') { @@ -1046,7 +1071,7 @@ class WebpackConfig { this.extractCss = !disabled; } - configureFilenames(configuredFilenames = {}) { + configureFilenames(configuredFilenames: { js?: string; css?: string; assets?: string } = {}) { if (typeof configuredFilenames !== 'object') { throw new Error('Argument 1 to configureFilenames() must be an object.'); } @@ -1064,11 +1089,15 @@ class WebpackConfig { this.configuredFilenames = configuredFilenames; } - /** - * @param {{filename?: string, maxSize?: number|null, type?: string, enabled?: boolean}} options - * @param {OptionsCallback} ruleCallback - */ - configureImageRule(options = {}, ruleCallback = () => {}) { + configureImageRule( + options: { + filename?: string; + maxSize?: number | null; + type?: string; + enabled?: boolean; + } = {}, + ruleCallback: OptionsCallback = () => {} + ) { for (const optionKey of Object.keys(options)) { if (!(optionKey in this.imageRuleOptions)) { throw new Error( @@ -1076,7 +1105,9 @@ class WebpackConfig { ); } - this.imageRuleOptions[optionKey] = options[optionKey]; + (this.imageRuleOptions as unknown as Record)[optionKey] = ( + options as Record + )[optionKey]; } if (this.imageRuleOptions.maxSize && this.imageRuleOptions.type !== 'asset') { @@ -1092,11 +1123,15 @@ class WebpackConfig { this.imageRuleCallback = ruleCallback; } - /** - * @param {{filename?: string, maxSize?: number|null, type?: string, enabled?: boolean}} options - * @param {OptionsCallback} ruleCallback - */ - configureFontRule(options = {}, ruleCallback = () => {}) { + configureFontRule( + options: { + filename?: string; + maxSize?: number | null; + type?: string; + enabled?: boolean; + } = {}, + ruleCallback: OptionsCallback = () => {} + ) { for (const optionKey of Object.keys(options)) { if (!(optionKey in this.fontRuleOptions)) { throw new Error( @@ -1104,7 +1139,9 @@ class WebpackConfig { ); } - this.fontRuleOptions[optionKey] = options[optionKey]; + (this.fontRuleOptions as unknown as Record)[optionKey] = ( + options as Record + )[optionKey]; } if (this.fontRuleOptions.maxSize && this.fontRuleOptions.type !== 'asset') { @@ -1120,10 +1157,11 @@ class WebpackConfig { this.fontRuleCallback = ruleCallback; } - /** - * @param {OptionsCallback[0], undefined>>} cleanOptionsCallback - */ - cleanupOutputBeforeBuild(cleanOptionsCallback = () => {}) { + cleanupOutputBeforeBuild( + cleanOptionsCallback: OptionsCallback< + Exclude[0], undefined> + > = () => {} + ) { if (typeof cleanOptionsCallback !== 'function') { throw new Error('Argument 1 to cleanupOutputBeforeBuild() must be a callback function'); } @@ -1132,7 +1170,7 @@ class WebpackConfig { this.cleanOptionsCallback = cleanOptionsCallback; } - autoProvideVariables(variables) { + autoProvideVariables(variables: Record) { // do a few sanity checks, so we can give better user errors if (typeof variables === 'string' || Array.isArray(variables)) { throw new Error( @@ -1152,11 +1190,7 @@ class WebpackConfig { }); } - /** - * @param {string} name - * @param {OptionsCallback} callback - */ - configureLoaderRule(name, callback) { + configureLoaderRule(name: string, callback: OptionsCallback) { // Key: alias, Value: existing loader in `this.loaderConfigurationCallbacks` const aliases = { js: 'javascript', @@ -1165,7 +1199,7 @@ class WebpackConfig { }; if (name in aliases) { - name = aliases[name]; + name = aliases[name as keyof typeof aliases]; } if (!(name in this.loaderConfigurationCallbacks)) { @@ -1181,11 +1215,7 @@ class WebpackConfig { this.loaderConfigurationCallbacks[name] = callback; } - /** - * @param {boolean} enabled - * @param {string|string[]} algorithms - */ - enableIntegrityHashes(enabled = true, algorithms = ['sha384']) { + enableIntegrityHashes(enabled = true, algorithms: string | string[] = ['sha384']) { if (!Array.isArray(algorithms)) { algorithms = [algorithms]; } @@ -1208,23 +1238,23 @@ class WebpackConfig { this.integrityAlgorithms = enabled ? algorithms : []; } - useDevServer() { + useDevServer(): boolean { return this.runtimeConfig.useDevServer; } - isProduction() { + isProduction(): boolean { return this.runtimeConfig.environment === 'production'; } - isDev() { + isDev(): boolean { return this.runtimeConfig.environment === 'dev'; } - isDevServer() { + isDevServer(): boolean { return this.isDev() && this.runtimeConfig.useDevServer; } - validateNameIsNewEntry(name) { + validateNameIsNewEntry(name: string): void { const entryNamesOverlapMsg = 'The entry names between addEntry(), addEntries(), and addStyleEntry() must be unique.'; diff --git a/lib/config-generator.js b/lib/config-generator.ts similarity index 87% rename from lib/config-generator.js rename to lib/config-generator.ts index f2f5794e..a0f1af62 100644 --- a/lib/config-generator.js +++ b/lib/config-generator.ts @@ -7,15 +7,12 @@ * file that was distributed with this source code. */ -/** - * @import WebpackConfig from './WebpackConfig.js' - */ - import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; import tmp from 'tmp'; +import type webpack from 'webpack'; import pathUtil from './config/path-util.ts'; import babelLoaderUtil from './loaders/babel.ts'; @@ -28,7 +25,7 @@ import sassLoaderUtil from './loaders/sass.ts'; import stylusLoaderUtil from './loaders/stylus.ts'; import tsLoaderUtil from './loaders/typescript.ts'; import vueLoaderUtil from './loaders/vue.ts'; -import logger from './logger.js'; +import logger from './logger.ts'; // plugins utils import assetOutputDisplay from './plugins/asset-output-display.ts'; import cssMinimizerPluginUtil from './plugins/css-minimizer.ts'; @@ -43,20 +40,20 @@ import notifierPluginUtil from './plugins/notifier.ts'; import PluginPriorities from './plugins/plugin-priorities.ts'; import variableProviderPluginUtil from './plugins/variable-provider.ts'; import vuePluginUtil from './plugins/vue.ts'; -import applyOptionsCallback from './utils/apply-options-callback.ts'; +import applyOptionsCallback, { type OptionsCallback } from './utils/apply-options-callback.ts'; import copyEntryTmpName from './utils/copyEntryTmpName.ts'; import getVueVersion from './utils/get-vue-version.ts'; import stringEscaper from './utils/string-escaper.ts'; +import type WebpackConfig from './WebpackConfig.js'; class ConfigGenerator { - /** - * @param {WebpackConfig} webpackConfig - */ - constructor(webpackConfig) { + webpackConfig: WebpackConfig; + + constructor(webpackConfig: WebpackConfig) { this.webpackConfig = webpackConfig; } - async getWebpackConfig() { + async getWebpackConfig(): Promise { // Perform deferred babel validation checks (moved from WebpackConfig // methods because they require async doesBabelRcFileExist()). await this._validateDeferredBabelConfig(); @@ -72,19 +69,16 @@ class ConfigGenerator { */ if ( this.webpackConfig.useDevServer() && - (devServerConfig.server === 'https' || - (typeof devServerConfig.server === 'object' && - devServerConfig.server.type === 'https')) + (devServerConfig!.server === 'https' || + (typeof devServerConfig!.server === 'object' && + devServerConfig!.server.type === 'https')) ) { this.webpackConfig.runtimeConfig.devServerFinalIsHttps = true; } else { this.webpackConfig.runtimeConfig.devServerFinalIsHttps = false; } - /** - * @type {import('webpack').Configuration} - */ - const config = { + const config: webpack.Configuration = { context: this.webpackConfig.getContext(), entry: this.buildEntryConfig(), mode: this.webpackConfig.isProduction() ? 'production' : 'development', @@ -113,7 +107,9 @@ class ConfigGenerator { } if (null !== devServerConfig) { - config.devServer = devServerConfig; + // `devServer` is added to webpack's Configuration type by + // webpack-dev-server's type augmentation, which is not loaded here. + (config as { devServer?: unknown }).devServer = devServerConfig; } config.performance = { @@ -127,6 +123,7 @@ class ConfigGenerator { extensions: ['.wasm', '.mjs', '.js', '.json', '.jsx', '.vue', '.ts', '.tsx', '.svelte'], alias: {}, }; + const resolveAlias = config.resolve.alias as Record; if ( this.webpackConfig.useVueLoader && @@ -142,7 +139,7 @@ class ConfigGenerator { const vueVersion = getVueVersion(this.webpackConfig); switch (vueVersion) { case 3: - config.resolve.alias['vue$'] = 'vue/dist/vue.esm-bundler.js'; + resolveAlias['vue$'] = 'vue/dist/vue.esm-bundler.js'; break; default: throw new Error(`Invalid vue version ${vueVersion}`); @@ -150,11 +147,11 @@ class ConfigGenerator { } if (this.webpackConfig.usePreact && this.webpackConfig.preactOptions.preactCompat) { - config.resolve.alias['react'] = 'preact/compat'; - config.resolve.alias['react-dom'] = 'preact/compat'; + resolveAlias['react'] = 'preact/compat'; + resolveAlias['react-dom'] = 'preact/compat'; } - Object.assign(config.resolve.alias, this.webpackConfig.aliases); + Object.assign(resolveAlias, this.webpackConfig.aliases); config.externals = [...this.webpackConfig.externals]; @@ -166,10 +163,8 @@ class ConfigGenerator { * synchronously in WebpackConfig.configureBabel() and * WebpackConfig.configureBabelPresetEnv(). These checks require * the async doesBabelRcFileExist() call. - * - * @returns {Promise} */ - async _validateDeferredBabelConfig() { + async _validateDeferredBabelConfig(): Promise { const babelRcFileExists = await this.webpackConfig.doesBabelRcFileExist(); // Check from configureBabel(): if a callback was provided and an @@ -203,11 +198,8 @@ class ConfigGenerator { } } - buildEntryConfig() { - /** - * @type {Record} - */ - const entry = {}; + buildEntryConfig(): Record { + const entry: Record = {}; for (const [entryName, entryChunks] of this.webpackConfig.entries) { // entryFile could be an array, we don't care @@ -243,7 +235,8 @@ class ConfigGenerator { const tmpFileObject = tmp.fileSync(); fs.writeFileSync( tmpFileObject.name, - copyFilesConfigs.reduce((buffer, entry, index) => { + copyFilesConfigs.reduce((buffer: string, entry, index) => { + const pattern = entry.pattern as RegExp; const copyFrom = path.resolve(this.webpackConfig.getContext(), entry.from); let copyTo = entry.to; @@ -271,8 +264,8 @@ class ConfigGenerator { // the patternSource is base64 encoded in case // it contains characters that don't work with // the "inline loader" syntax - patternSource: Buffer.from(entry.pattern.source).toString('base64'), - patternFlags: entry.pattern.flags, + patternSource: Buffer.from(pattern.source).toString('base64'), + patternFlags: pattern.flags, })}`; return ( @@ -281,7 +274,7 @@ class ConfigGenerator { const context_${index} = require.context( '${stringEscaper(`!!${copyFilesLoaderConfig}!${copyFrom}?copy-files-loader`)}', ${!!entry.includeSubdirectories}, - ${entry.pattern} + ${pattern} ); context_${index}.keys().forEach(context_${index}); ` @@ -295,7 +288,7 @@ class ConfigGenerator { return entry; } - buildOutputConfig() { + buildOutputConfig(): webpack.Configuration['output'] { // Default filename can be overridden using Encore.configureFilenames({ js: '...' }) let filename = this.webpackConfig.useVersioning ? '[name].[contenthash:8].js' : '[name].js'; if (this.webpackConfig.configuredFilenames.js) { @@ -304,7 +297,7 @@ class ConfigGenerator { return { clean: this.buildCleanConfig(), - path: this.webpackConfig.outputPath, + path: this.webpackConfig.outputPath as string, filename: filename, // default "asset module" filename // this is overridden for the image & font rules @@ -318,10 +311,7 @@ class ConfigGenerator { }; } - /** - * @returns {ConstructorParameters[0]|boolean} - */ - buildCleanConfig() { + buildCleanConfig(): ConstructorParameters[0] | boolean { if (!this.webpackConfig.cleanupOutput) { return false; } @@ -329,20 +319,33 @@ class ConfigGenerator { return applyOptionsCallback(this.webpackConfig.cleanOptionsCallback, {}); } - async buildRulesConfig() { - const applyRuleConfigurationCallback = (name, defaultRules) => { + async buildRulesConfig(): Promise { + const applyRuleConfigurationCallback = ( + name: string, + defaultRules: webpack.RuleSetRule + ) => { return applyOptionsCallback( - this.webpackConfig.loaderConfigurationCallbacks[name], + this.webpackConfig.loaderConfigurationCallbacks[name]!, defaultRules ); }; - const generateAssetRuleConfig = (testRegex, ruleOptions, ruleCallback, ruleName) => { - const generatorOptions = {}; + const generateAssetRuleConfig = ( + testRegex: RegExp, + ruleOptions: { + filename?: string; + maxSize?: number | null; + type?: string; + enabled?: boolean; + }, + ruleCallback: OptionsCallback, + ruleName: string + ) => { + const generatorOptions: { filename?: string } = {}; if (ruleOptions.filename) { generatorOptions.filename = ruleOptions.filename; } - const parserOptions = {}; + const parserOptions: { dataUrlCondition?: { maxSize: number } } = {}; if (ruleOptions.maxSize) { parserOptions.dataUrlCondition = { maxSize: ruleOptions.maxSize, @@ -379,7 +382,7 @@ class ConfigGenerator { cssExtensions.push('postcss'); } - let rules = [ + const rules: webpack.RuleSetRule[] = [ applyRuleConfigurationCallback('javascript', { test: babelLoaderUtil.getTest(this.webpackConfig), exclude: this.webpackConfig.babelOptions.exclude, @@ -552,8 +555,8 @@ class ConfigGenerator { return rules; } - async buildPluginsConfig() { - const plugins = []; + async buildPluginsConfig(): Promise { + const plugins: Array<{ plugin: webpack.WebpackPluginInstance; priority: number }> = []; miniCssExtractPluginUtil(plugins, this.webpackConfig); @@ -603,8 +606,8 @@ class ConfigGenerator { .map((plugin) => plugin.plugin); } - buildOptimizationConfig() { - const optimization = {}; + buildOptimizationConfig(): webpack.Configuration['optimization'] { + const optimization: NonNullable = {}; if (this.webpackConfig.isProduction()) { const minimizers = [jsMinimizerPluginUtil(this.webpackConfig)]; @@ -614,11 +617,11 @@ class ConfigGenerator { optimization.minimizer = minimizers; } - const splitChunks = { + const splitChunks: Record = { chunks: this.webpackConfig.shouldSplitEntryChunks ? 'all' : 'async', }; - const cacheGroups = {}; + const cacheGroups: Record = {}; for (const groupName in this.webpackConfig.cacheGroups) { cacheGroups[groupName] = Object.assign( @@ -640,21 +643,21 @@ class ConfigGenerator { } if (this.webpackConfig.shouldUseSingleRuntimeChunk) { - optimization.runtimeChunk = /** @type {const} */ ('single'); + optimization.runtimeChunk = 'single' as const; } optimization.splitChunks = applyOptionsCallback( this.webpackConfig.splitChunksConfigurationCallback, splitChunks - ); + ) as NonNullable['splitChunks']; return optimization; } - buildCacheConfig() { - const cache = {}; + buildCacheConfig(): webpack.FileCacheOptions { + const cache: webpack.FileCacheOptions = {} as webpack.FileCacheOptions; - cache.type = /** @type {const} */ ('filesystem'); + cache.type = 'filesystem' as const; cache.buildDependencies = this.webpackConfig.persistentCacheBuildDependencies; applyOptionsCallback(this.webpackConfig.persistentCacheCallback, cache); @@ -662,10 +665,10 @@ class ConfigGenerator { return cache; } - buildStatsConfig() { + buildStatsConfig(): webpack.StatsOptions { // try to silence as much as possible: the output is rarely helpful // this still doesn't remove all output - let stats = {}; + let stats: webpack.StatsOptions = {}; if ( !this.webpackConfig.runtimeConfig.outputJson && @@ -703,10 +706,10 @@ class ConfigGenerator { ); } - buildDevServerConfig() { + buildDevServerConfig(): { server?: string | { type?: string }; [key: string]: unknown } { const contentBase = pathUtil.getContentBase(this.webpackConfig); - const devServerOptions = { + const devServerOptions: { server?: string | { type?: string }; [key: string]: unknown } = { static: { directory: contentBase, }, @@ -737,15 +740,14 @@ class ConfigGenerator { return applyOptionsCallback( this.webpackConfig.devServerOptionsConfigurationCallback, devServerOptions - ); + ) as { server?: string | { type?: string }; [key: string]: unknown }; } } /** - * @param {WebpackConfig} webpackConfig A configured WebpackConfig object - * @returns {Promise} The final webpack config object + * @param webpackConfig A configured WebpackConfig object */ -export default async function (webpackConfig) { +export default async function (webpackConfig: WebpackConfig): Promise { const generator = new ConfigGenerator(webpackConfig); return generator.getWebpackConfig(); diff --git a/lib/config/path-util.ts b/lib/config/path-util.ts index f08fc42e..1efca152 100644 --- a/lib/config/path-util.ts +++ b/lib/config/path-util.ts @@ -9,7 +9,7 @@ import path from 'path'; -import logger from '../logger.js'; +import logger from '../logger.ts'; import type WebpackConfig from '../WebpackConfig.js'; // .js (not .ts): RuntimeConfig is exposed in this module's emitted .d.ts, and // rewriteRelativeImportExtensions does NOT rewrite .ts -> .js inside .d.ts files @@ -22,11 +22,11 @@ export default { */ getContentBase(webpackConfig: WebpackConfig): string { // strip trailing slash (for Unix or Windows) - const outputPath = webpackConfig.outputPath.replace(/\/$/, '').replace(/\\$/, ''); + const outputPath = webpackConfig.outputPath!.replace(/\/$/, '').replace(/\\$/, ''); // use the manifestKeyPrefix if available const publicPath = webpackConfig.manifestKeyPrefix ? webpackConfig.manifestKeyPrefix.replace(/\/$/, '') - : webpackConfig.publicPath.replace(/\/$/, ''); + : webpackConfig.publicPath!.replace(/\/$/, ''); /* * We use the intersection of the publicPath (or manifestKeyPrefix) and outputPath @@ -62,7 +62,7 @@ export default { * Returns the output path, but as a relative string (e.g. web/build) */ getRelativeOutputPath(webpackConfig: WebpackConfig): string { - return webpackConfig.outputPath.replace(webpackConfig.getContext() + path.sep, ''); + return webpackConfig.outputPath!.replace(webpackConfig.getContext() + path.sep, ''); }, /** @@ -77,7 +77,7 @@ export default { return; } - if (webpackConfig.publicPath.includes('://')) { + if (webpackConfig.publicPath!.includes('://')) { /* * If publicPath is absolute, you probably don't want your manifests.json * keys to be prefixed with the CDN URL. Instead, we force you to @@ -89,13 +89,13 @@ export default { ); } - let outputPath = webpackConfig.outputPath; + let outputPath = webpackConfig.outputPath!; // for comparison purposes, change \ to / on Windows outputPath = outputPath.replace(/\\/g, '/'); // remove trailing slash on each outputPath = outputPath.replace(/\/$/, ''); - const publicPath = webpackConfig.publicPath.replace(/\/$/, ''); + const publicPath = webpackConfig.publicPath!.replace(/\/$/, ''); /* * This is a sanity check. If, for example, you are deploying diff --git a/lib/config/validator.ts b/lib/config/validator.ts index 165d210f..677894a1 100644 --- a/lib/config/validator.ts +++ b/lib/config/validator.ts @@ -8,7 +8,7 @@ */ import type WebpackConfig from '../WebpackConfig.js'; -import logger from './../logger.js'; +import logger from './../logger.ts'; import pathUtil from './path-util.ts'; class Validator { @@ -75,7 +75,7 @@ class Validator { * There are some valid use-cases for not wanting this behavior * (see #59), but we want to warn the user. */ - if (this.webpackConfig.publicPath.includes('://')) { + if (this.webpackConfig.publicPath!.includes('://')) { logger.warning( `Passing an absolute URL to setPublicPath() *and* using the dev-server can cause issues. Your assets will load from the publicPath (${this.webpackConfig.publicPath}) instead of from the dev server URL.` ); diff --git a/lib/context.js b/lib/context.ts similarity index 75% rename from lib/context.js rename to lib/context.ts index 6f394ec0..790a44ab 100644 --- a/lib/context.js +++ b/lib/context.ts @@ -7,10 +7,12 @@ * file that was distributed with this source code. */ +import type RuntimeConfig from './config/RuntimeConfig.js'; + /** * Stores the current RuntimeConfig created by the encore executable. */ export default { - runtimeConfig: null, + runtimeConfig: null as RuntimeConfig | null, }; diff --git a/lib/features.js b/lib/features.ts similarity index 89% rename from lib/features.js rename to lib/features.ts index bf776dbe..f01dd71f 100644 --- a/lib/features.js +++ b/lib/features.ts @@ -7,19 +7,20 @@ * file that was distributed with this source code. */ -import packageHelper from './package-helper.js'; +import type { PackagesConfig } from './package-helper.js'; +import packageHelper from './package-helper.ts'; + +interface Feature { + method: string; + packages: PackagesConfig; + description: string; +} /** * An object that holds internal configuration about different * "loaders"/"plugins" that can be enabled/used. - * - * @type {{[key: string]: { - * method: string, - * packages: Array<{ name: string, enforce_version?: boolean } | Array<{ name: string }>>, - * description: string, - * }}} */ -const features = { +const features: Record = { sass: { method: 'enableSassLoader()', packages: [ @@ -166,16 +167,20 @@ const features = { }, }; -function getFeatureConfig(featureName) { - if (!features[featureName]) { +function getFeatureConfig(featureName: string): Feature { + const config = features[featureName]; + if (!config) { throw new Error(`Unknown feature ${featureName}`); } - return features[featureName]; + return config; } export default { - ensurePackagesExistAndAreCorrectVersion: function (featureName, method = null) { + ensurePackagesExistAndAreCorrectVersion: function ( + featureName: string, + method: string | null = null + ): void { const config = getFeatureConfig(featureName); packageHelper.ensurePackagesExist( @@ -184,7 +189,7 @@ export default { ); }, - getMissingPackageRecommendations: function (featureName) { + getMissingPackageRecommendations: function (featureName: string) { const config = getFeatureConfig(featureName); return packageHelper.getMissingPackageRecommendations( @@ -193,11 +198,11 @@ export default { ); }, - getFeatureMethod: function (featureName) { + getFeatureMethod: function (featureName: string): string { return getFeatureConfig(featureName).method; }, - getFeatureDescription: function (featureName) { + getFeatureDescription: function (featureName: string): string { return getFeatureConfig(featureName).description; }, }; diff --git a/lib/friendly-errors/formatters/missing-loader.ts b/lib/friendly-errors/formatters/missing-loader.ts index 87d1d26e..f85c0e88 100644 --- a/lib/friendly-errors/formatters/missing-loader.ts +++ b/lib/friendly-errors/formatters/missing-loader.ts @@ -10,7 +10,7 @@ import type { FriendlyError } from '@kocal/friendly-errors-webpack-plugin'; import pc from 'picocolors'; -import loaderFeatures from '../../features.js'; +import loaderFeatures from '../../features.ts'; interface MissingLoaderError extends FriendlyError { loaderName?: string; diff --git a/lib/loaders/babel.ts b/lib/loaders/babel.ts index e46e7554..ef53f637 100644 --- a/lib/loaders/babel.ts +++ b/lib/loaders/babel.ts @@ -9,7 +9,7 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.js'; +import loaderFeatures from '../features.ts'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import type WebpackConfig from '../WebpackConfig.js'; diff --git a/lib/loaders/css.ts b/lib/loaders/css.ts index e7d0c874..8e7a8ada 100644 --- a/lib/loaders/css.ts +++ b/lib/loaders/css.ts @@ -9,7 +9,7 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.js'; +import loaderFeatures from '../features.ts'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import type WebpackConfig from '../WebpackConfig.js'; diff --git a/lib/loaders/handlebars.ts b/lib/loaders/handlebars.ts index 8e7122bf..529605fc 100644 --- a/lib/loaders/handlebars.ts +++ b/lib/loaders/handlebars.ts @@ -9,7 +9,7 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.js'; +import loaderFeatures from '../features.ts'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import type WebpackConfig from '../WebpackConfig.js'; diff --git a/lib/loaders/less.ts b/lib/loaders/less.ts index b91036e6..c6438c67 100644 --- a/lib/loaders/less.ts +++ b/lib/loaders/less.ts @@ -9,7 +9,7 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.js'; +import loaderFeatures from '../features.ts'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import type WebpackConfig from '../WebpackConfig.js'; import cssLoader from './css.ts'; diff --git a/lib/loaders/sass.ts b/lib/loaders/sass.ts index 2833cdd0..22f7aa0f 100644 --- a/lib/loaders/sass.ts +++ b/lib/loaders/sass.ts @@ -9,7 +9,7 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.js'; +import loaderFeatures from '../features.ts'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import type WebpackConfig from '../WebpackConfig.js'; import cssLoader from './css.ts'; diff --git a/lib/loaders/stylus.ts b/lib/loaders/stylus.ts index f69f7428..41e79a82 100644 --- a/lib/loaders/stylus.ts +++ b/lib/loaders/stylus.ts @@ -9,7 +9,7 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.js'; +import loaderFeatures from '../features.ts'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import type WebpackConfig from '../WebpackConfig.js'; import cssLoader from './css.ts'; diff --git a/lib/loaders/typescript.ts b/lib/loaders/typescript.ts index ab7e77a2..de1ecfa4 100644 --- a/lib/loaders/typescript.ts +++ b/lib/loaders/typescript.ts @@ -9,7 +9,7 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.js'; +import loaderFeatures from '../features.ts'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import type WebpackConfig from '../WebpackConfig.js'; import babelLoader from './babel.ts'; diff --git a/lib/loaders/vue.ts b/lib/loaders/vue.ts index f6c42a71..fb6718ea 100644 --- a/lib/loaders/vue.ts +++ b/lib/loaders/vue.ts @@ -9,7 +9,7 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.js'; +import loaderFeatures from '../features.ts'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import getVueVersion from '../utils/get-vue-version.ts'; import type WebpackConfig from '../WebpackConfig.js'; diff --git a/lib/logger.js b/lib/logger.ts similarity index 66% rename from lib/logger.js rename to lib/logger.ts index a37c095f..8836d49a 100644 --- a/lib/logger.js +++ b/lib/logger.ts @@ -9,16 +9,22 @@ import pc from 'picocolors'; -const defaultConfig = { +type MessageType = 'debug' | 'recommendation' | 'warning' | 'deprecation'; + +interface LoggerConfig { + isVerbose: boolean; + quiet: boolean; +} + +const defaultConfig: LoggerConfig = { isVerbose: false, quiet: false, }; -/** @type {Record<'debug'|'recommendation'|'warning'|'deprecation', Array>} */ -let messages; -let config = {}; +let messages: Record; +let config: LoggerConfig = { ...defaultConfig }; -const reset = function () { +const reset = function (): void { messages = { debug: [], recommendation: [], @@ -29,7 +35,7 @@ const reset = function () { }; reset(); -function log(message) { +function log(message: string): void { if (config.quiet) { return; } @@ -38,7 +44,7 @@ function log(message) { } export default { - debug(message) { + debug(message: string): void { messages.debug.push(message); if (config.isVerbose) { @@ -46,40 +52,37 @@ export default { } }, - recommendation(message) { + recommendation(message: string): void { messages.recommendation.push(message); log(`${pc.bgBlue(pc.white(' RECOMMEND '))} ${message}`); }, - warning(message) { + warning(message: string): void { messages.warning.push(message); log(`${pc.bgYellow(pc.black(' WARNING '))} ${pc.yellow(message)}`); }, - deprecation(message) { + deprecation(message: string): void { messages.deprecation.push(message); log(`${pc.bgYellow(pc.black(' DEPRECATION '))} ${pc.yellow(message)}`); }, - /** - * @returns {Record<'debug'|'recommendation'|'warning'|'deprecation', Array>} - */ - getMessages() { + getMessages(): Record { return messages; }, - quiet(setQuiet = true) { + quiet(setQuiet = true): void { config.quiet = setQuiet; }, - verbose(setVerbose = true) { + verbose(setVerbose = true): void { config.isVerbose = setVerbose; }, - reset() { + reset(): void { reset(); }, }; diff --git a/lib/package-helper.js b/lib/package-helper.ts similarity index 69% rename from lib/package-helper.js rename to lib/package-helper.ts index db8ab287..6dabe2f1 100644 --- a/lib/package-helper.js +++ b/lib/package-helper.ts @@ -13,11 +13,34 @@ import { createRequire } from 'module'; import pc from 'picocolors'; import semver from 'semver'; -import logger from './logger.js'; +import packageJson from '../package.json' with { type: 'json' }; +import logger from './logger.ts'; +// `createRequire` is still needed for the dynamic `require('/package.json')` +// lookups in getPackageVersion() (arbitrary installed packages, not a static import). const require = createRequire(import.meta.url); -function ensurePackagesExist(packagesConfig, requestedFeature) { +export interface PackageConfig { + name: string; + version?: string; + enforce_version?: boolean; +} + +/** + * A list of package configs, where each entry is either a single package or a + * group of interchangeable alternatives (e.g. sass / sass-embedded / node-sass). + */ +export type PackagesConfig = Array; + +/** A single package or an arbitrarily-nested list of them (used for recursion). */ +type NestedPackagesConfig = PackageConfig | NestedPackagesConfig[]; + +export interface PackageRecommendation { + message: string; + installCommand: string; +} + +function ensurePackagesExist(packagesConfig: PackagesConfig, requestedFeature: string): void { const missingPackagesRecommendation = getMissingPackageRecommendations( packagesConfig, requestedFeature @@ -37,11 +60,11 @@ ${missingPackagesRecommendation.message} } } -function getInstallCommand(packageConfigs) { +function getInstallCommand(packageConfigs: PackageConfig[][]): string { const hasPnpmLockfile = fs.existsSync('pnpm-lock.yaml'); const hasYarnLockfile = fs.existsSync('yarn.lock'); const packageInstallStrings = packageConfigs.map((packageConfig) => { - const firstPackage = packageConfig[0]; + const firstPackage = packageConfig[0]!; if (typeof firstPackage.version === 'undefined') { return firstPackage.name; @@ -50,7 +73,7 @@ function getInstallCommand(packageConfigs) { // e.g. ^4.0||^5.0: use the latest version let recommendedVersion = firstPackage.version; if (recommendedVersion.includes('||')) { - recommendedVersion = recommendedVersion.split('|').pop().trim(); + recommendedVersion = recommendedVersion.split('|').pop()!.trim(); } // recommend the version included in our package.json file @@ -68,7 +91,7 @@ function getInstallCommand(packageConfigs) { return pc.yellow(`npm install ${packageInstallStrings.join(' ')} --save-dev`); } -function isPackageInstalled(packageConfig) { +function isPackageInstalled(packageConfig: PackageConfig): boolean { try { import.meta.resolve(packageConfig.name); return true; @@ -77,21 +100,19 @@ function isPackageInstalled(packageConfig) { } } -/** - * - * @param {string} packageName - * @returns {null|string} - */ -function getPackageVersion(packageName) { +function getPackageVersion(packageName: string): string | null { try { - return require(`${packageName}/package.json`).version; + return (require(`${packageName}/package.json`) as { version: string }).version; } catch { return null; } } -function getMissingPackageRecommendations(packagesConfig, requestedFeature = null) { - let missingPackageConfigs = []; +function getMissingPackageRecommendations( + packagesConfig: PackagesConfig, + requestedFeature: string | null = null +): PackageRecommendation | undefined { + const missingPackageConfigs: PackageConfig[][] = []; for (let packageConfig of packagesConfig) { if (!Array.isArray(packageConfig)) { @@ -134,10 +155,10 @@ function getMissingPackageRecommendations(packagesConfig, requestedFeature = nul }; } -function getInvalidPackageVersionRecommendations(packagesConfig) { - const processPackagesConfig = (packageConfig) => { +function getInvalidPackageVersionRecommendations(packagesConfig: PackagesConfig): string[] { + const processPackagesConfig = (packageConfig: NestedPackagesConfig): string[] => { if (Array.isArray(packageConfig)) { - let messages = []; + let messages: string[] = []; for (const config of packageConfig) { messages = messages.concat(processPackagesConfig(config)); @@ -177,17 +198,15 @@ function getInvalidPackageVersionRecommendations(packagesConfig) { return processPackagesConfig(packagesConfig); } -function addPackagesVersionConstraint(packages) { - const packageJsonData = require('../package.json'); - const addConstraint = (packageData) => { - if (Array.isArray(packageData)) { - return packageData.map(addConstraint); - } - +function addPackagesVersionConstraint(packages: PackagesConfig): PackagesConfig { + // packageJson.peerDependencies is inferred with literal keys; widen it to a + // string->version map so it can be looked up by an arbitrary package name. + const peerDependencies: Record = packageJson.peerDependencies; + const addConstraint = (packageData: PackageConfig): PackageConfig => { const newData = Object.assign({}, packageData); if (packageData.enforce_version) { - if (!packageJsonData.peerDependencies) { + if (!peerDependencies) { logger.warning( 'Could not find peerDependencies key on @symfony/webpack-encore package' ); @@ -198,19 +217,21 @@ function addPackagesVersionConstraint(packages) { // this method only supports peerDependencies due to how it's used: // it's mean to inform the user what deps they need to install // for optional features - if (!packageJsonData.peerDependencies[packageData.name]) { + if (!peerDependencies[packageData.name]) { throw new Error( `Could not find package ${packageData.name} in peerDependencies of @symfony/webpack-encore` ); } - newData.version = packageJsonData.peerDependencies[packageData.name]; + newData.version = peerDependencies[packageData.name]; delete newData['enforce_version']; } return newData; }; - return packages.map(addConstraint); + return packages.map((packageData) => + Array.isArray(packageData) ? packageData.map(addConstraint) : addConstraint(packageData) + ); } export default { diff --git a/lib/plugins/entry-files-manifest.ts b/lib/plugins/entry-files-manifest.ts index 8de96756..dd99e7cb 100644 --- a/lib/plugins/entry-files-manifest.ts +++ b/lib/plugins/entry-files-manifest.ts @@ -20,7 +20,7 @@ export default function ( plugins.push({ plugin: new EntryPointsPlugin({ publicPath: webpackConfig.getRealPublicPath(), - outputPath: webpackConfig.outputPath, + outputPath: webpackConfig.outputPath!, integrityAlgorithms: webpackConfig.integrityAlgorithms, }), priority: PluginPriorities.EntryPointsPlugin, diff --git a/lib/plugins/notifier.ts b/lib/plugins/notifier.ts index aea854bf..a9945b05 100644 --- a/lib/plugins/notifier.ts +++ b/lib/plugins/notifier.ts @@ -9,7 +9,7 @@ import type { WebpackPluginInstance } from 'webpack'; -import pluginFeatures from '../features.js'; +import pluginFeatures from '../features.ts'; import applyOptionsCallback from '../utils/apply-options-callback.ts'; import type WebpackConfig from '../WebpackConfig.js'; import PluginPriorities from './plugin-priorities.ts'; diff --git a/lib/utils/get-vue-version.ts b/lib/utils/get-vue-version.ts index 4deb4bd2..fda712f5 100644 --- a/lib/utils/get-vue-version.ts +++ b/lib/utils/get-vue-version.ts @@ -9,8 +9,8 @@ import semver from 'semver'; -import logger from '../logger.js'; -import packageHelper from '../package-helper.js'; +import logger from '../logger.ts'; +import packageHelper from '../package-helper.ts'; import type WebpackConfig from '../WebpackConfig.js'; export default function (webpackConfig: WebpackConfig): number | string | null { diff --git a/lib/utils/minifier-check.ts b/lib/utils/minifier-check.ts index a4cd40ac..e89be55f 100644 --- a/lib/utils/minifier-check.ts +++ b/lib/utils/minifier-check.ts @@ -9,7 +9,7 @@ import MinimizerPlugin from 'minimizer-webpack-plugin'; -import Features from '../features.js'; +import Features from '../features.ts'; const JS_MINIFIER_FEATURES = new Map([ [MinimizerPlugin.esbuildMinify, 'minify-js-esbuild'], diff --git a/package.json b/package.json index 298cf40a..7ce8c345 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "@tsconfig/node22": "^22.0.5", "@types/node": "^22.18.0", "@types/semver": "^7.7.1", + "@types/tmp": "^0.2.6", "@types/yargs-parser": "21.0.3", "@vue/babel-plugin-jsx": "^3.0.0", "@vue/compiler-sfc": "^3.2.14", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 117d81d0..87a4fe3d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -93,6 +93,9 @@ importers: '@types/semver': specifier: ^7.7.1 version: 7.7.1 + '@types/tmp': + specifier: ^0.2.6 + version: 0.2.6 '@types/yargs-parser': specifier: 21.0.3 version: 21.0.3 @@ -1695,6 +1698,9 @@ packages: '@types/sockjs@0.3.36': resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} + '@types/tmp@0.2.6': + resolution: {integrity: sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==} + '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -6475,6 +6481,8 @@ snapshots: dependencies: '@types/node': 22.20.0 + '@types/tmp@0.2.6': {} + '@types/trusted-types@2.0.7': {} '@types/webpack-env@1.18.8': {} diff --git a/test/WebpackConfig.js b/test/WebpackConfig.js index 8c78e8d9..c7ee85d3 100644 --- a/test/WebpackConfig.js +++ b/test/WebpackConfig.js @@ -14,8 +14,8 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import webpack from 'webpack'; import RuntimeConfig from '../lib/config/RuntimeConfig.ts'; -import logger from '../lib/logger.js'; -import WebpackConfig from '../lib/WebpackConfig.js'; +import logger from '../lib/logger.ts'; +import WebpackConfig from '../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/config-generator.js b/test/config-generator.js index b9da1e2b..83f04c47 100644 --- a/test/config-generator.js +++ b/test/config-generator.js @@ -15,10 +15,10 @@ import { describe, it, expect, beforeEach, beforeAll, afterAll } from 'vitest'; import webpack from 'webpack'; import { WebpackManifestPlugin } from 'webpack-manifest-plugin'; -import configGenerator from '../lib/config-generator.js'; +import configGenerator from '../lib/config-generator.ts'; import RuntimeConfig from '../lib/config/RuntimeConfig.ts'; -import logger from '../lib/logger.js'; -import WebpackConfig from '../lib/WebpackConfig.js'; +import logger from '../lib/logger.ts'; +import WebpackConfig from '../lib/WebpackConfig.ts'; const isWindows = process.platform === 'win32'; diff --git a/test/config/parse-runtime.js b/test/config/parse-runtime.js index 441a54a9..8ab4a29a 100644 --- a/test/config/parse-runtime.js +++ b/test/config/parse-runtime.js @@ -14,7 +14,7 @@ import { describe, it, expect } from 'vitest'; import yargsParser from 'yargs-parser'; import parseArgv from '../../lib/config/parse-runtime.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; import * as testSetup from '../helpers/setup.js'; function createArgv(argv) { diff --git a/test/config/path-util.js b/test/config/path-util.js index 5a773992..ebc08e05 100644 --- a/test/config/path-util.js +++ b/test/config/path-util.js @@ -11,10 +11,10 @@ import process from 'process'; import { describe, it, expect } from 'vitest'; -import configGenerator from '../../lib/config-generator.js'; +import configGenerator from '../../lib/config-generator.ts'; import pathUtil from '../../lib/config/path-util.ts'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/config/validator.js b/test/config/validator.js index 39d3ff21..d0629bbf 100644 --- a/test/config/validator.js +++ b/test/config/validator.js @@ -11,8 +11,8 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import validator from '../../lib/config/validator.ts'; -import logger from '../../lib/logger.js'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import logger from '../../lib/logger.ts'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/friendly-errors/transformers/missing-loader.js b/test/friendly-errors/transformers/missing-loader.js index 230d3f74..7d3ba4a5 100644 --- a/test/friendly-errors/transformers/missing-loader.js +++ b/test/friendly-errors/transformers/missing-loader.js @@ -11,7 +11,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../../lib/config/RuntimeConfig.ts'; import transformFactory from '../../../lib/friendly-errors/transformers/missing-loader.ts'; -import WebpackConfig from '../../../lib/WebpackConfig.js'; +import WebpackConfig from '../../../lib/WebpackConfig.ts'; const runtimeConfig = new RuntimeConfig(); runtimeConfig.context = import.meta.dirname; diff --git a/test/functional.js b/test/functional.js index 39e5fc52..ae94b768 100644 --- a/test/functional.js +++ b/test/functional.js @@ -16,7 +16,7 @@ import puppeteer from 'puppeteer'; import semver from 'semver'; import { afterAll, beforeAll, chai, describe, expect, it } from 'vitest'; -import packageHelper from '../lib/package-helper.js'; +import packageHelper from '../lib/package-helper.ts'; import getVueVersion from '../lib/utils/get-vue-version.ts'; import { assertWarning } from './helpers/logger-assert.js'; import * as testSetup from './helpers/setup.js'; diff --git a/test/helpers/logger-assert.js b/test/helpers/logger-assert.js index 3ac665d6..15e709f2 100644 --- a/test/helpers/logger-assert.js +++ b/test/helpers/logger-assert.js @@ -6,7 +6,7 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -import logger from '../../lib/logger.js'; +import logger from '../../lib/logger.ts'; /** * @param {string} expectedMessage diff --git a/test/helpers/setup.js b/test/helpers/setup.js index 2f37795d..fc55cec2 100644 --- a/test/helpers/setup.js +++ b/test/helpers/setup.js @@ -13,10 +13,10 @@ import fs from 'fs-extra'; import httpServer from 'http-server'; import webpack from 'webpack'; -import configGenerator from '../../lib/config-generator.js'; +import configGenerator from '../../lib/config-generator.ts'; import parseRuntime from '../../lib/config/parse-runtime.ts'; import validator from '../../lib/config/validator.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; import { Assert } from './assert.js'; const tmpDir = path.join(import.meta.dirname, '../', '../', 'test_tmp'); diff --git a/test/loaders/babel.js b/test/loaders/babel.js index fa180589..90612d65 100644 --- a/test/loaders/babel.js +++ b/test/loaders/babel.js @@ -13,7 +13,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import babelLoader from '../../lib/loaders/babel.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/loaders/css-extract.js b/test/loaders/css-extract.js index 6c60c010..f47dba03 100644 --- a/test/loaders/css-extract.js +++ b/test/loaders/css-extract.js @@ -12,7 +12,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import cssExtractLoader from '../../lib/loaders/css-extract.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/loaders/css.js b/test/loaders/css.js index 734ba403..a8f93020 100644 --- a/test/loaders/css.js +++ b/test/loaders/css.js @@ -11,7 +11,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import cssLoader from '../../lib/loaders/css.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/loaders/handlebars.js b/test/loaders/handlebars.js index faa04d73..9bdb31bc 100644 --- a/test/loaders/handlebars.js +++ b/test/loaders/handlebars.js @@ -11,7 +11,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import handlebarsLoader from '../../lib/loaders/handlebars.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/loaders/less.js b/test/loaders/less.js index c5c06a99..302d197b 100644 --- a/test/loaders/less.js +++ b/test/loaders/less.js @@ -12,7 +12,7 @@ import { vi, describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import cssLoader from '../../lib/loaders/css.ts'; import lessLoader from '../../lib/loaders/less.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/loaders/sass.js b/test/loaders/sass.js index 124cb786..a684308c 100644 --- a/test/loaders/sass.js +++ b/test/loaders/sass.js @@ -12,7 +12,7 @@ import { vi, describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import cssLoader from '../../lib/loaders/css.ts'; import sassLoader from '../../lib/loaders/sass.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/loaders/stylus.js b/test/loaders/stylus.js index 925d836c..ad6fdcb6 100644 --- a/test/loaders/stylus.js +++ b/test/loaders/stylus.js @@ -12,7 +12,7 @@ import { vi, describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import cssLoader from '../../lib/loaders/css.ts'; import stylusLoader from '../../lib/loaders/stylus.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/loaders/typescript.js b/test/loaders/typescript.js index 99d4a324..5570a914 100644 --- a/test/loaders/typescript.js +++ b/test/loaders/typescript.js @@ -11,7 +11,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import tsLoader from '../../lib/loaders/typescript.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/loaders/vue.js b/test/loaders/vue.js index 3c9828c1..9915da08 100644 --- a/test/loaders/vue.js +++ b/test/loaders/vue.js @@ -11,7 +11,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import vueLoader from '../../lib/loaders/vue.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/logger.js b/test/logger.js index 19099d01..f8bcbd13 100644 --- a/test/logger.js +++ b/test/logger.js @@ -9,9 +9,9 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; -import context from '../lib/context.js'; +import context from '../lib/context.ts'; context.runtimeConfig = {}; -import logger from '../lib/logger.js'; +import logger from '../lib/logger.ts'; describe('logger', function () { beforeEach(function () { diff --git a/test/package-helper.js b/test/package-helper.js index 3cdfa4e0..4958e093 100644 --- a/test/package-helper.js +++ b/test/package-helper.js @@ -14,7 +14,7 @@ import process from 'process'; import stripAnsi from 'strip-ansi'; import { describe, it, expect, afterAll } from 'vitest'; -import packageHelper from '../lib/package-helper.js'; +import packageHelper from '../lib/package-helper.ts'; describe('package-helper', function () { const baseCwd = process.cwd(); diff --git a/test/plugins/css-minimizer.js b/test/plugins/css-minimizer.js index a2d63aa8..e5c007b8 100644 --- a/test/plugins/css-minimizer.js +++ b/test/plugins/css-minimizer.js @@ -11,7 +11,7 @@ import MinimizerPlugin from 'minimizer-webpack-plugin'; import { describe, it, expect, vi, beforeEach } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; const { checkCssMinifierPackages } = vi.hoisted(() => ({ checkCssMinifierPackages: vi.fn(), diff --git a/test/plugins/define.js b/test/plugins/define.js index c2c14bff..5e7cf880 100644 --- a/test/plugins/define.js +++ b/test/plugins/define.js @@ -12,7 +12,7 @@ import webpack from 'webpack'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import definePluginUtil from '../../lib/plugins/define.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig(environment = 'production') { const runtimeConfig = new RuntimeConfig(); diff --git a/test/plugins/forked-ts-types.js b/test/plugins/forked-ts-types.js index c10a12fb..621fb60b 100644 --- a/test/plugins/forked-ts-types.js +++ b/test/plugins/forked-ts-types.js @@ -13,7 +13,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import tsLoader from '../../lib/loaders/typescript.ts'; import tsTypeChecker from '../../lib/plugins/forked-ts-types.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/plugins/friendly-errors.js b/test/plugins/friendly-errors.js index c4bf9941..5edad47d 100644 --- a/test/plugins/friendly-errors.js +++ b/test/plugins/friendly-errors.js @@ -12,7 +12,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import friendlyErrorsPluginUtil from '../../lib/plugins/friendly-errors.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/plugins/js-minimizer.js b/test/plugins/js-minimizer.js index e8bcd3be..dd0b326f 100644 --- a/test/plugins/js-minimizer.js +++ b/test/plugins/js-minimizer.js @@ -11,7 +11,7 @@ import MinimizerPlugin from 'minimizer-webpack-plugin'; import { describe, it, expect, vi, beforeEach } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; const { checkJsMinifierPackages } = vi.hoisted(() => ({ checkJsMinifierPackages: vi.fn(), diff --git a/test/plugins/manifest.js b/test/plugins/manifest.js index 30115827..0237e477 100644 --- a/test/plugins/manifest.js +++ b/test/plugins/manifest.js @@ -12,7 +12,7 @@ import { WebpackManifestPlugin } from 'webpack-manifest-plugin'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import manifestPluginUtil from '../../lib/plugins/manifest.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/plugins/mini-css-extract.js b/test/plugins/mini-css-extract.js index 6529630f..75c1962c 100644 --- a/test/plugins/mini-css-extract.js +++ b/test/plugins/mini-css-extract.js @@ -12,7 +12,7 @@ import { describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import miniCssExtractPluginUtil from '../../lib/plugins/mini-css-extract.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/plugins/notifier.js b/test/plugins/notifier.js index a50c423e..7a5245d5 100644 --- a/test/plugins/notifier.js +++ b/test/plugins/notifier.js @@ -12,7 +12,7 @@ import WebpackNotifier from 'webpack-notifier'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; import notifierPluginUtil from '../../lib/plugins/notifier.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; function createConfig() { const runtimeConfig = new RuntimeConfig(); diff --git a/test/utils/get-vue-version.js b/test/utils/get-vue-version.js index a305de04..fa271a8c 100644 --- a/test/utils/get-vue-version.js +++ b/test/utils/get-vue-version.js @@ -10,9 +10,9 @@ import { vi, describe, it, expect } from 'vitest'; import RuntimeConfig from '../../lib/config/RuntimeConfig.ts'; -import packageHelper from '../../lib/package-helper.js'; +import packageHelper from '../../lib/package-helper.ts'; import getVueVersion from '../../lib/utils/get-vue-version.ts'; -import WebpackConfig from '../../lib/WebpackConfig.js'; +import WebpackConfig from '../../lib/WebpackConfig.ts'; const createWebpackConfig = function () { const runtimeConfig = new RuntimeConfig(); diff --git a/test/utils/minifier-check.js b/test/utils/minifier-check.js index 99f2fcab..a1d7346c 100644 --- a/test/utils/minifier-check.js +++ b/test/utils/minifier-check.js @@ -14,7 +14,7 @@ const { ensurePackagesExistAndAreCorrectVersion } = vi.hoisted(() => ({ ensurePackagesExistAndAreCorrectVersion: vi.fn(), })); -vi.mock('../../lib/features.js', () => ({ +vi.mock('../../lib/features.ts', () => ({ default: { ensurePackagesExistAndAreCorrectVersion }, })); diff --git a/test/vitest-setup.js b/test/vitest-setup.js index 1bf03928..2dbdfadc 100644 --- a/test/vitest-setup.js +++ b/test/vitest-setup.js @@ -9,7 +9,7 @@ import { vi, beforeEach, afterEach } from 'vitest'; -import logger from '../lib/logger.js'; +import logger from '../lib/logger.ts'; beforeEach(() => { logger.reset(); From 753e14d451958b1ece7243a75bf84942aaa1bda7 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Wed, 1 Jul 2026 08:39:12 +0200 Subject: [PATCH 10/12] [TypeScript] Migrate `index.js` (#1511) --- index.js => index.ts | 564 +++++++++++++++++++++---------------------- package.json | 2 +- test/index.js | 2 +- 3 files changed, 275 insertions(+), 293 deletions(-) rename index.js => index.ts (76%) diff --git a/index.js b/index.ts similarity index 76% rename from index.js rename to index.ts index bbd3e6d6..58bc0d98 100644 --- a/index.js +++ b/index.ts @@ -7,33 +7,29 @@ * file that was distributed with this source code. */ -/** - * @import webpack from 'webpack' - */ - -/** - * @import { OptionsCallback } from './lib/utils/apply-options-callback.js' - */ - -/** - * @import { MinimizerOptionsCallback } from './lib/WebpackConfig.js' - */ - -/** - * @typedef {{from: string, pattern?: RegExp|string, to?: string|null, includeSubdirectories?: boolean, context?: string}} CopyFilesOptions - */ - +import type webpack from 'webpack'; import yargsParser from 'yargs-parser'; import configGenerator from './lib/config-generator.ts'; import parseRuntime from './lib/config/parse-runtime.ts'; +import type RuntimeConfig from './lib/config/RuntimeConfig.js'; import validator from './lib/config/validator.ts'; import context from './lib/context.ts'; import EncoreProxy from './lib/EncoreProxy.ts'; +import type { OptionsCallback } from './lib/utils/apply-options-callback.js'; +import type { MinimizerOptionsCallback } from './lib/WebpackConfig.js'; import WebpackConfig from './lib/WebpackConfig.ts'; -let runtimeConfig = context.runtimeConfig; -let webpackConfig = runtimeConfig ? new WebpackConfig(runtimeConfig) : null; +export interface CopyFilesOptions { + from: string; + pattern?: RegExp | string; + to?: string | null; + includeSubdirectories?: boolean; + context?: string; +} + +let runtimeConfig: RuntimeConfig | null = context.runtimeConfig; +let webpackConfig: WebpackConfig | null = runtimeConfig ? new WebpackConfig(runtimeConfig) : null; class Encore { /** @@ -42,11 +38,10 @@ class Encore { * If relative (e.g. web/build), it will be set relative * to the directory where your package.json lives. * - * @param {string} outputPath - * @returns {Encore} + * @param outputPath */ - setOutputPath(outputPath) { - webpackConfig.setOutputPath(outputPath); + setOutputPath(outputPath: string): this { + webpackConfig!.setOutputPath(outputPath); return this; } @@ -74,11 +69,10 @@ class Encore { * .setManifestKeyPrefix('/build') * ``` * - * @param {string} publicPath - * @returns {Encore} + * @param publicPath */ - setPublicPath(publicPath) { - webpackConfig.setPublicPath(publicPath); + setPublicPath(publicPath: string): this { + webpackConfig!.setPublicPath(publicPath); return this; } @@ -108,11 +102,10 @@ class Encore { * } * ``` * - * @param {string} manifestKeyPrefix - * @returns {Encore} + * @param manifestKeyPrefix */ - setManifestKeyPrefix(manifestKeyPrefix) { - webpackConfig.setManifestKeyPrefix(manifestKeyPrefix); + setManifestKeyPrefix(manifestKeyPrefix: string): this { + webpackConfig!.setManifestKeyPrefix(manifestKeyPrefix); return this; } @@ -129,11 +122,14 @@ class Encore { * }) * ``` * - * @param {OptionsCallback[0]>} definePluginOptionsCallback - * @returns {Encore} + * @param definePluginOptionsCallback */ - configureDefinePlugin(definePluginOptionsCallback = () => {}) { - webpackConfig.configureDefinePlugin(definePluginOptionsCallback); + configureDefinePlugin( + definePluginOptionsCallback: OptionsCallback< + ConstructorParameters[0] + > = () => {} + ): this { + webpackConfig!.configureDefinePlugin(definePluginOptionsCallback); return this; } @@ -150,11 +146,12 @@ class Encore { * }) * ``` * - * @param {OptionsCallback} friendlyErrorsPluginOptionsCallback - * @returns {Encore} + * @param friendlyErrorsPluginOptionsCallback */ - configureFriendlyErrorsPlugin(friendlyErrorsPluginOptionsCallback = () => {}) { - webpackConfig.configureFriendlyErrorsPlugin(friendlyErrorsPluginOptionsCallback); + configureFriendlyErrorsPlugin( + friendlyErrorsPluginOptionsCallback: OptionsCallback = () => {} + ): this { + webpackConfig!.configureFriendlyErrorsPlugin(friendlyErrorsPluginOptionsCallback); return this; } @@ -171,11 +168,12 @@ class Encore { * }) * ``` * - * @param {OptionsCallback} manifestPluginOptionsCallback - * @returns {Encore} + * @param manifestPluginOptionsCallback */ - configureManifestPlugin(manifestPluginOptionsCallback = () => {}) { - webpackConfig.configureManifestPlugin(manifestPluginOptionsCallback); + configureManifestPlugin( + manifestPluginOptionsCallback: OptionsCallback = () => {} + ): this { + webpackConfig!.configureManifestPlugin(manifestPluginOptionsCallback); return this; } @@ -207,11 +205,10 @@ class Encore { * }) * ``` * - * @param {MinimizerOptionsCallback} jsOptionsCallback - * @returns {Encore} + * @param jsOptionsCallback */ - configureJsMinimizerPlugin(jsOptionsCallback = () => {}) { - webpackConfig.configureJsMinimizerPlugin(jsOptionsCallback); + configureJsMinimizerPlugin(jsOptionsCallback: MinimizerOptionsCallback = () => {}): this { + webpackConfig!.configureJsMinimizerPlugin(jsOptionsCallback); return this; } @@ -243,11 +240,12 @@ class Encore { * }) * ``` * - * @param {MinimizerOptionsCallback} cssMinimizerPluginOptionsCallback - * @returns {Encore} + * @param cssMinimizerPluginOptionsCallback */ - configureCssMinimizerPlugin(cssMinimizerPluginOptionsCallback = () => {}) { - webpackConfig.configureCssMinimizerPlugin(cssMinimizerPluginOptionsCallback); + configureCssMinimizerPlugin( + cssMinimizerPluginOptionsCallback: MinimizerOptionsCallback = () => {} + ): this { + webpackConfig!.configureCssMinimizerPlugin(cssMinimizerPluginOptionsCallback); return this; } @@ -263,14 +261,13 @@ class Encore { * If the JavaScript file imports/requires CSS/Sass/LESS files, * then a CSS file (e.g. main.css) will also be output. * - * @param {string} name The name (without extension) that will be used + * @param name The name (without extension) that will be used * as the output filename (e.g. app will become app.js) * in the output directory. - * @param {string|string[]} src The path to the source file (or files) - * @returns {Encore} + * @param src The path to the source file (or files) */ - addEntry(name, src) { - webpackConfig.addEntry(name, src); + addEntry(name: string, src: string | string[]): this { + webpackConfig!.addEntry(name, src); return this; } @@ -289,15 +286,14 @@ class Encore { * If the JavaScript files imports/requires CSS/Sass/LESS files, * then a CSS file (e.g. main.css) will also be output. * - * @param {Record} entries where the Keys are the + * @param entries where the Keys are the * names (without extension) that will be used * as the output filename (e.g. app will become app.js) * in the output directory. The values are the path(s) * to the source file(s). - * @returns {Encore} */ - addEntries(entries) { - webpackConfig.addEntries(entries); + addEntries(entries: Record): this { + webpackConfig!.addEntries(entries); return this; } @@ -315,14 +311,13 @@ class Encore { * is to use addEntry() and then require/import your CSS files from * within your JavaScript files. * - * @param {string} name The name (without extension) that will be used + * @param name The name (without extension) that will be used * as the output filename (e.g. app will become app.css) * in the output directory. - * @param {string|string[]} src The path to the source file (or files) - * @returns {Encore} + * @param src The path to the source file (or files) */ - addStyleEntry(name, src) { - webpackConfig.addStyleEntry(name, src); + addStyleEntry(name: string, src: string | string[]): this { + webpackConfig!.addStyleEntry(name, src); return this; } @@ -363,12 +358,11 @@ class Encore { * Encore.addPlugin(new MyWebpackPlugin(), PluginPriorities.DefinePlugin); * ``` * - * @param {webpack.WebpackPluginInstance} plugin - * @param {number} priority - * @returns {Encore} + * @param plugin + * @param priority */ - addPlugin(plugin, priority = 0) { - webpackConfig.addPlugin(plugin, priority); + addPlugin(plugin: webpack.WebpackPluginInstance, priority = 0): this { + webpackConfig!.addPlugin(plugin, priority); return this; } @@ -376,11 +370,10 @@ class Encore { /** * Adds a custom loader config * - * @param {webpack.RuleSetRule} loader The loader config object - * @returns {Encore} + * @param loader The loader config object */ - addLoader(loader) { - webpackConfig.addLoader(loader); + addLoader(loader: webpack.RuleSetRule): this { + webpackConfig!.addLoader(loader); return this; } @@ -388,10 +381,9 @@ class Encore { /** * Alias to addLoader * - * @param {webpack.RuleSetRule} rule - * @returns {Encore} + * @param rule */ - addRule(rule) { + addRule(rule: webpack.RuleSetRule): this { this.addLoader(rule); return this; @@ -412,11 +404,10 @@ class Encore { * }) * ``` * - * @param {Record} aliases - * @returns {Encore} + * @param aliases */ - addAliases(aliases) { - webpackConfig.addAliases(aliases); + addAliases(aliases: Record): this { + webpackConfig!.addAliases(aliases); return this; } @@ -451,11 +442,10 @@ class Encore { * ]); * ``` * - * @param {webpack.Externals} externals - * @returns {Encore} + * @param externals */ - addExternals(externals) { - webpackConfig.addExternals(externals); + addExternals(externals: webpack.ExternalItem | webpack.ExternalItem[]): this { + webpackConfig!.addExternals(externals); return this; } @@ -477,11 +467,10 @@ class Encore { * Encore.enableVersioning(Encore.isProduction()); * ``` * - * @param {boolean} enabled - * @returns {Encore} + * @param enabled */ - enableVersioning(enabled = true) { - webpackConfig.enableVersioning(enabled); + enableVersioning(enabled = true): this { + webpackConfig!.enableVersioning(enabled); return this; } @@ -505,11 +494,10 @@ class Encore { * Encore.enableSourceMaps(!Encore.isProduction()); * ``` * - * @param {boolean} enabled - * @returns {Encore} + * @param enabled */ - enableSourceMaps(enabled = true) { - webpackConfig.enableSourceMaps(enabled); + enableSourceMaps(enabled = true): this { + webpackConfig!.enableSourceMaps(enabled); return this; } @@ -551,12 +539,14 @@ class Encore { * - `enforce` set to `true` * - `name` set to the value of the "name" parameter * - * @param {string} name The chunk name (e.g. vendor to create a vendor.js) - * @param {object} options Cache group option - * @returns {Encore} + * @param name The chunk name (e.g. vendor to create a vendor.js) + * @param options Cache group option */ - addCacheGroup(name, options) { - webpackConfig.addCacheGroup(name, options); + addCacheGroup( + name: string, + options: { test?: RegExp; node_modules?: string[]; [key: string]: unknown } + ): this { + webpackConfig!.addCacheGroup(name, options); return this; } @@ -623,11 +613,10 @@ class Encore { * - {string} context (default: path of the source directory) * The context to use as a root path when copying files. * - * @param {CopyFilesOptions|CopyFilesOptions[]} configs - * @returns {Encore} + * @param configs */ - copyFiles(configs) { - webpackConfig.copyFiles(configs); + copyFiles(configs: CopyFilesOptions | CopyFilesOptions[]): this { + webpackConfig!.copyFiles(configs); return this; } @@ -654,11 +643,9 @@ class Encore { * to be able to "initialize" some jQuery plugins, because the * jQuery required by the other entry will be a different instance, * and so won't have the plugins initialized on it. - * - * @returns {Encore} */ - enableSingleRuntimeChunk() { - webpackConfig.enableSingleRuntimeChunk(); + enableSingleRuntimeChunk(): this { + webpackConfig!.enableSingleRuntimeChunk(); return this; } @@ -667,11 +654,9 @@ class Encore { * Tell Webpack to *not* output a separate runtime.js file. * * See enableSingleRuntimeChunk() for more details. - * - * @returns {Encore} */ - disableSingleRuntimeChunk() { - webpackConfig.disableSingleRuntimeChunk(); + disableSingleRuntimeChunk(): this { + webpackConfig!.disableSingleRuntimeChunk(); return this; } @@ -687,11 +672,9 @@ class Encore { * * This is a performance optimization, but requires extra * work (described above) to support this. - * - * @returns {Encore} */ - splitEntryChunks() { - webpackConfig.splitEntryChunks(); + splitEntryChunks(): this { + webpackConfig!.splitEntryChunks(); return this; } @@ -708,11 +691,10 @@ class Encore { * }); * ``` * - * @param {OptionsCallback} callback - * @returns {Encore} + * @param callback */ - configureSplitChunks(callback) { - webpackConfig.configureSplitChunks(callback); + configureSplitChunks(callback: OptionsCallback): this { + webpackConfig!.configureSplitChunks(callback); return this; } @@ -730,11 +712,12 @@ class Encore { * }); * ``` * - * @param {OptionsCallback>} callback - * @returns {Encore} + * @param callback */ - configureWatchOptions(callback) { - webpackConfig.configureWatchOptions(callback); + configureWatchOptions( + callback: OptionsCallback> + ): this { + webpackConfig!.configureWatchOptions(callback); return this; } @@ -757,11 +740,10 @@ class Encore { * }); * ``` * - * @param {OptionsCallback} callback - * @returns {Encore} + * @param callback */ - configureDevServerOptions(callback) { - webpackConfig.configureDevServerOptions(callback); + configureDevServerOptions(callback: OptionsCallback): this { + webpackConfig!.configureDevServerOptions(callback); return this; } @@ -785,11 +767,10 @@ class Encore { * This is useful for older packages, that might * expect jQuery (or something else) to be a global variable. * - * @param {Record} variables - * @returns {Encore} + * @param variables */ - autoProvideVariables(variables) { - webpackConfig.autoProvideVariables(variables); + autoProvideVariables(variables: Record): this { + webpackConfig!.autoProvideVariables(variables); return this; } @@ -804,11 +785,9 @@ class Encore { * 'window.jQuery': 'jquery' * }); * ``` - * - * @returns {Encore} */ - autoProvidejQuery() { - webpackConfig.autoProvidejQuery(); + autoProvidejQuery(): this { + webpackConfig!.autoProvidejQuery(); return this; } @@ -833,11 +812,10 @@ class Encore { * }) * ``` * - * @param {OptionsCallback} postCssLoaderOptionsCallback - * @returns {Encore} + * @param postCssLoaderOptionsCallback */ - enablePostCssLoader(postCssLoaderOptionsCallback = () => {}) { - webpackConfig.enablePostCssLoader(postCssLoaderOptionsCallback); + enablePostCssLoader(postCssLoaderOptionsCallback: OptionsCallback = () => {}): this { + webpackConfig!.enablePostCssLoader(postCssLoaderOptionsCallback); return this; } @@ -873,12 +851,14 @@ class Encore { * Options parameters for resolve-url-loader * // https://www.npmjs.com/package/resolve-url-loader#options * - * @param {OptionsCallback} sassLoaderOptionsCallback - * @param {{resolveUrlLoader?: boolean, resolveUrlLoaderOptions?: object}} encoreOptions - * @returns {Encore} + * @param sassLoaderOptionsCallback + * @param encoreOptions */ - enableSassLoader(sassLoaderOptionsCallback = () => {}, encoreOptions = {}) { - webpackConfig.enableSassLoader(sassLoaderOptionsCallback, encoreOptions); + enableSassLoader( + sassLoaderOptionsCallback: OptionsCallback = () => {}, + encoreOptions: { resolveUrlLoader?: boolean; resolveUrlLoaderOptions?: object } = {} + ): this { + webpackConfig!.enableSassLoader(sassLoaderOptionsCallback, encoreOptions); return this; } @@ -900,11 +880,10 @@ class Encore { * }); * ``` * - * @param {OptionsCallback} lessLoaderOptionsCallback - * @returns {Encore} + * @param lessLoaderOptionsCallback */ - enableLessLoader(lessLoaderOptionsCallback = () => {}) { - webpackConfig.enableLessLoader(lessLoaderOptionsCallback); + enableLessLoader(lessLoaderOptionsCallback: OptionsCallback = () => {}): this { + webpackConfig!.enableLessLoader(lessLoaderOptionsCallback); return this; } @@ -925,11 +904,10 @@ class Encore { * }); * ``` * - * @param {OptionsCallback} stylusLoaderOptionsCallback - * @returns {Encore} + * @param stylusLoaderOptionsCallback */ - enableStylusLoader(stylusLoaderOptionsCallback = () => {}) { - webpackConfig.enableStylusLoader(stylusLoaderOptionsCallback); + enableStylusLoader(stylusLoaderOptionsCallback: OptionsCallback = () => {}): this { + webpackConfig!.enableStylusLoader(stylusLoaderOptionsCallback); return this; } @@ -1005,12 +983,19 @@ class Encore { * It should contain the version of core-js you added to your project * if useBuiltIns isn't set to false. * - * @param {OptionsCallback|null} callback - * @param {{exclude?: webpack.RuleSetCondition, includeNodeModules?: string[], useBuiltIns?: 'usage' | 'entry' | false, corejs?: number|string|{ version: string, proposals: boolean }|null}} encoreOptions - * @returns {Encore} + * @param callback + * @param encoreOptions */ - configureBabel(callback, encoreOptions = {}) { - webpackConfig.configureBabel(callback, encoreOptions); + configureBabel( + callback: OptionsCallback | null, + encoreOptions: { + exclude?: webpack.RuleSetCondition; + includeNodeModules?: string[]; + useBuiltIns?: 'usage' | 'entry' | false; + corejs?: number | string | { version: string; proposals: boolean } | null; + } = {} + ): this { + webpackConfig!.configureBabel(callback, encoreOptions); return this; } @@ -1031,11 +1016,10 @@ class Encore { * }); * ``` * - * @param {OptionsCallback} callback - * @returns {Encore} + * @param callback */ - configureBabelPresetEnv(callback) { - webpackConfig.configureBabelPresetEnv(callback); + configureBabelPresetEnv(callback: OptionsCallback): this { + webpackConfig!.configureBabelPresetEnv(callback); return this; } @@ -1052,11 +1036,10 @@ class Encore { * }); * ``` * - * @param {OptionsCallback} callback - * @returns {Encore} + * @param callback */ - configureCssLoader(callback) { - webpackConfig.configureCssLoader(callback); + configureCssLoader(callback: OptionsCallback): this { + webpackConfig!.configureCssLoader(callback); return this; } @@ -1064,11 +1047,10 @@ class Encore { /** * If enabled, the Stimulus bridge is used to load Stimulus controllers from PHP packages. * - * @param {string} controllerJsonPath Path to the controllers.json file. - * @returns {Encore} + * @param controllerJsonPath Path to the controllers.json file. */ - enableStimulusBridge(controllerJsonPath) { - webpackConfig.enableStimulusBridge(controllerJsonPath); + enableStimulusBridge(controllerJsonPath: string): this { + webpackConfig!.enableStimulusBridge(controllerJsonPath); return this; } @@ -1094,12 +1076,14 @@ class Encore { * }); * ``` * - * @param {Record} buildDependencies - * @param {OptionsCallback} cacheCallback - * @returns {Encore} + * @param buildDependencies + * @param cacheCallback */ - enableBuildCache(buildDependencies, cacheCallback = (cache) => {}) { - webpackConfig.enableBuildCache(buildDependencies, cacheCallback); + enableBuildCache( + buildDependencies: Record, + cacheCallback: OptionsCallback = (cache) => {} + ): this { + webpackConfig!.enableBuildCache(buildDependencies, cacheCallback); return this; } @@ -1122,12 +1106,16 @@ class Encore { * ); * ``` * - * @param {OptionsCallback} loaderOptionsCallback - * @param {OptionsCallback} pluginOptionsCallback - * @returns {Encore} + * @param loaderOptionsCallback + * @param pluginOptionsCallback */ - configureMiniCssExtractPlugin(loaderOptionsCallback, pluginOptionsCallback = () => {}) { - webpackConfig.configureMiniCssExtractPlugin(loaderOptionsCallback, pluginOptionsCallback); + configureMiniCssExtractPlugin( + loaderOptionsCallback: OptionsCallback, + pluginOptionsCallback: OptionsCallback< + import('mini-css-extract-plugin').PluginOptions + > = () => {} + ): this { + webpackConfig!.configureMiniCssExtractPlugin(loaderOptionsCallback, pluginOptionsCallback); return this; } @@ -1145,11 +1133,10 @@ class Encore { * }); * ``` * - * @param {OptionsCallback} callback - * @returns {Encore} + * @param callback */ - enableReactPreset(callback = () => {}) { - webpackConfig.enableReactPreset(callback); + enableReactPreset(callback: OptionsCallback = () => {}): this { + webpackConfig!.enableReactPreset(callback); return this; } @@ -1169,11 +1156,10 @@ class Encore { * Encore.enablePreactPreset({ preactCompat: true }) * ``` * - * @param {{preactCompat?: boolean}} options - * @returns {Encore} + * @param options */ - enablePreactPreset(options = {}) { - webpackConfig.enablePreactPreset(options); + enablePreactPreset(options: { preactCompat?: boolean } = {}): this { + webpackConfig!.enablePreactPreset(options); return this; } @@ -1197,11 +1183,10 @@ class Encore { * }); * ``` * - * @param {OptionsCallback} callback - * @returns {Encore} + * @param callback */ - enableTypeScriptLoader(callback = () => {}) { - webpackConfig.enableTypeScriptLoader(callback); + enableTypeScriptLoader(callback: OptionsCallback = () => {}): this { + webpackConfig!.enableTypeScriptLoader(callback); return this; } @@ -1212,11 +1197,12 @@ class Encore { * * This is a build optimization API to reduce build times. * - * @param {OptionsCallback} forkedTypeScriptTypesCheckOptionsCallback - * @returns {Encore} + * @param forkedTypeScriptTypesCheckOptionsCallback */ - enableForkedTypeScriptTypesChecking(forkedTypeScriptTypesCheckOptionsCallback = () => {}) { - webpackConfig.enableForkedTypeScriptTypesChecking( + enableForkedTypeScriptTypesChecking( + forkedTypeScriptTypesCheckOptionsCallback: OptionsCallback = () => {} + ): this { + webpackConfig!.enableForkedTypeScriptTypesChecking( forkedTypeScriptTypesCheckOptionsCallback ); @@ -1248,11 +1234,10 @@ class Encore { * }) * ``` * - * @param {object} options - * @returns {Encore} + * @param options */ - enableBabelTypeScriptPreset(options = {}) { - webpackConfig.enableBabelTypeScriptPreset(options); + enableBabelTypeScriptPreset(options: object = {}): this { + webpackConfig!.enableBabelTypeScriptPreset(options); return this; } @@ -1298,12 +1283,18 @@ class Encore { * Configure Babel to use the preset "@vue/babel-preset-jsx", * in order to enable JSX usage in Vue components. * - * @param {OptionsCallback} vueLoaderOptionsCallback - * @param {{useJsx?: boolean, version?: number, runtimeCompilerBuild?: boolean}} encoreOptions - * @returns {Encore} + * @param vueLoaderOptionsCallback + * @param encoreOptions */ - enableVueLoader(vueLoaderOptionsCallback = () => {}, encoreOptions = {}) { - webpackConfig.enableVueLoader(vueLoaderOptionsCallback, encoreOptions); + enableVueLoader( + vueLoaderOptionsCallback: OptionsCallback = () => {}, + encoreOptions: { + useJsx?: boolean; + version?: number | null; + runtimeCompilerBuild?: boolean | null; + } = {} + ): this { + webpackConfig!.enableVueLoader(vueLoaderOptionsCallback, encoreOptions); return this; } @@ -1324,12 +1315,14 @@ class Encore { * }); * ``` * - * @param {boolean} enabled - * @param {OptionsCallback} notifierPluginOptionsCallback - * @returns {Encore} + * @param enabled + * @param notifierPluginOptionsCallback */ - enableBuildNotifications(enabled = true, notifierPluginOptionsCallback = () => {}) { - webpackConfig.enableBuildNotifications(enabled, notifierPluginOptionsCallback); + enableBuildNotifications( + enabled = true, + notifierPluginOptionsCallback: OptionsCallback = () => {} + ): this { + webpackConfig!.enableBuildNotifications(enabled, notifierPluginOptionsCallback); return this; } @@ -1350,11 +1343,10 @@ class Encore { * }); * ``` * - * @param {OptionsCallback} callback - * @returns {Encore} + * @param callback */ - enableHandlebarsLoader(callback = () => {}) { - webpackConfig.enableHandlebarsLoader(callback); + enableHandlebarsLoader(callback: OptionsCallback = () => {}): this { + webpackConfig!.enableHandlebarsLoader(callback); return this; } @@ -1375,11 +1367,10 @@ class Encore { * Internally, this disables the mini-css-extract-plugin * and uses the style-loader instead. * - * @param {boolean} disabled - * @returns {Encore} + * @param disabled */ - disableCssExtraction(disabled = true) { - webpackConfig.disableCssExtraction(disabled); + disableCssExtraction(disabled = true): this { + webpackConfig!.disableCssExtraction(disabled); return this; } @@ -1397,11 +1388,10 @@ class Encore { * }); * ``` * - * @param {OptionsCallback} callback - * @returns {Encore} + * @param callback */ - configureStyleLoader(callback) { - webpackConfig.configureStyleLoader(callback); + configureStyleLoader(callback: OptionsCallback): this { + webpackConfig!.configureStyleLoader(callback); return this; } @@ -1429,11 +1419,10 @@ class Encore { * which is overridden for both fonts and images. See configureImageRule() * and configureFontRule() to control those filenames. * - * @param {{js?: string, css?: string, images?: string, fonts?: string}} filenames - * @returns {Encore} + * @param filenames */ - configureFilenames(filenames) { - webpackConfig.configureFilenames(filenames); + configureFilenames(filenames: { js?: string; css?: string; assets?: string }): this { + webpackConfig!.configureFilenames(filenames); return this; } @@ -1483,12 +1472,19 @@ class Encore { * }); * ``` * - * @param {{filename?: string, maxSize?: number|null, type?: string, enabled?: boolean}} options - * @param {OptionsCallback} ruleCallback - * @returns {Encore} + * @param options + * @param ruleCallback */ - configureImageRule(options = {}, ruleCallback = (rule) => {}) { - webpackConfig.configureImageRule(options, ruleCallback); + configureImageRule( + options: { + filename?: string; + maxSize?: number | null; + type?: string; + enabled?: boolean; + } = {}, + ruleCallback: OptionsCallback = () => {} + ): this { + webpackConfig!.configureImageRule(options, ruleCallback); return this; } @@ -1500,12 +1496,19 @@ class Encore { * * See configureImageRule() for more details. * - * @param {{filename?: string, maxSize?: number|null, type?: string, enabled?: boolean}} options - * @param {OptionsCallback} ruleCallback - * @returns {Encore} + * @param options + * @param ruleCallback */ - configureFontRule(options = {}, ruleCallback = (rule) => {}) { - webpackConfig.configureFontRule(options, ruleCallback); + configureFontRule( + options: { + filename?: string; + maxSize?: number | null; + type?: string; + enabled?: boolean; + } = {}, + ruleCallback: OptionsCallback = () => {} + ): this { + webpackConfig!.configureFontRule(options, ruleCallback); return this; } @@ -1524,12 +1527,11 @@ class Encore { * }); * ``` * - * @param {string} name - * @param {OptionsCallback} callback - * @returns {Encore} + * @param name + * @param callback */ - configureLoaderRule(name, callback) { - webpackConfig.configureLoaderRule(name, callback); + configureLoaderRule(name: string, callback: OptionsCallback): this { + webpackConfig!.configureLoaderRule(name, callback); return this; } @@ -1547,11 +1549,14 @@ class Encore { * }) * ``` * - * @param {OptionsCallback[0], undefined>>} cleanOptionsCallback - * @returns {Encore} + * @param cleanOptionsCallback */ - cleanupOutputBeforeBuild(cleanOptionsCallback = () => {}) { - webpackConfig.cleanupOutputBeforeBuild(cleanOptionsCallback); + cleanupOutputBeforeBuild( + cleanOptionsCallback: OptionsCallback< + Exclude[0], undefined> + > = () => {} + ): this { + webpackConfig!.cleanupOutputBeforeBuild(cleanOptionsCallback); return this; } @@ -1584,41 +1589,34 @@ class Encore { * ); * ``` * - * @param {boolean} enabled - * @param {string|string[]} algorithms - * @returns {Encore} + * @param enabled + * @param algorithms */ - enableIntegrityHashes(enabled = true, algorithms = ['sha384']) { - webpackConfig.enableIntegrityHashes(enabled, algorithms); + enableIntegrityHashes(enabled = true, algorithms: string | string[] = ['sha384']): this { + webpackConfig!.enableIntegrityHashes(enabled, algorithms); return this; } /** * Is this currently a "production" build? - * - * @returns {boolean} */ - isProduction() { - return webpackConfig.isProduction(); + isProduction(): boolean { + return webpackConfig!.isProduction(); } /** * Is this currently a "dev" build? - * - * @returns {boolean} */ - isDev() { - return webpackConfig.isDev(); + isDev(): boolean { + return webpackConfig!.isDev(); } /** * Is this currently a "dev-server" build? - * - * @returns {boolean} */ - isDevServer() { - return webpackConfig.isDevServer(); + isDevServer(): boolean { + return webpackConfig!.isDevServer(); } /** @@ -1632,11 +1630,10 @@ class Encore { * .when(process.argv.includes('--analyze'), (Encore) => Encore.addPlugin(new BundleAnalyzerPlugin())) * ``` * - * @param {(function(Encore): boolean) | boolean} condition - * @param {function(Encore): void} callback - * @returns {Encore} + * @param condition + * @param callback */ - when(condition, callback) { + when(condition: ((encore: this) => boolean) | boolean, callback: (encore: this) => void): this { if ( (typeof condition === 'function' && condition(this)) || (typeof condition === 'boolean' && condition) @@ -1653,13 +1650,11 @@ class Encore { * ``` * export default await Encore.getWebpackConfig(); * ``` - * - * @returns {Promise} */ - async getWebpackConfig() { - validator(webpackConfig); + async getWebpackConfig(): Promise { + validator(webpackConfig!); - return await configGenerator(webpackConfig); + return await configGenerator(webpackConfig!); } /** @@ -1667,10 +1662,8 @@ class Encore { * * getWebpackConfig should be used before resetting to build * a config for the existing state. - * - * @returns {void} */ - reset() { + reset(): void { webpackConfig = new WebpackConfig(runtimeConfig); } @@ -1699,11 +1692,10 @@ class Encore { * Be aware that using this method will also reset the current * webpack configuration. * - * @param {string} environment - * @param {object} options - * @returns {Encore} + * @param environment + * @param options */ - configureRuntimeEnvironment(environment, options = {}) { + configureRuntimeEnvironment(environment: string, options: object = {}): this { runtimeConfig = parseRuntime( Object.assign({}, yargsParser([environment]), options), process.cwd() @@ -1718,10 +1710,8 @@ class Encore { * Check if Encore was either called through * the CLI utility or after being manually initialized * using Encore.configureRuntimeEnvironment. - * - * @returns {boolean} */ - isRuntimeEnvironmentConfigured() { + isRuntimeEnvironmentConfigured(): boolean { return runtimeConfig !== null; } @@ -1730,10 +1720,8 @@ class Encore { * * Be aware that using this method will also reset the * current webpack configuration. - * - * @returns {void} */ - clearRuntimeEnvironment() { + clearRuntimeEnvironment(): void { runtimeConfig = null; webpackConfig = null; } @@ -1742,20 +1730,14 @@ class Encore { * If enabled, the SvelteJs loader is enabled. * * https://github.com/sveltejs/svelte-loader - * - * @returns {Encore} */ - enableSvelte() { - webpackConfig.enableSvelte(); + enableSvelte(): this { + webpackConfig!.enableSvelte(); return this; } } -/** - * Proxy the API in order to prevent calls to most of its methods - * if the webpackConfig object hasn't been initialized yet. - * - * @type {Encore} - */ +// Proxy the API in order to prevent calls to most of its methods +// if the webpackConfig object hasn't been initialized yet. export default EncoreProxy.createProxy(new Encore()); diff --git a/package.json b/package.json index 7ce8c345..e0902de0 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "prepublishOnly": "pnpm type-check", "pretest": "pnpm build", "test": "vitest run", - "lint": "eslint lib test index.js eslint.config.js --report-unused-disable-directives --max-warnings=0", + "lint": "eslint lib test index.ts eslint.config.js --report-unused-disable-directives --max-warnings=0", "fmt": "oxfmt", "fmt:check": "oxfmt --check" }, diff --git a/test/index.js b/test/index.js index 74e5fede..d55a2f2a 100644 --- a/test/index.js +++ b/test/index.js @@ -11,7 +11,7 @@ import path from 'path'; import { vi, describe, it, expect, beforeEach } from 'vitest'; -import api from '../index.js'; +import api from '../index.ts'; describe('Public API', function () { beforeEach(function () { From 20ea3e27aefd0f5aac37d213c4e8295584c9bdfe Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Sat, 4 Jul 2026 09:20:39 +0200 Subject: [PATCH 11/12] [TypeScript] Use .js import specifiers and drop TS-extension tsconfig options (#1512) --- bin/{encore.js => encore.ts} | 8 +-- eslint.config.js | 5 -- index.ts | 12 ++-- lib/EncoreProxy.ts | 2 +- lib/WebpackConfig.ts | 8 +-- lib/config-generator.ts | 56 +++++++++---------- lib/config/parse-runtime.ts | 5 +- lib/config/path-util.ts | 5 +- lib/config/validator.ts | 4 +- lib/features.ts | 2 +- .../formatters/missing-loader.ts | 2 +- .../transformers/missing-loader.ts | 2 +- lib/loaders/babel.ts | 4 +- lib/loaders/css-extract.ts | 2 +- lib/loaders/css.ts | 4 +- lib/loaders/handlebars.ts | 4 +- lib/loaders/less.ts | 6 +- lib/loaders/sass.ts | 6 +- lib/loaders/stylus.ts | 6 +- lib/loaders/typescript.ts | 6 +- lib/loaders/vue.ts | 6 +- lib/package-helper.ts | 2 +- lib/plugins/asset-output-display.ts | 6 +- lib/plugins/css-minimizer.ts | 4 +- lib/plugins/define.ts | 4 +- lib/plugins/delete-unused-entries.ts | 6 +- lib/plugins/entry-files-manifest.ts | 4 +- lib/plugins/forked-ts-types.ts | 4 +- lib/plugins/friendly-errors.ts | 14 ++--- lib/plugins/js-minimizer.ts | 4 +- lib/plugins/manifest.ts | 8 +-- lib/plugins/mini-css-extract.ts | 4 +- lib/plugins/notifier.ts | 6 +- lib/plugins/variable-provider.ts | 2 +- lib/plugins/vue.ts | 2 +- lib/shims.d.ts | 14 +++++ lib/utils/get-vue-version.ts | 4 +- lib/utils/minifier-check.ts | 2 +- lib/webpack/entry-points-plugin.ts | 2 +- tsconfig.json | 2 - 40 files changed, 125 insertions(+), 124 deletions(-) rename bin/{encore.js => encore.ts} (95%) mode change 100755 => 100644 create mode 100644 lib/shims.d.ts diff --git a/bin/encore.js b/bin/encore.ts old mode 100755 new mode 100644 similarity index 95% rename from bin/encore.js rename to bin/encore.ts index 7cab1b30..3eb69f3a --- a/bin/encore.js +++ b/bin/encore.ts @@ -11,10 +11,10 @@ import pc from 'picocolors'; import yargsParser from 'yargs-parser'; -import parseRuntime from '../lib/config/parse-runtime.ts'; -import context from '../lib/context.ts'; -import featuresHelper from '../lib/features.ts'; -import logger from '../lib/logger.ts'; +import parseRuntime from '../lib/config/parse-runtime.js'; +import context from '../lib/context.js'; +import featuresHelper from '../lib/features.js'; +import logger from '../lib/logger.js'; const runtimeConfig = parseRuntime(yargsParser(process.argv.slice(2)), process.cwd()); context.runtimeConfig = runtimeConfig; diff --git a/eslint.config.js b/eslint.config.js index 8620fdf3..639c6f92 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -102,11 +102,6 @@ file that was distributed with this source code.`, 'jsdoc/require-returns': 'off', 'jsdoc/require-returns-type': 'off', 'jsdoc/check-param-names': 'off', - // tsc owns module resolution for `.ts` files (strict, build fails on - // a missing import). eslint-plugin-n is not TS-aware: from a `.ts` - // file it rewrites `.js` -> `.ts` and cannot resolve imports of - // not-yet-migrated `.js` modules. `.js` files keep the rule. - 'n/no-missing-import': 'off', }, }, { diff --git a/index.ts b/index.ts index 58bc0d98..459c9ccf 100644 --- a/index.ts +++ b/index.ts @@ -10,15 +10,15 @@ import type webpack from 'webpack'; import yargsParser from 'yargs-parser'; -import configGenerator from './lib/config-generator.ts'; -import parseRuntime from './lib/config/parse-runtime.ts'; +import configGenerator from './lib/config-generator.js'; +import parseRuntime from './lib/config/parse-runtime.js'; import type RuntimeConfig from './lib/config/RuntimeConfig.js'; -import validator from './lib/config/validator.ts'; -import context from './lib/context.ts'; -import EncoreProxy from './lib/EncoreProxy.ts'; +import validator from './lib/config/validator.js'; +import context from './lib/context.js'; +import EncoreProxy from './lib/EncoreProxy.js'; import type { OptionsCallback } from './lib/utils/apply-options-callback.js'; import type { MinimizerOptionsCallback } from './lib/WebpackConfig.js'; -import WebpackConfig from './lib/WebpackConfig.ts'; +import WebpackConfig from './lib/WebpackConfig.js'; export interface CopyFilesOptions { from: string; diff --git a/lib/EncoreProxy.ts b/lib/EncoreProxy.ts index cd034bf3..ea0a8eab 100644 --- a/lib/EncoreProxy.ts +++ b/lib/EncoreProxy.ts @@ -10,7 +10,7 @@ import levenshtein from 'fastest-levenshtein'; import pc from 'picocolors'; -import prettyError from './utils/pretty-error.ts'; +import prettyError from './utils/pretty-error.js'; // Public methods that were removed. We show an explicit migration message instead of relying on // the generic "did you mean" suggestion below, whose closest Levenshtein match would be misleading. diff --git a/lib/WebpackConfig.ts b/lib/WebpackConfig.ts index a60c4b4f..2c0b8e78 100644 --- a/lib/WebpackConfig.ts +++ b/lib/WebpackConfig.ts @@ -14,12 +14,12 @@ import path from 'path'; import type webpack from 'webpack'; import type { CopyFilesOptions } from '../index.js'; -import pathUtil from './config/path-util.ts'; +import pathUtil from './config/path-util.js'; import type RuntimeConfig from './config/RuntimeConfig.js'; -import featuresHelper from './features.ts'; -import logger from './logger.ts'; +import featuresHelper from './features.js'; +import logger from './logger.js'; import type { OptionsCallback } from './utils/apply-options-callback.js'; -import regexpEscaper from './utils/regexp-escaper.ts'; +import regexpEscaper from './utils/regexp-escaper.js'; export type MinimizerPluginOptions = import('minimizer-webpack-plugin').BasePluginOptions & import('minimizer-webpack-plugin').DefinedDefaultMinimizerAndOptions< diff --git a/lib/config-generator.ts b/lib/config-generator.ts index a0f1af62..5d68c4a3 100644 --- a/lib/config-generator.ts +++ b/lib/config-generator.ts @@ -14,36 +14,36 @@ import { fileURLToPath } from 'url'; import tmp from 'tmp'; import type webpack from 'webpack'; -import pathUtil from './config/path-util.ts'; -import babelLoaderUtil from './loaders/babel.ts'; -import cssExtractLoaderUtil from './loaders/css-extract.ts'; +import pathUtil from './config/path-util.js'; +import babelLoaderUtil from './loaders/babel.js'; +import cssExtractLoaderUtil from './loaders/css-extract.js'; // loaders utils -import cssLoaderUtil from './loaders/css.ts'; -import handlebarsLoaderUtil from './loaders/handlebars.ts'; -import lessLoaderUtil from './loaders/less.ts'; -import sassLoaderUtil from './loaders/sass.ts'; -import stylusLoaderUtil from './loaders/stylus.ts'; -import tsLoaderUtil from './loaders/typescript.ts'; -import vueLoaderUtil from './loaders/vue.ts'; -import logger from './logger.ts'; +import cssLoaderUtil from './loaders/css.js'; +import handlebarsLoaderUtil from './loaders/handlebars.js'; +import lessLoaderUtil from './loaders/less.js'; +import sassLoaderUtil from './loaders/sass.js'; +import stylusLoaderUtil from './loaders/stylus.js'; +import tsLoaderUtil from './loaders/typescript.js'; +import vueLoaderUtil from './loaders/vue.js'; +import logger from './logger.js'; // plugins utils -import assetOutputDisplay from './plugins/asset-output-display.ts'; -import cssMinimizerPluginUtil from './plugins/css-minimizer.ts'; -import definePluginUtil from './plugins/define.ts'; -import deleteUnusedEntriesPluginUtil from './plugins/delete-unused-entries.ts'; -import entryFilesManifestPlugin from './plugins/entry-files-manifest.ts'; -import friendlyErrorPluginUtil from './plugins/friendly-errors.ts'; -import jsMinimizerPluginUtil from './plugins/js-minimizer.ts'; -import manifestPluginUtil from './plugins/manifest.ts'; -import miniCssExtractPluginUtil from './plugins/mini-css-extract.ts'; -import notifierPluginUtil from './plugins/notifier.ts'; -import PluginPriorities from './plugins/plugin-priorities.ts'; -import variableProviderPluginUtil from './plugins/variable-provider.ts'; -import vuePluginUtil from './plugins/vue.ts'; -import applyOptionsCallback, { type OptionsCallback } from './utils/apply-options-callback.ts'; -import copyEntryTmpName from './utils/copyEntryTmpName.ts'; -import getVueVersion from './utils/get-vue-version.ts'; -import stringEscaper from './utils/string-escaper.ts'; +import assetOutputDisplay from './plugins/asset-output-display.js'; +import cssMinimizerPluginUtil from './plugins/css-minimizer.js'; +import definePluginUtil from './plugins/define.js'; +import deleteUnusedEntriesPluginUtil from './plugins/delete-unused-entries.js'; +import entryFilesManifestPlugin from './plugins/entry-files-manifest.js'; +import friendlyErrorPluginUtil from './plugins/friendly-errors.js'; +import jsMinimizerPluginUtil from './plugins/js-minimizer.js'; +import manifestPluginUtil from './plugins/manifest.js'; +import miniCssExtractPluginUtil from './plugins/mini-css-extract.js'; +import notifierPluginUtil from './plugins/notifier.js'; +import PluginPriorities from './plugins/plugin-priorities.js'; +import variableProviderPluginUtil from './plugins/variable-provider.js'; +import vuePluginUtil from './plugins/vue.js'; +import applyOptionsCallback, { type OptionsCallback } from './utils/apply-options-callback.js'; +import copyEntryTmpName from './utils/copyEntryTmpName.js'; +import getVueVersion from './utils/get-vue-version.js'; +import stringEscaper from './utils/string-escaper.js'; import type WebpackConfig from './WebpackConfig.js'; class ConfigGenerator { diff --git a/lib/config/parse-runtime.ts b/lib/config/parse-runtime.ts index 35650dfe..27c1edfd 100644 --- a/lib/config/parse-runtime.ts +++ b/lib/config/parse-runtime.ts @@ -11,10 +11,7 @@ import path from 'path'; import type { Arguments } from 'yargs-parser'; -import packageUp from '../utils/package-up.ts'; -// .js (not .ts): RuntimeConfig is exposed in this module's emitted .d.ts, and -// rewriteRelativeImportExtensions does NOT rewrite .ts -> .js inside .d.ts files -// (only in emitted .js). tsc still resolves .js -> the .ts source here. +import packageUp from '../utils/package-up.js'; import RuntimeConfig from './RuntimeConfig.js'; export default function (argv: Arguments, cwd: string): RuntimeConfig { diff --git a/lib/config/path-util.ts b/lib/config/path-util.ts index 1efca152..4d01af50 100644 --- a/lib/config/path-util.ts +++ b/lib/config/path-util.ts @@ -9,11 +9,8 @@ import path from 'path'; -import logger from '../logger.ts'; +import logger from '../logger.js'; import type WebpackConfig from '../WebpackConfig.js'; -// .js (not .ts): RuntimeConfig is exposed in this module's emitted .d.ts, and -// rewriteRelativeImportExtensions does NOT rewrite .ts -> .js inside .d.ts files -// (only in emitted .js). tsc still resolves .js -> the .ts source here. import type RuntimeConfig from './RuntimeConfig.js'; export default { diff --git a/lib/config/validator.ts b/lib/config/validator.ts index 677894a1..f8f4250b 100644 --- a/lib/config/validator.ts +++ b/lib/config/validator.ts @@ -8,8 +8,8 @@ */ import type WebpackConfig from '../WebpackConfig.js'; -import logger from './../logger.ts'; -import pathUtil from './path-util.ts'; +import logger from './../logger.js'; +import pathUtil from './path-util.js'; class Validator { webpackConfig: WebpackConfig; diff --git a/lib/features.ts b/lib/features.ts index f01dd71f..7fbd78b9 100644 --- a/lib/features.ts +++ b/lib/features.ts @@ -8,7 +8,7 @@ */ import type { PackagesConfig } from './package-helper.js'; -import packageHelper from './package-helper.ts'; +import packageHelper from './package-helper.js'; interface Feature { method: string; diff --git a/lib/friendly-errors/formatters/missing-loader.ts b/lib/friendly-errors/formatters/missing-loader.ts index f85c0e88..87d1d26e 100644 --- a/lib/friendly-errors/formatters/missing-loader.ts +++ b/lib/friendly-errors/formatters/missing-loader.ts @@ -10,7 +10,7 @@ import type { FriendlyError } from '@kocal/friendly-errors-webpack-plugin'; import pc from 'picocolors'; -import loaderFeatures from '../../features.ts'; +import loaderFeatures from '../../features.js'; interface MissingLoaderError extends FriendlyError { loaderName?: string; diff --git a/lib/friendly-errors/transformers/missing-loader.ts b/lib/friendly-errors/transformers/missing-loader.ts index 238a8ac7..b2bb40d5 100644 --- a/lib/friendly-errors/transformers/missing-loader.ts +++ b/lib/friendly-errors/transformers/missing-loader.ts @@ -9,7 +9,7 @@ import type { FriendlyError, Transformer } from '@kocal/friendly-errors-webpack-plugin'; -import getVueVersion from '../../utils/get-vue-version.ts'; +import getVueVersion from '../../utils/get-vue-version.js'; import type WebpackConfig from '../../WebpackConfig.js'; const TYPE = 'loader-not-enabled'; diff --git a/lib/loaders/babel.ts b/lib/loaders/babel.ts index ef53f637..f43229ef 100644 --- a/lib/loaders/babel.ts +++ b/lib/loaders/babel.ts @@ -9,8 +9,8 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.ts'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import loaderFeatures from '../features.js'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; import type WebpackConfig from '../WebpackConfig.js'; export default { diff --git a/lib/loaders/css-extract.ts b/lib/loaders/css-extract.ts index 66695c9a..c1722c1a 100644 --- a/lib/loaders/css-extract.ts +++ b/lib/loaders/css-extract.ts @@ -12,7 +12,7 @@ import { fileURLToPath } from 'url'; import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import type { RuleSetUseItem } from 'webpack'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; import type WebpackConfig from '../WebpackConfig.js'; export default { diff --git a/lib/loaders/css.ts b/lib/loaders/css.ts index 8e7a8ada..0a38dfdf 100644 --- a/lib/loaders/css.ts +++ b/lib/loaders/css.ts @@ -9,8 +9,8 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.ts'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import loaderFeatures from '../features.js'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; import type WebpackConfig from '../WebpackConfig.js'; export default { diff --git a/lib/loaders/handlebars.ts b/lib/loaders/handlebars.ts index 529605fc..aaba971a 100644 --- a/lib/loaders/handlebars.ts +++ b/lib/loaders/handlebars.ts @@ -9,8 +9,8 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.ts'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import loaderFeatures from '../features.js'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; import type WebpackConfig from '../WebpackConfig.js'; export default { diff --git a/lib/loaders/less.ts b/lib/loaders/less.ts index c6438c67..1308da4f 100644 --- a/lib/loaders/less.ts +++ b/lib/loaders/less.ts @@ -9,10 +9,10 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.ts'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import loaderFeatures from '../features.js'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; import type WebpackConfig from '../WebpackConfig.js'; -import cssLoader from './css.ts'; +import cssLoader from './css.js'; export default { getLoaders(webpackConfig: WebpackConfig, useCssModules = false) { diff --git a/lib/loaders/sass.ts b/lib/loaders/sass.ts index 22f7aa0f..69c948e9 100644 --- a/lib/loaders/sass.ts +++ b/lib/loaders/sass.ts @@ -9,10 +9,10 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.ts'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import loaderFeatures from '../features.js'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; import type WebpackConfig from '../WebpackConfig.js'; -import cssLoader from './css.ts'; +import cssLoader from './css.js'; export default { getLoaders(webpackConfig: WebpackConfig, useCssModules = false) { diff --git a/lib/loaders/stylus.ts b/lib/loaders/stylus.ts index 41e79a82..dff5cd4e 100644 --- a/lib/loaders/stylus.ts +++ b/lib/loaders/stylus.ts @@ -9,10 +9,10 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.ts'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import loaderFeatures from '../features.js'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; import type WebpackConfig from '../WebpackConfig.js'; -import cssLoader from './css.ts'; +import cssLoader from './css.js'; export default { getLoaders(webpackConfig: WebpackConfig, useCssModules = false) { diff --git a/lib/loaders/typescript.ts b/lib/loaders/typescript.ts index de1ecfa4..792986c6 100644 --- a/lib/loaders/typescript.ts +++ b/lib/loaders/typescript.ts @@ -9,10 +9,10 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.ts'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import loaderFeatures from '../features.js'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; import type WebpackConfig from '../WebpackConfig.js'; -import babelLoader from './babel.ts'; +import babelLoader from './babel.js'; export default { async getLoaders(webpackConfig: WebpackConfig) { diff --git a/lib/loaders/vue.ts b/lib/loaders/vue.ts index fb6718ea..e38ce920 100644 --- a/lib/loaders/vue.ts +++ b/lib/loaders/vue.ts @@ -9,9 +9,9 @@ import { fileURLToPath } from 'url'; -import loaderFeatures from '../features.ts'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; -import getVueVersion from '../utils/get-vue-version.ts'; +import loaderFeatures from '../features.js'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; +import getVueVersion from '../utils/get-vue-version.js'; import type WebpackConfig from '../WebpackConfig.js'; export default { diff --git a/lib/package-helper.ts b/lib/package-helper.ts index 6dabe2f1..bcae55d1 100644 --- a/lib/package-helper.ts +++ b/lib/package-helper.ts @@ -14,7 +14,7 @@ import pc from 'picocolors'; import semver from 'semver'; import packageJson from '../package.json' with { type: 'json' }; -import logger from './logger.ts'; +import logger from './logger.js'; // `createRequire` is still needed for the dynamic `require('/package.json')` // lookups in getPackageVersion() (arbitrary installed packages, not a static import). diff --git a/lib/plugins/asset-output-display.ts b/lib/plugins/asset-output-display.ts index d7bdc234..f861fa35 100644 --- a/lib/plugins/asset-output-display.ts +++ b/lib/plugins/asset-output-display.ts @@ -10,10 +10,10 @@ import type FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin'; import type { WebpackPluginInstance } from 'webpack'; -import pathUtil from '../config/path-util.ts'; -import AssetOutputDisplayPlugin from '../friendly-errors/asset-output-display-plugin.ts'; +import pathUtil from '../config/path-util.js'; +import AssetOutputDisplayPlugin from '../friendly-errors/asset-output-display-plugin.js'; import type WebpackConfig from '../WebpackConfig.js'; -import PluginPriorities from './plugin-priorities.ts'; +import PluginPriorities from './plugin-priorities.js'; /** * Updates plugins array passed adding AssetOutputDisplayPlugin instance diff --git a/lib/plugins/css-minimizer.ts b/lib/plugins/css-minimizer.ts index a9ff0cab..024527c8 100644 --- a/lib/plugins/css-minimizer.ts +++ b/lib/plugins/css-minimizer.ts @@ -9,8 +9,8 @@ import MinimizerPlugin from 'minimizer-webpack-plugin'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; -import { checkCssMinifierPackages } from '../utils/minifier-check.ts'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; +import { checkCssMinifierPackages } from '../utils/minifier-check.js'; import type WebpackConfig from '../WebpackConfig.js'; export default function (webpackConfig: WebpackConfig) { diff --git a/lib/plugins/define.ts b/lib/plugins/define.ts index bf119feb..9e01669b 100644 --- a/lib/plugins/define.ts +++ b/lib/plugins/define.ts @@ -9,9 +9,9 @@ import webpack from 'webpack'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; import type WebpackConfig from '../WebpackConfig.js'; -import PluginPriorities from './plugin-priorities.ts'; +import PluginPriorities from './plugin-priorities.js'; export default function ( plugins: Array<{ plugin: webpack.WebpackPluginInstance; priority: number }>, diff --git a/lib/plugins/delete-unused-entries.ts b/lib/plugins/delete-unused-entries.ts index f724310f..6910d8d1 100644 --- a/lib/plugins/delete-unused-entries.ts +++ b/lib/plugins/delete-unused-entries.ts @@ -9,10 +9,10 @@ import type { WebpackPluginInstance } from 'webpack'; -import copyEntryTmpName from '../utils/copyEntryTmpName.ts'; -import DeleteUnusedEntriesJSPlugin from '../webpack/delete-unused-entries-js-plugin.ts'; +import copyEntryTmpName from '../utils/copyEntryTmpName.js'; +import DeleteUnusedEntriesJSPlugin from '../webpack/delete-unused-entries-js-plugin.js'; import type WebpackConfig from '../WebpackConfig.js'; -import PluginPriorities from './plugin-priorities.ts'; +import PluginPriorities from './plugin-priorities.js'; export default function ( plugins: Array<{ plugin: WebpackPluginInstance; priority: number }>, diff --git a/lib/plugins/entry-files-manifest.ts b/lib/plugins/entry-files-manifest.ts index dd99e7cb..d84b5f65 100644 --- a/lib/plugins/entry-files-manifest.ts +++ b/lib/plugins/entry-files-manifest.ts @@ -9,9 +9,9 @@ import type { WebpackPluginInstance } from 'webpack'; -import { EntryPointsPlugin } from '../webpack/entry-points-plugin.ts'; +import { EntryPointsPlugin } from '../webpack/entry-points-plugin.js'; import type WebpackConfig from '../WebpackConfig.js'; -import PluginPriorities from './plugin-priorities.ts'; +import PluginPriorities from './plugin-priorities.js'; export default function ( plugins: Array<{ plugin: WebpackPluginInstance; priority: number }>, diff --git a/lib/plugins/forked-ts-types.ts b/lib/plugins/forked-ts-types.ts index 52e37026..ecf7c02b 100644 --- a/lib/plugins/forked-ts-types.ts +++ b/lib/plugins/forked-ts-types.ts @@ -9,9 +9,9 @@ import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; import type WebpackConfig from '../WebpackConfig.js'; -import PluginPriorities from './plugin-priorities.ts'; +import PluginPriorities from './plugin-priorities.js'; export default function (webpackConfig: WebpackConfig): void { const config = {}; diff --git a/lib/plugins/friendly-errors.ts b/lib/plugins/friendly-errors.ts index 07b3bf6d..9c00aae2 100644 --- a/lib/plugins/friendly-errors.ts +++ b/lib/plugins/friendly-errors.ts @@ -9,13 +9,13 @@ import FriendlyErrorsWebpackPlugin from '@kocal/friendly-errors-webpack-plugin'; -import missingCssFileFormatter from '../friendly-errors/formatters/missing-css-file.ts'; -import missingLoaderFormatter from '../friendly-errors/formatters/missing-loader.ts'; -import missingPostCssConfigFormatter from '../friendly-errors/formatters/missing-postcss-config.ts'; -import missingCssFileTransformer from '../friendly-errors/transformers/missing-css-file.ts'; -import missingLoaderTransformerFactory from '../friendly-errors/transformers/missing-loader.ts'; -import missingPostCssConfigTransformer from '../friendly-errors/transformers/missing-postcss-config.ts'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import missingCssFileFormatter from '../friendly-errors/formatters/missing-css-file.js'; +import missingLoaderFormatter from '../friendly-errors/formatters/missing-loader.js'; +import missingPostCssConfigFormatter from '../friendly-errors/formatters/missing-postcss-config.js'; +import missingCssFileTransformer from '../friendly-errors/transformers/missing-css-file.js'; +import missingLoaderTransformerFactory from '../friendly-errors/transformers/missing-loader.js'; +import missingPostCssConfigTransformer from '../friendly-errors/transformers/missing-postcss-config.js'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; import type WebpackConfig from '../WebpackConfig.js'; export default function (webpackConfig: WebpackConfig) { diff --git a/lib/plugins/js-minimizer.ts b/lib/plugins/js-minimizer.ts index 3dc466e8..04a9d87c 100644 --- a/lib/plugins/js-minimizer.ts +++ b/lib/plugins/js-minimizer.ts @@ -9,8 +9,8 @@ import MinimizerPlugin from 'minimizer-webpack-plugin'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; -import { checkJsMinifierPackages } from '../utils/minifier-check.ts'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; +import { checkJsMinifierPackages } from '../utils/minifier-check.js'; import type WebpackConfig from '../WebpackConfig.js'; export default function (webpackConfig: WebpackConfig) { diff --git a/lib/plugins/manifest.ts b/lib/plugins/manifest.ts index 721c2b64..f1c49d86 100644 --- a/lib/plugins/manifest.ts +++ b/lib/plugins/manifest.ts @@ -10,11 +10,11 @@ import type { WebpackPluginInstance } from 'webpack'; import { WebpackManifestPlugin } from 'webpack-manifest-plugin'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; -import copyEntryTmpName from '../utils/copyEntryTmpName.ts'; -import manifestKeyPrefixHelper from '../utils/manifest-key-prefix-helper.ts'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; +import copyEntryTmpName from '../utils/copyEntryTmpName.js'; +import manifestKeyPrefixHelper from '../utils/manifest-key-prefix-helper.js'; import type WebpackConfig from '../WebpackConfig.js'; -import PluginPriorities from './plugin-priorities.ts'; +import PluginPriorities from './plugin-priorities.js'; type ManifestPluginOptions = { seed: object; diff --git a/lib/plugins/mini-css-extract.ts b/lib/plugins/mini-css-extract.ts index 8fad7df9..b4e84a9d 100644 --- a/lib/plugins/mini-css-extract.ts +++ b/lib/plugins/mini-css-extract.ts @@ -10,9 +10,9 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import type { WebpackPluginInstance } from 'webpack'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; import type WebpackConfig from '../WebpackConfig.js'; -import PluginPriorities from './plugin-priorities.ts'; +import PluginPriorities from './plugin-priorities.js'; export default function ( plugins: Array<{ plugin: WebpackPluginInstance; priority: number }>, diff --git a/lib/plugins/notifier.ts b/lib/plugins/notifier.ts index a9945b05..ce2283f4 100644 --- a/lib/plugins/notifier.ts +++ b/lib/plugins/notifier.ts @@ -9,10 +9,10 @@ import type { WebpackPluginInstance } from 'webpack'; -import pluginFeatures from '../features.ts'; -import applyOptionsCallback from '../utils/apply-options-callback.ts'; +import pluginFeatures from '../features.js'; +import applyOptionsCallback from '../utils/apply-options-callback.js'; import type WebpackConfig from '../WebpackConfig.js'; -import PluginPriorities from './plugin-priorities.ts'; +import PluginPriorities from './plugin-priorities.js'; export default async function ( plugins: Array<{ plugin: WebpackPluginInstance; priority: number }>, diff --git a/lib/plugins/variable-provider.ts b/lib/plugins/variable-provider.ts index 8f683a95..549634f7 100644 --- a/lib/plugins/variable-provider.ts +++ b/lib/plugins/variable-provider.ts @@ -10,7 +10,7 @@ import webpack from 'webpack'; import type WebpackConfig from '../WebpackConfig.js'; -import PluginPriorities from './plugin-priorities.ts'; +import PluginPriorities from './plugin-priorities.js'; export default function ( plugins: Array<{ plugin: webpack.WebpackPluginInstance; priority: number }>, diff --git a/lib/plugins/vue.ts b/lib/plugins/vue.ts index 78de88dd..2a75bb77 100644 --- a/lib/plugins/vue.ts +++ b/lib/plugins/vue.ts @@ -10,7 +10,7 @@ import type { WebpackPluginInstance } from 'webpack'; import type WebpackConfig from '../WebpackConfig.js'; -import PluginPriorities from './plugin-priorities.ts'; +import PluginPriorities from './plugin-priorities.js'; export default async function ( plugins: Array<{ plugin: WebpackPluginInstance; priority: number }>, diff --git a/lib/shims.d.ts b/lib/shims.d.ts new file mode 100644 index 00000000..6766a4d8 --- /dev/null +++ b/lib/shims.d.ts @@ -0,0 +1,14 @@ +/* + * This file is part of the Symfony Webpack Encore package. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +// The webpack / webpack-dev-server CLI entrypoints are imported for their side +// effects only (running the binary); they ship no type declarations for these +// subpaths, so declare them as ambient modules to satisfy the compiler. +declare module 'webpack/bin/webpack.js'; +declare module 'webpack-dev-server/bin/webpack-dev-server.js'; diff --git a/lib/utils/get-vue-version.ts b/lib/utils/get-vue-version.ts index fda712f5..4deb4bd2 100644 --- a/lib/utils/get-vue-version.ts +++ b/lib/utils/get-vue-version.ts @@ -9,8 +9,8 @@ import semver from 'semver'; -import logger from '../logger.ts'; -import packageHelper from '../package-helper.ts'; +import logger from '../logger.js'; +import packageHelper from '../package-helper.js'; import type WebpackConfig from '../WebpackConfig.js'; export default function (webpackConfig: WebpackConfig): number | string | null { diff --git a/lib/utils/minifier-check.ts b/lib/utils/minifier-check.ts index e89be55f..a4cd40ac 100644 --- a/lib/utils/minifier-check.ts +++ b/lib/utils/minifier-check.ts @@ -9,7 +9,7 @@ import MinimizerPlugin from 'minimizer-webpack-plugin'; -import Features from '../features.ts'; +import Features from '../features.js'; const JS_MINIFIER_FEATURES = new Map([ [MinimizerPlugin.esbuildMinify, 'minify-js-esbuild'], diff --git a/lib/webpack/entry-points-plugin.ts b/lib/webpack/entry-points-plugin.ts index 014c844c..b79b4cb0 100644 --- a/lib/webpack/entry-points-plugin.ts +++ b/lib/webpack/entry-points-plugin.ts @@ -13,7 +13,7 @@ import path from 'path'; import type webpack from 'webpack'; -import copyEntryTmpName from '../utils/copyEntryTmpName.ts'; +import copyEntryTmpName from '../utils/copyEntryTmpName.js'; interface EntryPointsManifest { entrypoints: Record>; diff --git a/tsconfig.json b/tsconfig.json index 9a4b7cea..7d73891d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,8 +11,6 @@ "isolatedModules": true, "verbatimModuleSyntax": true, "erasableSyntaxOnly": true, - "allowImportingTsExtensions": true, - "rewriteRelativeImportExtensions": true, // Library build "rootDir": ".", From 9ab5b8e287e190ae4fa26b9dd8eaaeaeb35ace8a Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Sat, 4 Jul 2026 09:31:52 +0200 Subject: [PATCH 12/12] Minor improvements --- .github/workflows/build.yaml | 21 +++++++++++++++++---- .github/workflows/format.yaml | 4 ++-- .github/workflows/lint.yaml | 4 ++-- .github/workflows/testing_apps.yml | 2 +- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index ef2e63cc..0b0c4e8c 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -20,10 +20,10 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 - - name: Node ${{matrix.node-versions}} + - name: Node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e with: - node-version: '22.13.0' + node-version: '22.18.0' cache: pnpm - name: Install pnpm Dependencies @@ -35,5 +35,18 @@ jobs: - name: Build (emit JS + type declarations) run: pnpm build - - name: Ensure type declarations were generated - run: test -f dist/index.d.ts + - name: Verify packaged output + run: | + pnpm pack --out webpack-encore.tgz + contents=$(tar -tzf webpack-encore.tgz) + for file in \ + package/dist/index.js \ + package/dist/index.d.ts \ + package/dist/bin/encore.js \ + package/dist/lib/plugins/plugin-priorities.js \ + package/dist/lib/plugins/plugin-priorities.d.ts; do + echo "$contents" | grep -qxF "$file" || { + echo "::error::Missing $file in the package tarball" + exit 1 + } + done diff --git a/.github/workflows/format.yaml b/.github/workflows/format.yaml index a1ba1537..7f86a43d 100644 --- a/.github/workflows/format.yaml +++ b/.github/workflows/format.yaml @@ -19,10 +19,10 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 - - name: Node ${{matrix.node-versions}} + - name: Node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e with: - node-version: '22.13.0' + node-version: '22.18.0' cache: pnpm - name: Install pnpm Dependencies diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 61833656..fecb40ac 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -19,10 +19,10 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 - - name: Node ${{matrix.node-versions}} + - name: Node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e with: - node-version: '22.13.0' + node-version: '22.18.0' cache: pnpm - name: Install pnpm Dependencies diff --git a/.github/workflows/testing_apps.yml b/.github/workflows/testing_apps.yml index 35afa68a..8da7a5ed 100644 --- a/.github/workflows/testing_apps.yml +++ b/.github/workflows/testing_apps.yml @@ -132,7 +132,7 @@ jobs: - run: npm i -g corepack && corepack enable - - name: Node ${{matrix.node-versions}} + - name: Node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e with: node-version: '22.18.0'