Objection.js - Query builder not a function using insert method - javascript

I'm new to nodejs Development and I currently practicing CRUD operations on my postgresql. I used Objection.js for the ORM and Model making. I follow some codes from the docs and edit necessary lines but I don't actually get it to success instead it returns this error:
builder.knex(...).queryBuilder is not a function
I am following MVC pattern so I seperate the files according to it.
My controller:
'use strict';
const Todo = require('./../models/Todo');
class TodoController {
createTodo() {
Todo
.query()
.insert({
'title': 'asdasdasda',
'description': 'sdasdasdasdasdsad',
'date': '2017-12-12',
'isActive': true,
})
.then(name => {
console.log(name.description);
})
.catch(err => {
console.log(err);
});
}
}
module.exports = TodoController;
Knex Schema:
knex.schema.createTableIfNotExists('todo', (table) => {
table.increments();
table.string('title', 255).notNullable();
table.text('description').notNullable();
table.boolean('isActive').defaultTo('false');
table.datetime('date').notNullable();
table.timestamp('createdAt').defaultTo(knex.fn.now());
})
Model:
'use strict';
const { Model } = require('objection');
class Todo extends Model {
static get tableName() {
return 'Todo';
}
}
module.exports = Todo;
server.js:
...
const KnexConfig = require('./knexfile');
const { Model } = require('objection');
...
...
Model.knex(KnexConfig.development);
Hopefully someone could guide me, I'm still newbie on nodejs

It looks like you're trying to pass the knex configuration object to Model.knex() whereas you need to pass the actual knex instance.
On server.js:
const { Model } = require('objection');
const knex = require('knex');
const KnexConfig = require('./knexfile');
Model.knex(knex(KnexConfig.development));
This error message seems to arise whenever the knex instance passed to Objection.js is not what is should be.

Related

How to fix Error: No valid exports main found for ‘web-application/node_modules/uuid'?

