I'm trying to learn how to use firestore and I can't solve this error when trying to add a client:
(I'm using Next.Js, Typescript and Firebase 8.8.0)
TypeError: this._delegate.toFirestore is not a function
return client;
} else {
const docRef = await this.collection().add(client);
| ^
const doc = await docRef.get();
return doc.data() as Client;
}
I tried to use Firebase V9 but got the same error.
If I add clients collection manually in firebase page I get this error:
TypeError: this._delegate.fromFirestore is not a function
async showAll(): Promise<Client[]> {
const query = await this.collection().get()
return query.docs.map((doc: any) => doc.data()) ?? [];
^
}
My code:
import ClientRepository from "../../core/ClientRepository";
import Client from "../../core/Clients";
import firebase from "../config";
export default class ClientCollection implements ClientRepository {
#converter: any = {
toFireStore(client: Client) {
return {
name: client.name,
taxId: client.taxId,
ie: client.ie,
zipCode: client.zipCode,
state: client.state,
city: client.city,
district: client.district,
street: client.street,
number: client.number,
};
},
fromFireStore(snapshot: firebase.firestore.QueryDocumentSnapshot, options: firebase.firestore.SnapshotOptions): Client {
const data = snapshot.data(options);
return new Client(
data.name,
data.taxId,
data.ie,
data.zipCode,
data.state,
data.city,
data.district,
data.street,
data.number,
snapshot.id
);
},
};
private collection() {
return firebase.firestore().collection("clients").withConverter(this.#converter);
}
async save(client: Client): Promise<Client> {
if (client?.id) {
await this.collection().doc(client.id).set(client);
return client;
} else {
const docRef = await this.collection().add(client);
const doc = await docRef.get();
return doc.data() as Client;
}
}
async delete(client: Client): Promise<void> {
return this.collection().doc(client.id).delete();
}
async showAll(): Promise<Client[]> {
const query = await this.collection().get()
return query.docs.map((doc: any) => doc.data()) ?? [];
}
}
Im havving trouble building an express api in TS node.
Im new at express and im learning Node, JS and TS since 2022 so im sorry if the question is not to complex.
The thing is that im tryng to build a class Controller that handles the needed instructions for every route in my express router.
And im passing through the constructor a DAO that ive builded to access the firebase firestore database.
But when i instanciate the object and i try to run it Gives me the cannot read properties of undefined error.
Even when ive found a solution by using a clousure i want to learn how to do this using classes
Here it is the code of the DAO
import { setDoc, doc, getDocs, collection, query, where, deleteDoc } from 'firebase/firestore'
import { getStorage, ref, uploadBytes, getDownloadURL } from 'firebase/storage'
import { DataResponse, GenericItem } from '../types'
import { DAO } from '../clases/abstractClasses'
import { v4 } from 'uuid'
import db from '../config/firebase'
// import fs from 'fs/promises'
const fs = require('fs').promises
const storage = getStorage()
export class DataResponseClass implements DataResponse {
data: GenericItem[]
status: number
statusText: string
err: string
ok: boolean
constructor (data: GenericItem[], status: number, statusText: string, err: string, ok: boolean) {
this.data = data
this.status = status
this.statusText = statusText
this.err = err
this.ok = ok
}
}
export class DbManager extends DAO {
constructor (collectionRef: string) {
super(collectionRef)
}
async addItem (item: GenericItem): Promise<DataResponse> {
const id = v4()
console.log(id, typeof id)
return await setDoc(doc(db, this.collectionRef, id), { ...item, id }).then(res => {
return new DataResponseClass([{ ...item, id }], 201, 'Item added successfully', '', true)
}).catch(err => {
return new DataResponseClass([item], 400, "Couldn't add item", err.toString(), false)
})
}
async getAll (): Promise<DataResponse> {
return await getDocs(collection(db, this.collectionRef)).then(response => {
const dataArray: any = []
response.forEach(item => dataArray.push(item.data()))
return new DataResponseClass(dataArray, 200, 'Information obtained', '', true)
}).catch(err => new DataResponseClass([], 400, 'Couldnt Retrieve data', err.toString(), false))
}
async getById (passedId: string): Promise<DataResponse> {
const q = query(collection(db, this.collectionRef), where('id', '==', passedId))
return await getDocs(q)
.then(res => {
const dataArray: any[] = []
res.forEach(item => {
dataArray.push(item.data())
})
if (dataArray.length === 0) throw new Error('No data found for the id')
return new DataResponseClass(dataArray, 200, 'Information obtained', '', true)
})
.catch(err => new DataResponseClass([], 400, 'Couldnt Retrieve data', err.toString(), false))
}
async updateById (id: string, item: GenericItem): Promise<DataResponse> {
return await setDoc(doc(db, this.collectionRef, id), item)
.then(() => new DataResponseClass([{ ...item, id }], 200, 'Item succesifuly updated', '', true))
.catch(err => new DataResponseClass([], 400, 'Couldnt update item', err.toString(), false))
}
async deleteByid (id: string): Promise<DataResponse> {
return await deleteDoc(doc(db, this.collectionRef, id))
.then(() => new DataResponseClass([], 200, 'Success deleting a document', '', true))
.catch(err => new DataResponseClass([], 400, 'Couldnt Delete data', err, false))
}
async upLoadFile (file: Express.Multer.File | undefined): Promise<string> {
if (file !== undefined) {
const buffer = await fs.readFile(file.path).then()
const reference = ref(storage, `/${this.collectionRef}/${file.filename}`)
try {
await uploadBytes(reference, buffer)
return await getDownloadURL(reference)
} catch (err: any) {
console.log(err)
return 'There was an error uploading the file'
}
}
return 'No file was uploaded'
}
}
And this is the Controller class code..
import colors from 'colors'
import { Request, Response } from 'express'
import { DbManager, DataResponseClass } from '../services/firebase'
import fs from 'fs/promises'
export class Controller {
protected readonly dbManager: DbManager
constructor (collection: string) {
this.dbManager = new DbManager(collection)
}
async readData (req: Request, res: Response): Promise<void> {
const id: string = req.params.id
if (id !== undefined) {
res.send(await this.dbManager.getById(id))
} else {
res.send(await this.dbManager.getAll())
}
}
async createData (req: Request, res: Response): Promise<void> {
if (req.file !== undefined) {
const uploadedFilePath = await this.dbManager.upLoadFile(req.file)
.then((response: any) => {
console.log(`${response}/${req.file?.filename || ' '}`)
if (req.file?.path !== undefined) {
fs.unlink(req.file.path).then(() => console.log('Upload Complete')).catch(err => console.log(err))
}
return `${response}`
})
.catch((err: any) => {
console.log(err)
res.send(false)
})
const data = { ...req.body, images: uploadedFilePath }
console.log(colors.bgRed.white(data))
res.send(await this.dbManager.addItem({ ...req.body, images: uploadedFilePath }))
} else res.send(new DataResponseClass([], 400, 'Invalid Request no image uploaded', 'Invalid Request no image uploaded', false))
}
async editData (req: Request, res: Response): Promise<void> {
const { id } = req.params
if (req.file !== undefined) {
const uploadedFilePath = await this.dbManager.upLoadFile(req.file)
.then((response: any) => {
if (req.file?.path !== undefined) {
fs.unlink(req.file.path).then(() => console.log('Upload Complete')).catch(err => console.log(err))
}
return `${response}`
})
.catch((err: { toString: () => string }) => {
console.log(err)
res.send(new DataResponseClass([], 400, 'Imposible to upload the file', err.toString(), false))
})
res.send(await this.dbManager.updateById(id, { ...req.body, images: uploadedFilePath }))
} else res.send(new DataResponseClass([], 400, 'Invalid Request no image uploaded', 'Invalid Request no image uploaded', false))
}
async deleteData (req: Request, res: Response): Promise<void> {
const { id } = req.params
if (id !== undefined) {
res.send(await this.dbManager.deleteByid(id))
} else res.send(new DataResponseClass([], 400, 'Invalid Request no id', 'Invalid Request no id', false))
}
}
Thanks for your time Im tryng to learn this beautifull world that is the backend development
Ive tryed to call the constructor outside the class and pass the constant to the constructor
Ive tryed to instanciate the DAO object as a param,Ive even called the dao constructor in a global variable and defined the properti taking value from it .
But the only solution ive found for my issue es transforming the class into a clousure function and calling the constructor in the body of the closure
TypeError: Cannot read properties of undefined (reading 'dbManager')
at /run/media/adrianabadin/code/dcsbackend/src/controllers/controllerClass.ts:20:27
at Generator.next (<anonymous>)
at /run/media/adrianabadin/code/dcsbackend/src/controllers/controllerClass.ts:8:71
at new Promise (<anonymous>)
at __awaiter (/run/media/adrianabadin/code/dcsbackend/src/controllers/controllerClass.ts:4:12)
at readData (/run/media/adrianabadin/code/dcsbackend/src/controllers/controllerClass.ts:24:16)
at Layer.handle [as handle_request] (/run/media/adrianabadin/code/dcsbackend/node_modules/express/lib/router/layer.js:95:5)
at next (/run/media/adrianabadin/code/dcsbackend/node_modules/express/lib/router/route.js:144:13)
at Route.dispatch (/run/media/adrianabadin/code/dcsbackend/node_modules/express/lib/router/route.js:114:3)
at Layer.handle [as handle_request] (/run/media/adrianabadin/code/dcsbackend/node_modules/express/lib/router/layer.js:95:5)
[ERROR] 16:55:20 TypeError: Cannot read properties of undefined (reading 'dbManager')
Routes
Here I call the method readData
import { Router } from 'express'
import { Controller } from '../controllers/controllerClass'
// import { Validation } from '../services/validation'
import { upload } from '../config/multer'
const router = Router()
// const { validate } = new Validation('welcome')
const { readData, createData, editData, deleteData } = new Controller('welcome')
router.get('/', readData)
router.get('/:id', readData)
router.post('/', upload.single('images'), createData)
router.put('/:id', upload.single('images'), editData)
router.delete('/:id', deleteData)
export default router
const { readData, createData, editData, deleteData } = new Controller('welcome')
You can't destructure normally declared instance methods from classes.
I'm going to vastly simplify this to this example:
class Foo {
private data = 123
getData() { return this.data }
}
Now if you call getData like so, it works:
const foo = new Foo()
console.log(foo.getData())
// 123
But if you destructure the method:
const { getData } = new Foo()
console.log(getData())
// Cannot read properties of undefined (reading 'data')
Then it crashes.
The value of this is being lost because you don't call it with a ., which is what provides the class instance to the function.
Now let's try this one:
class Foo {
private data = 123
getData = () => { return this.data }
}
const foo = new Foo()
console.log(foo.getData())
// 123
const { getData } = new Foo()
console.log(getData())
// 123
This works because typescript compiles property assignments in classes to happen in the constructor, and because the arrow function => captures the value of this from when it was declared. So now you can break off the method and it works.
Just note that while the traditional instance method declaration is shared between all instances, this arrow function method will create a new function for every instance. This may hurt performance if you plan to create a very large number of instances. But for backend service classes like this that's probably not a concern.
So in your case just call the method on the instance:
const controller = new Controller('welcome')
router.get('/', (req, res) => controller.readData(req, res))
Or you declare your method as a arrow function.
export class Controller {
//...
readData = async (req: Request, res: Response): Promise<void> => {
const id: string = req.params.id
if (id !== undefined) {
res.send(await this.dbManager.getById(id))
} else {
res.send(await this.dbManager.getAll())
}
}
//...
}
const { readData } = new Controller()
readData() // fine now
I'm new to Graphql and Typescript.
My aim is to unit test Graphql resolvers with Easygraphql-tester. But I'm facing the following error.
TypeError: easygraphql_tester_1.EasyGraphQLTester is not a constructor
Following is my code:
import {EasyGraphQLTester} from "easygraphql-tester";
const schema = `
type FamilyInfo {
id: ID!
isLocal: Boolean!
}
type Query {
getFamilyInfoByIsLocal(isLocal: Boolean!): FamilyInfo
}
`
const query: any = `
query TEST($isLocal: Boolean!) {
getFamilyInfoByIsLocal(isLocal: $isLocal) {
id
isLocal
}
}
`
function getFamilyInfoByIsLocal(__, args, ctx) {
return {
id: 1,
isLocal: args.isLocal
}
}
const resolvers: any = {
Query: {
getFamilyInfoByIsLocal
}
}
const tester = new EasyGraphQLTester(schema, resolvers);
tester.graphql(query, undefined, undefined, { isLocal: false})
.then((result: any) => console.log(result))
.catch((err: any) => console.log(err));
Any idea why I'm facing the constructor error?
The problem lies is in way of importing. As there are no Type Definitions for this package. See Here
const EasyGraphQLTester = require('easygraphql-tester')
I want to inject a provider (window.ethereum) that can make ethers.js web3.js work into the flutter WebView
Now I have implemented the first version, but it doesn't work and can't be recognized by ethers.js or Web3.js
Here is my code
enum RpcMethods {
eth_requestAccounts = "eth_requestAccounts",
}
interface RequestArguments {
method: RpcMethods;
params?: unknown[] | object;
}
function _request({ method, params }: RequestArguments): Promise<any> {
return _sendToFlutter(method, params);
}
function _connect({ method, params }: RequestArguments): Promise<any> {
return _sendToFlutter(method, params);
}
function _disconnect({ method, params }: RequestArguments): Promise<any> {
return _sendToFlutter(method, params);
}
function _isConnected({ method, params }: RequestArguments): Promise<any> {
return _sendToFlutter(method, params);
}
function _sendToFlutter(rpcMethod: RpcMethods, params?: any) {
return (<any>globalThis).flutter_inappwebview.callHandler(rpcMethod, params);
}
(<any>globalThis).ethereum = {
request: _request,
connect: _connect,
disconnect: _disconnect,
isConnected: _isConnected,
};
Call Contract
const callContract = async () => {
const contract = new ethers.Contract(
"0x27998293A37A0662389487214d1cF37E1B319fe3",
"Contract Abis",
new ethers.providers.Web3Provider((window as any).ethereum, {
name: "ETD",
chainId: 3101,
}).getSigner()
);
const res = await contract.functions.getRecentTokens();
alert(JSON.stringify(res));
}
error message:
Uncaught (in promise) TypeError: Cannot read property 'length' of null
My code looks like this:
interface MutationProps {
username: string;
Mutation: any;
}
export const UseCustomMutation: React.FC<MutationProps> | any = (username: any, Mutation: DocumentNode ) => {
const [functionForDoingAction, { data, loading, error }] = useMutation(
Mutation,
{
variables: {
username,
},
}
);
useEffect(() => {
// fn trigger for change data
functionForDoingAction({
variables: {
username: username,
},
});
console.log(JSON.stringify(data));
console.log(JSON.stringify(error, null, 2));
}, []);
if (loading) return "loading...";
if (error) return `Submission error! ${error.message}`;
return data;
};
export const DisplayUser = () => {
const GET_USER = gql`
mutation GetUser($username: String!) {
getUser(username: $username) {
pfp
username
password
age
CurrentLive
ismod
description
fullname
}
}
`;
const { username }: { username: any } = useParams();
const MyData = UseCustomMutation(username, GET_USER);
console.log(JSON.stringify(MyData));
I wanna a access MyData.pfp but it gives me this error:
TypeError: Cannot read property 'pfp' of undefined
if it matters when i go on e.g. localhost:3000/user/dakepake variable MyData looks like this:
UserProfile.tsx:39 {"getUser":{"pfp":""https://i.pinimg.com/564x/65/25/a0/6525a08f1df98a2e3a545fe2ace4be47.jpg"","username":""dakepake"","password":""mohikanac10"","age":14,"CurrentLive":"""","ismod":false,"description":""this user dont have a bio yet"","fullname":""damjan alimpic"","__typename":"GetUserResponse"}}
How can I fix this?
i fixed this on my own , i just replaced MyData.pfp whit MyData.getUser.pfp and now its working