## 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) );
});
/* 2023-04-26 */
https://www.sitepoint.com/community/t/best-way-to-use-if-else-in-a-promise-chain/414101/8
/* 2023-04-25 */
// https://stackoverflow.com/questions/24928846/get-return-value-from-settimeout
( (delay) => { return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(Math.floor(Math.random() * 2) ); /* returns a zero or a one BETTER WAY SEE SITEPOINT FORUM */
}, delay);
});
})(1500)
.then( (done) => { return ( ‘==>>’ + done )
})
.then( (last) => console.log(last) )
;
/* 2023-01-12a – async.await chaining */
const asyncFunction = (timeIn) => {
return new Promise( (resolve, reject) => {
setTimeout(() => {
resolve(++timeIn);
}, timeIn * 1000);
});
}
(async (value) => {
console.log(‘starting with: ‘, value);
const firstResult = await asyncFunction(value);
const secondResult = await asyncFunction(firstResult);
console.log(‘ending with:’, secondResult);
})(1);
/* 2023-01-12 – async-await chaining */
async function asyncCounterFunction(counter) {
return ++counter;
}
(async (initialData) => {
const firstTime = await asyncCounterFunction(initialData);
const secondTime = await asyncCounterFunction(firstTime);
const thirdTime = await asyncCounterFunction(secondTime)
console.info(await asyncCounterFunction(thirdTime))
console.log(‘Completion!’);
})(1)
async function testFunction(initialData) {
const firstTime = await asyncCounterFunction(initialData);
const secondTime = await asyncCounterFunction(firstTime);
const thirdTime = await asyncCounterFunction(secondTime)
console.info(await asyncCounterFunction(thirdTime))
console.log(‘Completion!’);
}
testFunction(1);
async function asyncCounterFunction(counter) {
try {
return ++counter;
} catch(e) { console.error(e)
}
}
/* 2023-01-10 – added async-await instead */
const myFunction = async (seconds) => { await setTimeout( () => { console.info(seconds, “done!”); }, seconds) } ; myFunction(2000) ;
/* one liner */
( async (seconds) => { await setTimeout( () => { console.info(seconds, “done!”); }, seconds) } )(2000)
/* old ugly way */
async function newFunction(seconds) { await setTimeout( () => { console.info(seconds, “done!”); }, seconds) } ; newFunction(2000) ;
==================================================================================
<<< leave this on top, fast & crude way to flatten out a promise! >>>
(async () => { try { let result = await feathersApp.logout(); console.log(‘the result is: ‘ + result) } catch (e) { console.log(e); } } ) () ;
(async () => let logoutResult = await feathersApp.logout(); console.log(logoutResult); })().catch(e => { console.log(e) });
===========================================================================================
2022-03-25:
const firstPromise = (promiseInput) => {
return new Promise( (resolve, reject) => { // long version
console.log(promiseInput);
let returnStuff = promiseInput + ‘ – parameter passed into first promise. ‘ ;
setTimeout( () => {
console.log (‘waiting a half-second, resolving: ‘ + returnStuff);
resolve (returnStuff);
},500 );
// we could use the “reject” function if this promise failed!
})
}
// shorter version per “windbeneathmywings”
const secondPromise = (promiseInput) => new Promise( (resolve, reject) => {
console.log(promiseInput);
let returnStuff = promiseInput + ‘ – parameter passed into second promise. ‘ ;
setTimeout( () => {
console.log (‘waiting a half-second, resolving: ‘ + returnStuff);
resolve (returnStuff);
},500 );
})
const thirdPromise = (promiseInput) => new Promise( (resolve, reject) => {
console.log(promiseInput);
let returnStuff = promiseInput + ‘ – parameter passed into third promise. ‘ ;
setTimeout( () => {
console.log (‘waiting a half-second, resolving: ‘ + returnStuff);
resolve (returnStuff);
},500 );
})
firstPromise(‘one’)
.then( value => { return secondPromise (value + ‘ two’) }) // long version
.then( value => thirdPromise (value + ‘ three’) ) // shorter version per “windbeneathmywings”
.then( value => console.log(’ FINAL result: ‘ + value) )
.catch( error => { console.log(’ ERROR! ‘ + error ) })
;
=================================================================================
// ======================================================
// ** 2021-09-14 10:47 AM return promise(dot)then example **
const promiseA = (parm) => {
return new Promise( (resolve, reject) => {
setTimeout( () => {
resolve(“promise-A “ + parm);
}, 1000 );
});
}
const promiseB = (parm) => {
return new Promise( (resolve, reject) => {
setTimeout( () => {
resolve(“promise-B “ + parm);
}, 2000 );
});
}
const promiseC = (parm) => {
return new Promise( (resolve, reject) => {
setTimeout( () => {
resolve(“promise-C “ + parm);
}, 3000 );
});
}
function getExample(initialParms) {
/* notice Promise-dot-then-dot-catch usage, NOT async/await usage */
// locally scoped
const results = {};
return promiseA(initialParms)
.then ( (resultA) => {
// add value to results object
results.a = resultA;
// pass result of this promise to next promise
return promiseB(resultA);
}
)
.then ( (resultB) => {
results.b = resultB;
return promiseC(resultB);
}
)
.then ( (resultC) => {
results.c = resultC;
// results object now contains all values from promise chain
return Promise.resolve(results);
}
)
.catch ( (error) => {
return Promise.reject(error);
}
)
;
}
let marksResults ; getExample(‘first parms entered’).then( (finalResults) => { marksResults = finalResults } ) ;
// =======================================================
// ** 2021-09-13 3:00 PM async/await example **
const promiseA = (parm) => { return new Promise((resolve, reject) => { setTimeout(resolve, 0500, ‘promise A ‘ + parm); }) };
const promiseB = (parm) => { return new Promise((resolve, reject) => { setTimeout(resolve, 0500, ‘promise B ‘ + parm); }) };
async function getExample(parm) {
/* notice async/await usage, not Promise-dot-then-dot-catch usage */
let resultA = await promiseA(parm);
console.log(‘first: ‘ + resultA);
// some processing
let resultB = await promiseB( parm + ‘-’ + resultA );
console.log(‘second: ‘ + resultB);
// more processing
return resultB // something using both resultA and resultB
}
let final ; getExample(‘123’).then ( (xx) => { final = xx ; } )
// =====================================================
// ** 2021-09-13 10am Promises.all example where parameters are not passed **
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
my own example of “Promises.all”:
const promise1 = new Promise((resolve, reject) => { setTimeout(resolve( ‘promise one’), 0500 ); }); // notice different way for parm!
const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 6000, ‘promise two’); });
const promise3 = new Promise((resolve, reject) => { setTimeout(resolve, 8000, ‘promise three’); });
Promise.all([promise1, promise2, promise3])
.then ((values) => { console.log(values); })
.finally((values) => { console.log(‘here!’); }) ;
// ================================================================================
Chained Promises:
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(‘foo’);
}, 300);
});
myPromise
.then(value => { return value + ‘ and bar’; })
.then(value => { return value + ‘ and bar again’; })
.then(value => { return value + ‘ and again’; })
.then(value => { return value + ‘ and again’; })
.then(value => { console.log(‘value: ‘ + value) })
.catch(err => { console.log(err) });
https://www.mariokandut.com/how-to-wait-for-multiple-promises-in-node-javascript/
How to use Promise.all
const all = Promise.all([
new Promise((resolve, reject) =>
setTimeout(() => resolve(1), 1000),
),
new Promise((resolve, reject) =>
setTimeout(() => resolve(2), 2000),
),
new Promise((resolve, reject) =>
setTimeout(() => resolve(3), 3000),
),
]).catch(err => console.log(‘Promise was rejected!’, err));
all.then(results => console.log(results)); // the output is: [1, 2, 3]
https://stackoverflow.com/questions/28250680/how-do-i-access-previous-promise-results-in-a-then-chain
A less harsh spin on “Mutable contextual state”
function getExample(){
//locally scoped
const results = {};
return promiseA(paramsA).then(function(resultA){
results.a = resultA;
return promiseB(paramsB);
}).then(function(resultB){
results.b = resultB;
return promiseC(paramsC);
}).then(function(resultC){
//Resolve with composite of all promises
return Promise.resolve(results.a + results.b + resultC);
}).catch(function(error){
return Promise.reject(error);
});
}
2023-01-26 – you can “disable” the normal security by following these instructions:
https://stackoverflow.com/questions/20294381/google-server-putty-connect-disconnected-no-supported-authentication-methods-a
https://zaedify.com/how-to-connect-to-gcp-vm-using-putty/
0 – set password for username (‘mark’)
1 – Edit the /etc/ssh/sshd_config file.
2 – Change PasswordAuthentication and ChallengeResponseAuthentication to yes.
line 70: (change “PasswordAuthentication no” to “PasswordAuthentication yes”)
??????? ChallengeResponseAuthentication too ????
3- sudo systemctl restart sshd.service ;
NOTE:
sudo vi /etc/selinux/config; and changing SELINUX=permissive will permanently lock you out!
SELINUX=enforcing appears to be required.
POSSIBLE SALVAGE: http://blog.aristadba.com/2021/03/failed-to-load-selinux-policy-freezingsolved/#:~:text=In%20the%20boot%20menu%2C%20select,system%20and%20system%20will%20restart.
.
much of this needs to be revised…. 2022-12-12
1) click name of vm instance
2) scroll down to “Network Interface” and click “default”
3) click “FIREWALLS” tab (inbetween “.STATIC INTERNALS IP ADDRESSES” and “ROUTES”)
4) either click down-arrow by “vpc-firewall-rules” or just create a new rule
5a) be sure to select “Ingress:
5b) be sure not to overlook the “0.0.0.0/0” setting for the “Source” and note trailing “/0” that must be included
UPDATE: or just include your own home IP number (webpage ssh login will no longer work)
6) UDP NOT REQUIRED some day, play with the ftp vs udp
7) naturally select which ports you want open!
IMPORTANT!
1 - set Target "Apply to All"
2 - source IP range: 0.0.0.0/0 (i always forget trailing slash-zero
3 - reboot (?)
4 - mariadb MAY need to have: (did this again 2023-05-18)
bind-address=0.0.0.0
skip-networking=0
in either /etc/my.cnf or /etc/my.cnf.d/server.cnf
https://docs.bitnami.com/virtual-machine/infrastructure/lamp/administration/connect-remotely-mariadb/
UPDATE: target tag does not seem to work, but "Apply to all" does!
I have had great difficulty getting google-vm to open a port.
my big "struggle/mistake" was the name of the network "target" - it should be "Apply to all".
This value should either be "Apply to all" (or MAYBE specify the name of the google-vm??)
this article is very comprehensive
https://docs.bitnami.com/google/faq/administration/use-firewall/
it proves a little "tricky" to get to the network area:
this is where it HAS to say "Apply to all": (i never did get the target-name working!)
EASY PORT TEST!
ON SERVER:
ls -l | ncat --listen 10000 ; ## this simple example will pass the results of the "ls" command out port 10000 then exit.
ON CLIENT:
telnet 10.128.15.223 10000; ## this client command should display the directory contents then exit.
ncat examples
To display open server ports:
netstat --listening --numeric --tcp --udp; ## displays open ports
netstat --listening --numeric --tcp --udp; ## displays open ports (deprecated)
EDIT: 2021-10-14
i forgot about the "target" and to set 0.0.0.0/0