# Backend script

## Script

Server side JS are executed inside an asynchronous function, and support the use of `await` and can return every javascript value or a `Promise`.

{% hint style="info" %}
You are not forced to return a string, the server will arrange to return the data with the correct content type.
{% endhint %}

Here are some examples:

### Script returning JSON

```javascript
const x = {success: false, someData = [1,2,3]}
return x;
```

### Working with Promise

A backend script can return a `Promise` directly, Anacleto takes care of managing the promis's`then`

```javascript
const queryArgs = {
    db: "MASTER",
    sql: "select id from table"
}
return mysql.query(queryArgs);
```

## Promise

In Anacleto all asynchronous methods work using `Promises`, otherwise it's a moment to end up in the `callback hell 😈`

Here are some examples of scripts that use promises.

* In a script you can use `await` to wait for the outcome of a promise. Don't worry, `wait` doesn't block the application because your script is run inside an async function

{% code lineNumbers="true" %}
```javascript
const queryArgs = {
    db: "MASTER",
    sql: "select id from table"
}
const ret = await mysql.query(queryArgs);
//work with ret
console.log(ret);
const myRet = ret.map(row =>{
    return row.id
})
return myRet;
```
{% endcode %}

* Use `then` and `catche` to handle asynchronous functions

{% code lineNumbers="true" %}
```javascript
const queryArgs = {
    db: "MASTER",
    sql: "select id from table"
}
return mysql.query(queryArgs)
    .then((res) => {
        //work with ret
        console.log(ret);
        return new Promise((resolve, reject) => {
            const myRet = ret.map(row =>{
                return row.id
            })
            resolve(myRet);
        });
    });
```
{% endcode %}

* Compact way

{% code lineNumbers="true" %}
```javascript
const queryArgs = {
    db: "MASTER",
    sql: "select id from table"
}
return mysql.query(queryArgs)
    .then((res) => {
        //work with ret
        console.log(ret);
        const myRet = ret.map(row =>{
            return row.id
        })
        return Promise.resolve(myRet);
    });
```
{% endcode %}

* And when things get serious

{% code lineNumbers="true" %}
```javascript
let query1Res = [];
let query2Res = [];

return mysql.query(args1)
    .then((res) => {
        query1Res = res;
        //work with res
        return  mysql.query(args2);
    })
    .then((res) => {
        query2Res = res;
        //work with res
        return Promise.resolve(res);
    })
    .catch((error) => {
        query2Res = res;
        //work with res
        return Promise.resolve(res); //or reject
    })
```
{% endcode %}

{% hint style="info" %}
Remember, `Promise` are your friends!
{% endhint %}

## Organize scripts

### Folder

In Anacleto you can group scripts in folders, use this feature to better organize and order your code.

{% hint style="success" %}
**May the force be with you**
{% endhint %}

### Import

In a backend script you can use the `import` keyword to import another script. Use this feature when you have code you want to reuse.

{% hint style="info" %}
Don't worry if some scripts import the same scripts or if some scripts import each other. Anacleto will manage the dependencies for you avoiding recursively importing the same script several times.
{% endhint %}

{% hint style="success" %}
Remember that in Anacleto you can organize your scripts in folders and you can do multiple imports. Combine these 2 features to write clean, non-duplicate, and well-organized code.
{% endhint %}

```javascript
import "utils/utils1";
import "utils/utils2"
import "asporti/insert_utils";

//your code...

return {success:true}
```

## Var, let or const

Anacleto supports`var`, `let` e `const`, use them!

* `var` declarations are globally scoped or function scoped while `let` and `const` are block scoped.
* `var` variables can be updated and re-declared within its scope; `let` variables can be updated but not re-declared; `const` variables can neither be updated nor re-declared.
* They are all hoisted to the top of their scope. But while `var` variables are initialized with `undefined`, `let` and `const` variables are not initialized.
* While `var` and `let` can be declared without being initialized, `const` must be initialized during declaration.

## Strings and ES6

With the advent of ES6 in 2015 working with strings has become much easier.

As you once did:

```javascript
var nome = "Mario";
var cognome = "Rossi"
var messaggio = "Benvenuto " + nome + " " + cognome;

console.log(messaggio); // Benvenuto Mario Rossi
```

how you can do it from 2015:

```javascript
const nome = `Mario`;
const cognome = `Rossi`
const messaggio = `Benvenuto ${nome} ${cognome}`;

console.log(messaggio); // Benvenuto Mario Rossi
```

> **TIPS**: don't know how to do this strange superscript \` in a Mac? Just press ALT+ BACKSLASH

## Date and Numbers

### Intl, localize dates and numers

With the advent of ECMAScript all modern browsers and NodeJS support using `Intl`, this new object can help you a lot in formatting dates and numbers.

> The Intl object is the namespace for the ECMAScript Internationalization API, which provides language sensitive string comparison, number formatting, and date and time formatting. The Intl object provides access to several constructors as well as functionality common to the internationalization constructors and other language sensitive functions. [Intl doc](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl)

{% code overflow="wrap" %}
```javascript
//use browser language
Intl.DateTimeFormat(navigator.language, { weekday: 'long', month: 'short', day: 'numeric' }).format(new Date()) // Friday, Dec 27

//specify language
Intl.DateTimeFormat("it", { weekday: 'long', month: 'short', day: 'numeric' }).format(new Date()) // venerdì 19 ago

Intl.DateTimeFormat("en", { weekday: 'long', month: 'short', day: 'numeric' }).format(new Date()) // Friday, Aug 19
```
{% endcode %}

```javascript
const number = 123456.789;

console.log(new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(number));
// expected output: "123.456,79 €"

// the Japanese yen doesn't use a minor unit
console.log(new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).format(number));
// expected output: "￥123,457"

// limit to three significant digits
console.log(new Intl.NumberFormat('en-IN', { maximumSignificantDigits: 3 }).format(number));
// expected output: "1,23,000"
```

> TIPS: don't hit your head when you define the formats, let the browser do this job!

### Date vs luxon

Working with dates is never easy, anyone who has worked in JS will surely have struggled with the Date object. Unfortunately this object is very basic and just parsing or printing a date is a battle.

For this reason `Intl` was introduced with ECMAScript which helps us in printing.

If this object is not enough for you in Anacleto it is possible to use [luxon](https://moment.github.io/luxon/).

> `Luxon` is the heir of `moment.js`, the moment.js team itself recommends switching to luxon. If you don't know what moment.js is, just know that it was the most used library for working with dates in Javascript

Here are some examples of how Luxon can help you, you can find much more info directly in the official doc - [luxon Docs](https://moment.github.io/luxon/)

{% code overflow="wrap" %}
```javascript
//change date format
DateTime.fromSQL("2017-05-15").toFormat('yyyy LLL dd');

//create a date
const dt = DateTime.local(2017, 5, 15, 8, 30);

//current date
const now = DateTime.now();

//object to date
dt = DateTime.fromObject({day: 22, hour: 12 }, { zone: 'America/Los_Angeles', numberingSystem: 'beng'})

//parse date 
DateTime.fromISO("2017-05-15")          //=> May 15, 2017 at midnight
DateTime.fromISO("2017-05-15T08:30:00") //=> May 15, 2017 at 8:30
DateTime.fromRFC2822("Tue, 01 Nov 2016 13:23:12 +0630");
DateTime.fromHTTP("Sunday, 06-Nov-94 08:49:37 GMT");
DateTime.fromHTTP("Sun, 06 Nov 1994 08:49:37 GMT");
//parse sql date
DateTime.fromSQL("2017-05-15");
DateTime.fromSQL("2017-05-15 09:24:15");
DateTime.fromSQL("09:24:15");
//parse timestamp
DateTime.fromMillis(1542674993410);
DateTime.fromSeconds(1542674993);
//formato custom
DateTime.fromFormat("May 25 1982", "LLLL dd yyyy");


//date to string
DateTime.now().toString(); //=> '2017-09-14T03:20:34.091-04:00'
dt.toISO(); //=> '2017-04-20T11:32:00.000-04:00'
dt.toISODate(); //=> '2017-04-20'
dt.toISOWeekDate(); //=> '2017-W17-7'
dt.toISOTime(); //=> '11:32:00.000-04:00'
dt.toMillis(); //=> 1492702320000
dt.toSeconds(); //=> 1492702320.000
dt.valueOf(); //=> 1492702320000, same as .toMillis()
dt.toLocaleString(); //=> '4/20/2017'
dt.toLocaleString(DateTime.DATETIME_FULL); //=> 'April 20, 2017, 11:32 AM EDT'
dt.setLocale('fr').toLocaleString(DateTime.DATETIME_FULL); //=> '20 avril 2017 à 11:32 UTC−4'
dt.toFormat('yyyy LLL dd');

//math operation
var dt = DateTime.now();
dt.plus({ hours: 3, minutes: 2 });
dt.minus({ days: 7 });
dt.startOf('day');
dt.endOf('hour');

//properties
dt = DateTime.now();
dt.year     //=> 2017
dt.month    //=> 9
dt.day      //=> 14
dt.second   //=> 47
dt.weekday  //=> 4
dt.zoneName     //=> 'America/New_York'
dt.offset       //=> -240
dt.daysInMonth  //=> 30
```
{% endcode %}

