teleren/devto huggingface dataset:
Como publicar pacote npm
Tags: node
Published: 2021-08-31 01:34:05

Como todo desenvolvedor eu construí uma biblioteca relativamente grande e crescente de funções comuns para o meu trabalho, essa biblioteca vinha ajudando muito na minha vida como desenvolvedor, mas com o uso em vários projetos diferentes e a biblioteca mudando constantemente, começaram a surgir problemas de versionamento dificultando a manutenção, foi então que tive a ideia de utilizar uma tecnologia muito popular no desenvolvimento web, então decidi publicar o meu primeiro pacote npm.

Embora a tecnologia que utilizo, o mql5, seja muito alheia ao Node, npm e ao Javascript, ainda é possível utilizar o gerenciador de pacotes para administrar as versões da biblioteca nos meus projetos.

## Requisitos

### Node e npm

Antes de tudo é preciso ter o Node e o npm instalados, ambos podem ser instalados seguindo o tutorial dinsponível no [link](https://nodejs.org/en/), ou utilizando o gerenciador de pacotes preferido do seu sistema, no caso do Windows eu gosto bastante do Chocolatey:

```bash
choco install nodejs
```  

### Conta npm

Será preciso também ter uma conta no site da npm, que pode ser criada no [link](https://www.npmjs.com/).

## Publicando

- Primeiro será preciso iniciar o pacote npm, dentro da pasta com os arquivos executar o seguinte comando:

```bash
npm init
```

- Configurar o arquivo gerado ```package.json```, como no exemplo, acrescente os scripts necessários, os urls do repositório, a homepage e as tags:
```json
{
  "name": "mql-simplify",
  "version": "1.1.2",
  "description": "MQL5 library that was born to simplify",
  "main": "index.js",
  "directories": {
    "doc": "docs"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "compile": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command ./compile.ps1"

  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/HommaTech/mql-simplify.git"
  },
  "keywords": ["mql5", "mql", "metatrader"],
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/HommaTech/mql-simplify/issues"
  },
  "homepage": "simplify.homma.tech"
}
```

- Logar na conta npm que foi criada nos passos anteriores utilizando o seguinte comando:

```bash
npm login
```

- Logado na conta npm basta publicar:

```bash
npm publish
```

Agora o seu pacote já está no npm acessível e com acesso ao sistema de versionamento.

Foi uma solução simples e que resolveu perfeitamente o meu problema, vai lá dar uma olhadinha no meu pacote, o [mql-simplify](https://www.npmjs.com/package/mql-simplify).
Setting Up Kubernetes Command Line Tool (kubectl)
Tags: aws, kubernetes
Published: 2021-08-31 01:30:59

## Summary
The Kubernetes command-line tool, kubectl, allows you to run commands against Kubernetes clusters. You can use kubectl to deploy applications, inspect and manage cluster resources, and view logs. 

This tutorial will guide you through the installation and configuration of this tool on Linux.

## Installation Steps:
Download the Amazon EKS vended kubectl from AWS. To download the Arm version, change amd64 to arm64 before running the command.

```shell-session
$ curl -o kubectl https://amazon-eks.s3.us-west-2.amazonaws.com/1.21.2/2021-07-05/bin/linux/amd64/kubectl
```

Add execute permission to the binary.

```shell-session
$ chmod +x ./kubectl
```

Add the binary to the search path.

```shell-session
$ mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$PATH:$HOME/bin
```

Verify the version with the following command:

```shell-session
$ kubectl version --short --client
Client Version: v1.21.2-13+d2965f0db10712
```
Two node Kafka development cluster using docker
Tags: kafka, docker
Published: 2021-09-06 12:10:57

---
title: Two node Kafka development cluster using docker
published: true
date: 2021-08-31 01:30:10 UTC
tags: kafka,docker
canonical_url: https://omkarpatil.dev/two-node-kafka-development-cluster-using-docker
---

Here is a docker-compose yaml file to start a two Kafka cluster and [kafdrop ui](https://github.com/obsidiandynamics/kafdrop) for a quick local development setup.

```yaml
# STARTING UP: docker-compose up --remove-orphans -d
# STOP: docker-compose down
# CHECK LOGS: docker-compose logs -f -t
version: '3'

networks:
  kafka-net:
    driver: bridge

services:
  zookeeper:
    image: bitnami/zookeeper
    networks:
      - kafka-net
    ports:
      - '2181:2181'
    environment:
      - ALLOW_ANONYMOUS_LOGIN=yes
    # volumes:
    # - ./data/zookeeper/data:/data
    # - ./data/zookeeper/datalog:/datalog
  kafka1:
    image: bitnami/kafka
    networks:
      - kafka-net
    ports:
      - '9091:9091'
    environment:
      - KAFKA_CFG_BROKER_ID=1
      - KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
      - ALLOW_PLAINTEXT_LISTENER=yes
      - KAFKA_CFG_LISTENERS=INTERNAL://:19091,EXTERNAL://:9091
      - KAFKA_CFG_ADVERTISED_LISTENERS=INTERNAL://kafka1:19091,EXTERNAL://localhost:9091
      - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
      - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=INTERNAL
      - KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=true
    # volumes:
    # - ./data/kafka1/data:/var/lib/kafka/data
    depends_on:
      - zookeeper
    restart: always
  kafka2:
    image: bitnami/kafka
    networks:
      - kafka-net
    ports:
      - '9092:9092'
    environment:
      - KAFKA_CFG_BROKER_ID=2
      - KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
      - ALLOW_PLAINTEXT_LISTENER=yes
      - KAFKA_CFG_LISTENERS=INTERNAL://:19092,EXTERNAL://:9092
      - KAFKA_CFG_ADVERTISED_LISTENERS=INTERNAL://kafka2:19092,EXTERNAL://localhost:9092
      - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
      - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=INTERNAL
      - KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=true
    # volumes:
    # - ./data/kafka2/data:/var/lib/kafka/data
    depends_on:
      - zookeeper
    restart: always
  kafdrop:
    image: obsidiandynamics/kafdrop
    networks:
      - kafka-net
    restart: 'no'
    ports:
      - '9000:9000'
    environment:
      - KAFKA_BROKERCONNECT=kafka1:19091,kafka2:19092
    depends_on:
      - kafka1
      - kafka2

```
Setting Up AWS Command Line Interface (CLI)
Tags: aws, cloud, awscli
Published: 2021-08-31 01:10:49

## Summary
The AWS Command Line Interface (CLI) is a unified tool to manage AWS services. This tutorial will guide you through the installation and configuration of this tool on Linux.

## Installation Steps:
We will start with downloading the the zip file from AWS.

```shell-session
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
```

Next, we will unzip the file and run the installation.

```shell-session
$ unzip awscliv2.zip
```
```shell-session
$ sudo ./aws/install
```

To make sure the installation is successful, we will print out the version of the AWS CLI on the screen.

```shell-session
$ aws --version
aws-cli/2.2.29 Python/3.8.8 Linux/5.4.119-14943-gff839c7fedcc exe/x86_64.debian.10 prompt/off
```
In the next few steps, we will log on to the AWS Management Console and set up a new AWS Identity and Access Management (IAM) user. This IAM user later will be used to configure the AWS CLI.

Choose IAM from the list of services and click on "Add User."
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0jipikry4nv4v4hdkl4e.png)

Choose your user name and check "Programmatic Access" and "AWS Management Console Access"

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v041427kfzhrxut71egb.png)

Attach "Administrator Access" permissions to the IAM user created. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/88goqb0p0u7lfuepd1eg.png)

Save your "Access Key ID" and "Secret Access Key" on your favorite password vault. These credentials are displayed only once, therefore it is essential to save them now.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/je8onenel4qdbrsen5fy.png)

```shell-session
$ aws configure
```

 Go back to the terminal and configure the AWS CLI. We will use the us-east-1 as the default region for this guide.
* Access Key ID: "From the Previous Step"
* Secret Access Key: "From the Previous Step"
* Default Region Name: us-east-1
* Default Output: "Leave Blank"

Execute a command using the AWS CLI. For this example, we are listing all the IAM users.

```shell-session
$ aws iam list-users
{
    "Users": [
        {
            "Path": "/",
            "UserName": "ahmet.akan",
            "UserId": "AIDASNOJDUC6SGCXK3MPJ",
            "Arn": "arn:aws:iam::********:user/ahmet.akan",
            "CreateDate": "2021-08-31T00:05:26+00:00"
        }
    ]
}
```
Por que usar mobx - Flutter
Published: 2021-08-31 00:53:13

####Este artigo pretende explicar e listar algumas razões para você    usar mobx. Peço desculpas se durante a explicação eu ficar um 
####pouco confuso, esse é meu primeiro artigo.

   Vamos lá. Afinal, o que é Mobx? Antes de listar os motivos de seu uso, é bom entender seu conceito. Mobx é um pacote para gerenciar estados de aplicativos Flutter de uma forma muito simples. Diferente de outros packages, utilizando mobx você não precisa escrever diversas linhas de código.
   Com basicamente três palavras, você pode tornar o aplicativo reativo. Ele usa os conceitos de @observable (que é colocado em cima da variável, toda vez que ela sofrer mudança notificará você), @action (a função responsável por mudar uma observable), finalmente, temos @reactions que são os efeitos colaterais quando um observável para modificado.

![Ilustração sobre as observables, actions e reactions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uo98b0a1m0tffloof268.png)
   Com essas três palavras conseguimos montar um aplicativo reativo e eliminar aqueles vários set states que sobrecarregam seu app, principalmente se for um grande.

Agora, vamos ver as razões para usar mobx como seu gerenciamento de estado (embora apenas a explicação acima seja justificada).

* Fácil de implementar, conforme explicado anteriormente, o mobx utiliza um gerenciador de código por debaixo dos panos tornando o trabalho do desenvolvedor muito mais fácil, além de melhorar a legibilidade do seu código.

* Pacote constantemente atualizado pela comunidade e com muito conteúdo na internet.
* Eficiente em 90% dos casos. Como todo pacote, Mobx também tem suas limitações, mas seu uso é suficiente na maioria dos casos e para você que é um aplicativo de pequeno / médio prazo será muito eficiente.

### Chegamos ao fim, sei que existem vários outros motivos, mas como este é o primeiro artigo preferi escrever apenas estes. Peço desculpas novamente se soei confuso em algum momento. Estou aberto a críticas e sugestões construtivas.
1yr after projen's debut
Tags: news, javascript, node
Published: 2021-08-31 00:32:58

---
title: 1yr after projen's debut
tags: news, javascript, nodejs
published: true
main_image: https://dev-to-uploads.s3.amazonaws.com/i/0rejkflr3sap1mnasmbf.png
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/0rejkflr3sap1mnasmbf.png
series: projen
---

It was September 30, 2020, and it was the 1st Cloud Development Kit (CDK) Day -- a community-driven event -- when Elad Ben-Israel announced `projen` to the world. It's already been 1yr and you can definitely expect to see `projen` at the 2nd CDK Day on April 30, 2021. In fact, 15% (3/19) talks will be on `projen`.

If you'd like to learn more about `projen` before diving in, please check out one of my other projen posts:

{% link https://dev.to/aws-builders/projen-the-next-cdk-suprise-13b2 %}

While CDK Day will focus on the actual use and development of projen, I'd like to summarize the community side today.

## Installed Versions

![Installed Versions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c367javvkctczz08ofuf.png)

* `projen` follows `semver` like many other projects*

In short, ~50% of the ecosystem is on the CURRENT minor version. That's an outstanding amount. It may have something to do with the GitHub Workflow that creates a PR to upgrade projen automatically on a cadence.  `projen` also is using a `release-on-commit` model making the pace **near-real-time**. In fact, Github Octoverse 2020 called this fact out:

{% twitter 1382164605305290753 %}

## Project Types

![Project Types](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fffn6lm53b3890k8eehh.png)

Predictably, AWS CDK Constructs and AWS CDK Typescript Applications are #1 and #2. I would look for web.NextJsProject to grow significantly in 2021. In fact, the cdk.dev website could be converted to this.

## Contributors

![Contributors](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5v7tyo2r3miuczcir796.png)

Projen now has 37 unique code contributors, over 280 members in the cdk.dev #projen Slack channel, at least 70 unique Github users/organizations across over 1,000 repositories.

## Community Meeting

![Community Meeting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c1iybisfodl6wl7guyjj.png)

Projen held its first and so far only community meeting in January 2021.  I'm betting there will be more and likely soon after CDK Day 2021.
Método slice - Javascript
Tags: javascript, tutorial, webdev, beginners
Published: 2021-08-31 00:30:26

O método **slice()** retorna uma cópia de parte de um array a partir de um subarray criado entre as posições inicio e fim (fim não é necessário). O array original não é modificado.

---

## **Parâmetros**

start **-** Índice baseado em zero no qual inicia a extração, caso seja um valor negativo indica que o deslocamento é em relação ao fim do array. Se o valor for maior que o comprimento do array será retornado um array vazio, caso o valor desse parâmetro for omitido será iniciado a partir do índice incial do array.

**end -** Índice baseado em zero no qual é o final da extração, slice extrai até, não incluindo fim, caso seja um valor negativo indica o deslocamento em relação ao fim do array. Se o valor for omitido ou maior que o comprimento do array slice considerará como o último elemento do array como sendo fim.

---

### Sintaxe

```jsx
nameArray.slice(start, end)
```

---

## **Retorno**

O método **slice()** retorna um novo array contendo os elementos extraídos.

---

## Exemplos

Exemplo para extrair 'Laranja' e 'Limão' do array frutas

```jsx
//                 0          1         2       3        4
const fruits = ["Banana", "Laranja", "Limão", "Maçã", "Manga"];

const citrus = fruits.slice(1, 3);
// citrus -> ["Laranja", "Limão"]
```

<a href="https://www.notion.so/elianbecali/slice-dcd63d1e51e34af890d0087de3f95f51" target="_blank">Leia no Notion
</a>
<a href="https://www.youtube.com/watch?v=-JI0qolwrWg" target="_blank">Assista no Youtube
</a>
New Github Issue(still Beta) looks awesome
Tags: github, taskmangement, agile
Published: 2021-08-31 00:29:03

The new GitHub Issues(still beta) looks very nice.
Check it out for the demo!

Plan and track projects closer to your code - YouTube: {% youtube SI1ra-XHWHM %}

## Memo

- Github project tables/spread sheet => Customizable like Notion
- Switching to a project board view/kanban
- Project information (Priority, Sprint...) can be seen in a PR
- Sprint Planing&Management: Planning, Current Sprint,.... in a different tab => All information in a single page
- Roadmap, Epic Tracking => Easy filtering
Método shift - Javascript
Tags: javascript, tutorial, webdev, beginners
Published: 2021-08-31 00:28:43

O método **shift()** remove o primeiro elemento do array, retornando o elemento removido desse array.

---

## **Parâmetros**

Nenhum 

---

### Sintaxe

```jsx
const removedElement = numbers.shift();
```

---

## **Retorno**

O método **shift()** retorna o elemento removido do array.

---

## Exemplo

Removendo o primeiro elemento do array.

```jsx
const numbers = [10, 20, 30, 40];

const removedElement = numbers.shift();
// removedElement -> 10
// numbers -> [20, 30, 40]
```

<a href="https://www.notion.so/elianbecali/shift-83b7b7909e084c1db84005d3ad29ba03" target="_blank">Leia no Notion
</a>
<a href="https://youtu.be/SvtxFCiyn-4" target="_blank">Assista no Youtube
</a>
Should we switch to a monorepo?
Tags: git, monorepo, polyrepos
Published: 2021-09-08 11:39:43

---
title: Should we switch to a monorepo?
published: true
date: 2021-08-31 00:00:00 UTC
tags: git,monorepo,polyrepos
canonical_url: https://jhall.io/archive/2021/08/31/should-we-switch-to-a-monorepo/
---

Once upon a time I was working with a company that had a large number of repos (probably ~60 in total; 20 or so in regular use). This was a bit painful. Especially for the SRE team (which I was working closely with), as making otherwise simple changes to a deployment pipeline might mean updating 20 or 30 repositories.

One of the SRE team members proposed a migration to a [monorepo](https://en.wikipedia.org/wiki/Monorepo), as it would allow us to make these types of changes once and only once. He had also had a good experience with monorepos at a prevoius company.

My honest reply was: “I’m happy to consider this. We need to identify what problems it solves, as well as which problems it will introduce, so that we can either mitigate or accept those new problems.”

He never brought it up again.

* * *

So multiple repos for the win? No so fast. I would have said the same thing if the situation had been reversed.

The thing is, each model (monorepo, or multiple repos) has its own strengths and its own weaknesses. Switching from one to the other mid-stream is going to be painful, and I expect not worth it in most cases. Making such a drastic change only makes sense if you’re facing a lot of pain.

* * *
_If you enjoyed this message, [subscribe](https://jhall.io/daily) to <u>The Daily Commit</u> to get future messages to your inbox._
Método reverse - Javascript
Tags: javascript, tutorial, webdev, beginners
Published: 2021-08-31 00:19:18

O método **reverse()** inverte os itens de um array. O primeiro elemento do array se torna o último e o último torna-se o primeiro modificando o array original. 

---

## **Parâmetros**

Nenhum

---

### Sintaxe

```jsx
nameArray.reverse();
```

---

## **Retorno**

O método **reverse()** retorna o array invertido.

---

## Exemplos

Ivertendo a ordem do array

```jsx
const numbers = [3, 2, 1];

const invertedNumbers = numbers.reverse();
// invertedNumbers -> [1, 2, 3]
```

<a href="https://www.notion.so/elianbecali/reverse-cf77bbc5b5ec436787c309ae800f6c24" target="_blank">Leia no Notion
</a>
<a href="https://youtu.be/BJOhB-QSJG4" target="_blank">Assista no Youtube
</a>
10 Awesome React Libraries & Frameworks
Tags: react, javascript, webdev, typescript
Published: 2021-08-31 00:19:06

## 10 awesome react libraries & frameworks

+ [react-google-login](https://github.com/anthonyjgrove/react-google-login)
+ [react-facebook-login](https://github.com/keppelen/react-facebook-login)
+ [styled-components](https://styled-components.com/)
+ [react-router-dom](https://reactrouter.com/web/guides/quick-start)
+ [react-select](https://react-select.com/)
+ [redux](https://redux.js.org/)
+ [react-bootstrap](https://react-bootstrap.github.io/)
+ [react-icons](https://react-icons.github.io/react-icons/)
+ [material-ui](https://material-ui.com/)
+ [react-avatar](https://www.npmjs.com/package/react-avatar)

Have a good day
Método reduce - Javascript
Tags: javascript, tutorial, webdev, beginners
Published: 2021-08-31 00:16:10

O método **reduce()** executa uma função callback (fornecida por você) para cada elemento do array, resultando no final um único valor de retorno.

---

## **Parâmetros**

**callback -** Função passada como referência, será executada a cada iteração do array. Esta função pode receber 4 argumentos, esta função sempre deverá retornar um valor e este valor será o **accumulator** na próxima iteração.

**accumulator -** O valor retornado na última invocação do **callback,** ou o argumento **initialValue** se fornecido. 

**element -** O elemento que está sendo processado no array. 

**index -** O índice do elemento atual que está sendo processado no array. (Opcional)

**array -** O array para qual **reduce** foi chamada. (Opcional)

**initialValue** - valor a ser usado como o primeiro argumento (**accumulator**) da primeira chamada da função **callback.** (Opcional)

---

### Sintaxe

```jsx
const total = numbers.reduce(functionCallback);
```

---

## **Retorno**

O método **reduce()** retorna um valor resultante da sua função **reducer** passada por você.

---

## Exemplo

Retorna o valor total da soma dos números no array.

```jsx
const numbers = [10, 6, 4];
function myReducer(accumulator, value) {
	return accumulator + value;
}

const total = numbers.reduce(myReducer, 0);
// total -> 20
```

<a href="https://www.notion.so/elianbecali/reduce-46ae7092302b4fca80d0b518ba1252c9" target="_blank">Leia no Notion
</a>
<a href="https://youtu.be/S3-YOBb7Mz4" target="_blank">Assista no Youtube
</a>
Método push - JavaScript
Tags: javascript, tutorial, webdev, beginners
Published: 2021-08-31 00:09:04

O método **push()** adiciona um ou mais elementos ao final de um array, retornando o novo comprimento desse array.

---

## **Parâmetros**

**element1 ..., elementN** - um ou mais elementos a serem incluídos no final do array. 

---

### Sintaxe

```jsx
const totalArray = nameArray.push(elementN);
```

---

## **Retorno**

O método **push()** retorna o valor da propriedade **length** do objeto no qual o método foi chamado (neste caso foi o array).

---

## Exemplo

Adicionando mais dois valores ao array.

```jsx
const numbers = [10, 20];

const totalArray = numbers.push(30, 40);
// totalArray -> 4
// numbers -> [10, 20, 30, 40]
```

<a href="https://www.notion.so/elianbecali/push-37f68ac42ae6473ea915798b8315aab6" target="_blank">Leia no Notion
</a>
<a href="https://youtu.be/TSs4FXTT69Y" target="_blank">Assista no Youtube
</a>
Which HTML element tag can be used to represent and show footer or ending content to the user?
Tags: html
Published: 2021-08-31 00:00:00

---
  title: Which HTML element tag can be used to represent and show footer or ending content to the user?
  published: true
  tags: HTML5
  date: Tue Aug 31 2021 05:30:00 GMT+0530 (India Standard Time)
  canonical_url: https://melvingeorge.me/blog/html-element-tag-to-represent-and-show-footer-ending-content-user
  cover_image: https://melvingeorge.me/_next/static/images/main-00ad991b6b87f0b7af2a82b616553482.jpg
  ---
  [Originally posted here!](https://melvingeorge.me/blog/html-element-tag-to-represent-and-show-footer-ending-content-user)
  
**The best HTML element to represent and show footer or ending content to the user is the `footer` HTML element tag.**

For example, the `footer` HTML elements tag is used to add footer parts of a website like copyright information, links to other pages, article author information, etc. that are seen by the user as ending content on the website.

The `footer` HTML element tag can be written like this,

```html
<!-- Usage of the 'footer' HTML element tag -->

<!DOCTYPE html>
<html>
  <body>
    <!-- 'footer' HTML element tag  -->
    <footer>
      <a href="/home">Home</a>
      <a href="/about-us">About US</a>
      <p>&copy; 2021 melvingeorge.me</p>
    </footer>
  </body>
</html>
```

As you see from the above code we have used the `a` (anchor) tags to link the other pages in the website and the `p` (paragraph) tag to show the copyright information inside the `footer` HTML element tag that is ending content when a user visits the website.

Some common use cases for the `footer` HTML element tags are to hold:

- Navigation links
- Related page links
- Article author information
- Copyright information

etc. and everything that is footer or ending content to the user who visits the website.

See the above code live in [JSBin](https://jsbin.com/jemeqedaze/2/edit?html,output).

That's all 😃!

### Feel free to share if you found this useful 😃.

---