Use multiple files for docker-compose config

2019-10-18

You can specify one or multiple config files for docker-compose with the -f flag:

# one file
docker-compose -f docker-compose.yml up -d
# multiple files
docker-compose -f docker-compose.yml -f docker-compose.tests.yml up -d

Be sure to specify the config files before the sub-command:

# invalid
docker-compose ps -f docker-compose.yml
# valid
docker-compose -f docker-compose.yml ps

Get granted roles with psql

2019-10-16

With psql, there is an easy way to check which roles are granted to a role: \du

henk=> CREATE ROLE accounting;
CREATE ROLE
henk=> CREATE ROLE alex;
CREATE ROLE
henk=> GRANT accounting TO alex;
GRANT ROLE
henk=> \du accounting
             List of roles
 Role name  |  Attributes  | Member of
------------+--------------+-----------
 accounting | Cannot login | {}

henk=> \du alex
              List of roles
 Role name |  Attributes  |  Member of
-----------+--------------+--------------
 alex      |              | {accounting}

Understanding Javascript at a low level

2019-10-15

Did you ever ask yourself how Javascript works under the hood? It's important to understand how the language we're working with works on a lower level.

 Top level view of the Javascript engine

  • Receive source code
  • Parse the code and produce an Abstract Syntax Tree (AST)
  • Interpret as byte code and execute it
  • The profiler checks for optimisations at run-time
  • The compiler creates optimized code and replaces it with the byte code

Javascript Engine

What does the parser do?

Parser

A parser takes the source code and creates an AST. First, the parser splits the source code into tokens. There are different kinds of tokens, e.g. let and new are keywords, while + is an operator.

The tokens are then used to build the AST. If something unexpected is found, a SyntaxError is thrown.

A SyntaxError is thrown when the Javascript engine finds a piece of codes that don't belong to the language syntax.

Example

Let's try out the parser (using this website).

> var answer = 6 * 7;
[
    {
        "type": "Keyword",
        "value": "var"
    },
    {
        "type": "Identifier",
        "value": "answer"
    },
    {
        "type": "Punctuator",
        "value": "="
    },
    {
        "type": "Numeric",
        "value": "6"
    },
    {
        "type": "Punctuator",
        "value": "*"
    },
    {
        "type": "Numeric",
        "value": "7"
    },
    {
        "type": "Punctuator",
        "value": ";"
    }
]

 Abstract Syntax Tree (AST)

It's a graph (data structure) that represents a program.

It's used in:

  • Javascript Engine
  • Bundlers: Webpack, Rollup, Parcel
  • Transpilers: Babel
  • Linters: ESLint, Prettify
  • Type Checkers: Typescript, Flow
  • Syntax Highlighters

You can check the generated AST in the AST Explorer.

Below is an example on how to add an ESLint rule.

export default function(context) {
  return {
    VariableDeclaration(node) {
    	// const variable type
     	if (node.kind === "const") {
        	const declaration = node.declarations[0];
          	
          	// make sure that the value it's a number
          	if (typeof declaration.init.value === "number") {
            	 if (declaration.id.name !== declaration.id.name.toUpperCase()) {
                   	context.report({
                      	node: declaration.id,
                      	message: "The constant name should be in uppercase",
                      	fix: function(fixer) {
                         	return fixer.replaceText(declaration.id, declaration.id.name.toUpperCase()) 
                        }
                    })
                 }
            }
        }
    }
  };
};

 Example using AST to extend an ESLint rule without fix option

Example using AST to extend an ESLint rule without fix option

 Example using AST to extend an ESLint rule with fix option

Example using AST to extend an ESLint rule with fix option


Object preventExtension vs seal vs freeze

2019-10-11

ECMAScript 5 introduced new Object methods to Javascript. Among them preventExtensions, seal, freeze methods will be compared to each other.

preventExtensions

An object called by this method can't have any new properties being added.

Example

let person = {
  name: "Agustin",
  age: 27,
};

Object.preventExtensions(person);
Object.isExtensible(person); // return false

