Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(plugin-typescript): check workspace tsconfig.json #6175

Merged
merged 9 commits into from
Apr 10, 2024
Merged
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
23 changes: 23 additions & 0 deletions .yarn/versions/dca3f277.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
releases:
"@yarnpkg/cli": minor
"@yarnpkg/plugin-typescript": minor

declined:
- "@yarnpkg/plugin-compat"
- "@yarnpkg/plugin-constraints"
- "@yarnpkg/plugin-dlx"
- "@yarnpkg/plugin-essentials"
- "@yarnpkg/plugin-init"
- "@yarnpkg/plugin-interactive-tools"
- "@yarnpkg/plugin-nm"
- "@yarnpkg/plugin-npm-cli"
- "@yarnpkg/plugin-pack"
- "@yarnpkg/plugin-patch"
- "@yarnpkg/plugin-pnp"
- "@yarnpkg/plugin-pnpm"
- "@yarnpkg/plugin-stage"
- "@yarnpkg/plugin-version"
- "@yarnpkg/plugin-workspace-tools"
- "@yarnpkg/builder"
- "@yarnpkg/core"
- "@yarnpkg/doctor"
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe(`Plugins`, () => {
);

test(
`it should automatically enable automatic @types insertion when a tsconfig is detected`,
`it should automatically enable automatic @types insertion when a tsconfig is detected at the root of the project`,
makeTemporaryEnv({}, async ({path, run, source}) => {
await xfs.writeFilePromise(ppath.join(path, `tsconfig.json`), ``);

Expand All @@ -44,6 +44,91 @@ describe(`Plugins`, () => {
}),
);

test(
`it should automatically enable automatic @types insertion when a tsconfig is detected in the current workspace`,
makeTemporaryMonorepoEnv({
workspaces: [`packages/*`],
}, {[`packages/foo`]: {}}, async ({path, run, source}) => {
await xfs.writeFilePromise(ppath.join(path, `packages/foo/tsconfig.json`), ``);

await run(`add`, `is-number`, {
cwd: `${path}/packages/foo` as PortablePath,
});

await expect(readManifest(`${path}/packages/foo` as PortablePath)).resolves.toMatchObject({
dependencies: {
[`is-number`]: `^2.0.0`,
},
devDependencies: {
[`@types/is-number`]: `^2`,
},
});
}),
);

test(
`it should automatically enable automatic @types insertion in the current workspace when tsEnableAutoTypes is set to true`,
makeTemporaryMonorepoEnv({
workspaces: [`packages/*`],
}, {[`packages/foo`]: {}}, async ({path, run, source}) => {
await run(`config`, `set`, `tsEnableAutoTypes`, `true`);

await run(`add`, `is-number`, {
cwd: `${path}/packages/foo` as PortablePath,
});

await expect(readManifest(`${path}/packages/foo` as PortablePath)).resolves.toMatchObject({
dependencies: {
[`is-number`]: `^2.0.0`,
},
devDependencies: {
[`@types/is-number`]: `^2`,
},
});
}),
);

test(
`it should not automatically enable automatic @types insertion when a tsconfig is present in a sibling workspace`,
makeTemporaryMonorepoEnv({
workspaces: [`packages/*`],
}, {[`packages/foo`]: {}, [`packages/bar`]: {}}, async ({path, run, source}) => {
await xfs.writeFilePromise(ppath.join(path, `packages/foo/tsconfig.json`), ``);

await run(`add`, `is-number`, {
cwd: `${path}/packages/bar` as PortablePath,
});

await expect(readManifest(`${path}/packages/bar` as PortablePath)).resolves.toMatchObject({
dependencies: {
[`is-number`]: `^2.0.0`,
},
});
}),
);

test(
`it should automatically enable automatic @types insertion when a tsconfig is detected in the root project of the current workspace`,
makeTemporaryMonorepoEnv({
workspaces: [`packages/*`],
}, {[`packages/foo`]: {}}, async ({path, run, source}) => {
await xfs.writeFilePromise(ppath.join(path, `tsconfig.json`), ``);

await run(`add`, `is-number`, {
cwd: `${path}/packages/foo` as PortablePath,
});

await expect(readManifest(`${path}/packages/foo` as PortablePath)).resolves.toMatchObject({
dependencies: {
[`is-number`]: `^2.0.0`,
},
devDependencies: {
[`@types/is-number`]: `^2`,
},
});
}),
);

test(
`it should automatically add @types to devDependencies when package doesn't provide types`,
makeTemporaryEnv({}, {
Expand Down Expand Up @@ -297,7 +382,24 @@ describe(`Plugins`, () => {
describe(`Removing types`, () => {
for (const type of Manifest.allDependencies) {
test(
`it should automatically remove @types from ${type}`,
`it should not automatically remove @types from ${type} without tsconfig or tsEnableAutoTypes`,
makeTemporaryEnv(merge({
dependencies: {
[`is-number`]: `^1.0.0`,
},
}, {
[type]: {
[`@types/is-number`]: `1.0.0`,
},
}), {}, async ({path, run, source}) => {
await run(`remove`, `is-number`);

await expect(readManifest(path)).resolves.toHaveProperty(`${type}.@types/is-number`);
}),
);

test(
`it should automatically remove @types from ${type} with tsEnableAutoTypes set to true`,
makeTemporaryEnv(merge({
dependencies: {
[`is-number`]: `^1.0.0`,
Expand All @@ -314,6 +416,102 @@ describe(`Plugins`, () => {
await expect(readManifest(path)).resolves.not.toHaveProperty(`${type}.@types/is-number`);
}),
);

test(
`it should automatically remove @types from ${type} with tsconfig.json present`,
makeTemporaryEnv(merge({
dependencies: {
[`is-number`]: `^1.0.0`,
},
}, {
[type]: {
[`@types/is-number`]: `1.0.0`,
},
}), {}, async ({path, run, source}) => {
await xfs.writeFilePromise(ppath.join(path, `tsconfig.json`), ``);

await run(`remove`, `is-number`);

await expect(readManifest(path)).resolves.not.toHaveProperty(`${type}.@types/is-number`);
}),
);

test(
`it should not automatically remove @types ${type} from the current workspace without tsconfig.json present or tsEnableAutoTypes`,
makeTemporaryMonorepoEnv({
workspaces: [`packages/*`],
},
merge(
{[`packages/foo`]: {dependencies: {[`is-number`]: `^1.0.0`}}},
{[`packages/foo`]: {[type]: {[`@types/is-number`]: `1.0.0`}}},
),
async ({path, run, source}) => {
await run(`remove`, `is-number`, {
cwd: `${path}/packages/foo` as PortablePath,
});

await expect(readManifest(`${path}/packages/foo` as PortablePath)).resolves.toHaveProperty(`${type}.@types/is-number`);
}),
);

test(
`it should automatically remove @types ${type} from the current workspace when a tsconfig is detected in the root project of the current workspace`,
makeTemporaryMonorepoEnv({
workspaces: [`packages/*`],
},
merge(
{[`packages/foo`]: {dependencies: {[`is-number`]: `^1.0.0`}}},
{[`packages/foo`]: {[type]: {[`@types/is-number`]: `1.0.0`}}},
),
async ({path, run, source}) => {
await xfs.writeFilePromise(ppath.join(path, `tsconfig.json`), ``);

await run(`remove`, `is-number`, {
cwd: `${path}/packages/foo` as PortablePath,
});

await expect(readManifest(`${path}/packages/foo` as PortablePath)).resolves.not.toHaveProperty(`${type}.@types/is-number`);
}),
);

test(
`it should automatically remove @types ${type} from the current workspace with tsEnableAutoTypes set to true`,
makeTemporaryMonorepoEnv({
workspaces: [`packages/*`],
},
merge(
{[`packages/foo`]: {dependencies: {[`is-number`]: `^1.0.0`}}},
{[`packages/foo`]: {[type]: {[`@types/is-number`]: `1.0.0`}}},
),
async ({path, run, source}) => {
await run(`config`, `set`, `tsEnableAutoTypes`, `true`);
await run(`remove`, `is-number`, {
cwd: `${path}/packages/foo` as PortablePath,
});

await expect(readManifest(`${path}/packages/foo` as PortablePath)).resolves.not.toHaveProperty(`${type}.@types/is-number`);
}),
);

test(
`it should automatically remove @types ${type} from the current workspace with tsconfig.json present`,
makeTemporaryMonorepoEnv({
workspaces: [`packages/*`],
},
merge(
{[`packages/foo`]: {dependencies: {[`is-number`]: `^1.0.0`}}},
{[`packages/foo`]: {[type]: {[`@types/is-number`]: `1.0.0`}}},
),
async ({path, run, source}) => {
await xfs.writeFilePromise(ppath.join(path, `packages/foo/tsconfig.json`), ``);

await run(`remove`, `is-number`, {
cwd: `${path}/packages/foo` as PortablePath,
});

await expect(readManifest(`${path}/packages/foo` as PortablePath)).resolves.not.toHaveProperty(`${type}.@types/is-number`);
}),
);
}

test(
Expand Down
2 changes: 1 addition & 1 deletion packages/docusaurus/static/configuration/yarnrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,7 @@
"tsEnableAutoTypes": {
"_package": "@yarnpkg/plugin-typescript",
"title": "Define whether to automatically install @types dependencies.",
"description": "If true, Yarn will automatically add `@types` dependencies when running `yarn add` with packages that don't provide their own typings (as reported by the Algolia npm database). This behavior is enabled by default if you have a tsconfig file at the root of your project.",
"description": "If true, Yarn will automatically add `@types` dependencies when running `yarn add` with packages that don't provide their own typings (as reported by the Algolia npm database). This behavior is enabled by default if you have a tsconfig.json file at the root of your project, or in your current workspace.",
"type": "boolean",
"examples": [true]
},
Expand Down
4 changes: 4 additions & 0 deletions packages/plugin-typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@

This plugin is included by default starting from Yarn 4.

## Configuration

This plugin is enabled by default if you have a `tsconfig.json` file at the root of your project, or in your current workspace. See [`tsEnableAutoTypes`](https://yarnpkg.com/configuration/yarnrc#tsEnableAutoTypes) for more information.

## Example

```
Expand Down
12 changes: 8 additions & 4 deletions packages/plugin-typescript/sources/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ const afterWorkspaceDependencyAddition = async (
const {project} = workspace;
const {configuration} = project;

const tsEnableAutoTypes = configuration.get(`tsEnableAutoTypes`)
?? xfs.existsSync(ppath.join(project.cwd, `tsconfig.json`));
const tsEnableAutoTypes = configuration.get(`tsEnableAutoTypes`) ?? (
xfs.existsSync(ppath.join(workspace.cwd, `tsconfig.json`))
|| xfs.existsSync(ppath.join(project.cwd, `tsconfig.json`))
);

if (!tsEnableAutoTypes)
return;
Expand Down Expand Up @@ -118,8 +120,10 @@ const afterWorkspaceDependencyRemoval = async (
const {project} = workspace;
const {configuration} = project;

const tsEnableAutoTypes = configuration.get(`tsEnableAutoTypes`)
?? xfs.existsSync(ppath.join(project.cwd, `tsconfig.json`));
const tsEnableAutoTypes = configuration.get(`tsEnableAutoTypes`) ?? (
xfs.existsSync(ppath.join(workspace.cwd, `tsconfig.json`))
|| xfs.existsSync(ppath.join(project.cwd, `tsconfig.json`))
);

if (!tsEnableAutoTypes)
return;
Expand Down
Loading