Skip to content

exports: ./components/* declares .tsx source targets for two modules authored .ts/.cts — ERR_MODULE_NOT_FOUND under source and react-native #445

Description

@YevheniiKotyrlo

Summary

The ./components/* wildcard in package.json declares source and react-native as ./src/components/*.tsx, but two modules matched by that pattern are authored .ts / .cts. Under either condition those subpaths are a hard ERR_MODULE_NOT_FOUND — export conditions match on key presence, not target existence, so there is no fallthrough to import/require.

react-native is not a dormant condition: Expo sets it for iOS and Android (unstable_conditionsByPlatform in @expo/metro-config), and source is the condition react-native-builder-bob's example-app workflow runs on.

Affected

exports["./components/*"] [react-native] -> ./src/components/copyComponentProperties.tsx
exports["./components/*"] [react-native] -> ./src/components/index.tsx
exports["./components/*"] [source]       -> ./src/components/copyComponentProperties.tsx
exports["./components/*"] [source]       -> ./src/components/index.tsx

Authored files, from the published tarball:

$ ls src/components/ | grep -E '^(index|copyComponentProperties)\.'
copyComponentProperties.ts
index.cts
index.ts

Reproduced against the published react-native-css@3.0.7:

$ node --conditions=source -e "…require.resolve(…)"
[source] react-native-css/components/copyComponentProperties -> FAILED: MODULE_NOT_FOUND

Note that the exact ./components entry already answers index with ./src/components/index.cts, so the wildcard's .tsx guess contradicts the map's own neighbouring entry.

Suggested fix

An exact key beats a pattern regardless of declaration order, so two entries alongside the existing ./components/react-native-gesture-handler resolve it:

"./components/copyComponentProperties": {
  "source": "./src/components/copyComponentProperties.ts",
  "react-native": "./src/components/copyComponentProperties.ts",
  "import":  { "types": "./dist/typescript/module/src/components/copyComponentProperties.d.ts",   "default": "./dist/module/components/copyComponentProperties.js" },
  "require": { "types": "./dist/typescript/commonjs/src/components/copyComponentProperties.d.ts", "default": "./dist/commonjs/components/copyComponentProperties.js" }
},
"./components/index": {
  "source": "./src/components/index.cts",
  "react-native": "./src/components/index.cts",
  "import":  { "types": "./dist/typescript/module/src/components/index.d.ts",   "default": "./dist/module/components/index.cjs" },
  "require": { "types": "./dist/typescript/commonjs/src/components/index.d.ts", "default": "./dist/commonjs/components/index.cjs" }
},

I've applied exactly this locally and both subpaths resolve under source and react-native.

Why it went unnoticed, and the cheap check that finds it

A wildcard entry hardcodes one source extension across a directory whose modules are authored with several, so the defect appears only for the exceptions and only under conditions most consumers never enable. Nothing in the toolchain reports it: the manifest is valid JSON, the package installs, and every other condition resolves.

I wrote a check that walks the real dist/module/** tree, expands each wildcard over it (skipping stems that have an exact key, since exact beats pattern), and asserts every declared target under every condition exists. Across 509 declared targets it found exactly these four, plus two of my own making in a local patch.

It is generic — nothing in it is specific to my project — and it needs dist/**, so it belongs as a post-prepare check rather than an ordinary jest test. Happy to open a PR with the fix and the check together, or just the fix, whichever you'd prefer.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions