Node.js

6 items

Jé pa l'temps #14 - Autoload correct Node.js version with nvm

These two scripts allows you to tell to your shell to autodetect .nvmrc in your Node.js projects and to load the wanted Node.js version.

With Bash

# Run 'nvm use' automatically every time there's 
# a .nvmrc file in the directory. Also, revert to default 
# version when entering a directory without .nvmrc
#
enter_directory() {
if [[ $PWD == $PREV_PWD ]]; then
  return
fi

PREV_PWD=$PWD
if [[ -f ".nvmrc" ]]; then
  nvm use
  NVM_DIRTY=true
elif [[ $NVM_DIRTY = true ]]; then
  nvm use default
  NVM_DIRTY=false
fi
}

export PROMPT_COMMAND=enter_directory

With ZSH

# place this after nvm initialization!
autoload -U add-zsh-hook
load-nvmrc() {
  local node_version="$(nvm version)"
  local nvmrc_path="$(nvm_find_nvmrc)"

  if [ -n "$nvmrc_path" ]; then
    local nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")

    if [ "$nvmrc_node_version" = "N/A" ]; then
      nvm install
    elif [ "$nvmrc_node_version" != "$node_version" ]; then
      nvm use
    fi
  elif [ "$node_version" != "$(nvm version default)" ]; then
    echo "Reverting to nvm default version"
    nvm use default
  fi
}
add-zsh-hook chpwd load-nvmrc

— — — — — — — — — — — — — — — — — — — — —

La série « Jé pa l’temps » est une série de tutoriels rapides en mode “prise de note” pour avoir une trace de tout ce dont je ne peux me rappeler et pourquoi pas le partager à d’autre. On va à l’essentiel, laissons les jolis pavés à d’autres sites comme medium… LOL !

Read more →
jplt Node.js

Jé pa l'temps #13 - Https server with Node.js

Code

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

const express = require('express');
const app = express();

app.get('/', async (req, res) => {
  return res.send('OK');
});

https.createServer({
  key: fs.readFileSync('./server.key'),
  cert: fs.readFileSync('./certificate.pem'),
}, app).listen(3000)

— — — — — — — — — — — — — — — — — — — — — —

La série « Jé pa l’temps » est une série de tutoriels rapides en mode “prise de note” pour avoir une trace de tout ce dont je ne peux me rappeler et pourquoi pas le partager à d’autre. On va à l’essentiel, laissons les jolis pavés à d’autres sites comme medium… LOL !

Read more →
jplt Node.js

Jé pa l'temps #9 - Node.js hacks

🎲 Insert in an array at index

Array.prototype.insert = function (index, item) {
    this.splice(index, 0, item);
};

🪓 Delete undefined and null properties from an object

Object.entries(a).reduce((a,[k,v]) => (v === null || v === undefined ? a : {...a, [k]:v}), {})

» Example

{
  b: null,
  c: undefined,
  d: 1,
  e: '1',
  f: '',
};

// becomes
{
  d: 1,
  e: '1',
  f: '',
};

🛠️ Sort keys of an object

function sortObject(obj) {
  return Object.keys(obj).sort().reduce((result, key) => {
    result[key] = obj[key];
    return result;
  }, {});
}

🎉 Get properties which change between two objects

function getObjectDiff(obj1, obj2) {
  const diff = Object.keys(obj1).reduce((result, key) => {
    if (!obj2.hasOwnProperty(key)) {
      result.push(key);
    } else if (_.isEqual(obj1[key], obj2[key])) {
      const resultKeyIndex = result.indexOf(key);
      result.splice(resultKeyIndex, 1);
    }
    return result;
  }, Object.keys(obj2));

  return diff;
}

💛 SQL request with templating

function sql(query, args) {
  return {
      query: query.join('?'),
       args,
   };
}

sql`SELECT * FROM users WHERE username = ${username}`;

💡 Show all express route

