Angular Universal server rendering WebSocket - node.js

Are there any examples of Angular Universal with WebSockets?
Serverside rendering does not know wat a WebSocket object is in my case. And if I use socket.io the node server hangs when trying to make a connections.
Some additional information about the problem:
I downloaded angular-universal-starter from github: https://github.com/angular/universal-starter
Which works fine out of the box running 'npm install' and 'npm start'
But after i added the following code to AppComponent
export class AppComponent implements OnInit {
ngOnInit() {
let webSocket = new WebSocket("----server url----")
}
}
I got the following error in my NodeJs server console:
EXCEPTION: WebSocket is not defined
ORIGINAL STACKTRACE:
ReferenceError: WebSocket is not defined
at AppComponent.ngOnInit (/Volumes/Development/cacadu/website/universal-starter-master2/dist
/server/index.js:41725:29)

Try only calling the websocket on the Client, for example you can detect whether it's the browser or the server with these imports
import { isPlatformBrowser } from '#angular/common';
import { Inject, PLATFORM_ID } from '#angular/core';
Then use them inside your code, this might be able to fix the problem!
#Component({ ... })
export class AppComponent implements OnInit {
private isBrowser: boolean = isPlatformBrowser(this.platformId);
constructor(
#Inject(PLATFORM_ID) private platformId: Object
) {
if (isBrowser) {
let webSocket = new WebSocket("----server url----");
}
}
}

Related

How to reference the app instance in a module in Nest.js

I'm working on a project that's using multiple Nest repos, around 4.
Every repo needs to implementing logging to log things like
Server lifecycle events
Uncaught errors
HTTP requests/responses
Ideally, I'd like to package everything up into a module which I can publish to my company's NPM organization and just consume directly in each of my projects.
That way, it would take very minimal code to get logging set up in each project.
One of the things I'd like to log in my server lifecycle event is the server's url.
I know you can get this via app.getUrl() in the bootstrapping phase, but it would be great to have access to the app instance in a module's lifecycle hook like so.
#Module({})
export class LoggingModule implements NestModule {
onApplicationBootstrap() {
console.log(`Server started on ${app.getUrl()}`)
}
beforeApplicationShutdown() {
console.log('shutting down')
}
onApplicationShutdown() {
console.log('successfully shut down')
}
configure(consumer: MiddlewareConsumer) {
consumer.apply(LoggingMiddleware).forRoutes('*')
}
}
Is this possible?
There's no way (besides hacky ones, maybe) to access the app itself inside modules.
As you can see here, app.getUrl() uses the underlying HTTP server. Thus I guess you can retrieve the same data using the provider HttpAdapterHost.
Ï thought I'd chime in and offer one of the hacky solutions. Only use this, if there is absolutely no other way or your deadline is coming in an hour.
Create a class that can hold the application instance
export class AppHost {
app: INesApplication
}
And a module to host it
#Module({
providers: [AppHost]
exports: [AppHost]
})
export class AppHostModule {}
In your bootstrap() function, retrieve the AppHost instance and assign the app itself
// after NestFactory.create() ...
app.select(AppHostModule).get(AppHost).app = app;
Now, the actual application will be available wherever you inject AppHost.
Be aware, though, that the app will not be available inside AppHost before the whole application bootstraps (in onModuleInit, onApplicationBootstrap hooks or in provider factories), but it should be available in shutdown hooks.
Not sure is that hacky... I'm using this to prevent the server from starting in case of pending migrations.
// AppModule.ts
export class AppModule implements NestModule {
app: INestApplication;
async configure(consumer: MiddlewareConsumer) {
if (await this.hasPendingMigrations()) {
setTimeout(()=> {
this.logger.error("There are pending migrations!")
process.exitCode = 1;
this.app.close();
}, 1000);
}
//...
}
public setApp(app: INestApplication) {
this.app = app;
}
//...
}
//main.ts
const app = await NestFactory.create(AppModule, {
logger: config.cfgServer.logger,
});
app.get(AppModule).setApp(app);

Angular9 http.get() doesn´t work properly

