Friday, April 20, 2018

left-pad, no we're not lazy! we're just reusable!

Are javascript programmers lazy?

One criticism levelled against the javascript ecosystem is that programmers are becoming lazy with javascript. Another criticism is that a javascript function should not be a package.

There's a merit to having the individual functions have their own packages though. It adheres to Unix philosophy of "Write programs that do one thing and do it well"

And function being a package lends itself easily to be usable for scripting.

Take uuid and mkdirp package for example.

$ yarn init && yarn add uuid mkdirp


With package having only one function, uuid and mkdirp can be both API and command-line utility.


As API:




As command-line utility:



How awesome is that?


If mkdirp (rmdir, mv, cat, ...) function is part of com.acme.fileSystem package, it'll be not intuitive to make the package a commandline utility as the package covers a lot of functionalities.


Happy Coding!



yarn binaries, yarn +scripts

$ mkdir test-yarn-run && cd test-yarn-run && yarn init && yarn add jest

Yarn has a nice shortcut to run binaries in node_modules/.bin. Instead of running this:

$ ./node_modules/.bin/jest --help

Or this:

$ $(npm bin)/jest --help

Run this instead:

$ yarn jest --help


However, there's a potential ambiguity that may lead to node_modules' binaries instead of the package.json's scripts be ran with that yarn shortcut, and vice versa.

"test": "yarn jest --config jest.json",
"build": "yarn && yarn jest && yarn webpack -p"

See the potential mistake above? There's a typo on build script, instead of it running the package.json's test script, it run the jest binary in node_modules instead.

With that said, it's a good idea to have a convention that can disambiguate the package.json's scripts from the node_modules' binaries.

One good way to disambiguate them is to prefix the package.json's script with plus sign. It gives a notion that package.json's scripts are additional executables aside from the node_modules' executables.

"+test": "yarn jest --config jest.json",
"+build": "yarn && yarn +jest && yarn webpack -p"

With prefix, the command yarn +jest will immediately flag that +jest command as non-existent, as there are no binaries prefixed with plus on their name.




The plus prefix has a nicer readability for pre and post scripts too. Whereas without the prefix, pre and post scripts are harder to identify if they are part of other script:
"pretest": "yarn lint",
"prebuild": "yarn clean",
"postbuild": "yarn rimraf temp",
"test": "yarn jest --config jest.json",
"build": "yarn && yarn test && webpack -p"


With the prefix, it's immediately obvious that pre+build and post+build are related to +build, likewise with pre+test to +test.

"pre+test": "yarn +lint",
"pre+build": "yarn +clean",
"post+build": "yarn rimraf temp",
"+test": "yarn jest --config jest.json",
"+build": "yarn && yarn +test && webpack -p"


With prefx, it's easy to spot that yarn somethingHere is running a binary, instead of it running a script from the package.json. Saves the hassle of scanning the package.json to see if somethingHere is part of package.json's scripts or not.


Happy Coding!

Wednesday, April 18, 2018

Completely solve a problem with Partial


"Whenever I write code in Java I feel like I'm filling out endless forms in triplicate." -- http://funcall.blogspot.com/2010/04/whenever-i-write-code-in-java.html


In order to appease the compiler from complaining this:





I had introduced another interface just to make the properties optional:

type ActionsUsed =
    IUserAction
    | IUserCancelledAction
    | ICompanyAction
    | ICounterAction
    | IErrorModuleAction
    | ILoggedUserAction
    ;


export interface IActionsForTest
{
    counter?: {
        increment: () => void;
        decrement: () => void;
    };

    goToUser?: (userId: number) => void;
    cancelUserLoading?: () => void;

    goToCompany?: (code: string) => void;

    tellModuleError?: (error: IErrorHappened) => void;

    saveUser?: (loggedUser: ILoggedUser) => void;

    goToLogin?: () => void;
}




export interface IActionsRequired
{
    counter: {
        increment: () => void;
        decrement: () => void;
    };

    goToUser: (userId: number) => void;
    cancelUserLoading: () => void;

    goToCompany: (code: string) => void;

    tellModuleError: (error: IErrorHappened) => void;

