Hapi.js views not seeing local scripts - javascript

I'm currently working on an app with a server that uses Hapi, and I am running into a problem whenever I try to load a .jade file. Here is the current code for my index.js file:
var Hapi = require('hapi');
var internals = {};
internals.main = function() {
var options = {
views: {
engines: { jade: 'jade' },
path: '../app',
compileOptions: {
pretty: true
}
}
};
this._server = new Hapi.createServer('localhost', 8000, options);
this._server.route({
method: 'GET',
path: '/',
handler: function(request, reply) {
reply.view('index')
}
});
// Start server.
this._server.start()
};
internals.main();
The file has a series of local scripts and CSS files that are in the app directory, but when the page index.jade is loaded, it does not see those local files. Is there something I need to add/modify in my options, or is this location of local scripts and style files a problem with jade compilation using Hapi?

I was looking for a similar solution, while trying to setup a single page application with angular.js and hapi.js
I have found that adding the configuration below to your server routes will help to make CSS, JS, ... files in '/public' directory visible to the application.
server.route({
method: "GET",
path: "/public/{path*}",
handler: {
directory: {
path: "./public",
listing: false,
index: false
}
}
});
Hope it helps.

Related

Webpack Devserver: Open page in browser without typing '.html'

I'm making a plain, static site (HTML/CSS/JS) with Webpack that I intend to eventually deploy to s3. I have my final HTML files exported to the root of my dist folder like, index.html, foo.html, bar.html.
When I go to localhost:9000, my index loads as expected. For foo and bar I have to type the file extension like /foo.html and /bar.html for those pages to load. Is there a setting that I'm missing that will allow me to simply type /foo and /bar in the browser and have the intended pages load?
One way I found for individual pages, is to specify a proxy using devServer.proxy. For /foo and /bar, this would look like that:
const path = require("path");
module.exports = {
...
devServer: {
static: {
directory: path.resolve(__dirname, 'dist')
},
port: 3000,
open: false,
hot: true,
proxy: {
'/foo': {
target: 'http://localhost:3000/foo.html',
pathRewrite: { '^/foo': '' }
},
'/bar': {
target: 'http://localhost:3000/bar.html',
pathRewrite: { '^/bar': '' }
}
}
}
}
Check the DevServer documentation for more options.
In addition to Nikolai's answer, in case you need your local dev server to serve urls w/o extensions in router history mode, just use the following:
historyApiFallback: {
rewrites: [
{ from: /^\/$/, to: '/views/landing.html' },
{ from: /^\/subpage/, to: '/views/subpage.html' },
{ from: /./, to: '/views/404.html' },
],
},
Source: https://webpack.js.org/configuration/dev-server/#devserverhistoryapifallback

Vue setup different vue.config.js configurations for different environments

I have a multi-page app that I need some pages to show only in my development environment. This is my vue.config.js:
module.exports = {
productionSourceMap: false,
pages: {
index: "src/main.js",
admin: {
entry: "src/main-admin.js",
template: "public/index.html",
filename: "admin"
}
}
};
I need the index page to go to my production build, but the admin to be removed from it. Is there a way to add an environment-conditional configuration on vue.config.js, or to add one vue.config.js per environment?
vue.config.js is javascript, so you can do pretty much anything you want in there. In your case you could do something like:
let config = {
productionSourceMap: false,
pages: {
index: "src/main.js",
}
}
if (process.env.NODE_ENV != 'production') {
config.pages.admin = {
entry: "src/main-admin.js",
template: "public/index.html",
filename: "admin"
}
}
module.exports = config
If you need more environments than the 'builtin' production, development etc, you can create your own by creating .env files, for example a file called .env.myenv containing NODE_ENV=myenv
https://cli.vuejs.org/guide/mode-and-env.html#modes

Defining Auth strategy using Glue

