I'm working on an app build with Electron and a config file is saved after login.
When the app is reopened in development, it works, but when it's reopened after being distributed with electron-builder, I have to login again.
Code
const {writeFile} = require('fs');
const {join} = require('path');
function write(config) {
writeFile(join(__dirname, './config.json'), JSON.stringify(config, null, 4), (err) => {
cb(err);
})
}
write(someJsonObject);
Project:
Electron 1.7.11
Electron-builder 19.55.2
Node 8.8.1
First check your are not building asar file for your production app since it is read-only and you are trying to write directly to __dirname.
My suggestion is to use writable directory for your configuration file, for example:
const fs = require('fs');
const _HOME_ = require('os').homedir();
const _SEP_ = require('path').sep;
const _APPHOME_ = `${_HOME_}${_SEP_}.myapp${_SEP_}`;
if (!fs.existsSync(_APPHOME_)) {//Check dir exists or create it
fs.mkdir(_APPHOME_, '0777', true, function () {
console.log('Created app home dir :)');
});
}
fs.writeFile(_APPHOME_ + 'config.json'), JSON.stringify(config, null, 4), (err) => {
cb(err);
});
Of course, you may want to accommodate this solution to your needs. Hope works for you!
Related
I am used to working on httpd ( Apache ) which provides a way to configure subdomains which is mapped to a directory.
How can I do the same thing in Connect.js/Express.js ? I see that the only thing that I have is routes which I am not sure how I can use to configure sub domains. I have subdomains like m.mysite.com, sync.mysite.com
Can someone help ?
Or alternatively you could use vhost.
Then, create several sites in their own directory and export the express app, eg. /path/to/m/index.js:
var app = express()
/* whatever configuration code */
exports.app = app
// There is no need for .listen()
And then handle all requests with the following app:
var vhost = require('vhost');
express()
.use(vhost('m.mysite.com', require('/path/to/m').app))
.use(vhost('sync.mysite.com', require('/path/to/sync').app))
.listen(80)
Note that /path/to/m and /path/to/sync can be absolute paths (as written above) or relative paths.
You could append a subdomain to a request and then check for it in subsequent next() calls.
I got the following code from > http://groups.google.com/group/express-js/browse_thread/thread/b04bbaea7f0e8eed (so full credit to the original author)
app.get('*', function(req, res, next){
if(req.headers.host == 'some.sub.domain.com') //if it's a sub-domain
req.url = '/mysubdomain' + req.url; //append some text yourself
next();
});
// This will mean that all get requests that come from the subdomain will get
// /subdomain appended to them, so then you can have routes like this
app.get('/blogposts', function(){
// for non-subdomain
});
app.get('/mysubdomain/blogposts', function(){
// for subdomain
});
I have recently came across this problem, and wrote a module to help with it using express 4. https://www.npmjs.org/package/express-subdomain.
Example - api subdomain.
var express = require('express');
var app = express();
var router = express.Router();
//api specific routes
router.get('/', function(req, res) {
res.send('Welcome to our API!');
});
router.get('/users', function(req, res) {
res.json([
{ name: "Brian" }
]);
});
app.use(subdomain('api', router));
app.listen(3000);
Check out the module on npm to see more examples.
I created a module to help with subdomains in Express: https://github.com/WilsonPage/express-subdomain-handler
Do as I say, create two express app in different folder.
For example:
one app in /blogsite directory
const express = require("express");
const blog = express();
blog.get("/", (req, res) => {
res.send("BLOG SECTION");
});
blog.get("/allblogs", (req, res) => {
res.json([
{ title: "csgo major boston", description: "Best CSGO major ever" },
{ title: "Blast pro series", description: "Coolest series of CSGO" },
]);
});
module.exports = { blog };
and another one in /portfolio directory
const express = require("express");
const portfolio = express();
portfolio.get("/", (req, res) => {
res.send("PORTFOLIO SECTION");
});
portfolio.get("/resume", (req, res) => {
res.send("HERE'S MY RESUME");
});
module.exports = { portfolio };
Now create a main app in the outer folder and import the other two express apps that you just made in /blogsite directory and /portfolio directory.
And in the main app do this,
const express = require("express");
const vhost = require("vhost");
const { blog } = require("./blogsite");
const { portfolio } = require("./portfolio");
const app = express();
// BLOG AND PORTFOLIO
// url: http://blog.localhost:3002/
// url: http://blog.localhost:3002/allblogs
// url: http://portfolio.localhost:3002/
// url: http://portfolio.localhost:3002/resume
app
.use(vhost("portfolio.localhost", portfolio))
.use(vhost("blog.localhost", blog));
// MAIN APP ROUTES OR ENDPOINTS
// url: http://localhost:3002
// url: http://localhost:3002/myhobbies
app.get("/", (req, res) => {
res.send("MAIN APP SECTION");
});
app.get("/myhobbies", (req, res) => {
res.send("MAIN APP -> myhobbies section");
});
app.listen(3002, () => {
console.log("started listening");
});
fileStructure at the end should be looking like this
main(folder)
index.js (main express app which you need to run using node or nodemon)
blogsite(folder that I talked about for blog.localhost)
index.js (blog express app)
portfolio(folder)
index.js (portfolio express app)
I've had this exact same requirement for a project I was working on and ended up throwing together a middleware-based solution. It allows you to define routers and view folders per subdomains.
Check it out on NPM https://www.npmjs.com/package/express-multiview
or GitHub https://github.com/daryl-cecile/express-multi-view#readme
I've built few pages of a static website using ExpressJS and PUG to get the advantage of the template engine.
But now I need to export all the raw HTML that is being rendered by all ExpressJS Routes.
Is there any package that can help me to do that? Or I've to write custom command and iterate over all the Routes and save the rendered output?
If a custom command is the only way, how do I iterate over all the routes and get the rendered output?
I couldn't find any library or resource to achieve what I wanted. But with some of my dirty code, hacks, and packages I was able to export all the routes.
Note: Instead of writing a node command to export the htmls, I've added a route to trigger the operations here is the code for the route:
app.use('/export_templates', router.get('/', async function (req, res, next) {
const endpoints = listEndpoints(app);
const failedEndpoints = [];
for (const i in endpoints) {
const endpoint = endpoints[i];
if (endpoint.path == '/export_templates') {
continue;
}
try {
const res = await axios.get('http://'+req.headers.host+''+endpoint.path+'?export=true');
}
catch(error) {
failedEndpoints.push(endpoint.path);
}
}
res.json({
"status": "succes",
"message": "Please check templates folder for the latest exported html templates",
"failed": failedEndpoints
})
}));
Basically this route iterates and makes a request to all the available routes with a export=true parameter.
Then inside every route view function a condition checks if the export parameter is available then calls the exportTemplateFile function with the pug template location and new file name as the function parameter.
If the request doesn't contain export parameter the requested route will simply output what template.
An example route:
router.get('/', function(req, res, next) {
if (req.query.export) {
exportTemplateFile('views/index.pug', 'index.html');
}
res.render('index.pug');
});
And here is the code for 2 util function to complete the export process
function createTemplateFile(filename) {
fs.open(filename,'r',function(err, fd){
if (err) {
fs.writeFile(filename, '', function(err) {
if(err) {
console.log(err);
}
});
}
});
}
function exportTemplateFile(templateLocation, templateName) {
const html = pretty(pug.renderFile(templateLocation));
createTemplateFile('templates/'+templateName);
var stream = fs.createWriteStream('templates/'+templateName);
stream.once('open', function (fd) {
stream.write(html);
stream.end();
});
}
The createTemplateFile function simply creates a new file if it doesn't exist.
The exportTemplateFile function saves the HTML in the html variable rendered by pug and prettifies it with the pretty package and then overwrites the new template file.
Note: In my case all the pug templates were static so I didn't have to pass any context to the pug.renderFile function. But if you need any context to be used inside the pug template you can simply pass that with the template location.
Edited version of the same answer.
First of all thank you so much for solving this problem.
I have made some changes to your code as per new errors.
Here is the code with async and await function for ejs users
const express = require('express')
const ejs = require('ejs')
const fs = require('fs')
const app = express()
const port = 3000
//set the templating engine as ejs
app.set('view engine', 'ejs');
function createTemplateFile(filename) {
fs.open(filename,'r',function(err, fd){
if (err) {
fs.writeFile(filename, '', function(err) {
if(err) {
console.log(err);
}
});
}
});
}
async function exportTemplateFile(templateLocation, templateName) {
var html = await ejs.renderFile(templateLocation);
createTemplateFile('templates/'+templateName);
var stream = fs.createWriteStream('templates/'+templateName);
stream.once('open', function (fd) {
stream.write(`${html}`);
stream.end();
});
}
app.get('/', (req, res, next) => {
res.render('./pages/home')
exportTemplateFile('views/pages/home.ejs', 'index.html');
console.log('file rendered and saved successfully')
})
app.listen(port, () => {
console.log(`App is listening on port ${port}`)
})
I am creating one web application using AdonisJs in backend and ReactJs in frontend.
While integrating both frameworks i am struggling to return index.html file of ReactJs on '/' route path from AdonisJs, since AdonisJs is supporting edge.js for view.
Is there any solution in AdonisJs similar to expressjs returning HTML file as given below
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'build')));
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(9000);
Currently my AdonisJs route returning edge file like,
Route.any('*', ({view}) => view.render('index'))
You can change template file extensions in config file which resides on config/app.js.
{
static: {
extensions: ['html']
}
}
For this you need to be running Adonis by motorcycle stack, if using only as API it will only return JSON rendered responses
now if you are in an Adonis stack installation just use the view object that looks like this:
Route.get('/page', ({ view }) => {
view.render('name_of_view')
})
I'm using Next.js to build my website. I modify the server using express.js server so I have server.js on my root folder of my project.
When I started the server npm run dev which run node server.js, my home page renders correctly. But when I navigate to some of other page in my website, the css is not loaded. But if I refresh the page, it will load the css and the problem is gone
const express = require('express')
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const app = next({dev})
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = express()
server.get('*', (req, res) => {
return handle(req, res)
})
const port = process.env.PORT || 3000
server.listen(port, err => {
if (err) throw err
console.log(`> Ready on port ${port}...`)
})
})
Here's my server.js file. I think there is no problem with the code.
I use #zeit/next-less package for compiling my LESS stylesheet
Please help
Thanks
Check this out: https://github.com/zeit/next-plugins/issues/282
In short as a workaround:
Create an empty CSS file in /static/ directory.
Import it in _app.js:
import '../static/jank-empty.css';
I hope that it would help.
For me the issue was that the nextjs wasn't loading the rel=stylesheet link tags. It was only able to load rel=preload link tags.
so I did a workaround like this:
document.querySelectorAll("link[rel='preload'][as='style']").forEach(link => link.rel = "stylesheet")
I am currently using MySQL for the db instead of the popular mongodb, since that is the case there isn't much documentation out there as far as architecture and getting set up. This is my current structure
client
-- angular files
routes
-- index.js
views
-- 404 page
app.js
I don't understand how I can implement controllers or models into this structure. I'm currently grabbing data from the db or sending it with the routes..I'm not sure what the added layer of controllers would do. Maybe this is a dumb question but I would just like to have a clear baseline so that my project will scale well. I feel like there should be way more to this than what I currently have.
index.js
const express = require('express');
const mysql = require('mysql');
const router = express.Router();
const db = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'password',
database : 'db'
});
// Connect
db.connect((err) => {
if(err){
throw err;
}
console.log('MySql Connected...');
});
// Select Data
router.get('/getData', (req, res) => {
let sql = 'SELECT * FROM data';
let query = db.query(sql, (err, results) => {
if(err) throw err;
console.log(results);
res.send(results)
});
});
module.exports = router;
app.js
const express = require('express');
const mysql = require('mysql');
const bodyParser = require('body-parser');
const path = require('path');
const cors = require('cors');
const compression = require('compression');
const helmet = require('helmet')
const expressSanitizer = require('express-sanitizer');
const index = require('./routes/index');
const app = express();
const port = 3000;
var corsOptions = {
origin: 'http://localhost:8100',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
// var logger = (req, res, next) => {
// console.log('logging...')
// next();
// }
//added security
app.use(helmet())
// //set logger
// app.use(logger)
//cors options
app.use(cors(corsOptions))
//body parser middleware
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: false}))
// Mount express-sanitizer here
app.use(expressSanitizer()); // this line follows bodyParser() instantiations
//set static path
app.use(express.static(path.join(__dirname, 'client')));
// set our default template engine to "ejs"
// which prevents the need for using file extensions
app.set('view engine', 'ejs');
//gzip compression
app.use(compression())
//set views for error and 404 pages
app.set('views', path.join(__dirname, 'views'));
app.use('/', index);
app.use('/fp/trips', trips);
app.listen(port, () => {
console.log('server started on port 3000')
})
When working on Node apps I tend to favor a scheme where controllers are (almost) services -- I think it works really well for small applications.
This is an example:
index.js
let app = express()
let users = require('./services/users')
app.get('/users/:id', async function(req, res, next) => {
try {
res.json(users.getByid(req.params.id))
} catch() {
next(err)
}
})
app.listen(8080)
services/users.js
let db = require('./db')
async function getById(id) {
let conn = await db.connect()
let user = conn.query('SELECT * FROM user WHERE id = ?', [id])
if (!user) {
throw new Error("404")
}
return user
}
module.exports = {getById}
services/db.js
let realDb = require('some-open-source-library-to-interact-with-db')
realDb.initialize(process.env.DB_CREDENTIALS) // pseudo-code here
module.exports = realDb
This though, won't work well when you're building large, complex apps -- I think you will require more structure in that case.
PS: I wouldn't suggest to build a large, complex app ever -- split it into smaller ones where patterns like the one I presented work nicely.
You can use Sequelize as ORM (Object Relational Mapper) for your MySQL DB to make your code more readable and to allow you to create better structure of your app. It also has support for PostgreSQL, MySQL, MariaDB, SQLite, and MSSQL.
There are samples out there how to integrate Sequelize with Express. I'm not sure if I'm allowed to post a github repository here but here it is:
https://github.com/jpotts18/mean-stack-relational
PS. I don't own this repository but this might help you somehow.