вторник, 25 октября 2016 г.

Detect a click outside of a React Component

Данный код необходим, если вы хотите обработать клик вне компонента React.
Например у вас есть компонент представляющий из себя модальное окно и вы хотите скрыть его при клике вне его границ.

class WindowComponent extends React.Component () {

    constructor (props) {
        super(props);
        this.state = {
            visible: true
        };
    }
 
    componentDidMount () {
        document.addEventListener('click', this.handleClickOutside.bind(this), true);
    }

    componentWillUnmount () {
        document.removeEventListener('click', this.handleClickOutside.bind(this), true);
    }

    handleClickOutside (event) {
        const domNode = ReactDOM.findDOMNode(this);
        if ((!domNode || !domNode.contains(event.target))) {
            this.setState({
                visible: false
            });
        }
    }
 
    render () {
        return (
            <div className={this.state.visible ? '' : 'hidden'}>Модальное окно</div>
        );
    }

}

понедельник, 24 октября 2016 г.

Как заставить работать event.stopPropagation в React, если у document есть свои события

Если требуется, чтобы клик по элементу, созданному с помощью React не доходил до уровня document, на который могут быть навешаны свои события, то для этого надо при создании данного элемента отказаться от добавления событий стандартным способом вроде
<Element onClick={this.handleClick.bind(this)} />, а вместо этого добавить слушатель события внутри функции componentDidMount () {}.

Для примера.

Document имеет свой слушатель события click:

document.addEventListener('click', function () {alert('Событие клика дошло до уровня document');});

Элемент имеет свой слушатель события click:

import React, {Component} from 'react';
import ReactDOM from 'react-dom';

class Element extends Component {
  handleClick (event) {
      event.stopPropagation();
      alert('Вы кликнули по элементу.');
  }
  render () {
      return <div onClick={this.handleClick.bind(this)}>Кликни по мне</div>;
  }
}

ReactDOM.render(<Element />, document.getElementById('root'));

Если в таком виде кликнуть по надписи "Кликни по мне", то сработает событие клика по элементу и событие клика по document, что приведет к выводу на экран двух сообщений alert.

Чтобы заблокировать распространения события необходимо добавление клика на элемент перенести в функцию componentDidMount:

class Element extends Component {
  handleClick (event) {
      event.stopPropagation();
      alert('Вы кликнули по элементу.');
  }
  componentDidMount () {
      ReactDOM.findDOMNode(this.refs.btn).addEventListener('click', this.handleClick);
  }
  render () {
      return <div ref="btn">Кликни по мне</div>;
  }
}

Теперь, если кликнуть по надписи "Кликни по мне", то сработает событие клика только по самому элементу, и событие клика по document, не сработате, что приведет к выводу на экран только одного сообщения alert.

Не забудьте удалить событие клика по элементу, если будет удалять сам компонент:

  componentWillUnmount () {
      ReactDOM.findDOMNode(this.refs.btn).removeEventListener('click', this.handleClick);
  }

Полный вариант кода примера:

import React, {Component} from 'react';
import ReactDOM from 'react-dom';

document.addEventListener('click', function () {alert('Событие клика дошло до уровня document');});

class Element extends Component {
  handleClick (event) {
      event.stopPropagation();
      alert('Вы кликнули по элементу.');
  }
  componentDidMount () {
      ReactDOM.findDOMNode(this.refs.btn).addEventListener('click', this.handleClick);
  }
  componentWillUnmount () {
      ReactDOM.findDOMNode(this.refs.btn).removeEventListener('click', this.handleClick);
  }
  render () {
      return <div ref="btn">Кликни по мне</div>;
  }
}

ReactDOM.render(<Element />, document.getElementById('root'));

четверг, 20 октября 2016 г.

Мой Webpack, TypeScript, Babel, React, Redux, ESLint, JSCS, Sass, Flow Boilerplate

Как установить файлы через Typings:
typings install dt~jquery --global --save

Структура файлов и папок:
- папка flow
- папка node
- папка source
- файл .flowconfig
- файл flow.exe
- файл index.html
- файл version.txt

Структура файлов и папок внутри flow:
- файл CSSModule.js.flow
- файл WebpackAsset.js.flow

Структура файлов и папок внутри node:
- папка node_modules
- папка typings
- файл node.exe
- файл npm.cmd
- файл typings.cmd
- файл webpack.cmd
- файл package.json
- файл .eslintrc
- файл .jscsrc
- файл .typingsrc
- файл typings.json
- файл tslint.json
- файл eslint.json
- файл stylelint.json
- файл tsconfig.json
- файл webpack.config.js
- файл build.js
- файл server.js

Структура файлов и папок внутри source:
- папка app
- папка config
- папка lib
- файл index.js

Файл /flow/CSSModule.js.flow

// @flow

declare export default { [key: string]: string }

Файл /flow/WebpackAsset.js.flow

// @flow

declare export default string

Файл /.flowconfig

[ignore]
.*/node/.*

[include]
source/index.js

[libs]

[options]
module.name_mapper.extension='css' -> '<PROJECT_ROOT>/flow/CSSModule.js.flow'
module.name_mapper.extension='scss' -> '<PROJECT_ROOT>/flow/CSSModule.js.flow'
module.name_mapper.extension='png' -> '<PROJECT_ROOT>/flow/WebpackAsset.js.flow'
module.name_mapper.extension='jpg' -> '<PROJECT_ROOT>/flow/WebpackAsset.js.flow'
module.name_mapper.extension='gif' -> '<PROJECT_ROOT>/flow/WebpackAsset.js.flow'
esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue

Файл /version.txt

1.4.0

Файл /index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <link href="build/bundle.css?v=1.0.0-1472804427607" rel="stylesheet" type="text/css" />
    <title>Мой сайт</title>
</head>
<body>
    <div id="root"></div>
    <p id="version">Мой сайт (v1.0.0)</p>
    <script src="build/bundle.js?v=1.0.0-1472804427607" type="text/javascript"></script>
</body>
</html>

Файл /node/package.json

{
      "version": "1.0.0"
    , "name": "webpack-all-in-one"
    , "description": "Webpack all in one"
    , "keywords": ["webpack", "all"]
    , "author": "John Doe"
    , "engines": {
          "node": "6.9.0"
        , "npm": "3.10.9"
      }
    , "scripts": {
          "build": "node build"
      }
    , "dependencies": {
          "bluebird": "3.4.6"
        , "jquery": "3.1.1"
        , "react": "15.3.2"
        , "react-dom": "15.3.2"
        , "react-router": "2.8.1"
        , "react-router-redux": "4.0.6"
        , "react-redux": "4.4.5"
        , "redux": "3.6.0"
        , "redux-router": "2.1.2"
        , "redux-thunk": "2.1.0"
        , "redux-logger": "2.7.0"
      }
    , "devDependencies": {
          "webpack": "1.13.2"
        , "webpack-dev-middleware": "1.8.4"
        , "webpack-hot-middleware": "2.13.0"
        , "clean-webpack-plugin": "0.1.13"
        , "extract-text-webpack-plugin": "1.0.1"
        , "express": "4.14.0"
        , "typescript": "2.0.3"
        , "ts-loader": "0.9.5"
        , "tslint": "3.15.1"
        , "tslint-react": "1.1.0"
        , "tslint-loader": "2.1.5"
        , "babel-core": "6.17.0"
        , "babel-polyfill": "6.16.0"
        , "babel-preset-es2015": "6.16.0"
        , "babel-preset-stage-0": "6.16.0"
        , "babel-preset-react": "6.16.0"
        , "babel-preset-react-hmre": "1.1.1"
        , "babel-plugin-syntax-flow": "6.13.0"
        , "babel-plugin-transform-flow-strip-types": "6.14.0"
        , "babel-plugin-tcomb": "0.3.19"
        , "babel-loader": "6.2.5"
        , "babel-eslint": "7.0.0"
        , "eslint": "3.8.1"
        , "eslint-plugin-react": "6.4.1"
        , "eslint-loader": "1.6.0"
        , "jscs": "3.0.7"
        , "jscs-loader": "0.3.0"
        , "node-sass": "3.10.1"
        , "sass-loader": "4.0.2"
        , "css-loader": "0.25.0"
        , "style-loader": "0.13.1"
        , "stylelint": "7.5.0"
        , "stylelint-loader": "6.2.0"
        , "file-loader": "0.9.0"
        , "url-loader": "0.5.7"
        , "html-loader": "0.4.4"
        , "json-loader": "0.5.4"
        , "source-map-loader": "0.1.5"
        , "tcomb": "3.2.15"
        , "tcomb-react": "0.9.3"
        , "@types/core-js": "0.9.34"
        , "@types/bluebird": "3.0.35"
        , "@types/glob": "5.0.30"
        , "@types/filesaver": "0.0.30"
        , "@types/jquery": "2.0.33"
        , "@types/history": "2.0.39"
        , "@types/react": "0.14.41"
        , "@types/react-dom": "0.14.18"
        , "@types/react-router": "2.0.38"
        , "@types/react-router-redux": "4.0.34"
        , "@types/react-redux": "4.4.32"
        , "@types/redux": "3.6.31"
        , "@types/redux-router": "1.0.33"
        , "@types/redux-thunk": "2.1.31"
        , "@types/redux-logger": "2.6.32"
        , "@types/tcomb": "1.0.27"
      }
    , "repository": {
          "type": "git"
        , "url": "http://stash.ca.sbrf.ru/scm/sirius/sirius-arm-new.git"
      }
}

Файл /node/.eslintrc

{
      "extends": "eslint:recommended"
    , "parser": "babel-eslint"
    , "env": {
          "browser": true
        , "node": true
      }
    , "plugins": [
          "react"
      ]
    , "rules": {
          "no-debugger": 0
        , "no-console": 0
        , "new-cap": 0
        , "strict": 0
        , "no-underscore-dangle": 0
        , "no-use-before-define": 0
        , "eol-last": 0
        , "quotes": [2, "single"]
        , "jsx-quotes": [1, "prefer-single"]
        , "react/jsx-no-undef": 1
        , "react/jsx-uses-react": 1
        , "react/jsx-uses-vars": 1
    }
}


Файл /node/.jscsrc

пуст


Файл /node/.typingsrc

{
    "rejectUnauthorized": false
}

Файл /node/typings.json

{
    "globalDependencies": {
        "jquery": "registry:dt/jquery#1.10.0+20160704162008",
        "react": "registry:dt/react#0.14.0+20160805125551",
        "react-dom": "registry:dt/react-dom#0.14.0+20160412154040"
    }
}


Файл /node/tslint.json

{
  "extends": ["tslint:latest", "tslint-react"],
  "rules": {
    "indent": [ true, "spaces" ],
    "quotemark": [ true, "single", "jsx-double" ],
    "no-var-requires": false,
    "ordered-imports": false,
    "no-unused-variable": [true, "react"],
    "member-ordering": false,
    "object-literal-sort-keys": false,
    "no-shadowed-variable": false,
    "no-console": false
  }
}

Файл /node/eslint.json

/*
{
      // Здесь нет правил для ECMAScript 6
      "parserOptions": { // Настройки парсера кода
          "ecmaVersion": 3 // версия проверяемого кода ECMAScript
        , "sourceType": "script" // источник кода - отдельно загружаемые файлы
        , "ecmaFeatures": { // особенности кода ECMAScript
            "impliedStrict": true // проверять, что код написан с соблюдением правил строгого режима "use strict"; ?
          }
      }
    , "env": { // Настройки окружения
          "browser": true // разрешить использование глобальных браузерных переменных?
        , "commonjs": true // разрешить использование глобальных переменных CommonJS?
        , "worker": true // разрешить использование глобальных переменных web workers?
        , "amd": true // разрешить использование глобальных переменных require() и define() ?
        , "jquery": true // разрешить использование глобальных переменных jQuery?
      }
    , "globals": { // перечень глобальных переменных, которые явно не определены, то могут использоваться в каждом файле
          "require": true
        , "define": true
        , "ActiveXObject": true
      }
    , "rules": { // Правила
        // Possible Errors - случаи возможных ошибок в коде
          "comma-dangle": [2, "never"] // наличие запятой в конце списка элементов объекта или массива
        , "no-cond-assign":  [2, "always"] // запретить присвоение значений внутри условия: if (x = 1)
        , "no-console": 2 // запретить использование console в коде
        , "no-constant-condition": 2 // запретить писать только true или false внутри устловия: if (true)
        , "no-control-regex": 2 // запретить скрытые символы внутри регулярных выражений: /\\x1f/
        , "no-debugger": 2 // запретить использование debugger; в коде
        , "no-dupe-args": 2 // запретить дублирование аргументов в функции
        , "no-dupe-keys": 2 // запретить дублирование ключей в объектах
        , "no-duplicate-case": 2 // запретить дублирование case в switch
        , "no-empty": 2 // запретить пустые блоки в коде
        , "no-empty-character-class": 2 // запретить пустые квадратные скобки в регулярных выражениях: /^abc[]/
        , "no-ex-assign": 2 // запретить присвоение занчений переменной error в блоке catch: catch (error) {error = 10;}
        , "no-extra-boolean-cast": 2 // запретить преобразование к типу Boolen посредством символов !!: if (!!foo) {}
        , "no-extra-parens": 0 // запретить писать лишние круглые скобки
        , "no-extra-semi": 2 // запретить писать лишние точки с запятыми
        , "no-func-assign": 2 // запретить переопределение уже созаднных функций
        , "no-inner-declarations": 2 // запретить опеределение функций и определений внутри условий
        , "no-invalid-regexp": 2 // проверить правильность написания регулярного выражения
        , "no-irregular-whitespace": 2 // запретить писать необычные виды пробелов
        , "no-negated-in-lhs": 2 // запретить писать условия с отрицанием вида if (!key in object)
        , "no-obj-calls": 2 // запретить вызов глобальных объектов: Math(); или JSON();
        , "no-regex-spaces": 2 // запретить писать простые пробелы внутри регулярных выражений: /foo   bar/
        , "no-sparse-arrays": 2 // запретить пропускать элементы в массивах: ["red", , "blue"]
        , "no-unexpected-multiline": 2 // запретить неожиданный переход на следующую строку
        , "no-unreachable": 2 // запретить написание кода, который никогда не будет выполнен
        , "use-isnan": 2 // запретить написание прямого сравнения с NaN: if (foo == NaN)
        , "valid-jsdoc": 2 // проверить правильность написания комментариев в формате JSDoc
        , "valid-typeof": 2 // проверить правильность написания сравнения с типом данных вида: typeof foo === "strnig"
        // Best Practices - наилучшие практики проверки кода
        , "accessor-pairs": 2 // проверить наличие get для каждого свойства объекта, для которого прописан set
        , "array-callback-return": 0 // проверить наличие return в функции, использующейся в качестве обработчика массива
        , "block-scoped-var": 2 // запретить использование переменной вне блока, в котором она была опеределена
        , "complexity": [2, 15] // цикломатическая сложность программы
        , "consistent-return": 0 // проверить, что все return возвращают значения или не возвращают ничего
        , "curly": 2 // проверить наличие фигурных скобок
        , "default-case": 2 // проверить наличие default в switch
        , "dot-location": [2, "property"] // проверить, что точка привязана к свойству, а не к объекту
        , "dot-notation": 2 // проверить, что вместо [] используется точка для получения значения свойств объекта
        , "eqeqeq": 2 // проверить, что используется только строго сравнение === и !==
        , "guard-for-in": 2 // проверить, что при перечислении свойств объекта используется проверка: if (foo.hasOwnProperty(key))
        , "no-alert": 2 // проверить, что в коде нет функции alert();, confirm();, prompt();
        , "no-caller": 2 // запретить использование в коде arguments.caller и arguments.callee
        , "no-case-declarations": 2 // запретить объявление переменных let, const, function и class внутри case и default в switch
        , "no-div-regex": 2 // проверить наличия escape для регулярного выражения вида /=foo/, которое может быть интерпретировано, как операция деления /=
        , "no-else-return": 0 // запретить написание внутри функции необязательно блока с кодом else {return x;}
        , "no-empty-function": 0 // запретить наличие в коде функций с пустым телом
        , "no-empty-pattern": 2 // запретить наличие в коде пустых паттернов деструктурирования объектов и массивов
        , "no-eq-null": 2 // запретить нестрогое сравнение с null: if (foo == null)
        , "no-eval": 2 // запретить использование функции eval
        , "no-extend-native": [2, {"exceptions": []}] // запретить расширение встроенных объектов
        , "no-extra-bind": 2 // запретить бессмысленное примение функции bind
        , "no-extra-label": 2 // запретить бессмысленное примение label
        , "no-fallthrough": 2 // запретить конструкции case без break; или return;
        , "no-floating-decimal": 2 // запретить писпть числа с плавающей точкой без нулей: .2 или 2.
        , "no-implicit-coercion": 0 // запретить преобразование типов с помощью конструкций вида: "" + foo, !!foo, +foo, ~foo
        , "no-implicit-globals": 2 // запретить объявление глобальных переменных без привязки к window
        , "no-implied-eval": 2 // запретить выполнять код через setTimeout(), setInterval() и execScript() вида: setTimeout("alert('Hi!');", 100); или execScript("alert('Hi!')");
        , "no-invalid-this": 2 // запретить неправильное использование this
        , "no-iterator": 2 // запретить изменять свойство __iterator__
        , "no-labels": 2 // запретить использование меток label
        , "no-lone-blocks": 2 // запретить использование одиночных блоков { }
        , "no-loop-func": 0 // запретить создавать функции внутри циклов
        , "no-magic-numbers": 0 // запретить использование магических чисел
        , "no-multi-spaces": 2 // запретить использование множественных пробелов в коде
        , "no-multi-str": 2 // запретить разбиение строк с помощью символа \
        , "no-native-reassign": 2 // запретить переопределение встроенных объектов: String = "hello world";
        , "no-new": 2 // запретить вызов функции конструктора объектов с new без присвоения его значения переменной: new Thing();
        , "no-new-func": 2 // запретить использование Function: var x = new Function("a", "b", "return a + b");
        , "no-new-wrappers": 2 // запретить использовать String, Number и Boolean с оператором new
        , "no-octal": 2 // запретить использовать литералы восьмиричных чисел: var num = 071;
        , "no-octal-escape": 2 // запретить использовать восьмиричные escape-последовательности: var foo = "Copyright \251";
        , "no-param-reassign": 0 // запретить измнение значений параметров функций: function foo(bar) {bar = 13;}
        , "no-process-env": 2 // запретить использование process.env: if (process.env.NODE_ENV === "development")
        , "no-proto": 2 // запретить использование __proto__: var a = obj.__proto__;
        , "no-redeclare": 2 // запретить повторное объявление переменных: var a = 3; var a = 10;
        , "no-return-assign": 2 // запретить присвоение значений в return: function doSomething() {return foo = bar + 2;}
        , "no-script-url": 2 // запретить писать JavaScript-код в url: location.href = "javascript:void(0)";
        , "no-self-assign": 2 // запретить присваивать значение переменной самой себе: foo = foo;
        , "no-self-compare": 2 // запретить сравнивать значение перемнной с самой собой: if (x === x)
        , "no-sequences": 2 // запретить писать последовательности кода через запятую: a = b += 5, a + b;
        , "no-throw-literal": 2 // запретить выбрасывать исключения с помощью литералов, не являющихся объектами типа Error: throw "error"; throw 0; throw undefined; throw null;
        , "no-unmodified-loop-condition": 2 // запретить изменение переменных, использующихся в циклах, вне этих циклов
        , "no-unused-expressions": 2 // запретить наличие в коде неиспользуемых выражений: c = a, b;
        , "no-unused-labels": 2 // запретить наличие в коде неиспользуемых меток label циклов
        , "no-useless-call": 2 // запретить бессмысленное применение call и apply: foo.call(undefined, 1, 2, 3); или foo.apply(null, [1, 2, 3]);
        , "no-useless-concat": 2 // запретить бессмысленное объединение строк: var foo = "a" + "b";
        , "no-void": 2 // запретить использование оператора void
        , "no-with": 2 // запретить использование в коде with
        , "radix": [2, "always"] // требуется писать значение второго аргумента в функции parseInt()
        , "vars-on-top": 0 // все переменные должны быть объявлены на самом верху
        , "wrap-iife": [0, "outside"] // тип обертывания в круглые скобки немедленно вызываемой функйции: var x = (function () { return {y: 1};})();
        , "yoda": 2 // запретить стиль Йоды при написании условных выражений: if ("red" === color)
        // Strict Mode - правила строгого режима: "use strict";
        , "strict": [2, "never"] // запретить использование инструкции "use strict"; в коде
        // Variables - правила создания переменных
        , "no-catch-shadow": 2 // запретить называть переменную внутри catch уже использующимся именем другой переменной
        , "no-delete-var": 2 // запретить применять delete к обычным переменным
        , "no-label-var": 2 // запретить называть метку цикла label уже использующимся именем другой переменной
        , "no-restricted-globals": [2, "event"] // запретить использование данных глобальных переменных
        , "no-shadow-restricted-names": 2 // запретить создавать переменные с именами: NaN, Infinity, undefined, eval, arguments
        , "no-undef": 2 // запретить использование необъявленных переменных, кроме тех, что перечислены в "globals"
        , "no-undef-init": 2 // запретить присваивать переменной значение undefined: var foo = undefined;
        , "no-undefined": 0 // запретить переписывать значение переменной undefined
        , "no-unused-vars": 2 // запретить наличие в коде неиспользуемых переменных и функций
        , "no-use-before-define": 0 // запретить обращение к элементу до того, как он был объявлен в коде
        // Stylistic Issues - правила оформления кода
        , "array-bracket-spacing": [2, "never"] // запретить пробелы между скобками массивов: ['foo', 'bar', 'baz']
        , "block-spacing": [2, "never"] // запретить пробелы между скобками блоков: if (foo) {bar = 0;}
        , "brace-style": [0, "1tbs", {"allowSingleLine": true}] // стиль расположения скобок в конструкциях типа if () {} else {}
        , "camelcase": 2 // имена переменных должны быть записаны в стиле camelCase
        , "comma-spacing": [2, {"before": false, "after": true}] // стиль написания пробелов до и после запятой
        , "comma-style": [2, "first"] // стиль написания запятой - ведущая запятая
        , "computed-property-spacing": [2, "never"] // стиль пробелов в свойствах
        , "consistent-this": [2, "that", "self"] // переменные, заменяющие значение this
        , "eol-last": 0 // требовать оставлять пустую строку в конце каждого файла
        , "func-names": 0 // требовать прописывать имена функциям в выражениях: Foo.prototype.bar = function bar() {};
        , "id-length": [2, {"min": 1}] // минимальное число символов в названиях переменных и функций
        , "indent": 0 // минимальный отступ от левого края: 4 пробела
        , "key-spacing": [2, {"beforeColon": false, "afterColon": true}] // пробелы в свойствах объектов
        , "keyword-spacing": 2 // пробелы перед ключевыми словами
        , "linebreak-style": [2, "windows"] // стиль перехода на следующую строку
        , "max-depth": [2, {"maximum": 5}] // максимальная вложенность блоков кода друг в друга
        , "max-len": [2, {"code": 300, "tabWidth": 4, "ignoreUrls": true, "ignoreTrailingComments": true}] // максимальная длина строки
        , "max-nested-callbacks": [2, {"maximum": 3}] // максимальное число вложенных обратных вызовов
        , "max-params": [2, {"maximum": 5}] // максимальное числов аргументов в функции
        , "max-statements": [2, 50, {"ignoreTopLevelFunctions": true}] // максимальное число предложений в функции
        , "new-cap": 0 // проверять, что названия всех функций конструкторов объектов начинаются с заглваной буквы: var friend = new Person();
        , "new-parens": 2 // проверять наличие круглых скобков при вызове функции конструктора объектов без аргументов: var person = new Person();
        , "no-array-constructor": 2 // запретить использование функции Array: new Array(0, 1, 2)
        , "no-bitwise": 2 // запретить побитовые операции: var x = y | z;
        , "no-mixed-spaces-and-tabs": 2 // запретить писать в одной строке пробелы и табы
        , "no-multiple-empty-lines": [2, {"max": 2}] // запретить множественные пустые строки
        , "no-negated-condition": 0 // запретить отрицающие сравнения:if (!a) {doSomething();} else {doSomethingElse();}
        , "no-new-object": 2 // запретить создание пустых объектов с помощью new Object();
        , "no-spaced-func": 2 // запретить пробелы перед круглыми скобками при вызовах функций: fn ()
        , "no-trailing-spaces": [2, {"skipBlankLines": true}] // запретить пробелы в конце строк
        , "no-unneeded-ternary": 2 // запретить ненужные тернарные операторы: var isYes = answer === 1 ? true : false;
        , "no-whitespace-before-property": 2 // запретить пробелы перед свойствами объекта: foo. bar. baz
        , "object-curly-spacing": [2, "never"] // запретить пробелы между фигурными скобками объектов
        , "one-var-declaration-per-line": [2, "always"] // допустимо использование только 1 var на линию кода
        , "operator-assignment": [2, "always"] // lдопустимо только присвоение значений вида: x += y;
        , "operator-linebreak": [2, "before"] // допустимы только ведущие +, -, *, / при разбиении выражения на несколько строк
        , "padded-blocks": 0 // требуется всегда делать отступы в коде внутри блоков
        , "quotes": [2, "single", "avoid-escape"] // стиль написания кавычек
        , "require-jsdoc": [0, { // требуется для функций, методов и классов писать комментарии в формате JSDoc
                                            "require": {
                                                "FunctionDeclaration": true,
                                                "MethodDefinition": true,
                                                "ClassDeclaration": true
                                            }
                                        }]
        , "semi": [2, "always"] // требуется всегда писать в коде точку с запятой
        , "semi-spacing": 2 // требуется всегда ставить пробел после точки с запятой
        , "space-before-blocks": [0, {"keywords": "always", "classes": "always"}] // требуется писать пробелы переред открывающей фигурной скобкой
        , "space-before-function-paren": [0, {"anonymous": "always", "named": "always"}] // требуется писать пробелы переред открывающей круглой скобкой
        , "space-in-parens": [2, "never"] // запретить пробелы внутри круглых скобок: var foo = (1 + 2) * 3;
        , "space-infix-ops": 2 // требуется писать пробелы вокруг инфиксных операторов: a + b
        , "space-unary-ops": 2 // ребуется писать пробелы вокруг унарных операторов: +"3";
        , "spaced-comment": [0, "always"] // требуется, чтобы первым символом в комментарии был пробел
        , "wrap-regex": 0 // требуется обертывать литералы регулярных выражений в круглые скобки: (/foo/).test("bar");
      }
    , "plugins": [
          "react"
      ]
    , "extends": ["eslint:all", "plugin:react/all"]
}
*/
{
  "extends": "eslint:recommended",
  "parser": "babel-eslint",
  "env": {
    "browser": true,
    "node": true
  },
  "plugins": [
    "react"
  ],
  "rules": {
    "no-debugger": 0,
    "no-console": 0,
    "new-cap": 0,
    "strict": 0,
    "no-underscore-dangle": 0,
    "no-use-before-define": 0,
    "eol-last": 0,
    "quotes": [2, "single"],
    "jsx-quotes": [1, "prefer-single"],
    "react/jsx-no-undef": 1,
    "react/jsx-uses-react": 1,
    "react/jsx-uses-vars": 1
  }
}

Файл /node/stylelint.json