i'm developing a simple app to make consults to a backend on NodeJS. Everything works perfectly on localhost, but when i run the angular server on my ip adress (192.168.1.x) it dosen`t work anymore.
The nodeJS REST api it's running on 'http://localhost:3000/api/article' and the Angular server in https://192.168.1.x:4200.
The http.get code its this:
articles.component.ts:
import {ArticlesService} from '../../services/articles.service';
import {Article} from '../../models/article';
import { ViewChild } from '#angular/core'
#Component({
selector: 'app-articles',
templateUrl: './articles.component.html',
styleUrls: ['./articles.component.scss'],
providers: [ArticlesService],
})
export class ArticlesComponent implements OnInit {
constructor(public articlesService: ArticlesService) { }
article: Article;
//Some other code that dosen't afect this
getArticle(id: String) {
this.articlesService.getArticle(id)
.subscribe( res => {
this.article = res as Article;
})
}
articles.service.ts:
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class ArticlesService {
readonly API_URI = 'http://localhost:3000/api/article';
constructor(private http: HttpClient) {
}
getArticle(id: String) {
return this.http.get(this.API_URI+`/${id}`);
}
}
I`ve been trying some flags test and i realize that it never enter on the subscribe(), i'm new and it's the first time i run the server on my current ip and not in the localhost. So, i don't if maybe i can't request at the backend like that in this case or something else.
Using morgan and postman at the nodeJS REST api i see that the get request work properly on that side.
If someone could help me it would be awsome.
I exactly don't get you with the Angular server but all indicates that your Angular server doesn't have visibility of your localhost:3000. It's like when you deploy your spa in another server. That server doesnt know about your localhost and you have to replace your API_URI (using environments.ts) with the IP or domain name where your backend is:
For example i have this in my environment.prod.ts:
export const environment = {
production: true,
apiUrl: 'https://urltothenodejsbackend/api',
apiVersion: '/v1'
};

Unable to add an UI extension on Contentful. When i run nopm run start, I get a 404 error on ui_config

I am new to contentful. I am trying to develop an UI extension on Contentful using Contentful SDK.
I followed all the steps mentioned in this article.
This is the code I have in index.js.
import React from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import { TextInput , Button } from '#contentful/forma-36-react-components';
import { init } from 'contentful-ui-extensions-sdk';
import '#contentful/forma-36-react-components/dist/styles.css';
import './index.css';
export class App extends React.Component {
static propTypes = {
sdk: PropTypes.object.isRequired
};
detachExternalChangeHandler = null;
constructor(props) {
super(props);
this.state = {
value: props.sdk.field.getValue() || ''
};
}
componentDidMount() {
this.props.sdk.window.startAutoResizer();
// Handler for external field value changes (e.g. when multiple authors are working on the same entry).
this.detachExternalChangeHandler = this.props.sdk.field.onValueChanged(this.onExternalChange);
}
componentWillUnmount() {
if (this.detachExternalChangeHandler) {
this.detachExternalChangeHandler();
}
}
onExternalChange = value => {
this.setState({ value });
};
onChange = e => {
const value = e.currentTarget.value;
this.setState({ value });
if (value) {
this.props.sdk.field.setValue(value);
} else {
this.props.sdk.field.removeValue();
}
};
onButtonClick = async () => {
console.log('hurray');
};
render() {
return (
<Button buttonType="primary" isFullWidth={false}
onClick={this.onButtonClick}>
Add Content from AEM DAM
</Button>
);
}
}
Ideally i am trying to create an UI extension to be used in contentful space. I downloaded the contentful SDK and i have put in a button. But I receive this error on the console and it doesn't work
Screenshot:
https://github.com/contentful/create-contentful-extension
Go to the content of this Content Type and enable mixed content at
your browser so that development version that is served from your
local machine could be rendered within https://app.contentful.com.
Better yet:
I'm not the biggest fan of disabling the mixed content setting in browsers. Can I use HTTPS in development mode?
Yes, you can serve your extension using HTTPS. Add --https to start command.
"start": "contentful-extension-scripts start --https",
It uses Parcel HTTPS under the hood , which generates a self-signed certificate, you might have to configure your browser to allow self-signed certificates for localhost.
I think that will fix the 404 error and get things working.
Please follow the readme carefully and post a separate question if you still have problems.

Open a URL in system default browser

I have an electron app using angular. I want to open a URL in the system default browser. I tried the code below
import { ElectronService } from 'ngx-electron';
export class AutoBackupsComponent implements OnInit {
constructor(private electronService: ElectronService) { }
private onAction() {
this.electronService.shell.openExternal('https:www.//google.com');
}
}
On the other threads, everyone suggested this way but it is not working for me. I am not sure how can I make it running in either renderer or main process.

App Object in Electron Module and getAppPath throws Error

I have a strange problem with my application. I get an error, and I can't solve it. First at all, I installed a new project, so everything is clean. Someone sent me this repo to use for an Angular, Electron and Nodejs Application. Everything worked fine, but then I decided to install an embedded database like sqlite3. For this I found NeDB, and the module is perfect for my needs. First I had the problem, has nothing to do with my general problem, that I can't create a database file. So I read that I can only create files in my application path, because something about Electron and that's working in a browser.
I found the getAppPath() method that is implemented in my app object from the Electron module. Here starts the problem. For hours I tried to get the application path from this object. Finally, I wrote this code.
import { Injectable } from '#angular/core';
var nedb = require('nedb');
import { app } from 'electron';
import * as path from 'path';
#Injectable()
export class DatabaseService {
app: typeof app;
Database: any;
constructor() {
this.app = window.require("electron").app;
this.Database = new nedb({ filename: path.join(this.app.getAppPath(), '/diary.db'), autoload: true, timestampData: true });
var scott = {
name: 'Scott',
twitter: '#ScottWRobinson'
};
this.Database.insert(scott, function(err, doc) {
console.log('Inserted', doc.name, 'with ID', doc._id);
});
}
}
And I get this error.
I found this posting, but I don't really understand what the post is trying to tell me. I followed the links, but nothing seems to help. Anyone have an idea?

Resources