Sequelize create not a function? - javascript

I am trying to use model.create and it's saying that model.create is not a function. I googled around and couldn't seem to find any rmesolutions. Please note that I'm using es6 imports / exports in node via babel.
model.js
'use strict';
export default (sequelize, DataTypes) => {
let attachments = sequelize.define('attachments', {
type: DataTypes.STRING,
category: DataTypes.STRING,
value: DataTypes.STRING,
}, {});
attachments.associate = (models) => {
};
return attachments;
};
controller
import attachments from '../../../models/attachments'
import to_attachments from '../../../models/to_attachments'
import AWSService from '../../utils/awsS3Api'
export async function createPhoto(ctx) {
...
try {
let attachment = await attachments.create({
type: 'image',
category: imageCategory,
value: data.location
});
..etc
What am I doing wrong?

If you declare model via function:
export default (sequelize, DataTypes) => {
...
};
Then you should import it with sequelize.import
const Attachment = sequelize.import('../../../models/attachments')
export async function createPhoto(ctx) {
const attachment = await Attachment.create({
type: 'image',
category: imageCategory,
value: data.location
});
}
P.S. Some recommendations
1) Name model variables with capital letter you deal with static classes.
const user = await User.findById(123)
const users = await User.findAll({where: {id: [1,2,3]}})
2) Singular not Users but User.

Related

How can I test the function called inside another function in Nestjs?

