New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

tsserver-lean

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tsserver-lean - npm Package Compare versions

Comparing version 0.0.0-pre-alpha.4 to 0.0.0-pre-alpha.5

lib/tsserver.log

189

lib/checker.js

@@ -32,2 +32,3 @@ "use strict";

const path = __importStar(require("path"));
const node_perf_hooks_1 = require("node:perf_hooks");
const config_1 = require("./config");

@@ -108,7 +109,12 @@ /**

}
const specifier = components[0].indexOf('@') > -1 && components.length > 2 ? true : components.length > 1;
return { resolvedPath: require.resolve(importSpecifier), external: true, specifier };
// third-party
// absolute paths can be specific (pkg-a/lib/p.ts), within the project, or global (pkg-a)
// because, for now, we are only interested in getting the project's tsconfig, we can overlook trying to find the specific file path
const specifier = components[0].indexOf('@') > -1 && components.length > 2 ? true : components.length > 1;
try {
return { resolvedPath: require.resolve(importSpecifier, { paths: [importeePath] }), external: true, specifier };
}
catch (err) {
return undefined;
}
}

@@ -139,4 +145,6 @@ // we are just gathering imports for the target path, and not for the entire module graph dependency

if (importSpecifiers.length > 0) {
let i = 0;
for (const importSpecifier of importSpecifiers) {
const start = Date.now();
const percentComplete = getPercentComplete('resolve-dependency', i / importSpecifiers.length + 1);
const start = node_perf_hooks_1.performance.now();
// ts.resolveModuleName takes surprisingly ~9 SECONDS (!) to resolve a single import

@@ -146,5 +154,6 @@ const resolvedModule = fastResolve(tsProject, importSpecifier, filePath);

logger.info({
phase: 'resolveDeps',
phase: 'resolve-dependency',
status: 'skip',
message: `could not resolve ${importSpecifier} in ${filePath}`,
percentComplete,
});

@@ -154,6 +163,7 @@ }

logger.info({
phase: 'resolveDeps',
phase: 'resolve-dependency',
status: 'skip',
message: `${importSpecifier} is third-party`,
elapsed: Date.now() - start,
elapsed: node_perf_hooks_1.performance.now() - start,
percentComplete,
});

@@ -163,6 +173,7 @@ }

logger.info({
phase: 'resolveDeps',
phase: 'resolve-dependency',
status: 'end',
message: `resolved ${importSpecifier} to ${resolvedModule.resolvedPath}`,
elapsed: Date.now() - start,
elapsed: node_perf_hooks_1.performance.now() - start,
percentComplete,
});

@@ -184,2 +195,23 @@ if (!collectedImports.has(resolvedModule.resolvedPath)) {

}
function getPercentComplete(phase, percentageComplete) {
// |==|==========|=====|
// 0 10 70 100
//
// module-resolution => 0-10%
// dependency-building => 11-70%
// type-checking => 71-100%
const realRange = 1.0 - 0;
const ranges = new Map([
['resolve-dependency', [0, 0.1]],
['build-dependency', [0.1, 0.5]],
['emit-dependency', [0.5, 0.7]],
['type-check', [0.7, 1.0]],
]);
const range = ranges.get(phase);
if (!range) {
return undefined;
}
const [lower, upper] = range;
return (upper - lower) * percentageComplete;
}
/**

@@ -195,2 +227,34 @@ * Creates a ProjectService for a given project

this.files = {};
/**
* Compiles all project references, dependencies of a given project
* to allow for accurate diagnostics
*
* Caveats:
* - compiles and emit only projects that are __directly imported by target file__; the optimal
* approach would be to compile only the _modules_ that are in the graph path
* - does not explicitly compile and emit indirect project references
* (e.g. A -> B -> C, where C is an indirect project reference); however, the language service
* when generate the programs, will compile (but not emit) the indirect project references
* - to do that, we would need to
* 1) resolve specific import specifiers (easy) e.g `import {x} from 'foo/bar/baz/qux' would
* only need to compile `foo/bar/baz/qux.ts`
* 2) resolve module specifiers from global imports e.g `import {x} from 'foo'`, we would need to track
* in `foo/index.ts`, which module defines and exports `x`, and import only that one.
*/
this.isDeclaration = (p) => /.*\.d\.ts$/g.test(p);
this.isValidSource = (p) => /.*\.(ts|tsx)$/g.test(p);
this.shouldEmit = (source, outputFiles) => {
const declarationFile = outputFiles.find((p) => p.endsWith('.d.ts'));
if (!declarationFile)
return false;
try {
const statDecl = fs.statSync(declarationFile);
const statSource = fs.statSync(source);
return statSource.mtime > statDecl.mtime;
}
catch (err) {
// probably ENOENT
return true;
}
};
this.documentRegistry = documentRegistry;

