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
5 changes: 5 additions & 0 deletions .changeset/tester-react-native-export.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@fluentui-react-native/tester': patch
---

Point the `react-native` export condition at `./src/index.tsx`; it referenced `./src/index.ts`, which does not exist.
2 changes: 1 addition & 1 deletion apps/fluent-tester/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"exports": {
".": {
"types": "./lib/index.d.ts",
"react-native": "./src/index.ts",
"react-native": "./src/index.tsx",
"import": "./lib/index.js",
"default": "./src/index.tsx"
}
Expand Down
31 changes: 31 additions & 0 deletions scripts/src/tasks/constrain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export function constrain(workspace: Yarn.Constraints.Workspace): void {
}
assertDeprecations(ctx);
useCatalogs(ctx);
ensureReactNativeExports(ctx);
}

export function constrainRoot(workspace: Yarn.Constraints.Workspace): void {
Expand Down Expand Up @@ -81,6 +82,36 @@ function useCatalogs(ctx: PackageContext): void {
}
}

/**
* Metro resolves the "react-native" export condition to TypeScript source. Ensure published packages point that condition
* at a file that exists, and that React Native libraries provide it for every export.
*/
function ensureReactNativeExports(ctx: PackageContext): void {
const { exports, peerDependencies, private: isPrivate } = ctx.manifest;
if (isPrivate || !exports || typeof exports !== 'object' || Array.isArray(exports)) {
return;
}
const requireCondition = Boolean(peerDependencies?.['react-native']);
for (const [subpath, conditions] of Object.entries(exports)) {
if (!conditions || typeof conditions !== 'object' || Array.isArray(conditions)) {
continue;
}
const target = (conditions as Record<string, unknown>)['react-native'];
if (typeof target === 'string') {
if (!repoCtx.hasFile(ctx.root, target)) {
const swapped = target.endsWith('.tsx') ? target.slice(0, -1) : target.endsWith('.ts') ? `${target}x` : undefined;
if (swapped && repoCtx.hasFile(ctx.root, swapped)) {
ctx.enforce(['exports', subpath, 'react-native'], swapped);
} else {
ctx.error(`exports["${subpath}"]["react-native"] points to ${target}, which does not exist`);
}
}
} else if (requireCondition) {
ctx.error(`exports["${subpath}"] is missing a "react-native" condition pointing to its TypeScript source`);
}
}
}

function assertDeprecations(ctx: PackageContext): void {
// placeholder to add deprecated packages or parts of package.json to remove them
ctx.enforce('scripts.lint-package', undefined);
Expand Down