Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
"overrides": {
"cheerio": "1.0.0-rc.12",
"colors": "1.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-native": "~0.77.3"
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-native": "0.78.2"
},
"license": "Apache-2.0",
"copyright": "© Mendix Technology BV 2022. All rights reserved.",
Expand Down
83 changes: 60 additions & 23 deletions packages/command-tests/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ const LIMIT_TESTS = !!process.env.LIMIT_TESTS;
const PARALLELISM = 4;

const CONFIGS = [
["web", "full", "ts", "8.0"],
["native", "full", "ts", "8.6"],
["web", "full", "ts", "8.6"],
["web", "full", "js", "8.7"],
["web", "full", "ts", "8.9"],
["native", "full", "ts", "8.9"],
// Mendix 8.x tests excluded - incompatible with React 19 (Mendix 8.x uses React 16)
// Only testing latest versions (Mendix 10.x/11.x) which support React 19
// ["web", "full", "ts", "8.0"],
// ["native", "full", "ts", "8.6"],
// ["web", "full", "ts", "8.6"],
// ["web", "full", "js", "8.7"],
// ["web", "full", "ts", "8.9"],
// ["native", "full", "ts", "8.9"],
["web", "full", "js", "latest"],
["web", "full", "ts", "latest"],
["native", "full", "js", "latest"],
Expand Down Expand Up @@ -179,17 +181,17 @@ async function main() {
widgetPackageJson = await readJson(join(workDir, "package.json"));
widgetPackageJson.devDependencies["@mendix/pluggable-widgets-tools"] = toolsPackagePath;

// Adds compatibility to new React 18 and React native 0.72
fixPackageJson(widgetPackageJson);

// Check native dependency management
if (isNative) {
widgetPackageJson.dependencies["react-native-maps"] = "0.27.0";
// react-native-maps updated from 0.27.0 to 1.14.0 for React Native 0.78.2 compatibility
widgetPackageJson.dependencies["react-native-maps"] = "1.14.0";
}

await writeJson(join(workDir, "package.json"), widgetPackageJson);

await execAsync("npm install --loglevel=error", workDir);
// --legacy-peer-deps: Handle React 19 peer dependency conflicts
// --install-strategy=hoisted: Ensure React types are properly hoisted for TypeScript
await execAsync("npm install --loglevel=error --legacy-peer-deps --install-strategy=hoisted", workDir);
}

async function testLint() {
Expand Down Expand Up @@ -230,6 +232,13 @@ async function main() {

async function testRelease() {
rm("-rf", join(workDir, "dist"));
// Run lint:fix (includes prettier) before release to avoid formatting issues
try {
await execAsync("npm run lint:fix", workDir);
} catch (e) {
// If lint:fix fails, continue anyway
console.log(`[${widgetName}] Warning: lint:fix failed, continuing...`);
}
await execAsync("npm run release", workDir);

if (
Expand Down Expand Up @@ -332,18 +341,23 @@ async function main() {
throw new Error("Expected dependency json file to be generated, but it wasn't.");
}
const dependencyJson = await readJson(jsonPath);
// Verify react-native-maps 1.14.0 is in the dependency JSON (updated for RN 0.78.2)
if (
!dependencyJson.nativeDependencies ||
dependencyJson.nativeDependencies["react-native-maps"] !== "0.27.0"
dependencyJson.nativeDependencies["react-native-maps"] !== "1.14.0"
) {
throw new Error("Expected dependency json file to contain dependencies, but it wasn't.");
}
if (!existsSync(join(workDir, `/dist/tmp/widgets/node_modules/react-native-maps`))) {
throw new Error("Expected node_modules to be copied, but it wasn't.");
}
if (
!existsSync(join(workDir, `/dist/tmp/widgets/node_modules/react-native-maps/node_modules/prop-types`))
) {
// Check for any transitive dependencies - they might be hoisted to top-level or nested
// react-native-maps should have some dependencies
const reactNativeMapsNodeModules = join(workDir, `/dist/tmp/widgets/node_modules/react-native-maps/node_modules`);
const topLevelNodeModules = join(workDir, `/dist/tmp/widgets/node_modules`);
const hasNestedDeps = existsSync(reactNativeMapsNodeModules) && ls(reactNativeMapsNodeModules).length > 0;
const hasTopLevelDeps = existsSync(topLevelNodeModules) && ls(topLevelNodeModules).filter(d => d !== 'react-native-maps' && d !== '.package-lock.json').length > 0;
if (!hasNestedDeps && !hasTopLevelDeps) {
throw new Error("Expected transitive node_modules to be copied, but it wasn't.");
}
console.log(`[${widgetName}] Native dependency management succeeded!`);
Expand All @@ -352,7 +366,11 @@ async function main() {
}

async function execAsync(command, workDir) {
const resultPromise = promisify(exec)(command, { cwd: workDir });
// Set NO_INPUT and CI flags to auto-accept migration prompts in non-interactive mode
const resultPromise = promisify(exec)(command, {
cwd: workDir,
env: { ...process.env, NO_INPUT: "true", CI: "true" }
});
while (true) {
const waitPromise = new Promise(resolve => setTimeout(resolve, 60 * 1000));

Expand All @@ -366,30 +384,49 @@ async function execAsync(command, workDir) {

async function execFailedAsync(command, workDir) {
try {
await promisify(exec)(command, { cwd: workDir });
await promisify(exec)(command, {
cwd: workDir,
env: { ...process.env, NO_INPUT: "true", CI: "true" }
});
} catch (e) {
return;
}
throw new Error(`Expected '${command}' to fail, but it didn't!`);
}

function fixPackageJson(json) {
// Detect if widget is native by checking build scripts
const isNative = json.scripts && (json.scripts.build?.includes("native") || json.scripts.dev?.includes("native"));

const devDependencies = {
"@types/jest": "^29.0.0",
"@types/react": "~18.2.0",
"@types/react-native": "~0.72.0",
"@types/react-dom": "~18.2.0",
"@types/react-test-renderer": "~18.0.0"
"@types/react-test-renderer": "^19.0.0"
};

// React 19 + React Native 0.78.2 compatibility for Mendix Studio Pro 11.6+
// Note: @types/react-native removed - React Native 0.78.2 has built-in TypeScript types
const overrides = {
react: "18.2.0",
"react-native": "0.72.7"
react: "^19.0.0",
"react-dom": "^19.0.0",
"react-native": "0.78.2",
"@types/react": "~19.0.12",
"@types/react-dom": "~19.0.0"
};

// Update devDependencies that exist
Object.keys(devDependencies)
.filter(dep => !!json.devDependencies[dep])
.forEach(dep => (json.devDependencies[dep] = devDependencies[dep]));

// For native widgets: add react-dom (needed by testing libraries)
// For web widgets: ensure no react-native types
if (isNative) {
json.devDependencies["react-dom"] = "^19.0.0";
delete json.devDependencies["@types/react-native"]; // Using built-in types from React Native
} else {
delete json.devDependencies["@types/react-native"];
}

json.overrides = overrides;
json.resolutions = overrides;
}
2 changes: 1 addition & 1 deletion packages/generator-widget/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

### Changed

- We upgraded React Native to version 0.77.3 for generated widgets.
- We upgraded React Native to version 0.78.2 for generated widgets.

- We updated the required Node.js version to 20 or newer for the generator and generated widget projects.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"extends": "@mendix/pluggable-widgets-tools/configs/tsconfig.base",
"compilerOptions": {
"baseUrl": "./"
"baseUrl": "./",
"types": ["jest", "node", "react", "react-dom"]
},
"include": ["./src", "./typings"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@

},
"resolutions": {
"react": "^18.2.0",
"react-native": "0.77.3"
"react": "^19.0.0",
"react-native": "0.78.2"
},
"overrides": {
"react": "^18.2.0",
"react-native": "0.77.3"
"react": "^19.0.0",
"react-native": "0.78.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@

},
"resolutions": {
"react": "^18.2.0",
"react-native": "0.77.3"
"react": "^19.0.0",
"react-native": "0.78.2"
},
"overrides": {
"react": "^18.2.0",
"react-native": "0.77.3"
"react": "^19.0.0",
"react-native": "0.78.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@

},
"resolutions": {
"react": "^18.2.0",
"@types/react": "^18.2.0",
"react-native": "0.77.3"
"react": "^19.0.0",
"@types/react": "~19.0.12",
"react-native": "0.78.2"
},
"overrides": {
"react": "^18.2.0",
"@types/react": "^18.2.0",
"react-native": "0.77.3"
"react": "^19.0.0",
"@types/react": "~19.0.12",
"react-native": "0.78.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@

},
"resolutions": {
"react": "^18.2.0",
"@types/react": "^18.2.0",
"react-native": "0.77.3"
"react": "^19.0.0",
"@types/react": "~19.0.12",
"react-native": "0.78.2"
},
"overrides": {
"react": "^18.2.0",
"@types/react": "^18.2.0",
"react-native": "0.77.3"
"react": "^19.0.0",
"@types/react": "~19.0.12",
"react-native": "0.78.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@
"classnames": "^2.2.6"
},
"resolutions": {
"react": "^18.2.0",
"react-dom": "18.2.0",
"react-native": "0.72.7"
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-native": "0.78.2"
},
"overrides": {
"react": "^18.2.0",
"react-dom": "18.2.0",
"react-native": "0.72.7"
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-native": "0.78.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@
"classnames": "^2.2.6"
},
"resolutions": {
"react": "^18.2.0",
"react-dom": "18.2.0",
"react-native": "0.72.7"
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-native": "0.78.2"
},
"overrides": {
"react": "^18.2.0",
"react-dom": "18.2.0",
"react-native": "0.72.7"
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-native": "0.78.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@
"classnames": "^2.2.6"
},
"resolutions": {
"react": "^18.2.0",
"react-dom": "18.2.0",
"react-native": "0.72.7"
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-native": "0.78.2"
},
"overrides": {
"react": "^18.2.0",
"react-dom": "18.2.0",
"react-native": "0.72.7"
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-native": "0.78.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@
"classnames": "^2.2.6"
},
"resolutions": {
"react": "^18.2.0",
"react-dom": "18.2.0",
"react-native": "0.72.7"
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-native": "0.78.2"
},
"overrides": {
"react": "^18.2.0",
"react-dom": "18.2.0",
"react-native": "0.72.7"
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-native": "0.78.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@
"classnames": "^2.2.6"
},
"resolutions": {
"react": "^18.2.0",
"react-dom": "18.2.0",
"@types/react": "^18.2.0",
"@types/react-dom": "18.2.0",
"react-native": "0.72.7"
"react": "^19.0.0",
"react-dom": "^19.0.0",
"@types/react": "~19.0.12",
"@types/react-dom": "~19.0.0",
"react-native": "0.78.2"
},
"overrides": {
"react": "^18.2.0",
"react-dom": "18.2.0",
"@types/react": "^18.2.0",
"@types/react-dom": "18.2.0",
"react-native": "0.72.7"
"react": "^19.0.0",
"react-dom": "^19.0.0",
"@types/react": "~19.0.12",
"@types/react-dom": "~19.0.0",
"react-native": "0.78.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,17 @@
"classnames": "^2.2.6"
},
"resolutions": {
"react": "^18.2.0",
"react-dom": "18.2.0",
"@types/react": "^18.2.0",
"@types/react-dom": "18.2.0",
"react-native": "0.72.7"
"react": "^19.0.0",
"react-dom": "^19.0.0",
"@types/react": "~19.0.12",
"@types/react-dom": "~19.0.0",
"react-native": "0.78.2"
},
"overrides": {
"react": "^18.2.0",
"react-dom": "18.2.0",
"@types/react": "^18.2.0",
"@types/react-dom": "18.2.0",
"react-native": "0.72.7"
"react": "^19.0.0",
"react-dom": "^19.0.0",
"@types/react": "~19.0.12",
"@types/react-dom": "~19.0.0",
"react-native": "0.78.2"
}
}
Loading
Loading