line-transform-machines
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

line-transform-machines

Processes text input stream/file line by line. Takes care of I/O & Errors. Great for CLI apps.

  • LineMachine/AsyncLineMachine processes input lines by calling a (sync/async) callback on them.

  • RxjsLineMachine processes input lines by subscribing to the customized Observable.

Installation

$ npm install line-transform-machines

Example

From the input file input.txt, print lines, in uppercase, with its line number at the beginning of each line. Do it only for non-empty lines.
So that:

Hello,

world!

Becomes:

1: HELLO,
3: WORLD!

Solution 1: use simple callback

import {createLineMachine} from 'line-transform-machines';
import {stdout} from 'node:process';

const toUpperIgnoreEmptyLinesNumbered = (s: string, lineNum: number) => {
  if (s.trim().length === 0) return null; // returning null removes that line from output
  return `${lineNum}: ${s.toUpperCase()}`;

const lineMachine = createLineMachine(toUpperIgnoreEmptyLinesNumbered);

const runner = async () => {
  try {
    await lineMachine('./examples/input.txt', stdout);
  } catch (err) {
    console.error(err);
  }
};
runner();

Solution 2: use RxJS

import {createLineMachine} from 'line-transform-machines';
import {Observable, map, filter} from 'rxjs';
import {stdout} from 'node:process';

const toUpperIgnoreEmptyLinesNumbered = (
  obs: Observable<{value: string; lineNumber: number}>
): Observable<string> => {
  return obs.pipe(
    filter(x => x.value.trim().length > 0),
    map(x => `${x.lineNumber}: ${x.value.toLocaleUpperCase()}`)
  );
};

const lineMachine = createRxjsLineMachine(toUpperIgnoreEmptyLinesNumbered);

// ...the same code as in solution 1
const runner = async () => {
  try {
    await lineMachine('./examples/input.txt', stdout);
  } catch (err) {
    console.error(err);
  }
};
runner();

Error handling

import {createLineMachine} from 'line-transform-machines';

// our callback that can throw error
const normalizeNumbers = (s: string) => {
  const num = parseInt(s);
  if (isNaN(num)) throw new Error(`Not a number: ${s}`);
  return num.toString();
};
const lineMachine = createLineMachine(normalizeNumbers);

const runner = async () => {
  try {
    await lineMachine('./examples/nums.txt', './examples/normalized.txt');
  } catch (err) {
    console.error(err);
  }
};
runner();

Input (./examples/nums.txt):

45
62
 12
  6
hello
5
3

Console output:

Error: [./examples/nums.txt:5]
Not a number: hello
    at Object.normalizeNumbers ...

See that input file name & line is present in the error message automatically;)

If output is a file, it contains computed values before error has been thrown:

Output file (./examples/normalized.txt):

45
62
12
6

Package Sidebar

Install

npm i line-transform-machines

Weekly Downloads

0

Version

1.0.0

License

MIT

Unpacked Size

27.7 kB

Total Files

21

Last publish

Collaborators

  • tomaskraus