add TypeScript support for Meteor Rspack plugin when typescript npm dep exists

This commit is contained in:
Nacho Codoñer
2025-09-08 16:23:16 +02:00
parent 5ad89cfea7
commit 0850049dd0
8 changed files with 59 additions and 8 deletions

View File

@@ -36,6 +36,7 @@ export const GLOBAL_STATE_KEYS = {
RSPACK_REACT_INSTALLATION_CHECKED: 'rspack.rspackReactInstallationChecked',
RSPACK_DOCTOR_INSTALLATION_CHECKED: 'rspack.rspackDoctorInstallationChecked',
REACT_CHECKED: 'rspack.reactChecked',
TYPESCRIPT_CHECKED: 'rspack.typescriptChecked',
INITIAL_ENTRYPONTS: 'meteor.initialEntrypoints',
CLIENT_FIRST_COMPILE: 'rspack.clientFirstCompile',
SERVER_FIRST_COMPILE: 'rspack.serverFirstCompile',

View File

@@ -211,3 +211,31 @@ export async function ensureRspackDoctorInstalled() {
'Rspack Doctor'
);
}
/**
* Checks if TypeScript is installed and sets global state accordingly
* Sets global state and environment variables based on TypeScript detection
* @returns {boolean} Whether TypeScript is installed
*/
export function checkTypescriptInstalled() {
// Skip if already checked
if (getGlobalState(GLOBAL_STATE_KEYS.TYPESCRIPT_CHECKED, false)) {
return;
}
const appDir = getMeteorAppDir();
// Check if TypeScript is a dependency in the project
const isTypescriptInstalled = checkNpmDependencyExists('typescript', { cwd: appDir });
if (isTypescriptInstalled) {
// Set environment variable to indicate TypeScript is enabled
process.env.METEOR_TYPESCRIPT_ENABLED = 'true';
} else {
process.env.METEOR_TYPESCRIPT_ENABLED = 'false';
}
// Mark as checked
setGlobalState(GLOBAL_STATE_KEYS.TYPESCRIPT_CHECKED, true);
return isTypescriptInstalled;
}

View File

@@ -3,7 +3,7 @@
* @description Functions for managing Rspack processes
*/
import { checkNpmDependencyExists, getNpxCommand } from 'meteor/tools-core/lib/npm';
import { getMeteorAppPort } from 'meteor/tools-core/lib/meteor';
import { getMeteorAppPort, isMeteorTypescriptProject } from 'meteor/tools-core/lib/meteor';
/**
* Calculates the devServerPort based on process.env.PORT
@@ -136,11 +136,14 @@ export function getRspackEnv({ isClient, isServer, isTest: inIsTest }) {
const entryKey = `${isTest && isTestModule ? 'test' : 'main'}${isClient ? 'Client' : 'Server'}`;
const inputFilePath = isTest && isTestModule ? initialEntrypoints.testModule : initialEntrypoints[entryKey];
const isTypescriptEnabled = inputFilePath?.endsWith('.ts') || inputFilePath?.endsWith('.tsx');
const isTsxEnabled = inputFilePath?.endsWith('.tsx');
const isJsxEnabled = inputFilePath?.endsWith('.jsx');
const isTypescriptEnabled = process.env.METEOR_TYPESCRIPT_ENABLED === 'true' ||
inputFilePath?.endsWith('.ts') ||
inputFilePath?.endsWith('.tsx');
const isReactEnabled = process.env.METEOR_REACT_ENABLED === 'true';
const isTsxEnabled = inputFilePath?.endsWith('.tsx') || isReactEnabled;
const isJsxEnabled = inputFilePath?.endsWith('.jsx') || isReactEnabled;
const isReactEnabled = !!process.env.METEOR_REACT_ENABLED;
const isBlazeEnabled = isMeteorBlazeProject();
const isBlazeHotEnabled = isMeteorBlazeHotProject();
const isBundleVisualizerEnabled = isMeteorBundleVisualizerProject();

View File

@@ -22,6 +22,7 @@ const {
const {
ensureRspackInstalled,
checkReactInstalled,
checkTypescriptInstalled,
ensureRspackReactInstalled,
} = require('./lib/dependencies');
@@ -114,13 +115,19 @@ if (isMeteorAppRun() || isMeteorAppBuild() || isMeteorAppTest()) {
if (hasMeteorAppConfigAutoInstallDeps()) {
// Ensure Rspack is installed
await ensureRspackInstalled();
}
// Check if Rspack React is installed
if (checkReactInstalled()) {
// Check if Rspack React is installed
if (checkReactInstalled()) {
// Auto install deps (by default enabled)
if (hasMeteorAppConfigAutoInstallDeps()) {
await ensureRspackReactInstalled();
}
}
// Check if TypeScript is installed
checkTypescriptInstalled();
// Ensure the Rspack build context directory exists
ensureRspackBuildContextExists();

View File

@@ -421,6 +421,14 @@ export function isMeteorBundleVisualizerProject() {
return getMeteorAppPackages().includes('bundle-visualizer');
}
/**
* Checks if the Meteor application is a Typescript project.
* @returns {boolean} True if the application is a Typescript project, false otherwise.
*/
export function isMeteorTypescriptProject() {
return getMeteorAppPackages().includes('typescript');
}
/**
* Checks if the current Meteor command is 'test-packages'.
* @returns {boolean} True if the current command is 'test-packages', false otherwise.

View File

@@ -26,7 +26,8 @@
"babel-loader": "^9.1.3",
"less": "^4.4.0",
"less-loader": "^12.3.0",
"playwright": "^1.54.2"
"playwright": "^1.54.2",
"typescript": "^5.9.2"
},
"meteor": {
"mainModule": {

View File

@@ -5,8 +5,10 @@ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/
import '@helper/alias';
import ReactAlias from '@react/alias';
import './resolve-extensions/first';
import { TypescriptEnabled } from './ts/helpers';
console.log('@react/alias loaded', ReactAlias.version);
console.log('TypescriptEnabled', TypescriptEnabled);
async function insertLink({ title, url }) {
await LinksCollection.insertAsync({ title, url, createdAt: new Date() });

View File

@@ -0,0 +1 @@
export const TypescriptEnabled: boolean = true;