I am using glue to spin up the hapi server so I gave the json object with connection and registration details.
I have 10 routes and i need to use authentication strategy for all the 10 routes, So followed the below steps
1) I have registered the xyz custom auth plugin
2) Defined the strategy server.auth.strategy('xyz', 'xyz', { });
3) At every route level I am enabling auth strategy
auth: {
strategies: ['xyz'],
}
How can I give below line to glue configuration object itself.
server.auth.strategy('xyz', 'xyz', { });
Glue.compose(ServerConfig, { relativeTo: baseDir }, (err, server) => {
internals.server = server;
})
One more question here is, in this line server.auth.strategy('xyz', 'xyz', { from json file}); I am reading the JSON data from a config file. When I change the data in this JSON file I dont want to restart the server manually to load the modified data. Is there any plugin or custom code to achieve this?
I figured out a general workaround for when you want to do setup that Glue does not directly support (AFAIK) and you also don't want to keep adding to index.js.
Create a plugins folder where your manifest.js is located.
Create a file plugins/auth.js (in this case). Here you will have a register callback with access to the server object and you can make setup calls that go beyond what Glue does declaratively.
Add a plugin item to manifest.js pointing to your plugin file.
in manifest.js:
register: {
plugins: [
{
plugin: './plugins/auth',
},
]
}
in plugins/auth.js:
module.exports = {
name: 'auth',
async register (server) {
await server.register([
require('#hapi/cookie'),
]);
server.auth.strategy('session', 'cookie', {
cookie: {
name: 'sid-example',
password: '!wsYhFA*C2U6nz=Bu^%A#^F#SF3&kSR6',
isSecure: false
},
redirectTo: '/login',
validateFunc: async (request, session) => {
const account = await users.find(
(user) => (user.id === session.id)
);
if (!account) {
return { valid: false };
}
return { valid: true, credentials: account };
}
});
server.auth.default('session');
},
};
(auth setup code is from the Hapi docs at enter link description here)
This is the way I have found where I can call things like server.auth.strategy() sort-of from manifest.js.
Note: Auth is not a great example for this technique as there is a special folder for auth strategies in lib/auth/strategies.

how can i convert this code using iron-router instead of router

https://github.com/davebryson/meteor_file_upload_example
the above is the original code using Meteor.router
and i wanted to convert this code only using iron-router, instead of previous router package
but the problem is when i upload file,
i can't understand how to convert these code using iron-router api.
i think there's a problem with index.html and serverside main.js code but i can't fix that.
would you please convert this code below using iron router plz?
in serverside main.js in the original code.
Meteor.Router.configure(
{
bodyParser:
{
uploadDir: 'uploads',
hash: 'sha1',
keepExtensions : true
}
}
);
Meteor.Router.add('/upload/file', 'POST',
function()
{
var title = this.request.body.fileTitle,
size = this.request.files.fileInfo.size,
path = this.request.files.fileInfo.path,
name = this.request.files.fileInfo.name,
obj = {title: title, size: size, path: path, name: name};
Files.insert(obj);
// redirect to root
return [301, {Location: '/'}, ""]
}
);
and i'v already converted the code in clientside main.js like below
Router.map(function () {
this.route('listFiles', {path: '/'});
this.route('addFile', {path: '/add'});
});
Template.listFiles.helpers({
list: function () {
return Files.find({});
}
});
Template.listFiles.events({
'click #addFileBtn' : function(e) {
e.preventDefault();
Router.go('/add');
}
});
Template.addFile.events({
'click #cancelBtn': function(e){
e.preventDefault();
Router.go('/');
}
});
Meteor.subscribe("files");
the point is that i can't handle how to use http method in serverside code with iron-router
Meteor now directly allows you to attach middleware to the server using the WebApp package, with standard Connect handlers.
Put webapp inside .meteor/packages of your app. You can then attach middleware to WebApp.connectHandlers inside your app. It's not too well documented yet, but treat it as a normal connect server.

Cordova on WP8: requirejs can't resolve views

I have a web application that uses requirejs to load its modules. The web applications works without problems in any desktop browser, it also works on iOS and Android when packaged with Cordova. Does however NOT work when building a Windows Phone 8 Cordova application.
I get the following error:
"View Not Found: Searched for "views/shell" via path "text!views/shell.html"
(I'm using Durandal)
I have the following application structure:
lib/require/require.js
www/app/viewmodels/shell.js
www/app/views/shell.html
www/app/main.js
www/index.html (contains line: )
:
www/app/main.js contains the following code:
requirejs.config({
//baseUrl: 'x-wmapp0:www/app',
baseUrl: 'app',
enforceDefine: true,
paths: {
'text': '../lib/require/text',
'durandal':'../lib/durandal/js',
'plugins' : '../lib/durandal/js/plugins',
'transitions' : '../lib/durandal/js/transitions',
'knockout': '../lib/knockout/knockout-2.3.0',
'bootstrap': '../lib/bootstrap3/js/bootstrap',
'jquery': '../lib/jquery/jquery-1.9.1',
'modules' : 'modules'
},
shim: {
'bootstrap': {
deps: ['jquery'],
exports: 'jQuery'
}
}
});
define(['durandal/system', 'durandal/app', 'durandal/viewLocator', 'bootstrap'], function (system, app, viewLocator, bootstrap) {
//>>excludeStart("build", true);
system.debug(true);
//>>excludeEnd("build");
app.title = 'MyApp';
app.configurePlugins({
router: true,
dialog: true,
widget: true
});
app.start().then(function() {
//Replace 'viewmodels' in the moduleId with 'views' to locate the view.
//Look for partial views in a 'views' folder in the root.
viewLocator.useConvention('viewmodels', 'views', 'views');
//Show the app by setting the root view model for our application with a transition.
app.setRoot('viewmodels/shell', 'entrance', 'applicationHost');
});
});
This code works perfectly on all devices except WP8. I tried the line baseUrl: 'x-wmapp0:www/app' to set the actual path used internally by WP8 Cordova, but that does not work. Is that because it is not a path starting with '/' or http?
Any ideas on how to configure requirejs to be able to load modules and views using requirejs?
See if this is any help to you http://mikaelkoskinen.net/durandal-phonegap-windows-phone-8-tutorial/
Also, as of the 18th October 2013, Phonegap Build has added beta support for WP8. Add "winphone: as the gap:platform and ensure you're using phonegap 3.0. We're currently having no luck but maybe you can use that.
I just solve this problem for myself as well, what I ended up doing was waiting for the deviceloaded event before I loaded my main.js.
Cordova applies a patch to XMLHttpRequest which has been applied when deviceloaded has been triggered.
In my app I it ended up looking similar to this:
<script src="js/require.js"></script>
<script>
document.addEventListener('deviceloaded', function() {
var script = document.createElement('script');
script.src = 'js/main.js';
document.body.appendChild(script);
}, false);
</script>
I hope that works out for you as well!
One other thing, I noticed in my app that if I try to load weinre I couldn't get my app started at all with require.js. I haven't been able to research this further yet though.
I recommend to set a breakpoint to cordovalib/XHRHelper.cs HandleCommand method and see what is going on. Also the following version of HandleCommand could work better for you
public bool HandleCommand(string commandStr)
{
if (commandStr.IndexOf("XHRLOCAL") == 0)
{
string url = commandStr.Replace("XHRLOCAL/", "");
Uri uri = new Uri(url, UriKind.RelativeOrAbsolute);
try
{
using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
{
if (isoFile.FileExists(uri.AbsolutePath))
{
using (
TextReader reader =
new StreamReader(isoFile.OpenFile(uri.AbsolutePath, FileMode.Open, FileAccess.Read))
)
{
string text = reader.ReadToEnd();
Browser.InvokeScript("__onXHRLocalCallback", new string[] { "200", text });
return true;
}
}
}
url = uri.AbsolutePath;
}
catch { }
var resource = Application.GetResourceStream(new Uri(url, UriKind.Relative)) ??
// for relative paths and app resources we need to add www folder manually
// there are many related issues on stackoverflow + some prev worked sample don't because of this
Application.GetResourceStream(new Uri("www/" + url, UriKind.Relative));
if (resource == null)
{
// 404 ?
Browser.InvokeScript("__onXHRLocalCallback", new string[] { "404" });
return true;
}
else
{
using (StreamReader streamReader = new StreamReader(resource.Stream))
{
string text = streamReader.ReadToEnd();
Browser.InvokeScript("__onXHRLocalCallback", new string[] { "200", text });
return true;
}
}
}
return false;
}

Categories