function print (path, layer) {
  if (layer.route) {
    layer.route.stack.forEach(print.bind(null, path.concat(split(layer.route.path))))
  } else if (layer.name === 'router' && layer.handle.stack) {
    layer.handle.stack.forEach(print.bind(null, path.concat(split(layer.regexp))))
  } else if (layer.method) {
    console.log('%s /%s',
      layer.method.toUpperCase(),
      path.concat(split(layer.regexp)).filter(Boolean).join('/'))
  }
}

function split (thing) {
  if (typeof thing === 'string') {
    return thing.split('/')
  } else if (thing.fast_slash) {
    return ''
  } else {
    var match = thing.toString()
      .replace('\\/?', '')
      .replace('(?=\\/|$)', '$')
      .match(/^\/\^((?:\\[.*+?^${}()|[\]\\\/]|[^.*+?^${}()|[\]\\\/])*)\$\//)
    return match
      ? match[1].replace(/\\(.)/g, '$1').split('/')
      : '<complex:' + thing.toString() + '>'
  }
}

app._router.stack.forEach(print.bind(null, []))

⑹ Reduce error stack trace size

Error.stackTraceLimit = 6; // Set the size you want

👉 Use coverage with mocha watch

nodemon --exec nyc --reporter=lcov --reporter=text mocha

📕 Merge two pdfs together

const hummus = require("hummus");
const memoryStreams = require("memory-streams");

/**
 * Concatenate two PDFs in Buffers
 * @param {Buffer} firstBuffer
 * @param {Buffer} secondBuffer
 * @returns {Buffer} - a Buffer containing the concactenated PDFs
 */
export const combinePDFBuffers = (firstBuffer: any, secondBuffer: any) => {
  var outStream = new memoryStreams.WritableStream();

  try {
    var firstPDFStream = new hummus.PDFRStreamForBuffer(firstBuffer);
    var secondPDFStream = new hummus.PDFRStreamForBuffer(secondBuffer);

    var pdfWriter = hummus.createWriterToModify(
      firstPDFStream,
      new hummus.PDFStreamForResponse(outStream)
    );
    pdfWriter.appendPDFPagesFromPDF(secondPDFStream);
    pdfWriter.end();
    var newBuffer = outStream.toBuffer();
    outStream.end();

    return newBuffer;
  } catch (e) {
    outStream.end();
    throw new Error(`Error during PDF combination: ${e.message}`);
  }
};

🪡 Parallel requester

const EventEmitter = require('events');

class ParallelRequester extends EventEmitter {
  constructor({ maxRequests = 4, delay = 0 } = {}) {
    super();

    this.maxRequests = maxRequests;
    this.delay = delay;
    this.queue = [];
    this.results = [];
    this.executingRequests = 0;

    this._endRequest = this._endRequest.bind(this);
    this._executeNext = this._executeNext.bind(this);

    this.on('execute', this._executeNext);
  }

  add(req) {
    if (Array.isArray(req)) {
      this.queue.push(...req);
    } else {
      this.queue.push(req);
    }

    return this;
  }

  start() {
    if (this.executingRequests < this.maxRequests) {
      this.emit('execute');
    }

    return this;
  }

  end() {
    if (!this.executingRequests && !this.queue.length) {
      return [];
    }

    return new Promise((resolve) => {
      this.on('end', () => {
        resolve(this.results);
      });
    });
  }

  _endRequest() {
    this.executingRequests--;

    if (this.executingRequests < this.maxRequests && this.queue.length) {
      setTimeout(() => {
        this.emit('execute');
      }, this.delay);
    }

    if (!this.executingRequests && !this.queue.length) {
      this.emit('end');
    }
  }

  _executeNext() {
    // console.log('Executing request - ', this.executingRequests, ' currently');
    while (this.executingRequests < this.maxRequests && this.queue.length) {
      this.executingRequests++;

      const request = this.queue.shift();

      Promise.resolve(request())
        .then((data) => {
          this.results.push(data);
          this._endRequest();
        })
        .catch(() => {
          this.results.push([]);
          this._endRequest();
        });
    }
  }
}

module.exports = {
  ParallelRequester,
};

— — — — — — — — — — — — — — — — — — — — — —

La série « Jé pa l’temps » est une série de tutoriels rapides en mode “prise de note” pour avoir une trace de tout ce dont je ne peux me rappeler et pourquoi pas le partager à d’autre. On va à l’essentiel, laissons les jolis pavés à d’autres sites comme medium… LOL !

Read more →
jplt node.js

Reverse engineering code

Hello :)

