Swagger Tools Production Build Node js - deployment

We implemented the swagger in our nodeJs application. As of now we are created production build using webpack and remove the controller and services file.
bin/www.js
const YAML = require('yamljs');
const swaggerTools = require('swagger-tools');
const swaggerDoc = YAML.safeLoad('./swagger.yaml');
// swaggerRouter configuration
const swaggerOptions = {
controllers: path.join(__dirname, '../public/javascripts/controllers'),
useStubs: true, // Conditionally turn on stubs (mock mode)
};
// Initialize the Swagger middleware
swaggerTools.initializeMiddleware(swaggerDoc, (middleware) => {
// Interpret Swagger resources and attach metadata to request - must be first in swagger-tools middleware chain
app.use(middleware.swaggerMetadata());
// validate the security using JWT token
app.use(middleware.swaggerSecurity({
Bearer: auth.verifyToken
}));
// Validate Swagger requests
app.use(middleware.swaggerValidator({
validateResponse: true
}));
// Route validated requests to appropriate controller
app.use(middleware.swaggerRouter(swaggerOptions));
// Serve the Swagger documents and Swagger UI
app.use(middleware.swaggerUi());
});
If we did the same in production build and the swagger middleware expecting the same path to resolve. after build we delete the public folder.
Webpack code
const path = require('path');
const nodeExternals = require('webpack-node-externals');
module.exports = {
entry: {
server: './bin/www',
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: 'server.build.js',
},
target: 'node',
node: {
// Need this when working with express, otherwise the build fails
__dirname: false, // if you don't put this is, __dirname
__filename: false, // and __filename return blank or /
},
externals: [nodeExternals()],
module: {
rules: [
{
// Transpiles ES6-8 into ES5
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
};
Pleas help us to create a build using swagger middleware
Thanks in advance

Swagger tools is not a package bundler like webpack. So you will still need to provide it the controller files. Since you are deleting /public from prod then there is no way for swagger tools middleware to get the files it needs. Webpack in this case is basically building a dist from your code which is why it's ok to delete the controller and services.

Related

How to deploy an generate a static site on Nuxt 3

Hello I'm creating website on Nuxt and i have created a new app on Nuxt 3. But I have an probleme for the deployement, there is no 'normal' build for 'normal server' as Nuxt 2.x.
I'm using 'Lamdba' preset.
https://v3.nuxtjs.org/docs/deployment/presets/lambda
// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt3'
// https://v3.nuxtjs.org/docs/directory-structure/nuxt.config
export default defineNuxtConfig({
// Global page headers: https://go.nuxtjs.dev/config-head
nitro: {
preset: 'lambda'
},
head: {
title: 'Title',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
],
link: [
{ rel: 'icon', type: 'image/png', href: '/favicon.png' }
],
script: [
{
type: 'text/javascript',
src: '/mana.js',
}
]
},
})
And on Nuxt 2.x I used this :
// nuxt.config.js
export default {
// Disable server-side rendering: https://go.nuxtjs.dev/ssr-mode
ssr: false,
// Target: https://go.nuxtjs.dev/config-target
target: 'static'
}
What configuration i should to use on Nuxt 3 to have 'normal' export with an index.html file at the root for all server ?
Please use generate script like yarn generate this will create the .output/public and output will depend on ssr: boolean property in nuxt.config.ts.
if ssr is true which is by default, then there will be individual html for each dynamic route and that means dynamic routes are rendered at build time and whenever there is change in data or number of dynamic routes then you will need to run this command again.
if ssr is false then rendering will be done at client side, like SPA app and dynamic routes will have only one file that will do client side rendering and data will be fetched at client side that way site will show latest data.
Check static-hosting
Static deployment is not currently available for Nuxt 3
Besides adding target: 'static' in your nuxt.config.ts
export default defineNuxtConfig({
target: 'static' // default is 'server'
})
You also need to update your build script to be nuxi generate in your package.json (which was nuxi build originally)
{
"scripts": {
"build": "nuxi generate"
}
}
References: https://v3.nuxtjs.org/bridge/overview#static-target
I managed to deploy my nuxt3 project static to gh-pages. I had to overcome two obstacles.
yarn generate did not generate static routes until I explicitly forced it by setting
generate: {routes: ['/','all','my','other','routes']} ....
in nuxt.config.js as target:"static" did not work for me.
gh-pages need an empty .nojekyll file which seems currently not being generated by nuxt generate nor gh-pages. I entered the following into my package.json:
"deploy": "touch .output/.nojekyll && gh-pages --dotfiles -d .output"
This seems ugly but works for me.

Set static path for karma runner

I was able prepare my OpenUI5 app for testing. I am having issue with the working directory for tests, because for my test I need to use a pre-populated sqlite3 database. For testing I use chrome with parameters --user-data-dir="C:\tmp" --profile-directory="karma", and I can place this file into chrome profile path. But I am not able to do this with karma, because karma always start with randomly generated id in path (karma-xxxxxx).
I am trying run custom browser config, with above chrome parameters, but it does not work.
module.exports = function(config) {
"use strict";
var chromeFlags = [
"--window-size=1280,1024",
"--disable-web-security",
"--allow-file-access-from-files",
'--user-data-dir="C:\\tmp"',
'--profile-directory="karma"'
];
config.set({
basePath: '',
ui5: {
type: "application",
preload: 'async',
animation: 'false',
paths: {
webapp: "www", // application
}
},
frameworks: ["ui5"],
browsers: ["CustomChrome"],
browserConsoleLogOptions: {
level: "error"
},
customLaunchers: {
CustomChrome: {
base: "Chrome",
flags: chromeFlags
},
CustomChromeHeadless: {
base: "ChromeHeadless",
flags: chromeFlags
}
},
});
};
with this config, chrome always start like this, so automatic testing does not work:

Using react-hot-loader with custom babel preset

My app doesn't support older browsers, and I like to trim down the set of Babel transforms to make the code easier to debug (so that the code in the debugger looks like more the original source).
However, when I migrate to react-hot-loader 3, this no longer works. That is, I can get RHL 3 to work with the standard es2015 preset, but not with my custom set of transforms. What happens is that the react components are rendered but never mounted, and won't respond to any events.
The set of transforms I am trying to use is:
var babel_plugins = [
'transform-runtime',
'transform-object-rest-spread',
// Transforms needed for modern browsers only
'babel-plugin-check-es2015-constants',
'babel-plugin-transform-es2015-block-scoping',
'babel-plugin-transform-es2015-function-name',
'babel-plugin-transform-es2015-parameters',
'babel-plugin-transform-es2015-destructuring',
// No longer needed with Webpack 2
// 'babel-plugin-transform-es2015-modules-commonjs',
'react-hot-loader/babel',
];
In response to the comments, here's more information:
Here's how I'm using the AppContainer:
export default (
<AppContainer>
<Router history={browserHistory}>
(My routes here...)
</Router>
</AppContainer>
);
And here's my dev server setup:
// Adjust the config for hot reloading.
config.entry = {
main: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://127.0.0.1:8000', // WebpackDevServer host and port
'webpack/hot/only-dev-server', // "only" prevents reload on syntax errors
'./src/main.js', // Your appʼs entry point
],
frame: './src/frame_main.js', // Entry point for popup tab
};
config.plugins.push(new webpack.HotModuleReplacementPlugin());
const compiler = webpack(config);
const server = new WebpackDevServer(compiler, {
contentBase: path.resolve(__dirname, '../builds/'),
historyApiFallback: true,
stats: 'errors-only',
hot: true,
});
server.listen(8000, '127.0.0.1', () => {});
Here's the relevant portion of my webpack config:
test: /\.jsx?$/,
include: __dirname + '/src',
exclude: __dirname + '/src/libs',
use: [
{
loader: 'babel-loader',
options: {
plugins: babel_plugins,
presets: babel_presets
},
},
{
loader: 'eslint-loader',
},
]

How do I parameterize the baseUrl property of the protractor config file

I need to run my protractor tests in different contexts with different baseUrls in the config files. I don't want to use separate config files for each situation since that is more difficult to maintain. Rather, I want to pass the base url in as a command line parameter. Here is what I have tried so far:
The protractor.conf.js:
exports.config = {
onPrepare : {
...
exports.config.baseUrl = browser.params.baseUrl;
...
}
}
And to invoke protractor:
protractor protractor.conf.js --params.baseUrl 'http://some.server.com'
This does not work since it seems like the browser instance is already configured before onPrepare is called.
Similarly, I have tried this:
exports.config = {
baseUrl : browser.params.baseUrl
}
But this doesn't work either since it seems like the browser instance is not available when the config is being generated.
It looks like I can use standard node process.argv to access all command line arguments, but that seems to be going against the spirit of protractor.
What is the best way for me to do what I need to do?
Seems like this is already possible, but the documentation is spotty in this area. Looking at the code, however, protractor does support a number of seemingly undocumented command line arguments.
So, running something like this will work:
protractor --baseUrl='http://some.server.com' my.conf.js
The other option is to use gruntfile.js and have it call the protractor config file.
//gruntfile.js
module.exports = function (grunt) {
grunt.registerTask("default", "", function () {
});
//Configure main project settings
grunt.initConfig({
//Basic settings and infor about our plugins
pkg: grunt.file.readJSON('package.json'),
//Name of plugin
cssmin: {
},
protractor: {
options: {
configFile: "conf.js", // Default config file
keepAlive: true, // If false, the grunt process stops when the test fails.
noColor: false, // If true, protractor will not use colors in its output.
args: {
baseUrl: grunt.option('baseUrl') || 'http://localhost:6034/'
}
},
your_target: { // Grunt requires at least one target to run so you can simply put 'all: {}' here too.
options: {
configFile: "conf.js", // Target-specific config file
args: {
baseUrl: grunt.option('baseUrl') || 'http://localhost:63634/'
}
}
},
},
//uglify
uglify: {
}
});
//Load the plugin
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-protractor-runner');
//Do the Task
grunt.registerTask('default', ['cssmin']);
};
the Protractor config file: conf.js
exports.config = {
directConnect: true,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome',
'chromeOptions': {
args: ['--no-sandbox']
}
},
chromeOnly: true,
// Framework to use. Jasmine is recommended.
framework: 'jasmine',
// Spec patterns are relative to the current working directory when
// protractor is called.
specs: ['specs/*/*_spec.js'],
suites : {
abcIdentity : 'specs/abcIdentity/*_spec.js' //picks up all the _spec.js files
},
params: {
UserName: 'abc#test.com',
Password: '123'
},
// Options to be passed to Jasmine.
jasmineNodeOpts: {
defaultTimeoutInterval: 30000,
includeStackTrace: true
},
onPrepare: function () {
browser.driver.manage().window().maximize();
if (process.env.TEAMCITY_VERSION) {
var jasmineReporters = require('jasmine-reporters');
jasmine.getEnv().addReporter(new jasmineReporters.TeamCityReporter());
}
}
};
//To run with default url http://localhost:6034
grunt protractor
//To run with any other url
grunt protractor --baseUrl:"http://dev.abc.com/"
I know, old one. but if anyone is still looking for a way to define a url based on capability (I had to do this because Ionic 5 will run in browser on port 8100, but in the app - unchangable - without port declaration on port 80, I use Appium)
add a baseUrl parameter inside your capability declaration.
{
browserName: 'chrome',
baseUrl: 'http://localhost:8100' //not required but as example
}
{
...
app: 'path to app.apk',
baseUrl: 'http://localhost'
...
}
and then configure your onPrepare method as follows.
async onPrepare() {
const config = await browser.getProcessedConfig();
if(config.capabilities.hasOwnProperty('baseUrl')) {
browser.baseUrl = config.capabilities.baseUrl;
}
}
OnPrepare runs for each capability you define in your multiCapabilities array. the getProcessedConfig returns the config as you defined it, with the addition of the current capability. Since that method returns a promise, I use async/await for readability.
This way, you can have multiple capabilities running, with each different a different host.
Base url should be declared baseUrl: "", in config.ts
I am using cucumber hooks and the below code is added in hooks file to pass the required url based upon the environments
if(browser.params.baseUrl==="QA"){
console.log("Hello QA")
await browser.get("https://www.google.com");
} else {
console.log("Hi Dev")
await browser.get("https://www.gmail.com");
}
run the tests using protractor command
protractor --params.baseUrl 'QA' typeScript/config/config.js --cucumberOpts.tags="#CucumberScenario"

Using Grunt to Mock Endpoints

I'm using Yeoman, Grunt, and Bower, to construct a platform for building a frontend independently of a a backend. The idea would be that all of my (AngularJS) controller, services, factories, etc live in this project, and get injected afterwards into my serverside codebase based off the result of grunt build.
My question is:
How can I mock endpoints so that the Grunt server responds to the same endpoints as my (Rails) App will?
At the moment I am using:
angular.module('myApp', ['ngResource'])
.run(['$rootScope', function ($rootScope) {
$rootScope.testState = 'test';
}]);
And then in each of my individual services:
mockJSON = {'foo': 'myMockJSON'}
And on every method:
if($rootScope.testState == 'test'){
return mockJSON;
}
else {
real service logic with $q/$http goes here
}
Then after grunt build, testState = 'test' gets removed.
This is clearly a relatively janky architecture. How can I avoid it? How can I have Grunt respond to the same endpoints as my app (some of which have dynamic params) apply some logic (if necessary), and serve out a json file (possibly dependent on path params)?
I've fixed this issue by using express to write a server that responds with static json.
First I created a directory in my project called 'api'. Within that directory I have the following files:
package.json:
{
"name": "mockAPI",
"version": "0.0.0",
"dependencies": {
"express": "~3.3.4"
}
}
Then I run npm install in this directory.
index.js:
module.exports = require('./lib/server');
lib/server.js:
express = require('express');
var app = express();
app.get('/my/endpoint', function(req, res){
res.json({'foo': 'myMockJSON'});
});
module.exports = app
and finally in my global Gruntfile.js:
connect: {
options: {
port: 9000,
hostname: 'localhost',
},
livereload: {
options: {
middleware: function (connect, options) {
return [
lrSnippet,
mountFolder(connect, '.tmp'),
mountFolder(connect, yeomanConfig.app),
require('./api')
];
}
}
},
Then the services make the requests, and the express server serves the correct JSON.
After grunt build, the express server is simply replaced by a rails server.
As of grunt-contrib-connect v.0.7.0 you can also just add your custom middleware to the existing middleware stack without having to manually rebuild the existing middleware stack.
livereload: {
options: {
open: true,
base: [
'.tmp',
'<%= config.app %>'
],
middleware: function(connect, options, middlewares) {
// inject a custom middleware into the array of default middlewares
middlewares.push(function(req, res, next) {
if (req.url !== '/my/endpoint') {
return next();
}
res.writeHead(200, {'Content-Type': 'application/json' });
res.end("{'foo': 'myMockJSON'}");
});
return middlewares;
}
}
},
See https://github.com/gruntjs/grunt-contrib-connect#middleware for the official documentation.
Alternatively you can use the grunt-connect-proxy to proxy everything that is missing in your test server to an actual backend.
It's quite easy to install, just one thing to remember when adding proxy to your livereload connect middleware is to add it last, like this:
middleware: function (connect) {
return [
lrSnippet,
mountFolder(connect, '.tmp'),
mountFolder(connect, yeomanConfig.app),
proxySnippet
];
}
grunt-connect-prism is similar to the Ruby project VCR. It provides an easy way for front end developers to record HTTP responses returned by their API (or some other remote source) and replay them later. It's basically an HTTP cache, but for developers working on a Single Page Application (SPA). You can also generate stubs for API calls that don't exist, and populate them the way you want.
It's useful for mocking complex & high latency API calls during development. It's also useful when writing e2e tests for your SPA only, removing the server from the equation. This results in much faster execution of your e2e test suite.
Prism works by adding a custom connect middleware to the connect server provided by the grunt-contrib-connect plugin. While in 'record' mode it will generate a file per response on the filesystem with content like the following:
{
"requestUrl": "/api/ponies",
"contentType": "application/json",
"statusCode": 200,
"data": {
"text": "my little ponies"
}
}
DISCLAIMER: I'm the author of this project.
You can use Apache proxy and connect your REST server with gruntjs.
Apache would do this:
proxy / -> gruntjs
proxy /service -> REST server
you would use your application hitting Apache and angular.js application would think that is talking with itself so no cross domain problem.
Here is a great tutorial on how to set this up:
http://alfrescoblog.com/2014/06/14/angular-js-activiti-webapp-with-activiti-rest/
Just my alternative way that based on Abraham P's answer. It does not need to install express within 'api' folder. I can separate the mock services for certain files. For example, my 'api' folder contains 3 files:
api\
index.js // assign all the "modules" and then simply require that.
user.js // all mocking for user
product.js // all mocking for product
file user.js
var user = function(req, res, next) {
if (req.method === 'POST' && req.url.indexOf('/user') === 0) {
res.end(
JSON.stringify({
'id' : '5463c277-87c4-4f1d-8f95-7d895304de12',
'role' : 'admin'
})
);
}
else {
next();
}
}
module.exports = user;
file product.js
var product = function(req, res, next) {
if (req.method === 'POST' && req.url.indexOf('/product') === 0) {
res.end(
JSON.stringify({
'id' : '5463c277-87c4-4f1d-8f95-7d895304de12',
'name' : 'test',
'category': 'test'
})
);
}
else {
next();
}
}
module.exports = product;
index.js just assigns all the "modules" and we simply require that.
module.exports = {
product: require('./product.js'),
user: require('./user.js')
};
My Gruntfile.js file
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost',
livereload: 35729
},
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
connect.static('.tmp'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect.static(appConfig.app),
require('./api').user,
require('./api').product,
];
}
}
}