Blog

Um Guia: Como Criar e Publicar um package NPM em TypeScript
Software
Sep 23, 2022
Um Guia: Como Criar e Publicar um package NPM em TypeScript
Introdução Já te aconteceu copiar e colar os mesmos pedaços de código entre diferentes projetos? Este era um problema constante para mim, por isso comecei a desenvolver packages em TypeScript que me permitissem reutilizar partes úteis de código. Este guia vai mostrar-te, passo a passo, como criar um package utilizando TypeScript e publicá-lo no Node Package Manager (NPM). Porque usar TypeScript? Usar TypeScript vai proporcionar-te uma melhor experiência de desenvolvimento, sendo o teu melhor amigo durante o processo. Ele vai “gritar” contigo sempre que cometeres um erro. No início, pode parecer que o strong typing diminui a produtividade e que não compensa utilizá-la. Mas, acredita em mim, o TypeScript tem algumas vantagens muito impactantes: Optional Static Typingya –  Podes adicionar types a variáveis, funções, propriedades, etc. Isto ajuda o compilador a detetar e avisar sobre possíveis erros no código antes mesmo do pacote ser executado. Os types são ótimos quando se usa libraries, pois mostram aos desenvolvedores exatamente que tipo de dados são esperados. Intellisense – Uma das maiores vantagens do TypeScript é a sua capacidade de code completion e IntelliSense, fornecendo sugestões ativas à medida que vais escrevendo código. Código mais robusto e fácil de manter. Na minha opinião, o TypeScript deve ser o teu melhor amigo ao construir packages! Vamos lá cozinhar! O primeiro passo é criar a pasta do teu package, escolhendo um nome criativo.Cria um repositório Git. A seguir, vamos criar um repositório Git remoto para o teu pacote. Embora a criação de repositórios Git não seja o foco deste artigo, o GitHub fornece instruções claras e simples para te ajudar a criar um repositório. Basta seguires os passos apresentados no GitHub durante a criação do repositório, e, quando estiveres pronto, volta aqui para continuar!Inicia o teu packageDepois de criares o repositório, precisas de criar um package.json. Este é um ficheiro JSON que reside na pasta principal do projeto. O package.json contém informações importantes sobre o projeto, como o nome e a descrição do mesmo, metadados funcionais como o número da versão do pacote, scripts a executar no CLI e uma lista de dependências necessárias para o projeto.Após isso, precisamos de criar um ficheiro .gitignore na raiz do projeto. Não queremos que código desnecessário entre no repositório ✋. Por agora, só precisamos de ignorar a pasta node_modules.Excelente trabalho! Assim deverá estar o teu projeto no Visual Studio Code e no repositório Git. A partir deste ponto, irei continuar a adicionar ficheiros diretamente do Visual Studio Code.Vamos adicionar o Typescript como uma DevDependency Vamos instalar uma versão mais estável do Typescript, que é compatível com múltiplos pacotes que serão usados durante este guia.Usando a flag --save-dev, estamos a dizer ao NPM para instalar o Typescript como uma devDependency. Isto significa que o Typescript será instalado apenas quando executares o npm install, mas não quando o utilizador final instalar o pacote.O Typescript é necessário para desenvolver o package, mas não é necessário quando o package é utilizado.Para compilar o Typescript, precisamos de criar um ficheiro tsconfig.json na raiz do projeto. Este ficheiro corresponde à configuração do compilador Typescript (tsc).Existem muitas opções de configuração no campo tsconfig.json, e é importante estar ciente do que elas fazem. target: a linguagem usada para a saída compilada. Compilar para es6 tornará o nosso pacote compatível com os navegadores mais recentes. module: o gestor de módulos usado na saída compilada. declaration: Deve estar definido como true ao construir um package. Isto permite que o Typescript exporte também os ficheiros de definição de types juntamente com o código JavaScript compilado, permitindo que o package seja usado tanto com Typescript quanto com JavaScript. outDir: A saída compilada será gravada nesta pasta. include: Caminho para os arquivos de origem. Neste caso, a pasta src. exclude: O que queremos excluir da compilação pelo tsc (compilador Typescript). Vamos codificar! Agora, com a configuração do Typescript pronta, estamos prontos para codificar uma função simples que recebe parâmetros e os multiplica, retornando o resultado da operação. Para isso, vamos criar uma pasta src na raiz do projeto e adicionar um arquivo index.ts:Depois adiciona um script de build ao arquivo package.json: Agora, executa o comando de build no console: Isto irá compilar o teu código Typescript e criar uma nova pasta chamada lib na raiz do projeto, contendo o código compilado em JavaScript e as definições de tipo. É necessário adicionar a pasta lib ao teu arquivo .gitignore. Não é recomendado que arquivos gerados automaticamente sejam enviados ao repositório remoto do Git, pois isso pode causar conflitos desnecessários.Formatação e Linting Um bom pacote deve incluir regras para linting e formatação. Este processo é importante quando várias pessoas estão a trabalhar/contribuir para o mesmo projeto, garantindo que todos estejam alinhados em relação à sintaxe e ao estilo do código. Tal como fizemos com o Typescript, estas ferramentas são usadas apenas para o desenvolvimento do pacote e, por isso, devem ser adicionadas como devDependencies. Vamos começar por adicionar o ESLint ao nosso pacote: eslint: Biblioteca principal do ESLint. @typescript-eslint/parser: Um parser que permite ao ESLint compreender código TypeScript. @typescript-eslint/eslint-plugin: Plugin com um conjunto de regras recomendadas para TypeScript. Assim como acontece com as definições do compilador TypeScript, pode-se usar a linha de comando para gerar um ficheiro de configuração ou criá-lo manualmente no VSCode. Em ambos os casos, é necessário um ficheiro de configuração para o ESLint. Cria um ficheiro .eslintrc de raiz: Podes usar a seguinte configuração inicial e depois explorar a lista completa de regras para ajustar as definições do ESLint às tuas necessidades: parser: indica ao ESLint para processar o código através de um parser ao analisá-lo. plugins: define os plugins que está a usar. extends: diz ao ESLint que configuração deve herdar. A ordem é importante. env: indica em que ambientes o seu código será executado. Agora vamos adicionar um script de lint ao package.json. Adicionar a flag --ext especificará quais extensões o lint deve considerar. Por padrão, é .js, mas também usaremos .ts. Não é necessário fazer linting em alguns ficheiros, como a pasta lib. É possível evitar o linting de ficheiros e pastas desnecessários ao criar um ficheiro .eslintignore.Agora o ESLint está pronto! Recomendo a integração do ESLint com o editor de código que preferires usar. No VSCode, vai até as extensões e instala a extensão do ESLint. Para verificar o teu código usando o ESLint, podes executar manualmente o script na linha de comandos:Agora vamos configurar o PrettierÉ comum o uso do ESLint e do Prettier ao mesmo tempo, por isso, vamos adicionar o Prettier ao nosso projeto:O Prettier não necessita de um ficheiro de configuração, pode simplesmente ser executado e utilizado imediatamente. Caso queiras definir a tua própria configuração, será necessário criar um ficheiro .prettierrc na raiz do teu projeto.Se estiveres curioso para saber mais, deixo aqui uma lista completa de opções de formatação e o Prettier Playground.Vamos adicionar o comando Prettier aos nossos scripts. Vamos também configurar o suporte a todos os ficheiros que terminem em .ts, .js, e .json, e ignorar os mesmos ficheiros e diretórios que estão no .gitignore (ou criar um ficheiro .prettierignore). Agora, basta executar o comando npm run format para formatar e corrigir todo o código.Conflitos entre ESLint e Prettier É possível que o Prettier e o ESLint gerem conflitos devido a regras comuns que se sobrepõem. A melhor solução para isso é usar o eslint-config-prettier, que desativa todas as regras do ESLint irrelevantes para formatação de código, já que o Prettier é eficaz nessa tarefa.Para fazer isto funcionar, precisas de ir ao ficheiro .eslintrc e adicionar o Prettier no final da tua lista de extends, para desativar qualquer outra regra anterior de outros plugins. Com isso, a secção de formatação e linting está concluída! Excelente trabalho!Configuração de testes com Jest Na minha opinião, todo o pacote deve incluir testes unitários! Vamos adicionar o Jest para nos ajudar com isso. Como estamos a usar o Typescript, também precisamos adicionar o ts-jest e @types/jest.Cria um ficheiro jestconfig.json na raiz:Agora, vamos atualizar o antigo script de testes no nosso ficheiro package.json:O teu ficheiro package.json deverá ficar algo assim: Agora, vamos escrever um teste básico! Na pasta src, cria uma nova pasta chamada tests, e dentro dessa pasta, adiciona um ficheiro com o nome que preferires, mas deve terminar com .test.ts. Por exemplo, multiplier.test.ts. Neste teste simples, vamos passar os números 2 e 3 como parâmetros para a nossa função Multiplier e esperar que o resultado seja 6. Agora, basta executá-lo.Funciona! Bom trabalho! O teste passou com sucesso, como podes ver! Isso significa que a nossa função está a multiplicar corretamente. Scripts mágicos do package.json Existem muitos scripts mágicos disponíveis para uso no ecossistema do Node Package Manager. É bom automatizar o nosso pacote tanto quanto possível. Nesta secção, vamos analisar alguns destes scripts no npm: prepare, prepublishOnly, preversion, version e postversion. prepare: O script prepare é executado quando as dependências do Git estão a ser instaladas. Este script corre após o prepublish e antes do prepublishOnly. Perfeito para construir o código. prepublishOnly: Este comando serve o mesmo propósito que prepublish e prepare, mas é executado apenas durante o comando npm publish. preversion: Este comando será executado antes de aumentar a versão de um novo package. Perfeito para verificar o código com linters. version: Este comando será executado depois de uma nova versão ser incrementada. Se o teu package tem um repositório Git, como no nosso caso, um commit e uma nova tag de versão serão feitos sempre que a versão for aumentada. Este comando será executado ANTES de o commit ser feito. postversion: Será executado depois de o commit ter sido feito. Um local perfeito para fazer o push do commit, bem como da tag. O meu package.json após a implementação dos novos scripts:Antes de publicarQuando adicionámos o .gitignore ao nosso projeto com o objetivo de não passar os ficheiros de build para o repositório Git, desta vez o oposto acontece para o package publicado. Não queremos que o código-fonte seja publicado com o package, apenas os ficheiros de build.Isso pode ser resolvido adicionando a propriedade files no package.json:Agora, apenas a pasta lib será incluída no package publicado! Detalhes finais no package.json Finalmente, é hora de preparar o nosso package.json antes de publicar o package:Estes toques finais no package.json incluem adicionar uma boa descrição, palavras-chave e um autor. Isto é importante, pois informará ao NPM de onde ele pode importar os módulos.Compromete-te e envia o código Chegou a hora de enviar todo o teu trabalho para o repositório remoto!Publica o teu pacote no NPM! Para poderes publicar o teu package, é necessário criar uma conta no NPM. Se ainda não tens uma conta, podes criar uma em: https://www.npmjs.com/signupExecuta o comando npm login para fazer login na tua conta do NPM. Depois, tudo o que precisas de fazer é publicar o teu package com o comando:Se tudo correu bem, agora podes ver o teu package em https://www.npmjs.com/.Temos um package! Excelente trabalho!Aumentar para uma nova versão Vamos aumentar a versão do nosso package utilizando os nossos scripts: Isto criará uma nova tag no Git e enviá-la-á para o repositório remoto. Agora, basta publicar novamente: Com isto, tens uma nova versão do teu pacote! Parabéns! Chegaste ao fim. Esperamos que agora saibas como começar a construir o teu incrível package!
João
João Santos
Mobile Developer Lead
Olá, BANCOS! Precisam mesmo de outro Core Banking System?
Software
Oct 12, 2019
Olá, BANCOS! Precisam mesmo de outro Core Banking System?
As nossas mentes estão formatadas para assumir sem questionar que os sistemas tecnológicos que envolvem operações complexas e críticas são sempre algo desenvolvido de forma secreta e gerido por pseudocientistas de um filme de Hollywood dos anos 80. "Complexidade é o inimigo da execução" Atualmente, na nossa sociedade, como resultado dessa visão comum, nas áreas de negócios mais tradicionais, é muito raro questionarmos "por que precisamos de tanta complexidade?". Depois de vários anos a trabalhar em arquiteturas de software complexas para instituições financeiras e desde 2017 como fundador de uma Fintech e empresa de Software, acredito verdadeiramente que todos os bancos tradicionais são o melhor exemplo da famosa citação de Tony Robbins sobre a complexidade: "complexidade é o inimigo da execução". A principal razão para esta conclusão foi identificada e é amplamente reconhecida por todos os profissionais de serviços financeiros: estamos a falar da dependência dos sistemas obsoletos. O meu objetivo, quando decidi escrever este artigo, não foi falar sobre os problemas de sistemas antigos obsoletos, lentos ou inseguros, mas sim partilhar a minha conclusão perturbadora de que os responsáveis pela estratégia de evolução tecnológica desses bancos estão a repetir os mesmos erros antigos quando tentam remover da equação os seus sistemas atuais. Dependência de um único componente, geralmente vindo dos anos 80 e 90, que chamamos de Core Banking System O que está a causar que a maioria dessas organizações esteja condenada a desaparecer num período mais curto do que podemos imaginar? A resposta é a sua dependência de um único componente, geralmente vindo dos anos 80 e 90, que chamamos de Core Banking system.A maioria dos Core Banking Systems foram desenvolvidas para oferecer todas as funcionalidades necessárias para gerir um banco. E UAU... isto foi ótimo para quem queria ter um banco em funcionamento rapidamente! Nos anos 80 e início dos anos 90, não existia internet acessível para todos, nem existiam empresas Fintech a revolucionar o mercado, e a maioria dos produtos bancários eram idênticos entre os bancos. Os verdadeiros desafios de operar com um Core Banking System antigo surgem quando os processos de negócios da organização começam a abrandar sempre que são necessárias pequenas alterações no sistema, quando é necessário suportar soluções de canais numa corrida para a transformação digital do banco, responder rapidamente a mudanças regulamentares obrigatórias ou implementar personalizações específicas para introduzir um novo produto no portfólio. A analogia do amante da música vs o profissional da música Recentemente encontrei a analogia perfeita para este processo de modernização do Core Banking. O amante da música vs o profissional da música.Deixa-me explicar a minha analogia. Se gostas de ouvir música em casa e não precisas de equipamento de som para viver, podes comprar um hi-fi ou até mesmo usar o hi-fi dos teus pais dos anos 90. Se precisares de reparar algo no hi-fi antigo, será difícil encontrar um bom técnico barato, e algumas peças podem ser difíceis de encontrar, mas o ponto é que tu não és um profissional, gostas de ouvir música relaxante no fim de semana, e este hi-fi antigo serve para o que precisas! Isto é o que muitos dos bancos tradicionais que não estão a investir em inovação estão a fazer, estão simplesmente a ouvir música e inconscientemente à espera do seu fim.Mas se fores um músico profissional ou um DJ, terás concorrência e precisas de manter o teu sistema atualizado, se possível com um sistema de última geração, para poder competir no mercado com outros músicos. Neste caso, não irás comprar um hi-fi "doméstico", mas sim vários módulos de hardware de som profissional separados e cabos de alta qualidade, todos com interfaces padrão para poder rapidamente atualizar ou simplesmente mudar parâmetros de som para melhor responder e adaptar-se ao espaço onde estás a tocar.Este tipo de sistema é difícil de montar, mas, uma vez estabelecido, torna-se significativamente mais fácil de adaptar a qualquer necessidade ou cenário. A imagem à esquerda é, na minha opinião, a analogia perfeita para representar uma camada de integração robusta e muito personalizável de um banco moderno, onde podemos conectar dezenas ou centenas de módulos externos, orquestrando e ajustando todos os resultados finais. Quando um banco com esta visão moderna de Arquitetura de Sistemas adquire ou desenvolve um novo módulo para integrar no seu ecossistema de microserviços, já sabe que será fácil substituí-lo no futuro, porque foi desenvolvido com a integração e o isolamento de domínio em mente e, esse é o ciclo normal de vida dos módulos tecnológicos na indústria financeira ultrarrápida de hoje. No final, trata-se de ser um músico profissional ou simplesmente alguém que gosta de música e tem uma caixa de som hi-fi, afinal, tudo se resume ao resultado final. Por que os bancos estão a substituir antigos sistemas monolíticos por novos sistemas monolíticos? Uma das questões mais difíceis para eu responder hoje em dia é porque é que os bancos estão a substituir sistemas monolíticos antigos por novos sistemas monolíticos? Mesmo que os novos sistemas sejam construídos com ferramentas mais modernas, utilizando arquiteturas de hardware menos proprietárias ou até mesmo executados na cloud, isso não resolve os problemas estruturais subjacentes. Só porque um fornecedor mostra alguns exemplos de serviços de integração, como APIs de serviços web, ou apresenta um catálogo de produtos com módulos separados, não significa que não esteja a comprar outro monólito! Nos últimos 8 anos, tornou-se cada vez mais comum ver bancos a substituir o seu Core banking System por um novo Core Banking System moderno. No entanto, a razão por trás dessa escolha é que a maioria dos Bancos não tem na sua equipa de gestão um verdadeiro engenheiro, ou engenheiros com uma visão limitada de arquitetura de sistemas, ou na maioria dos casos as decisões são tomadas sem o feedback da equipa de engenharia. Para os responsáveis pela decisão com um grande ego, e com medo da evolução tecnológica, a escolha mais segura quando se trata de fazer grandes investimentos em transformação tecnológica é sempre adquirir sistemas caros e de fornecedores de grande nome. Normalmente, como resultado de um ou mais relatórios feitos para eles por uma das grandes cinco consultoras, que têm um enorme interesse comercial em manter sistemas proprietários, fechados e, especialmente, difíceis de adaptar, para continuarem a vender contratos exorbitantes de desenvolvimento, análise, consultoria, etc.Os decisores devem concentrar-se no verdadeiro problema: a falta de liberdade para gerir e controlar o seu percurso tecnológico, que é a base do ritmo acelerado e do baixo custo de manutenção de quase todas as empresas Fintech. A essência do monólito vive nesse lado obscuro, onde o fornecedor do sistema interliga, na mesma base de código, todas as regras de negócio de diferentes áreas de domínio. A alma dos sistemas monolíticos está presa neste lado sombrio, onde o fornecedor do sistema combina todas as regras de negócio num único código, como a famosa “bola de esparguete infernal”. Com esta abordagem, os fornecedores podem afirmar que o novo Core Banking System oferece milhares de serviços de integração (APIs, filas, etc.), mas todos os problemas antigos permanecem. No final, estão apenas a vender um novo monólito, agora suportado por linguagens de programação modernas e instalado em infraestruturas de hardware padrão ou na cloud. O segredo para o sucesso neste processo de modernização está em libertar a organização da dependência de um único fornecedor. É crucial evitar ficar refém de sistemas que exijam suporte contínuo do mesmo fornecedor ou de empresas de consultoria dispendiosas para realizar, analisar ou executar todas as tarefas necessárias para que a organização opere os seus sistemas de forma eficaz. Arquitetura de Microserviços é o caminho para a modernização e acelera todas as mudanças de negócios e evolução dentro de um banco. Todos os sistemas dentro do banco devem respeitar os padrões da indústria em termos de estruturas de dados de entrada e saída, isolando pequenas funções de negócios ou integração em módulos de software separados. A Arquitetura de Microserviços é o alicerce para a modernização e a base para todos os processos de mudança e evolução de negócios num banco. O meu conselho para os responsáveis pela tomada de decisões na indústria financeira é que compreendam que o ativo mais importante dentro da organização são os seus dados. Não devem depender de um único grupo de fornecedores para gerir e aproveitar o poder dos dados, de forma a garantir que a organização continue a gerar oportunidades de negócios e de mercado. Arquitetura de sistemas é a base da flexibilidade da organização para se adaptar rapidamente às necessidades do mercado Aqueles responsáveis pela tomada de decisão que ainda não perceberam que o investimento em tecnologia não tem de ser um investimento em fornecedores específicos de grandes nomes, e que a Arquitetura de Sistemas é a base da flexibilidade da organização para se adaptar rapidamente às necessidades do mercado, serão responsáveis pela perda de clientes e, em muitos casos, pelo fim da organização. Nestes casos, a aposta "segura" nos fornecedores de renome não valerá nada como defesa.
Pedro
Pedro Camacho
CEO & Co-founder
Azure Active Directory — Authentication OAuth 2.0
Software
Jan 08, 2018
Azure Active Directory — Authentication OAuth 2.0
Nas últimas semanas, estive a trabalhar num serviço de integração para um sistema complexo baseado no Azure. O meu objetivo era encontrar uma forma de autenticar no Azure Active Directory, basicamente obtendo o token de acesso para as futuras requisições ao sistema, sem o pop-up de login da Microsoft, muito comum em integrações com serviços como Facebook e outros. O Microsoft Azure Active Directory (AD) já possui uma biblioteca de autenticação (ADAL), mas, infelizmente, não existe suporte para a linguagem que eu estava a utilizar no momento, GoLang. Diante desta situação, fui obrigado a encontrar uma solução alternativa. OAuth 2.0 OAuth 2.0 é um protocolo de autorização que permite que as aplicações obtenham acesso limitado às contas dos utilizadores num serviço HTTP. Não vou explicar todos os detalhes do protocolo aqui, o que vou me focar são nos grant types de autorização.OAuth 2.0 tem quatro grant types: Password; Client Credentials; Implicit; Authorization Code.  Com esta informação e para resolver o meu problema, escolhi o fluxo de autorização Password Grant. Para cenários semelhantes, quando se confia em clientes internos (first-party) ou de terceiros (third-party), tanto na web como em aplicações nativas, esta abordagem oferece ao utilizador final a melhor experiência. Para mais informações sobre o OAuth 2.0, podes consultar aqui. Microsoft Azure Active Directory e OAuth 2 Neste ponto, comecei a procurar como usar o tipo de fluxo Password Grant no Azure AD. A documentação da Microsoft não é muito útil nesse caso. Eles focam-se nos outros fluxos de grants usados em diferentes cenários, como: Authorization Code para aplicações Web Server; Implicit Grant para aplicações nativas; Client Credentials para aplicações de serviço.  No entanto, o tipo de fluxo Resource Owner Password Credentials Grant também é suportado desde a versão 1.1 no Azure AD. Este fluxo também é baseado em pedidos HTTP, mas sem redirecionamento de URL. Para mais informações sobre este fluxo, podes consultar aqui. Assim, para este caso específico, quando temos um serviço de integração, como um windows service, para obter informações de uma aplicação que requer autenticação, esta abordagem é prática e eficiente. Como usar Para usar esse método e obter o token no Azure AD OAuth 2, precisamos fazer a seguinte solicitação de serviço web:https://login.microsoftonline.com/<TenantId>/oauth2/token Content-Type: application/x-www-form-urlencoded Host: login.microsoftonline.com TenantId: <MY_HOST> (for example “mywebsite.com”) WS: /oauth2/token Parâmetros a utilizar no Body request: grant_type: password client_id: O valor do Client Id do Azure AD resource: O valor do App ID da aplicação para a qual deseja um access token client_secret: O valor do Client Secret do Azure AD username: O nome de utilizador de uma conta no Azure AD password: A password da conta do utilizador Resultado do request: HTTP/1.1 200 OKContent-Type: application/json; charset=utf-8{ "token_type":"Bearer", "expires_in":"600", "expires_on":"1511533698", "not_before":"1511533698", "resource":"*resource*", "access_token":"*token*","refresh_token":"*token*", "scope":"user_impersonation"} Agora tens o teu token de acesso para usar na tua aplicação. Já tiveste esta necessidade ou tens outra abordagem? Fica à vontade para partilhar. Espero que estas informações sejam úteis para futuros desenvolvimentos! Result access token exampleJá tiveste esta necessidade ou tens outra abordagem? Fica à vontade para partilhar. Espero que estas informações sejam úteis para futuros desenvolvimentos!@medium
João
João Marçal
Digital Products Development Manager

2 / 2