Skip to content

Commit aa4029d

Browse files
authored
feat(plugin-typescript): check workspace tsconfig.json (#6175)
**What's the problem this PR addresses?** <!-- Describe the rationale of your PR. --> <!-- Link all issues that it closes. (Closes/Resolves #xxxx.) --> Given the following monorepo setup, `plugin-typescript` is currently not enabled by default in the `foo` workspace, as it only checks that a `tsconfig.json` exists at the root of the project: ``` package.json workspace/foo/package.json workspace/foo/tsconfig.json ``` I also found the [current `README` of `plugin-typescript`](https://github.com/yarnpkg/berry/blob/daa574791b3b2df01e76c1fdfd9c975050a0fb9d/packages/plugin-typescript/README.md) not to be helpful in diagnosing my issue **How did you fix it?** <!-- A detailed description of your implementation. --> I've added a check to see if the current workspace had a `tsconfig.json` I've also added a Configuration section to `plugin-typescript/README.md`, to help users find the `tsEnableAutoTypes` option. **Checklist** <!--- Don't worry if you miss something, chores are automatically tested. --> <!--- This checklist exists to help you remember doing the chores when you submit a PR. --> <!--- Put an `x` in all the boxes that apply. --> - [x] I have read the [Contributing Guide](https://yarnpkg.com/advanced/contributing). <!-- See https://yarnpkg.com/advanced/contributing#preparing-your-pr-to-be-released for more details. --> <!-- Check with `yarn version check` and fix with `yarn version check -i` --> - [x] I have set the packages that need to be released for my changes to be effective. - I have only bumped `@yarnpkg/plugin-typescript` and `@yarnpkg/cli`, let me know if I should also select the other plugins/core etc. <!-- The "Testing chores" workflow validates that your PR follows our guidelines. --> <!-- If it doesn't pass, click on it to see details as to what your PR might be missing. --> - [x] I will check that all automated PR checks pass before the PR gets reviewed.
1 parent 4a889dc commit aa4029d

File tree

5 files changed

+236
-7
lines changed

5 files changed

+236
-7
lines changed

.yarn/versions/dca3f277.yml

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
releases:
2+
"@yarnpkg/cli": minor
3+
"@yarnpkg/plugin-typescript": minor
4+
5+
declined:
6+
- "@yarnpkg/plugin-compat"
7+
- "@yarnpkg/plugin-constraints"
8+
- "@yarnpkg/plugin-dlx"
9+
- "@yarnpkg/plugin-essentials"
10+
- "@yarnpkg/plugin-init"
11+
- "@yarnpkg/plugin-interactive-tools"
12+
- "@yarnpkg/plugin-nm"
13+
- "@yarnpkg/plugin-npm-cli"
14+
- "@yarnpkg/plugin-pack"
15+
- "@yarnpkg/plugin-patch"
16+
- "@yarnpkg/plugin-pnp"
17+
- "@yarnpkg/plugin-pnpm"
18+
- "@yarnpkg/plugin-stage"
19+
- "@yarnpkg/plugin-version"
20+
- "@yarnpkg/plugin-workspace-tools"
21+
- "@yarnpkg/builder"
22+
- "@yarnpkg/core"
23+
- "@yarnpkg/doctor"

packages/acceptance-tests/pkg-tests-specs/sources/plugins/plugin-typescript.test.ts

+200-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ describe(`Plugins`, () => {
2727
);
2828

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

@@ -44,6 +44,91 @@ describe(`Plugins`, () => {
4444
}),
4545
);
4646

47+
test(
48+
`it should automatically enable automatic @types insertion when a tsconfig is detected in the current workspace`,
49+
makeTemporaryMonorepoEnv({
50+
workspaces: [`packages/*`],
51+
}, {[`packages/foo`]: {}}, async ({path, run, source}) => {
52+
await xfs.writeFilePromise(ppath.join(path, `packages/foo/tsconfig.json`), ``);
53+
54+
await run(`add`, `is-number`, {
55+
cwd: `${path}/packages/foo` as PortablePath,
56+
});
57+
58+
await expect(readManifest(`${path}/packages/foo` as PortablePath)).resolves.toMatchObject({
59+
dependencies: {
60+
[`is-number`]: `^2.0.0`,
61+
},
62+
devDependencies: {
63+
[`@types/is-number`]: `^2`,
64+
},
65+
});
66+
}),
67+
);
68+
69+
test(
70+
`it should automatically enable automatic @types insertion in the current workspace when tsEnableAutoTypes is set to true`,
71+
makeTemporaryMonorepoEnv({
72+
workspaces: [`packages/*`],
73+
}, {[`packages/foo`]: {}}, async ({path, run, source}) => {
74+
await run(`config`, `set`, `tsEnableAutoTypes`, `true`);
75+
76+
await run(`add`, `is-number`, {
77+
cwd: `${path}/packages/foo` as PortablePath,
78+
});
79+
80+
await expect(readManifest(`${path}/packages/foo` as PortablePath)).resolves.toMatchObject({
81+
dependencies: {
82+
[`is-number`]: `^2.0.0`,
83+
},
84+
devDependencies: {
85+
[`@types/is-number`]: `^2`,
86+
},
87+
});
88+
}),
89+
);
90+
91+
test(
92+
`it should not automatically enable automatic @types insertion when a tsconfig is present in a sibling workspace`,
93+
makeTemporaryMonorepoEnv({
94+
workspaces: [`packages/*`],
95+
}, {[`packages/foo`]: {}, [`packages/bar`]: {}}, async ({path, run, source}) => {
96+
await xfs.writeFilePromise(ppath.join(path, `packages/foo/tsconfig.json`), ``);
97+
98+
await run(`add`, `is-number`, {
99+
cwd: `${path}/packages/bar` as PortablePath,
100+
});
101+
102+
await expect(readManifest(`${path}/packages/bar` as PortablePath)).resolves.toMatchObject({
103+
dependencies: {
104+
[`is-number`]: `^2.0.0`,
105+
},
106+
});
107+
}),
108+
);
109+
110+
test(
111+
`it should automatically enable automatic @types insertion when a tsconfig is detected in the root project of the current workspace`,
112+
makeTemporaryMonorepoEnv({
113+
workspaces: [`packages/*`],
114+
}, {[`packages/foo`]: {}}, async ({path, run, source}) => {
115+
await xfs.writeFilePromise(ppath.join(path, `tsconfig.json`), ``);
116+
117+
await run(`add`, `is-number`, {
118+
cwd: `${path}/packages/foo` as PortablePath,
119+
});
120+
121+
await expect(readManifest(`${path}/packages/foo` as PortablePath)).resolves.toMatchObject({
122+
dependencies: {
123+
[`is-number`]: `^2.0.0`,
124+
},
125+
devDependencies: {
126+
[`@types/is-number`]: `^2`,
127+
},
128+
});
129+
}),
130+
);
131+
47132
test(
48133
`it should automatically add @types to devDependencies when package doesn't provide types`,
49134
makeTemporaryEnv({}, {
@@ -297,7 +382,24 @@ describe(`Plugins`, () => {
297382
describe(`Removing types`, () => {
298383
for (const type of Manifest.allDependencies) {
299384
test(
300-
`it should automatically remove @types from ${type}`,
385+
`it should not automatically remove @types from ${type} without tsconfig or tsEnableAutoTypes`,
386+
makeTemporaryEnv(merge({
387+
dependencies: {
388+
[`is-number`]: `^1.0.0`,
389+
},
390+
}, {
391+
[type]: {
392+
[`@types/is-number`]: `1.0.0`,
393+
},
394+
}), {}, async ({path, run, source}) => {
395+
await run(`remove`, `is-number`);
396+
397+
await expect(readManifest(path)).resolves.toHaveProperty(`${type}.@types/is-number`);
398+
}),
399+
);
400+
401+
test(
402+
`it should automatically remove @types from ${type} with tsEnableAutoTypes set to true`,
301403
makeTemporaryEnv(merge({
302404
dependencies: {
303405
[`is-number`]: `^1.0.0`,
@@ -314,6 +416,102 @@ describe(`Plugins`, () => {
314416
await expect(readManifest(path)).resolves.not.toHaveProperty(`${type}.@types/is-number`);
315417
}),
316418
);
419+
420+
test(
421+
`it should automatically remove @types from ${type} with tsconfig.json present`,
422+
makeTemporaryEnv(merge({
423+
dependencies: {
424+
[`is-number`]: `^1.0.0`,
425+
},
426+
}, {
427+
[type]: {
428+
[`@types/is-number`]: `1.0.0`,
429+
},
430+
}), {}, async ({path, run, source}) => {
431+
await xfs.writeFilePromise(ppath.join(path, `tsconfig.json`), ``);
432+
433+
await run(`remove`, `is-number`);
434+
435+
await expect(readManifest(path)).resolves.not.toHaveProperty(`${type}.@types/is-number`);
436+
}),
437+
);
438+
439+
test(
440+
`it should not automatically remove @types ${type} from the current workspace without tsconfig.json present or tsEnableAutoTypes`,
441+
makeTemporaryMonorepoEnv({
442+
workspaces: [`packages/*`],
443+
},
444+
merge(
445+
{[`packages/foo`]: {dependencies: {[`is-number`]: `^1.0.0`}}},
446+
{[`packages/foo`]: {[type]: {[`@types/is-number`]: `1.0.0`}}},
447+
),
448+
async ({path, run, source}) => {
449+
await run(`remove`, `is-number`, {
450+
cwd: `${path}/packages/foo` as PortablePath,
451+
});
452+
453+
await expect(readManifest(`${path}/packages/foo` as PortablePath)).resolves.toHaveProperty(`${type}.@types/is-number`);
454+
}),
455+
);
456+
457+
test(
458+
`it should automatically remove @types ${type} from the current workspace when a tsconfig is detected in the root project of the current workspace`,
459+
makeTemporaryMonorepoEnv({
460+
workspaces: [`packages/*`],
461+
},
462+
merge(
463+
{[`packages/foo`]: {dependencies: {[`is-number`]: `^1.0.0`}}},
464+
{[`packages/foo`]: {[type]: {[`@types/is-number`]: `1.0.0`}}},
465+
),
466+
async ({path, run, source}) => {
467+
await xfs.writeFilePromise(ppath.join(path, `tsconfig.json`), ``);
468+
469+
await run(`remove`, `is-number`, {
470+
cwd: `${path}/packages/foo` as PortablePath,
471+
});
472+
473+
await expect(readManifest(`${path}/packages/foo` as PortablePath)).resolves.not.toHaveProperty(`${type}.@types/is-number`);
474+
}),
475+
);
476+
477+
test(
478+
`it should automatically remove @types ${type} from the current workspace with tsEnableAutoTypes set to true`,
479+
makeTemporaryMonorepoEnv({
480+
workspaces: [`packages/*`],
481+
},
482+
merge(
483+
{[`packages/foo`]: {dependencies: {[`is-number`]: `^1.0.0`}}},
484+
{[`packages/foo`]: {[type]: {[`@types/is-number`]: `1.0.0`}}},
485+
),
486+
async ({path, run, source}) => {
487+
await run(`config`, `set`, `tsEnableAutoTypes`, `true`);
488+
await run(`remove`, `is-number`, {
489+
cwd: `${path}/packages/foo` as PortablePath,
490+
});
491+
492+
await expect(readManifest(`${path}/packages/foo` as PortablePath)).resolves.not.toHaveProperty(`${type}.@types/is-number`);
493+
}),
494+
);
495+
496+
test(
497+
`it should automatically remove @types ${type} from the current workspace with tsconfig.json present`,
498+
makeTemporaryMonorepoEnv({
499+
workspaces: [`packages/*`],
500+
},
501+
merge(
502+
{[`packages/foo`]: {dependencies: {[`is-number`]: `^1.0.0`}}},
503+
{[`packages/foo`]: {[type]: {[`@types/is-number`]: `1.0.0`}}},
504+
),
505+
async ({path, run, source}) => {
506+
await xfs.writeFilePromise(ppath.join(path, `packages/foo/tsconfig.json`), ``);
507+
508+
await run(`remove`, `is-number`, {
509+
cwd: `${path}/packages/foo` as PortablePath,
510+
});
511+
512+
await expect(readManifest(`${path}/packages/foo` as PortablePath)).resolves.not.toHaveProperty(`${type}.@types/is-number`);
513+
}),
514+
);
317515
}
318516

319517
test(

packages/docusaurus/static/configuration/yarnrc.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,7 @@
835835
"tsEnableAutoTypes": {
836836
"_package": "@yarnpkg/plugin-typescript",
837837
"title": "Define whether to automatically install @types dependencies.",
838-
"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.",
838+
"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.",
839839
"type": "boolean",
840840
"examples": [true]
841841
},

packages/plugin-typescript/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99

1010
This plugin is included by default starting from Yarn 4.
1111

12+
## Configuration
13+
14+
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.
15+
1216
## Example
1317

1418
```

packages/plugin-typescript/sources/index.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ const afterWorkspaceDependencyAddition = async (
2626
const {project} = workspace;
2727
const {configuration} = project;
2828

29-
const tsEnableAutoTypes = configuration.get(`tsEnableAutoTypes`)
30-
?? xfs.existsSync(ppath.join(project.cwd, `tsconfig.json`));
29+
const tsEnableAutoTypes = configuration.get(`tsEnableAutoTypes`) ?? (
30+
xfs.existsSync(ppath.join(workspace.cwd, `tsconfig.json`))
31+
|| xfs.existsSync(ppath.join(project.cwd, `tsconfig.json`))
32+
);
3133

3234
if (!tsEnableAutoTypes)
3335
return;
@@ -118,8 +120,10 @@ const afterWorkspaceDependencyRemoval = async (
118120
const {project} = workspace;
119121
const {configuration} = project;
120122

121-
const tsEnableAutoTypes = configuration.get(`tsEnableAutoTypes`)
122-
?? xfs.existsSync(ppath.join(project.cwd, `tsconfig.json`));
123+
const tsEnableAutoTypes = configuration.get(`tsEnableAutoTypes`) ?? (
124+
xfs.existsSync(ppath.join(workspace.cwd, `tsconfig.json`))
125+
|| xfs.existsSync(ppath.join(project.cwd, `tsconfig.json`))
126+
);
123127

124128
if (!tsEnableAutoTypes)
125129
return;

0 commit comments

Comments
 (0)