Typeorm Multiple DB Node - mysql

Hello how are you? I'm trying to connect two different databases in a project. I'm creating one mysql and one postgres, using typeorm. But I'm not able to use mysql. Does anyone know how to resolve this error?
ormconfig.json:
[
{
"name": "default",
"type": "postgres",
"port": 5432,
"host": "localhost",
"username": "admin",
"password": "admin",
"database": "first",
"migrations": [
"./src/database/migrations/firstClient/*.ts"
],
"entities": [
"./src/modules/firstClient/entities/*.ts"
],
"cli": {
"migrationsDir": "./src/database/migrations/firstClient"
}
},
{
"name": "connection2",
"type": "mysql",
"port": 3306,
"host": "localhost",
"username": "admin",
"password": "admin",
"database": "second",
"migrations": [
"./src/database/migrations/secondClient/*.ts"
],
"entities": [
"./src/modules/secondClient/entities/*.ts"
],
"cli": {
"migrationsDir": "./src/database/migrations/secondClient"
}
}
]
database/index.ts:
import { createConnections, getConnectionOptions } from 'typeorm';
getConnectionOptions().then(() => {
createConnections();
});
entities/Client.ts:
import { v4 as uuidv4 } from 'uuid';
import { Entity, PrimaryColumn, Column } from 'typeorm';
#Entity({ database: 'connection2', name: 'contacts' })
class Client {
#PrimaryColumn()
id?: string;
#Column('varchar')
name: string;
#Column('varchar')
cellphone: string;
constructor() {
if (!this.id) {
this.id = uuidv4();
}
}
}
export { Client };
and in repositories/implementations/clientReporitory I import my entity:
import { Repository, getRepository } from 'typeorm';
import { Client } from '../../entities/Client';
import { IClientsRepository, ICreateClientDTO } from '../IClientsRepository';
class ClientsRepository implements IClientsRepository {
private repository: Repository<Client>;
constructor() {
this.repository = getRepository(Client);
}
async findByCellphone(cellphone: string): Promise<Client> {
const client = await this.repository.findOne({ cellphone });
return client;
}
async list(): Promise<Client[]> {
const clients = await this.repository.find();
return clients;
}
async createMultiple(contacts: Client[]): Promise<void> {
const clients = this.repository.create(contacts);
await this.repository.save(clients);
}
async create({ name, cellphone }: ICreateClientDTO): Promise<void> {
const client = this.repository.create({ name, cellphone });
await this.repository.save(client);
}
async update({ name, cellphone, id }: ICreateClientDTO): Promise<void> {
await this.repository.update({ id }, { name, cellphone });
}
async delete(id: string): Promise<void> {
await this.repository.delete({ id });
}
}
export { ClientsRepository };
if I run typeorm migration:run passing the connection it does the migration in mysql and postgres
typeorm migration:run -c "connection2"

Related

Typescript JSON to interface dynamically

I'm pretty new to typescript and I want to turn the below JSON into an interface/type but the user1 key is dynamic and could be something different but the JSON inside the of key will be the same.
{
"code": 200,
"status": "success",
"data": {
"user1": {
"firstName": "John",
"lastName": "Smith",
"age": 25
}
}
}
I have the below so far. Is it possible to turn the data into a map in the Root interface as this is how I would do it in golang.
export interface Root {
code: number
status: string
data: Data
}
export interface Data {
[key: string]: User
}
export interface User {
firstName: string
lastName: string
age: number
}
export const sendRequest = (url: string): Root => {
const [data,setData]=useState([]);
const getData=()=>{
fetch(url
,{
headers : {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
}
)
.then(function(response){
return response.json();
})
.then(function(myJson) {
setData(myJson)
});
}
useEffect(()=>{
getData()
},[])
return JSON.parse(JSON.stringify(data));
}
const user = sendRequest(host + path)
console.log(user.data?.[0])
You can use index signatures:
export interface Root {
code: number
status: string
data: Data
}
export interface Data {
[key: string]: User
}
export interface User {
firstName: string
lastName: string
age: number
}

Typeorm pool doesn't exist in replication

typegraphql, typeorm, Mysql with master slave replication.
I have configured mysql with master and slave databases with separate instances and its working fine. I have encounter an error
while connecting via typeorm. Here's my ormconfig.json
{
"type": "mysql",
"logging": true,
"replication": {
"master":
{
"host": "192.168.0.250",
"port": 3306,
"username": "root",
"password": "test#123",
"database": "master",
"synchronize": true,
"extra": {
"connectionLimit": 5
}
}
,
"slaves": [
{
"host": "192.168.0.175",
"port": 3306,
"username": "root",
"password": "test#123",
"database": "master",
"synchronize": true,
"extra": {
"connectionLimit": 5
}
}
]
},
"entities": [
"src/entity/**/*.ts"
],
"migrations": [
"src/migration/**/*.ts"
],
"subscribers": [
"src/subscriber/**/*.ts"
],
"cli": {
"entitiesDir": "src/entity",
"migrationsDir": "src/migration",
"subscribersDir": "src/subscriber"
}
}
My index.ts file with database connection as
import { gqSchema } from './schema';
import "reflect-metadata";
import { createConnection } from "typeorm";
import { ApolloServer } from "apollo-server";
async function main() {
await createConnection().then(async(res) => {
console.log(res)
console.log("Database Connected")
const schema = await gqSchema()
const server = new ApolloServer({
schema,
context: ({ req }: any) => ({ req })
})
await server.listen(4000)
console.log("Server has started!")
}).catch(err => {
console.log("err", err)
})
}
main();
And my resolver.ts file
#Resolver()
export class UserResolver {
/**
* query
*/
#Authorized()
#Query(() => User)
async hello(
#Arg("firstName") firstName: string,
): Promise<User | undefined > {
const slaveQueryRunner = getConnection().createQueryRunner("slave");
try {
const connection = getConnection().getRepository(User);
const usersList = await connection.createQueryBuilder()
.from(User, "user")
.setQueryRunner(slaveQueryRunner)
.where("user.firstName = ", {firstName})
.getOne();
console.log(usersList)
} finally {
slaveQueryRunner.release();
}
}
}

Angular 4+ handling multiarray json response best practice

user.ts
import { Company } from "./company";
export class User{
token: string;
companies: Company;
name: string;
email: string;
currentCompanyID: string;
constructor(){
}
}
company.ts
export class Company{
companyId: string;
name: string;
orgNo: string;
constructor(){
}
}
service.ts
getData(): Observable<User> {
return this.http.get(this.url).map((res: Response) => res.json())
}
component.ts
//call to my api in service.ts
this.avrs.getData().subscribe(
res => {
console.log("Result");
console.log("main res: " + res);
console.log("Name: " + res.name);
console.log("companyid: " + res.currentCompanyID);
console.log("companies: " + res.companies);
console.log("token: " + res.token);
console.log("user data: " + res.companies.companyId);
console.log("user data: " + res.companies.name);
console.log("user data: " + res.companies.orgNo);
},
error => {
console.log(error);
},
() => {
}
);
}
Output
Result
main res: [object Object]
Name: undefined
companyid: 28764
companies: [object Object]
token: lkjdfjsgosdfjuguerujgoiehjiughdskjge9r8w
user data: undefined
user data: undefined
user data: undefined
Json Response example:
{
"user": {
"id": 123456,
"company_id": "28764",
"name": "TEST",
"email": "test#dummy.com",
"mobile": "91273493412412",
"locale": "en",
"companies": [
{
"companyId": "idww",
"name": "nameww",
"orgNo": "orgww",
"roles": [
{
"role": "Admin"
},
{
"role": "Guest"
}
],
"services": []
},
{
"companyId": "idqq",
"name": "nameqq",
"orgNo": "orgqq",
"roles": [
{
"role": "Admin"
},
{
"role": "Guest"
}
],
"services": []
},
],
},
"token": "lkjdfjsgosdfjuguerujgoiehjiughdskjge9r8w",
"currentCompanyID": "28764"
}
I want to get:
token,
companyid,
user -> name,
user -> companies array
The question is basically what is the best way (best practice) to handle many array in a json file in Angular 2+? As you can see with my output I'm only getting companyid and token data, and not getting companies array or user data.
Create Role Model:
export class Role{
id: number;
name: string;
constructor(attrs: any = null) {
if (attrs) {
this.build(attrs);
}
}
build(attrs: any): void {
this.id = attrs.id;
this.name = attrs.name;
}
}
Create Company Model:
export class Company{
id: number;
name: string;
roles: Array<Role>;
services: any;
constructor(attrs: any = null) {
if (attrs) {
this.build(attrs);
}
}
build(attrs: any): void {
this.id = attrs.id;
this.name = attrs.name;
this.services = attrs.services;
if(attrs.roles) {
this.roles = attrs.roles.map(
r => new Role(r)
);
}
}
}
Create User Model:
export class User{
id: number;
name: string;
email: string;
companies: Array<Company>;
constructor(attrs: any = null) {
if (attrs) {
this.build(attrs);
}
}
build(attrs: any): void {
this.id = attrs.id;
this.name = attrs.name;
this.email = attrs.email;
if(attrs.companies) {
this.companies = attrs.companies.map(
c => new Company(c)
);
}
}
}
By doing so, you create entities automatically. According to your Json Response example, you need to create another model. Let's call it Data!
export class Data{
user: User;
token: string;
currentCompanyID: string;
constructor(attrs: any = null) {
if (attrs) {
this.build(attrs);
}
}
build(attrs: any): void {
this.currentCompanyID = attrs.currentCompanyID;
this.token = attrs.token;
this.user = attrs.user;
}
}
Retrieve data from sample service method like this:
getData(): Observable<any>{
return this.http
.get('awesome_url')
.map((data: any) => new Data(data));
}
Hope I help!

Supplied parameters do not match any signature of call target on api call angular4

I am consuming an api to Covalent UI, on user service. Which needs to post some data from an endpoint to the table as illustrated on the example from the GitHub.
Here is the modification I have made to the service.
import { Provider, SkipSelf, Optional, InjectionToken } from '#angular/core';
import { Response, Http } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { HttpInterceptorService, RESTService } from '#covalent/http';
import { ApiService } from '../../../../services/api.service';
import { AuthService } from '../../../../services/auth.service';
export interface IUser {
_id: string;
email:string;
createdAt: Date;
profile: {
name: string;
gender: string;
location: String;
picture: {
// data: Buffer;
contentType: string;
}
}
}
export class UserService extends RESTService<IUser> {
constructor(private _http: HttpInterceptorService, api: string,
private authService: AuthService,
private api2: ApiService,) {
super(_http, {
baseUrl: api,
path: '/dashboard/users',
});
}
staticQuery(): Observable<IUser[]> {
// return this._http.get('data/users.json')
// .map((res: Response) => {
// return res.json();
// });
return this.api2.get('auth/account/users')
.map((res: Response) => {
return res.json();
});
}
}
export const USERS_API: InjectionToken<string> = new InjectionToken<string>('USERS_API');
export function USER_PROVIDER_FACTORY(
parent: UserService, interceptorHttp: HttpInterceptorService, api: string): UserService {
return parent || new UserService(interceptorHttp, api);//<---- This is where I get the error mention.
}
export const USER_PROVIDER: Provider = {
// If there is already a service available, use that. Otherwise, provide a new one.
provide: UserService,
deps: [[new Optional(), new SkipSelf(), UserService], HttpInterceptorService, USERS_API],
useFactory: USER_PROVIDER_FACTORY,
};
JSON api data
[
{
"_id": "59d665c3acbde702b47d3987",
"updatedAt": "2017-10-07T17:23:00.498Z",
"createdAt": "2017-10-05T17:02:59.526Z",
"email": "me#mail.com",
"password": "$2a$05$z1mRUWqqUfM8wKMU/y9/sOLssAKcV7ydxi0XJyTR1d3BI2X7SSsoy",
"tokens": [],
"role": "admin",
"__v": 0,
"profile": {
"name": "F.name L.name",
"gender": "Female",
"location": "my place",
"avatar": {
"contentType": "image/png",
"data": "iVBORw0KGgoAAAANSUhEUgAAAaYAAAFmCAYAAAAmm....."
}
}
}
]
Am not sure what am doing wrong, I will appreciate your comment for this fix.
I get the error bellow.
users/services/user.service.ts (51,20): Supplied parameters do not match any signature of call target.
From this line of code
As #Philipp mentioned in the comments.
The class UserService expects 4 arguments in the constructor, but you are only providing 2 in the USER_PROVIDER_FACTORY function.
Therefore your factory should be defined:
export function USER_PROVIDER_FACTORY(
parent: UserService, interceptorHttp: HttpInterceptorService, api: string,
authService: AuthService, api2: ApiService
): UserService {
return parent || new UserService(interceptorHttp, api, authService, api2)
}