{
  "rules": {
    "block-no-empty": null,
    "color-no-invalid-hex": true,
    "declaration-colon-space-after": "always",
    "indentation": ["tab", {
      "except": ["value"]
    }],
    "max-empty-lines": 2,
    "unit-whitelist": ["px", em", "rem", "%", "s"]
  }
}

Файл /node/tsconfig.json

{
    "compilerOptions": {
          "declaration": false // true | false (default) - генерировать файлы .d.ts с описанием кода (declare) из TypeScript-файлов - Generates a .d.ts definitions file for compiled TypeScript files
        , "emitDecoratorMetadata": false // true | false (default) - сгенерировать мета-данные для типа/параметра декораторов - Emit metadata for type/parameter decorators.
        , "experimentalDecorators": false // true | false (default) - включить экспериментальную поддержку ES7 декораторов - Enables experimental support for ES7 decorators
        , "inlineSourceMap": false // true | false (default) - сгененрировать одиночный source map файл, включающий в себя все source map всех файлов вместо того, чтобы создавать отдельные .js.map файлы - Emit a single file that includes source maps instead of emitting a separate .js.map file.
        , "inlineSources": false // true | false (default) - Объединить весь исходный TypeScript код вместе со всеми source map в единый файл. Требуется чтобы правило inlineSourceMap было установлено в true. - Emit the TypeScript source alongside the sourcemaps within a single file. Requires inlineSourceMap to be set.
        , "isolatedModules": false // true | false (default) - убедиться, что вывод безопасен для компиляции только одиночных файлов путем создания ситуаций, которые сломают одиночный файл и приведут к ошибке - Ensures that the output is safe to only emit single files by making cases that break single-file transpilation an error
//     , "mapRoot": "" // "/maps" - корневая директория, в которой дебаггеру следует искать source map файлы вместо исходного их положения, определяемого при компиляции - Specifies the location where debugger should locate map files instead of generated locations.
        , "module": "amd" // "amd" (default) | "commonjs" | "system" | "umd" | "" - в какой тип модулей (amd, commonjs, system или umd) компилировать файлы - Specify module style for code generation
        , "newLine": "CRLF" // "CRLF" | "LF" | "" (default) - какие символы перехода на следующую строку (CRLF или LF) должны быть прописаны в скомпилированных файлах - Explicitly specify newline character (CRLF or LF); if omitted, uses OS default.
        , "noEmit": false // true | false (default) - проверить код на возможность компиляции, но не компилировать итоговые файлы даже, если в коде отсутсвуют ошибки - Check, but do not emit JS, even in the absence of errors.
        , "noEmitHelpers": true // true | false (default) - не вставлять в скомпилированные файлы вспомогательные функции типа __extends - Do not generate custom helper functions like __extends in compiled output.
        , "noImplicitAny": false // true | false (default) - запретить использовать тип any - выводить предупреждения, если выражения или объявления переменных имеют тип any - Warn on expressions and declarations with an implied any type.
        , "noResolve": true // true | false (default) - не добавлять тройной слэш /// или import target для модуля в скомпилированные файлы - Do not add triple-slash references or module import targets to the compilation context.
//     , "out": "" // "" - компиляция в разные файлы, если указана пустая строка "" или компиляция в единый файл, если указан итоговый файл "./js/single.js" -  - Concatenate and emit output to a single file.
//     , "outDir": "" // "dist" - если указана пустая строка "", то записывать скомпилированные файлы рядом с TypeScript-файлом или перенести итоговые скомпилированные файлы, включая их иерархическое расположение в подпапках, в заданную директорию "dist" - Redirect output structure to the directory.
        , "preserveConstEnums": false // true | false (default) - константы перечислений будут сохранены в качестве перечислений в скомпилированных файлах - Const enums will be kept as enums in the emitted JS.
        , "removeComments": false // true (default)| false - удалять или включать исходные комментарии в итоговые скомпилированные файлы - Configures if comments should be included in the output
        , "sourceMap": false // true (default) | false - генерировать source map файлы - для Generates corresponding .map file
//     , "sourceRoot": "" // "/dev" - корневая директория, в которой дебаггеру следует искать исхдные TypeScript-файлы вместо исходного их положения - Specifies the location where debugger should locate TypeScript files instead of source locations.
        , "suppressImplicitAnyIndexErrors": false // true | false (default) - если установлено true, то TypeScript позволит получить доступ к свойствам объекта по строковому индексу, если правило noImplicitAny активно, даже если TypeScript не знает о них. Это свойство не действует до тех пор, пока правило noImplicitAny не будет установлено активным. - If set to true, TypeScript will allow access to properties of an object by string indexer when noImplicitAny is active, even if TypeScript doesn"t know about them. This setting has no effect unless noImplicitAny is active.
        , "target": "es5" // "es3" | "es5" (default) | "es6" - в какую версию ECMAScript (3, 5 или 6) компилировать файлы - Specify ECMAScript target version": "es3", "es5", or "es6"
        , "allowJs": true // true | false (default) - разрешить компиляцию чистого JavaScript-кода
        , "strictNullChecks": true // true | false (default) - разрешить строгую проверку null
        , "noImplicitUseStrict": true // true | false (default) - запретить запись 'use strict' в итоговые файлы
        , "allowUnreachableCode": false // true | false (default) - запретить выводить сообщения об ошибка при обнаружении недостижимого кода
        , "jsx": "react" // "preserve" | "react" - определить тип генерируемого кода JSX
    }
  , "files": [
          "typings/index.d.ts"
    ]
}

Файл /node/webpack.config.js

const fs = require('fs')
        , path = require('path')
        , webpack = require('webpack')
        , CleanWebpackPlugin = require('clean-webpack-plugin')
        , ExtractTextPlugin = require('extract-text-webpack-plugin');

const fs = require('fs')
        , path = require('path')
        , webpack = require('webpack')
        , CleanWebpackPlugin = require('clean-webpack-plugin')
        , ExtractTextPlugin = require('extract-text-webpack-plugin');
        
const environment = require('./config/environment');

const indexFile = path.resolve(__dirname, '../source/index.js');

const entry = environment ? [
                                              'babel-polyfill'
                                            , indexFile
                                          ]
                                        : [
                                              'webpack/hot/dev-server'
                                            , 'webpack-hot-middleware/client'
                                            , 'babel-polyfill'
                                            , indexFile
                                          ];

module.exports = {
      entry: entry
    , resolve: {
            extensions: ['', '.js', '.jsx', '.ts', '.tsx']
          , alias: {
                  resetStyle: path.resolve(__dirname, '../source/app/common/reset.scss')
                , bodyStyle: path.resolve(__dirname, '../source/app/common/body.scss')
                , rootStyle: path.resolve(__dirname, '../source/app/common/root.scss')
                , hiddenStyle: path.resolve(__dirname, '../source/app/common/hidden.scss')
                , sortIconsStyle: path.resolve(__dirname, '../source/app/common/sort-icons.scss')
                , versionStyle: path.resolve(__dirname, '../source/app/common/version.scss')
                , windowOnErrorStyle: path.resolve(__dirname, '../source/app/window-onerror/window-onerror.scss')

                , 'react': path.resolve(__dirname, 'node_modules/react/lib/React.js')
                , 'react-dom': path.resolve(__dirname, 'node_modules/react/lib/ReactDOM.js')
                , 'react-router': path.resolve(__dirname, 'node_modules/react-router/lib/index.js')
                , 'react-router-redux': path.resolve(__dirname, 'node_modules/react-router-redux/lib/index.js')
                , 'react-redux': path.resolve(__dirname, 'node_modules/react-redux/lib/index.js')
                , 'redux': path.resolve(__dirname, 'node_modules/redux/lib/index.js')
                , 'redux-thunk': path.resolve(__dirname, 'node_modules/redux-thunk/lib/index.js')
                , 'redux-logger': path.resolve(__dirname, 'node_modules/redux-logger/lib/index.js')
                , 'tcomb': path.resolve(__dirname, 'node_modules/babel-plugin-tcomb/lib/index.js')

                , getHistory: path.resolve(__dirname, '../source/app/history/get-history.js')
                , historyStyle: path.resolve(__dirname, '../source/app/history/style.scss')
                , historyView: path.resolve(__dirname, '../source/app/history/history.js')
                , historyConstants: path.resolve(__dirname, '../source/app/history-data/history-constants.js')
                , historySortAction: path.resolve(__dirname, '../source/app/history-data/history-sort-action.js')
                , historySortReducer: path.resolve(__dirname, '../source/app/history-data/history-sort-reducer.js')
                , historyGetDataAction: path.resolve(__dirname, '../source/app/history-data/history-get-data-action.js')
                , historyGetDataReducer: path.resolve(__dirname, '../source/app/history-data/history-get-data-reducer.js')
            }
      }
    , output: {
          path: path.resolve(__dirname, '../build')
        , filename: 'bundle.js'
        , publicPath: '/build/'
        , pathinfo: true
      }
    , resolveLoader: {
          root: path.join(__dirname, 'node_modules')
      }
    , module: {
           preLoaders: [
                {
                      test: /\.js$/
                    , exclude: /node_modules/
                    , loader: 'jscs-loader!eslint-loader'
                }
              , {
                      test: /\.ts?$/
                    , exclude: /node_modules/
                    , loader: 'tslint-loader'
               }
              , {
                      test: /\.(sass|scss)$/
                    , loader: 'stylelint-loader'
               }
           ]
         , loaders: [
                {
                      test: /\.tsx?$/
                    , exclude: /node_modules/
                    , loader: 'awesome-typescript-loader'
                }
              , {
                      test: /\.jsx?$/
                    , exclude: /node_modules/
                    , loader: 'babel-loader'
                    , query: {
                          presets: [
                                  path.join(__dirname, 'node_modules/babel-preset-react-hmre')
                                , path.join(__dirname, 'node_modules/babel-preset-stage-0')
                                , path.join(__dirname, 'node_modules/babel-preset-react')
                                , path.join(__dirname, 'node_modules/babel-preset-es2015')
                          ]
                        , passPerPreset: true
                        , plugins: [
                                  path.join(__dirname, 'node_modules/babel-plugin-syntax-flow')
                                , path.join(__dirname, 'node_modules/babel-plugin-tcomb')
                                , path.join(__dirname, 'node_modules/babel-plugin-transform-flow-strip-types')
                          ]
                      }
                }
              , {
                      test: /\.html/
                    , exclude: /node_modules/
                    , loader: 'html-loader'
                }
              , {
                      test: /\.scss/
                    , exclude: /node_modules/
                    , loader: ExtractTextPlugin.extract('style-loader', 'css-loader!sass-loader')
                }
              , {
                      test: /\.(jpe?g|png|gif)$/i
                    , exclude: /node_modules/
                    , loader: 'url-loader'
                    , query: {
                            limit: 10000 // 10 kb
                          , name: 'images/[hash].[ext]'
                      }
                }
              , {
                      test: /\.json$/
                    , loader: 'json-loader'
                }
          ]
       }
     , plugins: [
            new CleanWebpackPlugin(['build'], {root: path.resolve(__dirname, '../')})
          , new ExtractTextPlugin('../build/bundle.css')
          , new webpack.BannerPlugin('Build date: ' + new Date().toString())
          , new webpack.optimize.DedupePlugin()
          , new webpack.optimize.OccurenceOrderPlugin()
          , new webpack.HotModuleReplacementPlugin()
          , new webpack.NoErrorsPlugin()
          , new webpack.DefinePlugin({VERSION: JSON.stringify(fs.readFileSync(path.join(__dirname, '../version.txt'), 'utf-8')).trim()})
      ]
    , bail: true
    , debug: true
    , eslint: {
            configFile: path.join(__dirname, 'eslint.json')
          , failOnError: true
       }
     , jscs: {
            validateIndentation: 2
          , emitErrors: false
          , failOnHint: false
          , reporter: function(errors) {}
       }
     , tslint: {
            configuration: {
                rules: {
                    quotemark: [true, 'double']
                }
            }
          , failOnHint: true
       }
     , stylelint: {
            configFile: path.join(__dirname, 'stylelint.json')
          , configOverrides: {
                rules: {
                    "block-no-empty": null
                }
            }
       }
};

Файл /node/build.js

const fs = require('fs')
        , path = require('path')
        , indexFilePath = path.join(__dirname, '../index.html')
        , versionFilePath = path.join(__dirname, '../version.txt');

fs.writeFileSync(
      indexFilePath
    , fs.readFileSync(indexFilePath, 'utf-8').replace(
              /\?v=\d+\.\d+\.\d+-\d+"/g
            , `?v=${fs.readFileSync(versionFilePath, 'utf-8')}-${new Date().getTime()}"`
      ).replace(
              /v\d+\.\d+\.\d+/g
            , `v${fs.readFileSync(versionFilePath, 'utf-8')}`
      )
);

require('./server');

Файл /node/server.js

const path = require('path')
        , webpack = require('webpack')
        , webpackDevMiddleware = require('webpack-dev-middleware')
        , webpackHotMiddleware = require('webpack-hot-middleware')
        , webpackConfig = require('./webpack.config')
        , express = require('express')
        , http = require('http');

const app = express();

const webpackCompiler = webpack(webpackConfig);

app.use(webpackDevMiddleware(webpackCompiler, {noInfo: true, publicPath: webpackConfig.output.publicPath}));
app.use(webpackHotMiddleware(webpackCompiler));

app.use(express.static(path.resolve(__dirname, '../')));

app.get('/', function (request, response) {
    response.sendFile(path.resolve(__dirname, '../index.html'));
});

app.get('/path/to/options', function (request, response){
//  proxyToServer('10.80.238.27', 9081, 'http://10.80.238.27:9081/path/to/options', 'GET', response);
    response.json(generateOptions());
});

app.listen(80, '127.0.0.1', function (error) {
    if (error) {throw error;}
    console.log('Server is running at http://127.0.0.1:80');
});

function proxyToServer (host, port, path, method, response) {
    const options = {
          host: host // host to forward to
        , port: port // port to forward to
        , path: path // path to forward to
        , method: method // request method
        , headers: response.headers // headers to send
    };

    let data = '';

    const proxy = http.request(options, function (proxyResponse) {
        proxyResponse.setEncoding('utf8');
        proxyResponse.on('data', function (chunk) {
            data += chunk;
        });
        proxyResponse.on('end', function () {
            response.writeHead(200, {'Content-Type': 'application/json'});
            response.write(data);
            response.end();
        });
    });

    proxy.on('error', function (error) {
        console.log(`Problem with proxy request: ${error.message}`);
        response.writeHead(500);
        response.end();
    });

    proxy.end();
}

function randomNumber (min, max) {
    min = parseInt(min, 10);
    max = parseInt(max, 10);
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

function randomString (len) {
    const possibleChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let text = '';
    for (let i = 0; i < len; i++) {
        text += possibleChars.charAt(Math.floor(Math.random() * possibleChars.length));
    }
    return text;
}

function generateOptions () {
    const result = [
          {
              'options': ['news', 'history']
            , 'message': ''
          }
        , {
              'options': []
            , 'message': 'У вас нет доступных опций.'
          }
    ][randomNumber(0, 1)];
    // return result;
    return {
          'options': ['news', 'history']
        , 'message': ''
    };
}

среда, 19 октября 2016 г.

Typescript with React and Redux Snippets

Basic react component

import * as React from "react";

interface IComponentNameProps {};

interface IComponentNameState {};

class ComponentName extends React.Component<IComponentNameProps, IComponentNameState> {
    public render(): JSX.Element {
        return (<span>Body</span>);
    }
}
export default ComponentName;

Redux container

import * as React from "react";
import { connect } from "react-redux";

interface IComponentNameProps {};

interface IComponentNameState {};

class ComponentName extends React.Component<IComponentNameProps, IComponentNameState> {
    public render(): JSX.Element {
        return (<span>Body</span>);
    }
}

export default connect()(ComponentName);

Redux container with implemented connect

import * as React from "react";
import { connect } from "react-redux";

interface IComponentNameProps {};

interface IComponentNameState {};

class ComponentName extends React.Component<IComponentNameProps, IComponentNameState> {
    public render(): JSX.Element {
        return (<span>Body</span>);
    }
}

export default connect(
    (state) => ({
        // Map state to props
    }),
    {
        // Map dispatch to props
    })(ComponentName);

Как установить React, TypeScript и Webpack

1) Создайте папку, в которой будут храниться все файлы вашего проекта. Назовите её для примера "project".

2) В этой папке создайте:
- папку "src"
- папку "dist"
- файл "package.json"
- файл "tsconfig.json"
- файл "webpack.config.js"
- файл "index.html"

3) Внутри папки "src" создайте:
- папку "components"
- файл "index.tsx"

4) Внутри папки "components" создайте:
- файл "Hello.tsx"

5) Поместите в созданные файлы следующий код.

Код для файла package.json

{
      "version": "1.0.0"
    , "name": "react-typescript-webpack"
    , "description": "React, TypeScript and Webpack"
    , "keywords": ["react", "typescript", "webpack"]
    , "author": "John Doe"
    , "engines": {
          "node": "6.9.0"
        , "npm": "3.10.9"
      }
    , "dependencies": {
          "react": "15.3.2"
        , "react-dom": "15.3.2"
      }
    , "devDependencies": {
          "webpack": "1.13.2"
        , "typescript": "2.0.3"
        , "ts-loader": "0.9.4"
        , "source-map-loader": "0.1.5"
        , "@types/react": "0.14.41"
        , "@types/react-dom": "0.14.18"
      }
}

Код для файла tsconfig.json

{
    "compilerOptions": {
          "target": "es5"
        , "module": "commonjs"
        , "jsx": "react"
        , "sourceMap": true
        , "noImplicitAny": true
    }
}

Код для файла webpack.config.js

const path = require('path');

module.exports = {

      entry: './src/index.tsx'

    , output: {
        filename: './dist/bundle.js'
      }

    // When importing a module whose path matches one of the following, just
    // assume a corresponding global variable exists and use that instead.
    // This is important because it allows us to avoid bundling all of our
    // dependencies, which allows browsers to cache those libraries between builds.
    , externals: {
          'react': 'React'
        , 'react-dom': 'ReactDOM'
      }

    , resolve: {
          // Add '.ts' and '.tsx' as resolvable extensions.
          extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js']
        , alias: {
            Hello: path.resolve(__dirname, './src/components/Hello.tsx')
          }
      }

    , module: {
          preLoaders: [
            // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
            {test: /\.js$/, loader: 'source-map-loader'}
          ]

        , loaders: [
            // All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
            {test: /\.tsx?$/, loader: 'ts-loader'}
          ]
      }

    // Enable sourcemaps for debugging webpack's output.
    , devtool: 'source-map'

};

Код для файла index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Hello React!</title>
    </head>
    <body>
        <div id="example"></div>

        <!-- Dependencies -->
        <script src="./node_modules/react/dist/react.js"></script>
        <script src="./node_modules/react-dom/dist/react-dom.js"></script>

        <!-- Main -->
        <script src="./dist/bundle.js"></script>
    </body>
</html>

Код для файла index.tsx

import * as React from 'react';
import * as ReactDOM from 'react-dom';

import {Hello} from 'Hello';

ReactDOM.render(<Hello compiler="TypeScript" framework="React" />, document.getElementById('example'));

Код для файла Hello.tsx

import * as React from 'react';

export interface HelloProps {
    compiler: string;
    framework: string;
}

export class Hello extends React.Component<HelloProps, {}> {
    render () {
        return <h1>Hello from {this.props.compiler} and {this.props.framework}!</h1>;
    }
}

6) Откройте командную строку и перейдите в ней в папку вашего проекта "project":
cd C:\path\to\project

7) Выполните команду:
npm install

8) Выполните команду:
webpack

9) Откройте файл "index.html" в браузере, чтобы убедиться. что всё работает и увидеть надпись "Hello from TypeScript and React!".

Как запустить Node.js без инсталляции

Как запустить Node.js без инсталляции.

Если необходима портативная версия Node.js, то достаточно просто скачать файл

http://nodejs.org/dist/latest/win-x86/node.exe

и поместить его в папку с вашими серверными JavaScript-файлами.

После этого в командной строке перейдите в папку вашего проекта и запустите ваш скрипт стандартным образом:

\path\to\saved\node.exe scriptname.js

При желании вы можете прописать ссылку на файл node.exe в системную переменную PATH, чтобы запускать ваши скрипты из любого места так:

node scriptname.js

Если вам нужен NPM, то скачайте его архив ZIP по ссылке:

https://github.com/npm/npm

и распакуйте его в папку, в которую поместили файл node.exe.

Переименуйте папку с файлами NPM в "npm", убрав из названия номер версии, если он есть.

Создайте рядом с файлом node.exe папку "node_modules" и перенесите в неё папку "npm".

Скопируйте в папку с файлом node.exe файл npm.cmd из папки "node_modules/npm/bin/".

После этого NPM автоматически заработает из командной строки стандартным образом.

Для того, чтобы в этом убедиться, наберите в командной строке команду:

npm -h

Если NPM не может скачать пакеты в Node.js для версии выше 0.12, то необходимо в командной строке выполнить команду:

npm config set strict-ssl=false

После этого пакеты начнут скачиваться.

Когда вам потребуется обновить Node.js, то просто замените файл node.exe на новую версию.

А для обновления NPM удалите старую папку "npm" и распакуйте в проект архив ZIP с новой версией NPM, таким образом, как было описано выше.

Ваша стартовая структура расположения папок и файлов должна выглядеть в итоге так:

C:\path\to\your\project\server.js - ваш сценарий JavaScript
C:\path\to\your\project\node.exe - файл новой версии Node.js
C:\path\to\your\project\node_modules\npm - папка из архива ZIP с новой версией NPM
C:\path\to\your\project\npm.cmd - файл из архива ZIP с новой версией NPM

вторник, 18 октября 2016 г.

JavaScript Type.js - How to check type in runtime

Файл type.js

/*
Примеры:

type.String(1, 'Wrong value.');

var a = type.func(
      [type.Number, type.String], type.Object
    , function (a, b) {
        return {
            a: a
          , b: b
        };
    }
);

a(1, 2);

type.add('Password', function (value, message) {
    if (not (typeof value === 'string' && value.length > 6)) {
        if (message) {
            throw new Error(message);
        } else {
            throw new Error('Type of value ' + value + ' must be password, but it has type ' + Object.prototype.toString.call(value).slice(8, -1).toLowerCase() + '.');
        }
    }
});

type.Password(1, 'Wrong value.');

var point = type.obj(
      {
          x: type.Number
        , y: type.Number
      }
    , {
          x: 1
        , y: '2'
    }
);

var list = type.arr(
      [type.Number, type.String, type.Object] // или просто type.Number для всех значений
    , [1, '2', {a: 3}]
);

*/

function not (bool) {return !bool;}

var type = {};

type.add = function (name, predicate) {
    if (name in type) {throw new Error('Type ' + name + ' already defined.');}
    type[name] = predicate;
};

type.alias = function (name, typeFunction) {
    if (name in type) {throw new Error('Type ' + name + ' already defined.');}
    type[name] = typeFunction;
}

type.func = function (argumentTypesArray, returnValueType, functionBody) {
    return function () {
        for (var i = 0, len = argumentTypesArray.length; i < len; i++) {
            argumentTypesArray[i](arguments[i]);
        }
        var result = functionBody.apply(null, arguments);
        returnValueType(result);
        return result;
    };
};

type.obj = function (types, object) {
    for (var key in types) {
        if (Object.prototype.hasOwnProperty.call(types, key)) {
            if (not (Object.prototype.hasOwnProperty.call(object, key))) {
                throw new Error('Object don\'t have key ' + key + '.');
            } else {
                types[key](object[key]);
            }
        }
    }
    return object;
};

type.arr = function (types, array) {
    var typesIndex = 0
        , arrayIndex = 0
        , typesLength
        , arrayLength = array.length;
    if (Object.prototype.toString.call(types) === '[object Array]') {
        for (typesLength = types.length; typesIndex < typesLength; typesIndex++, arrayIndex++) {
            types[typesIndex](array[arrayIndex]);
        }
    } else if (typeof types === 'function') {
        for (; arrayIndex < arrayLength; arrayIndex++) {
            types(array[arrayIndex]);
        }
    }
    return array;
};