I am trying to create a second data-access-layer for my web-app using sequelize. I get this error when i require the module 'sequelize'.
I have tried to change the node version to 4 different ones but still i do not get rid of the error.
const Sequelize = require('sequelize') // the error occur here
const sequelize = new Sequelize('sqlite::memory:')
//this is how i register the awilix container
container.register({
SQLiteDb: awilix.asValue(require('./data-access-layer-sequelize/SQLiteDb'))
})
//this is how the functions are exported
module.exports = function({ SQLiteDb }){
return {
getAllPosts: function(club, callback) {
SQLiteDb.findAll({ where: { club }, raw: true })
.then(posts => callback([], posts))
.catch(error => callback(['internalError'], null))
}
}

How to properly reuse MongoDriver connection across NodeJS modules with ES6

First of all it is a similar question like How to properly reuse connection to Mongodb across NodeJs application and modules, but I guess due to the ES6 syntax it's still different.
So I decided to use MongoDriver and created a class for this like in SO answer: dbconnections.js
import { default as mongodb } from 'mongodb';
const MongoClient = mongodb.MongoClient;
const url = "myurl"
let _db;
export const connectToServer = async (callback) => {
try {
MongoClient.connect( url, { useNewUrlParser: true, useUnifiedTopology:true }, ( err, db ) => {
_db = db
return callback( err )
})
} catch (e) {
throw e
}
}
export const getDB = () => _db
export const disconnectDB = () => _db.close()
The problem with this module is, that due to the ES6 syntax is that I can't make like something this
import {getDB} from '../dbconnections.js'
const driverDB=getDB()
export const someFunction= async (req,res) => {
console.log(driverDB)
because I always get undefiened so I have to call my getter in every function.
So my question: how to create properly a structure for a MongoDriver handler and pass this to different modules with ES6?
Pass the client object into objects and functions that need it.
https://en.wikipedia.org/wiki/Dependency_injection

FindAll inside model hooks 'afterFind' not working using sequilize in nodejs

I have a project in nodejs using sequelize.
I am tring to do a FindAll inside a model but I am getting this error:
Cannot read property 'findAll' of undefined
I import the models like this:
const db = require('./index');
And in the model hooks I am trying to do this:
hooks: {
afterFind: async function(User){
let ranks_db = await db.rank.findAll({ });
// let rank = await checkRank(User.exp);
User['exp'] = {
value: User.exp,
rank
};
return User;
}
}
The findAll it is working in the controller but not in the model
. I want to know if it is posible to do a FindAll inside a model
It is likely that you have a circular dependency between your models and that db.rank has not been populated yet when the Model you are showing here is constructed. Instead of importing the models via require you can reference them from the sequelize variable that is passed into the Model.
module.exports = function Model(sequelize, DataTypes) {
return sequelize.define('user', { /* columns */ }, {
hooks: {
afterFind: async function(user) {
const ranks = await sequelize.models.rank.findAll();
// user.ranks = ranks;
},
}
});
}

Non CRUD Route in FeathersJS

I have a service results that handles all CRUD Operations for the results service in feathersjs. How would I create a route /results/:id/hr_bar_graph which basically fetches the result at that particular id and uses the resulting data to create an bar graph.
My code currently is:
module.exports = function (app) {
const Model = createModel(app);
const paginate = app.get('paginate');
const options = {
name: 'results',
Model,
paginate
};
// Initialize our service with any options it requires
app.use('/results', createService(options));
app.use('/results/:id/hr_bargraph_image', {
find(id, params){
this.app.service('results').get(id)
.then(function(response){
console.log(response);
})
.cathc(function(error){
console.log(error);
})
return Promise.resolve({
imageData: ''
});
}
});
// Get our initialized service so that we can register hooks and filters
const service = app.service('results');
service.hooks(hooks);
};
Been stuck here for a while now. Please help.
For reference, from this issue, the answer is to use params.route and Feathers normal find(params):
module.exports = function (app) {
const Model = createModel(app);
const paginate = app.get('paginate');
const options = {
name: 'results',
Model,
paginate
};
// Initialize our service with any options it requires
app.use('/results', createService(options));
app.use('/results/:id/hr_bargraph_image', {
async find(params){
const { id } = params.route;
const results = await app.service('results').get(id);
return {
imageData: ''
};
}
});
// Get our initialized service so that we can register hooks and filters
const service = app.service('results');
service.hooks(hooks);
};

How to execute GraphQL query from server

I am using graphql-express to create an endpoint where I can execute graphql queries in. Although I am using Sequelize with a SQL database it feels wrong to use it directly from the server outside of my graphql resolve functions. How do I go about querying my graphql API from the same server as it was defined in?
This is how I set up my graphql endpoint:
const express = require('express');
const router = express.Router();
const graphqlHTTP = require('express-graphql');
const gqlOptions = {
schema: require('./schema')
};
router.use('/', graphqlHTTP(gqlOptions));
modules.exports = router;
Basically what I want is to be able to do something like this:
query(`
{
user(id: ${id}) {
name
}
}
`)
How would I create this query function?
GraphQL.js itself does not require a http server to run. express-graphql is just a helper to mount the query resolver to a http endpoint.
You can pass your schema and the query to graphql, it'll return a Promise that'll resolve the query to the data.
graphql(schema, query).then(result => {
console.log(result);
});
So:
const {graphql} = require('graphql');
const schema = require('./schema');
function query (str) {
return graphql(schema, str);
}
query(`
{
user(id: ${id}) {
name
}
}
`).then(data => {
console.log(data);
})
I would like to complete the answer from #aᴍɪʀ by providing the pattern for properly doing a query / mutation with parameters:
const params = {
username: 'john',
password: 'hello, world!',
userData: {
...
}
}
query(`mutation createUser(
$username: String!,
$password: String!,
$userData: UserInput) {
createUserWithPassword(
username: $username,
password: $password,
userData: $userData) {
id
name {
familyName
givenName
}
}
}`, params)
This way, you don't have to deal with the string construction bits " or ' here and there.
Thanks for the other answers, this is for Nextjs inside getServerSideProps, getStaticProps, getStaticPaths and getStaticProps, includes context for MongoDB. Need this because if you have your graphql sever in api route, when you build it wont build because your server in api route is not running.
Mongo file: plugin/zDb/index:
import {MongoClient} from "mongodb"
export const connectToDatabase = async() => {
const client = new MongoClient(process.env.MONGODB_URI, {useNewUrlParser: true, useUnifiedTopology: true})
let cachedConnection
if(cachedConnection) return cachedConnection
try {
const connection = await client.connect()
cachedConnection = connection
return connection
} catch(error) {
console.error(error)
}
}
export const mongoServer = async() => {
const connect = await connectToDatabase()
return connect.db(process.env.DB_NAME)
}
In pages folder, eg index.js file homepage:
import {graphql} from 'graphql'
import {schema} from '#/plugin/zSchema/schema'
import {mongoServer} from '#/plugin/zDb/index'
async function query(source, variableValues) {
return graphql({schema, source, contextValue: {mongo: await mongoServer()}, variableValues})
}
export async function getServerSideProps(ctx) {
const listingCurrent = await query(`query($keyField: String, $keyValue: String) {
ListingRQlistingListKeyValue(keyField: $keyField, keyValue: $keyValue) {
address
urlSlug
imageFeature {
photoName
}
}
}`, {
keyField: 'offerStatus'
, keyValue: 'CURRENT'
})
return {props: {
listingCurrent: listingCurrent.data.ListingRQlistingListKeyValue
}
}
}
Please note: the graphql call field names is from: https://github.com/graphql/graphql-js/blob/fb27b92a5f66466fd8143efc41e1d6b9da97b1f4/src/graphql.js#L62
export type GraphQLArgs = {|
schema: GraphQLSchema,
source: string | Source,
rootValue?: mixed,
contextValue?: mixed,
variableValues?: ?ObjMap<mixed>,
operationName?: ?string,
fieldResolver?: ?GraphQLFieldResolver<any, any>,
|};
And my schema file: plugin/zSchema/schema.js
import { makeExecutableSchema } from '#graphql-tools/schema'
import {resolvers} from '#/plugin/zSchema/resolvers'
import {typeDefs} from '#/plugin/zSchema/typeDefs'
export const schema = makeExecutableSchema({resolvers, typeDefs})
The #/plugin folder: I'm using this in root file called jsconfig.json, and I put all my folders inside root/plugin, and I call it with #/plugin. You can use your own folder structure importing them as how you normally do it.
{
"compilerOptions": {
"baseUrl": "."
, "paths": {
"#/*": ["./*"]
}
}
}

Categories