How to pass dynamic attribute/parameter to openDialog?

I need to pass the following ID: 59dc921ffedff606449abef5 dynamically to MatDialog. For testing proposes I'am using it as hard coded ID.
Unfortunately all my searches and tries failed and I can't get the id dynamically into the function call. I tried also the #input feature, but it didn't help.
edit-dilog.component.ts:
export class EditDialogComponent implements OnInit {
dialogResult:string = '';
constructor(public dialog:MatDialog, public loginService:LoginService ){ }
ngOnInit() {}
openDialog() {
this.dialog.open(EditUserComponent, { data: '59dc921ffedff606449abef5' })
.afterClosed()
.subscribe(result => this.dialogResult = result);
}
}
edit-user.component.ts:
export class EditUserComponent implements OnInit {
public message:any [];
public resData: {};
constructor(public thisDialogRef: MatDialogRef<EditUserComponent>,
#Inject(MAT_DIALOG_DATA) public data: number,
public loginService: LoginService) { }
ngOnInit() {
this.loginService.getSingleUser(this.data)
.subscribe(data => {
this.resData = JSON.stringify(data);
})
}
onCloseConfirm() {
this.thisDialogRef.close('Confirm');
}
onCloseCancel() {
this.thisDialogRef.close('Cancel');
}
}
The ID is coming from JSON Response in a service login-service.ts:
getSingleUser(id) {
return this.http.get(environment.urlSingleUsers + '/' + id, this.options)
.map(res => {
console.log('RES: ' + JSON.stringify( res.json() ) );
return res.json();
}).catch( ( error: any) => Observable.throw(error.json().error || 'Server error') );
}
extractData(result:Response):DialogUserData[] {
return result.json().message.map(issue => {
return {
ID: issue._id,
Email: issue.email,
Name: issue.fullName
}
});
}
And here is where I do the call of openDialog():
<i class="material-icons" (click)="openDialog()">create</i>
For more clarification here is how the JSON Response comes:
"message": [
{
"_id": "59415f148911240fc812d393",
"email": "jane.doe#foo.de",
"fullName": "Jane Doe",
"__v": 0,
"created": "2017-06-14T16:06:44.457Z"
},
{
"_id": "5943b80be8b8b605686a67fb",
"email": "john.doe#foo.de",
"fullName": "John Doe",
"__v": 0,
"created": "2017-06-16T10:50:51.180Z"
}
]
I just did something similar, though I'm a little bit confused by how you name the components (seems should be the other way around).
You can try: fetch the data (user) first and then (actually) open the dialog in your controlling component:
edit-dialog.component.ts:
openDialog(id: string) {
this.loginService.getSingleUser(id)
.subscribe(user=> {
const dialogRef = this.dialog.open(EditUserComponent, {
data: user
});
dialogRef.afterClosed().subscribe(result => {
console.log(`Dialog result: ${result}`);
});
});
}
You can then access the dialog data (user) to render the dialog view:
edit-user.component.ts:
ngOnInit() {
console.log(this.data);
}
In this way, you can pass the id dynamically:
<i class="material-icons" (click)="openDialog(id)">create</i>
where the id can be a member of your controlling component.