arrow-left

Only this pageAll pages
gitbookPowered by GitBook
1 of 11

Docs

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

crypto

http

child_process

hashtag
exec

Spawns a shell then executes the command within that shell, buffering any generated output. The command string passed to the exec function is processed directly by the shell, and special characters (vary based on shellarrow-up-right) need to be dealt with accordingly:

Never pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution.

The stdout and stderr arguments passed to the stream will contain the stdout and stderr output of the child process. By default, Node.js will decode the output as UTF-8 and pass strings to the callback. The encoding option can be used to specify the character encoding used to decode the stdout and stderr output. If encoding is 'buffer', or an unrecognized character encoding, Buffer objects will be passed to the callback instead.

If timeout is greater than 0, the parent will send the signal identified by the killSignal property (the default is 'SIGTERM') if the child runs longer than timeout milliseconds.

Unlike the POSIX system call, exec() does not replace the existing process and uses a shell to execute the command.

hashtag
execFile

The execFile() function is similar to except that it does not spawn a shell by default. Rather, the specified executable file is spawned directly as a new process making it slightly more efficient than .

The same options as are supported. Since a shell is not spawned, behaviors such as I/O redirection and file globbing are not supported.

The stdout and stderr arguments passed to the stream will contain the stdout and stderr output of the child process. By default, Node.js will decode the output as UTF-8 and pass strings to the callback. The encoding option can be used to specify the character encoding used to decode the stdout and stderr output. If encoding is 'buffer', or an unrecognized character encoding, Buffer objects will be passed to the callback instead.

If the shell option is enabled, do not pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution.

function exec(
  command: string,
  options?: {
    encoding?: string | BufferEncoding | null | 'buffer';
    cwd?: string;
    env?: NodeJS.ProcessEnv;
    shell?: string;
    timeout?: number;
    maxBuffer?: number;
    killSignal?: string;
    uid?: number;
    gid?: number;
    windowsHide?: boolean;
  }
): Observable<[stdout: string | Buffer, stderr: string | Buffer]>;
exec('"/path/to/test file/test.sh" arg1 arg2').subscribe();
// Double quotes are used so that the space in the path is not interpreted as
// a delimiter of multiple arguments.

exec('echo "The \\$HOME variable is $HOME"').subscribe();
// The $HOME variable is escaped in the first instance, but not in the second.
exec(3)arrow-up-right
exec()
exec()
exec()
import { exec } from '@rxnode/child_process';

exec('cat *.js missing_file | wc -l').subscribe({
  next([stdout, stderr]) {
    console.log(`stdout: ${stdout}`);
    console.error(`stderr: ${stderr}`);
  },
  error(error) {
    console.error(`exec error: ${error}`);
  },
});
function execFile(
  file: string,
  args?: readonly string[],
  options?: {
    encoding?: string | null | BufferEncoding;
    cwd?: string;
    env?: NodeJS.ProcessEnv;
    timeout?: number;
    maxBuffer?: number;
    killSignal?: string;
    uid?: number;
    gid?: number;
    windowsHide?: boolean;
    windowsVerbatimArguments?: boolean;
    shell?: boolean | string;
  }
): Observable<[stdout: string | Buffer, stderr: string | Buffer]>;
import { execFile } from '@rxnode/child_process';

execFile('node', ['--version']).subscribe({
  next([stdout, stderr]) {
    console.log(stdout);
  },
  error(error) {
    console.error(`exec error: ${error}`);
  },
});

Libraries

Rxnode

hashtag
Rxnode — reactive nodejs API

At the beginning of 2020, my career as a frontend developer turned in an unexpected direction for me. I haven't written a single Angular component in a year. I Replaced Angular with server code and code for the CLI. It was a new and interesting experience for me, but it wasn't easy to solve my usual tasks without RxJS.

Let's look at a simple example of reading and writing a file using the native features of nodejs

Code with callbacks after Angular seems complicated. First, I translated callbacks to promises.

I was OK with this solution until I needed to implement several tasks' competitive execution with a limit. RxJS has such an opportunity out of the box. Why would I invent my own algorithm on promises?

The promisify function is replaced by the bindNodeCallback function, which RxJS itself supplies.

It quickly became apparent that you need to import and wrap the API in each file or move it to the library at the project level. And when there was more than one such project, I decided to put my developments in separate packages with the @rxnode scopes and published .

The project is NX Workspace. Each core package from nodejs corresponds to one library in a scope. If you want to use the fs package, you import functions with the same names from the@rxnode/fs packages.

This is how you can start a simple server.

Currently, Rxnode contains only 4 packages out of 20 planned. An up-to-date list can be found in the . We will be glad to receive any help in project development! We need your ideas and your hands!

hashtag
About logo

The Rxnode logo features an . And this is the merit of my wife, for which many thanks to her!

While working on the library, she looked at the RxJS logo and asked me, "Is this an axolotl?" When I replied negatively, she suggested depicting the axolotl on the Rxnode logo in Node.js shades. So I did!

hashtag
Packages

hashtag
We are supported by

import { readFile, writeFile } from 'fs';

readFile('src/some-file.js', (error, data) => {
  if (error) {
    console.error(error);
    return;
  }

  writeFile('src/some-file.js', data, (error) => {
    if (error) {
      console.error(error);
      return;
    }

    console.log('Success!');
  });
});
dns
  • the GitHub codearrow-up-right
    documentationarrow-up-right
    axolotlarrow-up-right
    child_process
    crypto
    arrow-up-right
    import * as fs from 'fs';
    import { promisify } from 'util';
    
    const readFile = promisify(fs.readFile);
    const writeFile = promisify(fs.writeFile);
    
    readFile('src/some-file.js')
      .then((data) => writeFile('src/some-file.js', data))
      .then(() => {
        console.log('Success!');
      })
      .cacth(console.error);
    import * as fs from 'fs';
    import { bindNodeCallback, Observable } from 'rxjs';
    import { mergeMap, switchMap } from 'rxjs/operators';
    
    const readFile = bindNodeCallback(fs.readFile);
    const writeFile = bindNodeCallback(fs.writeFile);
    
    let files: Observable<string>;
    const LIMIT = 2;
    
    files
      .pipe(
        mergeMap(
          (file) => someProcessWithFiles(file),
          LIMIT
      )
      .subscribe({
        complete() {
          console.log('Complete!');
        },
      });
    import { readFile, writeFile } from '@rxnode/fs';
    import { switchMap } from 'rxjs/operators';
    
    readFile('src/some-file.js')
      .pipe(switchMap((data) => writeFile('src/some-file.js', data)))
      .subscribe({
        complete() {
          console.log('Complete!');
        },
      });
    import { createServer } from '@rxnode/http';
    
    const server = createServer();
    
    server.subscribe(([req, res]) => {
      res.writeHead(200, { 'Content-Type': 'text/plain' });
      res.end('okay');
    });
    
    server.listen(8080).subscribe();

    Contributing

    Thank you for considering contributing to our project. Your help if very welcome!

    When contributing, it's better to first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change.

    All members of our community are expected to follow our Code of Conduct. Please make sure you are welcoming and friendly in all of our spaces.

    hashtag
    Getting started

    In order to make your contribution please make a fork of the repository. After you've pulled the code, follow these steps to kick start the development:

    1. Run npm i to install dependencies

    2. Run npm start to launch demo project where you could test your changes

    3. Use following commands to ensure code quality

    hashtag
    Pull Request Process

    1. We follow

      in our commit messages, i.e. feat(core): improve typing

    2. Update to reflect changes related to public API and everything relevant

    Make sure you cover all code changes with unit tests
  • When you are ready, create Pull Request of your fork into the original repository

  • Conventional Commitsarrow-up-right
    README.md
    npm run lint
    npm run build
    npm run test

    Contributor Covenant Code of Conduct

    hashtag
    Our Pledge

    In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.

    hashtag
    Our Standards

    Examples of behavior that contributes to creating a positive environment include:

    • Using welcoming and inclusive language

    • Being respectful of differing viewpoints and experiences

    • Gracefully accepting constructive criticism

    Examples of unacceptable behavior by participants include:

    • The use of sexualized language or imagery and unwelcome sexual attention or

      advances

    • Trolling, insulting/derogatory comments, and personal or political attacks

    • Public or private harassment

    hashtag
    Our Responsibilities

    Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

    Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

    hashtag
    Scope

    This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

    hashtag
    Enforcement

    Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project owner at katsuba.igor@gmail.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

    Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

    hashtag
    Attribution

    This Code of Conduct is adapted from the , version 1.4, available at

    For answers to common questions about this code of conduct, see

    Focusing on what is best for the community
  • Showing empathy towards other community members

  • Publishing others' private information, such as a physical or electronic

    address, without explicit permission

  • Other conduct which could reasonably be considered inappropriate in a

    professional setting

  • Contributor Covenantarrow-up-right
    https://www.contributor-covenant.org/version/1/4/code-of-conduct.htmlarrow-up-right
    https://www.contributor-covenant.org/faqarrow-up-right

    Changelog

    hashtag
    v1.0.1

    2022.09.05

    hashtag
    📝 Documentation

    • reformat docs ()

    hashtag
    v1.0.0

    2022.09.04

    hashtag
    🚀 Features

    • update rxjs to v7 ()

    hashtag
    💥 BREAKING CHANGES

    • update rxjs to v7

    #b6600e8arrow-up-right
    #4508d9carrow-up-right

    License

    MIT License

    Copyright (c) 2020 Igor Katsuba

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    Rxnode — reactive nodejs APIMediumchevron-right
    Logo

    core

    hashtag
    observablify

    function observablify<A extends Arguments, R extends Results = []>(
      fn: (...args: [...A, ErrorCallback<R>]) => any
    ): (...args: A) => Observable<VoidOrItemOrItems<R>>;

    hashtag
    watchify

    function watchify<A extends Arguments, R extends Results>(
      fn: (...args: [...A, Callback<R>]) => any,
      { closeOnUnsubscribe: closeOnUnsubscribe }?: { closeOnUnsubscribe?: boolean }
    ): (...args: A) => Observable<VoidOrItemOrItems<R>>;

    fs

    hashtag
    access

    function(path: PathLike, mode?: number): Observable<void>

    Tests a user's permissions for the file or directory specified by path. The mode argument is an optional integer that specifies the accessibility checks to be performed. Check File access constantsarrow-up-right for possible values of mode. It is possible to create a mask consisting of the bitwise OR of two or more values (e.g. fs.constants.W_OK | fs.constants.R_OK).

    The following examples check if package.json exists and if it is readable or writable.

    Do not use access() to check for the accessibility of a file before calling open(), readFile() or writeFile(). Doing so introduces a race condition since other processes may change the file's state between the two calls. Instead, user code should open/read/write the file directly and handle the error raised if it is not accessible.

    write (NOT RECOMMENDED)

    write (RECOMMENDED)

    read (NOT RECOMMENDED)

    read (RECOMMENDED)

    The "not recommended" examples above check for accessibility and then use the file; the "recommended" examples are better because they use the file directly and handle the error if any.

    In general, check for the accessibility of a file only if the file will not be used directly, for example when its accessibility is a signal from another process.

    On Windows, access-control policies (ACLs) on a directory may limit access to a file or directory. The fs.access() function, however, does not check the ACL and therefore may report that a path is accessible even if the ACL restricts the user from reading or writing to it.

    import { open } from '@rxnode/fs';
    
    open('myfile', 'wx').subscribe((fd) => writeMyData(fd));
    import { access } from '@rxnode/fs';
    
    const file = 'package.json';
    
    // Check if the file exists in the current directory.
    access(file, fs.constants.F_OK).subscribe({
      next() {
        console.log(`${file} exists`);
      },
      error(err) {
        console.log(`${file} does not exist`);
      },
    });
    
    // Check if the file is readable.
    access(file, fs.constants.R_OK).subscribe({
      next() {
        console.log(`${file} is readable`);
      },
      error(err) {
        console.log(`${file} is not readable`);
      },
    });
    
    // Check if the file is writable.
    access(file, fs.constants.W_OK).subscribe({
      next() {
        console.log(`${file} is writable`);
      },
      error(err) {
        console.log(`${file} is not writable`);
      },
    });
    
    // Check if the file exists in the current directory, and if it is writable.
    access(file, fs.constants.F_OK | fs.constants.W_OK).subscribe({
      next() {
        console.log(`${file} exists, and it is writable`);
      },
      error(err) {
        console.error(
          `${file} ${err.code === 'ENOENT' ? 'does not exist' : 'is read-only'}`
        );
      },
    });
    import { access, open } from '@rxnode/fs';
    
    access('myfile').subscribe({
      next() {
        console.error('myfile already exists');
      },
      error() {
        open('myfile', 'wx').subscribe((fd) => {
          writeMyData(fd);
        });
      },
    });
    import { access, open } from '@rxnode/fs';
    
    access('myfile').subscribe(() => {
      open('myfile', 'r').subscribe((fb) => readMyData(fd));
    });
    import { open } from '@rxnode/fs';
    
    open('myfile', 'r').subscribe((fd) => {
      readMyData(fd);
    });