Skip to content

Commit 49ef758

Browse files
authored
feat: verify that the package.json fields point to correct path (#401)
### Summary After initial project setup, it's possible that the location of built files may diverge from value of package.json fields due to configuration changes. Previously it'd go unnoticed. This adds additional checks after the files are built to ensure that such mismatches cause a build failure. https://github.com/callstack/react-native-builder-bob/assets/1174278/25d1c427-da3e-4204-b49e-6754c1a316de ### Test plan - Tested it in React Navigation & React Native Paper repos
1 parent 47d1370 commit 49ef758

File tree

5 files changed

+105
-7
lines changed

5 files changed

+105
-7
lines changed

packages/react-native-builder-bob/src/targets/commonjs.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,6 @@ export default async function build({
3333
output,
3434
modules: 'commonjs',
3535
report,
36+
field: 'main',
3637
});
3738
}

packages/react-native-builder-bob/src/targets/module.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,6 @@ export default async function build({
3333
output,
3434
modules: false,
3535
report,
36+
field: 'module',
3637
});
3738
}

packages/react-native-builder-bob/src/targets/typescript.ts

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -193,16 +193,62 @@ export default async function build({
193193
report.success(
194194
`Wrote definition files to ${kleur.blue(path.relative(root, output))}`
195195
);
196+
197+
const packageJson = JSON.parse(
198+
await fs.readFile(path.join(root, 'package.json'), 'utf-8')
199+
);
200+
201+
if ('types' in packageJson) {
202+
if (!packageJson.types.endsWith('.d.ts')) {
203+
report.error(
204+
`The ${kleur.blue('types')} field in ${kleur.blue(
205+
'package.json'
206+
)} doesn't point to a definition file. Verify the path points to the correct file under ${kleur.blue(
207+
path.relative(root, output)
208+
)}.`
209+
);
210+
211+
throw new Error("Found incorrect path in 'types' field.");
212+
}
213+
214+
const typesPath = path.join(root, packageJson.types);
215+
216+
if (!(await fs.pathExists(typesPath))) {
217+
report.error(
218+
`The ${kleur.blue('types')} field in ${kleur.blue(
219+
'package.json'
220+
)} points to a non-existent file: ${kleur.blue(
221+
packageJson.types
222+
)}.\nVerify the path points to the correct file under ${kleur.blue(
223+
path.relative(root, output)
224+
)}.`
225+
);
226+
227+
throw new Error("Found incorrect path in 'types' field.");
228+
}
229+
} else {
230+
report.warn(
231+
`No ${kleur.blue('types')} field found in ${kleur.blue(
232+
'package.json'
233+
)}.\nConsider adding it so consumers can use the types.`
234+
);
235+
}
196236
} else {
197237
throw new Error('Failed to build definition files.');
198238
}
199-
} catch (e: any) {
200-
if (e.stdout) {
201-
report.error(
202-
`Errors found when building definition files:\n${e.stdout.toString()}`
203-
);
239+
} catch (e: unknown) {
240+
if (e != null && typeof e === 'object') {
241+
if ('stdout' in e && e.stdout != null) {
242+
report.error(
243+
`Errors found when building definition files:\n${e.stdout.toString()}`
244+
);
245+
} else if ('message' in e && typeof e.message === 'string') {
246+
report.error(e.message);
247+
} else {
248+
throw e;
249+
}
204250
} else {
205-
report.error(e.message);
251+
throw e;
206252
}
207253

208254
throw new Error('Failed to build definition files.');

packages/react-native-builder-bob/src/utils/compile.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type Options = Input & {
1212
sourceMaps?: boolean;
1313
copyFlow?: boolean;
1414
modules: 'commonjs' | false;
15+
field: 'main' | 'module';
1516
};
1617

1718
export default async function compile({
@@ -24,6 +25,7 @@ export default async function compile({
2425
copyFlow,
2526
sourceMaps = true,
2627
report,
28+
field,
2729
}: Options) {
2830
const files = glob.sync('**/*', {
2931
cwd: source,
@@ -120,4 +122,43 @@ export default async function compile({
120122
);
121123

122124
report.success(`Wrote files to ${kleur.blue(path.relative(root, output))}`);
125+
126+
const packageJson = JSON.parse(
127+
await fs.readFile(path.join(root, 'package.json'), 'utf-8')
128+
);
129+
130+
if (field in packageJson) {
131+
try {
132+
require.resolve(path.join(root, packageJson[field]));
133+
} catch (e: unknown) {
134+
if (
135+
e != null &&
136+
typeof e === 'object' &&
137+
'code' in e &&
138+
e.code === 'MODULE_NOT_FOUND'
139+
) {
140+
report.error(
141+
`The ${kleur.blue(field)} field in ${kleur.blue(
142+
'package.json'
143+
)} points to a non-existent file: ${kleur.blue(
144+
packageJson[field]
145+
)}.\nVerify the path points to the correct file under ${kleur.blue(
146+
path.relative(root, output)
147+
)}.`
148+
);
149+
150+
throw new Error(`Found incorrect path in '${field}' field.`);
151+
}
152+
153+
throw e;
154+
}
155+
} else {
156+
report.warn(
157+
`No ${kleur.blue(field)} field found in ${kleur.blue(
158+
'package.json'
159+
)}. Add it to your ${kleur.blue(
160+
'package.json'
161+
)} so that consumers of your package can use it.`
162+
);
163+
}
123164
}

packages/react-native-builder-bob/src/utils/logger.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,16 @@ import kleur from 'kleur';
33
const logger =
44
(type: string, color: Function) =>
55
(...messages: unknown[]) => {
6-
console.log(color(kleur.bold(type)), ...messages);
6+
console.log(
7+
color(kleur.bold(type)),
8+
...messages.map((message) => {
9+
if (typeof message === 'string') {
10+
return message.split('\n').join(`\n `);
11+
} else {
12+
return message;
13+
}
14+
})
15+
);
716
};
817

918
export const info = logger('ℹ', kleur.blue);

0 commit comments

Comments
 (0)