GithubHelp home page GithubHelp logo

vercel / nft Goto Github PK

View Code? Open in Web Editor NEW
1.2K 56.0 119.0 3.64 MB

Node.js dependency tracing utility

Home Page: https://npmjs.com/@vercel/nft

License: MIT License

JavaScript 89.76% TypeScript 10.24% CSS 0.01%
static-analysis

nft's Introduction

Node File Trace

CI Status

Used to determine exactly which files (including node_modules) are necessary for the application runtime.

This is similar to @vercel/ncc except there is no bundling performed and therefore no reliance on webpack. This achieves the same tree-shaking benefits without moving any assets or binaries.

Usage

Installation

npm i @vercel/nft

Usage

Provide the list of source files as input:

const { nodeFileTrace } = require('@vercel/nft');
const files = ['./src/main.js', './src/second.js'];
const { fileList } = await nodeFileTrace(files);

The list of files will include all node_modules modules and assets that may be needed by the application code.

Options

Base

The base path for the file list - all files will be provided as relative to this base.

By default the process.cwd() is used:

const { fileList } = await nodeFileTrace(files, {
  base: process.cwd(),
});

Any files/folders above the base are ignored in the listing and analysis.

Process Cwd

When applying analysis certain functions rely on the process.cwd() value, such as path.resolve('./relative') or even a direct process.cwd() invocation.

Setting the processCwd option allows this analysis to be guided to the right path to ensure that assets are correctly detected.

const { fileList } = await nodeFileTrace(files, {
  processCwd: path.resolve(__dirname),
});

By default processCwd is the same as base.

Exports & Imports

By default tracing of the Node.js "exports" and "imports" fields is supported, with the "node", "require", "import" and "default" conditions traced as defined.

Alternatively the explicit list of conditions can be provided:

const { fileList } = await nodeFileTrace(files, {
  conditions: ['node', 'production'],
});

Only the "node" export should be explicitly included (if needed) when specifying the exact export condition list. The "require", "import" and "default" conditions will always be traced as defined, no matter what custom conditions are set.

Exports Only

When tracing exports the "main" / index field will still be traced for Node.js versions without "exports" support.

This can be disabled with the exportsOnly option:

const { fileList } = await nodeFileTrace(files, {
  exportsOnly: true,
});

Any package with "exports" will then only have its exports traced, and the main will not be included at all. This can reduce the output size when targeting Node.js 12.17.0 or newer.

Paths

Status: Experimental. May change at any time.

Custom resolution path definitions to use.

const { fileList } = await nodeFileTrace(files, {
  paths: {
    'utils/': '/path/to/utils/',
  },
});

Trailing slashes map directories, exact paths map exact only.

Hooks

The following FS functions can be hooked by passing them as options:

  • readFile(path): Promise<string>
  • stat(path): Promise<FS.Stats>
  • readlink(path): Promise<string>
  • resolve(id: string, parent: string): Promise<string | string[]>
Advanced Resolving

When providing a custom resolve hook you are responsible for returning one or more absolute paths to resolved files based on the id input. However it may be the case that you only want to augment or override the resolve behavior in certain cases. You can use nft's underlying resolver by importing it. The builtin resolve function expects additional arguments that need to be forwarded from the hook

  • resolve(id: string, parent: string, job: Job, isCjs: boolean): Promise<string | string[]>

Here is an example showing one id being resolved to a bespoke path while all other paths being resolved by the built-in resolver

const { nodeFileTrace, resolve } = require('@vercel/nft');
const files = ['./src/main.js', './src/second.js'];
const { fileList } = await nodeFileTrace(files, {
  resolve: async (id, parent, job, isCjs) => {
    if (id === './src/main.js') {
      return '/path/to/some/resolved/main/file.js';
    } else {
      return resolve(id, parent, job, isCjs);
    }
  },
});

TypeScript

The internal resolution supports resolving .ts files in traces by default.

By its nature of integrating into existing build systems, the TypeScript compiler is not included in this project - rather the TypeScript transform layer requires separate integration into the readFile hook.

File IO Concurrency

In some large projects, the file tracing logic may process many files at the same time. In this case, if you do not limit the number of concurrent files IO, OOM problems are likely to occur.

We use a default of 1024 concurrency to balance performance and memory usage for fs operations. You can increase this value to a higher number for faster speed, but be aware of the memory issues if the concurrency is too high.

const { fileList } = await nodeFileTrace(files, {
  fileIOConcurrency: 2048,
});

Analysis

Analysis options allow customizing how much analysis should be performed to exactly work out the dependency list.

By default as much analysis as possible is done to ensure no possibly needed files are left out of the trace.

To disable all analysis, set analysis: false. Alternatively, individual analysis options can be customized via:

const { fileList } = await nodeFileTrace(files, {
  // default
  analysis: {
    // whether to glob any analysis like __dirname + '/dir/' or require('x/' + y)
    // that might output any file in a directory
    emitGlobs: true,
    // whether __filename and __dirname style
    // expressions should be analyzed as file references
    computeFileReferences: true,
    // evaluate known bindings to assist with glob and file reference analysis
    evaluatePureExpressions: true,
  },
});

Ignore

Custom ignores can be provided to skip file inclusion (and consequently analysis of the file for references in turn as well).

const { fileList } = await nodeFileTrace(files, {
  ignore: ['./node_modules/pkg/file.js'],
});

Ignore will also accept a function or globs.

Note that the path provided to ignore is relative to base.

Cache

To persist the file cache between builds, pass an empty cache object:

const cache = Object.create(null);
const { fileList } = await nodeFileTrace(['index.ts'], { cache });
// later:
{
  const { fileList } = await nodeFileTrace(['index.ts'], { cache });
}

Note that cache invalidations are not supported so the assumption is that the file system is not changed between runs.

Reasons

To get the underlying reasons for individual files being included, a reasons object is also provided by the output:

const { fileList, reasons } = await nodeFileTrace(files);

The reasons output will then be an object of the following form:

{
  [file: string]: {
    type: 'dependency' | 'asset' | 'sharedlib',
    ignored: true | false,
    parents: string[]
  }
}

reasons also includes files that were ignored as ignored: true, with their ignoreReason.

Every file is included because it is referenced by another file. The parents list will contain the list of all files that caused this file to be included.

nft's People

Contributors

7silva avatar andybitz avatar azu avatar brooooooklyn avatar commanderroot avatar danez avatar danielroe avatar dependabot[bot] avatar dummdidumm avatar ernestbrandi avatar ethan-arrowood avatar eulersson avatar frameflare avatar gnoff avatar guybedford avatar hehex9 avatar ijjk avatar jkrems avatar leo avatar lucleray avatar matheuss avatar mxschmitt avatar rich-harris avatar sergioramos avatar skn0tt avatar souporserious avatar styfle avatar timer avatar timsuchanek avatar tylerc 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  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  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

nft's Issues

Add support for "camaro"

Steps to Reproduce

  • git clone https://gitlab.com/henrymirza/ks-api
  • cd ks-api
  • npm i && nft build index.js && rm -rf node_modules
  • node dist/index.js

Result:

Error: ENOENT: no such file or directory, open '/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.wasm'
    at Object.openSync (fs.js:440:3)
    at Object.readFileSync (fs.js:342:35)
    at w (/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:9:121)
    at x (/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:9:178)
    at Ea (/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:17:305)
    at Fa.fetch.credentials (/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:18:85)
    at new Promise (<anonymous>)
    at Fa (/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:18:59)
    at d (/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:19:220)
    at /home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:20:193 {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: '/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.wasm'
}
Error: ENOENT: no such file or directory, open '/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.wasm'
    at Object.openSync (fs.js:440:3)
    at Object.readFileSync (fs.js:342:35)
    at w (/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:9:121)
    at x (/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:9:178)
    at Ea (/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:17:305)
    at Fa.fetch.credentials (/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:18:85)
    at new Promise (<anonymous>)
    at Fa (/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:18:59)
    at d (/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:19:220)
    at /home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:20:193 {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: '/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.wasm'
}
failed to asynchronously prepare wasm: abort(Error: ENOENT: no such file or directory, open '/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.wasm'). Build with -s ASSERTIONS=1 for more info.
abort(Error: ENOENT: no such file or directory, open '/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.wasm'). Build with -s ASSERTIONS=1 for more info.
abort(Error: ENOENT: no such file or directory, open '/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.wasm'). Build with -s ASSERTIONS=1 for more info.
abort(abort(Error: ENOENT: no such file or directory, open '/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.wasm'). Build with -s ASSERTIONS=1 for more info.). Build with -s ASSERTIONS=1 for more info.
abort(abort(Error: ENOENT: no such file or directory, open '/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.wasm'). Build with -s ASSERTIONS=1 for more info.). Build with -s ASSERTIONS=1 for more info.

/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.js:9
if(aa){v=__dirname+"/";var da,ea;w=function(a,b){da||(da=require("fs"));ea||(ea=require("path"));a=ea.normalize(a);a=da.readFileSync(a);return b?a:a.toString()};x=function(a){a=w(a,!0);a.buffer||(a=new Uint8Array(a));a.buffer||z("Assertion failed: undefined");return a};1<process.argv.length&&process.argv[1].replace(/\\/g,"/");process.argv.slice(2);process.on("uncaughtException",function(a){throw a;});process.on("unhandledRejection",z);e.inspect=function(){return"[Emscripten Module object]"}}else if(ca)"undefined"!=
                                                                                                                                                                                                                                                                                                                                                                                                         ^
abort(abort(abort(Error: ENOENT: no such file or directory, open '/home/paulogdm/Codes/tmp/ks-api/dist/node_modules/camaro/dist/camaro.wasm'). Build with -s ASSERTIONS=1 for more info.). Build with -s ASSERTIONS=1 for more info.). Build with -s ASSERTIONS=1 for more info.

Add support for `argon2`

This integration test fails:

const argon2 = require('argon2');
console.log('argon is ' + typeof argon2);

Error

/private/var/folders/v7/6kzxdgb93x328tk9pg633s200000gn/T/node-file-trace-2963026860021942/node_modules/node-gyp-build/index.js:56
  throw new Error('No native build was found for ' + target)
  ^

Error: No native build was found for platform=darwin arch=x64 runtime=node abi=64 uv=1 libc=glibc
    at Function.load.path (/private/var/folders/v7/6kzxdgb93x328tk9pg633s200000gn/T/node-file-trace-2963026860021942/node_modules/node-gyp-build/index.js:56:9)
    at load (/private/var/folders/v7/6kzxdgb93x328tk9pg633s200000gn/T/node-file-trace-2963026860021942/node_modules/node-gyp-build/index.js:20:30)
    at Object.<anonymous> (/private/var/folders/v7/6kzxdgb93x328tk9pg633s200000gn/T/node-file-trace-2963026860021942/node_modules/argon2/argon2.js:5:81)
    at Module._compile (internal/modules/cjs/loader.js:776:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Module.require (internal/modules/cjs/loader.js:690:17)
    at require (internal/modules/cjs/helpers.js:25:18)

Related to https://github.com/zeit/now-builders/issues/929

This is likely an issue with argon2's dependency node-gyp-build (related to #1) which will likely have to be special cased.

Fix `firebase/database` package

Related to vercel/vercel#1830

Steps to reproduce

yarn add firebase

const firebase = require('firebase/app');
require('firebase/database');
console.log('firebase type is ' + typeof firebase);

Error

Cannot find module 'request' loaded from node_modules/@firebase/database/dist/index.node.cjs.js

Does not work if `base` is not provided

To reproduce:

echo "module.exports = 'hello'" > hello.js
echo "let hello = require('./hello')" > index.js
echo "(async () => console.log((await require('@zeit/node-file-trace')(['./index.js'])).fileList))()" > trace.js
node trace.js

Result:

> node trace.js
[ '/Users/luc/w/test/node-file-trace-repro/api/index.js' ]

I would expect that hello.js to be included in fileList but it's not. It works again when I add base in the config object.

Use cjs/es-module-lexer instead of acorn

Given that @guybedford is involved in nft I don't expect this to be a novel idea but I'd like to discuss it anyway.
I think it would be possible to use these two modules to detect all requires instead of depending on acorn and walking the AST. The main advantage would be that it's likely faster and would make nft smaller/simpler.

https://github.com/guybedford/cjs-module-lexer
https://github.com/guybedford/es-module-lexer

Unfortunately cjs-module-lexer doesn't output required files but this PR adds support for it: nodejs/cjs-module-lexer#10

The main blocker for that PR appears to be that detecting requires is somewhat of an unbounded problem, however clear boundaries in what can/cannot be detected might help both cjs-module-lexer and nft.

Add support for `less-plugin-clean-css`

Package: https://www.npmjs.com/package/less-plugin-clean-css

The following integration test fails:

const LessPluginCleanCSS = require('less-plugin-clean-css');
console.log('The less plugin clean css is type ' + typeof LessPluginCleanCSS);

The error is:

internal/modules/cjs/loader.js:638
    throw err;
    ^

Error: Cannot find module './base64-vlq'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
    at Function.Module._load (internal/modules/cjs/loader.js:562:25)
    at Module.require (internal/modules/cjs/loader.js:690:17)
    at require (internal/modules/cjs/helpers.js:25:18)
    at stringRequire (/private/var/folders/v7/6kzxdgb93x328tk9pg633s200000gn/T/node-file-trace-7062704343464894/node_modules/amdefine/amdefine.js:220:28)
    at amdRequire (/private/var/folders/v7/6kzxdgb93x328tk9pg633s200000gn/T/node-file-trace-7062704343464894/node_modules/amdefine/amdefine.js:113:24)
    at Object.<anonymous> (/private/var/folders/v7/6kzxdgb93x328tk9pg633s200000gn/T/node-file-trace-7062704343464894/node_modules/clean-css/node_modules/source-map/lib/source-map/source-map-generator.js:12:19)
    at runFactory (/private/var/folders/v7/6kzxdgb93x328tk9pg633s200000gn/T/node-file-trace-7062704343464894/node_modules/amdefine/amdefine.js:183:30)
    at define (/private/var/folders/v7/6kzxdgb93x328tk9pg633s200000gn/T/node-file-trace-7062704343464894/node_modules/amdefine/amdefine.js:277:13)
    at Object.<anonymous> (/private/var/folders/v7/6kzxdgb93x328tk9pg633s200000gn/T/node-file-trace-7062704343464894/node_modules/clean-css/node_modules/source-map/lib/source-map/source-map-generator.js:10:1)

Reported here: https://spectrum.chat/zeit/now/error-cannot-find-module-base64-vlq~d61cd796-d48c-4a65-9d5c-045fae23964b

Add support for `bull`

Example integration test:

const Queue = require('bull');
const host = 'redis123.cloud.redislabs.com';
const port = 10883;
const password = 'abc123pswrd';
const pdfQueue = new Queue('pdf transcoding', { redis: { port, host, password }});

pdfQueue.process(function(job, done) {
    job.progress(42);
    job.progress(99);
    done();
    pdfQueue.close();
});

pdfQueue.add({ pdf: 'http://example.com/file.pdf' });

This currently fails to find any files in node_modules/bull/** like I would expect and fails with the following error:

TypeError: queue.client.updateDelaySet is not a function

Add option to allow app directory globs from packages

For things like automatic loading of translation files, it may be nice to allow globs of files even when they are not within the package boundary. Right now the following fails if it's part of a module:

const en = fs.readFileSync(path.resolve('locales/en.json');

In my specific case, I was also interested in having an installed module be able to preserve a directory by doing:

fs.statSync(path.resolve('app-data-dir'));

But there may be more examples, like automatically loaded config files from the app/working directory.

Add special case for `rox-ssr-multi-entrypoints`

rox-ssr-multi-entrypoints depends on rox-ssr which depends on rox-node and fails with:

Error: Cannot find module 'rox-node'
Require stack:
- /Users/styfle/Code/example/dist/node_modules/rox-ssr/dist/es6/utils.js
- /Users/styfle/Code/example/dist/node_modules/rox-ssr/dist/es6/index.js
- /Users/styfle/Code/example/dist/node_modules/rox-ssr-multi-entrypoints/dist/es6/index.js
- /Users/styfle/Code/example/dist/index.js

Steps to reproduce

  1. Run yarn add rox-ssr-multi-entrypoints
  2. Create a file with const { Rox } = require('rox-ssr-multi-entrypoints'); Rox.register('', {}); Rox.setup('12345')
  3. Run nft print index.js
  4. Expected node_modules/rox-node

Related to vercel/next.js#13736

Crashes when tracing `apollo-upload-client`

There are certain situations where nodeFileTrace crashes on perfectly valid modules. This critical bug is causing Vercel deployment errors for apollo-upload-client (see jaydenseric/apollo-upload-client#211) and next-graphql-react/graphql-react users.

For example:

const { nodeFileTrace } = require('@zeit/node-file-trace');
nodeFileTrace(['index.js']).then(console.log)

With index.js containing:

const ReactNativeFile = require('apollo-upload-client/public/ReactNativeFile')

Or alternatively containing:

const { ReactNativeFile } = require('apollo-upload-client')

nodeFileTrace crashes with an unhandled promise rejection:

(node:4082) UnhandledPromiseRejectionWarning: Error: File /[redacted]/node_modules/apollo-upload-clientpublic/ReactNativeFile does not exist.
    at Job.emitDependency (/[redacted]/node_modules/@zeit/node-file-trace/out/node-file-trace.js:261:23)
    at /[redacted]/node_modules/@zeit/node-file-trace/out/node-file-trace.js:290:36
    at async Promise.all (index 0)
    at async Job.emitDependency (/[redacted]/node_modules/@zeit/node-file-trace/out/node-file-trace.js:268:9)
    at async /[redacted]/node_modules/@zeit/node-file-trace/out/node-file-trace.js:297:21
    at async Promise.all (index 0)
    at async Job.emitDependency (/[redacted]/node_modules/@zeit/node-file-trace/out/node-file-trace.js:268:9)
    at async Promise.all (index 0)
    at async nodeFileTrace (/[redacted]/node_modules/@zeit/node-file-trace/out/node-file-trace.js:27:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:4082) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:4082) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

It seems to crash when one module re-exports something from another?

For example, if you replace the contents of index.js with:

const ReactNativeFile = require('extract-files/public/ReactNativeFile')

There is no crash.

Asset access isn't recognized in webpack bundles

In next apps, the app code is usually within a webpack bundle. The tracer currently doesn't recognize use of fs/path APIs in that context because of the indirection created by webpack.

Webpack Config

// Invoked via:
// $ webpack && prettier dist/cjs.js > dist/cjs.pretty.js && prettier dist/esm.js > dist/esm.pretty.js
'use strict';

module.exports = {
  mode: 'production',
  entry: {
    cjs: './src/cjs.js',
    esm: './src/esm.js',
  },
  node: false,
  externals: {
    fs: 'commonjs fs',
    path: 'commonjs path',
  },
};

CommonJS

// src/cjs.js
const fs = require('fs');
const path = require('path');

console.log(fs.readFileSync(path.resolve('package.json')));
Compiled Code (after Prettier)
!(function(e) {
  var t = {};
  function r(n) {
    if (t[n]) return t[n].exports;
    var o = (t[n] = { i: n, l: !1, exports: {} });
    return e[n].call(o.exports, o, o.exports, r), (o.l = !0), o.exports;
  }
  (r.m = e),
    (r.c = t),
    (r.d = function(e, t, n) {
      r.o(e, t) || Object.defineProperty(e, t, { enumerable: !0, get: n });
    }),
    (r.r = function(e) {
      "undefined" != typeof Symbol &&
        Symbol.toStringTag &&
        Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }),
        Object.defineProperty(e, "__esModule", { value: !0 });
    }),
    (r.t = function(e, t) {
      if ((1 & t && (e = r(e)), 8 & t)) return e;
      if (4 & t && "object" == typeof e && e && e.__esModule) return e;
      var n = Object.create(null);
      if (
        (r.r(n),
        Object.defineProperty(n, "default", { enumerable: !0, value: e }),
        2 & t && "string" != typeof e)
      )
        for (var o in e)
          r.d(
            n,
            o,
            function(t) {
              return e[t];
            }.bind(null, o)
          );
      return n;
    }),
    (r.n = function(e) {
      var t =
        e && e.__esModule
          ? function() {
              return e.default;
            }
          : function() {
              return e;
            };
      return r.d(t, "a", t), t;
    }),
    (r.o = function(e, t) {
      return Object.prototype.hasOwnProperty.call(e, t);
    }),
    (r.p = ""),
    r((r.s = 2));
})([
  function(e, t) {
    e.exports = require("fs");
  },
  function(e, t) {
    e.exports = require("path");
  },
  function(e, t, r) {
    const n = r(0),
      o = r(1);
    console.log(n.readFileSync(o.resolve("package.json")));
  }
]);

ESM

// src/esm.js
import fs from 'fs';
import * as path from 'path';

console.log(fs.readFileSync(path.resolve('package.json')));
Compiled Code (after Prettier)
!(function(e) {
  var r = {};
  function t(n) {
    if (r[n]) return r[n].exports;
    var o = (r[n] = { i: n, l: !1, exports: {} });
    return e[n].call(o.exports, o, o.exports, t), (o.l = !0), o.exports;
  }
  (t.m = e),
    (t.c = r),
    (t.d = function(e, r, n) {
      t.o(e, r) || Object.defineProperty(e, r, { enumerable: !0, get: n });
    }),
    (t.r = function(e) {
      "undefined" != typeof Symbol &&
        Symbol.toStringTag &&
        Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }),
        Object.defineProperty(e, "__esModule", { value: !0 });
    }),
    (t.t = function(e, r) {
      if ((1 & r && (e = t(e)), 8 & r)) return e;
      if (4 & r && "object" == typeof e && e && e.__esModule) return e;
      var n = Object.create(null);
      if (
        (t.r(n),
        Object.defineProperty(n, "default", { enumerable: !0, value: e }),
        2 & r && "string" != typeof e)
      )
        for (var o in e)
          t.d(
            n,
            o,
            function(r) {
              return e[r];
            }.bind(null, o)
          );
      return n;
    }),
    (t.n = function(e) {
      var r =
        e && e.__esModule
          ? function() {
              return e.default;
            }
          : function() {
              return e;
            };
      return t.d(r, "a", r), r;
    }),
    (t.o = function(e, r) {
      return Object.prototype.hasOwnProperty.call(e, r);
    }),
    (t.p = ""),
    t((t.s = 3));
})([
  function(e, r) {
    e.exports = require("fs");
  },
  function(e, r) {
    e.exports = require("path");
  },
  ,
  function(e, r, t) {
    "use strict";
    t.r(r);
    var n = t(0),
      o = t.n(n),
      u = t(1);
    console.log(o.a.readFileSync(u.resolve("package.json")));
  }
]);

fs.readFile trigger

We should be triggering asset emission on fs.readFile arguments, even if those arguments might be "ambiguous strings" from an asset analysis perspective:

const fs = require('fs');
fs.readFile('./symlink');

This can be done with the existing [TRIGGER] system in place in the analysis, it just needs to be set up.

Trace stops at `.mjs` files

With the advent of --experimental-modules getting unflagged, it may be good to support tracing through .mjs files. It looks like right now it doesn't even try to parse them?

unable to run on typescript file

target file: /Workspace/github/asynchronous-dev/botany/ui/pages/api/auth/[provider].ts

file contents:

import withPassport, { passport } from 'lib/withPassport';
import { NextApiResponse, NextApiRequest } from 'next';
import debug from 'shared/debug';

const handler = (req: NextApiRequest, res: NextApiResponse) => {
  const { provider } = req.query;
  if (!provider) {
    return { statusCode: 404 };
  }

  debug('auth', 'begin', provider);
  passport.authenticate(provider)(req, res, (...args) => {
    debug('auth', 'next', args);
  });
};

export default withPassport(handler);

trace call

yarn run v1.19.0
$ babel-node-ts trace.ts
{ fileList: [ 'pages/api/auth/[provider].ts' ],
  esmFileList: [],
  reasons:
   [Object: null prototype] {
     'pages/api/auth/[provider].ts': { type: 'initial', ignored: false, parents: [] } },
  warnings:
   [ Error: Failed to parse /Workspace/github/asynchronous-dev/botany/ui/pages/api/auth/[provider].ts as module:
     Unexpected token (5:20)
         at module.exports (/Workspace/github/asynchronous-dev/botany/node_modules/@zeit/node-file-trace/src/analyze.js:210:24)
         at Job.emitDependency (/Workspace/github/asynchronous-dev/botany/node_modules/@zeit/node-file-trace/src/node-file-trace.js:206:43)
         at Promise.all.files.map.file (/Workspace/github/asynchronous-dev/botany/node_modules/@zeit/node-file-trace/src/node-file-trace.js:31:18)
         at Array.map (<anonymous>)
         at module.exports (/Workspace/github/asynchronous-dev/botany/node_modules/@zeit/node-file-trace/src/node-file-trace.js:27:27)
         at Object.<anonymous> (/Workspace/github/asynchronous-dev/botany/ui/trace.ts:10:31)
         at Module._compile (internal/modules/cjs/loader.js:776:30)
         at Module._compile (/Workspace/github/asynchronous-dev/botany/node_modules/pirates/lib/index.js:99:24)
         at Module._extensions..js (internal/modules/cjs/loader.js:787:10)
         at Object.newLoader (/Workspace/github/asynchronous-dev/botany/node_modules/pirates/lib/index.js:104:7) ] }
undefined
โœจ  Done in 2.13s.

FS operations from compiled TypeScript import are ignored

If a third-party module was compiled from TypeScript (I assume the same is true for babel as well), the resulting code looks like this (simplified):

// Original:
import fs from 'fs';
fs.readFileSync('/path/to/file');

// Actual code:
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
const fs_1 = __importDefault(require("fs"));
fs_1.default.readFileSync('/path/to/file');

Afaict this causes node-file-trace to miss these file system operations, omitting the files from the build output.

Please add support for `envkey`

https://github.com/envkey/envkey-node

For some reason, it doesn't pick up on the binaries needed. Presently the integration test:

require('envkey')

fails with

  โ— should correctly trace and correctly execute envkey.js

    expect(received).toBe(expected) // Object.is equality

    Expected: 0
    Received: 1

      51 |     });
      52 |     const code = await new Promise(resolve => ps.on('close', resolve));
    > 53 |     expect(code).toBe(fails ? 1 : 0);
         |                  ^
      54 |     rimraf.sync(tmpdir);
      55 |   });
      56 | }

Absolute path mapping

It would be cool to add absolute path mapping support to this module. It is necessary to make typescript paths (compilerOptions.paths in tsconfig.json) work in @now/node.

Add support for `serve-favicon` on Windows

The following integration test currently fails to return anything on Windows but works fine on Linux and macOS.

(This snippet was taken from loopback.js)

var favicon = require('serve-favicon');
var path = require('path');

module.exports = function(icon, options) {
  icon = icon || path.join(__dirname, '../../favicon.ico');
  return favicon(icon, options);
};

Cleaning up modules removes necessary files

Hello,

I'm trying to deploy with now (v.2) a monorepo project which uses svgo, and svgo is using a default config file from node_modules/svgo/.svgo.yml.

โ™ป๏ธ During the build phase, on step [5/5] when now is cleaning modules the .svgo.yml file is removed.

I tried to add a .yarnclean file with !.svgo.yml inside but no success.

Any ideas how can I prevent the cleanup step or fix this?

Error: ENOENT: no such file or directory, open '//../../.svgo.yml'

The svgo issue.

Cache trace results for paths which start with node_modules

With the recent update, the @now/node builder switched from ncc to node-file-trace. This has already improved the build performance for my endpoints.
zeit/now-builders#786 illustrated that of the remaining time, most was spent in node-file-trace either the trace or the typescript compilation. A manual check running only node-file-trace demonstrated that the trace was the greatest contributor.

While the time is perfectly acceptable for a first time compilation, repeated compilation of the same endpoint in now dev with trival changes (add a comment to the file, add a console log etc) takes the same time.
This leads me to believe that node-file-trace doesn't cache trace results from one run to another.

The attached project node-20.zip(initially created by @styfle updated to the last versions of the stack tools) exhibits this behaviour.

I suggest updating node-file-trace to keep a cache of the trace result for each path in the result (this could take the form of a dictionnary with a path as key and an object with the hash of the content at that path associated with the resolved list of dependencies as value), retracing a codebase which was previously traced would be able to avoid retracing all the files which have already been traced when an entry is found in the map and the content hash matches. If the content hash doesn't match, the entry must be discarded and retracing must proceed on all the file's dependencies.

.tsx files used as an entrypoint for an API fail to get compiled

I thought I was out of the woods with https://github.com/zeit/now-builders/issues/869 getting fixed, but I hit a new problem.

I've got some routes handled by .tsx files:

{
	"builds": [
		{
			"src": "api-handler.tsx",
			"use": "@now/node"
		}
	],
	"routes": [
		{ "src": "/api-typescript", "dest": "api-handler.tsx" },
	]
}

And on the latest node builder they fail to get compiled, resulting in runtime errors due to TypeScript syntax remaining intact.

Repo that reproduces the issue: https://github.com/tylerc/zeit-now-ts-debugging

This is an issue everywhere. On my Windows machine, my Mac, and when deployed via now (so must be on Linux as well).

I traced back the cause to node-file-trace. I'll be filing a PR shortly.

Pinging @styfle since you were the one who handled my last issue.

Add support for `@prisma/sdk`

Similar to #28 there is a binary file that is dynamically generated that must be included.

Steps to reproduce:

  1. yarn add @prisma/sdk
  2. Create a file with:
const { getDMMF } = require('@prisma/sdk')

const defaultSchema = `
generator photon {
  provider = "photonjs"
}

model Test {
  id                 String           @default(cuid()) @id
}
`;

getDMMF({ datamodel: defaultSchema})
  .then(() => console.log('success')
  .catch(() => console.log('error')

Fails with error Could not find query-engine binary.

Solution

Special case @prisma/sdk/dist/engineCommands.js to include @prisma/sdk/query-engine-*.

Add support for `hummus-recipe`: fails with this._getEncryptOptions not a function

Reproducible example: https://codesandbox.io/s/distracted-bardeen-kks92
Public deployment with logs: https://zeit.co/pgdm/csb-kks92/qo1379ftg

ERROR	TypeError: this._getEncryptOptions is not a function
    at new Recipe (/var/task/node_modules/hummus-recipe/lib/Recipe.js:31:36)
    at /var/task/api/index.js:6:18
    at Layer.handle [as handle_request] (/var/task/node_modules/express/lib/router/layer.js:95:5)
    at next (/var/task/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/var/task/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/var/task/node_modules/express/lib/router/layer.js:95:5)
    at /var/task/node_modules/express/lib/router/index.js:281:22
    at Function.process_params (/var/task/node_modules/express/lib/router/index.js:335:12)
    at next (/var/task/node_modules/express/lib/router/index.js:275:10)
    at expressInit (/var/task/node_modules/express/lib/middleware/init.js:40:5)

Fails to trace `polyfill-library` package: Cannot read property 'type' of null

Versions

Tested with [email protected] and [email protected].

Input file

const polyfill = require('polyfill-library')

async function handler() {
  const script = await polyfill.getPolyfillString({
    minify: false,
    features: { 'es6': { flags: ['gated'] }
  })
  return script
}

handler().then(script => console.log(typeof script)).catch(console.error)

Error

TypeError: Cannot read property 'type' of null
    at handleWrappers (/usr/local/lib/node_modules/@zeit/node-file-trace/src/utils/wrappers.js:313:60)
    at module.exports (/usr/local/lib/node_modules/@zeit/node-file-trace/src/analyze.js:398:3)
    at Job.emitDependency (/usr/local/lib/node_modules/@zeit/node-file-trace/src/node-file-trace.js:245:40)
    at /usr/local/lib/node_modules/@zeit/node-file-trace/src/node-file-trace.js:256:22
    at Array.map (<anonymous>)
    at Job.emitDependency (/usr/local/lib/node_modules/@zeit/node-file-trace/src/node-file-trace.js:252:22)
    at async /usr/local/lib/node_modules/@zeit/node-file-trace/src/node-file-trace.js:270:9
    at async Promise.all (index 2)
    at async Job.emitDependency (/usr/local/lib/node_modules/@zeit/node-file-trace/src/node-file-trace.js:251:5)
    at async /usr/local/lib/node_modules/@zeit/node-file-trace/src/node-file-trace.js:270:9

`phantomjs-prebuilt` does not work

Attached is a zip for a project that uses phantomjs-prebuilt, and results in an error such as:

Error: spawn /var/task/node_modules/phantomjs-prebuilt/lib/phantom/bin/phantomjs ENOENT

Reproducible in now dev as well. When I take a look at the file path "node_modules/phantomjs-prebuilt/lib/phantom/bin/phantomjs" the file is indeed not there, so perhaps the detection mechanism isn't including the binary into the output results.

odc.zip

Error with Sentry and named exports

If I have two files:

// index.js
require('./sentry')

// sentry.js
const Sentry = require('@sentry/node')
module.exports = { log: console.log }

This package will fail to include @sentry/node in the trace (the entrypoint is index.js).

On the other hand, if I use a default export in sentry.js:

// sentry.js
const Sentry = require('@sentry/node')
module.exports = console.log

it works.

Add support for monorepo packages

In monorepo yarn workspace packages, for a package at ./packages/x the dependencies are often at ./node_modules

This is blacklisted in

if (path.startsWith('..' + sep)) return true;

Thoughts on adding an ignore opt in NodeFileTraceOptions that overrides the default and allows specific parent deps for people who need it?

Fails to trace `paraphrase/percent`: Cannot read property 'type' of null

@zeit/node-file-trace: 0.6.4
Node: v12.17.0

Input file:

import paraphrase from 'paraphrase/percent';

Running:

  const nodeFileTrace = require('@zeit/node-file-trace');
  const files = ['test2.js'];
  const { fileList } = await nodeFileTrace(files);

error is:

(node:15413) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'type' of null
    at /Users/chrismcc/workspace/social-distancin/node_modules/@zeit/node-file-trace/src/utils/wrappers.js:324:56
    at Array.every (<anonymous>)
    at handleWrappers (/Users/chrismcc/workspace/social-distancin/node_modules/@zeit/node-file-trace/src/utils/wrappers.js:324:41)
    at module.exports (/Users/chrismcc/workspace/social-distancin/node_modules/@zeit/node-file-trace/src/analyze.js:398:3)
    at Job.emitDependency (/Users/chrismcc/workspace/social-distancin/node_modules/@zeit/node-file-trace/src/node-file-trace.js:245:40)
    at /Users/chrismcc/workspace/social-distancin/node_modules/@zeit/node-file-trace/src/node-file-trace.js:270:20
    at async Promise.all (index 0)
    at async Job.emitDependency (/Users/chrismcc/workspace/social-distancin/node_modules/@zeit/node-file-trace/src/node-file-trace.js:251:5)
    at async Promise.all (index 0)
    at async module.exports (/Users/chrismcc/workspace/social-distancin/node_modules/@zeit/node-file-trace/src/node-file-trace.js:27:3)

Looks like a potential regression from c7f25ef

Expand compatibility to @trifoia/zcrmsdk

Reproduction example: https://github.com/jormaj/debug

NPM page

Error:

Cannot find module './local/local_util'
Require stack:- /var/task/api/node_modules/@trifoia/zcrmsdk/lib/js/util.js- /var/task/api/node_modules/@trifoia/zcrmsdk/lib/js/modules.js- /var/task/api/node_modules/@trifoia/zcrmsdk/lib/js/crmapi.js- /var/task/api/node_modules/@trifoia/zcrmsdk/lib/js/ZCRMRestClient.js- /var/task/api/test.js- /var/task/___now_launcher.js- /var/runtime/UserFunction.js- /var/runtime/index.js

Add support for `fast-glob`

The fast-glob package depends on @nodelib/fs.stat but the trace fails to pick up this dependency.

It finds these two just fine:

fast-glob/out/providers/stream.js
fast-glob/out/providers/sync.js

Here's the contents of sync.js which clearly requires fs.stat:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fsStat = require("@nodelib/fs.stat");
const fsWalk = require("@nodelib/fs.walk");
const reader_1 = require("./reader");
class ReaderSync extends reader_1.default {
    constructor() {
        super(...arguments);
        this._walkSync = fsWalk.walkSync;
        this._statSync = fsStat.statSync;
    }
    dynamic(root, options) {
        return this._walkSync(root, options);
    }
    static(patterns, options) {
        const entries = [];
        for (const pattern of patterns) {
            const filepath = this._getFullEntryPath(pattern);
            const entry = this._getEntry(filepath, pattern, options);
            if (entry === null || !options.entryFilter(entry)) {
                continue;
            }
            entries.push(entry);
        }
        return entries;
    }
    _getEntry(filepath, pattern, options) {
        try {
            const stats = this._getStat(filepath);
            return this._makeEntry(stats, pattern);
        }
        catch (error) {
            if (options.errorFilter(error)) {
                return null;
            }
            throw error;
        }
    }
    _getStat(filepath) {
        return this._statSync(filepath, this._fsStatSettings);
    }
}
exports.default = ReaderSync;

cc @williamli @Timer

Failing to trace node_modules containing symlinks (yarn workspaces)

The issue is that node-file-trace is following the symlinks is node_modules instead of returning them in the fileList output.

Steps to reproduce

git clone https://github.com/mattste/now-node-builder-issue
cd now-node-builder-issue
yarn install
cat > build.js <<- "EOF"
const nodeFileTrace = require('@zeit/node-file-trace');

nodeFileTrace(['project-a/index.js'], {
  base: process.cwd(),
  filterBase: true,
  ts: true,
}).then(({fileList}) => {
  console.log(fileList.join('\n'));
});

EOF

node build.js

Actual

        project-a/index.js
        project-b/index.js

Expected

        project-a/index.js
        project-b/index.js
        node_modules/project-a/index.js

cc @guybedford

Incorrect readme usage instructions

The readme usage section incorrectly instructs that nodeFileTrace can be required like so:

const nodeFileTrace = require('@zeit/node-file-trace');

Screen Shot 2020-07-27 at 5 03 12 pm

When really, it must be required like this:

const { nodeFileTrace } = require('@zeit/node-file-trace');

fs.readdir(Sync) doesn't preserve directory

I would have expected that the following code preserves the directory in question:

fs.readdir('/some/dir', () => { /* actual code */ });

But it doesn't. The following does:

fs.stat('/some/dir', () => { /* ignored, just here for the tracer */ });
fs.readdir('/some/dir', () => { /* actual code */ });

Was this a conscious design decision?

Output from uglify cannot be traced

I encountered the propblem when using minfied library in next.js runtime environmennt, it coudnt be loaded property. And it looks like not the problem of uglify.

Following is the way for procedure the problem.

npm init -y
yarn add @vercel/[email protected]
yarn add [email protected]

run nft print

npx nft print ./node_modules/yt-search/dist/yt-search.js

print result

FILELIST:
node_modules/async.parallellimit/index.js
node_modules/async.parallellimit/package.json
node_modules/async.util.eachoflimit/index.js
node_modules/async.util.eachoflimit/package.json
node_modules/async.util.isarray/index.js
node_modules/async.util.isarray/package.json
node_modules/async.util.isarraylike/index.js
node_modules/async.util.isarraylike/package.json
node_modules/async.util.keyiterator/index.js
node_modules/async.util.keyiterator/package.json
node_modules/async.util.keys/index.js
node_modules/async.util.keys/package.json
node_modules/async.util.noop/index.js
node_modules/async.util.noop/package.json
node_modules/async.util.once/index.js
node_modules/async.util.once/package.json
node_modules/async.util.onlyonce/index.js
node_modules/async.util.onlyonce/package.json
node_modules/async.util.parallel/index.js
node_modules/async.util.parallel/package.json
node_modules/async.util.restparam/index.js
node_modules/async.util.restparam/package.json
node_modules/boolbase/index.js
node_modules/boolbase/package.json
node_modules/cheerio/index.js
node_modules/cheerio/lib/api/attributes.js
node_modules/cheerio/lib/api/css.js
node_modules/cheerio/lib/api/forms.js
node_modules/cheerio/lib/api/manipulation.js
node_modules/cheerio/lib/api/traversing.js
node_modules/cheerio/lib/cheerio.js
node_modules/cheerio/lib/parse.js
node_modules/cheerio/lib/static.js
node_modules/cheerio/lib/utils.js
node_modules/cheerio/node_modules/dom-serializer/index.js
node_modules/cheerio/node_modules/dom-serializer/package.json
node_modules/cheerio/package.json
node_modules/css-select/index.js
node_modules/css-select/lib/attributes.js
node_modules/css-select/lib/compile.js
node_modules/css-select/lib/general.js
node_modules/css-select/lib/procedure.json
node_modules/css-select/lib/pseudos.js
node_modules/css-select/lib/sort.js
node_modules/css-select/package.json
node_modules/css-what/index.js
node_modules/css-what/package.json
node_modules/dasu/dist/dasu.min.js
node_modules/dasu/package.json
node_modules/dom-serializer/foreignNames.json
node_modules/dom-serializer/index.js
node_modules/dom-serializer/node_modules/domelementtype/lib/index.js
node_modules/dom-serializer/node_modules/domelementtype/package.json
node_modules/dom-serializer/node_modules/entities/lib/decode.js
node_modules/dom-serializer/node_modules/entities/lib/decode_codepoint.js
node_modules/dom-serializer/node_modules/entities/lib/encode.js
node_modules/dom-serializer/node_modules/entities/lib/index.js
node_modules/dom-serializer/node_modules/entities/lib/maps/decode.json
node_modules/dom-serializer/node_modules/entities/lib/maps/entities.json
node_modules/dom-serializer/node_modules/entities/lib/maps/legacy.json
node_modules/dom-serializer/node_modules/entities/lib/maps/xml.json
node_modules/dom-serializer/node_modules/entities/package.json
node_modules/dom-serializer/package.json
node_modules/domelementtype/index.js
node_modules/domelementtype/package.json
node_modules/domhandler/index.js
node_modules/domhandler/lib/element.js
node_modules/domhandler/lib/node.js
node_modules/domhandler/package.json
node_modules/domutils/index.js
node_modules/domutils/lib/helpers.js
node_modules/domutils/lib/legacy.js
node_modules/domutils/lib/manipulation.js
node_modules/domutils/lib/querying.js
node_modules/domutils/lib/stringify.js
node_modules/domutils/lib/traversal.js
node_modules/domutils/package.json
node_modules/entities/index.js
node_modules/entities/lib/decode.js
node_modules/entities/lib/decode_codepoint.js
node_modules/entities/lib/encode.js
node_modules/entities/maps/decode.json
node_modules/entities/maps/entities.json
node_modules/entities/maps/legacy.json
node_modules/entities/maps/xml.json
node_modules/entities/package.json
node_modules/escodegen/escodegen.js
node_modules/escodegen/package.json
node_modules/esprima/esprima.js
node_modules/esprima/package.json
node_modules/estraverse/estraverse.js
node_modules/estraverse/package.json
node_modules/esutils/lib/ast.js
node_modules/esutils/lib/code.js
node_modules/esutils/lib/keyword.js
node_modules/esutils/lib/utils.js
node_modules/esutils/package.json
node_modules/htmlparser2/lib/CollectingHandler.js
node_modules/htmlparser2/lib/FeedHandler.js
node_modules/htmlparser2/lib/Parser.js
node_modules/htmlparser2/lib/ProxyHandler.js
node_modules/htmlparser2/lib/Stream.js
node_modules/htmlparser2/lib/Tokenizer.js
node_modules/htmlparser2/lib/WritableStream.js
node_modules/htmlparser2/lib/index.js
node_modules/htmlparser2/node_modules/domutils/index.js
node_modules/htmlparser2/node_modules/domutils/lib/helpers.js
node_modules/htmlparser2/node_modules/domutils/lib/legacy.js
node_modules/htmlparser2/node_modules/domutils/lib/manipulation.js
node_modules/htmlparser2/node_modules/domutils/lib/querying.js
node_modules/htmlparser2/node_modules/domutils/lib/stringify.js
node_modules/htmlparser2/node_modules/domutils/lib/traversal.js
node_modules/htmlparser2/node_modules/domutils/package.json
node_modules/htmlparser2/package.json
node_modules/human-time/human.js
node_modules/human-time/package.json
node_modules/inherits/inherits.js
node_modules/inherits/inherits_browser.js
node_modules/inherits/package.json
node_modules/jsonpath/generated/parser.js
node_modules/jsonpath/include/action.js
node_modules/jsonpath/include/module.js
node_modules/jsonpath/index.js
node_modules/jsonpath/lib/aesprim.js
node_modules/jsonpath/lib/dict.js
node_modules/jsonpath/lib/grammar.js
node_modules/jsonpath/lib/handlers.js
node_modules/jsonpath/lib/index.js
node_modules/jsonpath/lib/parser.js
node_modules/jsonpath/lib/slice.js
node_modules/jsonpath/package.json
node_modules/lodash.assignin/index.js
node_modules/lodash.assignin/package.json
node_modules/lodash.bind/index.js
node_modules/lodash.bind/package.json
node_modules/lodash.defaults/index.js
node_modules/lodash.defaults/package.json
node_modules/lodash.filter/index.js
node_modules/lodash.filter/package.json
node_modules/lodash.flatten/index.js
node_modules/lodash.flatten/package.json
node_modules/lodash.foreach/index.js
node_modules/lodash.foreach/package.json
node_modules/lodash.map/index.js
node_modules/lodash.map/package.json
node_modules/lodash.merge/index.js
node_modules/lodash.merge/package.json
node_modules/lodash.pick/index.js
node_modules/lodash.pick/package.json
node_modules/lodash.reduce/index.js
node_modules/lodash.reduce/package.json
node_modules/lodash.reject/index.js
node_modules/lodash.reject/package.json
node_modules/lodash.some/index.js
node_modules/lodash.some/package.json
node_modules/nth-check/compile.js
node_modules/nth-check/index.js
node_modules/nth-check/package.json
node_modules/nth-check/parse.js
node_modules/readable-stream/errors.js
node_modules/readable-stream/lib/_stream_duplex.js
node_modules/readable-stream/lib/_stream_passthrough.js
node_modules/readable-stream/lib/_stream_readable.js
node_modules/readable-stream/lib/_stream_transform.js
node_modules/readable-stream/lib/_stream_writable.js
node_modules/readable-stream/lib/internal/streams/async_iterator.js
node_modules/readable-stream/lib/internal/streams/buffer_list.js
node_modules/readable-stream/lib/internal/streams/destroy.js
node_modules/readable-stream/lib/internal/streams/end-of-stream.js
node_modules/readable-stream/lib/internal/streams/from.js
node_modules/readable-stream/lib/internal/streams/pipeline.js
node_modules/readable-stream/lib/internal/streams/state.js
node_modules/readable-stream/lib/internal/streams/stream.js
node_modules/readable-stream/package.json
node_modules/readable-stream/readable.js
node_modules/safe-buffer/index.js
node_modules/safe-buffer/package.json
node_modules/source-map/lib/array-set.js
node_modules/source-map/lib/base64-vlq.js
node_modules/source-map/lib/base64.js
node_modules/source-map/lib/binary-search.js
node_modules/source-map/lib/mapping-list.js
node_modules/source-map/lib/quick-sort.js
node_modules/source-map/lib/source-map-consumer.js
node_modules/source-map/lib/source-map-generator.js
node_modules/source-map/lib/source-node.js
node_modules/source-map/lib/util.js
node_modules/source-map/package.json
node_modules/source-map/source-map.js
node_modules/static-eval/index.js
node_modules/static-eval/package.json
node_modules/string_decoder/lib/string_decoder.js
node_modules/string_decoder/package.json
node_modules/underscore/package.json
node_modules/underscore/underscore.js
node_modules/util-deprecate/node.js
node_modules/util-deprecate/package.json
node_modules/yt-search/dist/yt-search.js
node_modules/yt-search/package.json

Change yt-search version (minified version)

run nft print

npx nft print ./node_modules/yt-search/dist/yt-search.min.js

print result

FILELIST:
node_modules/yt-search/dist/yt-search.min.js
node_modules/yt-search/package.json

Hmm, look like nothing loaded..

Related issues:

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.