    saveUser: (loggedUser: ILoggedUser) => void;

    goToLogin: () => void;
}


export interface IDispatches
{
    actions: IActionsRequired;
}


// Redux's built-in Dispatch can't check if a wrong value is passed to dispatch's type parameter.
// So we make our own Dispatch type.
type Dispatch<A> = (action: A) => A;

export const mapDispatchToProps = (dispatch: Dispatch<ActionsUsed>): IDispatches =>
    ({
        actions: {
            counter: {
                increment: () => dispatch({type: CounterKind.INCREMENT}),
                decrement: () => dispatch({type: CounterKind.DECREMENT})
            },

            goToUser         : (userId: number) => dispatch({type: UserActionType.USER, payload: {userId}}),
            cancelUserLoading: () => dispatch({type: UserActionType.USER_CANCELLED}),

            goToCompany: (code: string) => dispatch({type: CompanyActionType.COMPANY, payload: {code}}),

            tellModuleError: (errorHappened: IErrorHappened) => dispatch({
                type: 'ERROR_MODULE', payload: errorHappened
            }),

            saveUser: (loggedUser: ILoggedUser) =>
                dispatch({type: LoggedUserActionType.SAVE_USER_INFO, payload: loggedUser}),

            goToLogin: () => dispatch({type: Routes.LOGIN} as any)
        }
    });





So no more problems on testing:




But it looks ridiculous to write another interface just for testing.

Another way to solve the problem is to make all properties of the IActionsRequired optional by suffixing the question mark on all properties:

export interface IActionsRequired
{
    counter?: {
        increment: () => void;
        decrement: () => void;
    };

    goToUser?: (userId: number) => void;
    cancelUserLoading: () => void;

    goToCompany?: (code: string) => void;

    tellModuleError?: (error: IErrorHappened) => void;

    saveUser?: (loggedUser: ILoggedUser) => void;

    goToLogin?: () => void;
}

Testing won't require all the properties of IActionsRequired:




It would introduce compilation error when the optional property is used though:







It can be solved by using non-null assertion operator, however, it would introduce exclamation noises in the code of the consumer of the IActionsRequired, e.g.,

this.props.actions.counter!.decrement

this.props.actions.saveUser!(loggedUser)


Then I found a generic interface that makes a property of an interface optional, it would solve the problem of requiring all the properties of interface for the test object. That generic interface is called Partial. Let's restore IActionsRequired's properties as required by removing all the question marks:



And then on test, use Partial on IActionsRequired:




Partial is part of TypeScript, no need to npm install / yarn add anything, nor import Partial. Here is its definition:




Happy Coding!

Saturday, April 14, 2018

Cookie security

Testing security

app.get('/page',  (req, res) => {
    res.send(
        `
        <button type='button' id='increment'>Test</button><br/><br/>
        <button type='button' id='gcv'>Get cookie's value</button>

        <script>
        function getCookie(cname) {
            const name = cname + "=";
            const decodedCookie = decodeURIComponent(document.cookie);
            const ca = decodedCookie.split(';');

            for(let i = 0; i < ca.length; i++) {
                let c = ca[i];
                while (c.charAt(0) == ' ') {
                    c = c.substring(1);
                }

                if (c.indexOf(name) == 0) {
                  return c.substring(name.length, c.length);
                }
            }
            return "";
        }

        document.getElementById('increment').onclick = async e => {  
            // same-origin is needed for the server be able to send back the cookie
            const fr = await fetch('/renew', {credentials: 'same-origin'});
            
            const jr = await fr.json();
                
            console.log(jr); // will output 'Yay!'
        };  

        document.getElementById('gcv').onclick = async e => {    
            console.log('cookie: ' + document.cookie);
            // will not show anything due to httpOnly true
            console.log('quickBrownFox: ' + getCookie('quickBrownFox')); 
        };  
        </script>
        `);
    }
);


let n = 1;
app.get('/renew', (req, res) => {  

  // Setting httpOnly to true makes the cookie not readable from browser's javascript.
  // More secure, avoids XSS attack.

  // a non-expiring cookie. yet it gets deleted when the browser is closed though
  res.cookie('quickBrownFox', n++, {httpOnly: true});

  // persistent cookie for 7 days, stays when the browser is closed. Hmm.. that's obvious :)
  res.cookie('makulit', 'hey',  { maxAge: 1000 * 60 * 60 * 24 * 7, httpOnly: true });
  
  res.status(200).json({message: 'Yay!'});
});


app.listen(3000);


Chrome certainly makes javascript beautiful.


Happy Coding!

JavaScript lazy-loading

function counterEager(): Iterable<number> {
    console.log('counterEager: ');

    const list = [];
    for (let i = 1; i <= 5; i++) {        
        list.push(i);
        console.log('pushed value ' + i);
    }

    console.log('counterEager ends');

    return list;
}


function* counterLazy(): Iterable<number> {
    console.log('\ncounterLazy: ');

    for (let i = 1; i <= 5; i++) {                        
        yield i;
        console.log(`resuming value ${i}`);
    }        
}


function* counterLazyMultiple(): Iterable<number> {            
    console.log('\ncounterLazyMultiple: ');
        
    const a = [100, 200, 300];            
    yield* a;
    console.log('resuming value 300');    
    yield 400;
    console.log('resuming value 400');    
    yield* a;
    console.log('resuming value 300');    
}



function* counterLazyWithMixedReturnType() {        
    console.log('\ncounterLazyWithMixedReturnType: ');

    const a = [100, 200, 300];
    yield* a;
    console.log('resuming value 300');
    yield 400;
    console.log('resuming value 400');
    yield a;
    console.log('resuming value 100, 200, 300');    
}

for (const i of counterEager()) {
    console.log('value: ' + i);    
}

let n = 1;
for (const i of counterLazy()) {
    console.log(`received value #${n++}: ${i}`);  
}

n = 1;
for (const i of counterLazyMultiple()) {
    console.log(`received value #${n++}: ${i}`);      
}

n = 1;
for (const i of counterLazyWithMixedReturnType()) {
    console.log(`received value #${n++}: ${i}`);      
}


Output:
Developers-iMac:it dev$ ts-node sample.ts 
ounterEager: 
pushed value 1
pushed value 2
pushed value 3
pushed value 4
pushed value 5
counterEager ends
value: 1
value: 2
value: 3
value: 4
value: 5

counterLazy: 
received value #1: 1
resuming value 1
received value #2: 2
resuming value 2
received value #3: 3
resuming value 3
received value #4: 4
resuming value 4
received value #5: 5
resuming value 5

counterLazyMultiple: 
received value #1: 100
received value #2: 200
received value #3: 300
resuming value 300
received value #4: 400
resuming value 400
received value #5: 100
received value #6: 200
received value #7: 300
resuming value 300

counterLazyWithMixedReturnType: 
received value #1: 100
received value #2: 200
received value #3: 300
resuming value 300
received value #4: 400
resuming value 400
received value #5: 100,200,300
resuming value 100, 200, 300


Unless you really want to yield the array itself instead of the array's individual elements, it's a good practice to explicitly indicate the return type when using TypeScript, the compiler can help you spot accidental error of yielding the array itself instead of yielding the array's individual elements:



On following, without the explicit type, the array itself (number[]) is yielded instead of its individual elements (number). Miss a single character (asterisk), the code will do different. See the output above.




It's interesting that JavaScript can yield individual elements from a list without looping by just suffixing the yield keyword with asterisk.

yield* listHere;

C# still don't have that functionality.

https://stackoverflow.com/questions/6957659/yield-multiple-ienumerables

https://stackoverflow.com/questions/5415902/c-yield-return-range-collection


And also, JavaScript syntax for generator is terser than C#. Javascript's yield elementHere vs C#'s yield return elementHere


Have C# used yield elementHere instead of yield return elementHere, yielding individual elements from an array without looping could have this syntax for C#:

yield foreach listHere;


C# team might be having a second thought to introduce syntactic sugar like this:
yield return foreach listHere;


Further reading:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function%2A

https://blog.johncrisostomo.com/basic-generators-in-javascript/



Happy Coding!

Saturday, April 7, 2018

Only Robinhood can do nested arrows, don't be so heroic

import IAllState from '../../../store/models/_i-all-state';

export interface IRootState
{
    rootState: IAllState;
}

export const mapAllStateAsRootStateToProps = (state: IAllState): IRootState => ({rootState: state});


// Following looks harder to read than the normal function
export const mapDestructuredStatesToPropsHard =
                 <T>(mapper: (rootState: IAllState) => T): (rootState: IAllState) => T & IRootState =>
                     rootState =>
                         // tslint:disable prefer-object-spread
                         Object.assign({}, {rootState}, mapper(rootState));


// Less hard than above. The exported expression is not mangled with too much types.
type IMapper = <T>(mapper: (rootState: IAllState) => T) => (rootState: IAllState) => T & IRootState;
export const mapDestructuredStatesToPropsLessHard: IMapper =
                 mapper =>
                     rootState =>
                         // tslint:disable prefer-object-spread
                         Object.assign({}, {rootState}, mapper(rootState));


// Nested arrow function looks hard, especially with TypeScript, since it's harder to decipher
// if the things that comes after the arrow is an executing code or if it is just a type.

// So despite some people going gaga over arrow functions,
// but some prefer to use normal functions when nested arrow functions mangles the readability of the code.

export function mapDestructuredStatesToProps
    <T>(mapper: (rootState: IAllState) => T): (rootState: IAllState) => T & IRootState
{
    return rootState =>
        // tslint:disable prefer-object-spread
        Object.assign({}, {rootState}, mapper(rootState));
}


Happy Coding!

Saturday, March 24, 2018

React + TypeScript + Hot-Reloading + lazy-loading a module using import and code-splitting

Plus one more thing, NodeJS.

In this post, I'll show you how to make the aforementioned technologies work.

TL;DR. Out-of-the-box, hot-reloading works, but dynamic import won't work. If dynamic import is made to work, both hot-reloading and node won't be able to work. There's a solution to these problems though.


The hot-reloading from react-hot-loader's TypeScript example is not working if code-splitting is used, though the page automatically refreshes whenever the code is changed, the whole page reloads instead of just the part that was changed, and the states reinitializes too. Even if the changes are coming from non-code-splitted code, the whole page reloads and the states gone.

Code-splitting requires setting tsconfig.json's module to esnext, and it also requires removing the babel-loader from webpack.config.js, babel-loader is used by react-hot-loader in order for hot-reloading to work.

If babel-loader is not removed from webpack.config.js's loaders, here's the error of webpack (tsconfig.json's module set esnext, target set to es6) when webpack is splitting the imports:




Here's the error if babel-loader is not removed from webpack.config.js's loaders, with tsconfig.json's module set to esnext, and target set es5:




react-hot-loader works with module set to commonjs only.


Another problem that arises from code-splitting, since it requires setting the tsconfig.json's module to esnext, codes written for node can't be run anymore. At the time of this writing (node version 8), node does not support ES modules. The only way for a TypeScript-generated code be runnable on node is by setting its tsconfig.json's module to commonjs, not esnext.

esnext might be compatible on node version 10: http://2ality.com/2017/09/native-esm-node.html

Here's the error on node when the tsconfig.json's module is set to esnext:



In order to make our TypeScript code be runnable on node, we must set the tsconfig.json's module to commonjs:



Node working: check. Node works by setting the module to commonjs.

Hot-reloading working: check. Hot-reloading is working again as tsconfig.json's module is set back to commonjs.

Lazy-loading a module using import and code-splitting: not yet working. The file theCompany.chunk.js is not splitted from index.js:




We have to find out why when tsconfig.json's module is set to esnext, webpack can split the dynamically-imported module (courtesy of await import) and in turn, emit working webpack code for lazy-loading. Here's the original code:




First, let's look at the code generated from TypeScript when the tsconfig.json's module is set to esnext. Following is the generated javascript code from the TypeScript code above.





The import statement is kept intact. Now let's apply webpack:




With tsconfig.json's module set to esnext, webpack can split the code (theCompany.chunk.js) from the code that uses await import.


When Webpack encounters dynamic import statement, Webpack replaces it with code that can dynamically import a module that works on the browser:





Now let's try setting tsconfig.json's module to commonjs, then run tsc.




Note: for ts.config that has esModuleInterop compilerOptions set to true..
"esModuleInterop": true

..TypeScript generates different code:
return [4 /*yield*/, Promise.resolve().then(function () { return tslib_1.__importStar(require(/* webpackChunkName: 'theCompany' */ '../../../front-end/Company')); })];



Hmm.. that's something different. When the module is set to commonjs, TypeScript generates Promise.resolve instead of keeping the import statement. Now let's check if webpack can apply code-splitting given the code above.



Well that's sad, the file theCompany.chunk.js is not splitted from its parent code. The file theCompany.chunk.js is not generated by webpack. Now let's take a look at the code that dynamically imports the file theCompany.chunk.js.




As the dynamic import statements is not present in the code generated by TypeScript (Promise.resolve+require is generated instead), webpack can't replace them with its own code that can dynamically-load a module from the browser, i.e.,




If we can only nudge TypeScript to keep the import statement despite the tsconfig.json's module is set to commonjs instead of it generating Promise.resolve+require, Webpack will be able to split the code afterwards. Unfortunately, there's no configuration in tsconfig.json that can keep the import statement when tsconfig.json's module is set to commonjs.


With that said, we can use webpack's string-replace-loader to revert all those generated Promise.resolve statements to dynamic import statements instead. Do an npm install or yarn add of string-replace-loader.


To cut to the chase, add the string-replace-loader to webpack.config.js's rules' loaders, then use the regex below to revert back the Promise.resolve to dynamic import statement:


use: [
    {
        loader: 'string-replace-loader',
        options: {
            search: "/\\*yield\\*/, Promise\\.resolve\\(\\)\\.then\\(function \\(\\) \\{[^r]+return require\\(([^)]+)\\);[^)]+\\)",
            replace: "/*yield*/, quickbrown($1)",
            flags: "g"
        }
    },
    'babel-loader',
    'awesome-typescript-loader'
],

Note: for ts.config that has esModuleInterop compilerOptions set to true..
"esModuleInterop": true

..use the following regular expression instead:
search: '/\\*yield\\*/, Promise\\.resolve\\(\\)\\.then\\(function \\(\\) \\{[^r]+return [^(]+\\(require\\(([^)]+)\\)\\);[^)]+\\)'


We revert Promise.resolve+require to quickbrown statement instead of dynamic import statement just to check first if our regex is correct, and check if webpack's string-replace-loader can successfully replace the Promise.resolve+require statement that was generated by TypeScript. Following is the output of the Promise.resolve+require code that was replaced by webpack's string-replace-loader:





The file theCompany.chunk.js is not splitted from index.js since Webpack cannot find any dynamic import statement from the code applied of string-replace-loader, we used quickbrown statement in string-replace-loader.




Now let's change the quickbrown statement to dynamic import statement:

use: [
    {
        loader: 'string-replace-loader',
        options: {
            search: "/\\*yield\\*/, Promise\\.resolve\\(\\)\\.then\\(function \\(\\) \\{[^r]+return require\\(([^)]+)\\);[^)]+\\)",
            replace: "/*yield*/, import($1)",
            flags: "g"
        }
    },
    'babel-loader',
    'awesome-typescript-loader'
],

Note: for ts.config that has esModuleInterop compilerOptions set to true..
"esModuleInterop": true


..use the following regular expression instead:
search: '/\\*yield\\*/, Promise\\.resolve\\(\\)\\.then\\(function \\(\\) \\{[^r]+return [^(]+\\(require\\(([^)]+)\\)\\);[^)]+\\)'


Then run webpack again:




Webpack is now able to split the file theCompany.chunk.js from index.js as it now sees the dynamic import statement.


Here's the generated code by webpack, it's the same as if the tsconfig.json's module is set to esnext:




Hot-reloading working: check.

Lazy-loading a module using import and code-splitting working: check.

Code generated from TypeScript is compatible with node: check.



This post's complete code: https://github.com/MichaelBuen/ssk-two-for-github


Happy Coding!