diff --git a/.github/workflows/Build.yml b/.github/workflows/Build.yml index e5d4b67c2..b9ffb782f 100644 --- a/.github/workflows/Build.yml +++ b/.github/workflows/Build.yml @@ -72,3 +72,7 @@ jobs: run: pnpm -r --filter='!native-widgets' --filter=$(if [ "${{ steps.files.outputs.global_files }}" = "" ] && ${{ github.event_name == 'pull_request' }}; then echo '...[origin/mx/11.12.x]'; else echo '**'; fi) run build env: NODE_OPTIONS: --max_old_space_size=8192 + - name: "Validating manifest format" + run: pnpm run validate-manifest-format + - name: "Validating native dependencies" + run: pnpm run validate-native-dependencies diff --git a/.husky/commit-msg b/.husky/commit-msg index 3b4299ef3..474570e59 100755 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -2,3 +2,4 @@ . "$(dirname "$0")/_/husky.sh" npx --no -- commitlint --edit "$1" +pnpm run validate-native-dependencies "$1" diff --git a/configs/jsactions/rollup-plugin-collect-dependencies.mjs b/configs/jsactions/rollup-plugin-collect-dependencies.mjs index 0a0ca59f2..b51714042 100644 --- a/configs/jsactions/rollup-plugin-collect-dependencies.mjs +++ b/configs/jsactions/rollup-plugin-collect-dependencies.mjs @@ -127,7 +127,14 @@ async function resolvePackage(target, sourceDir, optional = false) { } async function hasNativeCode(dir) { - return (await fg(["**/{android,ios}/*", "**/*.podspec"], { cwd: dir })).length > 0; + return (await fg( + ["**/{android,ios}/*", "**/*.podspec"], + { + cwd: dir, + ignore: ["**/example*/**", "**/__tests__/**", "**/docs/**", "**/.github/**"], + caseSensitiveMatch: false + } + )).length > 0; } async function getTransitiveDependencies(packagePath, isExternal) { @@ -187,7 +194,7 @@ export async function copyJsModule(moduleSourcePath, to) { // Skip certain directories if ( - relativePath.match(/[\\/](android|ios|windows|mac|jest|github|gradle|__.*__|docs|example.*)[\\/]/) + relativePath.match(/(^|[\\/])(android|ios|windows|mac|jest|\.github|gradle|__.*__|docs|example.*)([\\/]|$)/i) ) { return false; } diff --git a/package.json b/package.json index 428d1ccfa..38e497f34 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ "build-mpk": "ts-node --project ./scripts/tsconfig.json ./scripts/release/build-mpk.ts", "version": "ts-node --project ./scripts/tsconfig.json ./scripts/release/BumpVersion.ts", "validate-staged-widget-versions": "node scripts/validation/validate-versions-staged-files.js", + "validate-manifest-format": "node --experimental-strip-types scripts/validation/validate-manifest-format.ts", + "validate-native-dependencies": "node --experimental-strip-types scripts/validation/validate-native-dependencies.ts", "setup-mobile": "pnpm setup-android && pnpm setup-ios", "build:widgets": "node ./scripts/widget/buildWidgets.js", "test_widgets:maestro:ios": "bash maestro/run_maestro_widget_tests.sh ios", diff --git a/patches/@mendix__pluggable-widgets-tools@11.12.0.patch b/patches/@mendix__pluggable-widgets-tools@11.12.0.patch index 6f88831f7..c7bfd744b 100644 --- a/patches/@mendix__pluggable-widgets-tools@11.12.0.patch +++ b/patches/@mendix__pluggable-widgets-tools@11.12.0.patch @@ -1,5 +1,5 @@ diff --git a/configs/rollup-plugin-collect-dependencies.mjs b/configs/rollup-plugin-collect-dependencies.mjs -index d45c737bf32cb1029249fdc069b3df3f832d1ab4..9246919bd939c622447ba0227c5b695892f162a8 100644 +index d45c737bf32cb1029249fdc069b3df3f832d1ab4..9f5ae6f6adf3e41220d897ba1aa074c7da458314 100644 --- a/configs/rollup-plugin-collect-dependencies.mjs +++ b/configs/rollup-plugin-collect-dependencies.mjs @@ -1,8 +1,7 @@ @@ -21,7 +21,22 @@ index d45c737bf32cb1029249fdc069b3df3f832d1ab4..9246919bd939c622447ba0227c5b6958 ); } } -@@ -169,14 +168,28 @@ async function copyJsModule(moduleSourcePath, to) { +@@ -125,7 +124,13 @@ async function resolvePackage(target, sourceDir, optional = false) { + } + + async function hasNativeCode(dir) { +- return (await fg(["**/{android,ios}/*", "**/*.podspec"], { cwd: dir })).length > 0; ++ return (await fg( ++ ["**/{android,ios}/*", "**/*.podspec"], ++ { ++ cwd: dir, ++ ignore: ["**/example*/**", "**/__tests__/**", "**/docs/**"] ++ } ++ )).length > 0; + } + + async function getTransitiveDependencies(packagePath, isExternal) { +@@ -169,14 +174,28 @@ async function copyJsModule(moduleSourcePath, to) { if (existsSync(to)) { return; } @@ -45,7 +60,7 @@ index d45c737bf32cb1029249fdc069b3df3f832d1ab4..9246919bd939c622447ba0227c5b6958 + filter: src => { + const relativePath = src.replace(actualSourcePath, "").replace(/^[\\/]/, ""); + -+ if (relativePath.match(/[\\/](android|ios|windows|mac|jest|github|gradle|__.*__|docs|example.*)[\\/]/)) { ++ if (relativePath.match(/(^|[\\/])(android|ios|windows|mac|jest|github|gradle|__.*__|docs|example.*)([\\/]|$)/)) { + return false; + } + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a4b75dbbe..dd8e77241 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,7 +31,7 @@ overrides: patchedDependencies: '@mendix/pluggable-widgets-tools@11.12.0': - hash: cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf + hash: 6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389 path: patches/@mendix__pluggable-widgets-tools@11.12.0.patch react-native-gesture-handler@2.31.2: hash: 5be6c2cce8be6bd8afdbbf6c289d8b210686eafce0b41bf8cae2c29388aaa3b8 @@ -176,7 +176,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) '@types/querystringify': specifier: ^2.0.0 version: 2.0.2 @@ -213,7 +213,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) mendix: specifier: 11.8.0 version: 11.8.0 @@ -222,7 +222,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) concurrently: specifier: ^6.0.0 version: 6.5.1 @@ -244,7 +244,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/activity-indicator-native: dependencies: @@ -257,7 +257,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/animation-native: dependencies: @@ -273,7 +273,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/app-events-native: dependencies: @@ -289,7 +289,7 @@ importers: version: link:../../tools/piw-utils-internal '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/background-gradient-native: dependencies: @@ -299,7 +299,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/background-image-native: dependencies: @@ -312,7 +312,7 @@ importers: version: link:../../tools/piw-utils-internal '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/badge-native: dependencies: @@ -325,7 +325,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/bar-chart-native: dependencies: @@ -338,7 +338,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/barcode-scanner-native: dependencies: @@ -357,7 +357,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/bottom-sheet-native: dependencies: @@ -388,7 +388,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) '@types/react-native-actionsheet': specifier: ^2.4.1 version: 2.4.7 @@ -413,7 +413,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) '@types/react-native-snap-carousel': specifier: ^3.7.4 version: 3.8.12(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) @@ -441,7 +441,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) '@types/tinycolor2': specifier: ^1.4.1 version: 1.4.6 @@ -457,7 +457,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/feedback-native: dependencies: @@ -479,7 +479,7 @@ importers: version: link:../../tools/piw-utils-internal '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) '@types/querystringify': specifier: ^2.0.2 version: 2.0.2 @@ -498,7 +498,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/gallery-native: dependencies: @@ -514,7 +514,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/gallery-text-filter-native: dependencies: @@ -530,7 +530,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/image-native: dependencies: @@ -555,7 +555,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/intro-screen-native: dependencies: @@ -577,7 +577,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/line-chart-native: dependencies: @@ -590,7 +590,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/listview-swipe-native: dependencies: @@ -606,7 +606,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/maps-native: dependencies: @@ -628,7 +628,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/notifications-native: dependencies: @@ -647,7 +647,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/pie-doughnut-chart-native: dependencies: @@ -660,7 +660,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/popup-menu-native: dependencies: @@ -676,7 +676,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) '@types/react-native-material-menu': specifier: ^1.0.6 version: 1.0.10(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(react@19.2.3) @@ -695,7 +695,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/progress-circle-native: dependencies: @@ -711,7 +711,7 @@ importers: version: link:../../tools/piw-utils-internal '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/qr-code-native: dependencies: @@ -730,7 +730,7 @@ importers: version: link:../../tools/piw-utils-internal '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/radio-buttons-native: dependencies: @@ -743,7 +743,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/range-slider-native: dependencies: @@ -759,7 +759,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/rating-native: dependencies: @@ -778,7 +778,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) '@types/react-native-star-rating': specifier: ^1.1.6 version: 1.1.6(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(react@19.2.3) @@ -794,7 +794,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/safe-area-view-native: dependencies: @@ -813,7 +813,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/signature-native: dependencies: @@ -832,7 +832,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/slider-native: dependencies: @@ -848,7 +848,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/switch-native: dependencies: @@ -861,7 +861,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/toggle-buttons-native: dependencies: @@ -880,7 +880,7 @@ importers: version: 7.29.7(@babel/core@7.29.7) '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/pluggableWidgets/video-player-native: dependencies: @@ -899,7 +899,7 @@ importers: version: link:../../tools/piw-utils-internal '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) '@types/react-native-video': specifier: ^5.0.4 version: 5.0.21(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3)) @@ -918,13 +918,13 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) packages/tools/piw-native-utils-internal: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) rimraf: specifier: ^6.1.2 version: 6.1.3 @@ -933,7 +933,7 @@ importers: devDependencies: '@mendix/pluggable-widgets-tools': specifier: 11.12.0 - version: 11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) + version: 11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1) rimraf: specifier: ^6.1.2 version: 6.1.3 @@ -9304,7 +9304,7 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@mendix/pluggable-widgets-tools@11.12.0(patch_hash=cac90aed34fd19a0a6f1475c31d66a807c1e123ddf7116b44bf4b1f29ebe11bf)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1)': + '@mendix/pluggable-widgets-tools@11.12.0(patch_hash=6c126ccd843c0d2171a692235aff82990be64a7edbd70905cc90482bfd5c4389)(@jest/transform@30.3.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.43)(jest-util@30.4.1)(jiti@2.6.1)(picomatch@4.0.5)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.1(@babel/core@7.29.7))(@types/react@19.2.17)(react@19.2.3))(react@19.2.3)(tslib@2.8.1)': dependencies: '@babel/core': 7.29.7 '@babel/eslint-parser': 7.29.7(@babel/core@7.29.7)(eslint@9.39.4(jiti@2.6.1)) diff --git a/scripts/validation/validate-manifest-format.ts b/scripts/validation/validate-manifest-format.ts new file mode 100644 index 000000000..83f1d0a8c --- /dev/null +++ b/scripts/validation/validate-manifest-format.ts @@ -0,0 +1,118 @@ +import { readFileSync, existsSync, readdirSync } from "fs"; +import { join } from "path"; + +/** + * CI Check: Prevent Empty Manifest Objects + * + * Purpose: Ensure JS-only widgets don't emit empty {} manifests. + * Studio Pro's JSON parser uses MissingMemberHandling.Error with [JsonRequired], + * so an empty object would fail the entire manifest file parse. + * + * Expected behavior: + * - Widgets WITH native dependencies: emit {"nativeDependencies": {...}} + * - Widgets WITHOUT native dependencies: emit NO FILE at all + */ + +interface Manifest { + nativeDependencies?: Record; + [key: string]: unknown; +} + +interface Violation { + widget: string; + file: string; + reason: string; +} + +try { + validateManifestFormat(); +} catch (error) { + console.error(error); + process.exit(1); +} + +function validateManifestFormat(): void { + const violations: Violation[] = []; + const widgetsDir = join(process.cwd(), "packages/pluggableWidgets"); + + if (!existsSync(widgetsDir)) { + console.log("✅ No widgets directory found"); + return; + } + + const widgets = readdirSync(widgetsDir); + let checkedCount = 0; + + for (const widget of widgets) { + const manifestDir = join(widgetsDir, widget, "dist/tmp/widgets"); + + if (!existsSync(manifestDir)) continue; + + const files = readdirSync(manifestDir).filter(f => f.endsWith(".json") && f !== "package.json"); + + for (const file of files) { + checkedCount++; + const fullPath = join(manifestDir, file); + + try { + const content = readFileSync(fullPath, "utf-8"); + + // Check if file is empty (not even valid JSON) + if (!content.trim()) { + violations.push({ + widget, + file, + reason: "File is completely empty (not even valid JSON)" + }); + continue; + } + + const manifest: Manifest = JSON.parse(content); + + // Check for empty manifest or empty nativeDependencies object + const isEmpty = + Object.keys(manifest).length === 0 || + (manifest.nativeDependencies && Object.keys(manifest.nativeDependencies).length === 0); + + if (isEmpty) { + violations.push({ + widget, + file, + reason: + Object.keys(manifest).length === 0 + ? "Manifest is completely empty: {}" + : "nativeDependencies object is empty: {}" + }); + } + } catch (error) { + // Invalid JSON is also a violation + violations.push({ + widget, + file, + reason: `Invalid JSON: ${error instanceof Error ? error.message : String(error)}` + }); + } + } + } + + if (violations.length > 0) { + console.error("\n❌ EMPTY MANIFEST VIOLATION DETECTED\n"); + console.error("The following widgets have empty manifest files:\n"); + + for (const violation of violations) { + console.error(` Widget: ${violation.widget}`); + console.error(` File: ${violation.file}`); + console.error(` Issue: ${violation.reason}\n`); + } + + console.error("⚠️ Empty manifests break Studio Pro's JSON parser!"); + console.error(" Expected behavior:"); + console.error(" - Widgets WITH native deps: emit {nativeDependencies: {...}}"); + console.error(" - Widgets WITHOUT native deps: emit NO FILE at all\n"); + console.error("This is a bug in the build tooling. Check writeNativeDependenciesJson().\n"); + + throw new Error("Manifest format validation failed"); + } + + console.log(`✅ All manifests valid (checked ${checkedCount} manifest files)`); +} diff --git a/scripts/validation/validate-native-dependencies.ts b/scripts/validation/validate-native-dependencies.ts new file mode 100644 index 000000000..ab794596e --- /dev/null +++ b/scripts/validation/validate-native-dependencies.ts @@ -0,0 +1,184 @@ +import { existsSync, readdirSync, readFileSync } from "fs"; +import { join } from "path"; +import { execSync } from "child_process"; +import * as fg from "fast-glob"; + +/** + * CI Check: Detect New Native Dependencies + * + * Purpose: Warn when a widget adds a new dependency that contains native code. + * This helps catch when developers accidentally add native dependencies, + * which forces customers to rebuild their mobile apps. + * + * How it works: + * - Compares package.json dependencies against parent commit (HEAD^) + * - For any NEW dependencies, checks if they contain native code + * - Warns if the new dependency has ios/android folders + * + * Bypass: Include "NATIVE_DEPENDENCY_APPROVED" in the commit message. + */ + +interface PackageJson { + dependencies?: Record; + peerDependencies?: Record; +} + +interface Violation { + widget: string; + dependency: string; + path: string; +} + +try { + await validateNativeDependencies(); +} catch (error) { + console.error(error); + process.exit(1); +} + +async function validateNativeDependencies(): Promise { + // Check for bypass approval + let isApproved = false; + + // In commit-msg hook: read from file path passed as argument + const commitMsgFile = process.argv[2]; + if (commitMsgFile && existsSync(commitMsgFile)) { + const commitMessage = readFileSync(commitMsgFile, "utf-8"); + isApproved = commitMessage.includes("NATIVE_DEPENDENCY_APPROVED"); + } else { + // In CI: check all commits between HEAD^ and HEAD + try { + const commitMessages = execSync("git log HEAD^..HEAD --format=%B", { + encoding: "utf-8", + stdio: ["pipe", "pipe", "ignore"] + }); + isApproved = commitMessages.includes("NATIVE_DEPENDENCY_APPROVED"); + } catch (error) { + // If git log fails (e.g., no parent commit), fall back to checking HEAD only + try { + const commitMessage = execSync("git log -1 --format=%B", { + encoding: "utf-8", + stdio: ["pipe", "pipe", "ignore"] + }); + isApproved = commitMessage.includes("NATIVE_DEPENDENCY_APPROVED"); + } catch (fallbackError) { + // If even that fails, continue with validation + } + } + } + + if (isApproved) { + console.log("✅ Native dependency changes approved via commit message"); + return; + } + + const violations: Violation[] = []; + const widgetsDir = join(process.cwd(), "packages/pluggableWidgets"); + + if (!existsSync(widgetsDir)) { + console.log("✅ No widgets directory found"); + return; + } + + const widgets = readdirSync(widgetsDir); + let checkedCount = 0; + + for (const widget of widgets) { + const widgetPath = join(widgetsDir, widget); + const packageJsonPath = join(widgetPath, "package.json"); + + if (!existsSync(packageJsonPath)) continue; + + checkedCount++; + + try { + // Get current package.json + const currentPackageJson: PackageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")); + const currentDeps: Record = { + ...currentPackageJson.dependencies, + ...currentPackageJson.peerDependencies + }; + + // Get previous package.json from git (HEAD^) + let previousDeps: Record = {}; + try { + // Git always uses forward slashes, even on Windows + const relativePath = join("packages/pluggableWidgets", widget, "package.json").replace(/\\/g, "/"); + const previousContent = execSync(`git show HEAD^:${relativePath}`, { + encoding: "utf-8", + stdio: ["pipe", "pipe", "ignore"] + }); + const previousPackageJson: PackageJson = JSON.parse(previousContent); + previousDeps = { + ...previousPackageJson.dependencies, + ...previousPackageJson.peerDependencies + }; + } catch (error) { + // package.json doesn't exist in previous commit (new widget) + // We'll check all dependencies + } + + // Find NEW dependencies (in current but not in previous) + const newDeps = Object.keys(currentDeps).filter(dep => !previousDeps[dep]); + + if (newDeps.length === 0) continue; + + // Check each new dependency for native code + for (const depName of newDeps) { + const depPath = join(widgetPath, "node_modules", depName); + + if (!existsSync(depPath)) continue; + + const hasNative = await hasNativeCode(depPath); + + if (hasNative) { + violations.push({ + widget, + dependency: `${depName}@${currentDeps[depName]}`, + path: depPath + }); + } + } + } catch (error) { + console.warn(`⚠️ Could not check ${widget}: ${error instanceof Error ? error.message : String(error)}`); + } + } + + if (violations.length > 0) { + console.error("\n❌ NEW NATIVE DEPENDENCY DETECTED\n"); + console.error("The following widgets added dependencies with native code:\n"); + + for (const violation of violations) { + console.error(` Widget: ${violation.widget}`); + console.error(` New Dependency: ${violation.dependency}`); + console.error(` (Contains ios/android folders)\n`); + } + + console.error("⚠️ Adding native dependencies is a BREAKING CHANGE:"); + console.error(" - Forces customers to rebuild their mobile apps"); + console.error(" - Requires resubmission to App Store / Play Store"); + console.error(" - Can take days/weeks for customer deployment\n"); + console.error("To approve this change, include 'NATIVE_DEPENDENCY_APPROVED' in your commit message.\n"); + + throw new Error("Native dependency validation failed"); + } + + console.log(`✅ No new native dependencies detected (checked ${checkedCount} widgets)`); +} + +/** + * Check if a dependency contains native code + * Same logic as the patched hasNativeCode function + */ +async function hasNativeCode(dir: string): Promise { + try { + const files = await fg.default(["**/{android,ios}/*", "**/*.podspec"], { + cwd: dir, + ignore: ["**/example*/**", "**/__tests__/**", "**/docs/**", "**/.github/**"], + caseSensitiveMatch: false + }); + return files.length > 0; + } catch (error) { + return false; + } +}