type.Any = function () {
    // can be any value
};

type.Undefined = function (value, message) {
    if (not (value === void 0)) {
        if (message) {
            throw new Error(message);
        } else {
            throw new Error('Type of value ' + value + ' must be undefined, but it has type ' + Object.prototype.toString.call(value).slice(8, -1).toLowerCase() + '.');
        }
    }
};

type.Null = function (value, message) {
    if (not (value === null)) {
        if (message) {
            throw new Error(message);
        } else {
            throw new Error('Type of value ' + value + ' must be null, but it has type ' + Object.prototype.toString.call(value).slice(8, -1).toLowerCase() + '.');
        }
    }
};

type.Nil = function (value, message) {
    if (not (value === void 0 || value === null)) {
        if (message) {
            throw new Error(message);
        } else {
            throw new Error('Type of value ' + value + ' must be undefined or null, but it has type ' + Object.prototype.toString.call(value).slice(8, -1).toLowerCase() + '.');
        }
    }
};

type.Boolean = function (value, message) {
    if (not (value === true || value === false)) {
        if (message) {
            throw new Error(message);
        } else {
            throw new Error('Type of value ' + value + ' must be boolean, but it has type ' + Object.prototype.toString.call(value).slice(8, -1).toLowerCase() + '.');
        }
    }
};

type.Number = function (value, message) {
    if (not (typeof value === 'number' && value === value && isFinite(value))) {
        if (message) {
            throw new Error(message);
        } else {
            throw new Error('Type of value ' + value + ' must be number, but it has type ' + Object.prototype.toString.call(value).slice(8, -1).toLowerCase() + '.');
        }
    }
};

type.String = function (value, message) {
    if (not (typeof value === 'string')) {
        if (message) {
            throw new Error(message);
        } else {
            throw new Error('Type of value ' + value + ' must be string, but it has type ' + Object.prototype.toString.call(value).slice(8, -1).toLowerCase() + '.');
        }
    }
};

type.Array = function (value, message) {
    if (not (Object.prototype.toString.call(value) === '[object Array]')) {
        if (message) {
            throw new Error(message);
        } else {
            throw new Error('Type of value ' + value + ' must be array, but it has type ' + Object.prototype.toString.call(value).slice(8, -1).toLowerCase() + '.');
        }
    }
};

type.Object = function (value, message) {
    if (not (Object.prototype.toString.call(value) === '[object Object]')) {
        if (message) {
            throw new Error(message);
        } else {
            throw new Error('Type of value ' + value + ' must be object, but it has type ' + Object.prototype.toString.call(value).slice(8, -1).toLowerCase() + '.');
        }
    }
};

type.Function = function (value, message) {
    if (not (typeof value === 'function')) {
        if (message) {
            throw new Error(message);
        } else {
            throw new Error('Type of value ' + value + ' must be function, but it has type ' + Object.prototype.toString.call(value).slice(8, -1).toLowerCase() + '.');
        }
    }
};

type.Date = function (value, message) {
    if (not (value instanceof Date)) {
        if (message) {
            throw new Error(message);
        } else {
            throw new Error('Type of value ' + value + ' must be date, but it has type ' + Object.prototype.toString.call(value).slice(8, -1).toLowerCase() + '.');
        }
    }
};

type.RegExp = function (value, RegExp) {
    if (not (value instanceof Date)) {
        if (message) {
            throw new Error(message);
        } else {
            throw new Error('Type of value ' + value + ' must be regular expression, but it has type ' + Object.prototype.toString.call(value).slice(8, -1).toLowerCase() + '.');
        }
    }
};

type.Error = function (value, message) {
    if (not (value instanceof Error)) {
        if (message) {
            throw new Error(message);
        } else {
            throw new Error('Type of value ' + value + ' must be error, but it has type ' + Object.prototype.toString.call(value).slice(8, -1).toLowerCase() + '.');
        }
    }
};

понедельник, 17 октября 2016 г.

Node.js Quick Docs Help

// Errors

try {
    var a = b + 1;
} catch (error) {
    console.log('Ошибка!');
}

try {
    setTimeout(function () {throw new Error('Эта ошибка не будет перехвачена');}, 1000);
} catch (error) {
    console.log('Ошибки внутри асинхронных функций не могут быть перехвачены с помощью try-catch.');
}

myObserver.on('error', function (error) {console.log('Ошибка!');});
myObserver.emit('error', new Error('Произошла ошибка'));

process.on('uncaughtException', function (error) {console.log('Ошибка!');});

// Stack trace

var error = new Error('message text');
console.log(error.message); // message text
console.log(error.stack);

var myObject = {};
Error.captureStackTrace(myObject);
myObject.stack; // подобно new Error().stack;

function MyError () {
    Error.captureStackTrace(this, MyError);
}
new MyError().stack;

console.log(Error.stackTraceLimit);

// Domain

var domain = require('domain');

var dom = domain.create();

dom.on('error', function (error) {
    console.log('error: ' + error.message);
});

function asyncFunction () {
    setTimeout(function () {throw new Error('Произошла ошибка!');}, 1000);
}

dom.add(asyncFunction);

dom.run(function () {
    setTimeout(function () {throw new Error('Произошла еще  одна ошибка!');}, 1000);
});

console.log(dom.members);

dom.remove(asyncFunction);

dom.enter();
dom.exit();

dom.dispose();

function asyncReadSomeFile (filePath, callback) {
    fs.readFile(filePath, 'utf8', dom.intrcept(function (data) {
        return callback(JSON.parse(data));
    }));
}

// Assert

var assert = require('assert');
assert.ok(1 > 2, 'Ошибка! 1 должно быть меньше 2.');
assert.deepStrictEqual({a: {b: 1}}, {a: {b: '1'}}, 'Ошибка! Объекты не равны.');

// Console

console.log('message1', 'message2', 'message3');
console.info('message %d', 4);
console.warn('Danger!', 'Danger!', 'Danger!');
console.error('Error', 5);
console.assert(1 > 2, 'Ошибка!');
console.dir({a: 1, b: 2}, {showHidden: true, depth: 3, colors: true});

console.time('100-elements');
for (var i = 0; i < 100; i++) {/* some code */}
console.endTime('100-elements');

console.trace('Show me my stack trace');

var logger = new console.Console(fs.createWriteStream('./stdout.log'), fs.createWriteStream('./stderr.log'));
logger.log('message');

// Global

global.somVar = 1;

Buffer

__dirname; console.log(__dirname); // /Users/work/
__filename; console.log(__filename); // /Users/work/example.js

console.log('message');

var lib = require('./path/to/lib.js');

exports.value = value;
module.exports = function () {};

var fileName = require.resolve('./path/to/lib.js');

console.log(require.cache);

require.extensions['.sjs'] =  require.extensions['.js'];

// Modules

// Пути для загрузи модулей
// '/' - абсолютный путь
// './' - текущая папка
// '../' - переход на папку выше

// Раширения модулей
// 'file-name'
// 'file-name.js'
// 'file-name.json'
// 'file-name.node'

var lib = require('./lib.js');
lib.square(4);

exports.circle = function () {};
exports.cube = function () {};
module.exports = function () {
    return {
       square: function () {}
    }:
};

(function (exports, require, __filename, __dirname) {
    // по факту весь код модуля обернут в эту функции и находится здесь
});

// Определение загружен ли модуль внутри другого модуля или его код выполняется отдельно

if (require.main === module) {
    console.log('standalone module');
} else {
    console.log('this module is loaded by require("./lib.js")');
}

var moduleEntryPoint = require.main.filename;

// Перечень значений, содержащихся в объект module

module = {...};
module.id = 'id';
module.filename = 'filename';
module.loaded = true; // if (module.loaded) {}
module.parent = {};
module.children = [...];
module.exports = exports = {...};

var lib = module.require('id');

// Timers

var timeout =  setTimeout(function (a, b) {}, 1000, a, b);
var interval =  setInterval(function (a, b) {}, 1000, a, b);
var immediate = setImmediate(function (a, b) {}, a, b);

clearTimeout(timeout);
clearInterval(interval);
clearImmediate(immediate);

timeout.ref();
timeout.unref();

process.nextTick(function () {});

// Util

var util = require('util');

util.inherits(constructorFunction, superConstructorFunction);

var result = util.format('string: %s, number: %d, json: %j', 'text', 123, {a: 1}); // 'string: text, number: 123, json: {"a": 1}'

util.inspect({a: 1, b: 2}, {showHidden: true, depth: null}); // '{a: 1, b: 2}'

var obj = {name: 'John'};
obj.inspect = function (depth) {return 'My name is ' + this.name;};
util.inspect(obj); // 'My name is John'

util.isString('text'); // true
util.isObject({a: 1}); // true
util.isRegExp(/abc/); // true

// OS

var os = require('os');

writeStream.write(data + os.EOL); // os.EOL - \n on POSIX, \r\n on Windows

console.log(os.userinfo({encoding: 'utf8'}));

console.log(os.arch); // arm, arm64, ia32, mips, mipsel, ppc
console.log(os.platform()); // aix, darwin, freebsd, linux, openbsd, sunos, win32
console.log(os.type()); // Linux, Darwin, Windows_NT

console.log(os.release()); // 6.1.7601

console.log(os.constants);

console.log(os.cpus());
console.log(os.cpus().length);

console.log(os.endianness()); // BE for big endian and LE for little endian

console.log(os.homedir());
console.log(os.tmpdir());
console.log(os.hostname());

console.log(os.loadavg()); // [0, 0, 0] - minutes load averages
console.log(os.uptime()); // 399711.205897

console.log(os.networkInterfaces());

console.log(os.totalmem()); // 1952432128
console.log(os.freemem()); // 196345856

// Process

if (process.mainModule) {}

process.nextTick(function () {});

console.log(process.argv); // ['C:\\work\\node.exe', 'server.js', '--start']
process.argv.forEach(function (arg) {console.log(arg);});
console.log(process.argv0);
console.log(process.execArgv); // ['--harmony']
console.log(process.execPath); // 'C:\work\node.exe

console.log(process.hrtime()); // [1159384, 69735025]

process.env.someValue = 1;
console.log(process.env);
delete process.env.someValue;

console.log(process.cwd()); // C:\work
process.chdir('/path/to/directory');

process.stdin.setEncoding();
process.stdin.on('readable', function () {
    var chunk = process.stdin.read();
    if (chunk !== null) {
        process.stdout.write('data: ' + chunk);
    }
});
process.stdin.on('end', function () {
    process.stdout.end('done');
});

console.log = function (message) {process.stdout.write('' + message + '\n');};

console.log(process.stdin);
console.log(process.stdout);
console.log(process.stderr);

process.stdin.pause();
process.stdin.resume();

process.abort();

process.on('beforeExit', function () {});
process.on('exit', function () {});
process.exit(1);
if (process.exitCode === 1) {}

process.on('message', function () {});
process.send(message, sendHandle, options, callback);

process.on('disconnect', function () {});
process.disconnect();

if (process.connected) {}

process.on('unheldedRejection', function () {});
process.on('heldedRejection', function () {});

process.on('warning', function (warning) {
    console.log(warning.name);
    console.log(warning.message);
    console.log(warning.stack);
});
process.emitWarning('Something happened', 'Custom warning');

process.on('SIGINT', function () {});
process.on('SIGHUP', function () {});
process.kill(process.pid, 'SIGHUP');

console.log(process.pid);

console.log(process.platform); // darwin, freebsd, linux, sunos, win32
console.log(process.arch); // ia32
console.log(process.release); // {name: 'node'}
console.log(process.version);
console.log(process.versions);

console.log(process.config);

console.log(process.cpuUsage(previousCpuUsageValue));
console.log(process.memoryUsage());
console.log(process.uptime());

console.log(process.title); // C:\WINDOWS\system32\cmd.exe - node.exe

process.unmask(0o022);

// Child Process

var child_process = require('child_process');

// Выполнить файл и получить результат выполнения сразу через значения stdout и stderr
child_process.execFile('node.exe', ['--version'], {encoding: 'utf8'}, function (error, stdout, stderr) {
    if (error) {
        console.log('exec file error: ' + error);
        return;
    }
    console.log('stdout: ' + stdout); // v6.2.2
    console.log('stderr: ' + stderr);
});

// Выполнить файл и получить поток его выполнения
var spawnProcessStream = child_process.spawn('dir', ['/L'], {shell: true, stdin: 'ignore'});
spawnProcessStream.stdout.on('data', function (data) {console.log('stdout: ' + data);});
spawnProcessStream.stderr.on('data', function (data) {console.log('stderr: ' + data);});
spawnProcessStream.on('close', function (code) {console.log('spawn process exited with code ' + code);});
spawnProcessStream.on('error', function (error) {console.log('Spawn process failed');});

// Выполнить команду в консоли командной строки и получить результат выполнения сразу через значения stdout и stderr
child_process.exec('file.bat', {encoding: 'utf8'}, function (error, stdout, stderr) {
    if (error) {
        console.log('exec file error: ' + error);
        return;
    }
    console.log('stdout: ' + stdout);
    console.log('stderr: ' + stderr);
});

// Выполнить код JavaScript-файла в отдельном процессе Node.js
child_process.fork('./work/server.js', ['127.0.0.1', '80'], {cwd: null, env: process.env});

// Child Process STDIN, STDOUT, STDERR

childProcess.stdin.on('data', function (data) {});
childProcess.stdio.on('data', function (data) {});
childProcess.stdout.on('data', function (data) {});
childProcess.stderr.on('data', function (data) {});

// Child Process Events

childProcess.on('disconnect', function () {});
childProcess.disconnect();

childProcess.on('close', function (code, signal) {
    console.log('child process closed with code: ' + code + ' and signal ' + signal);
});

childProcess.on('exit', function (code, signal) {
    console.log('child process exit with code: ' + code + ' and signal ' + signal);
});

childProcess.on('error', function (error) {});

childProcess.kill('SIGHUP');

childProcess.on('message', function (message, sendHandler) {
    console.log(message);
    sendHandler(); // <Handle> netSocket or netServer object or undefined
});

childProcess.send({hello: 'workd'}, require('net').createServer(), {keepOpen: true}, function (error) {
    if (error) {throw error;}
    console.log('Message sent');
});

if (process.connected) {
    process.send('message');
}

console.log(childProcess.pid);

// Cluster

var cluster = require('cluster');

var createServer = require('./server.js');

var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    var worker;
    for (var i = 0; i < numCPUs; i++) {
        worker = cluster.fork();
        worker.send('hi');
        // Навешиваем события на воркеры
        var numReqs = 0;
        Object.keys(cluster.workers).forEach(function (id) {
            cluster.workers[id].on('message', function (message) {
                if (message.cmd && message.cmd === 'notifyRequest') {
                    numReqs++;
                }
            });
        });
        cluster.on('exit', function (worker, code, signal) {
            console.log('worker ' + worker.process.pid + ' died');
            console.log('starting new worker');
            cluster.fork();
        });
        var timeout;
        Object.keys(cluster.workers).forEach(function (id) {
            var worker = cluster.workers[id];
            worker.on('listening', function (address) {
                worker.send('shutdown');
                worker.disconnect();
                timeout = setTimeout(function () {
                    worker.kill();
                }, 2000);
            });
            worker.on('disconnect', function () {
                clearTimeout(timeout);
            });
        });
    }
} else if (cluster.isWorker) {
    createServer(function (request, response) {
        response.writeHead(200);
        response.end('hello world');
        // notify master about the request
        process.send({cmd: 'notifyRequest'});
    });
    process.on('message', function (message) {
        if (message === 'shutdown') {
            // initiate graceful close of any connection to server
        }
        if (message === 'hi') {
            process.send('bye');
        }
    });
    cluster.on('exit', function (worker, code, signal) {
        if (worker.exitedAfterDisconnect === true) { // Set by calling .kill() or .disconnect(). Until then, it is undefined.
            console.log('It was voluntary - no need to worry');
        }
    });
}

// Cluster events

cluster.on('fork', function (worker) {});

cluster.on('setup', function () {});

cluster.on('online', function (worker) {console.log('worker responded after it was forked');});

cluster.on('listening', function (worker, address) {console.log('worker connected to ' + address.address + ':' + address.port);});

cluster.on('mesage'), function (worker, message, handle) {
    if (arguments.length === 2) {
        handle = message;
        message = worker;
        worker = undefined;
    }
});

cluster.on('disconnect', function (worker) {console.log('worker ' + worker.id + ' disconnected');});

cluster.on('exit', function (worker, code, signal) {
    console.log('worker ' + worker.process.pid + ' died ' + (signal || code) + '. Restaring...');
    cluster.fork();
});

// Cluster status and methods

if (cluster.isMaster) {
    // cluster code
    console.log('I am master');
    cluster.fork();
    cluster.fork();
} else if (cluster.isWorker) {
    // worker code
    console.log('I am worker ' + cluster.worker.id);
}

var worker = cluster.fork({env});

cluster.disconnect(function () {});

cluster.shedulingPolicy;

cluster.settings;

cluster.setupMaster({exec: 'worker.js', args: ['--use', 'http']});
cluster.fork(); // http worker

cluster.setupMaster({exec: 'worker.js', args: ['--use', 'https', silent: true]});
cluster.fork(); // https worker

