I started having this problem whenever I run "yarn run dev:server" and my application doesn't start. Does anyone know how to solve it?
A important OBS: The application is running on Docker with redis and peerjs
The full error:
Error: connect ETIMEDOUT 13.49.22.0:443
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1129:16)
[ERROR] 15:27:24 Error: connect ETIMEDOUT 13.49.22.0:443
When I run in production mode (yarn start)
Error: connect ETIMEDOUT 13.49.22.0:443
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1129:16) {
errno: -4039,
code: 'ETIMEDOUT',
syscall: 'connect',
address: '13.49.22.0',
port: 443,
type: 'FETCH',
sourceUrl: 'https://api.nodemailer.com/user'
I have the file .env:
# App settings
APP_API_URL=http://localhost:3333
APP_WEB_URL=http://localhost:3000
APP_ADMIN_URL=http://localhost:3001
APP_SECRET=admin
APP_DEFAULT_PAGE_LIMIT=50
PORT=3333
STORAGE_DRIVER=disk
MAIL_DRIVER=ethereal
I try configure with mailjet, but show the same error.
MailjetProvider.ts, where I belive the Mailjet is configured:
#injectable()
export default class MailjetMailProvider implements IMailProvider {
private client: Transporter;
constructor(
#inject('MailTemplateProvider')
private mailTemplateProvider: IMailTemplateProvider,
) {
this.client = nodemailer.createTransport({
host: mailConfig.mailjet.host,
port: mailConfig.mailjet.port,
secure: false,
auth: mailConfig.mailjet.auth,
});
}
public async sendMail({
to,
from,
subject,
templateData,
}: ISendMailDTO): Promise<void> {
const { name, email } = mailConfig.defaults.from;
await this.client.sendMail({
from: {
name: from?.name || name,
address: from?.email || email,
},
to: {
name: to.name,
address: to.email,
},
subject,
html: await this.mailTemplateProvider.parse(templateData),
});
}
}
mail.ts:
interface IMailConfig {
driver: 'ethereal' | 'ses';
mailjet: {
host: string;
port: number;
auth: {
user: string;
pass: string;
};
};
defaults: {
from: {
email: string;
name: string;
};
};
}
export default {
driver: process.env.MAIL_DRIVER || 'ethereal',
mailjet: {
host: process.env.MAILJET_HOST || '',
port: Number(process.env.MAILJET_PORT) || 587,
auth: {
user: process.env.MAILJET_USER || '',
pass: process.env.MAILJET_PASS || '',
},
},
defaults: {
from: {
email: process.env.MAIL_FROM,
name: process.env.MAIL_FROM_NAME,
},
},
} as IMailConfig;
EtherealMailProvider.ts, where Ethereal is config.
#injectable()
export default class EtherealMailProvider implements IMailProvider {
private client: Transporter;
constructor(
#inject('MailTemplateProvider')
private mailTemplateProvider: IMailTemplateProvider,
) {
nodemailer.createTestAccount().then(account => {
const transporter = nodemailer.createTransport({
host: account.smtp.host,
port: account.smtp.port,
secure: account.smtp.secure,
auth: {
user: account.user,
pass: account.pass,
},
});
this.client = transporter;
});
}
public async sendMail({
to,
from,
subject,
templateData,
}: ISendMailDTO): Promise<void> {
const { name, email } = mailConfig.defaults.from;
const message = await this.client.sendMail({
from: {
name: from?.name || name,
address: from?.email || email,
},
to: {
name: to.name,
address: to.email,
},
subject,
html: await this.mailTemplateProvider.parse(templateData),
});=
}
Related
I keep getting this error upon starting my nestjs application:
TypeError: Cannot read property 'retryAttempts' of undefined
The error is originating from my common config file, which was loaded into my configurations in app.module. I had tried call an await function in it and it gave me the retryattempts undefined error.
However, after commenting out that line, the error is resolved.
Context: I am trying to load variables from a pcf config server in place of env variables.
getEnvfrompcfconfig
import { getPcfServerClientCredentials } from '#common/configurations/pcf-credentials.config';
import axios, { AxiosResponse } from 'axios';
import * as client from 'cloud-config-client';
import { getAppEnv } from 'cfenv';
export const getEnvFromPcfConfigServer = async () => {
const appEnv = getAppEnv();
const pcfCredentials = getPcfServerClientCredentials();
const { client_secret, client_id, access_token_uri, uri } = pcfCredentials;
const accessToken: string = await axios
.post(
access_token_uri,
new URLSearchParams({
grant_type: 'client_credentials', //gave the values directly for testing
client_id,
client_secret,
}),
)
.then((res: AxiosResponse) => {
return res.data.access_token;
})
.catch((e) => console.log('cannot get access token', e));
const options: client.Options = {
name: 'application',
rejectUnauthorized: false,
endpoint: uri,
profiles: [appEnv.app.space_name || 'dev'],
headers: { authorization: `bearer ${accessToken}` },
};
const config = await client.load(options);
const url = config.get('baseurl');
return url;
};
config file
import { ScheduleLog as ScheduleLogEntity } from '#scheduleLog/entities/schedule-log.entity';
import { CustomNamingStrategy } from '#common/helpers/database/database.helper';
import { Schedule as ScheduleEntity } from 'src/schedule/entities/schedule.entity';
import { ICommonConfiguration } from '#common/interfaces/configurations/common-configuration';
import { HttpsProxyAgent } from 'https-proxy-agent';
import { getCreds } from '#common/configurations/credhub.config';
export const configuration = async () => {
const {
APP_PORT,
ENVIRONMENT,
MARIADB_HOST,
MARIADB_PORT,
MARIADB_USERNAME,
MARIADB_PASSWORD,
MARIADB_DATABASE,
AUTH_PASSWORD,
EUREKA_AWS_URL,
EUREKA_UAA,
EUREKA_PCF,
EUREKA_DATALOADER,
EUREKA_COMMS,
EUREKA_PROXY_HOST,
EUREKA_PROXY_PORT,
EUREKA_FULFILMENT,
} = process.env;
const creds = getCreds();
const thing = await getEnvFromPcfConfigServer(); //<-- line that is causing problem
console.log('thing', thing);
return {
APP: {
PORT: Number(APP_PORT),
ENVIRONMENT,
},
UAAPASSWORD: creds.uaaPassword || AUTH_PASSWORD,
DATABASE: {
type: 'mysql',
host: MARIADB_HOST,
port: Number(MARIADB_PORT),
username: MARIADB_USERNAME,
password: MARIADB_PASSWORD || creds.mariaDbPassword,
database: MARIADB_DATABASE,
entities: [ScheduleEntity, ScheduleLogEntity],
synchronize: false,
namingStrategy: new CustomNamingStrategy(),
// autoLoadEntities: true,
},
HTTPMODULE: {
BASEURL: {
AWS: EUREKA_AWS_URL,
UAA: EUREKA_UAA,
PCF: EUREKA_PCF,
DATALOADER: 'hi',
COMMS: EUREKA_COMMS,
FULFILMENT: EUREKA_FULFILMENT,
},
PROXYAGENT: new HttpsProxyAgent({
host: EUREKA_PROXY_HOST,
port: EUREKA_PROXY_PORT,
}),
},
};
};
App.module
ConfigModule.forRoot({
isGlobal: true,
load: [configuration],
envFilePath: `.env.stage.${appEnv.app.space_name || 'local'}`,
}),
I find this very weird. Anyone able to help?
I am trying to develop a mail sending module in my NestJs project. when I send the mail through my local machine it works fine. But when it goes to the server (digital-ocean droplet) it throws the following error and it does not send any email further. what is going on and fix this?
My code segment is below:
Auth controller
#Post('register')
async register(#Body() register: RegisterRequest) {
const res = await this.authService.register(register);
if (res instanceof Error) {
throw res;
}
return {
statusCode: 200,
message:
'Your account is registered successfully. Please check your email to verify your account',
};
}
Auth Service
async register(register: RegisterRequest): Promise<any> {
register.isRegister = true;
register.status = 0;
register.roleId = 5;
const user = await this.userService.save(register);
console.log('User Saved');
if (user instanceof User) {
if (register.isRegister) {
console.log('IS REGISTER');
// Generate Token
const resultsToken = await this.userTokenService.save(user.id, 1);
console.log('USER TOKEN SAVED');
if (resultsToken) {
this.mailService.sendUserConfirmation(user, resultsToken.token);
}
}
}
return user;
}
User Service
async save(register: RegisterRequest): Promise<User> {
try {
const token = generateToken(8);
const user = new User();
user.email = register.email;
user.firstName = register.firstName;
user.lastName = register.lastName;
user.password = hashPassword(register.password || token);
user.role = register.roleId;
user.phoneNumber = register.phoneNumber;
user.isActive = register.status;
const errors = await validate(user);
if (errors.length > 0) {
throw new ParameterMissingException(
errors[0].constraints[Object.keys(errors[0].constraints)[0]],
);
}
const existing = await this.findOneByEmail(register.email);
if (existing) {
throw new EntityFoundException('Email');
}
const registered = await this.userRepository.save(user);
return registered;
} catch (error) {
return error;
}
}
User Token service
async save(userId: number, type: number): Promise<UserToken> {
try {
const userToken = new UserToken();
userToken.user = userId;
userToken.type = type;
userToken.token = generateToken();
if (type === 2) {
userToken.expireIn = 15;
}
console.log('USER TOKEN SAVE');
return await this.userTokenRepository.save(userToken);
} catch (error) {
console.log('USER TOKEN ERROR');
return error;
}
}
Mail Service
sendUserConfirmation(user: any, token: string) {
const url = `${
this.configService.get<string>('REGISTER_CONFIRM_URL') + token
}`;
console.log('MAIL SERVICE ' + url);
this.mailerService
.sendMail({
to: user.email,
// from: '"Support Team" <support#example.com>', // override default from
subject: 'Greetings from CEWAS!',
template: join(__dirname, 'templates') + './register-confirmation',
context: {
url,
},
})
.then((r) => console.log(r))
.catch((err) => {
console.log('MAIL SERVICE ERROR');
console.log(err);
});
}
Mail Module and Config
import { MailerModule } from '#nestjs-modules/mailer';
import { HandlebarsAdapter } from '#nestjs-
modules/mailer/dist/adapters/handlebars.adapter';
import { Module } from '#nestjs/common';
import { MailService } from './mail.service';
import { join } from 'path';
#Module({
imports: [
MailerModule.forRoot({
transport: {
service: 'gmail',
secure: true,
auth: {
user: '********#gmail.com',
pass: '********',
},
},
defaults: {
from: '"<No Reply>" <*******#gmail.com>',
},
template: {
dir: join(__dirname, 'templates'),
adapter: new HandlebarsAdapter(),
options: {
strict: true,
},
},
}),
],
providers: [MailService],
exports: [MailService],
})
export class MailModule {}
Hi try whit this configuration in your transport:
transport: {
host: 'smtp.gmail.com',
port: 465,
ignoreTLS: true,
secure: true,
auth: {
user: '********#gmail.com', //use the .env variable here for security
pass: '********'
},
}
and make sure you turned on access for less secure app
here the link: less secure app
UPDATED
I am getting the following error when trying to invoke my Lambda function
{
"errorType": "TypeError",
"errorMessage": "e is not a function",
"trace": [
"TypeError: e is not a function",
" at Runtime.handler (/var/task/serverless_sdk/index.js:9:88355)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
]
}
I have tracked this down to the reference to DB (see last few lines of schema.js DB should be imported at the top of schema.js
const { DB } = require('./db.js')
Indeed, when I try the same code on my local computer, there is no issue.
Does this have to do with some subtle ways how Lambda Functions (LF) are frozen for re-use in AWS? Where should I be initializing the DB connection in a LF?
I tried merging db.js into schema.js (no import) and I still get the same error.
I have checked the zip file that serverless loaded and it looks fine (node_modules and mine).
This is very hard to debug. So any tips in that direction would help.
server.js
const { ApolloServer } = require('apollo-server')
const { ApolloServer: ApolloServerLambda } = require('apollo-server-lambda')
const { typeDefs, resolvers, connect } = require('./schema.js')
// The ApolloServer constructor requires two parameters: your schema
// definition and your set of resolvers.
async function setup(where) {
if (where == 'local') {
const server = new ApolloServer({ typeDefs, resolvers })
let { url } = await server.listen()
console.log(`Server ready at ${url}`)
} else {
const server = new ApolloServerLambda({
typeDefs,
resolvers,
playground: true,
introspection: true,
cors: {
origin: '*',
credentials: true,
},
context: ({ event, context }) => (
{
headers: event.headers,
functionName: context.functionName,
event,
context
})
})
exports.graphqlHandler = server.createHandler()
}
}
let location = (process.env.USERNAME == 'ysg4206') ? 'local' : 'aws'
connect(location, setup)
schema.js
const { gql } = require('apollo-server')
const { GraphQLDateTime } = require('graphql-iso-date')
const { DB } = require('./db.js')
exports.typeDefs = gql`
scalar DateTime
type User {
id: Int
"English First Name"
firstName: String
lastName: String
addressNumber: Int
streetName: String
city: String
email: String
createdAt: DateTime
updatedAt: DateTime
}
type Query {
users: [User]
findUser(firstName: String): User
hello(reply: String): String
}
type Mutation {
addUser(user: UserType): User!
}
type Subscription {
newUser: User!
}
`
exports.resolvers = {
Query: {
users: () => DB.findAll(),
findUser: async (_, { firstName }) => {
let who = await DB.findFirst(firstName)
return who
},
hello: (_, { reply }, context, info) => {
console.log(`hello with reply ${reply}`)
console.log(`context : ${JSON.stringify(context)}`)
console.log(`info : ${JSON.stringify(info)}`)
return reply
}
},
Mutation: {
addUser: async (_, args) => {
let who = await DB.addUser(args.user)
return who
}
}
}
exports.connect = async (where, setup) => {
console.log(`DB: ${DB}') // BUG DB is returning null
await DB.dbSetup(where) //BUG these lines cause Lambda to fail
await DB.populate() //BUG these lines cause Lambda to fail
let users = await DB.findAll() //BUG these lines cause Lambda to fail
console.log(users) //BUG these lines cause Lambda to fail
await setup(where)
}
db.js
const { Sequelize } = require('sequelize')
const { userData } = require('./userData')
const localHost = {
db: 'm3_db',
host: 'localhost',
pass: 'xxxx'
}
const awsHost = {
db: 'mapollodb3_db',
host: 'apollodb.cxeokcheapqj.us-east-2.rds.amazonaws.com',
pass: 'xxxx'
}
class DB {
async dbSetup(where) {
let host = (where == "local") ? localHost : awsHost
this.db = new Sequelize(host.db, 'postgres', host.pass, {
host: host.host,
dialect: 'postgres',
logging: false,
pool: {
max: 5,
min: 0,
idle: 20000,
handleDisconnects: true
},
dialectOptions: {
requestTimeout: 100000
},
define: {
freezeTableName: true
}
})
this.User = this.db.define('users', {
firstName: Sequelize.STRING,
lastName: Sequelize.STRING,
addressNumber: Sequelize.INTEGER,
streetName: Sequelize.STRING,
city: Sequelize.STRING,
email: Sequelize.STRING,
})
try {
await this.db.authenticate()
console.log('Connected to DB')
} catch (err) {
console.error('Unable to connect to DB', err)
}
}
async select(id) {
let who = await this.User.findAll({ where: { id: id } })
return who.get({ plain: true })
}
async findFirst(name) {
let me = await this.User.findAll({ where: { firstName: name } })
return me[0].get({ plain: true })
}
async addUser(user) {
let me = await this.User.create(user)
return me.get({ plain: true })
}
async populate() {
await this.db.sync({ force: true })
try {
await this.User.bulkCreate(userData, { validate: true })
console.log('users created');
} catch (err) {
console.error('failed to create users')
console.error(err)
} finally {
}
}
async findAll() {
let users = await this.User.findAll({ raw: true })
return users
}
async close() {
this.db.close()
}
}
exports.DB = new DB()
serverless.yml
service: apollo-lambda
provider:
name: aws
stage: dev
region: us-east-2
runtime: nodejs10.x
# cfnRole: arn:aws:iam::237632220688:role/lambda-role
functions:
graphql:
# this is formatted as <FILENAME>.<HANDLER>
handler: server.graphqlHandler
vpc:
securityGroupIds:
- sg-a1e6f4c3
subnetIds:
- subnet-4a2a7830
- subnet-1469d358
- subnet-53b45038
events:
- http:
path: graphql
method: post
cors: true
- http:
path: graphql
method: get
cors: true
folder structure of zip
When AWS Lambda imports your file, the export isn't available yet. That's why it complains that your handler is not a function (because it is actually undefined at that time it is being imported).
Here are a couple of suggested solutions:
1. Use only apollo-server-lambda and use serverless-offline for local development. This way your handler code is exactly the same as what you have in Lambda.
const { ApolloServer: ApolloServerLambda } = require("apollo-server-lambda");
const { typeDefs, resolvers, connect } = require("./schema.js");
const server = new ApolloServerLambda({
typeDefs,
resolvers,
playground: true,
introspection: true,
cors: {
origin: "*",
credentials: true
},
context: ({ event, context }) => ({
headers: event.headers,
functionName: context.functionName,
event,
context
})
});
exports.graphqlHandler = server.createHandler();
2. Use apollo-server-lambda in your Lambda but use apollo-server in another file (e.g. local.js).. Then, you just use node local.js for local development. No need for that process.env.USERNAME check that you do at the end.
Found the problem. It is a bit embarrassing. But I post it in case others need this.
I was trying to connect to the DB as part of the initialization of the lambda app. Hoping that when the cold start or warm start happened, the variable with DB would be already holding the connection.
That is anti-pattern.
With apollo one has to reconnect to the DB on each request. that is in the resolver for the GraphQL one has to reconnect to the DB and then close it so that AWS can see there are no open connections and then close the Lambda function.
What threw me was this worked fine when running as ApolloServer and connecting to a local DB.
I have a NodeJS API working behind a corporate proxy and I have been trying to do authentication with Google with their NodeJS client:
const google = require('googleapis');
function getServiceAccountInfo() {
return {
type: 'service_account',
project_id: 'XXXXX',
private_key_id: 'XXXXXX',
private_key: 'XXXX',
client_email: 'XXXX',
client_id: 'XXXX',
auth_uri: 'XXXX',
token_uri: 'XXXX',
auth_provider_x509_cert_url: 'XXXX',
client_x509_cert_url: 'XXXXX'
};
}
const SCOPES = 'https://www.googleapis.com/auth/firebase.messaging';
let proxy2 = {
host: 'proxy.hkcsl.net',
port: 8080
};
const proxy3 = {
proxy: 'http://172.25.2.6:8080'
}
const proxy4 = {
proxy: {
host: '172.25.2.6',
port: 8080,
auth: {
username: '',
password: '',
},
}
}
process.env.HTTPS_PROXY = 'https://172.25.2.6:8080';
process.env.https_proxy = 'https://172.25.2.6:8080';
process.env.HTTP_PROXY = 'http://172.25.2.6:8080';
process.env.http_proxy = 'http://172.25.2.6:8080';
google.options({
proxy: proxy4.proxy
});
const key = getServiceAccountInfo();
const jwtClient = new google.auth.JWT(
key.client_email,
undefined, // null,
key.private_key,
SCOPES,
undefined, // null
);
jwtClient.authorize(function(err, tokens) {
if (err) {
console.error(err);
return;
}
console.log(tokens.access_token);
});
However, no matter how I configure the proxy option, I still either get a timeout error or something like
ERROR Error: write EPROTO 101057795:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:openssl\ssl\s23_clnt.c:827:
Some people managed to fix it by changing the port to 443 but it doesn't apply to my case since that port is not available to me inside the server. And I've already referenced on the discussions and solutions proposed here:
StackOverflow: node-request - Getting error “SSL23_GET_SERVER_HELLO:unknown protocol”
googleapis: There is no facility for passing a proxy to the oauth2client
Axios: Request to HTTPS with HTTP proxy fails
Using jwtClient.authenticate() behind a proxy results in ETIMEDOUT error
It also seems like Vue is also encountering a similar problem yesterday, they changed from using axios to using request instead. Is there a similar workaround for googleapis too?
After referencing on the workaround regarding the proxy issues with axios, which google-api-nodejs-client (i.e. googleapis) is using, and crawling through the source code of google-auth-library-nodejs (jwtclient.ts) and node-gtoken (index.ts), I wrote the following method to request token from Google manually as a temporary workaround:
const axios = require('axios-https-proxy-fix');
const querystring = require('querystring');
const jws = require('jws');
const GOOGLE_TOKEN_URL = 'https://www.googleapis.com/oauth2/v4/token';
const GOOGLE_REVOKE_TOKEN_URL =
'https://accounts.google.com/o/oauth2/revoke?token=';
const SCOPES = 'https://www.googleapis.com/auth/firebase.messaging';
const PROXY = {
host: '172.25.2.6',
port: 8080,
auth: {
username: '',
password: '',
}
};
function getServiceAccountInfo() {
return {
type: 'service_account',
project_id: 'XXXX',
private_key_id: 'XXXX',
private_key: 'XXXX',
client_email: 'XXXX',
client_id: 'XXXX',
auth_uri: 'https://accounts.google.com/o/oauth2/auth',
token_uri: 'https://accounts.google.com/o/oauth2/token',
auth_provider_x509_cert_url: 'https://www.googleapis.com/oauth2/v1/certs',
client_x509_cert_url: 'XXXX'
};
}
function requestToken(client_email, private_key) {
const iat = Math.floor(new Date().getTime() / 1000);
const additionalClaims = {};
const payload = Object.assign(
{
iss: client_email,
scope: SCOPES,
aud: GOOGLE_TOKEN_URL,
exp: iat + 3600,
iat,
sub: undefined
},
additionalClaims);
const signedJWT =
jws.sign({header: {alg: 'RS256'}, payload, secret: private_key});
return axios({
method: 'post',
url: GOOGLE_TOKEN_URL,
data: querystring.stringify({
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: signedJWT
}),
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
proxy: PROXY
})
.then(r => {
const body = r.data;
console.log(body);
return body.access_token;
})
.catch(e => {
const body = (e.response && e.response.data) ? e.response.data : {};
let err = e;
if (body.error) {
const desc =
body.error_description ? `: ${body.error_description}` : '';
err = new Error(`${body.error}${desc}`);
}
throw err;
});
}
const key = getServiceAccountInfo();
requestToken(key.client_email, key.private_key);
Reference: GitHub
The best solution I stumbled upon (on macOS) is to use proxychains4 with the following config
strict_chain
tcp_read_time_out 15000
tcp_connect_time_out 8000
localnet 127.0.0.0/255.0.0.0
[ProxyList]
http {your proxy ip address} {your proxy port}
Whenever the server starts, I see the following console error message:
Server started at: https://localhost:3333
170929/232536.579, [log,connection,client,error] message: socket hang up, stack: Error: socket hang up
at TLSSocket.<anonymous> (_tls_wrap.js:829:25)
at emitOne (events.js:95:20)
at TLSSocket.emit (events.js:182:7)
at Socket.<anonymous> (net.js:484:12)
at Socket.g (events.js:273:16)
at emitOne (events.js:90:13)
at Socket.emit (events.js:182:7)
at TCP._onclose (net.js:484:12)
I was able to determine that if I removed the tls option from the server.connection, the error disappears.
This is the code in the server
import Hapi from 'hapi';
import inert from 'inert';
import fs from 'fs';
import { apiRoutes } from './api/api-routes';
import { serverConfig } from 'common';
import _ from 'lodash';
const good = require('good');
const server = new Hapi.Server();
const tls = {
key: fs.readFileSync('cert/server-key.pem'),
cert: fs.readFileSync('cert/server-crt.pem'),
ca: fs.readFileSync('cert/ca-crt.pem'),
};
const host = serverConfig.host;
const port = serverConfig.port;
server.connection({
address: '0.0.0.0', // listen on all interfaces!
host,
port,
tls,
});
const options = {
reporters: {
myConsoleReporter: [{
module: 'good-squeeze',
name: 'Squeeze',
args: [{ log: '*', response: '*' }],
}, {
module: 'good-console',
}, 'stdout'],
myFileReporter: [{
module: 'good-squeeze',
name: 'Squeeze',
args: [{ ops: '*' }],
}, {
module: 'good-squeeze',
name: 'SafeJson',
}, {
module: 'good-file',
args: ['./hapi.log'],
}],
},
};
server.register([
{
register: inert,
},
{
register: good,
options,
},
],
(err) => {
if (err) {
throw
// define static ui
server.route({
method: 'GET',
path: '/{path*}',
handler: {
directory: {
path: serverConfig.staticAssetsDir,
},
},
});
// start server
server.start(() => {
console.log(`Server started at: ${server.info.uri}`);
});
}
);
What could be the issue, and how could I get started debugging this?