I have a GenericDB class to interface with Firestore, I want to extend this class to work with multiple collections:
export default class GenericDB {
constructor(collectionPath) {
this.collectionPath = collectionPath
}
/**
* Create a document in the collection
* #param data
* #param id
*/
async create(data, id = null) {
const collectionRef = (await DB()).collection(this.collectionPath)
const serverTimestamp = firebase.firestore.FieldValue.serverTimestamp()
const dataToCreate = {
...data,
createTimestamp: serverTimestamp,
updateTimestamp: serverTimestamp
}
const createPromise = isNil(id)
? // Create doc with generated id
collectionRef.add(dataToCreate).then(doc => doc.id)
: // Create doc with custom id
collectionRef
.doc(id)
.set(dataToCreate)
.then(() => id)
const docId = await createPromise
return {
id: docId,
...data,
createTimestamp: new Date(),
updateTimestamp: new Date()
}
}
}
However, when I extend the GenericDB class to another class, I can not call the methods in the GenericDB class.
import GenericDB from './generic-db'
export default class OpenHouseDB extends GenericDB {
constructor(userId) {
super(`open-houses/${userId}/properties`)
}
test() {
// I can call this function successfully
console.log('test worked')
}
}
Trying to call the create function defined in the GenericDB class which is inherited by the OpenHouseDB class produces the following error:
TypeError: Object(...) is not a function
async setup({ commit, rootState }, property) {
try {
const { uid } = rootState.user
const openHouseDb = new OpenHouseDB(uid)
const { mlsId } = property
openHouseDb.test()
const createdOpenHouse = await openHouseDb.create(property, mlsId)
console.log(createdOpenHouse)
} catch (err) {
console.log(err)
}
}
I've omitted some code but I've confirmed that calling openHouseDb.test() in the above code does successfully console log the correct string. I'm not sure why calling openHouseDb.create(property, mlsId) produces TypeError: Object(...) is not a function. I've confirmed that openHouseDb does have a create method but I can't figure out how to call it.
Related
I am not getting any clue how to mock a method. I have to write a unit test for this function:
index.ts
export async function getTenantExemptionNotes(platform: string) {
return Promise.all([(await getCosmosDbInstance()).getNotes(platform)])
.then(([notes]) => {
return notes;
})
.catch((error) => {
return Promise.reject(error);
});
}
api/CosmosDBAccess.ts
import { Container, CosmosClient, SqlQuerySpec } from "#azure/cosmos";
import { cosmosdbConfig } from "config/Config";
import { Workload } from "config/PlatformConfig";
import { fetchSecret } from "./FetchSecrets";
export class CosmoDbAccess {
private static instance: CosmoDbAccess;
private container: Container;
private constructor(client: CosmosClient) {
this.container = client
.database(cosmosdbConfig.database)
.container(cosmosdbConfig.container);
}
static async getInstance() {
if (!CosmoDbAccess.instance) {
try {
const connectionString = await fetchSecret(
"CosmosDbConnectionString"
);
const client: CosmosClient = new CosmosClient(connectionString);
// Deleting to avoid error: Refused to set unsafe header "user-agent"
delete client["clientContext"].globalEndpointManager.options
.defaultHeaders["User-Agent"];
CosmoDbAccess.instance = new CosmoDbAccess(client);
return CosmoDbAccess.instance;
} catch (error) {
// todo - send to app insights
}
}
return CosmoDbAccess.instance;
}
public async getAllNotesForLastSixMonths() {
const querySpec: SqlQuerySpec = {
// Getting data from past 6 months
query: `SELECT * FROM c
WHERE (udf.convertToDate(c["Date"]) > DateTimeAdd("MM", -6, GetCurrentDateTime()))
AND c.IsArchived != true
ORDER BY c.Date DESC`,
parameters: [],
};
const query = this.container.items.query(querySpec);
const response = await query.fetchAll();
return response.resources;
}
}
export const getCosmosDbInstance = async () => {
const cosmosdb = await CosmoDbAccess.getInstance();
return cosmosdb;
};
index.test.ts
describe("getExemptionNotes()", () => {
beforeEach(() => {
jest.resetAllMocks();
});
it("makes a network call to getKustoResponse which posts to axios and returns what axios returns", async () => {
const mockNotes = [
{
},
];
const cosmosDBInstance = jest
.spyOn(CosmoDbAccess, "getInstance")
.mockReturnValue(Promise.resolve(CosmoDbAccess.instance));
const kustoResponseSpy = jest
.spyOn(CosmoDbAccess.prototype, "getAllNotesForLastSixMonths")
.mockReturnValue(Promise.resolve([mockNotes]));
const actual = await getExemptionNotes();
expect(kustoResponseSpy).toHaveBeenCalledTimes(1);
expect(actual).toEqual(mockNotes);
});
});
I am not able to get instance of CosmosDB or spyOn just the getAllNotesForLastSixMonths method. Please help me code it or give hints. The complexity is because the class is singleton or the methods are static and private
I was using qraphql (JavaScript graphql-request library) in a project and ran into a typeError. Here's the code:
import { request, gql } from 'graphql-request'
const graphqlAPI = process.env.NEXT_PUBLIC_GRAPHCMS_ENDPOINT
export const getPosts = async () => {
const query = gql`
query MyQuery {
postsConnection {
edges {
node {
author {
bio
name
id
photo {
url
}
}
createdAt
slug
title
excerpt
featuredImage {
url
}
categories {
name
slug
}
}
}
}
}
`
const result = await request(graphqlAPI, query)
return result.postsConnection.edges
}
The error said there was a problem with the document parameter of the request.
Never Mind, its because the Next_endpoint wasnt defined, all good now!
2 Errors:
The method which you have used here to fetch the data is outdated.
The endpoint here is missing you will find it in the graphcms in your account : settings/access/api access /endpoints
Remove the command
const graphqlAPI = process.env.NEXT_PUBLIC_GRAPHCMS_ENDPOINT
and the .env file associated with it.
After that use the following code:
import { gql } from 'graphql-request';
import { GraphQLClient } from 'graphql-request';
export const getPosts = async () => {
// new endpoint
const graphQLClient = new GraphQLClient(
endpoint // here add your endpoint
);
const query = gql`
query MyQuery {
postsConnection {
edges {
node {
author {
bio
name
id
photo {
url
}
}
createdAt
slug
title
excerpt
featuredImage {
url
}
categories {
name
slug
}
}
}
}
}
`
const result = await graphQLClient.request(query)
return result.PostsConnection;
}
In JavaScript, how to do getter to object in the root level?
I mean how to create getter for this object:
const userModel = {
get() { return { foo: true, ... }; }
}
and access to it by userModel.foo; // true. the code gives me userModel.get().. which not expect what I need.
The idea is go invoke get when I access to userModel.
Is it possible to do with js?
I am using the typeorm library and I have models for example User.
typeorm is able me to use this model by using this syntax:
import { getConnection } from 'typeorm';
const b = await getConnection().getRepository(User).findOne({...})...
now I want to create UserModel that do this:
getConnection().getRepository(User)
as:
export const userModel = {
get() { return getConnection().getRepository(User) }
}
so can I use it as:
userModel.findOne({...});
And I can't just use:
export const userModel = getConnection().getRepository(User);
Because the connection is not initialized yet, so it throws an error.
Yes, it is possible using Proxy:
const getConnection = (model) => ({
getRepository: (model) => {
return { findOne: () => (model) }
}
});
const User = {
//...user model,
name: "Jonh Smith"
}
class ProxyModel {
constructor(model) {
this.model = model;
return new Proxy({}, {get: (function(target, name) {
const repo = getConnection().getRepository(this);
if(name in repo) {
return repo[name];
}
}).bind(this.model)})
}
}
const userModel = new ProxyModel(User);
console.log(userModel.findOne());
Make sure you define getter properly:
const userModel = {
get foo() { return { foo: true }; }
}
console.log(userModel.foo)
Im trying to extend a Mongoose Model using ES6 syntax. While I can call successfully find({}) to retrieve data from mongo database, I am not able to call save() to save data. Both are executed inside the Model.
The error returned is Error: TypeError: this.save is not a function
const mongoose = require('mongoose')
const {Schema, Model} = mongoose
const PersonSchema = new Schema(
{
name: { type: String, required: true, maxlength: 1000 }
},
{ timestamps: { createdAt: 'created_at', updatedAt: 'update_at' } }
)
class PersonClass extends Model {
static getAll() {
return this.find({})
}
static insert(name) {
this.name = 'testName'
return this.save()
}
}
PersonSchema.loadClass(PersonClass);
let Person = mongoose.model('Persons', PersonSchema); // is this even necessary?
(async () => {
try {
let result = await Person.getAll() // Works!
console.log(result)
let result2 = await Person.insert() // FAILS
console.log(result2)
} catch (err) {
throw new Error(err)
}
})()
Im using:
Nodejs 7.10
mongoose 5.3.15
This is normal. You're trying to access a non static method from a static method.
You need to do something like this:
static insert(name) {
const instance = new this();
instance.name = 'testName'
return instance.save()
}
Some working example:
class Model {
save(){
console.log("saving...");
return this;
}
}
class SomeModel extends Model {
static insert(name){
const instance = new this();
instance.name = name;
return instance.save();
}
}
const res = SomeModel.insert("some name");
console.log(res.name);
Here is an example of what works and what doesn't work.
class SomeParentClass {
static saveStatic(){
console.log("static saving...");
}
save(){
console.log("saving...");
}
}
class SomeClass extends SomeParentClass {
static funcStatic(){
this.saveStatic();
}
func(){
this.save();
}
static funcStaticFail(){
this.save();
}
}
//works
SomeClass.funcStatic();
//works
const sc = new SomeClass();
sc.func();
//fails.. this is what you're trying to do.
SomeClass.funcStaticFail();
I'm new to typescript and am not understanding this error that I am getting. I have route where I am pulling in a class called Article like so:
import { Request, Response } from "express";
const appRoot = require("app-root-path");
import { Article } from "./newsArticleModel";
const connection = require(appRoot + "/src/config/connection.ts");
const sql = require("mssql");
async function getNewsData() {
const pool = await connection;
const result = await pool.request()
.input("StoryID", sql.Int, 154147)
.execute("procedure");
console.log(result, "the result from the stored procedure");
return result;
}
sql.on("error", (err) => {
console.log("the error", err);
});
export let index = async(req: Request, res: Response) => {
try {
let articles = await getNewsData();
articles = Article.transformArticles(articles.recordset);
articles = JSON.stringify(articles);
res.render("home", {
articles,
title: "Home",
});
} catch (e) {
console.log(e, "teh error");
}
};
in the second line of the try above, I get the following error: Property 'transformArticles' does not exist on type 'typeof Article'. What does this mean? This is what my Article class looks like:
const appRoot = require("app-root-path");
import { TransformedRow } from "./transformedRowInterface";
export class Article {
transformArticles(articles) {
return articles.map((article) => {
return this.transformRows(article);
});
}
transformRows(row) {
const transformedRow: TransformedRow = {
id: row.StoryID,
title: row.Title,
summary: row.Summary,
body: row.Body,
synopsis: row.Synopsis,
author: {
name: row.AuthorName,
email: row.AuthorEmail,
},
impressions: row.ImpressionCount,
created: row.CreatedDate,
updated: row.UpdatedDate,
};
return transformedRow;
}
}
If you want to call:
Articles.transformArticles(...);
You need to make the method static:
export class Article {
static transformArticles(articles) {
Or, if you don't want it to be static, create an instance of Article
const article = new Article();
article.transformArticles(...);