• Knex is a query builder for JavaScript that allows developers to build SQL queries using a fluent and intuitive interface. It supports multiple database systems such as Postgres, MSSQL, MySQL, MariaDB, SQLite3, Oracle, and Amazon Redshift. In addition to query building, Knex also provides features for database migrations, making it easy to create and modify database tables using JavaScript code instead of raw SQL scripts. Knex is a powerful tool for managing database operations and simplifying database interactions in JavaScript applications.

    To add Knex to your Node.js project, you can follow these steps.

    Install dependencies:

    yarn add knex

    Make sure to install the driver that corresponds to your database of choice. Knex supports multiple database systems, such as Postgres, MSSQL, MySQL, MariaDB, SQLite3, Oracle, and Amazon Redshift. In my case I will use SQLite3.

    yarn add sqlite3

    Init the configuration

    Once you have Knex and the database driver installed, you can start using Knex in your project. You’ll typically need to configure Knex to connect to your database. Create a knexfile.js file in your project’s root directory, and define the necessary configurations based on your environment settings.

    knex init 

    It will create the following knexfile.js

    module.exports = {
    
      development: {
        client: 'sqlite3',
        connection: {
          filename: './dev.sqlite3'
        },
        debug: true
      },
    
      staging: {
        client: 'postgresql',
        connection: {
          database: 'my_db',
          user:     'username',
          password: 'password'
        },
        pool: {
          min: 2,
          max: 10
        },
        migrations: {
          tableName: 'knex_migrations'
        }
      },
    
      production: {
        client: 'postgresql',
        connection: {
          database: 'my_db',
          user:     'username',
          password: 'password'
        },
        pool: {
          min: 2,
          max: 10
        },
        migrations: {
          tableName: 'knex_migrations'
        }
      }
    
    };
    

    Let’s create now our first script with next to run a DB migration

    npx knex migrate:make create_table_users

    As a good practice, create small tasks instead of one task with all the schema. This is useful to detect problems. For example, avoid creating all the init schema in one task, create one task per table and even create another separate task for constraints such as foreign keys

    Use descriptive names such as “create_table_users”. Use also prefix for your actions such as “create_table_…” or “create_column_…”

    Result:

    migrations/20211005153317_create_table_users.js

    Open the file and paste this:

    exports.up = function(knex) {
        return knex.schema.createTable("users", (tb) => {
            tb.increments("id");
            tb.string("username", 100).notNullable();
            tb.string("email", 100).notNullable();
            tb.string("password", 100).notNullable();
        });
    };
    
    exports.down = function(knex) {
        return knex.schema.dropTable("users");
    };
    

    Save it and run:

    knex migrate:latest

    Or select a different environment:

    knex migrate:latest --env production    

    Handy commands:

    npx knex migrate:latest # To run all pending migrations
    npx knex migrate:up # To run the next pending migration
    npx knex migrate:down # To roll back the most recent migration
    npx knex migrate:list # To show current state of migrations.

    Knex is a query builder among other things and it’s an awesome tool to run DB migrations to create tables and modify them as you usually do with SQL scripts.

    That’s it! You have successfully added Knex to your Node.js project. Remember to refer to the Knex documentation for more details on how to use Knex for various database operations.

    You can find more information about Knex on its official website at https://knexjs.org.

  • How to reset unify from factory defaults

  • First of all download the controller, a desktop app to discover the device since there’s not a default wifi name like others devices such as Tp-Link.

    For MacOS download from here


    There are also controllers for Windows and Debian/Ubuntu
  • Install the controller like any other desktop app
  • Press the reset button in under the the device
  • If you haven’t done, connect your device to the network
  • Once you open the controller, your device should be discovered automatically
  • Select it and click on next
  • Follow the wizard until you configuration is done
  • Then access the dashboard from the browser: https://localhost:8443/manage/site/default/dashboard or open the controller application.







    Photo by Jordan Harrison on Unsplash

  • https://jsonplaceholder.typicode.com

    Example

          
    fetch('https://jsonplaceholder.typicode.com/todos/1')
      .then(response => response.json())
      .then(json => console.log(json))
          
        

    Output

          
    {
      id: 1,
      title: '...',
      body: '...',
      userId: 1
    }
          
        

    Photo by Kai Wenzel on Unsplash

  • Overview

    Prettier is a code formatter that supports many languages and can be integrated with most of the editors.

    Also, you can integrate it with your CI/CD.

    That why nobody will be able to merge to the master branch if the code is not well-formatted.

    With Prettier you will be able to define your own rules, however default rules are enough at the beginning.

    Your rules will be defined in a file called .prettierrc placed in your project’s root.

    Let’s see how to install Prettier and then make some configurations.

          
    npm install prettier --save-dev
      
        

    Example of Prettier config file

          
    {
      "trailingComma": "es5",
      "tabWidth": 4,
      "printWidth": 120,
      "semi": true,
      "singleQuote": false,
      "useTabs": false,
      "quoteProps": "as-needed",
      "jsxSingleQuote": false,
      "bracketSpacing": false,
      "jsxBracketSameLine": true,
      "arrowParens": "avoid",
      "requirePragma": false,
      "insertPragma": false,
      "proseWrap": "preserve",
      "endOfLine": "lf"
      }
      
        

    See more options for the .prettierrc file

    Gulp integration

          
    npm install gulp-prettier -save-dev
      
        
          
    gulp.task("prettier", () => {
      return gulp
      .src("./**/*.js")
      .pipe(prettier(".prettierrc"))
      .pipe(gulp.dest("./"));
    });
      
        

    PhpStorm IDE integration

    If you are using PHP Storm, it’s highly recommended that you configure your IDE to auto-format your code every time you save a .js file

    https://prettier.io/docs/en/webstorm.html
    The plugin will take the rules from you .prettierrc file

    Configure a File Watcher in PhpStorm to auto-format the code on save.

    Visual Studio Code

    You can install the extension as any other and then you can use these configurations in you settings.js with the prefix “prettier”

          
    {
      "prettier.useTabs": false,
      "prettier.trailingComma": "es5",
      "prettier.tabWidth": 4,
      "prettier.printWidth": 120,
      "prettier.semi": true,
      "prettier.singleQuote": false,
      "prettier.quoteProps": "as-needed",
      "prettier.jsxSingleQuote": false,
      "prettier.bracketSpacing": false,
      "prettier.jsxBracketSameLine": true,
      "prettier.arrowParens": "avoid",
      "prettier.proseWrap": "preserve",
      "prettier.endOfLine": "lf"
    }
      
        
  • About flexsearch package

    flexsearch It’s an awesome package to index in-memory data. You can use it to implement justa. search box in your site or to show related data with the content you are displaying

    How to install it

          
    yarn add flexsearch
          
        

    Or

          
    npm install flexsearch
          
        

    Example

          
    const { Index } = require("flexsearch");
    
    const options = {
        charset: "latin:extra",
        preset: 'match',
        tokenize: 'strict',
        cache: false
    }
    const index = new Index(options);
    
    // my collection
    const recipes = [
        {id:1, title: 'Orange cake'},
        {id:2, title: 'New York-Style Bacon Egg and Cheese Sandwich'},
        {id:3, title: 'Bacon Wrapped Cheese Stuffed Meatloaf'},
        {id:4, title: 'French Yogurt Cake'},
        {id:5, title: 'Gougeres (French Cheese Puffs)'},
        {id:6, title: 'Authentic Brazilian Cheese Bread (Pão de Queijo)'},
        {id:7, title: 'Camarão na Moranga (Brazilian Shrimp Stuffed Pumpkin)'},
        {id:8, title: 'Parmesan Cheese Muffins'},
        {id:9, title: 'Cookie Dough Stuffed Oreos'},
    ]
    
    // index my collection
    recipes.forEach((recipe) =>{
        index.add(recipe.id, recipe.title)
    })
    
    
    // search (it will return an array of ids)
    const ids = index.search('Cookie', 5);
    console.debug(ids);
    // based on the ids returned by the index, look for the recipes for those ids
    const result = recipes.filter((recipe) => ids.includes(recipe.id));
    console.debug(result);
    
    
          
        

    Execution output

          
    [ 9, 1, 4, 6 ]
    [
      { id: 1, title: 'Orange cake' },
      { id: 4, title: 'French Yogurt Cake' },
      { id: 6, title: 'Authentic Brazilian Cheese Bread (Pão de Queijo)' },
      { id: 9, title: 'Cookie Dough Stuffed Oreos' }
    ]
    
          
        

    Photo by Daniel Lerman on Unsplash

  • Convert date:

    =DATE(2021,9,1)

    Count business days:

    =NETWORKDAYS(DATE(2021,9,1), DATE(2021,9,30))

    Count business hours:

    =MULTIPLY(NETWORKDAYS(DATE(2021,9,1), DATE(2021,9,30)),8)

    Photo by Annie Spratt on Unsplash

  • Why should you load your images in a lazy way?

    Among other reasons:

    • Increase page speed
    • Better page rank
    • More visitors
    • Reduce bounce rate
    • Increase pages / session rate
    • Improve user experience
    • Reduce infrastructure costs

    In a nutshell

    This is the process:

    • Modify all your tags by changing src by data-src or something else
    • Add a specific class to every image we want to load lazily.
    • Add a listener to know when the image is being displayed
    • Once the image is displayed, the listener will call our code to modify our image tag
    • The code will get the url from data-src and will update the src property.
    • The image will be loaded by the browser
    • Call the listener after the page loads

    Straight to the point

    I will use a third-party library called lozad. It’s pretty small and it loads super fast so it won’t have a big impact in your page loading.

    From Lozad docs:

    “Highly performant, light and configurable lazy loader in pure JS with no dependencies for images, iframes and more, using IntersectionObserver API”

    Include the script via CDN in your head tag of your page

    
    
    https://cdn.jsdelivr.net/npm/lozad/dist/lozad.min.js
    
    

    Unfortunately, you cannot use async property here since the script must be loaded before the page loads.

    Add this code in your page

    
    
    <script type="text/javascript">
      // I assume you are using jQuery. Otherwise you can use the classic way
      $(document).ready(() => {
        // to load images in a lazy way
        // lazy loads elements with default selector as '.lozad'
        const observer = lozad();
        observer.observe();
        console.info('lozad observing...');
      });
    </script>
    
    

    Of course you can move this code to a different script file (let say common.js) instead of your page.
    You only have to make sure that your file common.js is downloaded and ready to use before lozad call:

    
    const observer = lozad();
    observer.observe();
    
    

    The last step is to modify all your images you want to load lazily.

    Before:

    
    <img src="image.jpg" class="yourClass" alt="your image description" />
    
    

    After:

    
    <img data-src="image.jpg" class="lozad yourClass" alt="your image description" />
    
    

    You can see more options here https://apoorv.pro/lozad.js/

    It’s important you add alt=”your image description” because that text will be displayed while the image is loading. This will give a better user experience to your visitors.

    Demo

    Resources

    Photo by elizabeth lies on Unsplash

  • You are trying to log in through an instance URL (example: sandbox) and you do this.

          
    sfdx auth:web:login -a myusername@myorg.sandbox --instanceurl=https://mysandbox-domain.lightning.force.com
    
    

    And you get this error in console:

    In your browser you get this

    image

    The problem is you are using lightning.force.com domain instead of my.salesforce.com

          
    sfdx auth:web:login -a myusername@myorg.sandbox --instanceurl=https://mysandbox-domain.my.salesforce.com
    
    

  •       
    sfdx force:source:deploy -x manifest/package.xml -l RunLocalTests --checkonly
          
        
          
    *** Deploying with SOAP API ***
    Deploy ID: 0Bf7D000003ygUYWBY
    SOURCE PROGRESS | █████████████████████████████████░░░░░░░ | 92/111 Components
    
    === Component Failures [0]
    Type  Name  Problem
    ────  ────  ───────
    
    
    === Test Results Summary
    Passing: 30
    Failing: 17
    Total: 47
    Time: 0
    ERROR running force:source:deploy:  Deploy failed.
          
        
          
    sfdx force:source:deploy:report -i 0Bf7D000003ygUYWBY  --json > deploy.log
          
        

    Open deploy.log and look for the node “runTestResult” and then “failures”.

    Example:

          
     "failures": [
              {
                "id": "01p0W000003fXQIQA2",
                "message": "System.DmlException: Insert failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Validation Formula [THE COMPLETE ERROR HERE] ",
                "methodName": "myUnitTest",
                "name": "MyApexClass",
                },
                "packageName": "MyApexClass",
                "stackTrace": "MyApexClass myUnitTest: line 38, column 1",
                "time": "1927.0",
                "type": "Class"
              }, 
             {
                   (...)
             }
        ]
          
        

    Photo by Siora Photography on Unsplash