how to serialize a class in an object to string - node.js

I have following object ICoreFileStat, which on the server side, URI will be a class created using vscode-uri. How do I convert only URI to string recursively?
export interface ICoreFileStat extends ICoreBaseStat {
children?: ICoreFileStat[];
}
export interface ICoreBaseStat {
resource: URI | string;
name?: string;
}
What I was expecting the URI in the above object will be transformed to string like (file:///index.js) and it will be a plain object like below.
const data = {
children: {
resource: "///file://tmp"
children: {
resource: "///file:/index.js"
}
}

Here is the solution, I came up with. But I would like to see others solutions as well.
const serialize = (stat: IFileStat) => Object.keys(stat).reduce((result, name) => {
// console.log(result);
if (name === 'resource') {
return result = { ...stat, resource: stat[name].toString() };
} else if (name === 'children') {
return { ...result, ...{ children: stat[name].map(child => serialize(child as any)) } }
}
else {
return result
}
}, {});

Related

NestJs: return modified response based on external API call

I am new to NestJs, Graphql, typescript.
I need to make an external API call which is basically Graphql query itself, modify the response if needed and return the response for the original request/query in this case test which is the query name.
I have the following code
#Query(returns => BlogPost) // #objectType
async test() {
const endpoint = 'https://testing.org/api/content/project-dev/graphql'
const graphQLClient = new GraphQLClient(endpoint, {
headers: {
authorization: 'Bearer xxxx',
},
})
const query = gql`
{
queryContentContentsWithTotal(top: 10) {
total
}
}`
const data = await graphQLClient.request(query)
console.log(JSON.stringify(data, undefined, 2))
return data;
}
The BlogPost is the ObjectType which looks like :
import { Field, ObjectType } from '#nestjs/graphql';
#ObjectType()
export class BlogPost {
#Field({ nullable: true })
total!: number;
}
I have placed console.log as well to see the external API call response which is:
{
"queryContentContentsWithTotal": {
"total": 1
}
}
but the Graphql response for the query is :
{
"data": {
"test": {
"total": null // this needs to be 1
}
}
}
total is null where the API call returns total value 1;
How can be the mapping done with flexibility here so that the query response looks the same?
GraphQL is expecting your return data in the shape of
{
"total": "number of some sort"
}
But you're actually returning data in the shape of
{
"queryContentContentsWithTotal": {
"total": 1
}
}
So the GraphQL engine can't understand the return type. You need to map your data to the proper return like so:
#Query(returns => BlogPost) // #objectType
async test() {
const endpoint = 'https://testing.org/api/content/project-dev/graphql'
const graphQLClient = new GraphQLClient(endpoint, {
headers: {
authorization: 'Bearer xxxx',
},
})
const query = gql`
{
queryContentContentsWithTotal(top: 10) {
total
}
}`
const data = await graphQLClient.request(query)
console.log(JSON.stringify(data, undefined, 2))
return data.queryContentContentsWithTotal;
}
You are returning data which is not the same type as BlogPost. You should return this instead
return {total: data.queryContentContentsWithTotal.total}

typeorm convert EntitySchema to Entity

I'm using typescript and typeorm. I have this Entity:
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
#Entity()
export class Sample {
#PrimaryGeneratedColumn()
id: number;
#Column({ length: 50 })
name: string;
#Column('text', { nullable: true })
description: string;
}
I query a single result like this:
const connection = await this.getConnection();
const sampleRepo = await connection.getRepository(Sample);
const sample = await sampleRepo.createQueryBuilder('sample')
.where('sample.id = :id', { id: id })
.getOne();
Now, I need to do some stuff with the result columns, but the sample object is of type EntitySchema. So, in typescript, I can't do sample.id because the error:
Property 'id' does not exist on type 'EntitySchema<any>'
Is there anyway to convert the EntitySchema into an actual Sample object?
As it turns out, this is due to a bad implementation. I moved the creation of the repository to a separate class:
export default class Database {
private connectionManager: ConnectionManager
constructor() {
this.connectionManager = getConnectionManager();
}
public getRepository<T extends EntitySchema>(type: ObjectType<T> | EntitySchema<T> | string): Promise<Repository<T>> {
const connection = await this.getConnection();
return connection.getRepository(type);
}
public async getConnection(connectionName = 'default'): Promise<Connection> {
let connection: Connection;
if (this.connectionManager.has(connectionName)) {
connection = this.connectionManager.get(connectionName);
if (!connection.isConnected) {
connection = await connection.connect();
}
}
else {
const connectionOptions: ConnectionOptions = Object
.assign({ name: connection }, connectionProperties);
connection = await createConnection(connectionOptions);
}
return connection;
}
}
It looks like connection.getRepository doesn't return a promise. As well, the T generic shouldn't be extending EntitySchema. To make the function work as intended, I had to write it like this:
public getRepository<T>(type: ObjectType<T> | EntitySchema<T> | string): Promise<Repository<T>> {
return new Promise((resolve, reject) => {
this.getConnection().then(conn => {
resolve(conn.getRepository(type));
}).catch(reject);
});
}

nestjs Post cannot receive array of multiple json `this.build(...).save is not a function`

I am trying to Post array of json objects to nestjs #Post and it doesnt accept it.
my controller
#Post()
async create(#Res() res, #Body() data: any) {
if (!data || (data && Object.keys(data).length === 0)) {
throw new HttpException("Empty Body ", HttpStatus.BAD_REQUEST);
}
let result: any = await this.Service.creat(data);
if (!result.success) {
throw new HttpException(result.message, HttpStatus.BAD_REQUEST);
}
return res.status(HttpStatus.OK).json(result);
}
my service
constructor(
#Inject('DATA_REPOSITORY')
private dataRepository: typeof Vols
) { }
public async creat(data: any): Promise<object> {
let newData: any;
newData = await this.dataRepository.create<data>(data);
return newData;
}
Vols : -> is just my Model of columns
id: number;
name:string
`[
{ id:1 name:'test2' },
{ id:2, name:'test' }
]`
Create is for a single use, try bulkSave
await this.dataRepository.buldSave<data>(data)

Pass Object to Node JS GET request

I am trying to pass an object to my NodeJS server from my angular application. I can read the object perfectly fine on the client-side, but not serverside.
Here is my client-side:
var query = {
date: '9-2-2019',
size: 4
}
this.http.get<any>(url, {params: {query: query} }).toPromise();
Why can I not pass this to my Node JS server?
No overload matches this call.
Is my error.
Please change { params: {query: query}} to be {params: query} and also change query.size to be string instead of number
var query = {
date: '9-2-2019',
size: '4'
}
this.http.get<any>(url, {params: query}).toPromise().then(response => {
console.log(response);
})
.catch(console.log);
Alternative
Create // utils.service.ts
import { HttpParams } from '#angular/common/http';
// ...
export class UtilsService {
static buildQueryParams(source: Object): HttpParams {
let target: HttpParams = new HttpParams();
Object.keys(source).forEach((key: string) => {
const value: string | number | boolean | Date = source[key];
if ((typeof value !== 'undefined') && (value !== null)) {
target = target.append(key, value.toString());
}
});
return target;
}
}
then use it in your service
import { UtilsService } from '/path/to/utils.service';
var query = {
date: '9-2-2019',
size: 4
}
const queryParams: HttpParams = UtilsService.buildQueryParams(query);
this.http.get<any>(url, {params: queryParams }).toPromise().then(response => {
console.log(response);
})
.catch(console.log);

How to receive an array as member of an input parameter of a GraphQL service?

Given this schema:
input TodoInput {
id: String
title: String
}
input SaveInput {
nodes: [TodoInput]
}
type SavePayload {
message: String!
}
type Mutation {
save(input: SaveInput): SavePayload
}
Given this resolver:
type TodoInput = {
id: string | null,
title: string
}
type SaveInput = {
nodes: TodoInput[];
}
type SavePayload = {
message: string;
}
export const resolver = {
save: (input: SaveInput): SavePayload => {
input.nodes.forEach(todo => api.saveTodo(todo as Todo));
return { message : 'success' };
}
}
When I sent this request:
mutation {
save(input: {
nodes: [
{id: "1", title: "Todo 1"}
]
}) {
message
}
}
Then the value for input.nodes is undefined on the server side.
Does anybody knows what am I doing wrong?
Useful info:
The mutation works properly with scalar values (such as String as input and return)
I'm using typescript, express and express-graphql.
You need to make changes in the key in the resolver,
export const resolver = {
save: (args: {input: SaveInput}): SavePayload => {
args.input.nodes.forEach(todo => api.saveTodo(todo as Todo));
return { message : 'success' };
}
}

Resources