2.1.10 • Published 1 year ago

declarative-optional v2.1.10

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

Build Coverage License Version

Declarative-Optional

A Javascript library to write concise functional code.Combined with features of Java Optional & Javascripts Promise chaining

Features

Lazily evaluated

chaining async and sync functions

Most of the Java Optional Features

Some of the Java Stream Features

Installation
    npm install declarative-optional   
Usage

To Import

// Common JS
    const {Optional} = require( "declarative-optional");

//ES6
    import {Optional} from "declarative-optional";

Common Usages

//Increment By 5 
  function incrementByFive(input) {
        return Optional.of(input)
            .map(i=>i+5)
            .orElse(0)
    }


// incrementByFive(41)  => 46
// incrementByFive(null)  => 0
// incrementByFive(undefined)  => 0



// All the expressions will be evaluated only after you specified get()

//Increment a Number by 5, Only if its dividable by 5
Optional.of(input)
    .filter(val=>val % 5 == 0)
    .map(val=>val+5)
    .get()


   

On Asynchronous code

// Consider the async function

function getFromUserService({username, password}) {
    return new Promise((function (resolve) {
        resolve({name: "user", isAdmin: true})
    }))
}

async function login({username, password}) {

    if (null == username || null == password) {
        throw new Error("Cannot be Null")
    }

    const result = await getFromUserService(username, password)


    if (result.isAdmin) {
        redirectTo("adminPage")
    } else {
        redirectTo("userPage")
    }

}

// With Declarative Optional
async function login({username, password}) {


    const page = await Optional.of({username: user, password: pass})
        .filter(({username, password}) => (null != username && null != password))
        .map(getFromUserService)
        .map(result => result.isAdmin ? "adminPage" : "userPage")
        .toAsync();


    page.ifPresentOrElse(redirectTo, () => {
        throw new Error("Cannot be Null")
    })
}

fetch Api with Optional

    // Typical code 

    const url  ='https://jsonplaceholder.typicode.com/todos/' + item
    const rawResults = await fetch(url);
    const response = await rawResults.json();

    if (response.completed) {
        return response.title
    } else {
        return null
    }

    
    // Can be rewritten with optional as 
    return await Optional.of('https://jsonplaceholder.typicode.com/todos/' + item)
        .map(fetch)
        .map(response => response.json())
        .filter(response => response.completed == true)
        .map(response => response.title)
        .getAsync();

   
    

There are so much you can play with declarative suite. It does have some features similar to Java Optional & RX libraries, except the code is small (one file around 4 Kb original source) and simple.

It also features a stream library, a wrapper for array , with lazy evaluation and functional programming features.

//commonjs
    const {Stream} = require("declarative-optional");

//ES6
    import {Stream} from "declarative-optional";
    
    
    const results = Stream.of([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
        .filter(val => val % 2 == 0)
        .map(val => val * 2)
        .get();

    console.log(stream) // [4,8,12,16,20]
    
    
    // first
    Stream.of([45,46,80])
        .first()
        .get()
    // [45]
    
    
    
    // last
    Stream.of([45,46,80])
        .last()
        .get()
    // [80]
    
    //The first and last methods are useful when you want to get the first or last element of a stream and also you can chain up map operations.

    Stream.of([45,46,80])
        .last()
        .map(val=>val*2)
        .get()
    // [160]
    

// Async Stream
    const input = [Promise.resolve(21),Promise.resolve(25),Promise.resolve(30)]
    const result = await Stream.of(input)
        .filter((value) => value %5 ==0)
        .map(getFromUserService)
        .getAsync()
    
    // [25,30]
    
    
// handle async errors or empty values with default value

    const input = [Promise.resolve(21),Promise.reject(25),Promise.resolve(30)]
    const val = await Stream.of(input)
        .filter((value) => value %5 ==0)
        .map(getFromUserService)
        .orElseAsync(["default"])

    // ["default"]    

Documentation

 Optional.of(input)
  Optional.of(21)
  .map(val => val + 1)
  Optional.of(21)
  .filter(val => val % 5 == 0)
// Consider a function which will return Optional
//returns Optional 
const powersOf = (name)=>Optional.of(['web-shooters','syntheitic-webbing'])

const superHeroById = (id) =>  "Spider-Man"
const res  = Optional.of(52001)
    .map(superHeroById)
    .map(powersOf )
    .flatten()
    .get()

// results ['web-shooters','syntheitic-webbing']
const res  = Optional.of(52001)
    .map(superHeroById)
    .flatmap(powersOf )
    .get()

// results ['web-shooters','syntheitic-webbing']
  Optional.of(21)
  .filter(val => val % 5 == 0)
  .map(val => val + 5)
  .get() ;  // returns null
  Optional.of(20)
  .filter(val => val % 5 == 0)
   .map(val => val + 5)
  .get() ;  // returns 25

Error

  Optional.of(input)      
   .map(promiseFunctionToValidateUserDetails)
   .map(promiseFunctionToValidateSomeOther)
  .get() ;  

// Error ? Use getAsync to deal with promises
  Optional.of(21)
  .filter(val => val % 5 == 0)
  .map(val => val + 5)
  .orElse(45) ;  // returns 45 , as the evaluation will return null
  Optional.of(20)
  .filter(val => val % 5 == 0)
   .map(val => val + 5)
  .orElse(45) ;  // returns 25
const res  = Optional.of([23,45])
    .stream()
    .map(i=>i+1);

//returns [24,46]
const res  = Optional.of(null)
    .stream()
    .map(i=>i+1);

//returns []
const res  = Optional.of(23)
    .stream()
    .map(i=>i+1);

//returns [24]
 const result = await Optional.of(input)      
               .map(promiseFunctionToValidateUserDetails)
               .map(promiseFunctionToValidateRole)
                .map(regularFunctionToFormatData)
                .getAsync()
               
const result = await Optional.of('https://jsonplaceholder.typicode.com/todos/' + item)
                    .map(fetch)
                    .map(response => response.json())
                    .filter(response => response.completed == true)
                    .map(response => response.title)
                    .getAsync();

The below will also work fine

  const result = await Optional.of(21)
                          .filter(val => val % 5 == 0)
                          .map(val => val + 5)
                          .getAsync()  

  
  Optional.of(input)      
   .map(promiseFunctionToValidateUserDetails)
   .map(promiseFunctionToValidateSomeOther)
  .toAsync()
   .then(optionalData=>{
        // optionalData.get() holds the result
    })
 const optionalData = await Optional.of(input)      
                   .map(promiseFunctionToValidateUserDetails)
                   .map(promiseFunctionToValidateSomeOther)
                  .toAsync()

// optionalData.get() holds the result
Alternatives

There are some alternatives , Have a look into them as well

Optional.js

amidevtech/optional.js

2.1.10

1 year ago

2.1.9

1 year ago

2.1.2

1 year ago

2.1.1

1 year ago

2.1.5

1 year ago

2.1.7

1 year ago

2.1.0

1 year ago

1.1.1

2 years ago

1.1.0

2 years ago

1.0.10

2 years ago

1.0.9

2 years ago

1.0.8

2 years ago

1.0.7

2 years ago

1.0.6

2 years ago

1.0.5

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago