Git Product home page Git Product logo

bagofwords's Introduction

Bag of Words

Bag of Words is an API that generates random words and also templates to be used on different platforms. The word definitions are collected from the Dictionary API

Try it here.

Requirements

  • AWS Account
  • Azure Account
  • Serverless framework
  • NodeJS
  • NPM or Yarn

Config

Azure Translator

It was used this translator because of the pricing limits

  • Create a Translator in the Azure Portal
  • Specify the Resource Group, region, name, and pricing tier (select the F0)
  • After the resource is created, access the "Keys and Endpoint"
  • Copy the value of "KEY1" and add in the MICROSOFT_TRANSLATOR_SUBSCRIPTION_KEY in the serverless.yml file
  • Fill the MICROSOFT_TRANSLATOR_LOCATION with the Location/Region
  • Get the link of Text Translation and add in the MICROSOFT_API_COGNITIVE_ENDPOINT

Image

Install

Rename the file serverless-copy.ymlto serverless.yml

# Install dependencies
npm i

# Install dev dependencies
npm i -D

Test

http://localhost:3000/dev/word/

//For testing is informing a single random word, but by default, the api will provide 3 words
{
    "words": [
        {
            "word": "Summer",
            "phonetic": "ˈsʌmə",
            "phonetics": [
                {
                    "text": "ˈsʌmə",
                    "audio": "//ssl.gstatic.com/dictionary/static/sounds/20200429/summer--_gb_1.mp3"
                }
            ],
            "origin": "Old English sumor, of Germanic origin; related to Dutch zomer, German Sommer, also to Sanskrit samā ‘year’.",
            "meanings": [
                {
                    "partOfSpeech": "noun",
                    "definitions": [
                        {
                            "definition": "the warmest season of the year, in the northern hemisphere from June to August and in the southern hemisphere from December to February.",
                            "example": "this plant flowers in late summer",
                            "synonyms": [],
                            "antonyms": []
                        }
                    ]
                },
                {
                    "partOfSpeech": "verb",
                    "definitions": [
                        {
                            "definition": "spend the summer in a particular place.",
                            "example": "well over 100 birds summered there in 1976",
                            "synonyms": [],
                            "antonyms": []
                        }
                    ]
                }
            ]
        }
    ]
}

Specific language

http://localhost:3000/dev/word/de

//For this example it'll collect Deutsch random words
{
    "words": [
        {
            "word": "Schaden",
            "phonetic": "scháden",
            "phonetics": [
                {
                    "text": "scháden"
                }
            ],
            "origin": "mittelhochdeutsch schaden, althochdeutsch scadōn, zu Schaden",
            "meanings": [
                {
                    "partOfSpeech": "schwaches Verb",
                    "definitions": [
                        {
                            "definition": "für jemanden, etwas von Nachteil sein; einen Verlust, eine Beeinträchtigung darstellen, bewirken",
                            "example": "jemandem geschäftlich schaden",
                            "synonyms": [],
                            "antonyms": []
                        }
                    ]
                }
            ],
            "translation": {
                "text": "Hurt",
                "language": "en"
            }
        }
    ]
}

Templates

{
    "blocks": [
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "*Word*: Track\n*Example*: Secondary radars that track the aircraft in flight\n*Phonetics*: <https://ssl.gstatic.com/dictionary/static/sounds/20200429/track--_gb_1.mp3|Track>"
            }
        },
        {
            "type": "divider"
        },
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "*Word*: Birth\n*Example*: She birthed five children within ten years\n*Phonetics*: <https://ssl.gstatic.com/dictionary/static/sounds/20200429/birth--_gb_1.mp3|Birth>"
            }
        },
        {
            "type": "divider"
        },
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "*Word*: My\n*Example*: My goodness!\n*Phonetics*: <https://ssl.gstatic.com/dictionary/static/sounds/20200429/my--_gb_1.mp3|My>"
            }
        },
        {
            "type": "divider"
        }
    ]
}

Deploy

As this project was built with the serverless framework and the provider was set as AWS, the project will be deployed in the AWS.

npm run deploy

Azure DevOps

In the folder Azure it was created the file that is responsible to run the Azure Pipelines.

Terraform (optional)

It was created an terraform script to create the Key Vault and the Text Translator in the Cognitive Services. It's optional but you can save some time doing it. It's required to rename the file terraform-copy.tfvars to terraform.tfvars and add the following values:

#Can be get using the command `az account show`
subscription_id             = "" #Subscription ID of Azure account
tenant_id                   = "" #homeTenantId
#Values that are set in the App registrations https://support.lacework.com/hc/en-us/articles/360029107274-Gather-the-Required-Azure-Client-ID-Tenant-ID-and-Client-Secret
client_id                   = ""
client_secret               = ""
aws_secret = ""
aws_key = ""

Access the directory terraform-main and run the commands terraform init, terraform plan and terraform apply.

It was also created an pipleline template to handle with terraform files to create all the environment in the Azure side. The file deploy-using-tf-kv.yml it's similar to the deploy.yml, the diffrence is that is using the secrets from the Key Vault that was created by the terraform.

Role assignments on AZ Subscription

  • Create a new App Registration or generate a new client secret in the App Registration of the Azure DevOps.
  • Open the AZ Subscription that you manage, open the Access control, click on Add and select Add role assignment. Chose Contribuitor and on Members select the App Registration that is related to your Azure DeVOps.

Key Vault

First it's needed a KeyVault to store all the secrets needed, so create a new one and add the following secrets:

  • Manually
* aws-key - AWS key of the user
* aws-secret - AWS secret of the user
* MICROSOFT-TRANSLATOR-LOCATION - location where Microsoft translator is
* MICROSOFT-TRANSLATOR-SUBSCRIPTION-KEY - Key from the Microsoft translator
  • Terraform
* CLIENT-ID - Id of the App registration of the Azure DevOps
* CLIENT-SECRET - Secret of the App registration of the Azure DevOps
* SUBSCRIPTION-ID - Subscription id. Can be get by using `az account show`
* TENANT-ID - Tenant Id. Can be get by using `az account show`

Library

In the Library from Azure DevOps, create a new variable group called BagOfWords var group (or chose a name that you want), click in the Link secrets from an Azure key vault variables. In Variables, click on Add and select all the secrets from the key vault. Click on save.

Image

In case you're using the terraform to create the environment on Azure Image

Azure Pipeline

This is the sample of the azure-pipeline.yml. It was created an template file to use as component called deploy.yml. It was also created a diffrent deployment file to handle with the terraform script. The deploy-using-tf-kv.yml has all the steps needed to deploy the app.

# Node.js
# Build a general Node.js project with npm.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript

trigger:
  batch: true
  branches:
    include:
    - main
  paths:
    exclude: 
    - README.md
    - LICENSE

# parameters:
#   - name: appName
#     default: "BagOfWords"
#     type: string

pool:
  vmImage: ubuntu-latest

#You can use this one if you have created the KeyVault and Cognitive Services manually.
variables:
  - group: "BagOfWords var group"

stages:
# You can use this one if you have created the KeyVault and Cognitive Services manually.
  - stage: dev
    condition: succeededOrFailed()
    jobs:
    - template: /azure/templates/deploy.yml
      parameters:
        stageDeployment: dev
        awsSecret: $(aws-secret)
        awsKey: $(aws-key)  
        microsoftLocation: $(MICROSOFT-TRANSLATOR-LOCATION)
        microsoftSubscription: $(MICROSOFT-TRANSLATOR-SUBSCRIPTION-KEY)
        performTests: false

  # - stage: terraform
  #   jobs:
  #   - template: /azure/templates/terraform.yml
  #     parameters:
  #       awsSecret: $(aws-secret)
  #       awsKey: $(aws-key)
  #       appName: ${{ parameters.appName }}
  
  # - stage: dev
  #   condition: succeededOrFailed()
  #   jobs:
  #   - template: /azure/templates/deploy-using-tf-kv.yml
  #     parameters:
  #       stageDeployment: dev
  #       performTests: false
  #       customKeyVaultName: "${{ parameters.appName }}-kv" #app_name-kv

bagofwords's People

Contributors

leomozzer avatar

Stargazers

 avatar

Watchers

 avatar

bagofwords's Issues

Integration Tests with Word.test.js

Receiving the following error when performing the tests in the GitHub Actions
Error: connect ECONNREFUSED 127.0.0.1:80
app_1 | at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1146:16) {
app_1 | errno: -111,
app_1 | code: 'ECONNREFUSED',
app_1 | syscall: 'connect',
app_1 | address: '127.0.0.1',
app_1 | port: 80,
app_1 | config: {
app_1 | url: 'undefined/en/horn',
app_1 | method: 'get',
app_1 | headers: {
app_1 | Accept: 'application/json, text/plain, /',
app_1 | 'User-Agent': 'axios/0.21.4'
app_1 | },
app_1 | transformRequest: [ [Function: transformRequest] ],
app_1 | transformResponse: [ [Function: transformResponse] ],
app_1 | timeout: 0,
app_1 | adapter: [Function: httpAdapter],
app_1 | xsrfCookieName: 'XSRF-TOKEN',
app_1 | xsrfHeaderName: 'X-XSRF-TOKEN',
app_1 | maxContentLength: -1,
app_1 | maxBodyLength: -1,
app_1 | validateStatus: [Function: validateStatus],
app_1 | transitional: {
app_1 | silentJSONParsing: true,
app_1 | forcedJSONParsing: true,
app_1 | clarifyTimeoutError: false
app_1 | },
app_1 | data: undefined
app_1 | },
app_1 | request: <ref *1> Writable {
app_1 | _writableState: WritableState {
app_1 | objectMode: false,
app_1 | highWaterMark: 16384,
app_1 | finalCalled: false,
app_1 | needDrain: false,
app_1 | ending: false,
app_1 | ended: false,
app_1 | finished: false,
app_1 | destroyed: false,
app_1 | decodeStrings: true,
app_1 | defaultEncoding: 'utf8',
app_1 | length: 0,
app_1 | writing: false,
app_1 | corked: 0,
app_1 | sync: true,
app_1 | bufferProcessing: false,
app_1 | onwrite: [Function: bound onwrite],
app_1 | writecb: null,
app_1 | writelen: 0,
app_1 | afterWriteTickInfo: null,
app_1 | buffered: [],
app_1 | bufferedIndex: 0,
app_1 | allBuffers: true,
app_1 | allNoop: true,
app_1 | pendingcb: 0,
app_1 | constructed: true,
app_1 | prefinished: false,
app_1 | errorEmitted: false,
app_1 | emitClose: true,
app_1 | autoDestroy: true,
app_1 | errored: null,
app_1 | closed: false,
app_1 | closeEmitted: false,
app_1 | [Symbol(kOnFinished)]: []
app_1 | },
app_1 | _events: [Object: null prototype] {
app_1 | response: [Function: handleResponse],
app_1 | error: [Function: handleRequestError]
app_1 | },
app_1 | _eventsCount: 2,
app_1 | _maxListeners: undefined,
app_1 | _options: {
app_1 | maxRedirects: 21,
app_1 | maxBodyLength: 10485760,
app_1 | protocol: 'http:',
app_1 | path: 'undefined/en/horn',
app_1 | method: 'GET',
app_1 | headers: [Object],
app_1 | agent: undefined,
app_1 | agents: [Object],
app_1 | auth: undefined,
app_1 | hostname: null,
app_1 | port: null,
app_1 | nativeProtocols: [Object],
app_1 | pathname: 'undefined/en/horn'
app_1 | },
app_1 | _ended: true,
app_1 | _ending: true,
app_1 | _redirectCount: 0,
app_1 | _redirects: [],
app_1 | _requestBodyLength: 0,
app_1 | _requestBodyBuffers: [],
app_1 | _onNativeResponse: [Function (anonymous)],
app_1 | _currentRequest: ClientRequest {
app_1 | _events: [Object: null prototype],
app_1 | _eventsCount: 7,
app_1 | _maxListeners: undefined,
app_1 | outputData: [],
app_1 | outputSize: 0,
app_1 | writable: true,
app_1 | destroyed: false,
app_1 | _last: true,
app_1 | chunkedEncoding: false,
app_1 | shouldKeepAlive: false,
app_1 | maxRequestsOnConnectionReached: false,
app_1 | _defaultKeepAlive: true,
app_1 | useChunkedEncodingByDefault: false,
app_1 | sendDate: false,
app_1 | _removedConnection: false,
app_1 | _removedContLen: false,
app_1 | _removedTE: false,
app_1 | _contentLength: 0,
app_1 | _hasBody: true,
app_1 | _trailer: '',
app_1 | finished: true,
app_1 | _headerSent: true,
app_1 | _closed: false,
app_1 | socket: [Socket],
app_1 | _header: 'GET undefined/en/horn HTTP/1.1\r\n' +
app_1 | 'Accept: application/json, text/plain, /\r\n' +
app_1 | 'User-Agent: axios/0.21.4\r\n' +
app_1 | 'Host: localhost\r\n' +
app_1 | 'Connection: close\r\n' +
app_1 | '\r\n',
app_1 | _keepAliveTimeout: 0,
app_1 | _onPendingData: [Function: nop],
app_1 | agent: [Agent],
app_1 | socketPath: undefined,
app_1 | method: 'GET',
app_1 | maxHeaderSize: undefined,
app_1 | insecureHTTPParser: undefined,
app_1 | path: 'undefined/en/horn',
app_1 | _ended: false,
app_1 | res: null,
app_1 | aborted: false,
app_1 | timeoutCb: null,
app_1 | upgradeOrConnect: false,
app_1 | parser: null,
app_1 | maxHeadersCount: null,
app_1 | reusedSocket: false,
app_1 | host: 'localhost',
app_1 | protocol: 'http:',
app_1 | _redirectable: [Circular *1],
app_1 | [Symbol(kCapture)]: false,
app_1 | [Symbol(kNeedDrain)]: false,
app_1 | [Symbol(corked)]: 0,
app_1 | [Symbol(kOutHeaders)]: [Object: null prototype]
app_1 | },
app_1 | _currentUrl: 'http:undefined/en/horn',
app_1 | [Symbol(kCapture)]: false
app_1 | },
app_1 | response: undefined,
app_1 | isAxiosError: true,
app_1 | toJSON: [Function: toJSON]
app_1 | }
app_1 |
app_1 | at GetWords (src/controllers/WordController.js:14:21)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.