From dd922289c22add1bc436d63273037327593cdcb6 Mon Sep 17 00:00:00 2001 From: Ivan Banov Date: Mon, 7 Sep 2026 18:10:55 +0200 Subject: [PATCH] =?UTF-8?q?chore(native):=20make=20knip=20pass=20=E2=80=94?= =?UTF-8?q?=20drop=20duplicate=20deps,=20cwd-independent=20jest=20mapping?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `pnpm knip` failed on the native shell alone, for four unrelated reasons: - expo, react and react-native were listed in both dependencies and devDependencies; the devDependencies copies go (the lockfile already resolved the dependencies specifiers). - jest-expo turns the nearest tsconfig's `paths` into moduleNameMapper entries relative to ``, which for this package points nowhere and which tsconfig is nearest depends on the cwd. Filter the @dunky.dev mappers out: the workspace links plus the resolver do that job. - knip's expo plugin infers expo-updates unless the manifest says updates are off (they are: `updates.enabled: false`), and expo-system-ui from `userInterfaceStyle`, which a stories harness has no use for on Android — ignored with the reason, alongside jest-expo's own @expo/vector-icons mapping and the babel-preset-expo / babel-jest modules the presets resolve themselves. - the on-device Storybook reaches the stories through the generated, gitignored storybook.requires.ts, so the story files are entries for knip, mirroring the react and solid workspaces. Co-Authored-By: Claude Fable 5.1 --- knip.config.ts | 15 +++++++++++++++ packages/native/app.json | 1 + packages/native/jest.config.cjs | 12 ++++++++++++ packages/native/package.json | 3 --- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/knip.config.ts b/knip.config.ts index 9f7fa4c..bd3523c 100644 --- a/knip.config.ts +++ b/knip.config.ts @@ -28,6 +28,21 @@ const config: KnipConfig = { // The babel presets are referenced as strings in tsdown.config.ts. ignoreDependencies: ['babel-preset-solid', '@babel/preset-typescript'], }, + 'packages/native': { + // The Expo shell: `userInterfaceStyle` is honored from the manifest on + // iOS; the Android half would need the expo-system-ui native module, + // which a stories harness has no use for. `@expo/vector-icons` is a + // moduleNameMapper target inside jest-expo's own preset, not ours. + ignoreDependencies: ['expo-system-ui', '@expo/vector-icons'], + // babel-preset-expo ships inside `expo`; babel-jest is jest-expo's + // transform, resolved from the preset. Neither is ours to list. + ignoreUnresolved: ['babel-preset-expo', 'babel-jest'], + }, + // The on-device Storybook reaches the stories through the generated, + // gitignored storybook.requires.ts (see .rnstorybook/index.ts). + 'packages/native/*': { + entry: ['stories/*.stories.tsx'], + }, }, } diff --git a/packages/native/app.json b/packages/native/app.json index 818cf5d..8fec13f 100644 --- a/packages/native/app.json +++ b/packages/native/app.json @@ -6,6 +6,7 @@ "orientation": "portrait", "userInterfaceStyle": "light", "newArchEnabled": true, + "updates": { "enabled": false }, "ios": { "supportsTablet": true, "bundleIdentifier": "dev.dunky.ui" }, "android": { "package": "dev.dunky.ui" } } diff --git a/packages/native/jest.config.cjs b/packages/native/jest.config.cjs index e5bba1e..faf394c 100644 --- a/packages/native/jest.config.cjs +++ b/packages/native/jest.config.cjs @@ -12,10 +12,22 @@ const transformIgnorePatterns = expoPreset.transformIgnorePatterns.map(pattern = pattern.replace('/node_modules/(?!(.pnpm|', '/node_modules/(?!(.pnpm|@dunky\\.dev|'), ) +// jest-expo turns the nearest tsconfig's `paths` into moduleNameMapper entries +// relative to `` — which for this package points nowhere, and which +// tsconfig is "nearest" depends on the cwd (the repo root's has the workspace +// paths, this package's has none). The @dunky.dev packages resolve through the +// workspace links and the resolver below instead, so drop the mapping. +const moduleNameMapper = Object.fromEntries( + Object.entries(expoPreset.moduleNameMapper ?? {}).filter( + ([pattern]) => !pattern.startsWith('^@dunky\\.dev/'), + ), +) + module.exports = { ...expoPreset, rootDir: '.', testMatch: ['/*/tests/**/*.test.@(ts|tsx)'], + moduleNameMapper, // Establish React 19's act environment for the whole run (appended to // jest-expo's own setup, not replacing it). setupFiles: [...(expoPreset.setupFiles ?? []), '/jest-setup.cjs'], diff --git a/packages/native/package.json b/packages/native/package.json index 651bafc..6ccee37 100644 --- a/packages/native/package.json +++ b/packages/native/package.json @@ -25,11 +25,8 @@ "@react-native/jest-preset": "^0.86.2", "@storybook/react-native": "^10.5.0", "@types/react": "^19.2.17", - "expo": "~57.0.11", "jest": "^29.7.0", "jest-expo": "~57.0.3", - "react": "19.2.3", - "react-native": "^0.86.2", "react-native-gesture-handler": "~2.32.0", "react-native-reanimated": "4.5.1", "react-native-safe-area-context": "~5.7.0",