Skip to content

Commit f53f17f

Browse files
authoredDec 13, 2023
Use package dependencies to manage TypeScript, instead of $HOME/.dts (#848)
1 parent 99c345a commit f53f17f

19 files changed

+233
-141
lines changed
 

‎.changeset/bright-rats-fetch.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@definitelytyped/typescript-packages": patch
3+
"@definitelytyped/dtslint-runner": patch
4+
"@definitelytyped/dtslint": patch
5+
"@definitelytyped/utils": patch
6+
---
7+
8+
Use package dependencies to manage TypeScript, instead of `$HOME/.dts`

‎.changeset/swift-shoes-shout.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@definitelytyped/typescript-packages": patch
3+
---
4+
5+
Add package

‎.knip.jsonc

+17
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,23 @@
5757
"entry": "src/index.ts",
5858
"project": "**/*.ts"
5959
},
60+
"packages/typescript-packages": {
61+
"entry": "src/index.ts",
62+
"project": "**/*.ts",
63+
"ignoreDependencies": [
64+
// A regex should work, but doesn't.
65+
"typescript-4.5",
66+
"typescript-4.6",
67+
"typescript-4.7",
68+
"typescript-4.8",
69+
"typescript-4.9",
70+
"typescript-5.0",
71+
"typescript-5.1",
72+
"typescript-5.2",
73+
"typescript-5.3",
74+
"typescript-5.4"
75+
]
76+
},
6077
"packages/typescript-versions": {
6178
"entry": "src/index.ts",
6279
"project": "**/*.ts"

‎packages/dtslint-runner/src/main.ts

-10
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import {
44
joinPaths,
55
runWithListeningChildProcesses,
66
CrashRecoveryState,
7-
installAllTypeScriptVersions,
8-
installTypeScriptNext,
97
} from "@definitelytyped/utils";
108
import fs from "fs";
119
import { RunDTSLintOptions } from "./types";
@@ -48,14 +46,6 @@ export async function runDTSLint({
4846
? await prepareAffectedPackages(definitelyTypedPath)
4947
: await prepareAllPackages(definitelyTypedPath, definitelyTypedAcquisition.kind === "clone");
5048

51-
if (!noInstall && !localTypeScriptPath) {
52-
if (onlyTestTsNext) {
53-
await installTypeScriptNext();
54-
} else {
55-
await installAllTypeScriptVersions();
56-
}
57-
}
58-
5949
const allFailures: [string, string][] = [];
6050
const expectedFailures = getExpectedFailures(onlyRunAffectedPackages, dependents);
6151

‎packages/dtslint/src/index.ts

+4-27
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,7 @@ import assert = require("assert");
55
import fs from "fs";
66
import { basename, dirname, join as joinPaths, resolve } from "path";
77

8-
import {
9-
cleanTypeScriptInstalls,
10-
deepEquals,
11-
installAllTypeScriptVersions,
12-
installTypeScriptNext,
13-
} from "@definitelytyped/utils";
8+
import { deepEquals } from "@definitelytyped/utils";
149
import { checkPackageJson, checkTsconfig } from "./checks";
1510
import { checkTslintJson, lint, TsVersion } from "./lint";
1611
import { getCompilerOptions, packageNameFromPath } from "./util";
@@ -43,12 +38,6 @@ async function main(): Promise<void> {
4338
continue;
4439
}
4540
switch (arg) {
46-
case "--installAll":
47-
console.log("Cleaning old installs and installing for all TypeScript versions...");
48-
console.log("Working...");
49-
await cleanTypeScriptInstalls();
50-
await installAllTypeScriptVersions();
51-
return;
5241
case "--localTs":
5342
lookingForTsLocal = true;
5443
break;
@@ -88,44 +77,32 @@ async function main(): Promise<void> {
8877
}
8978

9079
if (shouldListen) {
91-
listen(dirPath, tsLocal, onlyTestTsNext);
80+
listen(dirPath, tsLocal);
9281
} else {
93-
await installTypeScriptAsNeeded(tsLocal, onlyTestTsNext);
9482
await runTests(dirPath, onlyTestTsNext, expectOnly, tsLocal);
9583
}
9684
}
9785

98-
async function installTypeScriptAsNeeded(tsLocal: string | undefined, onlyTestTsNext: boolean): Promise<void> {
99-
if (tsLocal) return;
100-
if (onlyTestTsNext) {
101-
return installTypeScriptNext();
102-
}
103-
return installAllTypeScriptVersions();
104-
}
105-
10686
function usage(): void {
107-
console.error("Usage: dtslint [--version] [--installAll] [--onlyTestTsNext] [--expectOnly] [--localTs path]");
87+
console.error("Usage: dtslint [--version] [--onlyTestTsNext] [--expectOnly] [--localTs path]");
10888
console.error("Args:");
10989
console.error(" --version Print version and exit.");
110-
console.error(" --installAll Cleans and installs all TypeScript versions.");
11190
console.error(" --expectOnly Run only the ExpectType lint rule.");
11291
console.error(" --onlyTestTsNext Only run with `typescript@next`, not with the minimum version.");
11392
console.error(" --localTs path Run with *path* as the latest version of TS.");
11493
console.error("");
11594
console.error("onlyTestTsNext and localTs are (1) mutually exclusive and (2) test a single version of TS");
11695
}
11796

118-
function listen(dirPath: string, tsLocal: string | undefined, alwaysOnlyTestTsNext: boolean): void {
97+
function listen(dirPath: string, tsLocal: string | undefined): void {
11998
// Don't await this here to ensure that messages sent during installation aren't dropped.
120-
const installationPromise = installTypeScriptAsNeeded(tsLocal, alwaysOnlyTestTsNext);
12199
process.on("message", async (message: unknown) => {
122100
const { path, onlyTestTsNext, expectOnly } = message as {
123101
path: string;
124102
onlyTestTsNext: boolean;
125103
expectOnly?: boolean;
126104
};
127105

128-
await installationPromise;
129106
runTests(joinPaths(dirPath, path), onlyTestTsNext, !!expectOnly, tsLocal)
130107
.catch((e) => e.stack)
131108
.then((maybeError) => {
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
src
2+
test
3+
logs
4+
.DS_Store
5+
.vscode
6+
*.tsbuildinfo
7+
tsconfig.json
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# @definitelytyped/typescript-packages
2+
3+
Reexport of all supported TypeScript versions.
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "@definitelytyped/typescript-packages",
3+
"version": "0.0.1",
4+
"description": "Reexport of all supported TypeScript versions",
5+
"author": "Andrew Branch <andrew@wheream.io>",
6+
"homepage": "https://github.com/microsoft/DefinitelyTyped-tools/tree/master/packages/typescript-packages#readme",
7+
"license": "MIT",
8+
"main": "dist/index.js",
9+
"publishConfig": {
10+
"access": "public"
11+
},
12+
"repository": {
13+
"type": "git",
14+
"url": "https://github.com/microsoft/DefinitelyTyped-tools.git",
15+
"directory": "packages/typescript-packages"
16+
},
17+
"bugs": {
18+
"url": "https://github.com/microsoft/DefinitelyTyped-tools/issues"
19+
},
20+
"engines": {
21+
"node": ">=16.17.0"
22+
},
23+
"dependencies": {
24+
"@definitelytyped/typescript-versions": "workspace:*",
25+
"typescript-4.6": "npm:typescript@~4.6.0-0",
26+
"typescript-4.7": "npm:typescript@~4.7.0-0",
27+
"typescript-4.8": "npm:typescript@~4.8.0-0",
28+
"typescript-4.9": "npm:typescript@~4.9.0-0",
29+
"typescript-5.0": "npm:typescript@~5.0.0-0",
30+
"typescript-5.1": "npm:typescript@~5.1.0-0",
31+
"typescript-5.2": "npm:typescript@~5.2.0-0",
32+
"typescript-5.3": "npm:typescript@~5.3.0-0",
33+
"typescript-5.4": "npm:typescript@~5.4.0-0"
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { TypeScriptVersion } from "@definitelytyped/typescript-versions";
2+
3+
export function resolve(version: TypeScriptVersion) {
4+
return require.resolve(`typescript-${version}`);
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { TypeScriptVersion } from "@definitelytyped/typescript-versions";
2+
import { resolve } from "../src";
3+
4+
describe("package.json", () => {
5+
it("must contain correct dependencies", () => {
6+
const dependencies = require("../package.json").dependencies as Record<string, string>;
7+
const typescripts = new Map<string, string>(
8+
Object.entries(dependencies).filter(([name]) => name.startsWith("typescript-")),
9+
);
10+
11+
for (const version of TypeScriptVersion.supported) {
12+
const name = `typescript-${version}`;
13+
const entry = typescripts.get(name);
14+
expect(entry).toBe(`npm:typescript@~${version}.0-0`);
15+
typescripts.delete(name);
16+
}
17+
18+
expect([...typescripts]).toStrictEqual([]);
19+
});
20+
});
21+
22+
describe("resolve", () => {
23+
it("resolves to the right version", () => {
24+
for (const version of TypeScriptVersion.supported) {
25+
const ts = require(resolve(version));
26+
expect(typeof ts.versionMajorMinor).toBe("string");
27+
expect(ts.versionMajorMinor).toBe(version);
28+
}
29+
});
30+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"extends": "../../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"types": ["node", "jest"],
5+
"composite": false,
6+
"noEmit": true
7+
},
8+
"references": [
9+
{ "path": ".." }
10+
],
11+
"exclude": ["fixtures"]
12+
}
13+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"rootDir": "src",
5+
"outDir": "dist"
6+
},
7+
"include": ["src"]
8+
}

‎packages/typescript-versions/src/index.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,22 @@ import assert from "assert";
88
99
1. Add a new version to the end of `TypeScriptVersion` and `supported`.
1010
`supported` now contains the shipped versions, the RC, and the nightly.
11-
2. Update failing tests.
11+
2. Add the new version to `packages/typescript-packages/package.json`.
12+
3. Update failing tests.
1213
1314
For the release:
1415
1516
1. Move the newly-released version from `supported` to `shipped`.
1617
`supported` now contains the shipped versions and the nightly.
17-
2. Update failing tests.
18+
2. Add the new version to `packages/typescript-packages/package.json`.
19+
3. Update failing tests.
1820
1921
# How to deprecate an old version on Definitely Typed #
2022
2123
1. Move the old version from `TypeScriptVersion` to `UnsupportedTypeScriptVersion`.
2224
2. Move the old version from `shipped` to `unsupported`.
23-
3. Update failing tests.
25+
3. Remove the old version from `packages/typescript-packages/package.json`.
26+
4. Update failing tests.
2427
2528
Currently, it's possible to release a new version and deprecate an old version
2629
at the same time because of the way release schedule overlaps.

‎packages/utils/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
},
2121
"dependencies": {
2222
"@definitelytyped/typescript-versions": "workspace:*",
23+
"@definitelytyped/typescript-packages": "workspace:*",
2324
"@qiwi/npm-registry-client": "^8.9.1",
2425
"@types/node": "^16.18.61",
2526
"charm": "^1.0.2",
+3-83
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,11 @@
1-
import assert = require("assert");
2-
import { exec } from "child_process";
3-
import * as fs from "fs";
4-
import * as os from "os";
5-
import * as path from "path";
6-
import * as process from "process";
71
import { TypeScriptVersion } from "@definitelytyped/typescript-versions";
2+
import * as typeScriptPackages from "@definitelytyped/typescript-packages";
83

94
export type TsVersion = TypeScriptVersion | "local";
105

11-
const installsDir = path.join(os.homedir(), ".dts", "typescript-installs");
12-
13-
export async function installAllTypeScriptVersions() {
14-
for (const v of TypeScriptVersion.shipped) {
15-
await install(v);
16-
}
17-
// `shipped + [rc, next] == supported` during the RC period. During that time, typescript@rc needs to be installed too.
18-
if (TypeScriptVersion.shipped.length + 2 === TypeScriptVersion.supported.length) {
19-
await install("rc");
20-
}
21-
await installTypeScriptNext();
22-
}
23-
24-
export async function installTypeScriptNext() {
25-
await install("next");
26-
}
27-
28-
export async function install(version: TsVersion | "next" | "rc"): Promise<void> {
29-
if (version === "local") {
30-
return;
31-
}
32-
const dir = installDir(version);
33-
if (!fs.existsSync(dir)) {
34-
console.log(`Installing to ${dir}...`);
35-
await fs.promises.mkdir(dir, { recursive: true });
36-
await fs.promises.writeFile(
37-
path.join(dir, "package.json"),
38-
JSON.stringify({
39-
description: `Installs typescript@${version}`,
40-
repository: "N/A",
41-
license: "MIT",
42-
dependencies: {
43-
typescript: version,
44-
},
45-
}),
46-
);
47-
await execAndThrowErrors("npm install --ignore-scripts --no-shrinkwrap --no-package-lock --no-bin-links", dir);
48-
console.log("Installed!");
49-
console.log("");
50-
}
51-
}
52-
53-
export function cleanTypeScriptInstalls(): Promise<void> {
54-
return fs.promises.rm(installsDir, { recursive: true, force: true });
55-
}
56-
57-
export function typeScriptPath(version: TsVersion | "next" | "rc", tsLocal: string | undefined): string {
6+
export function typeScriptPath(version: TsVersion, tsLocal: string | undefined): string {
587
if (version === "local") {
598
return tsLocal! + "/typescript.js";
609
}
61-
return path.join(installDir(version), "node_modules", "typescript");
62-
}
63-
64-
function installDir(version: TsVersion | "next" | "rc"): string {
65-
assert(version !== "local");
66-
if (version === "next") version = TypeScriptVersion.latest;
67-
if (version === "rc") version = TypeScriptVersion.supported[TypeScriptVersion.supported.length - 2];
68-
return path.join(installsDir, version);
69-
}
70-
71-
/** Run a command and return the stdout, or if there was an error, throw. */
72-
async function execAndThrowErrors(cmd: string, cwd?: string): Promise<void> {
73-
// tslint:disable-next-line:promise-must-complete
74-
return new Promise<void>((resolve, reject) => {
75-
const env = { ...process.env };
76-
if (env.NODE_OPTIONS && env.NODE_OPTIONS.includes("--require")) {
77-
delete env.NODE_OPTIONS;
78-
}
79-
exec(cmd, { encoding: "utf8", cwd, env }, (err, _stdout, stderr) => {
80-
if (stderr) {
81-
console.error(stderr);
82-
}
83-
84-
if (err) {
85-
reject(err);
86-
} else {
87-
resolve();
88-
}
89-
});
90-
});
10+
return typeScriptPackages.resolve(version);
9111
}

‎packages/utils/test/typescript-installer.test.ts

-17
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.