i am writing test functions in nestjs and i am new to this task.
I mostly had problems with typeorm. but my current problem is that I do not call the paginate function in the PaginateLib class inside the function I wrote in the service. I tested the userList function directly before, but it gave paginate undefined error. Now I used mock and paginate function in test. it still gives undefined error.
Here's my admin.service code
public async userList(page, limit): Promise<any> {
const opt = {
relations: ['userInfo'],
};
const userData = await this.paginateLib.paginate(
getRepository(Users),
opt,
page,
limit,
);
return userData;
}
Here's Paginate function code in PaginateLib class. I'm cutting this short as I don't think it's very necessary.
export class PaginateLib {
async paginate(repo, opt, page, limit) {
try {
page = Number(page);
limit = Number(limit);
const items = (Number(page) - 1) * Number(limit);
const [data, count] = await repo.findAndCount({
...opt,
skip: Number(items),
take: Number(limit),
});
if (count <= items) {
return [];
}
and here's my test code
class PaginateMock {
paginate(repo: any, opt: any, page: number, limit: number) {
return [];
}
}
describe('AdminService', () => {
let service: AdminService;
let connection: Connection;
let module: TestingModule;
let services: PaginateLib;
beforeAll(async () => {
const ApiServiceProvider = {
provide: PaginateLib,
useClass: PaginateMock,
},
module = await Test.createTestingModule({
imports: [
TypeOrmModule.forRoot({
type: '****',
host: '****',
port: ****,
username: '****',
password: '****',
database: '****',
entities: [__dirname + '/../../**/*.entity.ts'],
synchronize: true,
}),
],
providers: [
AdminService,
ApiServiceProvider,
],
}).compile();
service = module.get<AdminService>(AdminService);
services = module.get<PaginateLib>(PaginateLib);
});
// afterAll(async () => {
// await module.close();
// });
describe('User Info', () => {
it('should be get user list', async () => {
const paginateSpy = jest.spyOn(services, 'paginate');
expect(paginateSpy).toHaveBeenCalled();
expect(true).toBe(service.userList(1, 1));
});
});
});
I tried different things many times. but the error I get is undefined. what should I do? Is there anyone have an idea?thank you
Try this:
describe('User Info', () => {
it('should be get user list', async () => {
const paginateSpy = jest.spyOn(services, 'paginate');
const userData = await service.userList(1, 1);
expect(paginateSpy).toHaveBeenCalled();
expect(userData).toBe(); // Don't know what userData actually looks like. So this is up to you
});
});

How do I update a foreign key (belongsTo) in Sequelize

I have the following model:
'use strict';
const {Model} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Key extends Model {
static associate(models) {
Key.belongsTo(models.User, {
foreignKey: 'userId',
onDelete: 'CASCADE'
});
}
};
Key.init({
keyType: DataTypes.STRING,
key: DataTypes.JSON
}, {
sequelize,
modelName: 'Key',
});
return Key;
};
I then try to create a row, after receiving userId, keyType and key:
...
const Key = KeyModel(sequelize, Sequelize);
const createKey = async (userid, keyType, key) => {
const result = await Key.create({userId, keyType, key});
return result;
}
The row gets created successfully in the DB, and i get back an ID (the createdAt and updatedAt are updated as well), but the userId is null.
How should I pass it to the create method so the value gets to the DB? Am I missing something in the model?
PS: the DB is MySQL 8.
I think you should change your code like below.
'use strict';
const {Model} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Key extends Model {
static associate(models) {
Key.belongsTo(models.User, {
foreignKey: 'keyId',
targetKey: 'userId'
onDelete: 'CASCADE'
});
}
};
Key.init({
keyId: DataTypes.STRING,
keyType: DataTypes.STRING,
key: DataTypes.JSON
}, {
sequelize,
modelName: 'Key',
});
return Key;
};
const Key = KeyModel(sequelize, Sequelize);
const createKey = async (userId, keyType, key) => {
const result = await Key.create({keyId: userId, keyType, key});
return result;
}

Can't get Graphql-tools to read my schema.graphql file

I am using Apollo-server-express and Graphql-tools. I have been all over the Graphql-tools documentation and I can't get this to work. I'm trying to get my schema.graphql file to import as my typeDefs. It seems like Graphql-tools should be making this easy, but something isn't falling into place.
index.js
const { ApolloServer } = require("apollo-server-express");
const { makeExecutableSchema } = require('#graphql-tools/schema');
const express = require("express");
const { join } = require("path");
const { loadSchema } = require("#graphql-tools/load");
const { GraphQLFileLoader } = require("#graphql-tools/graphql-file-loader");
const { addResolversToSchema } = require("#graphql-tools/schema");
const app = express();
const resolvers = {
Query: {
items: (parent, args, ctx, info) => {
return ctx.prisma.item.findMany();
},
},
Mutation: {
makeItem: (parent, args, context, info) => {
const newItem = context.prisma.item.create({
data: {
...args,
price: parseInt(Math.ceil(args.price * 100)),
},
});
return newItem;
},
deleteItem: (parent, args, context, info) => {
return context.prisma.item.delete({
where: {
id: args.id,
},
});
},
},
};
const schemaSource = loadSchemaSync(join(__dirname, "schema.graphql"), {
loaders: [new GraphQLFileLoader()],
});
const schema = makeExecutableSchema({
typeDefs: schemaSource,
resolvers,
});
const server = new ApolloServer({
schema,
resolvers,
});
server.applyMiddleware({ app });
app.listen(
{ port: 4000 },
() =>
console.log(
`🌎 => Backend server is now running on port http://localhost:4000`
)
);
schema.graphql
type Query {
items: [Item!]!
}
type Mutation {
makeItem(
piece: String!
image: String!
identifier: String!
price: Float!
itemNumber: Int!
): Item!
deleteItem(id: ID!): Item!
}
type Item {
id: ID!
piece: String!
image: String!
identifier: String!
price: Int!
itemNumber: Int!
}
In its current state I am getting an error that says: "Error: typeDefs must be a string, array or schema AST, got object"
As I understand it makeExecutableSchema should be doing all the necessary steps, like changing the schema into a string. I can't seem to figure out what is going on here and any help would be greatly appreciated.
loadSchemaSync will load a GraphQLSchema object using the provided pointer. You should use loadTypedefsSync instead.
const sources = loadTypedefsSync(join(__dirname, "schema.graphql"), {
loaders: [new GraphQLFileLoader()],
});
const typeDefs = sources.map(source => source.document)
const server = new ApolloServer({ typeDefs, resolvers })
If you want to use loadSchema, you don't need to use makeExecutableSchema because your schema has already been created. So you would do this instead as shown in the docs:
const schema = loadSchemaSync(join(__dirname, "schema.graphql"), {
loaders: [new GraphQLFileLoader()],
});
const resolvers = {...};
const schemaWithResolvers = addResolversToSchema({
schema,
resolvers,
});
const server = new ApolloServer({ schema: schemaWithResolvers })

Problem with with ES2020 dynamic import()

I'm parsing all the modules in a directory, initialise them, and finally export them. The modules in question are knex models like this one:
// schema/users.js
import createModel from './common'
const name = 'User'
const tableName = 'users'
const selectableProps = ['userId', 'name', 'email', 'updated_at', 'created_at']
export default knex => {
const model = createModel({
knex,
name,
tableName,
selectableProps,
})
return { ...model }
}
Each of the model definitions is extended with common parts:
// schema/common.js
export default ({
knex = {},
name = 'name',
tableName = 'tablename',
selectableProps = [],
timeout = 1000,
}) => {
const findAll = () =>
knex
.select(selectableProps)
.from(tableName)
.timeout(timeout)
return {
name,
tableName,
selectableProps,
timeout,
findAll,
}
}
Finally, all models are initialised and exported:
// schema/index.js
import { readdir } from 'fs'
import { promisify } from 'util'
import { default as knex } from '../db'
let modules = {}
export default new Promise(async $export => {
const readFileAsync = promisify(readdir)
const getModels = async dir => await readFileAsync(dir)
const files = await getModels(__dirname)
for await (const file of files) {
if (file !== 'common.js' && file !== 'index.js') {
let mod = await import(__dirname + '/' + file).then(m => m.default(knex))
modules[mod.name] = mod
}
}
await $export(modules)
console.log(modules)
})
The above seem to be working but I'm not able to figure out how to import one of these modules from another file. I'm trying to do something along the lines of:
const User = async () => await import('../schema') // not working
or
const User = (async () => await import('../schema'))() // not working
Any help with this will be appreciated!

How to mongoose model based on dynamic schema passed as parameter?

I am new on mongoose and for expressjs
I want to retrieve a collection based on the doc and model.
I have multiple schema that inherits a common schema.
const extendSchema = (schema: mongoose.Schema<any>, definition: any): Schema<any> => {
return new mongoose.Schema({ ...schema.obj, ...definition, ...{ strict: false }});
};
const CommonSchema = new mongoose.Schema({ ... });
const OtherSchema = extendSchema(CommonSchema, { ... });
const OtherOtherSchema = extendSchema(CommonSchema, { ... });
Then, I want to retrieve the collection from the mongoose
const getCollectionObject = (collection: string, schema: Schema) => {
return collection.model(collection, schema);
};
// get the first collection
export const getOtherCollection = async (name: string, id: string) => {
try {
const model = getCollectionObject(name, OtherSchema);
const document = await model.findById(mongoose.Types.ObjectId(id)).lean();
return document;
} catch (error) {
return error;
}
};
// get the second collection
export const getOtherOtherCollection = async (name: string, id: string) => {
try {
const model = getCollectionObject(name, OtherOtherSchema);
const document = await model.findById(mongoose.Types.ObjectId(id)).lean();
return document;
} catch (error) {
return error;
}
};
I've got an error below
Is it possible?
Thank you in advance!
PS: I've already saw other posts which the solution is to make the properties optional.
This solved my issue.
Create a common schema plus the other schema
const CommonSchema = new mongoose.Schema({ ... });
const OtherSchema = { ... };
const OtherOtherSchema = { ... };
Then, I declared my based model.
const Base = mongoose.model('collection-name', CommonSchema);
Next, I created my other models based on the base model using discriminator
const OtherModel = Base.discriminator("Other", new mongoose.Schema(OtherSchema));
const OtherOtherModel = Base.discriminator("OtherOther", new mongoose.Schema(OtherOtherSchema));
You can now use the model on any scoped function, you may export it if you want to.
Other.create({ ... });
Other.findById()
OtherOther.create();
OtherOther.findById();
please let me know if this right approach
or you have any other suggestions
Thanks!

Categories

Resources