complete feathers knex and CLI installation

Nov 18, 05:58 AM

1 – Initialization

latest RH node instructions
older instructions

Install Node version 16 or greater:

   dnf module enable nodejs:20 ;   ## installing version 20 in this example.
   dnf module list nodejs   ;       ## optional step!
   dnf install nodejs    ;
   node --version ;
   npm  --version ;

install the feathers command-line interpreter (CLI):

    npm   install -g feathersjs/cli  ;     ###  or    --global
    npm   install feathersjs/cli -g ;    ### for generating apps  (notice g trails…. i think only this one actually works!

    npm   install feathersjs/cli4.8.0 —global  ;     ##  2023-04-19  install a SPECIFIC VERSION!   

    npm   install @feathersjs/feathers —save  ;     ## save is no longer needed  
                                         ##https://stackoverflow.com/questions/19578796/what-is-the-save-option-for-npm-install
    export PATH=$PATH:/usr/local/bin/  ;   ## 2024-09-24 — this was required!
    which feathers ;  ##
    feathersjs  —version ; ##

Optionally disable or modify the firewall

  systemctl stop firewalld;   ## or just authorize port 3030
  ##   --or---
  firewall-cmd --add-port=3030/tcp ;.
  ##   --- or----
  firewall-cmd --add-port=3030/tcp --permanent   ;

Generate an app using the CLI

feathers generate app ;         ## notice that NO npm install's are used
npx feathers generate ;  ## apparently another method (2024-09-24
feathers generate service ;   
     ## select 'knex' or 'objection' (see below)
     ### connection string should look like this:  "mysql://knexUser:knexPassword@localhost:3306/comptonTransAnlys"
DEBUG=*                  npm start ;   ## test that app starts successfully, optional DEBUG  
DEBUG=knex:query  npm start ;

2 – modify this files

