mirror of
https://github.com/chenasraf/DefinitelyTyped-tools.git
synced 2026-05-18 01:49:03 +00:00
Merge branch 'master' into gabritto/reportResults
This commit is contained in:
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@@ -1,4 +1,3 @@
|
||||
{
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"typescript.tsdk": "/Developer/microsoft/TypeScript/built/local"
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "0.0.148-next.7",
|
||||
"version": "0.0.151-next.1",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
"@types/jest": "^25.1.3",
|
||||
"@types/node": "^14.14.37",
|
||||
"@types/yargs": "^15.0.4",
|
||||
"@typescript-eslint/eslint-plugin": "^4.8.1",
|
||||
"@typescript-eslint/parser": "^4.8.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.53.0",
|
||||
"@typescript-eslint/parser": "^5.53.0",
|
||||
"eslint": "^7.31.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jsdoc": "^30.7.8",
|
||||
|
||||
@@ -767,6 +767,9 @@ react-native-svg
|
||||
react-native-tab-view
|
||||
react-navigation
|
||||
react-popper
|
||||
react-router
|
||||
react-router-dom
|
||||
react-router-native
|
||||
recast
|
||||
recharts
|
||||
redis
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@definitelytyped/definitions-parser",
|
||||
"version": "0.0.148-next.5",
|
||||
"version": "0.0.151-next.1",
|
||||
"description": "Reads the DefinitelyTyped repository and provides an API for querying its metadata",
|
||||
"homepage": "https://github.com/microsoft/DefinitelyTyped-tools/tree/master/packages/definitions-parser#readme",
|
||||
"license": "MIT",
|
||||
@@ -19,9 +19,9 @@
|
||||
"url": "https://github.com/microsoft/DefinitelyTyped-tools/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@definitelytyped/header-parser": "^0.0.147",
|
||||
"@definitelytyped/typescript-versions": "^0.0.147",
|
||||
"@definitelytyped/utils": "^0.0.148-next.5",
|
||||
"@definitelytyped/header-parser": "^0.0.150",
|
||||
"@definitelytyped/typescript-versions": "^0.0.150",
|
||||
"@definitelytyped/utils": "^0.0.150",
|
||||
"@types/node": "^14.14.35",
|
||||
"fs-extra": "^9.1.0",
|
||||
"pacote": "^13.6.1",
|
||||
|
||||
@@ -3,6 +3,7 @@ import { DiskFS, downloadAndExtractFile, LoggerWithErrors, FS, exec } from "@def
|
||||
|
||||
import { dataDirPath, definitelyTypedZipUrl } from "./lib/settings";
|
||||
import { ExecException } from "child_process";
|
||||
import path from "path";
|
||||
|
||||
/** Settings that may be determined dynamically. */
|
||||
export interface ParseDefinitionsOptions {
|
||||
@@ -36,9 +37,9 @@ export async function getDefinitelyTyped(options: ParseDefinitionsOptions, log:
|
||||
throw new Error(`'git diff' should be empty. Following files changed:\n${stdout}`);
|
||||
}
|
||||
log.info(`Using local DefinitelyTyped at ${options.definitelyTypedPath}`);
|
||||
return new DiskFS(`${options.definitelyTypedPath}/`);
|
||||
return new DiskFS(`${path.resolve(options.definitelyTypedPath)}/`);
|
||||
}
|
||||
|
||||
export function getLocallyInstalledDefinitelyTyped(path: string): FS {
|
||||
return new DiskFS(`${path}/`);
|
||||
export function getLocallyInstalledDefinitelyTyped(definitelyTypedPath: string): FS {
|
||||
return new DiskFS(`${path.resolve(definitelyTypedPath)}/`);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import process = require("process");
|
||||
import { logUncaughtErrors } from "@definitelytyped/utils";
|
||||
import { getLocallyInstalledDefinitelyTyped } from "../get-definitely-typed";
|
||||
import { getTypingInfo } from "./definition-parser";
|
||||
import { dirname } from "path";
|
||||
|
||||
// This file is "called" by runWithChildProcesses from parse-definition.ts
|
||||
export const definitionParserWorkerFilename = __filename;
|
||||
@@ -14,10 +15,7 @@ if (!module.parent) {
|
||||
// tslint:disable-next-line no-async-without-await
|
||||
logUncaughtErrors(async () => {
|
||||
for (const packageName of message as readonly string[]) {
|
||||
const data = await getTypingInfo(
|
||||
packageName,
|
||||
getLocallyInstalledDefinitelyTyped(typesPath).subDir(packageName)
|
||||
);
|
||||
const data = await getTypingInfo(packageName, getLocallyInstalledDefinitelyTyped(dirname(typesPath)));
|
||||
process.send!({ data, packageName });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
TypingsDataRaw,
|
||||
TypingsVersionsRaw,
|
||||
DirectoryParsedTypingVersion,
|
||||
getMangledNameForScopedPackage,
|
||||
} from "../packages";
|
||||
import { getAllowedPackageJsonDependencies } from "./settings";
|
||||
import {
|
||||
@@ -27,8 +28,10 @@ import {
|
||||
removeVersionFromPackageName,
|
||||
hasVersionNumberInMapping,
|
||||
mangleScopedPackage,
|
||||
createModuleResolutionHost,
|
||||
} from "@definitelytyped/utils";
|
||||
import { TypeScriptVersion } from "@definitelytyped/typescript-versions";
|
||||
import path from "path";
|
||||
|
||||
function matchesVersion(
|
||||
typingsDataRaw: TypingsDataRaw,
|
||||
@@ -47,8 +50,7 @@ function formattedLibraryVersion(typingsDataRaw: TypingsDataRaw): `${number}.${n
|
||||
return `${typingsDataRaw.libraryMajorVersion}.${typingsDataRaw.libraryMinorVersion}`;
|
||||
}
|
||||
|
||||
/** @param fs Rooted at the package's directory, e.g. `DefinitelyTyped/types/abs` */
|
||||
export async function getTypingInfo(packageName: string, fs: FS): Promise<TypingsVersionsRaw> {
|
||||
export async function getTypingInfo(packageName: string, dt: FS): Promise<TypingsVersionsRaw> {
|
||||
if (packageName !== packageName.toLowerCase()) {
|
||||
throw new Error(`Package name \`${packageName}\` should be strictly lowercase`);
|
||||
}
|
||||
@@ -56,6 +58,8 @@ export async function getTypingInfo(packageName: string, fs: FS): Promise<Typing
|
||||
readonly directoryName: string;
|
||||
readonly version: DirectoryParsedTypingVersion;
|
||||
}
|
||||
|
||||
const fs = dt.subDir("types").subDir(getMangledNameForScopedPackage(packageName));
|
||||
const [rootDirectoryLs, olderVersionDirectories] = split<string, OlderVersionDir>(
|
||||
fs.readdir(),
|
||||
(fileOrDirectoryName) => {
|
||||
@@ -64,11 +68,12 @@ export async function getTypingInfo(packageName: string, fs: FS): Promise<Typing
|
||||
}
|
||||
);
|
||||
|
||||
const moduleResolutionHost = createModuleResolutionHost(dt);
|
||||
const considerLibraryMinorVersion = olderVersionDirectories.some(({ version }) => version.minor !== undefined);
|
||||
|
||||
const latestData: TypingsDataRaw = {
|
||||
libraryVersionDirectoryName: undefined,
|
||||
...(await combineDataForAllTypesVersions(packageName, rootDirectoryLs, fs, undefined)),
|
||||
...(await combineDataForAllTypesVersions(packageName, rootDirectoryLs, fs, undefined, moduleResolutionHost)),
|
||||
};
|
||||
|
||||
const older = await Promise.all(
|
||||
@@ -87,7 +92,13 @@ export async function getTypingInfo(packageName: string, fs: FS): Promise<Typing
|
||||
const ls = fs.readdir(directoryName);
|
||||
const data: TypingsDataRaw = {
|
||||
libraryVersionDirectoryName: formatTypingVersion(directoryVersion),
|
||||
...(await combineDataForAllTypesVersions(packageName, ls, fs.subDir(directoryName), directoryVersion)),
|
||||
...(await combineDataForAllTypesVersions(
|
||||
packageName,
|
||||
ls,
|
||||
fs.subDir(directoryName),
|
||||
directoryVersion,
|
||||
moduleResolutionHost
|
||||
)),
|
||||
};
|
||||
|
||||
if (!matchesVersion(data, directoryVersion, considerLibraryMinorVersion)) {
|
||||
@@ -193,9 +204,20 @@ async function combineDataForAllTypesVersions(
|
||||
typingsPackageName: string,
|
||||
ls: readonly string[],
|
||||
fs: FS,
|
||||
directoryVersion: DirectoryParsedTypingVersion | undefined
|
||||
directoryVersion: DirectoryParsedTypingVersion | undefined,
|
||||
moduleResolutionHost: ts.ModuleResolutionHost
|
||||
): Promise<Omit<TypingsDataRaw, "libraryVersionDirectoryName">> {
|
||||
const { remainingLs, typesVersions, hasPackageJson } = getTypesVersionsAndPackageJson(ls);
|
||||
const packageJson = hasPackageJson
|
||||
? (fs.readJson(packageJsonName) as {
|
||||
readonly license?: unknown;
|
||||
readonly dependencies?: unknown;
|
||||
readonly imports?: unknown;
|
||||
readonly exports?: unknown;
|
||||
readonly type?: unknown;
|
||||
})
|
||||
: {};
|
||||
const packageJsonType = checkPackageJsonType(packageJson.type, packageJsonName);
|
||||
|
||||
// Every typesVersion has an index.d.ts, but only the root index.d.ts should have a header.
|
||||
const {
|
||||
@@ -210,33 +232,23 @@ async function combineDataForAllTypesVersions(
|
||||
const dataForRoot = getTypingDataForSingleTypesVersion(
|
||||
undefined,
|
||||
typingsPackageName,
|
||||
fs.debugPath(),
|
||||
remainingLs,
|
||||
fs,
|
||||
directoryVersion
|
||||
directoryVersion,
|
||||
moduleResolutionHost
|
||||
);
|
||||
const dataForOtherTypesVersions = typesVersions.map((tsVersion) => {
|
||||
const subFs = fs.subDir(`ts${tsVersion}`);
|
||||
return getTypingDataForSingleTypesVersion(
|
||||
tsVersion,
|
||||
typingsPackageName,
|
||||
fs.debugPath(),
|
||||
subFs.readdir(),
|
||||
subFs,
|
||||
directoryVersion
|
||||
directoryVersion,
|
||||
moduleResolutionHost
|
||||
);
|
||||
});
|
||||
const allTypesVersions = [dataForRoot, ...dataForOtherTypesVersions];
|
||||
|
||||
const packageJson = hasPackageJson
|
||||
? (fs.readJson(packageJsonName) as {
|
||||
readonly license?: unknown;
|
||||
readonly dependencies?: unknown;
|
||||
readonly imports?: unknown;
|
||||
readonly exports?: unknown;
|
||||
readonly type?: unknown;
|
||||
})
|
||||
: {};
|
||||
const license = getLicenseFromPackageJson(packageJson.license);
|
||||
const packageJsonDependencies = await checkPackageJsonDependencies(packageJson.dependencies, packageJsonName);
|
||||
|
||||
@@ -271,7 +283,7 @@ async function combineDataForAllTypesVersions(
|
||||
declaredModules: getAllUniqueValues<"declaredModules", string>(allTypesVersions, "declaredModules"),
|
||||
imports: checkPackageJsonImports(packageJson.imports, packageJsonName),
|
||||
exports: checkPackageJsonExportsAndAddPJsonEntry(packageJson.exports, packageJsonName),
|
||||
type: checkPackageJsonType(packageJson.type, packageJsonName),
|
||||
type: packageJsonType,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -300,19 +312,33 @@ interface TypingDataFromIndividualTypeScriptVersion {
|
||||
function getTypingDataForSingleTypesVersion(
|
||||
typescriptVersion: TypeScriptVersion | undefined,
|
||||
packageName: string,
|
||||
packageDirectory: string,
|
||||
ls: readonly string[],
|
||||
fs: FS,
|
||||
directoryVersion: DirectoryParsedTypingVersion | undefined
|
||||
directoryVersion: DirectoryParsedTypingVersion | undefined,
|
||||
moduleResolutionHost: ts.ModuleResolutionHost
|
||||
): TypingDataFromIndividualTypeScriptVersion {
|
||||
const tsconfig = fs.readJson("tsconfig.json") as TsConfig;
|
||||
const configHost: ts.ParseConfigHost = {
|
||||
...moduleResolutionHost,
|
||||
readDirectory: (dir) => fs.readdir(dir),
|
||||
useCaseSensitiveFileNames: true,
|
||||
};
|
||||
|
||||
const compilerOptions = ts.parseJsonConfigFileContent(
|
||||
tsconfig,
|
||||
configHost,
|
||||
path.resolve("/", fs.debugPath())
|
||||
).options;
|
||||
checkFilesFromTsConfig(packageName, tsconfig, fs.debugPath());
|
||||
|
||||
const { types, tests, hasNonRelativeImports } = allReferencedFiles(
|
||||
tsconfig.files!,
|
||||
fs,
|
||||
packageName,
|
||||
packageDirectory
|
||||
moduleResolutionHost,
|
||||
compilerOptions
|
||||
);
|
||||
|
||||
const usedFiles = new Set([...types.keys(), ...tests.keys(), "tsconfig.json", "tslint.json"]);
|
||||
const otherFiles = ls.includes(unusedFilesName)
|
||||
? fs
|
||||
@@ -336,7 +362,10 @@ function getTypingDataForSingleTypesVersion(
|
||||
)) {
|
||||
// add d.ts files from OTHER_FILES.txt in order get their dependencies
|
||||
// tslint:disable-next-line:non-literal-fs-path -- Not a reference to the fs package
|
||||
types.set(untestedTypeFile, createSourceFile(untestedTypeFile, fs.readFile(untestedTypeFile)));
|
||||
types.set(
|
||||
untestedTypeFile,
|
||||
createSourceFile(untestedTypeFile, fs.readFile(untestedTypeFile), moduleResolutionHost, compilerOptions)
|
||||
);
|
||||
}
|
||||
|
||||
const { dependencies: dependenciesWithDeclaredModules, globals, declaredModules } = getModuleInfo(packageName, types);
|
||||
@@ -348,7 +377,9 @@ function getTypingDataForSingleTypesVersion(
|
||||
.map((m) => rootName(m, types, packageName))
|
||||
.filter((dependency) => dependency !== packageName)
|
||||
);
|
||||
const testDependencies = [...getTestDependencies(packageName, tests.keys(), dependenciesSet, fs)]
|
||||
const testDependencies = [
|
||||
...getTestDependencies(packageName, tests.keys(), dependenciesSet, fs, moduleResolutionHost, compilerOptions),
|
||||
]
|
||||
.filter((m) => !declaredModulesSet.has(m))
|
||||
.map((m) => rootName(m, types, packageName))
|
||||
.filter((dependency) => dependency !== packageName);
|
||||
@@ -774,7 +805,7 @@ function checkAllUsedRecur(ls: Iterable<string>, usedFiles: Set<string>, unusedF
|
||||
for (const unusedFile of unusedFiles) {
|
||||
if (usedFiles.has(unusedFile)) {
|
||||
throw new Error(
|
||||
`File ${fs.debugPath()}/${unusedFile} listed in ${unusedFilesName} is already reachable from tsconfig.json.`
|
||||
`File ${fs.debugPath()}${unusedFile} listed in ${unusedFilesName} is already reachable from tsconfig.json.`
|
||||
);
|
||||
}
|
||||
throw new Error(`File ${fs.debugPath()}/${unusedFile} listed in ${unusedFilesName} does not exist.`);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import assert = require("assert");
|
||||
import * as path from "path";
|
||||
import * as ts from "typescript";
|
||||
import { sort, joinPaths, FS, normalizeSlashes, hasWindowsSlashes } from "@definitelytyped/utils";
|
||||
import { sort, joinPaths, FS, hasWindowsSlashes, assertDefined } from "@definitelytyped/utils";
|
||||
|
||||
import { readFileAndThrowOnBOM } from "./definition-parser";
|
||||
import { getMangledNameForScopedPackage } from "../packages";
|
||||
@@ -19,7 +19,7 @@ export function getModuleInfo(packageName: string, all: Map<string, ts.SourceFil
|
||||
|
||||
for (const sourceFile of all.values()) {
|
||||
for (const ref of imports(sourceFile)) {
|
||||
addDependency(ref);
|
||||
addDependency(ref.text);
|
||||
}
|
||||
for (const ref of sourceFile.typeReferenceDirectives) {
|
||||
addDependency(ref.fileName);
|
||||
@@ -130,72 +130,110 @@ export function allReferencedFiles(
|
||||
entryFilenames: readonly string[],
|
||||
fs: FS,
|
||||
packageName: string,
|
||||
baseDirectory: string
|
||||
moduleResolutionHost: ts.ModuleResolutionHost,
|
||||
compilerOptions: ts.CompilerOptions
|
||||
): { types: Map<string, ts.SourceFile>; tests: Map<string, ts.SourceFile>; hasNonRelativeImports: boolean } {
|
||||
const seenReferences = new Set<string>();
|
||||
const types = new Map<string, ts.SourceFile>();
|
||||
const tests = new Map<string, ts.SourceFile>();
|
||||
// The directory where the tsconfig/index.d.ts is - i.e., may be a version within the package
|
||||
const baseDirectory = path.resolve("/", fs.debugPath());
|
||||
// The root of the package and all versions, i.e., the direct subdirectory of types/
|
||||
const packageDirectory = baseDirectory.slice(
|
||||
0,
|
||||
baseDirectory.lastIndexOf(`types/${getMangledNameForScopedPackage(packageName)}`) +
|
||||
`types/${getMangledNameForScopedPackage(packageName)}`.length
|
||||
);
|
||||
let hasNonRelativeImports = false;
|
||||
entryFilenames.forEach((text) => recur({ text, exact: true }));
|
||||
entryFilenames.forEach((fileName) => recur(undefined, { text: fileName, kind: "path" }));
|
||||
return { types, tests, hasNonRelativeImports };
|
||||
|
||||
function recur({ text, exact }: Reference): void {
|
||||
const resolvedFilename = exact ? text : resolveModule(text, fs);
|
||||
if (seenReferences.has(resolvedFilename)) {
|
||||
function recur(containingFileName: string | undefined, ref: Reference): void {
|
||||
// An absolute file name for use with TS resolution, e.g. '/DefinitelyTyped/types/foo/index.d.ts'
|
||||
const resolvedFileName = resolveReference(containingFileName, ref);
|
||||
|
||||
if (!resolvedFileName) {
|
||||
return;
|
||||
}
|
||||
seenReferences.add(resolvedFilename);
|
||||
|
||||
if (seenReferences.has(resolvedFileName)) {
|
||||
return;
|
||||
}
|
||||
seenReferences.add(resolvedFileName);
|
||||
|
||||
// E.g. 'index.d.ts' - suitable for lookups in `fs` and for our result
|
||||
const relativeFileName = path.relative(baseDirectory, resolvedFileName);
|
||||
if (path.relative(packageDirectory, resolvedFileName).startsWith("..")) {
|
||||
throw new Error(
|
||||
`${containingFileName ?? "tsconfig.json"}: ` +
|
||||
'Definitions must use global references to other packages, not parent ("../xxx") references.' +
|
||||
`(Based on reference '${ref.text}')`
|
||||
);
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:non-literal-fs-path -- Not a reference to the fs package
|
||||
if (fs.exists(resolvedFilename)) {
|
||||
const src = createSourceFile(resolvedFilename, readFileAndThrowOnBOM(resolvedFilename, fs));
|
||||
if (fs.exists(relativeFileName)) {
|
||||
const src = createSourceFile(
|
||||
resolvedFileName,
|
||||
readFileAndThrowOnBOM(relativeFileName, fs),
|
||||
moduleResolutionHost,
|
||||
compilerOptions
|
||||
);
|
||||
if (
|
||||
resolvedFilename.endsWith(".d.ts") ||
|
||||
resolvedFilename.endsWith(".d.mts") ||
|
||||
resolvedFilename.endsWith(".d.cts")
|
||||
relativeFileName.endsWith(".d.ts") ||
|
||||
relativeFileName.endsWith(".d.mts") ||
|
||||
relativeFileName.endsWith(".d.cts")
|
||||
) {
|
||||
types.set(resolvedFilename, src);
|
||||
types.set(relativeFileName, src);
|
||||
} else {
|
||||
tests.set(resolvedFilename, src);
|
||||
tests.set(relativeFileName, src);
|
||||
}
|
||||
|
||||
const { refs, hasNonRelativeImports: result } = findReferencedFiles(
|
||||
src,
|
||||
packageName,
|
||||
path.dirname(resolvedFilename),
|
||||
normalizeSlashes(path.relative(baseDirectory, fs.debugPath()))
|
||||
);
|
||||
refs.forEach(recur);
|
||||
const { refs, hasNonRelativeImports: result } = findReferencedFiles(src, packageName);
|
||||
refs.forEach((ref) => recur(resolvedFileName, ref));
|
||||
hasNonRelativeImports = hasNonRelativeImports || result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resolveModule(importSpecifier: string, fs: FS): string {
|
||||
importSpecifier = importSpecifier.endsWith("/")
|
||||
? importSpecifier.slice(0, importSpecifier.length - 1)
|
||||
: importSpecifier;
|
||||
if (importSpecifier !== "." && importSpecifier !== "..") {
|
||||
// tslint:disable-next-line:non-literal-fs-path -- Not a reference to the fs package
|
||||
if (fs.exists(importSpecifier + ".d.ts")) {
|
||||
return importSpecifier + ".d.ts";
|
||||
}
|
||||
// tslint:disable-next-line:non-literal-fs-path -- Not a reference to the fs package
|
||||
if (fs.exists(importSpecifier + ".ts")) {
|
||||
return importSpecifier + ".ts";
|
||||
}
|
||||
// tslint:disable-next-line:non-literal-fs-path -- Not a reference to the fs package
|
||||
if (fs.exists(importSpecifier + ".tsx")) {
|
||||
return importSpecifier + ".tsx";
|
||||
function resolveReference(
|
||||
containingFileName: string | undefined,
|
||||
{ kind, text, resolutionMode }: Reference
|
||||
): string | undefined {
|
||||
switch (kind) {
|
||||
case "path":
|
||||
if (containingFileName) {
|
||||
return ts.resolveTripleslashReference(text, containingFileName);
|
||||
} else {
|
||||
return path.resolve(baseDirectory, text);
|
||||
}
|
||||
case "types":
|
||||
return ts.resolveTypeReferenceDirective(
|
||||
text,
|
||||
assertDefined(containingFileName, "Must have a containing file to resolve a type reference directive"),
|
||||
compilerOptions,
|
||||
moduleResolutionHost,
|
||||
/*redirectedReference*/ undefined,
|
||||
/*cache*/ undefined,
|
||||
resolutionMode
|
||||
).resolvedTypeReferenceDirective?.resolvedFileName;
|
||||
case "import":
|
||||
return ts.resolveModuleName(
|
||||
text,
|
||||
assertDefined(containingFileName, "Must have an containing file to resolve an import"),
|
||||
compilerOptions,
|
||||
moduleResolutionHost,
|
||||
/*cache*/ undefined,
|
||||
/*redirectedReference*/ undefined,
|
||||
resolutionMode
|
||||
).resolvedModule?.resolvedFileName;
|
||||
}
|
||||
}
|
||||
return importSpecifier === "." ? "index.d.ts" : joinPaths(importSpecifier, "index.d.ts");
|
||||
}
|
||||
|
||||
interface Reference {
|
||||
/** <reference path> includes exact filename, so true. import "foo" may reference "foo.d.ts" or "foo/index.d.ts", so false. */
|
||||
readonly exact: boolean;
|
||||
kind: "path" | "import" | "types";
|
||||
text: string;
|
||||
resolutionMode?: ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,76 +241,40 @@ interface Reference {
|
||||
* For example, `baseDirectory` may be `react-router` and `subDirectory` may be `react-router/lib`.
|
||||
* versionsBaseDirectory may be "" when not in typesVersions or ".." when inside `react-router/ts3.1`
|
||||
*/
|
||||
function findReferencedFiles(src: ts.SourceFile, packageName: string, subDirectory: string, baseDirectory: string) {
|
||||
function findReferencedFiles(src: ts.SourceFile, packageName: string) {
|
||||
const refs: Reference[] = [];
|
||||
let hasNonRelativeImports = false;
|
||||
|
||||
for (const ref of src.referencedFiles) {
|
||||
// Any <reference path="foo"> is assumed to be local
|
||||
addReference({ text: ref.fileName, exact: true });
|
||||
refs.push({
|
||||
text: ref.fileName,
|
||||
kind: "path",
|
||||
resolutionMode: ref.resolutionMode,
|
||||
});
|
||||
}
|
||||
for (const ref of src.typeReferenceDirectives) {
|
||||
// only <reference types="../packagename/x" /> references are local (or "packagename/x", though in 3.7 that doesn't work in DT).
|
||||
if (ref.fileName.startsWith("../" + packageName + "/")) {
|
||||
addReference({ text: ref.fileName, exact: false });
|
||||
} else if (ref.fileName.startsWith(packageName + "/")) {
|
||||
addReference({ text: convertToRelativeReference(ref.fileName), exact: false });
|
||||
if (ref.fileName.startsWith("../" + packageName + "/") || ref.fileName.startsWith(packageName + "/")) {
|
||||
refs.push({ kind: "types", text: ref.fileName, resolutionMode: ref.resolutionMode });
|
||||
}
|
||||
}
|
||||
|
||||
for (const ref of imports(src)) {
|
||||
if (ref.startsWith(".")) {
|
||||
addReference({ text: ref, exact: false });
|
||||
} else if (getMangledNameForScopedPackage(ref).startsWith(packageName + "/")) {
|
||||
addReference({ text: convertToRelativeReference(ref), exact: false });
|
||||
hasNonRelativeImports = true;
|
||||
const resolutionMode = ts.getModeForUsageLocation(src, ref);
|
||||
if (ref.text.startsWith(".") || getMangledNameForScopedPackage(ref.text).startsWith(packageName + "/")) {
|
||||
refs.push({ kind: "import", text: ref.text, resolutionMode });
|
||||
hasNonRelativeImports = !ref.text.startsWith(".");
|
||||
}
|
||||
}
|
||||
return { refs, hasNonRelativeImports };
|
||||
|
||||
function addReference(ref: Reference): void {
|
||||
// `path.normalize` may add windows slashes
|
||||
let full = normalizeSlashes(
|
||||
path.normalize(joinPaths(subDirectory, assertNoWindowsSlashes(src.fileName, ref.text)))
|
||||
);
|
||||
// allow files in typesVersions directories (i.e. 'ts3.1') to reference files in parent directory
|
||||
if (full.startsWith("../" + packageName + "/")) {
|
||||
full = full.slice(packageName.length + 4);
|
||||
} else if (baseDirectory && full.startsWith("../" + baseDirectory + "/")) {
|
||||
full = full.slice(baseDirectory.length + 4);
|
||||
} else if (
|
||||
full.startsWith("..") &&
|
||||
(baseDirectory === "" || path.normalize(joinPaths(baseDirectory, full)).startsWith(".."))
|
||||
) {
|
||||
throw new Error(
|
||||
`${src.fileName}: ` +
|
||||
'Definitions must use global references to other packages, not parent ("../xxx") references.' +
|
||||
`(Based on reference '${ref.text}')`
|
||||
);
|
||||
}
|
||||
ref.text = full;
|
||||
refs.push(ref);
|
||||
}
|
||||
|
||||
/** boring/foo -> ./foo when subDirectory === '.'; ../foo when it's === 'x'; ../../foo when it's 'x/y' */
|
||||
function convertToRelativeReference(name: string) {
|
||||
let relative = ".";
|
||||
if (subDirectory !== ".") {
|
||||
relative += "/..".repeat(subDirectory.split("/").length);
|
||||
if (baseDirectory && subDirectory.startsWith("..")) {
|
||||
relative = relative.slice(0, -2) + baseDirectory;
|
||||
}
|
||||
}
|
||||
return relative + name.slice(packageName.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All strings referenced in `import` statements.
|
||||
* Does *not* include <reference> directives.
|
||||
*/
|
||||
function imports({ statements }: ts.SourceFile): Iterable<string> {
|
||||
const result: string[] = [];
|
||||
function imports({ statements }: ts.SourceFile): Iterable<ts.StringLiteralLike> {
|
||||
const result: ts.StringLiteralLike[] = [];
|
||||
for (const node of statements) {
|
||||
recur(node);
|
||||
}
|
||||
@@ -284,7 +286,7 @@ function imports({ statements }: ts.SourceFile): Iterable<string> {
|
||||
case ts.SyntaxKind.ExportDeclaration: {
|
||||
const { moduleSpecifier } = node as ts.ImportDeclaration | ts.ExportDeclaration;
|
||||
if (moduleSpecifier && moduleSpecifier.kind === ts.SyntaxKind.StringLiteral) {
|
||||
result.push((moduleSpecifier as ts.StringLiteral).text);
|
||||
result.push(moduleSpecifier as ts.StringLiteral);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -300,7 +302,7 @@ function imports({ statements }: ts.SourceFile): Iterable<string> {
|
||||
case ts.SyntaxKind.ImportType: {
|
||||
const { argument } = node as ts.ImportTypeNode;
|
||||
if (ts.isLiteralTypeNode(argument) && ts.isStringLiteral(argument.literal)) {
|
||||
result.push(argument.literal.text);
|
||||
result.push(argument.literal);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -311,12 +313,12 @@ function imports({ statements }: ts.SourceFile): Iterable<string> {
|
||||
}
|
||||
}
|
||||
|
||||
function parseRequire(reference: ts.ExternalModuleReference): string {
|
||||
function parseRequire(reference: ts.ExternalModuleReference): ts.StringLiteralLike {
|
||||
const { expression } = reference;
|
||||
if (!expression || !ts.isStringLiteral(expression)) {
|
||||
throw new Error(`Bad 'import =' reference: ${reference.getText()}`);
|
||||
}
|
||||
return expression.text;
|
||||
return expression;
|
||||
}
|
||||
|
||||
function isValueNamespace(ns: ts.ModuleDeclaration): boolean {
|
||||
@@ -360,12 +362,14 @@ export function getTestDependencies(
|
||||
packageName: string,
|
||||
testFiles: Iterable<string>,
|
||||
dependencies: ReadonlySet<string>,
|
||||
fs: FS
|
||||
fs: FS,
|
||||
moduleResolutionHost: ts.ModuleResolutionHost,
|
||||
compilerOptions: ts.CompilerOptions
|
||||
): Iterable<string> {
|
||||
const testDependencies = new Set<string>();
|
||||
for (const filename of testFiles) {
|
||||
const content = readFileAndThrowOnBOM(filename, fs);
|
||||
const sourceFile = createSourceFile(filename, content);
|
||||
const sourceFile = createSourceFile(filename, content, moduleResolutionHost, compilerOptions);
|
||||
const { fileName, referencedFiles, typeReferenceDirectives } = sourceFile;
|
||||
const filePath = () => path.join(packageName, fileName);
|
||||
let hasImports = false;
|
||||
@@ -388,8 +392,8 @@ export function getTestDependencies(
|
||||
}
|
||||
for (const imported of imports(sourceFile)) {
|
||||
hasImports = true;
|
||||
if (!imported.startsWith(".") && !dependencies.has(imported)) {
|
||||
testDependencies.add(imported);
|
||||
if (!imported.text.startsWith(".") && !dependencies.has(imported.text)) {
|
||||
testDependencies.add(imported.text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,6 +417,18 @@ export function getTestDependencies(
|
||||
return testDependencies;
|
||||
}
|
||||
|
||||
export function createSourceFile(filename: string, content: string): ts.SourceFile {
|
||||
return ts.createSourceFile(filename, content, ts.ScriptTarget.Latest, /*setParentNodes*/ false);
|
||||
export function createSourceFile(
|
||||
filename: string,
|
||||
content: string,
|
||||
moduleResolutionHost: ts.ModuleResolutionHost,
|
||||
compilerOptions: ts.CompilerOptions
|
||||
): ts.SourceFile {
|
||||
const file = ts.createSourceFile(filename, content, ts.ScriptTarget.Latest, /*setParentNodes*/ false);
|
||||
file.impliedNodeFormat = ts.getImpliedNodeFormatForFile(
|
||||
filename as ts.Path,
|
||||
/*packageJsonInfoCache*/ undefined,
|
||||
moduleResolutionHost,
|
||||
compilerOptions
|
||||
);
|
||||
return file;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { parseHeaderOrFail } from "@definitelytyped/header-parser";
|
||||
import { Dir, FS, InMemoryFS, mangleScopedPackage } from "@definitelytyped/utils";
|
||||
import * as semver from "semver";
|
||||
|
||||
class DTMock {
|
||||
export class DTMock {
|
||||
public readonly fs: FS;
|
||||
private readonly root: Dir;
|
||||
|
||||
@@ -19,7 +19,7 @@ class DTMock {
|
||||
},
|
||||
})
|
||||
);
|
||||
this.fs = new InMemoryFS(this.root, "DefinitelyTyped");
|
||||
this.fs = new InMemoryFS(this.root, "/DefinitelyTyped/");
|
||||
}
|
||||
|
||||
public pkgDir(packageName: string): Dir {
|
||||
@@ -172,12 +172,7 @@ untested.d.ts
|
||||
declare var x: number
|
||||
`
|
||||
);
|
||||
globby.set(
|
||||
"merges.d.ts",
|
||||
`
|
||||
declare var y: number
|
||||
`
|
||||
);
|
||||
|
||||
globby.set(
|
||||
"sneaky.d.ts",
|
||||
`
|
||||
@@ -194,7 +189,6 @@ var z = x;
|
||||
tests.set(
|
||||
"other-tests.ts",
|
||||
`
|
||||
/// <reference types="globby/merges" />
|
||||
var z = y;
|
||||
`
|
||||
);
|
||||
|
||||
@@ -40,7 +40,7 @@ export async function parseDefinitions(
|
||||
} else {
|
||||
log.info("Parsing in main process...");
|
||||
for (const packageName of packageNames) {
|
||||
typings[packageName] = await getTypingInfo(packageName, typesFS.subDir(packageName));
|
||||
typings[packageName] = await getTypingInfo(packageName, dt);
|
||||
}
|
||||
}
|
||||
log.info("Parsing took " + (Date.now() - start) / 1000 + " s");
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import path from "path";
|
||||
import { DiskFS } from "@definitelytyped/utils";
|
||||
import { createMockDT } from "../src/mocks";
|
||||
import { getTypingInfo } from "../src/lib/definition-parser";
|
||||
@@ -7,14 +8,14 @@ describe(getTypingInfo, () => {
|
||||
const dt = createMockDT();
|
||||
dt.addOldVersionOfPackage("jquery", "1.42");
|
||||
dt.addOldVersionOfPackage("jquery", "2");
|
||||
const info = await getTypingInfo("jquery", dt.pkgFS("jquery"));
|
||||
const info = await getTypingInfo("jquery", dt.fs);
|
||||
|
||||
expect(Object.keys(info).sort()).toEqual(["1.42", "2.0", "3.3"]);
|
||||
});
|
||||
|
||||
it("works for a package with dependencies", async () => {
|
||||
const dt = createMockDT();
|
||||
const info = await getTypingInfo("has-dependency", dt.pkgFS("has-dependency"));
|
||||
const info = await getTypingInfo("has-dependency", dt.fs);
|
||||
expect(info).toBeDefined();
|
||||
});
|
||||
|
||||
@@ -65,7 +66,7 @@ export function myFunction(arg:string): string;
|
||||
|
||||
dt.addOldVersionOfPackage("@ckeditor/ckeditor5-utils", "10");
|
||||
|
||||
const info = await getTypingInfo("@ckeditor/ckeditor5-engine", dt.pkgFS("ckeditor__ckeditor5-engine"));
|
||||
const info = await getTypingInfo("@ckeditor/ckeditor5-engine", dt.fs);
|
||||
expect(info).toBeDefined();
|
||||
});
|
||||
|
||||
@@ -124,7 +125,7 @@ export * from 'buffer';
|
||||
} `
|
||||
);
|
||||
|
||||
const info = await getTypingInfo("safer", dt.pkgFS("safer"));
|
||||
const info = await getTypingInfo("safer", dt.fs);
|
||||
expect(info).toBeDefined();
|
||||
expect(info["1.0"].dependencies).toEqual({ node: "*" });
|
||||
});
|
||||
@@ -189,7 +190,7 @@ const a = new webpack.AutomaticPrefetchPlugin();
|
||||
}`
|
||||
);
|
||||
|
||||
const info = await getTypingInfo("webpack", dt.pkgFS("webpack"));
|
||||
const info = await getTypingInfo("webpack", dt.fs);
|
||||
expect(info).toBeDefined();
|
||||
});
|
||||
|
||||
@@ -197,9 +198,7 @@ const a = new webpack.AutomaticPrefetchPlugin();
|
||||
return expect(
|
||||
getTypingInfo(
|
||||
"typeref-fails",
|
||||
new DiskFS(
|
||||
"packages/definitions-parser/test/fixtures/rejects-references-to-old-versions-of-other-types-packages/"
|
||||
)
|
||||
new DiskFS(path.resolve(__dirname, "fixtures/rejects-references-to-old-versions-of-other-types-packages/"))
|
||||
)
|
||||
).rejects.toThrow("do not directly import specific versions of another types package");
|
||||
});
|
||||
@@ -207,7 +206,7 @@ const a = new webpack.AutomaticPrefetchPlugin();
|
||||
it("allows references to old versions of self", async () => {
|
||||
const info = await getTypingInfo(
|
||||
"fail",
|
||||
new DiskFS("packages/definitions-parser/test/fixtures/allows-references-to-old-versions-of-self/")
|
||||
new DiskFS(path.resolve(__dirname, "fixtures/allows-references-to-old-versions-of-self/"))
|
||||
);
|
||||
expect(info).toBeDefined();
|
||||
});
|
||||
@@ -261,26 +260,33 @@ import route = require('@ember/routing/route');
|
||||
}`
|
||||
);
|
||||
|
||||
const info = await getTypingInfo("ember", dt.pkgFS("ember"));
|
||||
const info = await getTypingInfo("ember", dt.fs);
|
||||
expect(info["2.8"].testDependencies).toEqual([]);
|
||||
});
|
||||
|
||||
it("doesn't omit dependencies if only some deep modules are declared", async () => {
|
||||
const info = await getTypingInfo(
|
||||
"styled-components-react-native",
|
||||
new DiskFS(
|
||||
"packages/definitions-parser/test/fixtures/doesnt-omit-dependencies-if-only-some-deep-modules-are-declared/"
|
||||
)
|
||||
new DiskFS(path.resolve(__dirname, "fixtures/doesnt-omit-dependencies-if-only-some-deep-modules-are-declared/"))
|
||||
);
|
||||
expect(info["5.1"].dependencies).toEqual({ "styled-components": "*" });
|
||||
});
|
||||
|
||||
it("rejects relative references to other packages", async () => {
|
||||
expect(() =>
|
||||
getTypingInfo(
|
||||
"referencing",
|
||||
new DiskFS(path.resolve(__dirname, "fixtures/rejects-relative-references-to-other-packages/"))
|
||||
)
|
||||
).rejects.toThrow("Definitions must use global references to other packages");
|
||||
});
|
||||
|
||||
describe("concerning multiple versions", () => {
|
||||
it("records what the version directory looks like on disk", async () => {
|
||||
const dt = createMockDT();
|
||||
dt.addOldVersionOfPackage("jquery", "2");
|
||||
dt.addOldVersionOfPackage("jquery", "1.5");
|
||||
const info = await getTypingInfo("jquery", dt.pkgFS("jquery"));
|
||||
const info = await getTypingInfo("jquery", dt.fs);
|
||||
|
||||
expect(info).toEqual({
|
||||
"1.5": expect.objectContaining({
|
||||
@@ -300,7 +306,7 @@ import route = require('@ember/routing/route');
|
||||
const dt = createMockDT();
|
||||
dt.addOldVersionOfPackage("jquery", "2");
|
||||
dt.addOldVersionOfPackage("jquery", "1.5");
|
||||
const info = await getTypingInfo("jquery", dt.pkgFS("jquery"));
|
||||
const info = await getTypingInfo("jquery", dt.fs);
|
||||
|
||||
expect(info).toEqual({
|
||||
"1.5": expect.objectContaining({
|
||||
@@ -343,7 +349,7 @@ import route = require('@ember/routing/route');
|
||||
|
||||
dt.addOldVersionOfPackage("@ckeditor/ckeditor5-utils", "10");
|
||||
|
||||
const info = await getTypingInfo("@ckeditor/ckeditor5-utils", dt.pkgFS("ckeditor__ckeditor5-utils"));
|
||||
const info = await getTypingInfo("@ckeditor/ckeditor5-utils", dt.fs);
|
||||
expect(info).toEqual({
|
||||
"10.0": expect.objectContaining({
|
||||
pathMappings: {
|
||||
@@ -362,7 +368,7 @@ import route = require('@ember/routing/route');
|
||||
const dt = createMockDT();
|
||||
dt.addOldVersionOfPackage("jquery", "3");
|
||||
|
||||
return expect(getTypingInfo("jquery", dt.pkgFS("jquery"))).rejects.toThrow(
|
||||
return expect(getTypingInfo("jquery", dt.fs)).rejects.toThrow(
|
||||
"The latest version of the 'jquery' package is 3.3, so the subdirectory 'v3' is not allowed; " +
|
||||
"since it applies to any 3.* version, up to and including 3.3."
|
||||
);
|
||||
@@ -372,7 +378,7 @@ import route = require('@ember/routing/route');
|
||||
const dt = createMockDT();
|
||||
dt.addOldVersionOfPackage("jquery", "3.3");
|
||||
|
||||
return expect(getTypingInfo("jquery", dt.pkgFS("jquery"))).rejects.toThrow(
|
||||
return expect(getTypingInfo("jquery", dt.fs)).rejects.toThrow(
|
||||
"The latest version of the 'jquery' package is 3.3, so the subdirectory 'v3.3' is not allowed."
|
||||
);
|
||||
});
|
||||
@@ -381,7 +387,7 @@ import route = require('@ember/routing/route');
|
||||
const dt = createMockDT();
|
||||
dt.addOldVersionOfPackage("jquery", "3.0");
|
||||
|
||||
return expect(getTypingInfo("jquery", dt.pkgFS("jquery"))).resolves.toBeDefined();
|
||||
return expect(getTypingInfo("jquery", dt.fs)).resolves.toBeDefined();
|
||||
});
|
||||
|
||||
it("checks that older versions with non-relative imports have wildcard path mappings", () => {
|
||||
@@ -393,7 +399,7 @@ import route = require('@ember/routing/route');
|
||||
`
|
||||
);
|
||||
dt.addOldVersionOfPackage("jquery", "1");
|
||||
return expect(getTypingInfo("jquery", dt.pkgFS("jquery"))).rejects.toThrow(
|
||||
return expect(getTypingInfo("jquery", dt.fs)).rejects.toThrow(
|
||||
'jquery: Older version 1 must have a "paths" entry of "jquery/*": ["jquery/v1/*"]'
|
||||
);
|
||||
});
|
||||
@@ -422,9 +428,7 @@ import first from "@ckeditor/ckeditor5-utils/src/first";
|
||||
|
||||
dt.addOldVersionOfPackage("@ckeditor/ckeditor5-utils", "10");
|
||||
|
||||
return expect(
|
||||
getTypingInfo("ckeditor__ckeditor5-utils", dt.pkgFS("ckeditor__ckeditor5-utils"))
|
||||
).rejects.toThrow(
|
||||
return expect(getTypingInfo("ckeditor__ckeditor5-utils", dt.fs)).rejects.toThrow(
|
||||
'@ckeditor/ckeditor5-utils: Older version 10 must have a "paths" entry of "@ckeditor/ckeditor5-utils/*": ["ckeditor__ckeditor5-utils/v10/*"]'
|
||||
);
|
||||
});
|
||||
@@ -433,6 +437,6 @@ import first from "@ckeditor/ckeditor5-utils/src/first";
|
||||
|
||||
it("allows wildcard scope path mappings", () => {
|
||||
const dt = createMockDT();
|
||||
return expect(getTypingInfo("wordpress__plugins", dt.pkgFS("wordpress__plugins"))).resolves.toBeDefined();
|
||||
return expect(getTypingInfo("wordpress__plugins", dt.fs)).resolves.toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Type definitions for referenced 1.0
|
||||
// Project: https://youtube.com/s-fails
|
||||
// Definitions by: Type Ref Fails <https://github.com/typeref-fails>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
|
||||
export interface Referenced {}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"lib": ["es6"],
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictFunctionTypes": true,
|
||||
"strictNullChecks": true,
|
||||
"baseUrl": "../",
|
||||
"typeRoots": ["../"],
|
||||
"types": [],
|
||||
"noEmit": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"files": ["index.d.ts"]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Type definitions for referencing 1.0
|
||||
// Project: https://youtube.com/s-fails
|
||||
// Definitions by: Type Ref Fails <https://github.com/typeref-fails>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
|
||||
import { Referenced } from "../referenced";
|
||||
|
||||
export interface Referencing extends Referenced {}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"lib": ["es6"],
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictFunctionTypes": true,
|
||||
"strictNullChecks": true,
|
||||
"baseUrl": "../",
|
||||
"typeRoots": ["../"],
|
||||
"types": [],
|
||||
"noEmit": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"files": ["index.d.ts"]
|
||||
}
|
||||
@@ -26,7 +26,7 @@ testo({
|
||||
root.set("file1.txt", "ok");
|
||||
const dir = root.subdir("sub1");
|
||||
dir.set("file2.txt", "x");
|
||||
const fs: FS = new InMemoryFS(root, "test/");
|
||||
const fs: FS = new InMemoryFS(root, "/test/");
|
||||
expect(fs.exists("file1.txt")).toBe(true);
|
||||
expect(fs.readFile("file1.txt")).toBe("ok");
|
||||
expect(fs.readFile("sub1/file2.txt")).toBe("x");
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
import * as ts from "typescript";
|
||||
import { Dir, InMemoryFS } from "@definitelytyped/utils";
|
||||
import { createMockDT } from "../src/mocks";
|
||||
import { createModuleResolutionHost } from "@definitelytyped/utils";
|
||||
import { DTMock, createMockDT } from "../src/mocks";
|
||||
import { testo } from "./utils";
|
||||
import { allReferencedFiles, getModuleInfo, getTestDependencies } from "../src/lib/module-info";
|
||||
|
||||
const fs = createMockDT().fs;
|
||||
const moduleResolutionHost = createModuleResolutionHost(fs);
|
||||
const compilerOptions = {
|
||||
module: ts.ModuleKind.CommonJS,
|
||||
baseUrl: "/DefinitelyTyped/types",
|
||||
typeRoots: ["/DefinitelyTyped/types"],
|
||||
};
|
||||
|
||||
function getBoringReferences() {
|
||||
return allReferencedFiles(
|
||||
["index.d.ts", "boring-tests.ts"],
|
||||
fs.subDir("types").subDir("boring"),
|
||||
"boring",
|
||||
"types/boring"
|
||||
moduleResolutionHost,
|
||||
compilerOptions
|
||||
);
|
||||
}
|
||||
testo({
|
||||
@@ -31,7 +39,8 @@ testo({
|
||||
["boring-tests.ts"],
|
||||
fs.subDir("types").subDir("boring"),
|
||||
"boring",
|
||||
"types/boring"
|
||||
moduleResolutionHost,
|
||||
compilerOptions
|
||||
);
|
||||
expect(Array.from(types.keys())).toEqual([
|
||||
"secondary.d.ts",
|
||||
@@ -47,7 +56,8 @@ testo({
|
||||
["jquery-tests.ts", "index.d.ts"],
|
||||
fs.subDir("types").subDir("jquery"),
|
||||
"jquery",
|
||||
"types/jquery"
|
||||
moduleResolutionHost,
|
||||
compilerOptions
|
||||
);
|
||||
expect(Array.from(types.keys())).toEqual(["index.d.ts", "JQuery.d.ts"]);
|
||||
expect(Array.from(tests.keys())).toEqual(["jquery-tests.ts"]);
|
||||
@@ -57,21 +67,28 @@ testo({
|
||||
["globby-tests.ts", "test/other-tests.ts"],
|
||||
fs.subDir("types").subDir("globby"),
|
||||
"globby",
|
||||
"types/globby"
|
||||
moduleResolutionHost,
|
||||
compilerOptions
|
||||
);
|
||||
expect(Array.from(types.keys())).toEqual(["merges.d.ts"]);
|
||||
expect(Array.from(types.keys())).toEqual([]);
|
||||
expect(Array.from(tests.keys())).toEqual(["globby-tests.ts", "test/other-tests.ts"]);
|
||||
},
|
||||
allReferencedFilesIncludesTypesImports() {
|
||||
const pkg = new Dir(undefined);
|
||||
const dtMock = new DTMock();
|
||||
const pkg = dtMock.pkgDir("mock");
|
||||
pkg.set(
|
||||
"index.d.ts",
|
||||
`type T = import("./types");
|
||||
`
|
||||
);
|
||||
pkg.set("types.d.ts", "");
|
||||
const memFS = new InMemoryFS(pkg, "types/mock");
|
||||
const { types, tests } = allReferencedFiles(["index.d.ts"], memFS, "mock", "types/mock");
|
||||
const { types, tests } = allReferencedFiles(
|
||||
["index.d.ts"],
|
||||
dtMock.fs.subDir("types/mock"),
|
||||
"mock",
|
||||
createModuleResolutionHost(dtMock.fs),
|
||||
compilerOptions
|
||||
);
|
||||
expect(Array.from(types.keys())).toEqual(["index.d.ts", "types.d.ts"]);
|
||||
expect(Array.from(tests.keys())).toEqual([]);
|
||||
},
|
||||
@@ -97,32 +114,35 @@ testo({
|
||||
["index.d.ts", "globby-tests.ts", "test/other-tests.ts"],
|
||||
fs.subDir("types").subDir("globby"),
|
||||
"globby",
|
||||
"types/globby"
|
||||
moduleResolutionHost,
|
||||
compilerOptions
|
||||
);
|
||||
expect(Array.from(types.keys())).toEqual(["index.d.ts", "sneaky.d.ts", "merges.d.ts"]);
|
||||
expect(Array.from(types.keys())).toEqual(["index.d.ts", "sneaky.d.ts"]);
|
||||
const i = getModuleInfo("globby", types);
|
||||
expect(i.dependencies).toEqual(new Set(["andere/snee"]));
|
||||
},
|
||||
selfInScopedPackage() {
|
||||
const scoped = new Dir(undefined);
|
||||
const dtMock = new DTMock();
|
||||
const scoped = dtMock.pkgDir("rdfjs__to-ntriples");
|
||||
scoped.set(
|
||||
"index.d.ts",
|
||||
`import "@rdfjs/to-ntriples/component";
|
||||
`
|
||||
);
|
||||
scoped.set("component.d.ts", "");
|
||||
const memFS = new InMemoryFS(scoped, "types/rdfjs__to-ntriples");
|
||||
const { types, tests } = allReferencedFiles(
|
||||
["index.d.ts"],
|
||||
memFS,
|
||||
dtMock.fs.subDir("types/rdfjs__to-ntriples"),
|
||||
"rdfjs__to-ntriples",
|
||||
"types/rdfjs__to-ntriples"
|
||||
createModuleResolutionHost(dtMock.fs),
|
||||
{ ...compilerOptions, paths: { "@rdfjs/to-ntriples/*": ["rdfjs__to-ntriples/*"] } }
|
||||
);
|
||||
expect(Array.from(types.keys())).toEqual(["index.d.ts", "component.d.ts"]);
|
||||
expect(Array.from(tests.keys())).toEqual([]);
|
||||
},
|
||||
selfInTypesVersionsParent() {
|
||||
const pkg = new Dir(undefined);
|
||||
const dtMock = new DTMock();
|
||||
const pkg = dtMock.pkgDir("mock");
|
||||
const ts20 = pkg.subdir("ts2.0");
|
||||
ts20.set(
|
||||
"index.d.ts",
|
||||
@@ -136,15 +156,28 @@ testo({
|
||||
`import "mock/component";
|
||||
`
|
||||
);
|
||||
const memFS = new InMemoryFS(ts20, "types/mock/ts2.0");
|
||||
const { types, tests } = allReferencedFiles(["index.d.ts"], memFS, "mock", "types/mock");
|
||||
|
||||
const { types, tests } = allReferencedFiles(
|
||||
["index.d.ts"],
|
||||
dtMock.fs.subDir("types/mock/ts2.0"),
|
||||
"mock",
|
||||
createModuleResolutionHost(dtMock.fs),
|
||||
{ ...compilerOptions, paths: { "mock/*": ["mock/ts2.0/*"] } }
|
||||
);
|
||||
expect(Array.from(types.keys())).toEqual(["index.d.ts", "../ts1.0/index.d.ts", "component.d.ts"]);
|
||||
expect(Array.from(tests.keys())).toEqual([]);
|
||||
},
|
||||
getTestDependenciesWorks() {
|
||||
const { types, tests } = getBoringReferences();
|
||||
const i = getModuleInfo("boring", types);
|
||||
const d = getTestDependencies("boring", tests.keys(), i.dependencies, fs.subDir("types").subDir("boring"));
|
||||
const d = getTestDependencies(
|
||||
"boring",
|
||||
tests.keys(),
|
||||
i.dependencies,
|
||||
fs.subDir("types").subDir("boring"),
|
||||
moduleResolutionHost,
|
||||
compilerOptions
|
||||
);
|
||||
expect(d).toEqual(new Set(["boring", "boring/commonjs", "boring/secondary", "boring/v1", "super-big-fun-hus"]));
|
||||
},
|
||||
});
|
||||
|
||||
@@ -66,7 +66,7 @@ describe(TypingsVersions, () => {
|
||||
dt.addOldVersionOfPackage("jquery", "1");
|
||||
dt.addOldVersionOfPackage("jquery", "2");
|
||||
dt.addOldVersionOfPackage("jquery", "2.5");
|
||||
versions = new TypingsVersions(await getTypingInfo("jquery", dt.pkgFS("jquery")));
|
||||
versions = new TypingsVersions(await getTypingInfo("jquery", dt.fs));
|
||||
});
|
||||
|
||||
it("sorts the data from latest to oldest version", () => {
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
"rootDir": "src",
|
||||
"types": ["node"],
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "@definitelytyped/dts-critic",
|
||||
"version": "0.0.147",
|
||||
"version": "0.0.150",
|
||||
"author": "Nathan Shively-Sanders",
|
||||
"description": "Checks a new .d.ts against the Javascript source and tells you what problems it has",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@definitelytyped/header-parser": "^0.0.147",
|
||||
"@definitelytyped/header-parser": "^0.0.150",
|
||||
"command-exists": "^1.2.8",
|
||||
"rimraf": "^3.0.2",
|
||||
"semver": "^6.2.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@definitelytyped/dtslint-runner",
|
||||
"version": "0.0.148-next.7",
|
||||
"version": "0.0.151-next.1",
|
||||
"description": "Run dtslint on DefinitelyTyped packages",
|
||||
"homepage": "https://github.com/microsoft/DefinitelyTyped-tools/tree/master/packages/dtslint-runner#readme",
|
||||
"license": "MIT",
|
||||
@@ -23,9 +23,9 @@
|
||||
"url": "https://github.com/microsoft/DefinitelyTyped-tools/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@definitelytyped/definitions-parser": "^0.0.148-next.5",
|
||||
"@definitelytyped/dtslint": "^0.0.148-next.7",
|
||||
"@definitelytyped/utils": "^0.0.148-next.5",
|
||||
"@definitelytyped/definitions-parser": "^0.0.151-next.1",
|
||||
"@definitelytyped/dtslint": "^0.0.150",
|
||||
"@definitelytyped/utils": "^0.0.150",
|
||||
"fs-extra": "^9.0.0",
|
||||
"pacote": "^13.6.1",
|
||||
"semver": "^7.3.7",
|
||||
|
||||
@@ -213,21 +213,13 @@ function logPerformance() {
|
||||
console.log("\n\n=== PERFORMANCE ===\n");
|
||||
for (const filename of readdirSync(perfDir, { encoding: "utf8" })) {
|
||||
const x = JSON.parse(readFileSync(joinPaths(perfDir, filename), { encoding: "utf8" })) as {
|
||||
[s: string]: { typeCount: number; memory: number };
|
||||
[s: string]: { types: number; memory: number };
|
||||
};
|
||||
for (const k of Object.keys(x)) {
|
||||
big.push([k, x[k].typeCount]);
|
||||
types.push(x[k].typeCount);
|
||||
big.push([k, x[k].types]);
|
||||
types.push(x[k].types);
|
||||
}
|
||||
}
|
||||
console.log(
|
||||
"{" +
|
||||
big
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.map(([name, count]) => ` "${name}": ${count}`)
|
||||
.join(",") +
|
||||
"}"
|
||||
);
|
||||
|
||||
console.log(" * Percentiles: ");
|
||||
console.log("99:", percentile(types, 0.99));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@definitelytyped/dtslint",
|
||||
"version": "0.0.148-next.7",
|
||||
"version": "0.0.150",
|
||||
"description": "Runs tests on TypeScript definition files",
|
||||
"main": "./dist/index.js",
|
||||
"bin": "./dist/index.js",
|
||||
@@ -22,10 +22,10 @@
|
||||
"test": "../../node_modules/.bin/jest --config ../../jest.config.js packages/dtslint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@definitelytyped/dts-critic": "^0.0.147",
|
||||
"@definitelytyped/header-parser": "^0.0.147",
|
||||
"@definitelytyped/typescript-versions": "^0.0.147",
|
||||
"@definitelytyped/utils": "^0.0.148-next.5",
|
||||
"@definitelytyped/dts-critic": "^0.0.150",
|
||||
"@definitelytyped/header-parser": "^0.0.150",
|
||||
"@definitelytyped/typescript-versions": "^0.0.150",
|
||||
"@definitelytyped/utils": "^0.0.150",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.0",
|
||||
"@typescript-eslint/parser": "^5.30.0",
|
||||
"@typescript-eslint/utils": "^5.30.0",
|
||||
|
||||
@@ -21,6 +21,8 @@ export async function lint(
|
||||
tsLocal: string | undefined
|
||||
): Promise<string | undefined> {
|
||||
const tsconfigPath = joinPaths(dirPath, "tsconfig.json");
|
||||
const estree = await import(require.resolve("@typescript-eslint/typescript-estree", { paths: [dirPath] }));
|
||||
process.env.TSESTREE_SINGLE_RUN = "true";
|
||||
// TODO: To remove tslint, replace this with a ts.createProgram (probably)
|
||||
const lintProgram = Linter.createProgram(tsconfigPath);
|
||||
|
||||
@@ -74,6 +76,7 @@ export async function lint(
|
||||
const formatter = await eslint.loadFormatter("stylish");
|
||||
const eresults = await eslint.lintFiles(esfiles);
|
||||
output += formatter.format(eresults);
|
||||
estree.clearCaches();
|
||||
process.chdir(cwd);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,10 +59,12 @@ function walk(ctx: Lint.WalkContext<void>): void {
|
||||
const jsdocSeeTag = (ts.SyntaxKind as any).JSDocSeeTag || 0;
|
||||
const jsdocDeprecatedTag = (ts.SyntaxKind as any).JSDocDeprecatedTag || 0;
|
||||
const jsdocThrowsTag = (ts.SyntaxKind as any).JSDocThrowsTag || 0;
|
||||
const jsdocOverrideTag = (ts.SyntaxKind as any).JSDocOverrideTag || 0;
|
||||
switch (tag.kind) {
|
||||
case jsdocSeeTag:
|
||||
case jsdocDeprecatedTag:
|
||||
case jsdocThrowsTag:
|
||||
case jsdocOverrideTag:
|
||||
case ts.SyntaxKind.JSDocAuthorTag:
|
||||
// @deprecated and @see always have meaning
|
||||
break;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@definitelytyped/header-parser",
|
||||
"version": "0.0.147",
|
||||
"version": "0.0.150",
|
||||
"description": "",
|
||||
"author": "Nathan Shively-Sanders <nathansa@microsoft.com>",
|
||||
"homepage": "https://github.com/microsoft/DefinitelyTyped-tools/tree/master/packages/header-parser#readme",
|
||||
@@ -20,7 +20,7 @@
|
||||
"url": "https://github.com/microsoft/DefinitelyTyped-tools/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@definitelytyped/typescript-versions": "^0.0.147",
|
||||
"@definitelytyped/typescript-versions": "^0.0.150",
|
||||
"@types/parsimmon": "^1.10.1",
|
||||
"parsimmon": "^1.13.0"
|
||||
},
|
||||
|
||||
@@ -169,7 +169,18 @@ describe("isTypeScriptVersion", () => {
|
||||
|
||||
describe("range", () => {
|
||||
it("works", () => {
|
||||
expect(TypeScriptVersion.range("4.2")).toEqual(["4.2", "4.3", "4.4", "4.5", "4.6", "4.7", "4.8", "4.9", "5.0"]);
|
||||
expect(TypeScriptVersion.range("4.2")).toEqual([
|
||||
"4.2",
|
||||
"4.3",
|
||||
"4.4",
|
||||
"4.5",
|
||||
"4.6",
|
||||
"4.7",
|
||||
"4.8",
|
||||
"4.9",
|
||||
"5.0",
|
||||
"5.1",
|
||||
]);
|
||||
});
|
||||
it("includes 4.2 onwards", () => {
|
||||
expect(TypeScriptVersion.range("4.2")).toEqual(TypeScriptVersion.supported);
|
||||
@@ -188,6 +199,7 @@ describe("tagsToUpdate", () => {
|
||||
"ts4.8",
|
||||
"ts4.9",
|
||||
"ts5.0",
|
||||
"ts5.1",
|
||||
"latest",
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@definitelytyped/perf",
|
||||
"version": "0.0.148-next.5",
|
||||
"version": "0.0.151-next.1",
|
||||
"description": "",
|
||||
"bin": "index.js",
|
||||
"scripts": {
|
||||
@@ -16,9 +16,10 @@
|
||||
"directory": "packages/perf"
|
||||
},
|
||||
"dependencies": {
|
||||
"@definitelytyped/definitions-parser": "^0.0.148-next.5",
|
||||
"@definitelytyped/header-parser": "^0.0.147",
|
||||
"@definitelytyped/utils": "^0.0.148-next.5",
|
||||
"@definitelytyped/definitions-parser": "^0.0.151-next.1",
|
||||
"@definitelytyped/header-parser": "^0.0.150",
|
||||
"@definitelytyped/typescript-versions": "^0.0.150",
|
||||
"@definitelytyped/utils": "^0.0.150",
|
||||
"@octokit/rest": "^16.33.0",
|
||||
"@types/node": "^12.12.29",
|
||||
"markdown-table": "^1.1.3",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@definitelytyped/publisher",
|
||||
"private": true,
|
||||
"version": "0.0.148-next.5",
|
||||
"version": "0.0.151-next.1",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"description": "Publish DefinitelyTyped definitions to NPM",
|
||||
@@ -9,11 +9,11 @@
|
||||
"@azure/functions": "^3.2.0",
|
||||
"@azure/identity": "^1.5.2",
|
||||
"@azure/keyvault-secrets": "^4.3.0",
|
||||
"@definitelytyped/definitions-parser": "^0.0.148-next.5",
|
||||
"@definitelytyped/header-parser": "^0.0.147",
|
||||
"@definitelytyped/retag": "^0.0.148-next.5",
|
||||
"@definitelytyped/typescript-versions": "^0.0.147",
|
||||
"@definitelytyped/utils": "^0.0.148-next.5",
|
||||
"@definitelytyped/definitions-parser": "^0.0.151-next.1",
|
||||
"@definitelytyped/header-parser": "^0.0.150",
|
||||
"@definitelytyped/retag": "^0.0.151-next.1",
|
||||
"@definitelytyped/typescript-versions": "^0.0.150",
|
||||
"@definitelytyped/utils": "^0.0.150",
|
||||
"@octokit/rest": "^16.1.0",
|
||||
"applicationinsights": "^2",
|
||||
"fs-extra": "^9.1.0",
|
||||
|
||||
@@ -14,7 +14,7 @@ export interface TesterOptions extends ParseDefinitionsOptions {
|
||||
export const defaultLocalOptions: TesterOptions = {
|
||||
definitelyTypedPath: "../../../DefinitelyTyped",
|
||||
progress: true,
|
||||
parseInParallel: true,
|
||||
parseInParallel: !process.env.VSCODE_INSPECTOR_OPTIONS,
|
||||
};
|
||||
|
||||
export const defaultRemoteOptions: ParseDefinitionsOptions = {
|
||||
|
||||
@@ -39,7 +39,7 @@ if (!module.parent) {
|
||||
}
|
||||
|
||||
async function single(singleName: string, dt: FS): Promise<void> {
|
||||
const data = await getTypingInfo(singleName, dt.subDir("types").subDir(singleName));
|
||||
const data = await getTypingInfo(singleName, dt);
|
||||
const typings = { [singleName]: data };
|
||||
await writeDataFile(typesDataFilename, typings);
|
||||
console.log(JSON.stringify(data, undefined, 4));
|
||||
|
||||
@@ -60,7 +60,7 @@ function defaultFS(): FS {
|
||||
`
|
||||
);
|
||||
pkg.set("jquery.test.ts", "// tests");
|
||||
const memFS = new InMemoryFS(pkg, "types/mock");
|
||||
const memFS = new InMemoryFS(pkg, "/types/mock/");
|
||||
return memFS;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@definitelytyped/retag",
|
||||
"version": "0.0.148-next.5",
|
||||
"version": "0.0.151-next.1",
|
||||
"description": "Refresh tags on all DT-published packages in the @types scope.",
|
||||
"author": "Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>",
|
||||
"homepage": "https://github.com/microsoft/DefinitelyTyped-tools/tree/master/packages/retag#readme",
|
||||
@@ -18,9 +18,9 @@
|
||||
"url": "https://github.com/microsoft/DefinitelyTyped-tools/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@definitelytyped/definitions-parser": "^0.0.148-next.5",
|
||||
"@definitelytyped/typescript-versions": "^0.0.147",
|
||||
"@definitelytyped/utils": "^0.0.148-next.5",
|
||||
"@definitelytyped/definitions-parser": "^0.0.151-next.1",
|
||||
"@definitelytyped/typescript-versions": "^0.0.150",
|
||||
"@definitelytyped/utils": "^0.0.150",
|
||||
"pacote": "^13.6.1",
|
||||
"semver": "^7.3.7",
|
||||
"yargs": "^15.3.1"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@definitelytyped/typescript-versions",
|
||||
"version": "0.0.147",
|
||||
"version": "0.0.150",
|
||||
"description": "List of supported TypeScript versions",
|
||||
"author": "Andrew Branch <andrew@wheream.io>",
|
||||
"homepage": "https://github.com/microsoft/DefinitelyTyped-tools/tree/master/packages/typescript-versions#readme",
|
||||
|
||||
@@ -55,7 +55,7 @@ export type UnsupportedTypeScriptVersion =
|
||||
* Parseable and supported TypeScript versions.
|
||||
* Only add to this list if we will support this version on Definitely Typed.
|
||||
*/
|
||||
export type TypeScriptVersion = "4.2" | "4.3" | "4.4" | "4.5" | "4.6" | "4.7" | "4.8" | "4.9" | "5.0";
|
||||
export type TypeScriptVersion = "4.2" | "4.3" | "4.4" | "4.5" | "4.6" | "4.7" | "4.8" | "4.9" | "5.0" | "5.1";
|
||||
|
||||
export type AllTypeScriptVersion = UnsupportedTypeScriptVersion | TypeScriptVersion;
|
||||
|
||||
@@ -63,7 +63,7 @@ export namespace TypeScriptVersion {
|
||||
/** Add to this list when a version actually ships. */
|
||||
export const shipped: readonly TypeScriptVersion[] = ["4.2", "4.3", "4.4", "4.5", "4.6", "4.7", "4.8", "4.9"];
|
||||
/** Add to this list when a version is available as typescript@next */
|
||||
export const supported: readonly TypeScriptVersion[] = [...shipped, "5.0"];
|
||||
export const supported: readonly TypeScriptVersion[] = [...shipped, "5.0", "5.1"];
|
||||
/** Add to this list when it will no longer be supported on Definitely Typed */
|
||||
export const unsupported: readonly UnsupportedTypeScriptVersion[] = [
|
||||
"2.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@definitelytyped/utils",
|
||||
"version": "0.0.148-next.5",
|
||||
"version": "0.0.150",
|
||||
"description": "Shared utilities for DefinitelyTyped tools",
|
||||
"homepage": "https://github.com/microsoft/DefinitelyTyped-tools/tree/master/packages/utils#readme",
|
||||
"license": "MIT",
|
||||
@@ -19,7 +19,7 @@
|
||||
"url": "https://github.com/microsoft/DefinitelyTyped-tools/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@definitelytyped/typescript-versions": "^0.0.147",
|
||||
"@definitelytyped/typescript-versions": "^0.0.150",
|
||||
"@qiwi/npm-registry-client": "^8.9.1",
|
||||
"@types/node": "^14.14.35",
|
||||
"charm": "^1.0.2",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import assert from "assert";
|
||||
import { relative, resolve } from "path";
|
||||
import { assertDefined } from "./assertions";
|
||||
import { pathExistsSync, readdirSync, statSync } from "fs-extra";
|
||||
import { readFileSync, readJsonSync } from "./io";
|
||||
@@ -37,6 +38,17 @@ export interface FS {
|
||||
debugPath(): string;
|
||||
}
|
||||
|
||||
export function createModuleResolutionHost(fs: FS): import("typescript").ModuleResolutionHost {
|
||||
return {
|
||||
fileExists: (filename) => fs.exists(filename),
|
||||
readFile: (filename) => fs.readFile(filename),
|
||||
directoryExists: (directoryName) => fs.exists(directoryName),
|
||||
getCurrentDirectory: () => "",
|
||||
realpath: (path) => path,
|
||||
useCaseSensitiveFileNames: () => true,
|
||||
};
|
||||
}
|
||||
|
||||
interface ReadonlyDir extends ReadonlyMap<string, ReadonlyDir | string> {
|
||||
readonly parent: Dir | undefined;
|
||||
}
|
||||
@@ -70,15 +82,28 @@ export class Dir extends Map<string, Dir | string> implements ReadonlyDir {
|
||||
}
|
||||
}
|
||||
|
||||
function ensureTrailingSlash(dir: string) {
|
||||
return dir.endsWith("/") ? dir : dir + "/";
|
||||
}
|
||||
|
||||
export class InMemoryFS implements FS {
|
||||
/** pathToRoot is just for debugging */
|
||||
constructor(readonly curDir: ReadonlyDir, readonly pathToRoot: string) {}
|
||||
constructor(readonly curDir: ReadonlyDir, readonly rootPrefix: string) {
|
||||
this.rootPrefix = ensureTrailingSlash(rootPrefix);
|
||||
assert(rootPrefix[0] === "/", `rootPrefix must be absolute: ${rootPrefix}`);
|
||||
}
|
||||
|
||||
private tryGetEntry(path: string): ReadonlyDir | string | undefined {
|
||||
validatePath(path);
|
||||
if (path[0] === "/") {
|
||||
path = relative(this.rootPrefix, path);
|
||||
}
|
||||
if (path === "") {
|
||||
return this.curDir;
|
||||
}
|
||||
const needsDir = path.endsWith("/");
|
||||
if (needsDir) {
|
||||
path = path.slice(0, -1);
|
||||
}
|
||||
|
||||
const components = path.split("/");
|
||||
const baseName = assertDefined(components.pop());
|
||||
let dir = this.curDir;
|
||||
@@ -89,18 +114,19 @@ export class InMemoryFS implements FS {
|
||||
}
|
||||
if (!(entry instanceof Dir)) {
|
||||
throw new Error(
|
||||
`No file system entry at ${this.pathToRoot}/${path}. Siblings are: ${Array.from(dir.keys()).toString()}`
|
||||
`No file system entry at ${this.rootPrefix}/${path}. Siblings are: ${Array.from(dir.keys()).toString()}`
|
||||
);
|
||||
}
|
||||
dir = entry;
|
||||
}
|
||||
return dir.get(baseName);
|
||||
const res = dir.get(baseName);
|
||||
return needsDir ? (res instanceof Dir ? res : undefined) : res;
|
||||
}
|
||||
|
||||
private getEntry(path: string): ReadonlyDir | string {
|
||||
const entry = this.tryGetEntry(path);
|
||||
if (entry === undefined) {
|
||||
throw new Error(`No file system entry at ${this.pathToRoot}/${path}`);
|
||||
throw new Error(`No file system entry at ${this.rootPrefix}/${path}`);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
@@ -108,7 +134,7 @@ export class InMemoryFS implements FS {
|
||||
private getDir(dirPath: string): Dir {
|
||||
const res = this.getEntry(dirPath);
|
||||
if (!(res instanceof Dir)) {
|
||||
throw new Error(`${this.pathToRoot}/${dirPath} is a file, not a directory.`);
|
||||
throw new Error(`${this.rootPrefix}/${dirPath} is a file, not a directory.`);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -116,7 +142,7 @@ export class InMemoryFS implements FS {
|
||||
readFile(filePath: string): string {
|
||||
const res = this.getEntry(filePath);
|
||||
if (typeof res !== "string") {
|
||||
throw new Error(`${this.pathToRoot}/${filePath} is a directory, not a file.`);
|
||||
throw new Error(`${this.rootPrefix}/${filePath} is a directory, not a file.`);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -138,25 +164,23 @@ export class InMemoryFS implements FS {
|
||||
}
|
||||
|
||||
subDir(path: string): FS {
|
||||
return new InMemoryFS(this.getDir(path), joinPaths(this.pathToRoot, path));
|
||||
assert(path[0] !== "/", "Cannot use absolute paths with InMemoryFS.subDir");
|
||||
return new InMemoryFS(this.getDir(path), resolve(this.rootPrefix, path));
|
||||
}
|
||||
|
||||
debugPath(): string {
|
||||
return this.pathToRoot;
|
||||
return this.rootPrefix;
|
||||
}
|
||||
}
|
||||
|
||||
export class DiskFS implements FS {
|
||||
constructor(private readonly rootPrefix: string) {
|
||||
assert(rootPrefix.endsWith("/"));
|
||||
assert(rootPrefix.startsWith("/"), "DiskFS must use absolute paths");
|
||||
this.rootPrefix = ensureTrailingSlash(rootPrefix);
|
||||
}
|
||||
|
||||
private getPath(path: string | undefined): string {
|
||||
if (path === undefined) {
|
||||
return this.rootPrefix;
|
||||
}
|
||||
validatePath(path);
|
||||
return this.rootPrefix + path;
|
||||
return resolve(this.rootPrefix, path ?? "");
|
||||
}
|
||||
|
||||
readdir(dirPath?: string): readonly string[] {
|
||||
@@ -189,16 +213,3 @@ export class DiskFS implements FS {
|
||||
return this.rootPrefix.slice(0, this.rootPrefix.length - 1); // remove trailing '/'
|
||||
}
|
||||
}
|
||||
|
||||
/** FS only handles simple paths like `foo/bar` or `../foo`. No `./foo` or `/foo`. */
|
||||
function validatePath(path: string): void {
|
||||
if (path.startsWith(".") && path !== ".editorconfig" && path !== ".eslintrc.json" && !path.startsWith("../")) {
|
||||
throw new Error(`${path}: filesystem doesn't support paths of the form './x'.`);
|
||||
}
|
||||
if (path.startsWith("/")) {
|
||||
throw new Error(`${path}: filesystem doesn't support paths of the form '/xxx'.`);
|
||||
}
|
||||
if (path.endsWith("/")) {
|
||||
throw new Error(`${path}: filesystem doesn't support paths of the form 'xxx/'.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ export function downloadAndExtractFile(url: string, log: LoggerWithErrors): Prom
|
||||
extract.on("finish", () => {
|
||||
log.info("Done receiving " + url);
|
||||
clearTimeout(timeout);
|
||||
resolve(new InMemoryFS(root.finish(), ""));
|
||||
resolve(new InMemoryFS(root.finish(), "/"));
|
||||
});
|
||||
|
||||
response.pipe(zlib.createGunzip()).pipe(extract);
|
||||
|
||||
Reference in New Issue
Block a user