Complete FeathersJs SQL Raw Query

Oct 8, 09:54 AM

## Feathers Knex Raw Sql Examples 2022-11-10

(cross-referenced in https://github.com/edwardsmarkf/comptonTransAnlys-conversion/blob/main/raw-feathers-example)

0) Install feathers if not already done

 
    npm install @feathersjs/feathers --save ;

1) Initialize new feathers environment

     npm init --yes ; 
     npm install   knex     feathers-knex ;
 

2) create a username/password:

    DROP USER IF EXISTS ‘knexUser’@‘localhost’                              ;
    CREATE USER ‘knexUser’@‘localhost’ IDENTIFIED BY ‘knexPassword’;

    GRANT ALL ON `comptonTransAnlys`.* TO ‘knexUser’@‘localhost’                    
    IDENTIFIED BY ‘knexPassword’ WITH MAX_QUERIES_PER_HOUR 0                
    MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0                ;

    GRANT ALL PRIVILEGES ON `comptonTransAnlys`.* TO ‘knexUser’@‘localhost’ ;

    # to test:
    # mariadb  —host=localhost —user=knexUser  —password=knexPassword    comptonTransAnlys    ;

3) Create feather application

 feathers generate app ;   ## probably select "n" for security, which can be created later

4) Create default Knex service

    ****** !!Only required if this is a NEW app, otherwise skip this entire step!! ******
feathers generate  service ;            ###  create type "knex" named  "knex-raw-init" and MariaDb"

4a) edit knex-raw-init.model.js

should look like this:
module.exports = function (app) {
  return app.get('knexClient');
};
its possible AFTER generating other calls that this file can (should?) be deleted

4b) move (or delete) directory

 mv  ./src/services/initialize-knex/  ./src/services/knex-raw-init-UNUSED/ ;
        ##  -- or   --
       tar -zcvf    knex-raw-init.gz   ./src/services/knex-raw-init/ ;
       ##   -- or/and  --
       rm -Rf    ./src/services/knex-raw-init/ ;

4c) change index.js file

vi ./src/services/index.js ; COMMENT OUT:
    //    const initializeKnex = require('./initialize-knex/initialize-knex.service.js');
   //     app.configure(knexInitialize);

4e) modify ./config/default.json to reflect the database access

(or answer this in the “generate service” prompt)
        'connection': 'mysql://knexUser:knexPassword@localhost:3306/comptonTransAnlys'
                  -- or  --
      "mysql": {
          "client": "mysql2",
          "connection":
              { "host"      : "localhost"
              , "port"      : 3306
              , "user"      : "knexUser"
              , "password"  : "knexPassword"
              , "database"  : "comptonTransAnlys"
              }
          }

5) Create our custom service!

 feathers  generate service ;  ##    create custom service named "my-custom-service"     

5a) change my-custom-service.class.js file

./src/services/my-custom-service/my-custom-service.class.js :
    /* eslint-disable no-unused-vars */
    const { QueryTypes } = require(‘feathers-knex’);     // new line!!

    exports.MyCustomService = class MyCustomService {
        constructor (options, app) {                     //  formerly just  constructor(options)
            this.options = options || {};
            this.app = app;                                    // new line!
        }

        async find (key) {                         /* note the default is “params” you may need to change this */
             /*   Postman GET:  http://123.123.123.123:3030/my-custom-service/?one=twooo
                         notice /?one=twoooo   – last slash between service name and question mark is OPTIONAL!
             */
            console.info(JSON.stringify(key.query) + ‘ in my find routine!!’);
            const knexClient = this.app.get(‘knexClient’);
                //  const rows = await knexClient.raw(‘SELECT VERSION;’);

                           //  https://knexjs.org/guide/raw.html#raw-parameter-binding  ::
                           //   Positional bindings ? are interpreted as values and ?? are interpreted as identifiers.
            const sqlStatement = ‘SELECT variable_value  FROM information_schema.global_variables WHERE ?? = ?;’  ;
            const rows = await knexClient.raw( sqlStatement, [‘VARIABLE_NAME’, ‘VERSION’]);

// should execute this: SELECT variable_value FROM information_schema.global_variables where variable_name = ‘VERSION’ ;

console.table (rows); return `${JSON.stringify(key.query) + JSON.stringify(rows)} find routine!!`; } async get (key) { /* Postman GET: http://123.123.123.123:3030/my-custom-service/123456789 notice /123456789 – only ONE parameter as a suffix */ console.info(JSON.stringify(key) + ‘ in get routine!!’); const knexClient = this.app.get(‘knexClient’); const mariaDbDate = await knexClient.raw(‘SELECT CURDATE ;’ ); console.table(mariaDbDate); return `${JSON.stringify(key) + JSON.stringify(mariaDbDate)} get routine!`; } };

6) stop firewall if necessary

systemctl stop firewalld  ; 

7) Start the app

run    DEBUG=*    npm start ;
run    DEBUG=knex:query  npm start ;

8) either postman or browser do:

    http://123.123.123.123:3030/my-custom-service/1234    # get
    http://123.123.123.123:3030/my-custom-service/?one=twoooooo  # find

Optionally include parameters

     /*  named variables, please notice    DOUBLE-COLON does backticks while SINGLE-COLON does quote characters!  */
const sqlStatement = 'SELECT variable_value  FROM information_schema.global_variables WHERE :var_name: = :val ;'  ;
const sqlQuery = { var_name:  'VARIABLE_NAME' , val: 'VERSION' }  ;
const rows = await knexClient.raw( sqlStatement, sqlQuery);

#########################################################################

easier to just generate…. to many steps to get this working.

4X) Create initial raw init model file (????)

mkdir  --parent   ./src/models/  ;  // just in case this does not exist yet.
cat <<END   >  ./src/models/INIT-KNEX-RAW.model.js;
module.exports = function (app) {
  return app.get('knexClient');
};
END

###############################################################################

## S E Q U E L I Z E:

0) npm install sequelize

1) create sequelize CUSTOM SERVICE named: “my-custom-service”

2) edit ./src/sequelize.js change logging false to logging true

3) change: src/services/my-custom-service/my-custom-service.class.js :

/* eslint-disable no-unused-vars */
const { QueryTypes } = require(‘sequelize’);

exports.MyCustomService = class MyCustomService { constructor (options, app) { this.options = options || {}; this.app = app; }

async find (key) { const sequelize = this.app.get(‘sequelizeClient’); const stimwordPositionSelectFind = ‘SELECT * FROM stimwordPosition WHERE 1 AND stimwordPositionWord = $stimwordPositionWord;’ ; const stimwordPositionSelectParms = { ‘stimwordPositionWord’ : JSON.parse(key.query).stimwordPositionWord } ; const rows = await sequelize.query ( stimwordPositionSelectFind , { ‘bind’ : stimwordPositionSelectParms } ); return rows; }
};

################################ browser-console:

in browser console (common initial setup for all examples)

[you may need to visit the “about:blank” webpage — 2022-22-21 ]

first visit http://123.123.123.123:3030/ to “initialize” chrome

[ ‘//cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js’
, ‘//unpkg.com/@feathersjs/client@^3.0.0/dist/feathers.js’
].forEach( (src) => { let script = document.createElement(‘script’); script.src = src; script.async = false; document.head.appendChild(script);
});
const app = feathers(); const socket = io(); app.configure(feathers.socketio(socket));

// optional if trying to run on another http[s] webpage rather than at http://123.123.123.123:3030:

const socket = io.connect ( ’35.192.14.166:3030’ , { ‘path’ : ‘/socket.io/’ , ‘port’ : ‘3030’ , ‘hostname’ : ’35.192.14.166’ , ‘secure’ : false } );

// socket.io.engine.transport

async function stimwordPositionFind(param) { console.log( ‘param: ‘ + param); let getResult = await app.service(‘my-custom-service’).find(param); console.log(‘stimwordPosition function: ‘ + JSON.stringify(getResult) ); return getResult;
};
let stimwordPositionResult = null;
let key = { ‘query’ : { ‘stimwordWord’ : ‘horse’, ‘parm2’ : ‘answer2’ } } ;
stimwordPositionFind(key).then( value => { /* get(GET) */ stimwordPositionResult = value; console.log(‘stimwordPosition(’ + key + ‘) : ‘ + JSON.stringify(stimwordPositionResult) );
});

async function stimwordPosition(id) { /* get(GET) (just one by index) */ console.log( ‘id: ‘ + id); let getResult = await app.service(‘my-custom-service’).find(id); console.log(‘stimwordPosition function: ‘ + JSON.stringify(getResult) ); return getResult;
};

############ GET GET GET GET GET GET

async get (id) { const sequelize = this.app.get(‘sequelizeClient’); const stimwordPositionSelectGet = `SELECT * FROM stimwordPosition WHERE 1 AND stimwordPositionAutoIncr = ${id};`; const rows = await sequelize.query(stimwordPositionSelectGet); return rows; }

async function stimwordPosition(id) { /* get(GET) (just one by index) */ console.log( ‘id: ‘ + id); let getResult = await app.service(‘my-custom-service’).get(id); console.log(‘stimwordPosition function: ‘ + JSON.stringify(getResult) ); return getResult;
};
let stimwordPositionResult = null; let key = 1; // assuming your row ID is one
stimwordPosition(key).then( value => { /* get(GET) */ stimwordPositionResult = value; console.log(‘stimwordPosition(’ + key + ‘) : ‘ + JSON.stringify(stimwordPositionResult) );
});
#####################################################

let stimwordPositionResult = null; let key = 1; // assuming your row ID is one
stimwordPosition(key).then( value => { /* get(GET) */ stimwordPositionResult = value; console.log(‘stimwordPosition(’ + key + ‘) : ‘ + JSON.stringify(stimwordPositionResult) );
});

/notice object starting with “query” for the find: let stimwordPositionResult = null; let key = { ‘query’ : ‘horse’ } ; // assuming your row ID is one stimwordPositionFind(key).then( value => { /* get(GET) */ stimwordPositionResult = value; console.log(‘stimwordPosition(’ + key + ‘) : ‘ + JSON.stringify(stimwordPositionResult) ); });
Mark Edwards

,

---

Commenting is closed for this article.

---