GithubHelp home page GithubHelp logo

dependents / node-filing-cabinet Goto Github PK

View Code? Open in Web Editor NEW
74.0 4.0 44.0 828 KB

Get the file location associated with a dependency/partial's path

License: MIT License

JavaScript 100.00%
resolver stylus scss sass javascript commonjs webpack amd es6 modules

node-filing-cabinet's Introduction

Dependents

Gitter Package Control

Navigate front-end codebases in Sublime Text 2/3

For updates, follow @getDependents.

Currently supports JavaScript (AMD, CommonJS, and ES6) and CSS Preprocessor (Sass and Stylus) codebases.

  1. Installation
  2. Usage and Settings Details
  3. Bindings
  4. Reporting an Issue
  5. Contributing to Dependents

Installation

You can install Dependents via Package Control.

Don't see it? Try reinstalling Package Control. Alternatively, add the repository and install it:

  1. Package Control -> Add Repository
  2. Enter https://github.com/dependents/Dependents
  3. Package Control -> Install Package
  4. Choose Dependents

Nodejs Dependency

You must have Node.js installed on your system. Anything v0.10 and above is fine.

  • Note: The Node.js windows installer will add the install directory to the PATH variable but you must reboot to reload it.
NVM Users

NVM will install Nodejs outside of the standard binary location. If you encounter an error where your Node executable cannot be found, please override the node_path in User settings:

  • Preferences -> Package Settings -> Dependents -> Settings - User
{
  "node_path": "path/to/the/node/install/directory"
}
  • This will allow Dependents to find the Node binary for every codebase

Bindings

To more swiftly and conveniently trigger the package's commands both key and mouse bindings are provided.

Key bindings

By default, the following key bindings have been supplied:

OSX:

  • Jump to dependency: Command + Option + Right arrow
  • Find Dependents: Command + Option + Up arrow
  • Copy path to clipboard: Command + Shift + C

Windows and Linux:

  • Jump to dependency: Ctrl + Shift + Down arrow
  • Find Dependents: Ctrl + Shift + Up arrow

Mouse bindings

By default, the following key bindings have been supplied:

OSX:

  • Jump to dependency: Command + Option + Click on the dependency item
  • Find Dependents: Command + Shift + Click anywhere in document

Windows and Linux:

  • Jump to dependency: Ctrl + Alt + Click on the dependency item
  • Find Dependents: Ctrl + Shift + Click anywhere in document

Reporting an issue

You can get console logs via View -> Show Console.

Paste those logs into the body of your issue.

Feel free to chat with me on Gitter if you need help or ping me @mrjoelkemp.

License

(Creative Commons Attribution NoDerivs (CC-ND)](https://tldrlegal.com/license/creative-commons-attribution-noderivs-(cc-nd))

The no derivatives creative commons license is straightforward; you can take a work released under this license and re-distribute it but you can’t change it.

node-filing-cabinet's People

Contributors

bpscott avatar dazinator avatar dependabot[bot] avatar digitalkaoz avatar h7kayama avatar igmdvc avatar igrayson avatar jjangga0214 avatar jkemp-spotify avatar jstevans avatar mrjoelkemp avatar pahen avatar pastak avatar pcardune avatar re-fort avatar realityking avatar simenb avatar symind avatar vansosnin avatar vbraun avatar xhmikosr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

node-filing-cabinet's Issues

Resolves to wrong version

Considering the following package.json:

{
  "dependencies": {
    "uuid": "8.3.2",
    "request": "2.88.2"
  }
}

this will install the following (among others):

|- node_modules
   |- uuid // version 8.3.2
   |- request
      |- node_modules
         |- uuid // version 3.4.0

filing-cabinet -d ./ -f ./node_modules/request/lib/auth.js uuid
yields

/node_modules/uuid/dist/index.js

instead of

/node_modules/request/node_modules/uuid/index.js

1.14.4 contains a breaking change

Hi,

version 1.14.4 starts to use language features such as const which is not a bug fix more a breaking change. Was this intended? I also see that a version 2.y.z now exists which might be better suited to contain such changes.

I'm not a direct user of filing-cabinet, instead madge -> dependency-tree -> filing-cabinet and dependency-tree sets this dependency filing-cabinet@^1.9.0

returns empty path for require'd json file w/ no extension

So, given foo.json, apparently this is valid:

require('./foo')

(And they say you shouldn't require JSON files...)

At any rate, when filing-cabinet receives a partial of ./foo, it returns an empty string instead of /path/to/foo.json.

Not all imports in TypeScript are detected.

I'm using dependency-tree to get a tree of my TypeScript project, but it does not show all imported files. When an import statement directs to a folder with an index file, it will not detect it. When I step through the call stack the problem is probably in the tsLookup() function in filing-cabinet.

The line: const namedModule = ts.resolveModuleName(dependency, filename, compilerOptions, host); does not resolve in a module. am I doing something wrong, or is this a bug?

When I change the files to .js everything works as expected.

Example

  • File Structure

    ├── main.ts
    ├── lib
        ├── index.ts
    
  • main.ts

    import { func } from './lib';
  • index.ts

    export function func() {
      
    }
  • Output

    { 'main.ts': {} }
  • Desired output

    { 'main.ts': { 'main.ts/lib/index.ts': {} } }

Config dependency-tree

const tree = dependencyTree({
  filename: 'src/index.ts',
  directory: 'src',
  nodeModulesConfig: {
    entry: 'module'
  },
});

Typescript module resolution does not resolve arbitrary file extensions

JS module resolution supports arbitrary import names. For instance given two files in a directory "index.js" and "style.css", where "index.js" contains `import style from './style.css';

Running npx filing-cabinet -d . -f index.js './style.css' will return <path_current_folder>/style.css.

Thats' all good.

However if you rename index.ts and perform the same command (changing index.js to index.ts) then no value is returned. I would expect <path_current_folder>/style.css to be returned.

It also does not work if you add a tsconfig containing { "compilerOptions": { "moduleResolution": "node" } } to force using node-style module resolution.

I'm not sure how the classic module resolution should work but that should work using the node-style one. falling back to the commonJs style lookup would kinda work in the common case but would break if people have custom paths specified in their tsconfig.json

webpack config appears to be re-executed once for every resolve attempt

This greatly increases execution times for non-trivial webpack.config.js files. It would be great if the config would only be required and instantiated once, using memoization if necessary.

function resolveWebpackPath({dependency, filename, directory, webpackConfig}) {
if (!webpackResolve) {
webpackResolve = require('enhanced-resolve');
}
webpackConfig = path.resolve(webpackConfig);
let loadedConfig;
try {
loadedConfig = require(webpackConfig);
if (typeof loadedConfig === 'function') {
loadedConfig = loadedConfig();
}
} catch (e) {
debug('error loading the webpack config at ' + webpackConfig);
debug(e.message);
debug(e.stack);
return '';
}
const resolveConfig = Object.assign({}, loadedConfig.resolve);
if (!resolveConfig.modules && (resolveConfig.root || resolveConfig.modulesDirectories)) {
resolveConfig.modules = [];
if (resolveConfig.root) {
resolveConfig.modules = resolveConfig.modules.concat(resolveConfig.root);
}
if (resolveConfig.modulesDirectories) {
resolveConfig.modules = resolveConfig.modules.concat(resolveConfig.modulesDirectories);
}
}
try {
const resolver = webpackResolve.create.sync(resolveConfig);
// We don't care about what the loader resolves the dependency to
// we only wnat the path of the resolved file
dependency = stripLoader(dependency);
const lookupPath = isRelative(dependency) ? path.dirname(filename) : directory;
return resolver(lookupPath, dependency);
} catch (e) {
debug('error when resolving ' + dependency);
debug(e.message);
debug(e.stack);
return '';
}
}

Resolving symlink real paths for js resolver

The problem I have is that syminks are not replaced with their real paths. I found two problems:

  1. https://github.com/browserify/resolve/pull/195/files
  2. filing-cabinet does not allow to set preserveSymlinks: false anyway.

So, I have two questions:

  1. Could you replace browserify/resolve with build-in node resolve? (because the first one have bugs)
  2. Could you set preserveSymlinks: false by default for js resolver? TS resolver has that option by default.

PS: I use yarn workspaces, and all dependencies symlinked through node_modules. But I want to resolve all dependencies through their real paths.

Fails with an error when resolving import of the js file that has the same-named ".d.ts" type-definition file

Fails with an error when resolving import of the js file that has the same-named ".d.ts" type-definition file
with 'noTypeDefinitions' set to true

Reproduce:
File structure:

src
 |- bar.ts // ts file with "import something from '@test/foo';"
 |- foo.js
 |- foo.d.ts // type-definition file with the same name

The script that resolves imports:

import cabinet from 'filing-cabinet';

const pathToDirectory = './';
const result = cabinet({ 
  partial: '@test/foo',
  `${pathToDirectory}/bar.ts`, // fileName
  pathToDirectory, // directory
  tsConfig: {
    compilerOptions: {
      allowJs: true,
      moduleResolution: 'node',
      baseUrl: pathToDirectory,
      paths: {
        '@test/*': ['*'],
      }
    }
  },
  noTypeDefinitions: true,
});

console.log('result: ', result);

Expected result:

result: <path_to_directory>/foo.js

Actual result:
Fails with the next error:

Error: Could not resolve JS module '@test/foo'

Tests assertions fail on windows under vscode due to / versus \ in paths.

For example this test fails:


 it('adds the directory to the require resolution paths', function() {
        const directory = 'js/commonjs/';
        cabinet({
          partial: 'foobar',
          filename: 'js/commonjs/foo.js',
          directory: directory
        });

        assert.ok(require.main.paths.some(function(p) {
          return p.indexOf(directory) !== -1;
        }));
      });

because on windows, require.main.paths looks like this:

image

So the assertion fails becuase the slash direction in the paths doesn't match.

Filename not given

I get an error "Filename not given" thrown from resolve-dependency-path. I'm using [email protected].

Here's a relevant piece of code:

caller:

resolveDependencyPath = require('resolve-dependency-path');
}
resolver = resolveDependencyPath;
}
debug(`found a resolver for ${ext}`);
options.dependency = partial;
const result = resolver(options);

callee:

https://github.com/dependents/node-resolve-dependency-path/blob/6bad609f2cd9f5e740a78b8c2c05007903ed6ca8/index.js#L10-L12

Could you explain how it supposed to work if you supply only one argument to the function that throws when there are less than 3 arguments?

Upgrade Typescript

Typescript 3.0.0 has been release with no breaking changes
Upgrading typescript to ^2.4.2 || ^3.0.1 should work best

Webpack: Support Ignore Plugin

I've recently been using pahen/madge to show dependency graphs (and explain circular dependencies), for my webpack codebase. pahen/madge depends on this module. In tracing why dependencies are showing on the graph that shouldn't be there, it has come to light that node-filing-cabinet only checks the resolve field in webpackConfig despite resolution issues being affected by plugin fields.

In my case I use the canonical IgnorePlugin to exclude certain files from certain builds.

I doubt it is feasible to process every plugin, but it would be very useful to support the built in webpack plugin "IgnorePlugin".

`failedLookupLocations` no longer exists in Typescript

I needed to get newer versions of ts-parsers etc to support using the using keyword. Got some issues with filing-cabinet then which is a sub-sub dependency of madge.

The stacktrace:

TypeError: Cannot read properties of undefined (reading 'filter')
 ❯ tsLookup node_modules/filing-cabinet/index.js:262:8
 ❯ module.exports node_modules/filing-cabinet/index.js:73:18
 ❯ Function.module.exports._getDependencies node_modules/dependency-tree/index.js:100:20
 ❯ traverse node_modules/dependency-tree/index.js:146:37
 ❯ traverse node_modules/dependency-tree/index.js:170:29
 ❯ traverse node_modules/dependency-tree/index.js:170:29
 ❯ module.exports node_modules/dependency-tree/index.js:37:19
 ❯ node_modules/madge/lib/tree.js:121:27
 ❯ Tree.generateTree node_modules/madge/lib/tree.js:116:9

I've done a local yarn patch filing-cabinet which looks like this to fix it:

diff --git a/index.js b/index.js
index d5e792434fb0b3ad5ef060cc9b924b845df5605d..4e257fd48b898b08275abd79db66c1a8c4546f9f 100644
--- a/index.js
+++ b/index.js
@@ -259,10 +259,10 @@ function tsLookup({ dependency, filename, directory, webpackConfig, tsConfig, ts
   } else {
     const suffix = '.d.ts';
     const lookUpLocations = namedModule.failedLookupLocations
-      .filter(string => string.endsWith(suffix))
+      ?.filter(string => string.endsWith(suffix))
       .map(string => string.substr(0, string.length - suffix.length));

-    result = lookUpLocations.find(location => ts.sys.fileExists(location)) || '';
+    result = lookUpLocations?.find(location => ts.sys.fileExists(location)) || '';
   }

   if (!result && tsConfigPath && compilerOptions.baseUrl && compilerOptions.paths) {

Which works well and as expected. Not sure about the impact of effectively just ignoring that code though, but thought I'd give a heads up. Also if anyone else is (or comes into) the same situation.

I can provide the above patch as a PR of course, but I'm quite sure that it's probably not a great route. So someone with more insight should probably look at it :)

tsConfig argument conflates two different objects

The documentation says

Could also be an object representing a pre-parsed typescript config.

but that could be two different things:

1) raw json

Meaning that you read the tsconfig.json file and apply JSON.parse()

In this case, the compiler options are tsconfig.compilerOptions. The module setting tsconfig.compilerOptions.module is a string, for example 'CommonJs'. And if you want to be able to resolve index.ts files then it better be that value.

filing-cabinet still needs to convert the raw json to typescript's own format before using it.

2) parsed using typescript's api to parse the config file

That is, using typescript.parseJsonSourceFileConfigFileContent

In this case, the compiler options are tsconfig.options. The module setting tsconfig.options.module is a number, for example the number-based enum value typescript.ModuleKind.CommonJS. And if you want to be able to resolve index.ts files then it better be that value.

This is the preferred usage if you care about resolution speed for multiple files as typescript doesn't have to re-parse its configuration.

There is no api to go from 2) back to 1), only from 1) to 2).

Problem

Passing 2) into filing-cabinet means that the module is typescript configuration is accidentally undefined. Filing-cabinet then defaults to typescript.ModuleKind.AMD which does not include index.ts files.

madge tries to hack around that by trying to convert 2) back to 1), but unsuccessfully so: pahen/madge#271, pahen/madge#322

Instead, filing-cabinet should accept both kinds of tsConfig objects and handle them according to wether tsConfig.compilerOptions or tsConfig.options is present.

CommonJS needs to resolve in directory

Currently trying to resolve the import in this library's directory.

Need to somehow specify a context for resolution. If I want to continue using require.resolve (which does everything I need but in the wrong directory), then I may need to call static private methods of require('module') to work around the limitation.

When `noTypeDefinitions` is enabled and the extension `.d.ts` is found, a crash can occur.

There are likely two bugs here:

Given that I am performing a TypeScript import, with noTypeDefinitions as a parameter, if I have a package like @types/ramda installed, resolveJSModule will not resolve to ramda.

Instead of gracefully ignoring it, what will instead occur is it will check for the .js file in the wrong directory, and resolveJSModule will throw an exception, rather than nothing (which the || result implies the code expects)

if (namedModule.resolvedModule) {
    result = namedModule.resolvedModule.resolvedFileName;
    if (namedModule.resolvedModule.extension === '.d.ts' && noTypeDefinitions) {
      const resolvedFileNameWithoutExtension = result.replace(namedModule.resolvedModule.extension, '');
      result = ts.resolveJSModule(resolvedFileNameWithoutExtension, path.dirname(filename), host) || result;
    }
  }

For now, I will work around it by enabling type definitions, but I recommend wrapping the logic with a try catch instead of using the or statement, and potentially reworking the logic to check another directory.

tsLookup only resolves using AMD module system

var options = {
module: ts.ModuleKind.AMD
};
var host = ts.createCompilerHost({});
debug('with options: ', options);
var resolvedModule = ts.resolveModuleName(partial, filename, options, host).resolvedModule;

Currently the tsLookup function only resolves using the AMD module system. Any specific reason for that? or can we find a way to make it configurable?

Thanks for the great lib! 🍻

configure NODE_PATH?

Hey,

we're using something similar to https://gist.github.com/branneman/8048520#52-only-while-executing-node to prevent having to use long, relative paths when importing/requiring modules.

Is there a way to make filing cabinet aware of such a situation? I'm trying to build a dependency graph for a project that uses NODE_PATH=src and would like to be able to resolve something like import Foo from 'components/Foo' to /absolute/path/to/project/src/components/Foo.js

Consider supporting Webpack configurations that export a Promise

Webpack -- I believe since version 2 -- has been able to export a promise as it's configuration object. At the time of writing, filing-cabinet does check if the config object is a function, but this if branch will be spuriously matched in the case of an exported Promise, and will (eventually) result in result in an UnhandledPromiseRejectionWarning being thrown.

I'm not sure if there's an easy fix for this missing feature, though, so I would understand if handling promises in this manner isn't in scope for the project.

Issue in tsConfig options resolving

Hello!

Noticed that method that is being used to resolve ts config compiler options not working properly if passed config has extends field.

const {options} = ts.convertCompilerOptionsFromJson(tsConfig.compilerOptions);

Maybe try using parseJsonConfigFileContent from TS Compiler API? It resolves CompilerOptions well, though a bit more complicated in use: you need to create an instance of ParseConfigHost. It can be done like here.

allow non-singleton usage

the register() method keeps whatever was registered in memory, but if two libs were using filing-cabinet at the same time, they may have differing requirements for custom resolvers. maybe a resolver for .foo is different from one to the other, or perhaps one of them should not, under any circumstances, resolve a .foo file.

a way to address this would be to provide a factory function, e.g.:

const filingCabinet = require('filing-cabinet');
const cabinet = filingCabinet.create();
cabinet.register('.foo', myFooResolver);
cabinet({partial: 'bar', filename: 'quux.js', directory: '/some/path'}) // works with .foo files
filingCabinet({partial: 'bar', filename: 'quux.js', directory: '/some/path'}) // does not work with .foo files

I can send a PR to that effect, or if you have a different idea...

Allow multiple default lookups for projects with JS and TS usage

Our use case is that we have a monorepo with several projects, some of them are in Typescript and some in plain JS.

When we pass tsConfig options (via madge) it fails to resolve modules written in JS because on the default lookups array:

const defaultLookups = {

Only seems to have one lookup for each file extension, where as tsConfig can also resolve JS module via allowJs option.

This will make it significantly easier for project which are in the process of migration to Typescript.

Enhacement: support for package.json module property

Hi,

First of all, thanks for the great job on this module and also the dependency-tree one which I am currently using.

I am trying to generate dependencies and some of the packages in node_modules that declare the module property as entry point, and it would be nice that, through configuration, we can resolve the filename of the import by using module property instead of the main one.

I have been looking at the source code and I think it would be straightforward by using the option packageFilter from resolve npm module. Something like this inside commonJSLookup resolve.sync:

result = resolve.sync(partial, { basedir: directory, packageFilter: function(obj) { obj.main = obj.module ? obj.module : obj.main; return obj; }, // Add fileDir to resolve index.js files in that dir moduleDirectory: ['node_modules', directory] });

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.