Today, i was trying to understand how a open source project was working and i met some difficult to understand the behaviour.

For debugging my projects, i have the habbit to log every function like that :

myClass {
  myFunction () {
    console.log('myClass.myFunction');

    // Do something
  }
}

Insteed of using console.log i use my logger library with its level. So, while i’m developing i can trace every executing function and i win a lot of time to understand what it is doing. In bonus, the cost of this method is close to zero and it is very useful !

Read more →
node.js

Jé pa l'temps #7 - Secure your Node.js

Limit rate

https://github.com/animir/node-rate-limiter-flexible#readme


— — — — — — — — — — — — — — — — — — — — — —

La série « Jé pa l’temps » est une série de tutoriels rapides en mode “prise de note” pour avoir une trace de tout ce dont je ne peux me rappeler et pourquoi pas le partager à d’autre. On va à l’essentiel, laissons les jolis pavés à d’autres sites comme medium… LOL !

Read more →
jplt node.js

Jé pa l'temps #3 - Eslint basic configuration

Make it yourself

npm i -D eslint
./node_modules/.bin/eslint --init

// Choose to answer to question to define your style !

On the road example

{
  "env": {
    "es6": true,
    "node": true,
    "mocha": true
  },
  "extends": "eslint:recommended",
  "globals": {
    "Atomics": "readonly",
    "SharedArrayBuffer": "readonly"
  },
  "parserOptions": {
    "ecmaVersion": 2020,
    "sourceType": "module"
  },
  "rules": {
    "indent": [
      "error",
      2
    ],
    "linebreak-style": [
      "error",
      "unix"
    ],
    "quotes": [
      "error",
      "single"
    ],
    "semi": [
      "error",
      "always"
    ],
    "comma-dangle": [
      "error",
      "always-multiline"
    ],
    "no-console": "error",
    "prefer-template": "error",
    "no-trailing-spaces": "error",
    "no-multi-spaces": "error",
    "no-multiple-empty-lines": [
      "error",
      {
        "max": 1,
        "maxEOF": 0
      }
    ],
    "prefer-const": [
      "error",
      {
        "destructuring": "any",
        "ignoreReadBeforeAssign": false
      }
    ]
  }
}

Nuxt.js eslint configuration

module.exports = {
  root: true,
  env: {
    browser: true,
    node: true,
  },
  parserOptions: {
    parser: 'babel-eslint',
  },
  extends: [
    '@nuxtjs',
    'plugin:nuxt/recommended',
  ],
  rules: {
    'nuxt/no-cjs-in-config': 'off',
    semi: [
      'error',
      'always',
    ],
    'comma-dangle': [
      'error',
      'always-multiline',
    ],
    'prefer-template': 'error',
  },
};

Editor config

# Editor configuration, see http://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
end_of_line = lf

[*.md]
max_line_length = off
trim_trailing_whitespace = false

— — — — — — — — — — — — — — — — — — — — — —

La série « Jé pa l’temps » est une série de tutoriels rapides en mode “prise de note” pour avoir une trace de tout ce dont je ne peux me rappeler et pourquoi pas le partager à d’autre. On va à l’essentiel, laissons les jolis pavés à d’autres sites comme medium… LOL !

Read more →
node.js