I followed the instructions on how to generate models from an existing database as pointed here https://github.com/sequelize/sequelize-auto. However when I try to query the database using the model i get this error:
TypeError: Cannot convert undefined or null to object
at Function.keys ()
at Function.findAll (/home/jefry/node/sequelize/node_modules/sequelize/src/model.js:1755:47)
at /home/jefry/node/sequelize/src/components/users/controllers.ts:11:32
at Generator.next ()
at /home/jefry/node/sequelize/src/components/users/controllers.ts:31:71
at new Promise ()
at __awaiter (/home/jefry/node/sequelize/src/components/users/controllers.ts:27:12)
at list (/home/jefry/node/sequelize/src/components/users/controllers.ts:45:12)
at Layer.handle [as handle_request] (/home/jefry/node/sequelize/node_modules/express/lib/router/layer.js:95:5)
at next (/home/jefry/node/sequelize/node_modules/express/lib/router/route.js:144:13)
Controller*
export async function list(req: Request, res: Response) {
try {
const list = await primera.findAll();
res.json({ list });
} catch (error) {
console.log(error);
}
}
Model*
import * as Sequelize from 'sequelize';
import { DataTypes, Model, Optional } from 'sequelize';
export interface primeraAttributes {
verdad?: number;
}
export type primeraOptionalAttributes = "verdad";
export type primeraCreationAttributes = Optional<primeraAttributes, primeraOptionalAttributes>;
export class primera extends Model<primeraAttributes, primeraCreationAttributes> implements primeraAttributes {
verdad?: number;
static initModel(sequelize: Sequelize.Sequelize): typeof primera {
return primera.init({
verdad: {
type: DataTypes.BOOLEAN,
allowNull: true
}
}, {
sequelize,
tableName: 'primera',
timestamps: false
});
}
}
init-models
import type { Sequelize } from "sequelize";
import { primera as _primera } from "./primera";
import type { primeraAttributes, primeraCreationAttributes } from "./primera";
export {
_primera as primera,
};
export type {
primeraAttributes,
primeraCreationAttributes,
};
export function initModels(sequelize: Sequelize) {
const primera = _primera.initModel(sequelize);
return {
primera: primera,
};
}
You should pass at least an empty object as an argument of findAll:
const list = await primera.findAll({});
Related
Im trying to generate rest-api for Odoo - ERP whith Nestjs and odoo-xmlrpc. I can connect to odoo but i cant respose the values than odoo response to my service.
This is the odoo service that response a value or an error:
import { Injectable, OnModuleInit } from '#nestjs/common';
#Injectable()
export class OdooService {
private Odoo = require('odoo-xmlrpc');
public odoo;
constructor () {
this.odoo = new this.Odoo({
url: 'https:/www.xxxxxxxxx.xxx',
db: 'xxxx',
username: 'username',
password: 'password'
});
}
execute(model: string, funtion: string , params: any[], callback) {
const odoo = new this.Odoo({
url: 'https:/www.xxxxxxxxx.xxx',
db: 'xxxx',
username: 'username',
password: 'password'
});
odoo.connect(async function (error: any): Promise<any> {
if (error) {
console.log(error);
return [{}];
}
odoo.execute_kw(model, funtion, params, function (error: any, values: []) {
if (error) {
console.log('error :>> ', error);
return [{}];
}
callback(values);
})
})
}
}
this is the service that use the odooServive
import { Injectable } from '#nestjs/common';
import { OdooService } from '../odoo/odoo.service';
import { CreateCountryDto } from './dto/create-country.dto';
import { UpdateCountryDto } from './dto/update-country.dto';
#Injectable()
export class CountriesService {
constructor(
private odooService: OdooService
) {}
async findAll() {
return await this.odooService.execute('res.country', 'search_read', [[[]], { fields: ['name'] }], async function (response: []) {
// console.log(response);
return await response;
});
}
}
odoo documentation: https://www.odoo.com/documentation/14.0/webservices/odoo.html
library documentation: https://www.npmjs.com/package/odoo-xmlrpc
Elaborating #charlietfl's comment into an answer, you can use one of these codes, either using callback, or using async await
No Promise, no callback
findAll() {
return this.odooService.execute('res.country', 'search_read', [[[]], { fields: ['name'] }]);
}
Using callback, no need for Promise
findAll() {
this.odooService.execute('res.country', 'search_read', [[[]], { fields: ['name'] }], function (response: []) {
return response;
});
}
Using Promise
async findAll() {
const response = await this.odooService.execute('res.country', 'search_read', [[[]], { fields: ['name'] }]);
return response;
}
i try to pass a model class as parameter, but typescript doesn't see methods, properties.
import type { Model } from 'sequelize';
const isExistsValidator = (model: typeof Model, field: string) => {
return async (value): boolean => {
const result = await model.findOne({ where: { [field]: value } }); // No overload matches this call.
// ...
};
};
I have tried some variants:
import type { Model, ModelStatic } from 'sequelize';
const isExistsValidator = <M extends Model>(model: ModelStatic<M>, field: string) {
// ...
const result = await model.findOne({ where: { [field]: value } });// Property 'findOne' does not exist on type
}
import type { Model } from 'sequelize';
const isExistsValidator = (model: Model, field: string) {
// ...
const result = await model.findOne({ where: { [field]: value } });// Property 'findOne' is a static member of type 'Model<any, any>'
How it will be use (something like this):
const isExistsName = isExistsValidator(UserModel, 'name');
// ...
if(await isExistsName('alex4answer')) {
throw new Error('Name already in use');
}
What am i doing wrong?
i'm new in typescript
I am new to GraphQL and mongoose and trying to create a function in a resolver which creates a shawarma order, the inputs required are the shawarma ID, the quantity and an address, when I run the code typed below, I get an Error which states
TypeError: Cannot read property 'shawarmaOrdered' of undefined
the resolver code:
import mongoose from 'mongoose';
import AuthenticationError from 'apollo-server';
import {shawarma} from '../models/shawarmaModel';
export default {
Query:{
},
Mutation: {
createOrder: async(parent, {OrderInput}, {models: {orderModel, shawarmaModel}}, info) => {
console.log('reached1')
try{
const {shawarmaOrdered, quantity, address} = OrderInput;
const order = await orderModel.updateOne({shawarmaOrdered, quantity, address})
return order
} catch(err){
console.log('errorr')
console.log(err)
}
}
},
Order: {
shawarmaOrdered: async(parent, {shawarmaOrdered}, {models:shawarmaModel}, info) =>{
return shawarmaOrdered = shawarmaModel.find((shawarma)=>{
return shawarma.id == parent.id
})
}
}
the schema code:
import {gql} from 'apollo-server'
export default gql`
type Order{
id: ID!
shawarmaOrdered: Shawarma!
quantity: Int
orderedTo: String
}
input OrderInput{
shawarmaOrdered: ID!
quantity: Int
orderedTo: String
}
extend type Query {
order(id: ID!): Order!
}
extend type Mutation {
createOrder(shawarmaOrdered: String!, quantity: Int!, orderedTo: String!): Order!
}
`
the order model code:
import mongoose, { Mongoose } from 'mongoose'
import shawarma from './shawarmaModel'
const orderSchema = new mongoose.Schema({
shawarmaOrdered: {
type: mongoose.Schema.Types.ObjectId,
ref: shawarma
},
quantity: {
type: Number
},
completed: {
type: Boolean,
default: false
}
})
const order = mongoose.model('order', orderSchema)
export default order;
kindly let me know if I'm doing something wrong
So here's how I fixed the problem.
in the index.js file
import cors from 'cors';
import express from 'express';
import jwt from 'jsonwebtoken';
import mongoose from 'mongoose';
import { ApolloServer, AuthenticationError } from 'apollo-server-express';
import schemas from './schemas';
import resolvers from './resolvers';
import userModel from './models/userModel';
import orderModel from './models/orderModel';
import shawarmaModel from './models/shawarmaModel';
const app = express();
app.use(cors());
const getUser = async (req) => {
const token = req.headers['token'];
// console.log(token)
if (token) {
try {
return await jwt.verify(token, 'riddlemethis');
} catch (e) {
console.log(e)
throw new AuthenticationError('Your session expired. Sign in again.');
}
}
};
const server = new ApolloServer({
typeDefs: schemas,
resolvers,
context: async ({ req }) => {
if (req) {
const me = await getUser(req);
return {
me,
models: {
userModel,
orderModel, //this was where the orderModel was misspelled as OrderModel
shawarmaModel
},
};
}
},
});
server.applyMiddleware({ app, path: '/graphql' });
app.listen(5000, async () => {
await mongoose.connect('mongodbconnectionString')
});
in the code above, I have commented the section in which the error was from. Carelessly, when debugging I overlooked checking this file. my mistake. I apologise for not including this code in the original question
I want to implement method in schema class like below.
import { SchemaFactory, Schema, Prop } from '#nestjs/mongoose';
import { Document } from 'mongoose';
import bcrypt from 'bcrypt';
#Schema()
export class Auth extends Document {
#Prop({ required: true, unique: true })
username: string;
#Prop({ required: true })
password: string;
#Prop({
methods: Function,
})
async validatePassword(password: string): Promise<boolean> {
return bcrypt.compareAsync(password, this.password);
}
}
export const AuthSchema = SchemaFactory.createForClass(Auth);
this schema return undefined when log the method . How can I write method in class schema with nestjs/mongoose package?
You can use below approach to achieve this.
#Schema()
export class Auth extends Document {
...
validatePassword: Function;
}
export const AuthSchema = SchemaFactory.createForClass(Auth);
AuthSchema.methods.validatePassword = async function (password: string): Promise<boolean> {
return bcrypt.compareAsync(password, this.password);
};
Use this function instead of SchemaFactory.createForClass(Auth):
export function createSchema(document: any) {
const schema = SchemaFactory.createForClass(document);
const instance = Object.create(document.prototype);
for (const objName of Object.getOwnPropertyNames(document.prototype)) {
if (
objName != 'constructor' &&
typeof document.prototype[objName] == 'function'
) {
schema.methods[objName] = instance[objName];
}
}
return schema;
}
This is my nodejs typescript class and written jest unit test for isHealthy() public method.
Test coverage shows that this.pingCheck() then block, catch and last return statement are not covered.
Please advise.
Can we do unit test for pingCheck private method ?
This my class
import { HttpService, Injectable } from '#nestjs/common';
import { DependencyUtlilizationService } from '../dependency-utlilization/dependency-utlilization.service';
import { ComponentType } from '../enums/component-type.enum';
import { HealthStatus } from '../enums/health-status.enum';
import { ComponentHealthCheckResult } from '../interfaces/component-health-check-result.interface';
import { ApiHealthCheckOptions } from './interfaces/api-health-check-options.interface';
#Injectable()
export class ApiHealthIndicator {
private healthIndicatorResponse: {
[key: string]: ComponentHealthCheckResult;
};
constructor(
private readonly httpService: HttpService,
private readonly dependencyUtilizationService: DependencyUtlilizationService,
) {
this.healthIndicatorResponse = {};
}
private async pingCheck(api: ApiHealthCheckOptions): Promise<boolean> {
let result = this.dependencyUtilizationService.isRecentlyUsed(api.key);
if (result) {
await this.httpService.request({ url: api.url }).subscribe(() => {
return true;
});
}
return false;
}
async isHealthy(
listOfAPIs: ApiHealthCheckOptions[],
): Promise<{ [key: string]: ComponentHealthCheckResult }> {
for (const api of listOfAPIs) {
const apiHealthStatus = {
status: HealthStatus.fail,
type: ComponentType.url,
componentId: api.key,
description: `Health Status of ${api.url} is: fail`,
time: Date.now(),
output: '',
links: {},
};
await this.pingCheck(api)
.then(response => {
apiHealthStatus.status = HealthStatus.pass;
apiHealthStatus.description = `Health Status of ${api.url} is: pass`;
this.healthIndicatorResponse[api.key] = apiHealthStatus;
})
.catch(rejected => {
this.healthIndicatorResponse[api.key] = apiHealthStatus;
});
}
return this.healthIndicatorResponse;
}
}
This is my unit test code.
I get the following error when I run npm run test
(node:7876) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'status' of undefined
(node:7876) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 6)
import { HttpService } from '#nestjs/common';
import { Test, TestingModule } from '#nestjs/testing';
import { DependencyUtlilizationService } from '../dependency-utlilization/dependency-utlilization.service';
import { ApiHealthIndicator } from './api-health-indicator';
import { ApiHealthCheckOptions } from './interfaces/api-health-check-options.interface';
import { HealthStatus } from '../enums/health-status.enum';
describe('ApiHealthIndicator', () => {
let apiHealthIndicator: ApiHealthIndicator;
let httpService: HttpService;
let dependencyUtlilizationService: DependencyUtlilizationService;
let dnsList: [{ key: 'domain_api'; url: 'http://localhost:3001' }];
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
ApiHealthIndicator,
{
provide: HttpService,
useValue: new HttpService(),
},
{
provide: DependencyUtlilizationService,
useValue: new DependencyUtlilizationService(),
},
],
}).compile();
apiHealthIndicator = module.get<ApiHealthIndicator>(ApiHealthIndicator);
httpService = module.get<HttpService>(HttpService);
dependencyUtlilizationService = module.get<DependencyUtlilizationService>(
DependencyUtlilizationService,
);
});
it('should be defined', () => {
expect(apiHealthIndicator).toBeDefined();
});
it('isHealthy should return status as true when pingCheck return true', () => {
jest
.spyOn(dependencyUtlilizationService, 'isRecentlyUsed')
.mockReturnValue(true);
const result = apiHealthIndicator.isHealthy(dnsList);
result.then(response =>
expect(response['domain_api'].status).toBe(HealthStatus.pass),
);
});
it('isHealthy should return status as false when pingCheck return false', () => {
jest
.spyOn(dependencyUtlilizationService, 'isRecentlyUsed')
.mockReturnValue(false);
jest.spyOn(httpService, 'request').mockImplementation(config => {
throw new Error('could not call api');
});
const result = apiHealthIndicator.isHealthy(dnsList);
result
.then(response => {
expect(response['domain_api'].status).toBe(HealthStatus.fail);
})
.catch(reject => {
expect(reject['domain_api'].status).toBe(HealthStatus.fail);
});
});
});
Looks like you should define the status before initialize the unit test, try to grab some more logs using console.log and for the second test, added catch block to make sure you're grabing the failures