// Worker events

var worker = cluster.fork();

worker.on('online', function () {console.log('worker is online');});

worker.on('listening', function (address) {console.log('worker is listening');});

worker.on('message', function (message) {
    if (message.cmd && message.cmd === 'notifyRequest') {
        requestNumber++;
    }
});
var requestNumber = 0;
process.send({cmd: 'notifyRequest'});

worker.on('disconnect', function () {console.log('Worker has disconnected');});
worker.disconnect();

worker.on('exit', function (code, signal) {
    if (signal) {
        console.log('worker was killed by signal: ' + signal);
    } else if (code !== 0) {
        console.log('worker exited with cocde: ' + code);
    } else {
        console.log('worker success');
    }
});

worker.on('error', function (error) {console.log('Error in worker process');});

// Worker status and methods

worker.kill('SIGTERM');
worker.send(message, sendHandle, callback);

if (worker.isDead()) {}
if (worker.isDisconnected()) {}
if (worker.exitedAfterDisconnect) {}

console.log(worker.id);
console.log(worker.process.pid);

// Пройтись по всем созданным worker

function forEachWorker (callback) {
    for (var id in cluster.workers) {
        callback(cluster.workers[id]);
    }
}

forEachWorker(function (worker) {
    worker.send('message to all workers');
});

// V8

var v8 = require('v8');

console.log(v8.getHeapStatistics());
console.log(v8.getHeapSpaceStatistics());
v8.setFlagsFromString('--trace_gc');

// VM

var vm = require('vm');

var script = new vm.Script('var a = 1; console.log(a);');
script.runInThisContext(); // 1

var sandbox = {globalVar: 1};
var script = new vm.Script('globalVar *= 2;');
script.runInNewContext(sandbox);
console.log(sandbox); // {globalVar: 2}

eval('var b = 3;');
console.log('b = ' + b); // b = 3

// REPL

var repl = require('repl');

repl.start('>>> ').context.m = 'Привет!'; // >>> 'Привет!'

// Debugger

debugger;

// Пример.

var x = 5;
setTimeout(function () {
    debugger;
    console.log('world');
}, 1000);
console.log('Hello');

// Events

var events = require('events');

class Observer extends events.EventEmitter {}

var myObserver= new Observer();

myObserver.addListener('click', function firstClick (a, b) {console.log('First event: ' + a + ', ' + b);});
myObserver.prependListener('click', function zeroClick () {console.log('Zero event');});
myObserver.on('click', secondClick); function secondClick () {console.log('Second event');}
myObserver.once('keyup', function () {console.log('First keyup event'); console.log(this);});
myObserver.prependOnceListener('keyup', function () {console.log('Zero keyup event');});

myObserver.emit('click', 1, 2); // | Zero event | First event: 1, 2 | Second event |
myObserver.emit('keyup'); // | Zero keyup event | First keyup event |

myObserver.removeListener('click', secondClick);
myObserver.removeAllListeners('keyup');

myObserver.on('error', function (error) {console.log('Произошла ошибка: ' + error);});
myObserver.emit('error', new Error('Ошибка!')); // Произошла ошибка!
process.on('uncaughtException', function (error) {console.log('Где-то произошла ошибка!');});

console.log(myObserver.eventNames()); // ['click', 'error']

console.log(myObserver.listeners('click')); // [[Function: zeroClick], [Function: firstClick]]

console.log(myObserver.listenerCount('click')); // 2

console.log(events.EventEmitter.defaultMaxListeners); // 10

myObserver.setMaxListeners(20);
console.log(myObserver.getMaxListeners()); // 20

// Stream

// Readable - читает информацию из источника
// Writable - записывает информацию
// Duplex - читает информацию из источника и записывает её далее
// Transform - преобразует информацию из источника

// Readable streams:
// http.Client.Response
// fs.createReadStream
// process.stdin
// child.process.stdout

var fs = require('fs');

var readFileStream = fs.createReadStream('input.txt', {encoding: 'utf8', hightWaterMark: 2});
var data = '';
readFileStream.on('readable', function () {
    data += readFileStream.read();
});
readFileStream.on('error', function (error) {
    console.log('Ошибка');
});

// 2 режима чтения потока:
// Flowing Mode - поток информации течет непрерывно и автоматически обрабатывается как можно скорее
// Paused Mode - информация получается с через вызов метода read()

// Flowing Mode
readStream.on('data', function (data) {});
readStream.pipe(writeStream);
readStream.resume();

// Paused Mode
readStream.removeAllListeners('data');
readStream.unpipe(writeStream);
readStream.pause();

// Events
readStream.on('readable', function () {result += readStream.read();}); // как только будет доступна следующая часть данных
readStream.on('data', function (data) {result += data;}); // как только будет автоматически прочитана часть данных
readStream.on('end', function () {console.log('чтение данных завершено');}); // как только больше не будет новых частей данных
readStream.on('close', function () {}); // как только поток для чтения будет закрыт
readStream.on('error', function (error) {}); // как только произойдет ошибка в процессе чтения данных

// Данные читаются в формате string или buffer.

// Пример.

var stream = require('stream');

class TemperatureReadableStream extends stream.Readable {
    constructor (options) {
        super(options);
        this.items = 0;
        this.maxItems = 10;
    }
    _read () {
        if (this.items++ < this.maxItems) {
            this.push({
                  date: new Date(2015, 9, this.items + 1)
                , temperature: Math.floor(Math.random() * 1000 - 273) + 'C'
            });
        } else {
            this.push(null);
        }
    }
}

var readTemperatureStream = new TemperatureReadableStream({objectMode: true});
var temperatureObject;
readTemperatureStream.on('readable', function () {
    temperatureObject = readTemperatureStream.read();
    while (temperatureObject !== null) {
        console.log(JSON.stringify(temperatureObject));
        temperatureObject = readTemperatureStream.read();
    }
});

// Дополнительный пример.

var readableStream = getReadableStreamSomehow();

readableStream.on('readable', function () {console.log('Теперь данные можно прочитать'); readableStream.read();});
readableStream.on('data', function (chunk) {console.log(chunk.length);});
readableStream.on('end', function () {console.log('Все данные успешно прочитаны.'); writableStream.end('Goodbye')});
readableStream.on('close', function () {console.log('Поток чтения данных закрыт.');});
readableStream.on('error', function (error) {console.log('Ошибка!');});

readableStream.pause();
if (readableStream.isPaused()) {
    console.log('поток чтения роставлен на паузу');
}
readableStream.resume();

readableStream.setEncoding('utf8');

readableStream.read();
readableStream.end();

readerStream.pipe(writableStream);
readerStream.unpipe(writableStream);

// Writable streams:
// http.Client.Rerquest
// fs.createWriteStream
// process.stdout
// child_process.stdin

var fs = require('fs');

var writeFileStream = fs.createWriteStream('output.txt');
for (var i = 0; i < 10; i++) {
    writeFileStream.write('chunk ' + i);
}
writeFileStream.end('Done');

// Events
writeStream.on('drain', function () {}); // как только метод write() вернул значение false, событие drain сообщает о том, что поток готов принять новые данных для записи
writeStream.on('finish', function () {}); // как только поток закончит записывать данные
writeStream.on('close', function () {}); // как только поток для записи данных будет закрыт
writeStream.on('error', function () {}); // как только произойдет ошибка в процессе записи данных
writeStream.on('pipe', function () {}); // как только поток чтения будет подключен к потоку записи данных
writeStream.on('unpipe', function () {}); // как только поток чтения будет отключен от потока записи данных

// Пример.

var stream = require('stream');

class WriteStream extends stream.Writable {
    _write (chunk, encoding, callback) {
        console.log('write: ' + chunk.toString());
        callback();
    }
}

var writeStream = new WriteStream();
for (var i = 0; i < 10; i++) {
    writeStream.write('chink ' + 1);
}
writeStream.end();

// Buffering
writeStream.cork(); // поместить все данные в буфер памяти для дозирования потока
writeStream.uncork(); // очистить данные из буфера памяти

// Пример.

var writeStream = fs.createWriteStream('output.txt');

writeStream.write('Start');

writeStream.cork();

for (var i = 0; i < 10; i++) {
    writeStream.write('chunk ' + i);
}
setTimeout(function () {

    writeStream.uncork();

    writeStream.end('Done');

}, 2000);

// Дополнительный пример.

var writableStream = getWritableStreamSomehow();

writableStream.on('drain', function writeData () {
    writableStream.write('some data', 'utf8');
});
writableStream.on('pipe', function (source) {console.log('Что-то подключилось к потоку записи данных.');});
writableStream.on('unpipe', function (source) {console.log('Что-то отключилось от потока записи данных.');});
writableStream.on('finish', function () {console.log('Все данные успешно записаны.');});
writableStream.on('close', function () {console.log('Поток записи данных закрыт.');}});
writableStream.on('error', function (error) {console.log('Ошибка!');});

writableStream.setDefaultEncoding('utf8');
writableStream.write('some data', 'utf8', function () {console.log('Writing...');});
writableStream.write('some more data', 'utf8', function () {console.log('Writing...');});
writableStream.end('done writing data', 'utf8', function () {console.log('Done');});

readerStream.pipe(writableStream);
readerStream.unpipe(writableStream);

writableStream.cork(); // поместить все данные в буфер памяти для дозирования потока
writableStream.uncork(); // очистить данные из буфера памяти

// Piping

var fs = require('fs');

var readStrem = fs.createReadStream('input.txt');
var writeStream = fs.createWriteStream('output.txt');

writeStream.on('pipe', function () {
    console.log('read stream piped to write stream');
});

readStream.pipe(writeStream);

// Duplex streams:
// tcp sockets
// zlib streams
// crypto streams

var stream = require('stream');

class DuplexStream extends stream.Duplex {
    _read (size) {...}
    _write (chunk, encoding, callback) {...}
}

// Transform streams
// Трансформирует поток чтения по заданным правилам и передает его в поток записи

var fs = require('fs');
var readStream = fs.createReadStream('input.txt');
var writeStream = fs.createWriteStream('output.txt');

var stream = require('stream');

class ToUpperCaseStream extends stream.Transform {
    _transform (chunk, encoding, callback) {
        this.push(chunk.toString().toUpperCase());
        callback();
    }
}

var toUpperCaseStream = new ToUpperCaseStream();

readStream.pipe(toUpperCaseStream).pipe(writeStream);

// _flush(callback) - вызывается как только все данные будут потреблены прямо перед событием end

// Path

var path = require('path');

           if (path.posix) {var root = path.parse('/home/user/dir/file.txt').root; // '/'
} else if (path.win32) {var root = path.parse('C:\\path\\dir\\file.txt').root; // 'C:\'
}

path.dirname('/foo/bar/baz/asdf/quux'); // return '/foo/bar/baz/asdf'

path.basename('/foo/bar/baz/asdf/quux.html'); // return 'quux.html'
path.basename('/foo/bar/baz/asdf/quux.html', 'html'); // return 'quux'

path.extname('index.coffee.md'); // return '.md'
path.extname('index.'); // return '.'
path.extname('index'); // return ''

path.delimiter; // ; for Windows and : for POSIX
process.env.PATH.split(path.delimiter); // ['C\\Windows\\system32', 'C\\Windows', 'C:\\Program Files\\node\\']

path.sep; // \ on Windows and / on POSIX
'foo/bar/baz'.split(path.sep); // return ['foo', 'bar', 'baz']

path.parse('/home/user/dir/file.txt'); // return {root: '/', dir: '/home/user/dir', base: 'file.txt', name: 'file', ext: '.txt'}

path.format({root: '/', base: 'file.txt'}); // return '/file.txt'
path.format({root: '/', name: 'file', ext: '.txt'}); // return '/file.txt'
path.format({base: 'file.txt'}); // return 'file.txt'
path.format({dir: '/home/user/dir', base: 'file.txt'}); // return '/home/user/dir/file.txt'
path.format({root: 'C:\\', dir: 'C:\\path\\dir', base: 'file.txt', name: 'file', ext: '.txt'}); // return 'C:\\path\\dir\\file.txt'

path.normalize('/foo//bar//baz//asdf/quux'); // return '/foo/bar/baz/asdf/quux'
path.normalize('C:\\temp\\\\foo\\bar'); // return 'C:\\temp\\foo\\bar''

path.join('/foo', 'bar', 'baz/asdf', 'quux'); // return '/foo/bar/baz/asdf/quux'

path.resolve('/foo/bar', './baz'); // return '/foo/bar/baz'
path.resolve('/foo/bar', '/tmp/file'); // return '/tmp/file'
path.resolve('www', 'static_files/png/', '../gif/image.gif'); // Current Working Directory is '/home/user/node' -> return '/home/user/node/www/static_files/gif/image.png'

path.relative(from, to);
path.relative('data/orandea/text/aaa', '/data/ornadea/impl/bbb'); // return '../../impl/bbb'

path.isAbsolute('C:/foo/'); // true
path.isAbsolute('/foo/bar'); // true
path.isAbsolute('quux/'); // false
path.isAbsolute('.'); // false

// File System

var fs = require('fs');

// Константы

fs.constants.F_OK - файл виден текущему процессу
fs.constants.R_OK - файл может быть прочитан
fs.constants.W_OK - файл может быть записан
fs.constants.X_OK - файл может быть выполнен

// Открытие файла для чтения

fs.open('/dir/file.txt', 'r', function (error, fileDescriptor) { // fileDescriptor - переменная, хранящая в себе ссылку на открытый файл - число
    if (error) {
        if (error.code === 'ENOENT') {
            console.log('Файл не существует');
            return;
        } else {
            throw error;
        }
    }
    readMyData(fileDescriptor);
});

// Открытие файла для записи

fs.open('/dir/file.txt', 'wx', function (error, fileDescriptor) { // fileDescriptor - переменная, хранящая в себе ссылку на открытый файл - число
    if (error) {
        if (error.code === 'EEXIST') {
            console.log('Файл уже существует');
            return;
        } else {
            throw error;
        }
    }
    writeMyData(fileDescriptor);
});

// Закрыть открытый файл

fs.close(fileDescriptor); // fileDescriptor - переменная, хранящая в себе ссылку на открытый файл - число

// Прочитать данные

fs.read(fileDescriptor, buffer, offset, length, position, function (error, bytesRead, buffer) {});

// Прочитать данные из файла

fs.readFile('path/to/file.txt', {encoding: 'utf8', flags: 'r'}, function (error, data) {
    if (error) {throw error;}
    console.log(data);
});

// Записать данные

fs.write(fileDescriptor, buffer, offset, length, position, function (error, written, buffer) {});
fs.write(fileDescriptor, 'data', postion, 'utf8', function (error, writte, string) {});

// Записать данные в файл или создать новй файл

fs.writeFile('path/to/file.txt', 'some text', {encoding: 'utf8', mode: 0o666, flag: 'w'}, function (error) {
    if (error) {throw error;}
    console.log('Данные в файл записаны');
});

// Запись данных в конец файла

fs.appendFile('/dir/file.txt', 'data to append', 'utf8', function (error) {
    if (error) {throw error;}
    console.log('Данные успешно записаны в конец файла');
});

// Обрезать файл

fs.truncate('path/to/file.txt', 10, function (error) {});

fs.ftruncate(fileDescriptor, 10, function (error) {
    if (error) {throw error;}
    console.log('Файл обрезан до 10 байт');
});

// Удаление файла

fs.unlink('/dir/file.txt', function (error) {
    if (error) {
        console.log('Файл не найден');
        return;
    }
    console.log('Файл успешно удален');
});

fs.unlinkSync('/dir/file.txt');
console.log('Файл успешно удален');

// Переименование или перемещение файла в другую директорию

fs.rename('/dir/file-1.txt', '/dir/file-2.txt', function (error) {
    if (error) {
        console.log('Невозможно переименовать файл');
        return;
    }
    console.log('Файл успешно переименован');
});

// Получение информации о файле

fs.stat('/dir/file.txt', function (error, stats) {
    if (error) {
        console.log('Файл не найден');
        return;
    }
               if (stats.isFile()) { // some code
    } else if (stats.isDirectory()) { // some code
    } else if (stats.isBlockDevice()) { // some code
    } else if (stats.isCharacterDevice()) { // some code
    } else if (stats.isSymbolicLink()) { // some code
    } else if (stats.isFIFO()) { // some code
    } else if (stats.isSocket()) { // some code
    }
    console.log('Информация о файле: ' + JSON.stringify(stats));
});

// Опеределния возможности доступа к файлу

fs.access('path/to/file.txt', fs.constants.R_OK | fs.constants.W_OK, function (error) {
    if (error) {
        console.log('К файлу не доступа');
    } else {
        console.log('Файл доступен для чтения и записи');
    }
});

// Отслеживание изменения файла

fs.watch('/dir/file.txt', {persistent: true, recursive: true, encoding: 'buffer'}, function (eventType, filename) {
    console.log('event type: ' + eventType);
    if (filename) {
        console.log(filename); // Prints: <Buffer ...>
    } else {
        console.log('filename not provided');
    }
});

fs.watchFile('/dir/file.txt', function (curr, prev) {
    console.log('current mtime: ' + curr.mtime);
    console.log('previous mtime: ' + prev.mtime);
});

var watcher = fs.watch();
watcher.on('change', function () {});
watcher.on('error', function (error) {});
watcher.close();

// Отменить отслеживание измнения файла

fs.unwatch('filename', listener);

// Изменение прав доступа к файлу

fs.chmod('path/to/file.txt', 777, function (error) {});

// Изменение владельца файла

fs.chown('path/to/file.txt', uid, gid, function (error) {});

// Прочитать ссылку на файл

fs.readlink('path/to/file.txt', {encoding: 'utf8'}, function (error, linkString) {});

// Создать ссылку на файл

fs.link('path/to/file.txt', 'path/to/dstfile.txt', function (error) {});

fs.symlink('./foo', './new-port');

// Получить реальный путь до файла

fs.realpath('path/to/file.txt', {encoding: 'utf8'}, function (error, resolvedPath) {});

// Создание директории

fs.mkdir('path/to/directory', 777, function (error) {});

// Удаление директории

fs.rmdir('path/to/directory', function (error) {});

// Создание директории для временных файлов

fs.mkdtemp('/tmp/foo', function (error, folder) {
    if (error) {throw error;}
    console.log(folder);
});

// Создание потока чтения

var readStream = fs.readStream();

readStream.on('open', function () {});
readStream.on('close', function () {});

console.log(readStream.bytesRead);
console.log(readStream.path);

// Создание потока записи

var writeStream = fs.writeStream();

writeStream.on('open', function () {});
writeStream.on('close', function () {});

console.log(writeStream.bytesWritten);
console.log(writeStream.path);

// Создание потока чтения из файла

var readFileStream = fs.createReadStream('/dir/file.txt', {flags: 'r', encoding: 'utf8', fs: null, mode: 0o666, autoClose: true, start: 90, end: 99});
var data = '';
readFileStream.on('readable', function () {
    data += readFileStream.read();
});
readFileStream.on('error', function (error) {
    console.log('Ошибка');
});

// Создание потока записи в файл

var writeFileStream = fs.createWriteStream('/dir/file.txt', {flags: 'w', defaultEncoding: 'utf8', fs: null, mode: 0o666, autoClose: true, start: 15});
for (var i = 0; i < 10; i++) {
    writeFileStream.write('chunk ' + i);
}
writeFileStream.end('Done');

// Readline - чтение по строке за раз из потока чтения

var readline = require('readline');

readline.clearLine(stream, dir);
readline.clearScreenDown(stream);

readline.cursorTo(stream, x, y);
readline.moveCursor(strean, dx, dy);

readline.emitKeypressEvents(stream, interface);
readline.emitKeypressEvents(procecss.stdin);
if (process.stdin.isTTY) {
    process.stdinsetRawMode(true);
}

var readLine = readline.createInterface({
      input: process.stdin
    , output: process.stdout
});

readLine.on('line', function (line) {
    console.log('Received: ' + line);
});

readLine.question('What do you think?', function (answer) {
    // write answer in Database
    console.log('Thank you for your feedback: ' + answer);
    readLine.close();
});

// Events

readLine.on('line', function (input) {console.log('Received: ' + input);});
readLine.on('pause', function () {console.log('Paused');});
readLine.on('resume', function () {console.log('Resumed');});
readLine.on('close', function () {});

readLine.on('SIGCONT', function () {
    readLine.prompt(); // "prompt" will automatically resume the stream
});

readLine.on('SIGINT', function () {
    readLine.question('Are you sure you want to exit?', function (answer) {
        if (answer.match(/^y(es)$/i)) {
            readLine.pause();
        }
    });
});

readLine.on('SIGTSTP', function () {
    console.log('Caught SIGTSTP');
});

// Methods

readLine.pause();
readLine.resume();
readLine.close();

readLine.question('What is your name?', function (answer) {console.log('Your name is ' + answer);});
readLine.prompt(preserveCursor);
readLine.setPrompt(prompt);

readLine.write(data, key);
readLine.write('Delete this!');
readLine.write(null, {ctrl: true, name: 'u'}); // Similar Ctrl+u to delete the line written previously

// Completer function

function completer (line) {
    var completions = '.help .error .exit .quit .q'.split(' ');
    var hits = completions.filter(function (c) {
        return c.indexOf(line) === 0;
    });
    return [hits.length ? hits : completions, line]; // show all completions if none found
}

funciton completer (linePartial, callback) {
    callback(null, [['123'], linePartial]);
}

// Пример Tiny CLI

var readline = require('readline');

var readLine = readline.createInterface({
      input: process.stdin
    , output: process.stdout
    , prompt: '>>> '
});

readLine.on('line', function (line) {
    switch (line.trim()) {
        case 'hello': console.log('world'); break;
        default: console.log('Say something.');
    }
    line.prompt();
});

readLine.on('close', function () {
    console.log('Goodbye');
    process.exit(0);
});

readLine.prompt();

// Пример чтения из потока файла линия за линией

var readline = require('readline');
var fs = require('fs');

var readLine = readline.createInterface({
    input: fs.createReadStream('./file.txt')
});

readLine.on('line', function (line) {
    console.log('Line from file: ' + line);
});

// TTY

var tty = require('tty');

if (process.stdout.isTTY) {}

// tty.ReadStream

if (readStream.isRaw) {}
readStream.setRawMode(mode);

// tty.WriteStream

process.stdout.on('resize', function () {
    console.log('screen size has changed');
    console.log(process.stdout.columns + 'x' + process.stdout.rows);
});

var columns = writeStream.columns;
var rows = writeStream.rows;

if (tty.isatty(fileDescriptor)) {}

// Buffer

console.log(buffer.INSPECT_MAX_BYTES); // 50
console.log(buffer.kMaxLength); // ~ 1GB

var buf = new Buffer([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]); // deprecated
var buf = new Buffer(new Buffer('buffer')); // deprecated
var buf = new Buffer(new Uint16Array(2), 0, 2); // deprecated
var buf = new Buffer(10); // deprecated
var buf = new Buffer('text', 'utf8'); // deprecated

var buf = new SlowBuffer(size); // deprecated

var buf = Buffer.alloc(10, 'a' , 'utf8');
var buf = Buffer.allocUnsafe(10)
var buf = Buffer.allocUnsafeSlow(10);

var str = '0123456789';
for (var index = 0; index < str.length; index++) {
    buf[index] = str.charAt(index);
}

var buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);
var buf = Buffer.from(new Buffer('buffer'));
var buf = Buffer.from(new Uint16Array(2), 0, 2);
var buf = Buffer.from('text', 'utf8');

var isBuffer = Buffer.isBuffer(new Buffer('buffer'));

var isBufferEncodingUTF8 = Buffer.isEncoding('utf8');

var bytesLength = Buffer.bytesLength('text', 'utf8');

var buf = Buffer.alloc(5);
console.log(buf.length);

var result = buf.toString('base64', start, end);
var result = buf.toJSON();

var isEqual = Buffer.compare(Buffer.form(['1234']), Buffer.form(['0123']));
var isEqual = buf1.compare(buf2, targetStart, targetEnd, sourceStart, sourceEnd);
var isEqual = buf1.equals(buf2);

buf.write('text', offest, length, 'utf8');
buf.writeInt8(2, offset, false);
buf.writeUInt8(0x3, offset, false);
buf.writeFloatBE(0xcafebabe, offset, false);
buf.writeDoubleBE(0xdeadbeefcafebabe, offset, false);

var buf = Buffer.concat([buf1, buf2, buf3], buf1.length + buf2.length + buf3.length);

buf1.copy(buf2, targetStart, sourceStart, sourceEnd);

var buf2 = buf1.slice(0, 3);

var index = buf.indexOf('abc', byteOffset, 'utf8');
var lastIndex = buf.lastIndexOf('abc', byteOffest, 'utf8');

var includes = buf.includes('abc', byteOffset, 'utf8');

var poolSize = Buffer.poolSize; // 8192

var buf = Buffer.from('buffer');
for (var pair of buf.entries()) {
    console.log(pair); // [0, 98]
}

var buf = Buffer.from('buffer');
for (var key of buf.keys()) {
    console.log(key); // 0
}

var buf = Buffer.from('buffer');
for (var value of buf.values()) {
    console.log(value); // 98
}

var buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]);
console.log(buf); // <Buffer 01 02 03 04 05 06 07 08>
buf.swap16();
console.log(buf); // <Buffer 02 01 04 03 06 05 08 07>
buf.swap16();
buf.swap32();
buf.swap64();

var result = buf.readInt8(offset, false);
var result = buf.readUInt8(offset, false);
var result = buf.readFloatBE(offset, false);
var result = buf.readDoubleBE(offset, false);

// StringDecoder

var StringDecoder = require('string_decoder').StringDecoder;

var decoder = new StringDecoder('utf8');
decoder.write(buffer);
decoder.end(buffer);

var cent = Buffer.from([0xC2, 0xA2]);
console.log(decoder.write(cent));

var euro = Buffer.from([0xE2, 0x82, 0xAC]);
console.log(decoder.write(euro));

decoder.write(Buffer.from([0xE2]));
decoder.write(Buffer.from([0x82]));
console.log(decoder.end(Buffer.from([0xAC])));

// Punycode - deprecated

var punycode = require('punycode');

console.log(punycode.version); // 1.2.0

punycode.decode('maana-pta'); // 'mahana'
punycode.decode('--dqo34k'); // ':)' - смайлик

punycode.encode('mahana.com'); // 'xn--maana-pta.com'
punycode.encode(':).com'); // 'xn----dqo34k.com'

punycode.toASCII('mahana.com'); // 'xn--maana-pta.com'
punycode.toASCII(':).com'); // 'xn----dqo34k.com'

punycode.toUnicode('xn----maana-pta.com'); // 'mahana.com'
punycode.toUnicode('xn--dqo34k.com'); // ':).com'

punycode.ucs2.decode('abc'); // [0x61, 0x62, 0x63]
punycode.ucs2.decode('\uD834\uDF06'); // [0x1D306] - сурогатная пара

punycode.ucs2.encode([0x61, 0x62, 0x63]); // 'abc'
punycode.ucs2.encode([0x1D306]); // '\uD834\uDF06' - сурогатная пара

// URL

var url = require('url');

Escapes characters: < > " ` \r \n \t {} | \ ^ '

var urlObject = url.parse('http://username:password@host.com/8080/p/a/t/h?query=string#hash', parseQueryString, slashesDenoteHost);

urlObject.href; // 'http://username:password@host.com/8080/p/a/t/h?query=string#hash'
urlObject.protocol; // 'http'
if (urlObject.slashes) {} // true если требуется, чтобы за двоеточием (:) в протоколе следовало 2 прямых слэша (//)
urlObject.auth; // 'username:password'
urlObject.host; // 'host.com:8080'
urlObject.hostname; // 'host.com'
urlObject.port; // '8080'
urlObject.path; // '/p/a/t/h?query=string'
urlObject.pathname; // '/p/a/t/h'
urlObject.search; // '?query=string'
urlObject.query; // 'query=string' или {query: 'string'}
urlObject.hash; // '#hash'

url.format(urlObject); // 'http://username:password@host.com/8080/p/a/t/h?query=string#hash'

url.resolve(from, to);
url.resolve('/one/two/three', 'four'); // 'one/two/four'
url.resolve('http://example.com', '/one'); // 'http://example.com/one'
url.resolve('http://example.com/one', '/two'); // 'http://example.com/two'

// Query String

var querystring = require('querystring');

querystring.parse('w=%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82&foo=bar', null, null, {decodeURIComponent: gbkDecodeURIComponent});
querystring.stringify({w: 'привет', foo: 'bar'}, null, null, {encodeURIComponent: gbkEncodeURIComponent});

querystring.escape('w=привет&foo=bar');
querystring.unescape('w=%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82&foo=bar');

// DNS

var dns = require('dns');

dns.lookup('google.com', {family: 4, hints: dns.ADDRCONFIG | dns.V4MAPPED, all: false}, function (error, addresses, family) {
    console.log('addresses: ' + addresses);
});

dns.lookupService('127.0.0.1', 22, function (error, hostname, service) {
    console.log(hostname, service); // localhost ssh
});

dns.resolve('google.com', 'TXT', function (error, addresses) {});

dns.resolve4('google.com', function (error, addresses) {
    if (error) {throw error;}
    console.log('addresses: ' + JSON.stringify(addresses));
    addresses.forEach(function (a) {
        dns.reverse(a, function (error, hostnames) {
            if (error) {throw error;}
            console.log('reverse for ' + a ':' + JSON.stringify(hostnames));
        });
    });
});

dns.reverse(ip, function (error, hostnames) {});

// HTTP

http.METHODS
http.STATUS_CODES

http.globalAgent

http.get('http://www.google.com/index.html', function (response) {
    console.log('Got response: ' + response.statusCode);
    response.resume();
}).on('error', function (error) {
    console.log('Got error: ' + error.message);
});

http.createClient(80, '127.0.0.1'); // deprecated

var request = http.request({
      hostname: 'www.google.com'
    , port: 80
    , path: '/'
    , method: 'POST'
    , headers: {
          'Content-Type': 'application/x-www-form-urlencoded'
        , 'Content-Length': Buffer.byteLength(querystring.stringify({msg: 'Hello World!'}))
      }
}, function (response) {
    console.log('STATUS: ' + response.statusCode);
    console.log('HEADERS: ' + JSON.stringify(response.headers));
    response.setEncoding('utf8');
    response.on('data', function (chunk) {console.log('BODY: ' + chunk);});
    response.on('end', function () {console.log('Node more data in response');});
});
request.on('error', function (error) {console.log('Problem with request: ' + error.message);});
request.write(querystring.stringify({msg: 'Hello World!'}));
request.end();

var server = http.createServer(function (request, response) {
    response.writeHead(200, 'OK');
    response.write('Hello');
    response.end('World');
});
server.listen(80);

// http.get

http.get({
      hostname: 'localhost'
    , port: 80
    , path: '/'
    , agent: false // create a new agent just for this one request
}, function (response) {
    // Do stuff with response
}).on('socket', function (socket) {
    socket.emit('agentRemove');
});

// http.Agent

var http = require('http');

var keepAliveAgent = new http.Agent({keepAlive: true});

http.request({
      hostname: 'localhost'
    , port: 80
    , path: '/'
    , agent: keepAliveAgent
}, function (request, response) {
    // Do stuff with response
});

agent.createConnection(options, function (error, stream) {});
agent.destroy();
agent.getName(options); // return host:port:localAddress
agent.freeSockets;
agent.maxFreeSockets = 256;
agent.maxSockets;
agent.requests;
agent.sockets;

// http.ClientRequest

request.on('response', function (response) {});
request.on('socket', function (socket) {});
request.on('continue', function () {});
request.on('abort', function () {});
request.on('aborted', function () {});
request.on('checkExpectation', function (request, response) {});
request.on('upgrade', function (response, socket, head) {});

// Create HTTP tunneling proxy

var http = require('http');
var net = require('net');
var url = require('url');

var proxy = http.createServer(function (request, response) {
    response.writeHead(200, {'Content-Type': 'text/plain'});
    response.end('ok');
});

proxy.on('connect', function (response, clientSocket, head) {
    // connect to origin server
    var serverUrl = url.parse('http://' + request.url);
    var serverSocket = net.connect(serverUrl.port, serverUrl.hostname, function () {
        clientSocket.write('HTTP/1.1 200 Connection Established\r\nProxy-agent: Node.js-Proxy\r\n\r\n');
        serverSocket.write(head);
        serverSocket.pipe(clientSocket);
        clientSocket.pipe(serverSocket);
    });
});

// now that proxy is running
proxy.listen(1337, '127.0.0.1', function () {
    // make request to tunneling proxy
    var request = http.request({
          hostname: '127.0.0.1'
        , port: 1337
        , path: 'www.google.com:80'
        , method: 'CONNECT'
    });
    request.end();
    request.on('connect', function (response, socket, head) {
        console.log('got connected!');
        // make request over HTTP tunnel
        socket.write('GET / HTTP/1.1\r\nHost: www.google.com:80\r\nConnection: close\r\n\r\n');
        socket.on('data', function (chunk) {console.log(chunk.toString());});
        socket.on('end', function () {proxy.close();});
    });
});

// http.createServer

var http = require('http');

var server = http.createServer(function (request, response) {
    response.writeHead(200, {'Content-Type': 'text/plain'});
    response.write('Hello');
    response.end('World');
});

server.on('upgrade', function (request, socket, head) {
    socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\n\r\n');
    socket.pipe(socket); // echo back
});

// now that server is running
server.listen(1337, '127.0.0.1', function () {
    // make request
    var request = http.request({
          hostname: '127.0.0.1'
        , port: 1337
        , headers: {
              'Connection': 'Upgarde'
            , 'Upgrade': 'websocket'
          }
    });
    request.end();
    request.on('upgrade', function (response, socket, upgradeHead) {
        console.log('got upgraded!');
        socket.end();
        process.exit(0);
    });
});

request.flushHeaders();
request.write('some text', 'utf8', function () {});
request.end('some text', 'utf8', function () {});
request.abort();
request.setNoDelay(noDelay);
request.setSocketKeepAlive(enable, initialDelay);
request.setTimeout(1500, function () {});

// http.Server

// Events

server.on('connect', function (request, socket, head) {});
server.on('connection', function (socket) {});
server.on('request', function (request, response) {});
server.on('upgrade', function (request, socket, head) {});
server.on('checkContinue', function (request, response) {});
server.on('close', function () {});
server.on('clientError', function (exception, socket) {});

var http = require('http');
var server = http.createServer(function (request, response) {response.end();});
server.on('clientError', function (error, socket) {socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');});
server.listen(8000);

// Methods

server.listen(handle, function () {});
server.listen('127.0.0.1', function () {});
server.listen(80, '127.0.0.1', backlog, function () {});
if (server.listening) {}
server.close(function () {});

server.maxHeadersCount = 1000;
server.setTimeout(1500, function () {});
server.timeout = 120000;

// http.ServerResponse

// Events

respose.on('finish', function () {});
respose.on('close', function () {});

// Methods

response.writeHead(200, 'OK', {'Content-Length': Buffer.byteLength('hello'), 'Content-Type': 'text/plain', 'Trailer': 'Content-MD5'});
response.write('some text', 'utf8', function () {});
response.writeContinue(); // send HTTP/1.1 100 Continue message to the client
response.end('some text', 'utf8', function () {});

respose.addTrailers({'Content-MD5': '7895b5573b623g62l62qw'});

response.statusCode = 404;
response.statusMessage = 'Not Found';

response.setTimeout(1500, function () {});

response.setHeader('Content-Type', 'text/html');
response.setHeader('Set-Cookie', ['type=ninjs', 'language=javasript']);

var contentType = respose.getHeader('content-type');

respose.removeHeader('Content-Encoding');

if (respose.headersSend()) {}

console.log(response.sendDate);

if (response.finished) {}

var server = http.createServer(function (request, response) {
    response.setHeader('Content-Type', 'text/html');
    response.setHeader('X-Foo', 'bar');
    response.writeHead(200, {'Content-Type': 'text/plain'});
    response.write('Hello');
    response.end('World'); // return content-type = text/plain
});

// http.IncomingMessage

// Events

message.on('aborted', function () {});
message.on('close', function () {});

// Methods

message.setTimeout(1500, function () {});
message.destroy();
message.statusCode = 404;
message.statusMessage = 'Not Found';
console.log(message.rawHeaders); // ['user-agent', 'this is invalid because there can be only one', 'User-Agent', 'curl/7.22.0', 'Host', '127.0.0.1:8000', 'ACCEPT', '*/*']
console.log(message.headers); // {'user-agent': 'curl/7.22.0', host: '127.0.0.1:8000', accept: '*/*'}
console.log(message.httpVersion);
console.log(message.url); // '/status?name=ryan'
console.log(message.method);
console.log(message.rawTrailers);
console.log(message.trailers);
console.log(message.sockets);

// HTTPS

// https.globalAgent

// https.get

var https = require('https');

https.get('https://encrypted.google.com/', function (response) {
    console.log('Status code: ' + response.statusCode);
    console.log('Header: ' + response.headers);
    response.on('data', function (data) {process.stdout.write(data);});
}).on('error', function (error) {
    console.error(error);
});

// https.request

var https = require('https');
var fs = require('fs');

var request = https.request({
      hostname: 'encrypted.google.com'
    , port: 443
    , path: '/'
    , method: 'GET'
    , key: fs.readFileSync('test/keys/agent2-key.pem')
    , cert: fs.readFileSync('test/keys/agent2-cert.pem')
    , agent: new https.Agent(options) // или false
}, function (response) {
    console.log('Status code' + response.statusCode);
    console.log('Headers: ' + response.headers);
    response.on('data', function (data) {process.stdout.write(data);});
});
request.end();
request.on('error', function (error) {console.error(error);});

// https.createServer

var https = require('https');
var fs = require('fs');

var httpsServer = https.createServer({
      key: fs.readFileSync('test/keys/agent2-key.pem')
    , cert: fs.readFileSync('test/keys/agent2-cert.pem')
// , pfx: fs.readFileSync('server.pfx')
}, function (request, response) {
    response.writeHead(200);
    response.write('Hello');
    response.end('World');
});
httpsServer.listen(8000);

// Method

httpsServer.listen(handle, function () {});
httpsServer.listen(path, function () {});
httpsServer.listen(80, '127.0.0.1', backlog function () {});

httpsServer.close();

httpsServer.setTimeout(1500, function () {});
httpsServer.timeout;

// Net

var net = require('net');

var server = net.Server();

// Events

server.on('listening', function () {});
server.on('connection', function () {});
server.on('close', function () {});
server.on('error', function () {});

// Method

var address = server.address();

var server = net.createServer(function (socket) {
    socket.end('bye');
}).on('error', function (error) {throw error;});

// grab random port
server.listen(function () {
    console.log('opened server on ' + server.address()); // don't call server.address() until the 'listening' event has been emitted
});

server.listen(handle, backlog, callback);
server.listen(options, callback);
server.listen(path, backlog, callback);
server.listen(port, hostname, backlog, callback);
server.listen({host: 'localhost', port: 80, exclusive: true});
net.createServer().listen(path.join('\\\\?\\pipe', process.cwd(), 'myctl'));

if (server.listening) {}

server.close();

console.log(server.connections); // deprecated
server.getConnections(function (error, count) {
    console.log('Connections number: ' = count);
});

console.log(server.maxConnections);

server.on('error', function (error) {
    if (error.code === 'EADDRINUSE') {
        console.log('Address in use, retrying...');
        setTimeout(function () {
            server.close();
            server.listen(PORT, HOST);
        }, 1000);
    }
});

server.ref();
server.unref();

// net.Socket

var socket = new http.Socket({
      fs: null
    , allowHalfOpen: false
    , redable: false
    , writable: false
});

// Events

socket.on('connect', function () {});
socket.on('lookup', function () {});
socket.on('drain', function () {});
socket.on('data', function () {});
socket.on('end', function () {});
socket.on('close', function () {});
socket.on('timeout', function () {});
socket.on('error', function () {});

// Methods

var address = socket.address(); // return {port: 1234, family: 'IPv4', address: '127.0.0.1'}

socket.bufferSize;
socket.bytesRead;
socket.bytesWritten;

socket.connect(options, connectListener);
socket.connect(path, connectListener);
socket.connect(port, host, connectListener);

if (socket.connectiong) {}

socket.destroy(exception);
if (socket.destroyed) {}

socket.write(data, 'utf8', function () {});
socket.end(data, 'utf8');

socket.remoteAddress(); // '74.125.127.100'
socket.remoteFamily(); // 'IPv6'
socket.remotePosrt(); // 80

socket.localAddress; // '192.168.1.1'
socket.localPort; // 80

socket.pause();
socket.resume();

socket.setEncoding('utf8');
socket.setKeepAlive(ebable, initialDelay);
socket.setNoDelay(noDelay);

socket.setTimeout(1500, function () {});

socket.ref();
socket.unref();

// connect

net.connect(options, connectListener);
net.connect(path, connectListener);
net.connect(port, host, connectListener);

var net = require('net');

var client = net.connect({port: 8124}, function () {
    // 'connect' listener
    console.log('connected to server');
    client.write('world');
});
client.on('data', function (data) {
    console.log(data.toString());
    client.end();
});
client.on('end', function () {
    console.log('desconnected from server');
});

// createConnection

net.createConnection(options, connectListener);
net.createConnection(path, connectListener);
net.createConnection(port, host, connectListener);

var net = require('net');

var client = net.createConnection({port: 8124}, function () {
    // 'connect' listener
    console.log('connected to server');
    client.write('world');
});
client.on('data', function (data) {
    console.log(data.toString());
    client.end();
});
client.on('end', function () {
    console.log('desconnected from server');
});

// createServer

net.createServer({
      allowHalfOpen: false
    , pauseOnConnect: false
}, connectionListener);

var net = require('net');

var server = net.createServer(function (connection) {
    // 'connection' listener
    console.log('client connected');
    connection.on('end', function () {
        console.log('client diconnected');
    });
    connection.write('hello');
    connection.pipe(connection);
});

server.on('error', function (error) {throw error;});
server.listen(8124, function () {console.log('server bound');});

>>> telnet localhost 8124

// net.isIPv4

if (net.isIP('input')) {}
if (net.isIPv4('input')) {}
if (net.isIPv6('input')) {}

// UDP / Datagaram Sockets

var dgram = require('dgram');

dgram.createSocket(options, function () {});
dgram.createSocket(type, function () {});

var server = dgram.createServer('udp4');

server.on('listening', function () {
    var address = server.address();
    console.log('server listening ' + address.address + ':' + address.port);
});

server.on('message', function (message, rinfo) {
    console.log('server got: ' + message + ' from ' + rinfo.address + ':' + rinfo.port);
});

server.on('error', function (error) {
    console.log('server error: ' + error.stack);
    server.close();
});

server.bind(41234); // server listening: 0.0.0.0:41234

server.bind({
      address: 'localhost'
    , port: 8000
    , exclusive: true
});

dgram.Socket

// Events

dgram.on('listening', function () {});
dgram.on('message', function (message, rinfo) {console.log('Received ' + msg.length + ' bytes from: ' + rinfo.address + ':' + rinfo.port);});
dgram.on('close', function () {});
dgram.on('error', function (error) {});

// Methods

socket.addMembership(mulitcastAdddress, multicastInterface);
socket.dropMembership(mulitcastAdddress, multicastInterface);

socket.address();

socket.bind(port, address, function () {});
socket.bind(otions, function () {});

socket.send(Buffer.from('some bytes'), offest, length, 41234, 'localhost', function (error) {socket.close();});

socket.setBroadcast(flag);
socket.setMulticastLoopback(flag);
socket.setMulticastTTL(ttl);
sockeet.setTTL(ttl);

socket.close(function () {});

socket.ref();
spcket.unref();

// Change to asynchronous socket.bind() behavior

var socket = dgram.createSocket('udp4');

socket.bind(1234);
socket.addMembership('224.0.0.114');

var socket = dgram.createSocket('udp4');

socket.bind(1234, function () {
    socket.addMembership('224.0.0.114');
});


// Transport Layer Security - TLS and Secure Socket Layer - SSL

var tls = require('tls');

// tls.Server

// Events

tlsServer.on('newSession', function (sessionId, sessionData, callback) {});
tlsServer.on('resumeSession', function (sessionId, callback) {});
tlsServer.on('secureConnection', function (tlsSocket) {});
tlsServer.on('OCSPRequest', function (certificate, issuer, callback) {});
tlsServer.on('tlsClientError', function (exception, tlsSocket) {});

var tlsSessionStore = {};
server.on('newSession', function (id, data, callback) {
    tlsSessionStore[id.toString('hex')] = data;
    callback();
});
server.on('resumeSession', function (id, callback)  {
    callback(null, tlsSessionStore[id.toString('hex')] || null);
});

// Methods

server.listen(port, hostname, callback);
var connectionsNumber = server.connections;
server.addContext(hostname, context);
server.address();
server.setTicketKeys(keys);
server.getTicketKeys();
server.close(callback);

// tls.TLSSocket

new tls.TLSSocket(socket, options);

// Events

tlsSocket.on('OCSPResponse', function (response) {});
tlsSocket.on('secureConnect', function () {});

// Methods

tlsSocket.address(); // {port: 12346, family: 'IPv4', address: '127.0.0.1'}
tlsSocket.getCipher(); // {name: 'AES256-SHA', version: 'TLSv1/SSLv3'}
tlsSocket.getEphemeralKeyInfo(); // {type: 'ECDH', name: 'prime256v1', size: 256}
tlsSocket.getPeerCertificate(detailed);
tlsSocket.getProtocol(); // SSLv3, TLSv1, TLSv1.1, TLSv1.2, unknown
tlsSocket.getSession();
tlsSocket.getTLSTicket();
tlsSocket.renegotiate(options, function () {});
tlsSocket.setMaxSendFragment(16384);

tlsSocket.localAddress; // local IP address
tlsSocket.localPort; // local port

tlsSocket.remoteAddress; // '74.125.127.100'
tlsSocket.remoteFamily; // 'IPv4' or 'IPv6'
tlsSocket.remotePort; // 443

if (tlsSocket.authorized) {}
if (tlsSocket.authorizationError) {}
if (tlsSocket.encrypted) {}

// connect

tls.connect(options, callback);
tls.connect(port, host, options, function () {});

var tls = require('tls');
var fs = require('fs');

var options = {
    // Necessary only if using the client certificate authentication
    key: fs.readFileSync('client-key.pem')
  , cert: fs.readFileSync('client-cert.pem')

    // Necessary only if the server uses the self-signed certificate
  , ca: [fs.readFileSync('server-cert.pem')]
};

var socket = tls.connect(8000, options, function () {
    console.log('client connected', socket.authorized ? 'authorized' : 'unauthorized');
    process.stdin.pipe(socket);
    process.stdin.resume();
});
socket.setEncoding('utf8');
socket.on('data', function(data) {console.log(data);});
socket.on('end', function () {server.close();});

var tls = require('tls');
var fs = require('fs');

var options = {
    pfx: fs.readFileSync('client.pfx')
};

var socket = tls.connect(8000, options, function () {
    console.log('client connected', socket.authorized ? 'authorized' : 'unauthorized');
    process.stdin.pipe(socket);
    process.stdin.resume();
});
socket.setEncoding('utf8');
socket.on('data', function (data) {console.log(data);});
socket.on('end', function () {server.close();});

// createServer

tls.createSecureContext(options);
tls.createServer(options, secureConnectionListener);

var tls = require('tls');
var fs = require('fs');

var options = {
      key: fs.readFileSync('server-key.pem')
    , cert: fs.readFileSync('server-cert.pem')

      // This is necessary only if using the client certificate authentication.
    , requestCert: true

      // This is necessary only if the client uses the self-signed certificate.
    , ca: [ fs.readFileSync('client-cert.pem') ]
};

var server = tls.createServer(options, function (socket) {
    console.log('server connected', socket.authorized ? 'authorized' : 'unauthorized');
    socket.write('welcome!\n');
    socket.setEncoding('utf8');
    socket.pipe(socket);
});
server.listen(8000, function () {console.log('server bound');});

var tls = require('tls');
var fs = require('fs');

var options = {
      pfx: fs.readFileSync('server.pfx')

      // This is necessary only if using the client certificate authentication.
    , requestCert: true
};

var server = tls.createServer(options, function (socket) {
    console.log('server connected', socket.authorized ? 'authorized' : 'unauthorized');
    socket.write('welcome!\n');
    socket.setEncoding('utf8');
    socket.pipe(socket);
});
server.listen(8000, function () {console.log('server bound');});

openssl s_client -connect 127.0.0.1:8000

// getCiphers

tls.getCiphers();
console.log(tls.getCiphers()); // ['AES128-SHA', 'AES256-SHA', ...]

// Deprecated APIs

// CryptoStream
cryptoStream.bytesWritten

// SecurePair

// Events
securePair.on('secure', function () {});

// Methods

tls.createSecurePair(context, isServer, requestCert, rejectUnauthorized, options);

pair = tls.createSecurePair(...);
pair.encrypted.pipe(socket);
socket.pipe(pair.encrypted);

secure_socket = tls.TLSSocket(socket, options);

// Crypto

// Determining if crypto support is unavailable

var crypto;

try {
    crypto = require('crypto');
} catch (error) {
    console.log('crypto support is disabled!');
}

if (crypto) {
    var secret = 'abcdefg';
    var hash = crypto.createHmac('sha256', secret)
                               .update('I love cupcakes')
                               .digest('hex');
    console.log(hash); // Prints: c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658e
}

// Certificate

var crypto = require('crypto');
var cert1 = new crypto.Certificate();
var cert2 = crypto.Certificate();

var cert = require('crypto').Certificate();
var spkac = getSpkacSomehow();
var challenge = cert.exportChallenge(spkac);
console.log(challenge.toString('utf8')); // Prints the challenge as a UTF8 string

var cert = require('crypto').Certificate();
var spkac = getSpkacSomehow();
var publicKey = cert.exportPublicKey(spkac);
console.log(publicKey); // Prints the public key as <Buffer ...>

var cert = require('crypto').Certificate();
var spkac = getSpkacSomehow();
console.log(cert.verifySpkac(Buffer.from(spkac))); // Prints true or false

// Cipher

var crypto = require('crypto');
var cipher = crypto.createCipher('aes192', 'a password');

var encrypted = '';
cipher.on('readable', function () {
    var data = cipher.read();
    if (data) {
        encrypted += data.toString('hex');
    }
});
cipher.on('end', function () {
    console.log(encrypted); // Prints: ca981be48e90867604588e75d04feabb63cc007a8f8ad89b10616ed84d815504
});

cipher.write('some clear text data');
cipher.end();


var crypto = require('crypto');
var fs = require('fs');
var cipher = crypto.createCipher('aes192', 'a password');

var input = fs.createReadStream('test.js');
var output = fs.createWriteStream('test.enc');

input.pipe(cipher).pipe(output);


var crypto = require('crypto');
var cipher = crypto.createCipher('aes192', 'a password');

var encrypted = cipher.update('some clear text data', 'utf8', 'hex');
encrypted += cipher.final('hex');
console.log(encrypted); // Prints: ca981be48e90867604588e75d04feabb63cc007a8f8ad89b10616ed84d815504

cipher.final('base64');
cipher.setAAD(buffer);
cipher.getAuthTag();
cipher.setAutoPadding(false);
cipher.update('some text', 'ascii', 'utf8');

// Decipher

var crypto = require('crypto');
var decipher = crypto.createDecipher('aes192', 'a password');

var decrypted = '';
decipher.on('readable', function () {
    var data = decipher.read();
    if (data) {decrypted += data.toString('utf8');}
});
decipher.on('end', function () {
    console.log(decrypted); // Prints: some clear text data
});

var encrypted = 'ca981be48e90867604588e75d04feabb63cc007a8f8ad89b10616ed84d815504';
decipher.write(encrypted, 'hex');
decipher.end();


var crypto = require('crypto');
var fs = require('fs');
var decipher = crypto.createDecipher('aes192', 'a password');

var input = fs.createReadStream('test.enc');
var output = fs.createWriteStream('test.js');

input.pipe(decipher).pipe(output);


var crypto = require('crypto');
var decipher = crypto.createDecipher('aes192', 'a password');

var encrypted = 'ca981be48e90867604588e75d04feabb63cc007a8f8ad89b10616ed84d815504';
var decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted); // Prints: some clear text data

decipher.final('base64');
decipher.setAAD(buffer);
decipher.setAuthTag(buffer);
decipher.setAutoPadding(false);
decipher.update('some text', 'base64', 'utf8');

// DiffieHellman

var crypto = require('crypto');
var assert = require('assert');

// Generate Alice's keys...
var alice = crypto.createDiffieHellman(2048);
var alice_key = alice.generateKeys();

// Generate Bob's keys...
var bob = crypto.createDiffieHellman(alice.getPrime(), alice.getGenerator());
var bob_key = bob.generateKeys();

// Exchange and generate the secret...
var alice_secret = alice.computeSecret(bob_key);
var bob_secret = bob.computeSecret(alice_key);

assert.equal(alice_secret.toString('hex'), bob_secret.toString('hex')); // OK

diffieHellman.computeSecret(other_public_key, 'hex', 'base64');
diffieHellman.generateKeys('base64');
diffieHellman.getGenerator('base64');
diffieHellman.getPrime('base64');
diffieHellman.getPrivateKey('base64');
diffieHellman.getPublicKey('base64');
diffieHellman.setPrivateKey('some key', 'base64');
diffieHellman.setPublicKey('some key', 'base64');
diffieHellman.verifyError = DH_CHECK_P_NOT_SAFE_PRIME';

// ECDH

var crypto = require('crypto');
var assert = require('assert');

// Generate Alice's keys...
var alice = crypto.createECDH('secp521r1');
var alice_key = alice.generateKeys();

// Generate Bob's keys...
var bob = crypto.createECDH('secp521r1');
var bob_key = bob.generateKeys();

// Exchange and generate the secret...
var alice_secret = alice.computeSecret(bob_key);
var bob_secret = bob.computeSecret(alice_key);

assert(alice_secret, bob_secret); // OK

ecdh.computeSecret(other_public_key, 'hex', 'base64');
ecdh.generateKeys('base64', 'compressed');
ecdh.getPrivateKey('base64');
ecdh.getPublicKey('base64', 'compressed');
ecdh.setPrivateKey('some key', 'base64');

ecdh.setPublicKey('some key', 'base64'); // deprecated

var crypto = require('crypto');
var alice = crypto.createECDH('secp256k1');
var bob = crypto.createECDH('secp256k1');

// Note: This is a shortcut way to specify one of Alice's previous private
// keys. It would be unwise to use such a predictable private key in a real
// application.
alice.setPrivateKey(
    crypto.createHash('sha256').update('alice', 'utf8').digest()
);

// Bob uses a newly generated cryptographically strong
// pseudorandom key pair bob.generateKeys();

var alice_secret = alice.computeSecret(bob.getPublicKey(), null, 'hex');
var bob_secret = bob.computeSecret(alice.getPublicKey(), null, 'hex');

// alice_secret and bob_secret should be the same shared secret value
console.log(alice_secret === bob_secret);

// Hash

var crypto = require('crypto');
var hash = crypto.createHash('sha256');

hash.on('readable', function () {
    var data = hash.read();
    if (data) {
        console.log(data.toString('hex')); // Prints:  6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50
    }
});

hash.write('some data to hash');
hash.end();

var crypto = require('crypto');
var fs = require('fs');
var hash = crypto.createHash('sha256');

var input = fs.createReadStream('test.js');
input.pipe(hash).pipe(process.stdout);


var crypto = require('crypto');
var hash = crypto.createHash('sha256');

hash.update('some data to hash');
console.log(hash.digest('hex')); // Prints: 6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50

hash.digest('base64');
hash.update('some text', 'utf8');

// Hmac

var crypto = require('crypto');
var hmac = crypto.createHmac('sha256', 'a secret');

hmac.on('readable', function () {
    var data = hmac.read();
    if (data) {
        console.log(data.toString('hex')); // Prints: 7fd04df92f636fd450bc841c9418e5825c17f33ad9c87c518115a45971f7f77e
    }
});

hmac.write('some data to hash');
hmac.end();


var crypto = require('crypto');
var fs = require('fs');
var hmac = crypto.createHmac('sha256', 'a secret');

var input = fs.createReadStream('test.js');
input.pipe(hmac).pipe(process.stdout);


var crypto = require('crypto');
var hmac = crypto.createHmac('sha256', 'a secret');

hmac.update('some data to hash');
console.log(hmac.digest('hex')); // Prints: 7fd04df92f636fd450bc841c9418e5825c17f33ad9c87c518115a45971f7f77e

hmac.digest('base64');
hmac.update('some text', 'utf8');

// Sign

var crypto = require('crypto');
var sign = crypto.createSign('RSA-SHA256');

sign.write('some data to sign');
sign.end();

var private_key = getPrivateKeySomehow();
console.log(sign.sign(private_key, 'hex')); // Prints the calculated signature


var crypto = require('crypto');
var sign = crypto.createSign('RSA-SHA256');

sign.update('some data to sign');

var private_key = getPrivateKeySomehow();
console.log(sign.sign(private_key, 'hex')); // Prints the calculated signature


var crypto = require('crypto');
var sign = crypto.createSign('sha256');

sign.update('some data to sign');

var private_key = '-----BEGIN EC PRIVATE KEY-----\n' +
        'MHcCAQEEIF+jnWY1D5kbVYDNvxxo/Y+ku2uJPDwS0r/VuPZQrjjVoAoGCCqGSM49\n' +
        'AwEHoUQDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNhB8i3mXyIMq704m2m52FdfKZ2\n' +
        'pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' +
        '-----END EC PRIVATE KEY-----\n';

console.log(sign.sign(private_key).toString('hex'));


sign.sign('some key', 'base64');
sign.update('some text', 'utf8');

// Verify

var crypto = require('crypto');
var verify = crypto.createVerify('RSA-SHA256');

verify.write('some data to sign');
verify.end();

var public_key = getPublicKeySomehow();
var signature = getSignatureToVerify();
console.log(verify.verify(public_key, signature)); // Prints true or false


var crypto = require('crypto');
var verify = crypto.createVerify('RSA-SHA256');

verify.update('some data to sign');

var public_key = getPublicKeySomehow();
var signature = getSignatureToVerify();
console.log(verify.verify(public_key, signature)); // Prints true or false


verifier.update('some text', 'utf8');
verifier.verify({object}, 'hex', signature_format);


// Crypto module methods and properties

let constants = crypto.constants;
crypto.constants.ENGINE_METHOD_RSA
crypto.constants.ENGINE_METHOD_DSA
crypto.constants.ENGINE_METHOD_DH
crypto.constants.ENGINE_METHOD_RAND
crypto.constants.ENGINE_METHOD_ECDH
crypto.constants.ENGINE_METHOD_ECDSA
crypto.constants.ENGINE_METHOD_CIPHERS
crypto.constants.ENGINE_METHOD_DIGESTS
crypto.constants.ENGINE_METHOD_STORE
crypto.constants.ENGINE_METHOD_PKEY_METHS
crypto.constants.ENGINE_METHOD_PKEY_ASN1_METHS
crypto.constants.ENGINE_METHOD_ALL
crypto.constants.ENGINE_METHOD_NONE

let encoding = crypto.DEFAULT_ENCODING;

if (crypto.fips) {}

crypto.createCipher(algorithm, password);
crypto.createCipheriv(algorithm, key, iv);
crypto.createCredentials(details); // deprecated
crypto.createDecipher(algorithm, password);
crypto.createDecipheriv(algorithm, key, iv);
crypto.createDiffieHellman(prime, prime_encoding, generator, generator_encoding);
crypto.createDiffieHellman(prime_length, generator);
crypto.createECDH(curve_name);


crypto.createHash(algorithm);

onst filename = process.argv[2];
var crypto = require('crypto');
var fs = require('fs');

var hash = crypto.createHash('sha256');

var input = fs.createReadStream(filename);
input.on('readable', function () {
    var data = input.read();
    if (data) {
        hash.update(data);
    } else {
        console.log(`${hash.digest('hex')} ${filename}`);
    }
});


crypto.createHmac(algorithm, key);

var filename = process.argv[2];
var crypto = require('crypto');
var fs = require('fs');

var hmac = crypto.createHmac('sha256', 'a secret');

var input = fs.createReadStream(filename);
input.on('readable', function () {
  var data = input.read();
  if (data)
    hmac.update(data);
  else {
    console.log(`${hmac.digest('hex')} ${filename}`);
  }
});


crypto.createSign(algorithm);
crypto.createVerify(algorithm);


crypto.getCiphers();

var ciphers = crypto.getCiphers();
console.log(ciphers); // ['aes-128-cbc', 'aes-128-ccm', ...]


crypto.getCurves();

var curves = crypto.getCurves();
console.log(curves); // ['secp256k1', 'secp384r1', ...]


crypto.getDiffieHellman(group_name);

var crypto = require('crypto');
var alice = crypto.getDiffieHellman('modp14');
var bob = crypto.getDiffieHellman('modp14');

alice.generateKeys();
bob.generateKeys();

var alice_secret = alice.computeSecret(bob.getPublicKey(), null, 'hex');
var bob_secret = bob.computeSecret(alice.getPublicKey(), null, 'hex');

/* alice_secret and bob_secret should be the same */
console.log(alice_secret == bob_secret);


crypto.getHashes();

var hashes = crypto.getHashes();
console.log(hashes); // ['sha', 'sha1', 'sha1WithRSAEncryption', ...]


crypto.pbkdf2(password, salt, iterations, keylen, digest, callback);

var crypto = require('crypto');
crypto.pbkdf2('secret', 'salt', 100000, 512, 'sha512', (err, key) => {
  if (err) throw err;
  console.log(key.toString('hex'));  // 'c5e478d...1469e50'
});


crypto.pbkdf2Sync(password, salt, iterations, keylen, digest);

var crypto = require('crypto');
var key = crypto.pbkdf2Sync('secret', 'salt', 100000, 512, 'sha512');
console.log(key.toString('hex'));  // 'c5e478d...1469e50'


crypto.privateDecrypt(private_key, buffer);
crypto.timingSafeEqual(a, b);
crypto.privateEncrypt(private_key, buffer);
crypto.publicDecrypt(public_key, buffer);
crypto.publicEncrypt(public_key, buffer);


crypto.randomBytes(size, callback);

// Asynchronous
var crypto = require('crypto');
crypto.randomBytes(256, (err, buf) => {
  if (err) throw err;
  console.log(`${buf.length} bytes of random data: ${buf.toString('hex')}`);
});

// Synchronous
var buf = crypto.randomBytes(256);
console.log(`${buf.length} bytes of random data: ${buf.toString('hex')}`);

crypto.setEngine(engine, flags);

// Zlib

var zlib = require('zlib');

var gzip = zlib.createGzip();
var fs = require('fs');
var inp = fs.createReadStream('input.txt');
var out = fs.createWriteStream('input.txt.gz');

inp.pipe(gzip).pipe(out);

var input = '.................................';
zlib.deflate(input, (err, buffer) => {
  if (!err) {
    console.log(buffer.toString('base64'));
  } else {
    // handle error
  }
});

var buffer = Buffer.from('eJzT0yMAAGTvBe8=', 'base64');
zlib.unzip(buffer, (err, buffer) => {
  if (!err) {
    console.log(buffer.toString());
  } else {
    // handle error
  }
});

// Compressing HTTP requests and responses

// client request example
var zlib = require('zlib');
var http = require('http');
var fs = require('fs');
var request = http.get({
      host: 'example.com'
    , port: 80
    , path: '/'
    , headers: {'Accept-Encoding': 'gzip,deflate'}
});
request.on('response', function (response) {
  var output = fs.createWriteStream('example.com_index.html');
  switch (response.headers['content-encoding']) {
    // or, just use zlib.createUnzip() to handle both cases
    case 'gzip':
      response.pipe(zlib.createGunzip()).pipe(output);
      break;
    case 'deflate':
      response.pipe(zlib.createInflate()).pipe(output);
      break;
    default:
      response.pipe(output);
      break;
  }
});

// server example
// Running a gzip operation on every request is quite expensive.
// It would be much more efficient to cache the compressed buffer.
var zlib = require('zlib');
var http = require('http');
var fs = require('fs');
http.createServer(function (request, response){
  var raw = fs.createReadStream('index.html');
  var acceptEncoding = request.headers['accept-encoding'];
  if (!acceptEncoding) {
    acceptEncoding = '';
  }
  // Note: this is not a conformant accept-encoding parser.
  // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
  if (acceptEncoding.match(/\bdeflate\b/)) {
    response.writeHead(200, { 'Content-Encoding': 'deflate' });
    raw.pipe(zlib.createDeflate()).pipe(response);
  } else if (acceptEncoding.match(/\bgzip\b/)) {
    response.writeHead(200, { 'Content-Encoding': 'gzip' });
    raw.pipe(zlib.createGzip()).pipe(response);
  } else {
    response.writeHead(200, {});
    raw.pipe(response);
  }
}).listen(1337);


// This is a truncated version of the buffer from the above examples
var buffer = Buffer.from('eJzT0yMA', 'base64');

zlib.unzip(buffer, {finishFlush: zlib.Z_SYNC_FLUSH}, function (err, buffer) {
  if (!err) {
    console.log(buffer.toString());
  } else {
    // handle error
  }
});

// Memory Usage Tuning

(1 << (windowBits+2)) +  (1 << (memLevel+9))

{windowBits: 14, memLevel: 7}

1 << windowBits

// Flushing

var zlib = require('zlib');
var http = require('http');

http.createServer((request, response) => {
  // For the sake of simplicity, the Accept-Encoding checks are omitted.
  response.writeHead(200, { 'content-encoding': 'gzip' });
  var output = zlib.createGzip();
  output.pipe(response);
  setInterval(function () {
    output.write(`The current time is ${Date()}\n`, function () {
      // The data has been passed to zlib, but the compression algorithm may
      // have decided to buffer the data for more efficient compression.
      // Calling .flush() will make the data available as soon as the client
      // is ready to receive it.
      output.flush();
    });
  }, 1000);
}).listen(1337);

Constants

zlib.Z_NO_FLUSH
zlib.Z_PARTIAL_FLUSH
zlib.Z_SYNC_FLUSH
zlib.Z_FULL_FLUSH
zlib.Z_FINISH
zlib.Z_BLOCK
zlib.Z_TREES

zlib.Z_OK
zlib.Z_STREAM_END
zlib.Z_NEED_DICT
zlib.Z_ERRNO
zlib.Z_STREAM_ERROR
zlib.Z_DATA_ERROR
zlib.Z_MEM_ERROR
zlib.Z_BUF_ERROR
zlib.Z_VERSION_ERROR


// Class Options:
- flush (default: zlib.Z_NO_FLUSH)
- finishFlush (default: zlib.Z_FINISH)
- chunkSize (default: 16*1024)
- windowBits
- level (compression only)
- memLevel (compression only)
- strategy (compression only)
- dictionary (deflate/inflate only, empty dictionary by default)

Class: zlib.Deflate
Class: zlib.DeflateRaw
Class: zlib.Gunzip
Class: zlib.Gzip
Class: zlib.Inflate
Class: zlib.InflateRaw
Class: zlib.Unzip
Class: zlib.Zlib

zlib.flush(kind, function () {});
zlib.params(level, strategy, function () {});
zlib.reset();
zlib.constants
zlib.createDeflate(options);
zlib.createDeflateRaw(options);
zlib.createGunzip(options);
zlib.createGzip(options);
zlib.createInflate(options);
zlib.createInflateRaw(options);
zlib.createUnzip(options);

// Convenience Methods

zlib.deflate(buf, options, function () {});
zlib.deflateSync(buf, options);
zlib.deflateRaw(buf, options, function () {});
zlib.deflateRawSync(buf, options);
zlib.gunzip(buf, options, function () {});
zlib.gunzipSync(buf, options);
zlib.gzip(buf, options, function () {});
zlib.gzipSync(buf, options);
zlib.inflate(buf, options, function () {});
zlib.inflateSync(buf, options);
zlib.inflateRaw(buf, options, function () {});
zlib.inflateRawSync(buf, options);
zlib.unzip(buf, options, function () {});
zlib.unzipSync(buf, options);