person.surname = "Ramirez";
console.log(person.surname); // return undefined

person.name = "Maria";
console.log(person); // return { name: "Maria", age: 27 }

delete person.age;
console.log(person); // return { name: "Maria" }

seal

An object called by this method can not have any new properties being added or current properties deleted.

Example

let person = {
  name: "Agustin",
  age: 27,
};

Object.seal(person);
Object.isSealed(person); // return true

// In strict mode this will throw a `TypeError`
person.foo = "something";
console.log(person.foo); // return undefined

person.name = "Maria";
console.log(person); // return { name: "Maria", age: 27 }

delete person.age;
console.log(person); // return { name: "Maria", age: 27 }

Object.defineProperty(person, "name", {
  get: () => "Juan",
}); // Throw TypeError

console.log(person); // return { name: "Maria", age: 27 }

freeze

An object called by this method can not have any further changes done to it.

Example

let person = {
  name: "Agustin",
  age: 27,
};

Object.freeze(person);
Object.isFrozen(person); // return true

person.name = "Maria";
console.log(person); // return { name: "Agustin", age: 27 }

shallow only

All of these methods only work on object properties shallowly, meaning that just work with the direct property references.

let person = {
  name: "Agustin", // Prevented, Sealed and Frozen
  age: 27, // Prevented, Sealed and Frozen
  address: {
    // Un-prevented, un-sealed and un-frozen
    country: "Argentina", // Un-prevented, un-sealed and un-frozen
    city: "Corrientes", // Un-prevented, un-sealed and un-frozen
  },
};

Feature matrix

Feature default preventExtensions seal freeze
add new properties
remove existing properties
change existing property values

`diff.orderFile`: order your `git diff` output smart!

2019-10-10

Working on a project, you might consider that one folder is more important than others. For example, src folder might be more relevant to you as a developer than doc, test, or samples, you name it. Or you may want source files to be listed first, e.g. *.c, *.go...

To order the list of files in git diff output, one may use git's diff.orderFile option.

If you are working with PostgreSQL for example, you may want such an order:

src/include/* 
src/common/* 
src/port/* 
config/* 
src/makefiles/* 
src/template/* 
src/backend/* 
src/fe_utils/* 
src/bin/* 
src/interfaces/libpq/* 
src/pl/* 
contrib/* 
src/interfaces/* 
doc/* 
src/test/*

To achieve this:

  • create a file with the proper list, e.g. .gitorderfile
  • run git config diff.orderFile .gitorderfile

You're done!


Postgres literal escape sequences

2019-10-09

Postgres automatically escapes all occurrences of escape sequences if strings aren't prefixed with the E escape constant. This can lead to unexpected results:

select array_to_string(array['first line', 'second line', 'third line'], '\n');
           array_to_string
-------------------------------------
 first line\nsecond line\nthird line

Prefixing the separator string with the escape constant tells Postgres to interpret the sequence literally.

select array_to_string(array['first line', 'second line', 'third line'], E'\n');
 array_to_string
-----------------
 first line     +
 second line    +
 third reich

There's no need to prefix the template string when using format, as E-strings are substituted in literally.

select format('first line%ssecond line', E'\n');
   format
-------------
 first line +
 second line

CSS class grouping

2019-10-07

In HTML, any symbol or undefined class name is ignored. Thus, you can use custom separators to group your classes.

<div class="sm-8 lg-3 bg-black fg-green custom-class1" />
<div class="sm-8 lg-3 / bg-black fg-green / custom-class1" />
<div class="[ sm-8 lg-3 ] [ bg-black fg-green ] [ custom-class1 ]" />

How to chain multiple functions in Javascript properly with async/await

2019-10-04

The code below chains multiple functions waits for everything to resolve, and then sends the result:

// chain any number of async functions
const asyncChain = (...fns) => x => fns.reduce(async (res, fn) => fn(await res), x);

// async functions
const add = async x => x + 1;
const multiply = async x => x * 2;
const square = async x => x * x;

const getResult = asyncChain(add, multiply, square);

(async () => console.log(await getResult(4)))(); // 100