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!