@@ -235,18 +299,2 @@ this.languageServiceHost = this.createLanguageServiceHost(tsProject);

}
/**
* Compiles all project references, dependencies of a given project
* to allow for accurate diagnostics
*
* Caveats:
* - compiles and emit only projects that are __directly imported by target file__; the optimal
* approach would be to compile only the _modules_ that are in the graph path
* - does not explicitly compile and emit indirect project references
* (e.g. A -> B -> C, where C is an indirect project reference); however, the language service
* when generate the programs, will compile (but not emit) the indirect project references
* - to do that, we would need to
* 1) resolve specific import specifiers (easy) e.g `import {x} from 'foo/bar/baz/qux' would
* only need to compile `foo/bar/baz/qux.ts`
* 2) resolve module specifiers from global imports e.g `import {x} from 'foo'`, we would need to track
* in `foo/index.ts`, which module defines and exports `x`, and import only that one.
*/
compileProjectReferences(targetPath, getTypescriptProject, getProjectService) {

@@ -256,5 +304,4 @@ if (!this.tsProject.projectReferences || this.tsProject.projectReferences.length === 0) {

}
const start = Date.now();
const start = node_perf_hooks_1.performance.now();
const projectsQueue = [];
const seenProjects = new Set();
const emittedFiles = new Set();

@@ -265,2 +312,3 @@ const emitPromises = [];

// populate the queue
let i = 0;
for (const importSpecifier of resolvedImportSpecifiers) {

@@ -274,2 +322,4 @@ const relevantProj = getTypescriptProject(importSpecifier.resolvedPath); // todo: could share this with TypeChecker

while (projectsQueue.length > 0) {
i++;
const percentComplete = getPercentComplete('build-dependency', i / resolvedImportSpecifiers.length + 1);
const cur = projectsQueue.shift();

@@ -279,9 +329,7 @@ if (!cur)

const { project: referenceProject, filesToMaybeEmit } = cur;
if (seenProjects.has(referenceProject.configPath)) {
continue;
}
this.logger.info({
phase: 'buildDeps',
phase: 'build-dependency',
status: 'start',
message: `building dependency ${referenceProject.configPath}...`,
message: `building project ${referenceProject.configPath}...`,
percentComplete,
});

@@ -292,8 +340,7 @@ const filesToEmit = [];

for (const fileToMaybeEmit of filesToMaybeEmit) {
if (fileToMaybeEmit.endsWith('.d.ts') || !fileToMaybeEmit.endsWith('.ts')) {
if (this.isDeclaration(fileToMaybeEmit) || !this.isValidSource(fileToMaybeEmit)) {
continue;
}
const outputFiles = ts.getOutputFileNames(referenceProject.raw, fileToMaybeEmit, /*forceDtsPaths*/ true);
const declarationOutput = outputFiles.find((p) => p.endsWith('.d.ts'));
if (declarationOutput && !fs.existsSync(declarationOutput)) {
if (this.shouldEmit(fileToMaybeEmit, outputFiles)) {
filesToEmit.push(fileToMaybeEmit);

@@ -307,2 +354,9 @@ continue;

if (emittedFiles.has(fileName)) {
this.logger.info({
phase: 'build-dependency',
status: 'skip',
message: `${referenceProject.configPath} has already been built`,
elapsed: node_perf_hooks_1.performance.now() - start,
percentComplete,
});
continue;

@@ -312,2 +366,9 @@ }

emitPromises.push(projectServiceRef.emitAndCollectDiagnostics(fileName, false /* collect diagnostics */, true /* emit */));
this.logger.info({
phase: 'build-dependency',
status: 'end',
message: `${referenceProject.configPath} has already been built`,
elapsed: node_perf_hooks_1.performance.now() - start,
percentComplete,
});
}

@@ -317,16 +378,10 @@ }

this.logger.info({
phase: 'buildDeps',
phase: 'build-dependency',
status: 'skip',
message: `declaration files for ${referenceProject.configPath} are up to date`,
elapsed: Date.now() - start,
elapsed: node_perf_hooks_1.performance.now() - start,
percentComplete,
});
}
seenProjects.add(referenceProject.configPath);
}
this.logger.info({
phase: 'buildDeps',
status: 'end',
message: `done building dependencies`,
elapsed: Date.now() - start,
});
return Promise.all(emitPromises);

@@ -336,15 +391,12 @@ }

return new Promise((resolve, reject) => {
const start = Date.now();
const start = node_perf_hooks_1.performance.now();
if (forceEmit) {
this.logger.info({
phase: 'buildDepsEmit',
phase: 'emit-dependency',
status: 'start',
message: `emitting declaration files for ${fileName}...`,
percentComplete: getPercentComplete('emit-dependency', 0),
});
const output = this.languageService.getEmitOutput(fileName, true /* emitOnlyDtsFiles */, true /* forceDtsPaths */);
// got an error while emitting so we need to force diagnostics
// todo: need to re-enable this once we expose the emit command
// if (output.emitSkipped) {
// forceDiagnostics = true;
// }
// todo: need to account for output.emitSkipped once we expose the emit command
output.outputFiles.forEach((o) => {

@@ -357,3 +409,3 @@ try {

this.logger.err({
phase: 'buildDepsEmit',
phase: 'emit-dependency',
message: `failed to emit ${o.name}: ${JSON.stringify(e)}}`,

@@ -364,6 +416,7 @@ });

this.logger.info({
phase: 'buildDepsEmit',
phase: 'emit-dependency',
status: 'end',
elapsed: Date.now() - start,
elapsed: node_perf_hooks_1.performance.now() - start,
message: `done emitting declaration files for ${fileName}`,
percentComplete: getPercentComplete('emit-dependency', 1.0),
});

@@ -374,9 +427,9 @@ }

this.logger.info({
phase: 'semanticDiag',
phase: 'type-check',
status: 'start',
message: `getting diagnostics for ${fileName}...`,
message: `requesting semantic & syntactic analysis for ${fileName}...`,
percentComplete: getPercentComplete('type-check', 0),
});
const startd = Date.now();
const startd = node_perf_hooks_1.performance.now();
const allDiagnostics = [
// ...this.languageService.getCompilerOptionsDiagnostics(),
...this.languageService.getSyntacticDiagnostics(fileName),

@@ -386,6 +439,7 @@ ...this.languageService.getSemanticDiagnostics(fileName),

this.logger.info({
phase: 'semanticDiag',
phase: 'type-check',
status: 'end',
elapsed: Date.now() - startd,
elapsed: node_perf_hooks_1.performance.now() - startd,
message: `done`,
percentComplete: getPercentComplete('type-check', 1.0),
});

@@ -410,7 +464,18 @@ emitCallback(allDiagnostics, version);

mapInternalDiagnostics(fileName, diagnostics, version, elapsed) {
const ignoredMessagesRe = [/Cannot find module/];
const diagnosticsRaw = diagnostics.filter((d) => !!d.file);
const diagnosticsInternal = [];
for (const diagnostic of diagnosticsRaw) {
// Ignoring "Cannot find module 'third-party'. Did you mean to set 'moduleResolution'..."
// because that's a message that only shows up in dev mode, when launching an npm-linked `tsserver-lean`
// Being tackled on #703
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
if (!diagnostic.file)
let shouldIgnore = false;
for (const ignoreRe of ignoredMessagesRe) {
if (ignoreRe.test(message)) {
shouldIgnore = true;
break;
}
}
if (shouldIgnore || !diagnostic.file)
continue;

@@ -449,3 +514,3 @@ const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);

async getDiagnostics(targetPath, callback) {
const start = Date.now();
const start = node_perf_hooks_1.performance.now();
const targetPathAbs = path.resolve(targetPath);

@@ -457,3 +522,3 @@ // get project service

.then(() => {
return projectService.emitAndCollectDiagnostics(targetPathAbs, true /* forceDiagnostics */, false /* forceEmit */, (diagnostics, version) => callback(this.mapInternalDiagnostics(targetPath, diagnostics, version, Date.now() - start)));
return projectService.emitAndCollectDiagnostics(targetPathAbs, true /* forceDiagnostics */, false /* forceEmit */, (diagnostics, version) => callback(this.mapInternalDiagnostics(targetPath, diagnostics, version, node_perf_hooks_1.performance.now() - start)));
});

@@ -460,0 +525,0 @@ }

@@ -38,2 +38,5 @@ "use strict";

async requestDiagnostics(request, requestSeq) {
if (!request.arguments) {
this.logger.err({ phase: 'request', message: `Invalid 'geterr' request. Missing 'arguments' property` });
}
const { files } = request.arguments;

@@ -40,0 +43,0 @@ if (files.length === 0) {

@@ -13,3 +13,3 @@ {

"sideEffects": false,
"version": "0.0.0-pre-alpha.4",
"version": "0.0.0-pre-alpha.5",
"exports": {

@@ -16,0 +16,0 @@ ".": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc