Skip to content

Add TypeScript foundation and upgrade build tooling - #3794

Merged
bobvandevijver merged 4 commits into
bolt:6.2from
Vondry:chore/typescript-foundation
Sep 28, 2026
Merged

bobvandevijver merged 4 commits into
bolt:6.2from
Vondry:chore/typescript-foundation

Conversation

@Vondry

@Vondry Vondry commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

Add TypeScript foundation and upgrade build tooling

Second step of the Vue 3 / TypeScript migration, which adds TypeScript to the existing Vue 2.7 codebase without touching component logic

Changes

  • Encore 1.8.2 → 4.7.0 — the last release supporting Vue 2 (5.0 dropped it). Brings sass-loader 14 and postcss-loader 8, and drops vue-template-compiler.
  • TypeScript — tsconfig.json (strict, .ts-only include), ts-loader via enableTypeScriptLoader(), npm run typecheck + a CI step, and typescript-eslint scoped to assets/**/*.ts.
  • Filters converted to TS, and Vue 2 global filters (Vue.filter() / $options.filters, both removed in Vue 3) replaced with direct imports at all 13 call sites.

Review notes

  • enableVueLoader()'s version option is deliberately omitted. It only accepts 2 or 3, and 2 selects the target that still requires vue-template-compiler. Unset, Encore detects vue@2.7 and uses the SFC compiler Vue 2.7 ships itself.
  • SFCs are not type-checked yet — none use lang="ts". That comes when they move to <script setup lang="ts"> and the checker becomes vue-tsc.

Behaviour

Unchanged, except trim(), strip() and uppercase() no longer throw a TypeError on null/non-string input. Values that previously rendered are unaffected — trim() still passes non-strings through untouched rather than coercing, so numbers aren't truncated and objects don't become [object Object].

Verified by diffing the compiled render functions of all changed SFCs, and by a 348-case differential harness against the pre-migration implementations.

Next

Vitest + tests for the converted filters, then components to Composition API.

Testing

I manually clicked through the admin pages and verified that they work as previously

image

@Vondry

Vondry commented Aug 21, 2026 •

Copy link
Copy Markdown
Contributor Author

I created follow up #3797 with test setup.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

trim() still throws for some non-string values despite the stated behavior guarantee.

Review effort: Balanced
Findings: None

What changed in this PR

Adds a TypeScript foundation while retaining the Vue 2.7 application architecture and existing component behavior.

Changes:

  • Upgrades Encore and related frontend tooling.
  • Adds strict TypeScript compilation, linting, and CI checks.
  • Converts filters and API helpers to TypeScript, replacing global Vue filters with direct imports.
File Description
webpack.config.js Enables Vue 2.7 and TypeScript loaders.
tsconfig.json Defines strict TypeScript settings.
package.json Upgrades tooling and adds TypeScript dependencies/scripts.
package-lock.json Locks upgraded frontend dependencies.
eslint.config.mjs Adds TypeScript linting.
assets/​js/​version.js Updates generated-file formatting.
assets/​js/​services/​api/​dashboardNews.ts Converts dashboard news helpers to TypeScript.
assets/​js/​services/​api/​dashboardNews.js Removes the JavaScript implementation.
assets/​js/​services/​api/​content.ts Converts cached-content access to TypeScript.
assets/​js/​services/​api/​content.js Removes the JavaScript implementation.
assets/​js/​filters/​string.ts Converts string filters into typed exports.
assets/​js/​filters/​date.ts Converts date filters into typed exports.
assets/​js/​filters/​index.ts Exports typed filter helpers.
assets/​js/​filters/​index.js Removes global filter registration entry point.
assets/​js/​bolt.js Stops loading global Vue filters.
assets/​js/​app/​listing/​Components/​Table/​Row/​index.vue Uses imported string helpers.
assets/​js/​app/​listing/​Components/​Table/​Row/​_Meta.vue Uses the imported date helper.
assets/​js/​app/​listing/​Components/​Table/​Row/​_Actions.vue Uses imported date and trim helpers.
assets/​js/​app/​editor/​Components/​Slug.vue Uses the imported slug helper.
assets/​js/​app/​editor/​Components/​Select.vue Uses the imported raw helper.
assets/​js/​app/​editor/​Components/​Markdown.vue Uses the imported strip helper.
assets/​js/​app/​editor/​Components/​Html.vue Uses the imported strip helper.
.github/​workflows/​assets_code_analysis.yaml Adds TypeScript checking to CI.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread assets/js/filters/index.ts Resolved
Comment thread assets/js/services/api/content.ts Resolved
Comment thread assets/js/services/api/dashboardNews.ts Resolved
Comment thread assets/js/services/api/dashboardNews.ts Resolved
Comment thread webpack.config.js Resolved
@bobvandevijver
bobvandevijver force-pushed the chore/typescript-foundation branch from b4dd35d to 6c9c25a Compare September 26, 2026 14:23
@bobvandevijver

Copy link
Copy Markdown
Member

@Vondry already rebased for you, when those small changes have been made it can be merged 👍🏻

@Vondry

Vondry commented Sep 27, 2026

Copy link
Copy Markdown
Contributor Author

@Vondry already rebased for you, when those small changes have been made it can be merged 👍🏻

Great, should be ready now.

First step of the staged Vue 3 / TypeScript migration. Introduces
TypeScript on the existing Vue 2.7 codebase without touching any
component logic, so the eventual framework swap lands as a much
smaller, mechanical change.

Build tooling:

- Upgrade @symfony/webpack-encore 1.8.2 -> 4.7.0. 4.7 is the last
  release supporting Vue 2; Encore 5.0 dropped it. The version option
  of enableVueLoader() is deliberately omitted: it only accepts 2 or 3,
  and passing 2 selects the target that still requires
  vue-template-compiler. Left unset, Encore detects vue@2.7 and picks
  its "vue2.7" target, which uses the SFC compiler Vue 2.7 ships
  itself, so vue-template-compiler is no longer needed.
- Bump sass-loader 9 -> 14 and postcss-loader 4 -> 8 to match Encore
  4.7's peer ranges, and add webpack and webpack-cli as explicit
  dependencies as Encore 4 requires.
- Drop @babel/plugin-transform-regenerator and
  @babel/plugin-transform-runtime, which were declared but unreferenced.

TypeScript:

- Add tsconfig.json with strict plus noImplicitReturns,
  noFallthroughCasesInSwitch, noImplicitOverride, isolatedModules,
  allowUnreachableCode false and allowUnusedLabels false. The include
  list is .ts/.d.ts only; the SFCs have no lang="ts" yet, so they are
  not type-checked until they move to <script setup lang="ts"> and the
  checker becomes vue-tsc.
- Add typescript 6, ts-loader and @types/luxon, wire ts-loader through
  Encore.enableTypeScriptLoader(), and add a typecheck script plus a CI
  step running it.
- Scope typescript-eslint to assets/**/*.ts so the Vue 2 SFCs keep
  being linted by the vue2 preset.

Filters:

- Convert assets/js/filters and assets/js/services/api to TypeScript.
- Replace the Vue 2 global filters, removed in Vue 3, with directly
  imported functions at all 13 call sites across 7 components. Return
  types are inferred rather than annotated.

Behaviour is unchanged apart from trim(), strip() and uppercase() no
longer throwing a TypeError on null or non-string input. Values that
previously rendered are unaffected: trim() still passes non-strings
through untouched instead of coercing them, so numbers are not
truncated and objects do not become "[object Object]".
The filters are imported directly from ./date and ./string at every call
site, and bolt.js no longer imports ./filters to register them as Vue
filters, so nothing references the index.
Drop the unknown-typed locals in getRecords(), getNews() and fetchNews().
The callers are still plain JS SFCs, so narrowing the return type to
unknown bought nothing yet; the proper types come with the component
conversion.
Keep the Encore chain in its previous order and append the TypeScript
loader at the end, dropping the explanatory comments, so the diff
against master stays minimal.
@Vondry
Vondry force-pushed the chore/typescript-foundation branch from 98e2902 to 78f2818 Compare September 28, 2026 05:52
@bobvandevijver
bobvandevijver merged commit d097333 into bolt:6.2 Sep 28, 2026
37 checks passed
@bobvandevijver

Copy link
Copy Markdown
Member

Thank you @Vondry!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants