Skip to content

Commit

Permalink
fix: fix locating tsc in yarn 3 workspaces (#462)
Browse files Browse the repository at this point in the history
### Summary

With Yarn 3, the aliases for binaries only seem to exist at the monorepo
root `node_modules`, so the current logic fails to find `tsc`. This
change uses `yarn bin tsc` to get the correct location for the `tsc`
binary.

### Test plan

Tested in the React Navigation monorepo
  • Loading branch information
satya164 committed Sep 15, 2023
1 parent 82ad903 commit 19396ce
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 55 deletions.
41 changes: 9 additions & 32 deletions packages/create-react-native-library/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import ejs from 'ejs';
import dedent from 'dedent';
import kleur from 'kleur';
import yargs from 'yargs';
import spawn from 'cross-spawn';
import ora from 'ora';
import validateNpmPackage from 'validate-npm-package-name';
import githubUsername from 'github-username';
import prompts, { type PromptObject } from './utils/prompts';
import generateExampleApp from './utils/generateExampleApp';
import { spawn } from './utils/spawn';

const FALLBACK_BOB_VERSION = '0.20.0';

Expand Down Expand Up @@ -259,12 +259,7 @@ async function create(argv: yargs.Arguments<any>) {
}

try {
const child = spawn('npx', ['--help']);

await new Promise((resolve, reject) => {
child.once('error', reject);
child.once('close', resolve);
});
await spawn('npx', ['--help']);
} catch (error) {
// @ts-expect-error: TS doesn't know about `code`
if (error != null && error.code === 'ENOENT') {
Expand All @@ -283,15 +278,8 @@ async function create(argv: yargs.Arguments<any>) {
let name, email;

try {
name = spawn
.sync('git', ['config', '--get', 'user.name'])
.stdout.toString()
.trim();

email = spawn
.sync('git', ['config', '--get', 'user.email'])
.stdout.toString()
.trim();
name = await spawn('git', ['config', '--get', 'user.name']);
email = await spawn('git', ['config', '--get', 'user.email']);
} catch (e) {
// Ignore error
}
Expand Down Expand Up @@ -497,18 +485,7 @@ async function create(argv: yargs.Arguments<any>) {
new Promise<string>((resolve) =>
setTimeout(() => resolve(FALLBACK_BOB_VERSION), 1000)
),
new Promise<string>((resolve, reject) => {
const npm = spawn('npm', [
'view',
'react-native-builder-bob',
'dist-tags.latest',
]);

npm.stdout?.on('data', (data) => resolve(data.toString().trim()));
npm.stderr?.on('data', (data) => reject(data.toString().trim()));

npm.on('error', (err) => reject(err));
}),
spawn('npm', ['view', 'react-native-builder-bob', 'dist-tags.latest']),
]);
} catch (e) {
// Fallback to a known version if we couldn't fetch
Expand Down Expand Up @@ -697,10 +674,10 @@ async function create(argv: yargs.Arguments<any>) {
});

try {
spawn.sync('git', ['init'], { cwd: folder });
spawn.sync('git', ['branch', '-M', 'main'], { cwd: folder });
spawn.sync('git', ['add', '.'], { cwd: folder });
spawn.sync('git', ['commit', '-m', 'chore: initial commit'], {
await spawn('git', ['init'], { cwd: folder });
await spawn('git', ['branch', '-M', 'main'], { cwd: folder });
await spawn('git', ['add', '.'], { cwd: folder });
await spawn('git', ['commit', '-m', 'chore: initial commit'], {
cwd: folder,
});
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fs from 'fs-extra';
import spawn from 'cross-spawn';
import path from 'path';
import https from 'https';
import { spawn } from './spawn';

const FILES_TO_DELETE = [
'__tests__',
Expand Down Expand Up @@ -78,26 +78,9 @@ export default async function generateExampleApp({
: // `npx create-expo-app example --no-install`
['create-expo-app@latest', directory, '--no-install'];

await new Promise((resolve, reject) => {
const child = spawn('npx', args, {
cwd: dest,
env: { ...process.env, npm_config_yes: 'true' },
});

let stderr = '';

child.stderr?.setEncoding('utf8');
child.stderr?.on('data', (data) => {
stderr += data;
});

child.once('error', reject);
child.once('close', resolve);
child.once('exit', (code) => {
if (code === 1) {
reject(new Error(stderr));
}
});
await spawn('npx', args, {
cwd: dest,
env: { ...process.env, npm_config_yes: 'true' },
});

// Remove unnecessary files and folders
Expand Down
29 changes: 29 additions & 0 deletions packages/create-react-native-library/src/utils/spawn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import crossSpawn from 'cross-spawn';

export const spawn = async (...args: Parameters<typeof crossSpawn>) => {
return new Promise<string>((resolve, reject) => {
const child = crossSpawn(...args);

let stdout = '';
let stderr = '';

child.stdout?.setEncoding('utf8');
child.stdout?.on('data', (data) => {
stdout += data;
});

child.stderr?.setEncoding('utf8');
child.stderr?.on('data', (data) => {
stderr += data;
});

child.once('error', reject);
child.once('close', (code) => {
if (code === 0) {
resolve(stdout.trim());
} else {
reject(new Error(stderr.trim()));
}
});
});
};
21 changes: 19 additions & 2 deletions packages/react-native-builder-bob/src/targets/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,20 @@ export default async function build({
);
}
} else {
tsc = path.resolve(root, 'node_modules', '.bin', 'tsc');
const execpath = process.env.npm_execpath;
const cli = execpath?.split('/').pop()?.includes('yarn') ? 'yarn' : 'npm';

if (cli === 'yarn') {
const result = spawn.sync('yarn', ['bin', 'tsc'], {
stdio: 'pipe',
encoding: 'utf-8',
cwd: root,
});

tsc = result.stdout.trim();
} else {
tsc = path.resolve(root, 'node_modules', '.bin', 'tsc');
}

if (platform() === 'win32' && !tsc.endsWith('.cmd')) {
tsc += '.cmd';
Expand All @@ -108,7 +121,11 @@ export default async function build({

if (await fs.pathExists(tsc)) {
report.warn(
`Failed to locate 'tsc' in the workspace. Falling back to the globally installed version. Consider adding ${kleur.blue(
`Failed to locate ${kleur.blue(
'tsc'
)} in the workspace. Falling back to the binary found in ${kleur.blue(
'PATH'
)} at ${kleur.blue(tsc)}. Consider adding ${kleur.blue(
'typescript'
)} to your ${kleur.blue(
'devDependencies'
Expand Down

0 comments on commit 19396ce

Please sign in to comment.