Skip to content

feat(template)!: unify JS/TS templates#4229

Open
erickzhao wants to merge 31 commits into
nextfrom
template-unification
Open

feat(template)!: unify JS/TS templates#4229
erickzhao wants to merge 31 commits into
nextfrom
template-unification

Conversation

@erickzhao

@erickzhao erickzhao commented Apr 20, 2026

Copy link
Copy Markdown
Member

Having separate packages for TypeScript-based templates is a burden. You need to duplicate any bundler-related template work, which leaves our templates open to drift.

This PR attempts to reconcile the two templates variants together, and to have --typescript as an instantiation option.

The crux to this approach is that a lot of TypeScript files can be stripped by default in Node 22.13+ with node:module's stripTypeScriptTypes function.

For app code: this works great.

For bundler-specific config: This works great for Vite, since it supports TS out of the box without additional configuration. For webpack, we still need to configure additional loaders, so the bundler configurations are kept separate for JS/TS.

@github-actions github-actions Bot added the next label Apr 20, 2026
@socket-security

socket-security Bot commented May 21, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​electron-forge/​plugin-webpack@​0.0.0-use.local100100100100100

View full report

@erickzhao
erickzhao marked this pull request as ready for review May 22, 2026 00:14
@erickzhao
erickzhao requested a review from a team as a code owner May 22, 2026 00:14
Comment thread packages/template/base/package.json Outdated
Comment thread package.json Outdated
@erickzhao
erickzhao requested a review from erikian May 23, 2026 00:25
Comment thread packages/template/base/src/BaseTemplate.ts Outdated
Comment thread packages/template/base/src/BaseTemplate.ts Outdated
Comment thread packages/template/base/src/BaseTemplate.ts Outdated
Comment thread packages/external/create-electron-app/src/create-electron-app.ts
Comment thread packages/template/vite/src/ViteTemplate.ts Outdated
Comment thread packages/template/webpack/src/WebpackTemplate.ts Outdated
Comment thread packages/template/webpack/src/WebpackTemplate.ts
Comment thread vitest.config.mts
@erickzhao

Copy link
Copy Markdown
Member Author

@claude review

Comment thread packages/external/create-electron-app/src/init-scripts/find-template.ts Outdated
Comment thread packages/template/webpack/tmpl/renderer.ts Outdated
Comment thread packages/template/webpack/src/WebpackTemplate.ts
The 3-line comment explaining "TypeScript magic constants" survives
type stripping and appears in the generated JS output, referencing
declarations that no longer exist. Remove it since the declare const
lines are self-explanatory for TS users.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
@erickzhao
erickzhao requested a review from MarshallOfSound June 6, 2026 06:52
@erickzhao

Copy link
Copy Markdown
Member Author

@claude review

Comment thread packages/external/create-electron-app/src/init.ts Outdated
Comment thread packages/template/webpack/tmpl/main.ts
…int directive

Move the "base does not support TypeScript" rejection into
BaseTemplate.initializeTemplate (gated on the base templateDir) so it
fires regardless of how the template was resolved, including the
fully-qualified `@electron-forge/template-base` name that bypassed the
string compare in init.ts.

Switch webpack's main.ts to the ESM `import started from
'electron-squirrel-startup'` pattern that vite already uses. This removes
the `// oxlint-disable-next-line @typescript-eslint/no-require-imports`
directive that stripTypeScriptTypes preserved verbatim into the generated
JS scaffold, where the referenced rule isn't even enabled. Adds
@types/electron-squirrel-startup to the webpack TS devDeps (filtered out of
the JS variant) so `tsc --noEmit` still passes.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
@erickzhao

Copy link
Copy Markdown
Member Author

@claude review

@erickzhao
erickzhao dismissed erikian’s stale review June 10, 2026 02:09

comments addressed

@MarshallOfSound

Copy link
Copy Markdown
Member

@claude review

claude added 5 commits July 6, 2026 19:02
Resolves conflicts from the removal of the vite-typescript and
webpack-typescript template packages, and ports the
publish -> release script rename (#4305) into the unified
template specs.
…assed without --template

The base template does not support TypeScript, so a bare --typescript
flag now prompts for a bundler in interactive contexts instead of
failing after scaffolding begins.
…d of instance state

Replaces the typescript flag stashed on the template instance during
initializeTemplate with a getDevDependencies(options) method, removing
the hidden ordering dependency between template initialization and
dependency installation. Also hoists the duplicated forge.config.mts
copy in ViteTemplate and documents the formatting assumption behind
WebpackTemplate's JS config rewriting.
…ore typescript ^6

- Throw a descriptive error when oxfmt reports parse or format errors
  instead of silently writing the (possibly broken) output.
- Fail with a clear "requires Node.js >= 22.13" message when
  stripTypeScriptTypes is unavailable, since npx does not enforce the
  engines field.
- Restore the typescript ^6.0.0 dev dependency that the deleted
  language-specific templates shipped.

@claude claude Bot 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.

No new issues found on this pass — my earlier nits are addressed and MarshallOfSound's blocking concerns from May 25 look resolved. Deferring the final sign-off to a human given the size and breaking-change scope of this PR.

Extended reasoning...

Overview

This PR unifies the previously-separate JS and TS template packages (template-vite + template-vite-typescript, template-webpack + template-webpack-typescript) into single packages controlled by a new --typescript flag. It leans on Node 22.13's node:module.stripTypeScriptTypes to generate the JS variant from a single TS-authored source of truth (with webpack keeping a hand-maintained tmpl/js/ for its bundler configs because ts-loader/fork-ts-checker have no clean strippable equivalent). Also bumps the workspace Node engine floor to 22.13.0 and threads a new typescript flag through InitOptions / InitTemplateOptions / ForgeTemplate.getDevDependencies.

Security risks

None material. Changes are confined to project scaffolding (template files, package.json engine ranges, template-selection UX). No auth, crypto, permissions, or process-boundary code is touched. The one bit of dynamic behavior — stripTypeScriptTypes on template source — reads files the tool itself ships, not user input.

Level of scrutiny

High — this is a large feat! breaking change touching 101 files, deletes two published packages (@electron-forge/template-vite-typescript, @electron-forge/template-webpack-typescript), bumps a Node engine floor across every workspace package, and reshapes the CLI/interactive UX around a new flag. That combination (public API surface + package deletion + engine bump + scaffolding contract change) is exactly the class of change that warrants human maintainer sign-off, independent of correctness on the specific lines.

Other factors

Prior review coverage on this PR is strong: MarshallOfSound (CODEOWNER) filed six review comments on May 25 including two blocking, and my three subsequent bot passes (June 3, 5, 7) found follow-up nits — all are marked resolved. The recent commits map cleanly onto that feedback: 5e81b01 fixes the --typescript flag being overwritten by the interactive language prompt; 0b64f19 replaces the shared-mutable-state this._typescript with a getDevDependencies(options) method threaded through init.ts; c005de8 surfaces oxfmt errors, guards old Node.js at call time with a namespace import + runtime check, and restores typescript@^6; a333f11 adds tests for base-template TS rejection and the vite/webpack-typescript short-name redirects. Test coverage is comprehensive across both variants in the fast specs and the verdaccio slow specs, including typecheck and package flows for TS and lint/package flows for JS.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants