So I have my NestJs application connected to mongoDB/Mongoose. I'd like to get everything in the repository and save it locally on my computer as a json file. Could anyone advise how to go about that?
backup.service.ts
#Injectable()
export class BackupService {
constructor(private userService: UserService) {}
private async getUsers(): Promise<User[]> {
return await this.shiftService.getMany();
}
public async downloadUserData() {
const users = await this.getUsers();
// next step to download as json file to local computer?
}
}
Any advice would be greatly appreciated!
You'll need to write the data to a file using Node's fs module. You'll be able to do something like this:
import { writeFile } from 'fs/promises';
import { join } from 'path';
#Injectable()
export class BackupService {
constructor(private userService: UserService) {}
private async getUsers(): Promise<User[]> {
return await this.shiftService.getMany();
}
public async downloadUserData() {
const users = await this.getUsers();
await writeFile(join(process.cwd(), 'db', 'users.json'), JSON.stringify(users));
}
}
This should write the data to a JSON file at <projectRoot>/db/users.json. Keep in mind this is a direct write and not an append, so any data there will be overwritten.
Related
Im trying to reading a JSON config file from my assets in angular project. I have created a Service and calling in App.Module.ts in a initializeApp function.
my jSON files are in src/assets/config/ folder
When it starts it shows me in console a Empty Json file "{}".
This is my service.
import { IConfig } from "../_model/config";
import { Injectable } from '#angular/core';
import { environment } from 'src/environments/environment';
import { HttpClient, HttpResponse } from '#angular/common/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';
#Injectable()
export class Config {
static settings: IConfig;
constructor(private http: HttpClient) {
}
load() {
const jsonFile = `assets/config/config.${environment.name}.json`; // ${environment.name} could be 'prod' or 'dev'
return new Promise<void>((resolve, reject) => {
this.http.get(jsonFile).toPromise().then((response: IConfig) => {
Config.settings = <IConfig>response;
resolve();
}).catch((response: any) => {
reject(`Error en archivo de configuracion '${jsonFile}': ${JSON.stringify(response)}`);
});
});
}
and Config interface if you want check:
export interface IConfig {
config: {
production: boolean;
};
path: {
url_root: string;
};
timeZone: {
time: number;
};
}
console error
core.js:15724 ERROR Error en archivo de configuracion 'assets/config/config.dev.json': {}
it always goes for Catch and prints error message with anf EMPTY JSON, like if not exists.
If you need more info just tell me.
I think you have to add the "src/assets/config/" path to the assets: [] array your angular.json file. Then I think you have to recompile the server.
You need to step back twice. ../../
replace
const jsonFile = `assets/config/config.${environment.name}.json`;
with
const jsonFile = `../../assets/config/config.${environment.name}.json`;
Secure Recommention
However, I recommend that you have to place the config inside the environment files instead of the assets folder because the environment is secured by the browsers while assets will be public to anyone.
I am developing a restAPI with nodejs, express and mysql. Now I have a app.js which is the starting point of the App.
Within app.js I initialize the UserController:
const router: express.Router = express.Router();
new UserController(router);
The UserController looks like this:
import { Request, Response, Router } from 'express';
import UserModel from '../model/user';
class UserController {
constructor(private router: Router) {
router.get('/users', async (req: Request, resp: Response) => {
try {
// const users = get Users with mysql
// resp.status(200).send(users);
} catch (error) {
resp.send({
msg: 'Not found',
status: 404
});
}
});
}
}
export default UserController;
Now I would like to have a DatabaseController which handels everything around the Database like providing a Connection, closing it and so on:
class DatabaseController {
constructor() {
}
}
export default DatabaseController;
How can I achieve that I open the connection in the DatabaseController and let the UserController simply access it? Is that even possible without initializing the DatabaseController and giving the UserController a parameter "dbConnection"?
Yes it's possible. I'm not entirely familiar with typescript so some psuedo code below. Untested.
Somewhere in another file, configure your database connection and the service:
import { MyConnection } from 'my-db-package';
class DatabaseService {
private connection: MyConnection
constructor(db: MyConnection) {
this.connection = db;
}
// Return the promise if any.
// Don't want to handle the error here.
// Let your controller handle the error
async openConnection() {
return this.connection.open()
}
async closeConnection() {
return this.connection.close()
}
async getAllUsers() {
return this.connection.query('SELECT * FROM USERS;')
}
}
export default DatabaseService;
import { Database } from 'my-db-driver'
import { DatabaseService } from 'my-db-service'
// Don't actually connect here
// Just create the object so it's ready for connection.
const connection = new Database({
// config
})
// Wire up the internal db connection
// Remember this is a singleton.
export default new DatabaseService(connection)
Next wire up your controller with the new database service:
import { Request, Response } from 'express';
import { DatabaseService } from './my-service'
class UserController {
private dbService: DatabaseService;
constructor(dbService: DatabaseService) {
this.dbService = dbService;
}
async connect() {
return this.dbService.openConnection()
}
async close() {
return this.dbService.closeConnection()
}
async getAllUsers(req: Request, res: Response) {
let users
try {
users = await this.dbService.getAllUsers();
} catch (error) {
// ...
}
res.json(users)
}
}
export default UserController;
Then hook up your routes:
import { express } from 'express'
import { UserController } from 'user-controller'
import { DatabaseService } from 'database-service'
const userController = new UserController(DatabaseService);
const router: express.Router = express.Router();
router.get('/users', userController.getAllUsers)
// ...
export default router
Finally, hook up your routes with the main Express app:
import { express } from 'express'
import { userRoutes } from 'user-routes'
const app = express()
app.use(userRoutes)
// ..
Again, the above code is untested and likely unusable. It is meant to give you an example of one approach. You may find a better way to do it, but that's the gist of it.
I am creating an application in angular 2. I am trying to access the json data via http in a service. But i am getting an error saying that
**GET http://localhost:4200/data/products.json 404 (Not Found)**
I have the data in the specified folder but i am unable to access it.
My service code is as follows.
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';
import { Item } from './item';
#Injectable()
export class ItemService {
observableItems: Observable<Item[]>
allItems: Item[] = [];
selectedItems: Item[] = [];
errorMessage: string;
url = "http://localhost:4200/data/products.json";
constructor(private http:Http) {
this.observableItems = this.http.get(this.url).map((res: Response) => res.json());
this.observableItems.subscribe(
data => this.allItems = data,
error => this.errorMessage = <any>error);
}
getItems(): Observable<Item[]> {
return this.observableItems;
}
getSelectedItems(): Item[] {
return this.selectedItems;
}
addItem(id:number): void {
let item = this.allItems.find(ob => ob.id === id);
if (this.selectedItems.indexOf(item) < 0) {
this.selectedItems.push(item);
}
}
removeItem(id:number): void {
let item = this.selectedItems.find(ob => ob.id === id);
let itemIndex = this.selectedItems.indexOf(item);
this.selectedItems.splice(itemIndex, 1);
}
}
My html files are in
"Project/src/app/..."
So to access JSON File I need to come back from tabs folder and app folder to reach the base directory for both code and images. I used ../ to come back from a folder.
From this my url in the service will be as follows:
url = "../../assets/data/products.json";
Try using direct path to the file from the location of your service file. For example:
url = "data/products.json";
It will work.
I want to get a json object from a json file using angular 2 http.get. What I end up getting from the file is this:
t_isScalar: falseoperator: tsource: t__proto__: Object
Here is my code
#Injectable()
export class ValidateJSONSchemaService {
constructor(private http: Http) { }
getSchema(fileName): any {
return(this.http.get(fileName)
.map(this.extractData)
);
}
private extractData(res: Response) {
let body = res.json();
return body.data || {};
}
}
How do I fix getSchema to make it return the json object rather than this: t_isScalar: falseoperator: tsource: t__proto__: Object. Note that when I change the file name it returns the same thing. I would have expected an informational error (I did do error handling but the code never errors out).
You need to subscribe to observable:
#Injectable()
export class ValidateJSONSchemaService {
constructor(private http: Http) { }
getSchema(fileName): any {
return(this.http.get(fileName)
.map(this.extractData).subscribe(data => console.log(data));
);
}
private extractData(res: Response) {
let body = res.json();
return body.data || {};
}
}
In addition to Maciej s answer you can use the | async pipe that does the subscribing for you.
<div>{{getSchmea('fileName') | async}}</div>
i am new to angular 2 and to observables but i wanted to give it a shot. So i have installed the angular-cli and made a simple test project.
All i wanted it to do is read a json file and work with the data inside of a component (the first intention was to make a service but i wanted to start on a low basis).
So i have created a json file in the assets/json folder (testjson.json):
{
"teststring": "test works"
}
then i have imported the http from angular and the rxjs map stuff inside of my content.component.ts file:
import { Component, OnInit } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
#Component({
selector: 'app-content',
templateUrl: './content.component.html',
styleUrls: ['./content.component.css']
})
export class ContentComponent implements OnInit {
title: string = "Default";
data;
constructor(private http:Http) {
http.get('assets/json/testjson.json').map(res => res.json()).subscribe(data => {this.data = data; this.title = data.teststring; console.log(this.data);});
}
ngOnInit() {
}
}
So far so good, the app prints out the following:
app works!
test works [object Object]
But i want to use this data in the whole component, not only in the constructor. but if i try to console.log "this.data" outside of the constructor (inside the ngOnInit function), it prints undefined in the console.
I know, that it must have something to do with asynch loading but unfortunately i have no clue how to tell the app to wait until this.data is filled.
I hope you can help me with that. Of course in the future i want a service which does that kind of stuff and more than one component should grab data from it.
Thanks in advance!
You should move the initialization code to the initialization method.
Your data becomes available once the callback completes. In your template you can use *ngIf to execute code inside a block once there is data. As long as the *ngIf does not eval to true the inner code will not run.
The only way you can run console.log(data) is from inside the callback or called from the callback because you have to wait until the data is loaded.
content.component.html
<div *ngIf="data">
<span>{{data.teststring}}</span>
</div>
content.component.ts
export class ContentComponent implements OnInit {
title: string = "Default";
data: any = null;
constructor(private http:Http) {
}
ngOnInit() {
this.http.get('assets/json/testjson.json')
.map(res => res.json())
.subscribe(data => {
this.data = data;
this.title = data.teststring;
console.log(this.data);
});
}
}
Edit
In response to the comment below If you abstract out the http call to a service you can see the exact same logic still applies. You are still using the concept of a promise of data and that you can subscribe to that promise once it has completed. The only difference here is the http call is abstracted to a different class.
content.component.ts
export class ContentComponent implements OnInit {
title: string = "Default";
data: any = null;
// inject service
constructor(private contentService:ContentService) {
}
ngOnInit() {
this.contentService.getData()
.subscribe(data => {
this.data = data;
this.title = data.teststring;
console.log(this.data);
});
}
Service
export class ContentService {
constructor(private http:Http) {
}
getData(): IObservable<{teststring:string}> { // where string can be some defined type
return http.get('assets/json/testjson.json')
.map(res => res.json() as {teststring:string});
}