./config/default.js

  "paginate": {
    "default": 0,
    "max": 0

3a – modify these files for KNEX

./src/services/tester/tester.class.js – KNEX

    super({
      ...options,
      name: 'tableName'    		/* changed this name to reflect the ACTUAL table name */
      , id:  'tableNameAutoIncr'	      /* added this line to reflect the primary key */
    });

./src/models/tester.model.js – KNEX

	module.exports = function (app) {
	  return app.get('knexClient');  /* this is MUCH shorter than original! */
	};

3b – modify these files for OBJECTION

./src/services/tester/tester.class.js – OBJECTION

add actual table name and unique id column name
     model: Model
        ,  'name'  : 'marksTestTable'   ,   'id'  :   'marksTestTableAutoIncr'               // line added by mark!!

./src/models/tester.model.js – OBJECTION

line 8: [specify REAL table name]
     static get tableName() {
       return 'marksTestTable';       // make SURE table name is correct !!  (had to remove underscores)
    }
line 14 old: [specify column names in array]
   required: ['text'], 
line 17 new:
    required: ['columnOne', 'columnTwo'],    /* original:    required: ['text'],  */
line 17 old: [specify column types {type: ‘string’ } { type: ‘number’ } { type: ‘timestamp’} ]
    text: { type: 'string' }
line 17 new:
    'columnOne': { type: 'string' }   , 'columnTwo': { type: 'number' }    /* original:    text: { type: 'string' }  */
see: https://knexjs.org/guide/schema-builder.html#date

line 22: comment out lines: ( or add .slice(0, 19).replace(‘T’, ‘ ‘); to dates.)
    $beforeInsert() {
      /* original:    this.createdAt = this.updatedAt = new Date().toISOString();     */
           // or possibly add this:
            this.createdAt = this.updatedAt = new Date().toISOString().slice(0, 19).replace(‘T’, ‘ ‘);

    $beforeUpdate() {
      /* original:    this.updatedAt = new Date().toISOString();      */
       // or possibly add this:
        this.updatedAt = new Date().toISOString().slice(0, 19).replace(‘T’, ‘ ‘);
per https://stackoverflow.com/questions/5129624/convert-js-date-time-to-mysql-datetime

line 35: [ eliminate the ‘create table’ stuff ]
/* most likely db.schema.createTable can be SKIPPED unless a table actually needs to be created this way!   */
 const db =  app.get('knex');
 db.schema.hasTable('marksTestTable').then(exists => {
    if (!exists) {
             console.error('table marksTestTable  missing!');
                       /*
                      db.schema.createTable('shit', table => {
                        table.increments('id');
                        table.string('text');
                        table.timestamp('createdAt');
                        table.timestamp('updatedAt');
                      })
                     */
        .then(() => console.log('Created shit table')) // eslint-disable-line no-console
        .catch(e => console.error('Error creating shit table', e)); // eslint-disable-line no-console
    }
  })
    .catch(e => console.error('Error creating shit table', e)); // eslint-disable-line no-console
it should ONLY contain:
module.exports = function (app) {
  return [class name];
}

4 – Start the app


DEBUG=knex:query npm start ;   ## run the app, optional DEBUG
DEBUG=*                 npm start ;   ## run the app, optional DEBUG

5 -Test the app

DONT USE “PUT”, USE “PATCH” INSTEAD! Postman: Body—->x-www-form-url-urlencoded to POST (create)

POST: http://192.168.123.220:3030/teachers?lastName=Edwards&firstName=Lori (create)
PATCH: http://192.168.123.220:3030/teachers/2/?firstName=Marky (patch)

POST – http://192.168.123.220:3030/tester?columnOne=Column One Value&columnTwo=Column Two Value (add new value)
GET – http://192.168.123.220:3030/tester/1/ ( get by primary id)
GET – http://192.168.123.220:3030/tester/?columnOne=column One Value (find by column value)

GET (find) – be sure “Body—>xx-www-form-urlencode” is blank
GET (get) – be sure “Params” is blank
PATCH – be SURE “Params” is blank, only use “Body—>xx-www-form-urlencode”

## a complicated one!
http://192.168.123.220:3030/tester/ ? testerAutoIncr=1 & $select[]=columnTwo & $select[]=columnOne & $sort[columnOne]=-1

## will produce:
## select `columnTwo`, `columnOne`, `tester`.`testerAutoIncr` from `tester` where `testerAutoIncr` = ? order by `columnOne`

## https://stackoverflow.com/questions/11889997/how-to-send-an-array-in-url-request/11890080#11890080
## ? col0 = val1 & col1 = val2 & col2 = val3
## will produce:
## WHERE col= ‘val1’ OR col=‘val2’ OR col=‘val3’

### reference: https://dove.feathersjs.com/api/databases/querying.html#select

6 – Create a “before” hook to manipulate the SELECT statement.

feathers “before” hook: [i think that is required by Objection]

./src/hooks/tester.js

    // Use this hook to manipulate incoming or outgoing data.
    // For more information on hooks see: http://docs.feathersjs.com/api/hooks.html

    // eslint-disable-next-line no-unused-vars
    module.exports = (options = {}) => {
      return async context => {
        context.params.query = {                          // added by mark
          …context.params.query,                         // added by mark
          $select: [‘columnTwo’,‘columnOne’],       // added by mark
          $sort: { ‘columnOne’ : 1 }                        // added by mark
        }                                                                // added by mark
        return context;
      };
    };

or: (much better:) https://knexjs.org/guide/query-builder.html

module.exports = (options = {}) => {
  return async context => {

        const query = context.service.createQuery(context.params) ;

        // https://knexjs.org/guide/query-builder.html#knex
        query    .clear(‘select’)  // remove ALL existing columns from queryBuilder
                .select({ ‘languageNormsName’ : ‘languageNormsName’ } )
                        // or just  .select(‘languageNormsName’)
                .distinct()
                .orderBy(‘languageNormsName’)
                ;

        context.params.knex = query ;

    return context;
  };
};
        [i think this is required for knex (not objection]
// https://feathersjs.com/api/databases/knex.html#createquery-params
// https://knexjs.org/guide/query-builder.html#clear
// https://stackoverflow.com/questions/47263583/how-can-i-retrieve-unique-values-from-a-column-with-knex-js
                        /*  old fashioned way to clear select statements, use ` .clear('select') ` instead!
                        for ( index in query._statements.filter ( val => val['grouping'] === 'columns' ) )
                                        {  query._statements.splice(index,1)   // remove the "default" column selection
                                       } ;
                        */

==========================================================

#####################npm init —yes ;
################npm install @feathersjs/feathers —save ;
######### ???????? npm install knex —save ;
############npm install feathers-knex —save ;

Mark Edwards

,

---

Commenting is closed for this article.

---