关于javascript:nodejs交互工具库-memfs和execa

88次阅读

共计 9882 个字符,预计需要花费 25 分钟才能阅读完成。

nodejs 交互工具库系列

作用
chalk-pipe 应用更简略的款式字符串创立粉笔款式计划
chalk 正确处理终端字符串款式
Commander.js 残缺的 node.js 命令行解决方案
Inquirer.js 一组通用的交互式命令行用户界面。
slash 零碎门路符解决
minimist 解析参数选项
dotenv 将环境变量从 .env 文件加载到 process.env 中
hash-sum 十分快的惟一哈希生成器
deepmerge 深度合并两个或多个对象的可枚举属性。
yaml-front-matter 解析 yaml 或 json
resolve 实现 node 的 require.resolve()算法,这样就能够异步和同步地应用 require.resolve()代表文件
semver npm 的语义版本器
leven 测量两字符串之间的差别 <br/> 最快的 JS 实现之一
lru cache 删除最近起码应用的项的缓存对象
portfinder 主动寻找 800065535 内可用端口号
ora 优雅的终端转轮
envinfo 生成故障排除软件问题 (如操作系统、二进制版本、浏览器、已装置语言等) 时所需的通用详细信息的报告
memfs 内存文件系统与 Node’s fs API 雷同实现
execa 针对人类的流程执行

nodejs 交互工具库 — chalk-pipe 和 chalk

nodejs 交互工具库 — commander 和 Inquirer

nodejs 交互工具库 — slash, minimist 和 dotenv

nodejs 交互工具库 — hash-sum, deepmerge 和 yaml-front-matter

nodejs 交互工具库 — resolve 和 semver

nodejs 交互工具库 — leven, lru cache 和 portfinder

nodejs 交互工具库 — ora 和 envinfo

nodejs 交互工具库 — memfs 和 execa

memfs

内存文件系统与 Node’s fs API 雷同实现

  • Node’s fs API 实现, 查阅API Status
  • 在内存中存储文件Buffer
  • 像 Node.js 一样抛出 sameish* 谬误
  • i-nodes 的概念
  • 实现硬链接
  • 实现软链接(又名符号链接、符号链接)
  • 权限可能在将来被实现
  • 能够在浏览器中应用, 查阅memfs-webpack

Install

npm install --save memfs

Usage

import {fs} from 'memfs';

fs.writeFileSync('/hello.txt', 'World!');
fs.readFileSync('/hello.txt', 'utf8'); // World!

从一个一般 JSON 创立一个文件系统

import {fs, vol} from 'memfs';

const json = {
  './README.md': '1',
  './src/index.js': '2',
  './node_modules/debug/index.js': '3',
};
vol.fromJSON(json, '/app');

fs.readFileSync('/app/README.md', 'utf8'); // 1
vol.readFileSync('/app/src/index.js', 'utf8'); // 2

导出 JSON:

vol.writeFileSync('/script.sh', 'sudo rm -rf *');
vol.toJSON(); // {"/script.sh": "sudo rm -rf *"}

用来测试

vol.writeFileSync('/foo', 'bar');
expect(vol.toJSON()).toEqual({'/foo': 'bar'});

创立您须要的文件系统卷:

import {Volume} from 'memfs';

const vol = Volume.fromJSON({'/foo': 'bar'});
vol.readFileSync('/foo'); // bar

const vol2 = Volume.fromJSON({'/foo': 'bar 2'});
vol2.readFileSync('/foo'); // bar 2

应用 memfsunionfs 从内存卷和理论磁盘文件系统创立一个文件系统:

import * as fs from 'fs';
import {ufs} from 'unionfs';

ufs.use(fs).use(vol);

ufs.readFileSync('/foo'); // bar

应用fs-monkey 对 monkey-patch Node’s require 函数:

import {patchRequire} from 'fs-monkey';

vol.writeFileSync('/index.js', 'console.log("hi world")');
patchRequire(vol);
require('/index'); // hi world

Docs

  • Reference
  • Relative paths
  • API status
  • Dependencies

参考

根本罕用的办法场景就这些了, 更残缺的用法能够间接查阅文档

memfs

execa

针对人类的流程执行

Why

这个包改良了 child_process 办法:

  • Promise 接口
  • 从输入中删除最初的换行符,这样您就不用执行stdout.trim()
  • 反对跨平台的 shebang 二进制文件
  • 改良 Windows 反对。
  • 更高的最大缓冲区。100mb 而不是 200kb。
  • 按名称执行本地装置的二进制文件。
  • 在父过程终止时革除派生的过程。
  • stdoutstderr 取得交织输入,相似于在终端上打印的输入。(异步)
  • 能够指定文件和参数作为一个繁多的字符串没有外壳
  • 更具描述性的谬误。

Install

$ npm install execa

Usage

const execa = require('execa');

(async () => {const {stdout} = await execa('echo', ['unicorns']);
    console.log(stdout);
    //=> 'unicorns'
})();

通过管道将子过程 stdout 传输到父过程

const execa = require('execa');

execa('echo', ['unicorns']).stdout.pipe(process.stdout);

错误处理

const execa = require('execa');

(async () => {
  // Catching an error
  try {await execa('unknown', ['command']);
  } catch (error) {console.log(error);
    /*
    {
      message: 'Command failed with ENOENT: unknown command spawn unknown ENOENT',
      errno: -2,
      code: 'ENOENT',
      syscall: 'spawn unknown',
      path: 'unknown',
      spawnargs: ['command'],
      originalMessage: 'spawn unknown ENOENT',
      shortMessage: 'Command failed with ENOENT: unknown command spawn unknown ENOENT',
      command: 'unknown command',
      stdout: '',
      stderr: '',
      all: '',
      failed: true,
      timedOut: false,
      isCanceled: false,
      killed: false
    }
    */
  }

})();

勾销派生的过程

const execa = require('execa');

(async () => {const subprocess = execa('node');

  setTimeout(() => {subprocess.cancel();
  }, 1000);

  try {await subprocess;} catch (error) {console.log(subprocess.killed); // true
    console.log(error.isCanceled); // true
  }
})()

用同步办法捕捉谬误

try {execa.sync('unknown', ['command']);
} catch (error) {console.log(error);
    /*
    {
        message: 'Command failed with ENOENT: unknown command spawnSync unknown ENOENT',
        errno: -2,
        code: 'ENOENT',
        syscall: 'spawnSync unknown',
        path: 'unknown',
        spawnargs: ['command'],
        originalMessage: 'spawnSync unknown ENOENT',
        shortMessage: 'Command failed with ENOENT: unknown command spawnSync unknown ENOENT',
        command: 'unknown command',
        stdout: '',
        stderr: '',
        all: '',
        failed: true,
        timedOut: false,
        isCanceled: false,
        killed: false
    }
    */
}

杀死一个过程

应用 SIGTERM, 2 秒后,用 SIGKILL 杀死它。

const subprocess = execa('node');

setTimeout(() => {
  subprocess.kill('SIGTERM', {forceKillAfterTimeout: 2000});
}, 1000);

API

execa(file, arguments, options?)

执行一个文件。能够把它看作是 child_process.execFile()child_process.spawn() 的混合.

不须要本义 / 援用。

除非应用 shell 选项,否则没有 shell 解释器(Bash, cmd.exe, 等),因而不容许应用 shell 个性,如变量替换(echo $PATH)。

返回其中一个 child_process 实例:

  • 总是一个带有 childProcessResult 的胜利或者失败态的Promise.
  • 公开下列附加办法和属性。
kill(signal?, options?)

与原来的 child_process#kill()雷同,除了: 如果 signalSIGTERM(默认值),并且子过程在 5 秒后没有终止,通过发送 SIGKILL 强制执行。

options.forceKillAfterTimeout

Type: number | false
Default: 5000

在发送前期待子过程终止的毫秒 SIGKILL.

能够设置 false 禁用.

cancel()

相似于 childProcess.kill()。当勾销子过程执行时,这是首选的,因为谬误更具备描述性和 childProcessResult.scancelled 被设置为true

all

Type: ReadableStream | undefined

流合并 / 交织 stdout stderr.

这是 undefined如果满足其中:

  • all 选项为 false(默认值)
  • stdout stderr 选项都被设置为'inherit', 'ipc', Stream 或者 integer`

execa.sync(file, arguments?, options?)

同步执行文件。

返回或抛出childProcessResult.

execa.command(command, options?)

execa() 雷同,只是文件和参数都在单个命令字符串中指定。例如,execa('echo', ['unicorns'])execa.command('echo unicorns') 雷同。

如果文件或参数蕴含空格,则必须应用反斜杠对它们进行本义。如果 command 不是常量而是变量,例如 __dirnameprocess.cwd()是残余的,那么这一点尤其重要。除空分外,不须要本义 / 引号。

如果命令应用特定于 shell 的个性,则必须应用 shell 选项,而不是一个前面跟着参数的简略文件。

execa.commandSync(command, options?)

execa.command()雷同,然而是同步的。

返回或抛出一个 childProcessResult

execa.node(scriptPath, arguments?, options?)

将 Node.js 脚本作为子过程执行。

等同于 execa('node', [scriptPath, ...arguments], options) 除了(如child_process#fork())

  • 应用以后 Node 版本和选项。这能够应用 nodePathnodeOptions 选项笼罩。
  • 不能应用 shell选项
  • 一个额定的通道 ipc 被传递给 stdio

childProcessResult

Type: object

子过程执行的后果。对于胜利,这是一个简略的指标。对于失败,这也是一个谬误实例。

子过程在:

  • 它的退出代码不是 0
  • 它被一个信号杀死了
  • 定时生效
  • 被勾销了
  • 没有足够的内存或者子过程曾经太多了
command

Type: string

运行的文件和参数。

exitCode

Type: number

已运行过程的数字退出代码。

stdout

Type: string | Buffer

过程在 stdout 上的输入。

stderr

Type: string | Buffer

过程在 stderr 上的输入。

all

Type: string | Buffer | undefined

应用 stdoutstderr 的过程的输入是交织的。

这是 undefined如果满足其中:

  • all项是false(默认值)
  • execa.sync() 应用
failed

Type: boolean

过程是否运行失败。

timedOut

Type: boolean

过程是否超时。

isCanceled

Type: boolean

过程是否已勾销。

killed

Type: boolean

过程是否被终止。

signal

Type: string | undefined

用于终止过程的信号的名称。例如, SIGFPE.

如果一个信号终止了过程,则定义此属性并将其蕴含在谬误音讯中。否则它是 undefined.

signalDescription

Type: string | undefined

对用于终止过程的信号的人性化形容。例如 Floating point arithmetic error.

如果一个信号终止了过程,则定义此属性并将其蕴含在谬误音讯中。否则它是 undefined. 当信号十分不常见,而这种状况很少产生时,它也是undefined

message

Type: string

子过程运行失败时的谬误音讯。除了底层谬误音讯外,它还蕴含一些与子过程出错起因相干的信息。

子过程 stderr而后 stdout 被追加到开端,用新行分隔,不穿插。

shortMessage

Type: string

这与 message属性雷同,只是它不蕴含子过程stdout/stderr

originalMessage

Type: string | undefined

原始谬误音讯。这与 message属性雷同,只是它既不蕴含子过程stdout/stderr,也不蕴含 Execa 增加的一些附加信息。

这是undefined,除非子过程因为谬误事件或超时而退出。

options

Type: object

cleanup

Type: boolean
Default: true

当父过程退出时终止派生过程,除非:- 派生过程拆散 - 父过程忽然终止,例如,应用 SIGKILL而不是 SIGTERM 或失常退出

preferLocal

Type: boolean
Default: false

在寻找要执行的二进制文件时,首选本地装置的二进制文件。
如果你 $ npm install foo, 你能够 execa('foo').

localDir

Type: string
Default: process.cwd()

查找本地装置的二进制文件的首选门路 (应用 preferLocal).

execPath

Type: string
Default: process.execPath (以后的 node . js 可执行)

要在子过程中应用的 Node.js 可执行文件的门路。

这能够是绝对路径,也能够是绝对于 cwd选项的门路。

要求 preferLocaltrue.

例如,它能够与 get-node一起应用,在子过程中运行特定的 Node.js 版本。

buffer

Type: boolean
Default: true

缓冲生成的过程的输入。当设置为 false, 必须读取 stdoutstderr 的输入 (如果 all 选项为真,则读取all)。否则,返回的 promise 将不会被 resolved/rejected。

如果衍生的过程失败, error.stdout, error.stderr, 和error.all 将蕴含缓冲数据。

input

Type: string | Buffer | stream.Readable

向二进制文件的 stdin中写入一些输出。

在应用同步办法时不容许应用流。

stdin

Type: string | number | Stream | undefined
Default: pipe

stdio雷同的选项.

stdout

Type: string | number | Stream | undefined
Default: pipe

stdio雷同的选项.

stderr

Type: string | number | Stream | undefined
Default: pipe

stdio雷同的选项.

all

Type: boolean
Default: false

在承诺和解析值上增加.all 属性。该属性蕴含交织应用 stdout 和 stderr 的过程的输入。

reject

Type: boolean
Default: true

将此设置为 false将解决带有谬误的承诺,而不是回绝它。

stripFinalNewline

Type: boolean
Default: true

从输入中去掉最初的换行符。

extendEnv

Type: boolean
Default: true

如果在提供 env属性时不心愿扩大环境变量,则设置为false


Execa 还承受以下选项,这些选项与的选项雷同child_process#spawn()/child_process#exec()

cwd

Type: string
Default: process.cwd()

子过程的当前工作目录。

env

Type: object
Default: process.env

环境 key-value 对。主动从 process.env扩大。如果你不想这样做,请将 extendEnv 设置为false

argv0

Type: string

显式设置发送给子过程的 argv[0]的值。如果未指定,将设置为 file

stdio

Type: string | string[]
Default: pipe

子 stdio 配置.

serialization

Type: string
Default: 'json'

当应用 stdio: 'ipc'选项或 exec. node() 时,指定用于在过程之间发送音讯的序列化类型:- json: 应用 json .stringify()json .parse()。- advanced: 应用v8.serialize()

须要 Node.js13.2.0或更高版本。

detached

Type: boolean

让子过程独立于父过程运行。具体的行为取决于平台。

uid

Type: number

设置过程的用户标识。

gid

Type: number

设置流程的组标识。

shell

Type: boolean | string
Default: false

如果为真,则在 shell 中运行文件。在 UNIX 上应用 /bin/sh,在 Windows 上应用 cmd.exe。能够将不同的 shell 指定为字符串。shell 应该了解 UNIX 上的-c 开关或 Windows 上的 /d /s /c 开关。

咱们倡议不要应用此选项,因为它是:

  • 不是跨平台的,激励 shell 特定的语法。
  • 较慢,因为附加了 shell 解释。
  • 不平安,可能容许命令注入
encoding

Type: string | null
Default: utf8

指定用于解码 stdoutstderr 输入的字符编码。如果设置为 null,那么stdoutstderr将是缓冲区而不是字符串。

timeout

Type: number
Default: 0

如果超时工夫大于 0,如果子线程运行的工夫超过超时毫秒,父线程将发送 killSignal 属性标识的信号(默认为SIGTERM)。

maxBuffer

Type: number
Default: 100_000_000 (100 MB)

容许的最大字节数据量的 stdout 或者stderr.

killSignal

Type: string | number
Default: SIGTERM

当派生的过程将被终止时应用的信号值。

windowsVerbatimArguments

Type: boolean
Default: false

如果为真,则不会在 Windows 上援用或本义参数。在其余平台上被疏忽。当 shell 选项为真时,这将主动设置为真。

windowsHide

Type: boolean
Default: true

在 Windows 上,不要创立新的控制台窗口。请留神,这也会阻止 CTRL-CWindows 上工作。

nodePath (For .node() only)

Type: string
Default: process.execPath

用于创立子过程的可执行文件。

nodeOptions (For .node() only)

Type: string[]
Default: process.execArgv

传递给 Node.js 可执行文件的 CLI 选项列表。

Tips

Retry on error

通过应用主动重试和 p-retry 包指数返回 (exponential backoff) 来优雅地解决失败:

const pRetry = require('p-retry');

const run = async () => {const results = await execa('curl', ['-sSL', 'https://sindresorhus.com/unicorn']);
    return results;
};

(async () => {console.log(await pRetry(run, {retries: 5}));
})();

Save and pipe output from a child process

假如您心愿实时显示子过程的输入,同时将其保留到一个变量中。

const execa = require('execa');

const subprocess = execa('echo', ['foo']);
subprocess.stdout.pipe(process.stdout);

(async () => {const {stdout} = await subprocess;
    console.log('child output:', stdout);
})();

Redirect output to a file

const execa = require('execa');

const subprocess = execa('echo', ['foo'])
subprocess.stdout.pipe(fs.createWriteStream('stdout.txt'))

Redirect input from a file

const execa = require('execa');

const subprocess = execa('cat')
fs.createReadStream('stdin.txt').pipe(subprocess.stdin)

Execute the current package’s binary

const {getBinPathSync} = require('get-bin-path');

const binPath = getBinPathSync();
const subprocess = execa(binPath);

能够将 execaget-bin-path联合应用,以测试以后包的二进制代码。与硬编码到二进制文件的门路相同,这验证了 package.json bin字段设置正确。

参考

根本罕用的办法场景就这些了, 更残缺的用法能够间接查阅文档

execa

正文完
 0