Proper Angularjs way to use JSON maintain RESTful urls - javascript

I am building an Angularjs web application by the books I guess you could say. I am following the John Papa Angular Styleguide and things have been going well so far. I now have a need to keep all of the RESTful host urls in some sort of configuration file in JSON format. These host endpoints change frequently depending on the client or change of AWS machines, so to keep all of the urls in one place could be beneficial for ease of change.
Currently in the javascript files in my application that deal with making the REST calls things are setup like this:
function ModelViewService($http, $q, exception, logger) {
var HOST = 'http://xxxxxxxxxxxxxxxxxx.amazonaws.com';
var MODULE = '/modelview/service/rest';
...
And then when a call is made to get some data for example it looks like this:
function getGroups() {
return $http.get(HOST + MODULE + '/group/retrieveAll')
.then(success)
.catch(fail);
...
I then have other files with different services and different HOSTs so I basically want to house JSON objects somewhere that look like:
{
'modelviewservice': {
'HOST': 'http://xxxxxxxxxxxxxxxxxx.amazonaws.com',
'MODULE': '/modelview/service/rest'
},
... //other service
}
And then back in the javascript file do something like $http.get(config.modelviewservice.host + config.modelviewservice.MODULE + '/group/retrieveAll').
I don't know the best way to achieve this and follow the angular style guide. I found something called requre.js that apparently would inject the config.json file into the javascript via something like var config = require('config.json')('./config.json'); where the first config.json refers to the config.json npm module, and the second ./config.json refers to my local configuration JSON file. This seemed like an ok solution but since I couldn't get it to work it had me second guessing if there was an easier or more proper way to do this.

Well, this is how I do it to make my endpoints organize. Add constant to main module of the application .
(function() {
'use strict';
angular
.module('apiConstant', [])
.constant('apiConstant', constant());
function constant() {
return {
HOST: 'http://xxxxxxxxxxxxxxxxxx.amazonaws.com',
modules: {
MODULE_1: '/modelview/service/rest',
MODULE_2: '/modelview/factory/rest',
MODULE_3: '/modelview/sample/rest'
},
endpoints: {
GET_GROUPS: '/group/retrieveAll',
GET_USERS: '/users/retrieveAll',
POST_GROUP: '/group/add'
}
};
}
})();
And then in your service
function ModelViewService($http, $q, exception, logger, apiConstant) {
var HOST = apiConstant.HOST;
var MODULE = apiConstant.modules.MODULE_1;
...
function getGroups() {
return $http.get(HOST + MODULE + apiConstant.endpoints.GET_GROUPS)
.then(success)
.catch(fail);
...

Related

Basic Node.js question with regards to serverless functions

I am developing an Alexa Skill for the first time. For the Fulfillment sections, I planned to hook them up to serverless functions (written in Node.js) on Azure. I developed the intents with Google's Dialogflow which I plan to export to Amazon Alexa's console. I am a C# programmer but willing to learn Node.js/Javascript and have a few basic questions.
I installed/used the "azure-functions-core-tools" from Github to create my serverless function in Node.js. It created the file below.
The name of my Function is HelloWorld
Index.js file below was created by "func new" command and contains the following:
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
if (req.query.name || (req.body && req.body.name)) {
context.res = {
// status: 200, /* Defaults to 200 */
body: "Hello " + (req.query.name || req.body.name)
};
}
else {
context.res = {
status: 400,
body: "Please pass a name on the query string or in the request body"
};
}
};
My questions are
1) Are you limited to one function per file?
2) Can I have multiple functions in the same file?
3) If so, how is that possible because just looking at this, there is no name for this function?
4) If not, how can I call other functions outside this function?
5) I am taking an online class on Node.js but wonder if I really should take a Javascript class instead. What would you recommend?
Many Thanks
Answers:
No
Yes. You basically need to search for basic syntax using a search engine (example: google.com)
Because some js-file/module will use this as a module, importing it using require and then using it as a method. For example :
-
// file name - run.js
var asyncFunction = require('index.js'); // This fetches the function, as its exported in index.js
asyncFunction() // this executes the function.
You use export and require.
Nodejs is a complete set of environment which uses javascript as the programming language. So it basically depends on the content of that course.

How can we make the swagger-js library save web service interface definitions?

We are writing an Angular web application that uses the swagger-js library (version 2.1.25) to call RESTful web services described with Swagger 2.0.
Each time we call a service, we create a new Swagger client object, so the swagger-js library requests the Swagger interface definition again (see pseudo-code of our calls below). The JSON definitions for our services can be quite large, on the order of 40 to 120 K bytes. As far as we can tell, we can't reuse the Swagger client objects
Is there a way to get the swagger-js library to cache the Swagger interface definitions for web services, or reuse the client objects, so that we don't waste bandwidth downloading interface definitions over and over?
Sample code below to GET data from the serviceURL/foo entry point in a RESTful service.
var swagger = new SwaggerClient({
url: "serviceURL",
success: () => {
swagger.foo.fooGet({param1: x, param2: y},
(results) => {
if ( /* results good */ ) { /* do things with results */ }
else { /* report bad results */ }
}
}, (errorResponse) => {
/* alert user that call failed */
});
});
We ended up keeping long-lived SwaggerClient objects in our Angular application for services that we called frequently.

How to set a Angular config var to set server address?

How can I do some centralized solution to store strings on AngularJS? I've asked a similar question regarding NodeJS, but I don't know how to use the same approach to Angular as I've used to Node.
I've thought of 2 approaches:
1 - Setting a Angular Constant
app.constant('config',
{
serverUrl: 'http://localhost:8080'
});
This is my actual solution, but it comes with the downside that I need to update my code with the server address every time I send the code to the cloud.
2 - Using something like Node's process.env
And I have no idea how.
3 - Using something like require('./config.js')
I'm thinking on the Node like approach. Don't know how.
Well, is there a good, effective way of accomplishing this?
I do not think that there is one right answer. I prefer your first approach:
app.constant('config',
{
serverUrl: 'http://localhost:8080'
});
It is because I think about node.js backend and angular frontend as separete applications. For example I can add to node.js second version of api and connect other angular application (or event in another technology) to new api, but also use old angular app with previous api version.
In short in my opinion it is more flexible
Edit:
So, I need to update this line everytime I upload my come to Git
I don't add configuration file to repository. I create example config file which we add to repository. But actual config is ignored.
Edit2:
In one of mine project we use this module https://www.npmjs.com/package/gulp-ng-constant for build app.constant from config.json
This is how we switch the server url without rewriting it every time
var hostname = window.location.hostname;
if (hostname.indexOf("our.live.url") > -1) {
usedEnvironment = availableEnvironments.LIVE;
} else if (hostname.indexOf("localhost") > -1) {
usedEnvironment = availableEnvironments.LOCAL;
} else {
usedEnvironment = availableEnvironments.TEST;
}
switch (usedEnvironment) {
case availableEnvironments.LIVE:
angular.module('app')
.value('apiHost', 'https://our.live.backend.com');
angular.module('app')
.value('IntercomConfig', {
Enabled: true,
AppId: ''
});
break;
case availableEnvironments.TEST:
angular.module('app')
.value('apiHost', 'our.test.backend');
angular.module('app')
.value('IntercomConfig', {
Enabled: false,
});
break;
default:
angular.module('app')
.value('apiHost', 'http://localhost:8080');
angular.module('app')
.value('IntercomConfig', {
Enabled: false,
});
}

The SailsJS way of connecting to an API. What's the best method?

I'm currently trying to connect to the Artsy public API and I'm having some trouble. Please go easy on me, I'm new to NodeJS and SailsJS. I've created a file called api/services/Artsy.js and now I'm hung up on whether my approach (see below) is really the Sails way of doing things. That's one question. If not, what is the proper way to set up a basic call to an API in SailsJS? Or more specifically, to the Artsy API?
Issues that come to mind:
I need to wait until the token is retrieved before I can call an API method that requires it. Is this done via pubsub, or some other technique. Are there any practical examples that show how this works in SailsJS?
Can you use service calls inside of views? How? Does this even make sense? It seems like it might be useful for an API call.
Note: I've set up the file config/artsy.js that holds important variables. (see this below)
/api/services/Artsy.js
/**
*
* Artsy.js => in api/services
* #description A service that connects to the Artsy.net public API.
* #url https://developers.artsy.net/
**/
var request = require('superagent'),
traverson = require('traverson'),
xappToken;
module.exports = {
init: function(){
sails.log.info('----- Artsy API Initialized -----');
var clientID = sails.config.artsy.clientId,
clientSecret = sails.config.artsy.clientSecret,
apiTokenUrl = sails.config.artsy.apiTokenUrl;
try{
request
.post(apiTokenUrl)
.send({ client_id: clientID, client_secret: clientSecret })
.end(function(res) {
if (res) {
xappToken = res.body.token;
} else {
sails.log.error('api/services/Artsy.js:');
sails.log.error(res.text);
}
});
} catch(e) {
sails.log.error('api/services/Artsy.js:');
sails.log.error(e);
}
},
getArtistStatement: function(){
var api = traverson.jsonHal.from(sails.config.artsy.apiUrl);
var request = api.newRequest()
.follow('artist')
.withRequestOptions({
headers: {
'X-Xapp-Token': xappToken,
'Accept': 'application/vnd.artsy-v2+json'
}
})
.withTemplateParameters({ id: 'andy-warhol' })
.getResource(function(error, andyWarhol) {
console.log(andyWarhol.name + 'was born in ' + andyWarhol.birthday + ' in ' + andyWarhol.hometown);
});
}
};
/config/artsy.js
/**
* artsy.js
*
* #description :: This is the brains that allow the app to connect to artsy.
* #docs :: http://sailsjs.org/#!documentation/models
*/
module.exports.artsy = {
clientId: 'CLIENT_ID',
clientSecret: 'CLIENT_SECRET',
apiUrl: 'https://api.artsy.net/api',
apiTokenUrl: 'https://api.artsy.net/api/tokens/xapp_token'
};
If I understand your questions correctly so
That's one question. If not, what is the proper way to set up a basic call to an API in SailsJS?
Service is quite right place for such case.
And you can call your init method in config/bootstrap.js, or when user has log in or somewhere else.
I need to wait until the token is retrieved before I can call an API method that requires it. Is this done via pubsub
Yes, you can use pubsub, but it seems better to use promises. For example you can use this lib
https://github.com/istavros/vowjs
Can you use service calls inside of views? How? Does this even make sense? It seems like it might be useful for an API call.
I think yes, but it seems you should not want it. It looks betted when templates works with controller passed data and nothing else. So use service in controller (or mb model) an then pass results to template.

NodeJS Modulization

So, I was told that passing around the request and or response variable in nodeJS is "bad practice". But this means that most of your code has to be in the server.js file, making it cluttered and kind of ugly.
How can you modularize your nodejs server, passing around req/res appropriately and be able to organize your code into separate files?
For example, I would like to split my socket routing, .get and .post into different files, but still be able to use the callback parameters like so:
app.io.route("disconnect", function(req,res) { <--- these params
db.query("UPDATE player_data SET online=0 WHERE id="+mysql.escape(req.session.user));
req.io.broadcast("event", {msg:req.session.username+" has logged out!"});
app.io.broadcast("reloadXY");
});
As of right now they're all in one file and I don't like that.
I think what the person meant by 'passing around' was something like this (in plain express):
app.get('/kittens', function(req, res) {
db.doAthing(req);
updateSomethingElse(res);
upvoteThisAnswer(res);
});
That is, passing around the two variables beyond the first function. This is bad because it becomes increasingly difficult to figure out where the call actually ends. One little res.end(500) in updateSomethingElse can cause the whole house of cards to come tumbling down.
It's perfectly ok (in fact, standard to the point of being the default in express) to declare that callback elsewhere (usually the /routes directory of your project.)
// app.js
var user = require('./routes/user')
, kittens = require('./routes/kittens');
// express stuff...
app.get('/settings', user.getSettings);
app.get('/fur', kittens.shed);
Then, in routes/user.js:
exports.getSettings = function(req, res) {
// Note how we're passing around properties of req/res, not the objects themselves.
db.getUserSettings(req.user.id).then(function(settings) {
res.render('settings', settings);
});
};
This video from TJ Holowaychuk (the guy who wrote Express and a ton of other Node infrastructure that we all use) helped me take Express modularization to the next level. Basically you can make individual apps in their own folders and consume them as middleware very easily. I have managed to extend this technique to socket.io with some tricks.
http://vimeo.com/56166857
You should not pass req and res to another modules but pass callbacks from another modules to route.
It should look like.
var someModule = require("./someModule")
app.get("/someAction", someModule.handleSomeAction) ;
If You want to have post and get in another modules You should pass reference to app (from express()) once to that module and operate on that.
For example :
var express = require("express") ;
var app = express();
var get_handler = require("./get_handler ")
var post_handler = require("./post_handler ")
get_handler.init(app);
post_handler.init(app);
and in post/get_handler :
var app;
exports.init = function( eApp){
app = eApp;
// operate on app
}

Categories