feat(template)!: unify JS/TS templates#4229
Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Co-authored-by: Erik Moura <erikian@electronjs.org>
… template-unification
|
@claude review |
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>
|
@claude review |
…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>
|
@claude review |
|
@claude review |
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.
There was a problem hiding this comment.
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.
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
--typescriptas 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'sstripTypeScriptTypesfunction.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.