<commit_before>const webpack = require('webpack')
const HtmlWebpackPLugin = require('html-webpack-plugin')
const OfflinePlugin = require('offline-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const autoprefixer = require('autoprefixer')

const debug = process.env.NODE_ENV !== 'production'

module.exports = {
  context: `${__dirname}/src`,
  devtool: debug ? 'cheap-module-eval-source-map' : 'source-map',
  entry: {
    app: [
      'babel-polyfill',
      'react-hot-loader/patch',
      './client.js',
    ],
  },
  output: {
    path: `${__dirname}/public`,
    filename: debug ? '[name].js' : '[name].[chunkhash].js',
    publicPath: '/',
  },
  performance: {
    hints: false,
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
      },
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              minimize: true,
              importLoaders: 2,
              modules: true,
              localIdentName: debug ? '[name]__[local]--[hash:base64:5]' : null,
            },
          },
          'sass-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: [
                autoprefixer(),
              ],
            },
          },
        ],
      },
      {
        test: /\.svg$/,
        loader: {
          loader: 'svg-sprite-loader',
          options: {
            name: '[name]',
          },
        },
      },
    ],
  },
  plugins: debug ? [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new FriendlyErrorsPlugin(),
    new HtmlWebpackPLugin({
      template: './index.html',
    }),
  ] : [
    new webpack.EnvironmentPlugin('NODE_ENV'),
    new webpack.NamedModulesPlugin(),
    new HtmlWebpackPLugin({
      template: './index.html',
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: module => module.context && module.context.indexOf('node_modules') !== -1,
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      minChunks: Infinity,
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: true,
      debug: false,
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
      },
      mangle: true,
      sourcemap: true,
    }),
    new CopyWebpackPlugin([
      { from: 'manifest.json' },
    ]),
    new OfflinePlugin({
      version: '[hash]',
      AppCache: false,
      ServiceWorker: {
        events: true,
      },
    }),
  ],
  devServer: {
    contentBase: `${__dirname}/src`,
    historyApiFallback: true,
    hot: true,
    quiet: true,
  },
}
<commit_msg>Refactor webpack conf<commit_after>const webpack = require('webpack')
const HtmlWebpackPLugin = require('html-webpack-plugin')
const OfflinePlugin = require('offline-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const autoprefixer = require('autoprefixer')

const debug = process.env.NODE_ENV !== 'production'

module.exports = {
  context: `${__dirname}/src`,
  devtool: debug ? 'cheap-module-eval-source-map' : 'source-map',
  entry: {
    app: [
      'babel-polyfill',
      'react-hot-loader/patch',
      './client.js',
    ],
  },
  output: {
    path: `${__dirname}/public`,
    filename: debug ? '[name].js' : '[name].[chunkhash].js',
    publicPath: '/',
  },
  performance: {
    hints: false,
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
      },
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              minimize: true,
              importLoaders: 2,
              modules: true,
              localIdentName: debug ? '[name]__[local]--[hash:base64:5]' : null,
            },
          },
          'sass-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: [
                autoprefixer(),
              ],
            },
          },
        ],
      },
      {
        test: /\.svg$/,
        loader: {
          loader: 'svg-sprite-loader',
          options: {
            name: '[name]',
          },
        },
      },
    ],
  },
  devServer: {
    contentBase: `${__dirname}/src`,
    historyApiFallback: true,
    hot: true,
    quiet: true,
  },
  plugins: debug ? [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new FriendlyErrorsPlugin(),
    new HtmlWebpackPLugin({
      template: './index.html',
    }),
  ] : [
    new webpack.EnvironmentPlugin('NODE_ENV'),
    new webpack.NamedModulesPlugin(),
    new HtmlWebpackPLugin({
      template: './index.html',
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: module => module.context && module.context.indexOf('node_modules') !== -1,
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      minChunks: Infinity,
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: true,
      debug: false,
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
      },
      mangle: true,
      sourcemap: true,
    }),
    new CopyWebpackPlugin([
      { from: 'manifest.json' },
    ]),
    new OfflinePlugin({
      version: '[hash]',
      AppCache: false,
      ServiceWorker: {
        events: true,
      },
    }),
  ],
}
<|endoftext|>


<commit_before>const neo4j = require('neo4j-driver').v1;
const logger = require('./../../../../applogger');
const neo4jconfig = require('./../../../../config/config');

/* single instance class for neo4j connection */

function singleton() {
    let instance = undefined;
    this.connection = function() {
        if (!this.instance) {
            this.instance = neo4j.driver('bolt://localhost', neo4j.auth.basic(neo4jconfig.NEO4J.USERNAME, neo4jconfig.NEO4J.PASSWORD)).session();
        }
        return this.instance;
    };
}

module.exports = exports = new singleton;<commit_msg>fix for neo4j host related issue on UAT<commit_after>const neo4j = require('neo4j-driver').v1;
const logger = require('./../../../../applogger');
const neo4jconfig = require('./../../../../config/config');

/* single instance class for neo4j connection */

function singleton() {
    let instance = undefined;
    this.connection = function() {
        if (!this.instance) {
            this.instance = neo4j.driver('bolt://' + neo4jconfig.NEO4J.HOST, neo4j.auth.basic(neo4jconfig.NEO4J.USERNAME, neo4jconfig.NEO4J.PASSWORD)).session();
        }
        return this.instance;
    };
}

module.exports = exports = new singleton;<|endoftext|>


<commit_before>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

require('@v4fire/core/build/i18n');

const
	$C = require('collection.js'),
	config = require('config'),
	path = require('path');

const
	{hash, args, isProdEnv, version, hashLength} = require('./build/helpers.webpack'),
	{env} = process,
	{src} = config;

const
	webpack = require('webpack'),
	HardSourceWebpackPlugin = require('hard-source-webpack-plugin'),
	ExtractTextPlugin = require('extract-text-webpack-plugin'),
	AssetsWebpackPlugin = require('assets-webpack-plugin'),
	WebpackMd5Hash = require('webpack-md5-hash');

const
	cwd = src.cwd,
	folders = src.client,
	entryFolder = folders[0];

function d(file = '') {
	return path.join(src.cwd, file);
}

function o(file = '') {
	return path.join(src.clientOutput(), file);
}

function r(file) {
	return `./${path.relative(cwd, file).replace(/\\/g, '/')}`;
}

const
	output = r(o('[hash]_[name]')),
	assetsJSON = o(`${version}assets.json`),
	lib = d('node_modules');

const build = require('./build/entities.webpack')({
	entries: path.join(entryFolder, 'entries'),
	output: hash(output),
	cache: env.FROM_CACHE && d('app-cache/graph'),
	folders,
	assetsJSON,
	lib
});

require('./build/snakeskin.webpack')(folders);
console.log('Project graph initialized');

function buildFactory(entry, i = '00') {
	const
		base = {'0': true, '00': true}[i];

	return {
		entry,
		externals: config.externals,

		output: {
			path: cwd,
			publicPath: '/',
			filename: hash(output, true)
		},

		resolve: {
			modules: [
				entryFolder,
				cwd,
				...folders.slice(1),
				lib
			]
		},

		resolveLoader: {
			moduleExtensions: ['-loader'],
			alias: {
				prop: path.join(__dirname, './web_loaders/prop'),
				proxy: path.join(__dirname, './web_loaders/proxy')
			}
		},

		plugins: [
			new webpack.DefinePlugin(config.globals),
			new ExtractTextPlugin(`${hash(output, true)}.css`),
			new AssetsWebpackPlugin({filename: assetsJSON, update: true})

		].concat(
			base ? new webpack.optimize.CommonsChunkPlugin({
				name: 'index.js',
				chunks: $C(Object.keys(build.entry)).get((el) => /^[^$]+\.js$/.test(el)),
				minChunks: 2,
				async: false
			}) : [],

			isProdEnv && !env.DEBUG ? [
				/* eslint-disable camelcase */

				new webpack.optimize.UglifyJsPlugin({
					compress: {
						warnings: false,
						keep_fnames: true
					},

					output: {
						comments: false
					},

					mangle: false
				}),

				/* eslint-enable camelcase */

				new webpack.LoaderOptionsPlugin({
					minimize: true,
					debug: false,
					options: {
						context: __dirname
					}
				})
			] : [],

			isProdEnv ? [
				new WebpackMd5Hash()

			] : [
				new HardSourceWebpackPlugin({
					cacheDirectory: d(`app-cache/${i}/[confighash]`),
					recordsPath: d(`app-cache/${i}/[confighash]/records.json`),
					environmentHash: {files: ['package-lock.json']},
					configHash: (webpackConfig) => require('node-object-hash')().hash(webpackConfig)
				})
			]
		),

		module: {
			rules: [
				{
					test: /\.js$/,
					exclude: /node_modules\/(?!@v4fire)/,
					use: [
						{
							loader: 'babel',
							options: config.babel.client
						},

						{
							loader: 'prop',
							options: {
								modules: folders
							}
						},

						{
							loader: 'proxy',
							options: {
								modules: folders
							}
						}
					]
				},

				{
					test: /\.styl$/,
					use: ExtractTextPlugin.extract({
						fallback: 'style',
						use: [].concat(
							{
								loader: 'css',
								options: {
									minimize: Boolean(isProdEnv || env.MINIFY_CSS === 'true')
								}
							},

							isProdEnv ? [
								{
									loader: 'postcss',
									options: {
										plugins: [require('autoprefixer')()]
									}
								}

							] : [],

							{
								loader: 'stylus',
								options: {
									use: require('./build/stylus.plugins'),
									preferPathResolver: 'webpack'
								}
							},

							{
								loader: 'monic',
								options: $C.extend({deep: true, concatArray: true}, {}, config.monic.styl, {
									replacers: [
										Object.assign(require('./build/stylus-import.replacer'), {folders, lib}),
										require('@pzlr/stylus-inheritance')
									]
								})
							}
						)
					})
				},

				{
					test: /\.ss$/,
					use: [
						{
							loader: 'snakeskin',
							options: config.snakeskin.client
						}
					]
				},

				{
					test: /\.ess$/,
					use: [
						{
							loader: 'file',
							options: {
								name: `${output.replace(/\[hash]_/, '')}.html`
							}
						},

						'extract',
						'html',

						{
							loader: 'snakeskin',
							options: Object.assign({}, config.snakeskin.server, {
								exec: true,
								data: {
									root: cwd,
									output: o(),
									dependencies: build.dependencies,
									assets: src.assets(),
									version,
									hashLength,
									lib
								}
							})
						}
					]
				},

				{
					test: /\.(png|gif|jpg|svg|ttf|eot|woff|woff2|mp3|ogg|aac)$/,
					use: [
						{
							loader: 'url',
							options: {
								name: hash('[path][hash]_[name].[ext]'),
								limit: 4096
							}
						}
					]
				}
			]
		}
	};
}

module.exports = args.single ?
	buildFactory(build.entry) : $C(build.processes).map((el, i) => buildFactory(el, i));
<commit_msg>:wrench:<commit_after>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

require('@v4fire/core/build/i18n');

const
	$C = require('collection.js'),
	config = require('config'),
	path = require('path');

const
	{hash, args, isProdEnv, version, hashLength} = require('./build/helpers.webpack'),
	{env} = process,
	{src} = config;

const
	webpack = require('webpack'),
	HardSourceWebpackPlugin = require('hard-source-webpack-plugin'),
	ExtractTextPlugin = require('extract-text-webpack-plugin'),
	AssetsWebpackPlugin = require('assets-webpack-plugin'),
	WebpackMd5Hash = require('webpack-md5-hash');

const
	cwd = src.cwd,
	folders = src.client,
	entryFolder = folders[0];

function d(file = '') {
	return path.join(src.cwd, file);
}

function o(file = '') {
	return path.join(src.clientOutput(), file);
}

function r(file) {
	return `./${path.relative(cwd, file).replace(/\\/g, '/')}`;
}

const
	output = r(o('[hash]_[name]')),
	assetsJSON = r(o(`${version}assets.json`)),
	lib = d('node_modules');

const build = require('./build/entities.webpack')({
	entries: path.join(entryFolder, 'entries'),
	output: hash(output),
	cache: env.FROM_CACHE && d('app-cache/graph'),
	folders,
	assetsJSON,
	lib
});

require('./build/snakeskin.webpack')(folders);
console.log('Project graph initialized');

function buildFactory(entry, i = '00') {
	const
		base = {'0': true, '00': true}[i];

	return {
		entry,
		externals: config.externals,

		output: {
			path: cwd,
			publicPath: '/',
			filename: hash(output, true)
		},

		resolve: {
			modules: [
				entryFolder,
				cwd,
				...folders.slice(1),
				lib
			]
		},

		resolveLoader: {
			moduleExtensions: ['-loader'],
			alias: {
				prop: path.join(__dirname, './web_loaders/prop'),
				proxy: path.join(__dirname, './web_loaders/proxy')
			}
		},

		plugins: [
			new webpack.DefinePlugin(config.globals),
			new ExtractTextPlugin(`${hash(output, true)}.css`),
			new AssetsWebpackPlugin({filename: assetsJSON, update: true})

		].concat(
			base ? new webpack.optimize.CommonsChunkPlugin({
				name: 'index.js',
				chunks: $C(Object.keys(build.entry)).get((el) => /^[^$]+\.js$/.test(el)),
				minChunks: 2,
				async: false
			}) : [],

			isProdEnv && !env.DEBUG ? [
				/* eslint-disable camelcase */

				new webpack.optimize.UglifyJsPlugin({
					compress: {
						warnings: false,
						keep_fnames: true
					},

					output: {
						comments: false
					},

					mangle: false
				}),

				/* eslint-enable camelcase */

				new webpack.LoaderOptionsPlugin({
					minimize: true,
					debug: false,
					options: {
						context: __dirname
					}
				})
			] : [],

			isProdEnv ? [
				new WebpackMd5Hash()

			] : [
				new HardSourceWebpackPlugin({
					cacheDirectory: d(`app-cache/${i}/[confighash]`),
					recordsPath: d(`app-cache/${i}/[confighash]/records.json`),
					environmentHash: {files: ['package-lock.json']},
					configHash: (webpackConfig) => require('node-object-hash')().hash(webpackConfig)
				})
			]
		),

		module: {
			rules: [
				{
					test: /\.js$/,
					exclude: /node_modules\/(?!@v4fire)/,
					use: [
						{
							loader: 'babel',
							options: config.babel.client
						},

						{
							loader: 'prop',
							options: {
								modules: folders
							}
						},

						{
							loader: 'proxy',
							options: {
								modules: folders
							}
						}
					]
				},

				{
					test: /\.styl$/,
					use: ExtractTextPlugin.extract({
						fallback: 'style',
						use: [].concat(
							{
								loader: 'css',
								options: {
									minimize: Boolean(isProdEnv || env.MINIFY_CSS === 'true')
								}
							},

							isProdEnv ? [
								{
									loader: 'postcss',
									options: {
										plugins: [require('autoprefixer')()]
									}
								}

							] : [],

							{
								loader: 'stylus',
								options: {
									use: require('./build/stylus.plugins'),
									preferPathResolver: 'webpack'
								}
							},

							{
								loader: 'monic',
								options: $C.extend({deep: true, concatArray: true}, {}, config.monic.styl, {
									replacers: [
										Object.assign(require('./build/stylus-import.replacer'), {folders, lib}),
										require('@pzlr/stylus-inheritance')
									]
								})
							}
						)
					})
				},

				{
					test: /\.ss$/,
					use: [
						{
							loader: 'snakeskin',
							options: config.snakeskin.client
						}
					]
				},

				{
					test: /\.ess$/,
					use: [
						{
							loader: 'file',
							options: {
								name: `${output.replace(/\[hash]_/, '')}.html`
							}
						},

						'extract',
						'html',

						{
							loader: 'snakeskin',
							options: Object.assign({}, config.snakeskin.server, {
								exec: true,
								data: {
									root: cwd,
									output: o(),
									dependencies: build.dependencies,
									assets: src.assets(),
									version,
									hashLength,
									lib
								}
							})
						}
					]
				},

				{
					test: /\.(png|gif|jpg|svg|ttf|eot|woff|woff2|mp3|ogg|aac)$/,
					use: [
						{
							loader: 'url',
							options: {
								name: hash('[path][hash]_[name].[ext]'),
								limit: 4096
							}
						}
					]
				}
			]
		}
	};
}

module.exports = args.single ?
	buildFactory(build.entry) : $C(build.processes).map((el, i) => buildFactory(el, i));
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const autoprefixer = require('autoprefixer');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CleanPlugin = require('clean-webpack-plugin');

const production = process.env.NODE_ENV === 'production';
// Permitirmos usar la variable de entorno EPBDURLPREFIX para añadir prefijo
// a las direcciones estáticas y la url del servicio que llamamos con ajax
const epbdurlprefix = process.env.EPBDURLPREFIX || '';

const PATHS = {
  app: path.resolve(path.join(__dirname, 'app')),
  build: path.resolve(path.join(__dirname, 'build')),
  nodedir: 'node_modules',
  node: path.resolve(path.join(__dirname, 'node_modules')),
  styles: path.resolve(path.join(__dirname, 'app', 'css')),
  images: path.resolve(path.join(__dirname, 'app', 'img')),
  components: path.resolve(path.join(__dirname, 'app', 'components')),
  actions: path.resolve(path.join(__dirname, 'app', 'actions')),
  reducers: path.resolve(path.join(__dirname, 'app', 'reducers')),
  store: path.resolve(path.join(__dirname, 'app', 'store'))
};

var plugins = [
  new webpack.DefinePlugin({
    __EPBDURLPREFIX__: JSON.stringify(epbdurlprefix)
  }),
  new webpack.HotModuleReplacementPlugin(),
  new ExtractTextPlugin('bundle-[hash].css', { allChunks: true }),
  new HtmlWebpackPlugin({
    // https://github.com/jaketrent/html-webpack-template
    template: 'app/index.template.html',
    title: "DB-HE NZEB: implementación de la ISO 52000-1 en el CTE DB-HE",
    inject: false,
    //favicon: 'favicon.ico',
    filename: './index.html', // relativo al output path
    minify: { removeComments: true, collapseWhitespace: true }
  }),
  new webpack.NoErrorsPlugin(),
  new webpack.optimize.CommonsChunkPlugin({
    names: ['vendor'],
    filename: '[name].js',
    minChunks: Infinity // only vendor chunks here
  })
];

if (production) { // Production plugins go here
  plugins = plugins.concat([
    // Cleanup the builds/ folder before compiling final assets
    new CleanPlugin(PATHS.build),
    // Looks for similar chunks and files and merge them
    new webpack.optimize.DedupePlugin(),
    // Optimize chunks and modules by how much they are used
    new webpack.optimize.OccurenceOrderPlugin(),
    // Prevent Webpack from creating too small chunks
    new webpack.optimize.MinChunkSizePlugin({ minChunkSize: 51200 }), // ~50kb
    // Minify all the Javascript code of the final bundle
    new webpack.optimize.UglifyJsPlugin({ minimize: true,
                                          compress: { warnings: false } }),
    new webpack.optimize.AggressiveMergingPlugin(),
    // Define variables, useful to distinguish production and devel
    new webpack.DefinePlugin({
      __SERVER__:      !production,
      __DEVELOPMENT__: !production,
      __DEVTOOLS__:    !production,
      'process.env': { // This has effect on the react lib size
        'NODE_ENV': JSON.stringify('production'),
        'BABEL_ENV': JSON.stringify(process.env.NODE_ENV)
      }
    })
  ]);
}

var config = {
  debug: !production,
  cache: true,
  devtool: production ? 'cheap-module-source-map': 'cheap-module-eval-source-map',
  entry: {
    app: [
      'babel-polyfill',
      PATHS.app
    ],
    vendor: ['d3', 'dimple', 'react', 'react-dom', 'react-redux', 'react-router', 'redux']
  },
  output: {
    path: PATHS.build,
    filename: '[name]-[hash].js',
    // publicPath: "http://localhost:8080/", // Development server
    // publicPath: "http://example.com/", // Production
    publicPath: production ? epbdurlprefix : '' // This is used to generate URLs to e.g. images,css
  },
  resolve: {
    root: [PATHS.app, PATHS.node],
    modulesDirectories: [PATHS.nodedir],
    extensions: ['', '.js', '.jsx', '.json'],
    alias: { // Para usar alias en imports
      'styles': PATHS.styles,
      'components': PATHS.components,
      'img': PATHS.images,
      'actions': PATHS.actions,
      'reducers': PATHS.reducers,
      'store': PATHS.store,
      'node': PATHS.node
    }
  },
  module: {
    noParse: [],
    loaders: [
      { // JS, JSX: BABEL
        test: /\.jsx?$/,
        include: PATHS.app,
        loader: 'babel',
        query: {cacheDirectory: true,
                presets: ['es2015', 'stage-0', 'react']}
      },
      { // CSS
        test: /\.css$/,
        include: [PATHS.app, PATHS.node],
        loader: ExtractTextPlugin.extract('style', 'css!postcss')
      },
      { // SASS
        test: /\.scss$/,
        include: PATHS.app,
        loader: ExtractTextPlugin.extract('style', 'css!postcss!sass?outputStyle=expanded')
      },
      { // IMG  direct URLs for the rest
        test: /\.(png|jpe?g|gif)$/i,
        include: PATHS.app,
        loader: 'img!file?name=img/[name]-[hash].[ext]'
      },
      { // .ico files
        test: /\.ico$/i,
        include: PATHS.app,
        loader: 'img!file?name=[name].[ext]'
      },
      // required for bootstrap icons
      { test: /\.woff2?$/,                     loader: 'file?name=fonts/[name]-[hash].[ext]' },
      { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,    loader: 'file?name=fonts/[name]-[hash].[ext]' },
      { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,    loader: 'file?name=fonts/[name]-[hash].[ext]' },
      { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,    loader: 'file?name=img/[name]-[hash].[ext]' },
      // Bootstrap 3
      { test: /bootstrap-sass\/assets\/javascripts\//, loader: 'imports?jQuery=jquery' },
      // Bootstrap 4
      { test: /bootstrap\/build\/js\/umd\//, loader: 'imports?jQuery=jquery' }
    ]
  },
  plugins: plugins,
  postcss: [ autoprefixer({ browsers: ['last 3 versions'] }) ]
};

module.exports = config;
<commit_msg>webpack: cambia título a VisorEPBD<commit_after>'use strict';

const path = require('path');
const autoprefixer = require('autoprefixer');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CleanPlugin = require('clean-webpack-plugin');

const production = process.env.NODE_ENV === 'production';
// Permitirmos usar la variable de entorno EPBDURLPREFIX para añadir prefijo
// a las direcciones estáticas y la url del servicio que llamamos con ajax
const epbdurlprefix = process.env.EPBDURLPREFIX || '';

const PATHS = {
  app: path.resolve(path.join(__dirname, 'app')),
  build: path.resolve(path.join(__dirname, 'build')),
  nodedir: 'node_modules',
  node: path.resolve(path.join(__dirname, 'node_modules')),
  styles: path.resolve(path.join(__dirname, 'app', 'css')),
  images: path.resolve(path.join(__dirname, 'app', 'img')),
  components: path.resolve(path.join(__dirname, 'app', 'components')),
  actions: path.resolve(path.join(__dirname, 'app', 'actions')),
  reducers: path.resolve(path.join(__dirname, 'app', 'reducers')),
  store: path.resolve(path.join(__dirname, 'app', 'store'))
};

var plugins = [
  new webpack.DefinePlugin({
    __EPBDURLPREFIX__: JSON.stringify(epbdurlprefix)
  }),
  new webpack.HotModuleReplacementPlugin(),
  new ExtractTextPlugin('bundle-[hash].css', { allChunks: true }),
  new HtmlWebpackPlugin({
    // https://github.com/jaketrent/html-webpack-template
    template: 'app/index.template.html',
    title: "VisorEPBD: implementación de la ISO 52000-1 para el CTE DB-HE",
    inject: false,
    //favicon: 'favicon.ico',
    filename: './index.html', // relativo al output path
    minify: { removeComments: true, collapseWhitespace: true }
  }),
  new webpack.NoErrorsPlugin(),
  new webpack.optimize.CommonsChunkPlugin({
    names: ['vendor'],
    filename: '[name].js',
    minChunks: Infinity // only vendor chunks here
  })
];

if (production) { // Production plugins go here
  plugins = plugins.concat([
    // Cleanup the builds/ folder before compiling final assets
    new CleanPlugin(PATHS.build),
    // Looks for similar chunks and files and merge them
    new webpack.optimize.DedupePlugin(),
    // Optimize chunks and modules by how much they are used
    new webpack.optimize.OccurenceOrderPlugin(),
    // Prevent Webpack from creating too small chunks
    new webpack.optimize.MinChunkSizePlugin({ minChunkSize: 51200 }), // ~50kb
    // Minify all the Javascript code of the final bundle
    new webpack.optimize.UglifyJsPlugin({ minimize: true,
                                          compress: { warnings: false } }),
    new webpack.optimize.AggressiveMergingPlugin(),
    // Define variables, useful to distinguish production and devel
    new webpack.DefinePlugin({
      __SERVER__:      !production,
      __DEVELOPMENT__: !production,
      __DEVTOOLS__:    !production,
      'process.env': { // This has effect on the react lib size
        'NODE_ENV': JSON.stringify('production'),
        'BABEL_ENV': JSON.stringify(process.env.NODE_ENV)
      }
    })
  ]);
}

var config = {
  debug: !production,
  cache: true,
  devtool: production ? 'cheap-module-source-map': 'cheap-module-eval-source-map',
  entry: {
    app: [
      'babel-polyfill',
      PATHS.app
    ],
    vendor: ['d3', 'dimple', 'react', 'react-dom', 'react-redux', 'react-router', 'redux']
  },
  output: {
    path: PATHS.build,
    filename: '[name]-[hash].js',
    // publicPath: "http://localhost:8080/", // Development server
    // publicPath: "http://example.com/", // Production
    publicPath: production ? epbdurlprefix : '' // This is used to generate URLs to e.g. images,css
  },
  resolve: {
    root: [PATHS.app, PATHS.node],
    modulesDirectories: [PATHS.nodedir],
    extensions: ['', '.js', '.jsx', '.json'],
    alias: { // Para usar alias en imports
      'styles': PATHS.styles,
      'components': PATHS.components,
      'img': PATHS.images,
      'actions': PATHS.actions,
      'reducers': PATHS.reducers,
      'store': PATHS.store,
      'node': PATHS.node
    }
  },
  module: {
    noParse: [],
    loaders: [
      { // JS, JSX: BABEL
        test: /\.jsx?$/,
        include: PATHS.app,
        loader: 'babel',
        query: {cacheDirectory: true,
                presets: ['es2015', 'stage-0', 'react']}
      },
      { // CSS
        test: /\.css$/,
        include: [PATHS.app, PATHS.node],
        loader: ExtractTextPlugin.extract('style', 'css!postcss')
      },
      { // SASS
        test: /\.scss$/,
        include: PATHS.app,
        loader: ExtractTextPlugin.extract('style', 'css!postcss!sass?outputStyle=expanded')
      },
      { // IMG  direct URLs for the rest
        test: /\.(png|jpe?g|gif)$/i,
        include: PATHS.app,
        loader: 'img!file?name=img/[name]-[hash].[ext]'
      },
      { // .ico files
        test: /\.ico$/i,
        include: PATHS.app,
        loader: 'img!file?name=[name].[ext]'
      },
      // required for bootstrap icons
      { test: /\.woff2?$/,                     loader: 'file?name=fonts/[name]-[hash].[ext]' },
      { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,    loader: 'file?name=fonts/[name]-[hash].[ext]' },
      { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,    loader: 'file?name=fonts/[name]-[hash].[ext]' },
      { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,    loader: 'file?name=img/[name]-[hash].[ext]' },
      // Bootstrap 3
      { test: /bootstrap-sass\/assets\/javascripts\//, loader: 'imports?jQuery=jquery' },
      // Bootstrap 4
      { test: /bootstrap\/build\/js\/umd\//, loader: 'imports?jQuery=jquery' }
    ]
  },
  plugins: plugins,
  postcss: [ autoprefixer({ browsers: ['last 3 versions'] }) ]
};

module.exports = config;
<|endoftext|>


<commit_before>/*
  ONLY RUN BUILDS WITH `npm run webpack`!
  DO NOT USE NORMAL WEBPACK! IT WILL NOT WORK!
*/

const webpack = require('webpack');
const createVariants = require('parallel-webpack').createVariants;
const version = require('./package.json').version;

const createConfig = (options) => {
  const plugins = [
    new webpack.DefinePlugin({ 'global.GENTLY': false }),
  ];

  if (options.minify) plugins.push(new webpack.optimize.UglifyJsPlugin({ minimize: true }));

  const filename = `./webpack/discord${process.env.VERSIONED === 'false' ? '' : '.' + version}${options.minify ? '.min' : ''}.js`; // eslint-disable-line

  return {
    entry: './src/index.js',
    output: {
      path: __dirname,
      filename,
    },
    module: {
      rules: [
        { test: /\.md$/, loader: 'ignore-loader' },
      ],
    },
    node: {
      fs: 'empty',
      dns: 'mock',
      tls: 'mock',
      child_process: 'empty',
      dgram: 'empty',
      zlib: 'empty',
      __dirname: true,
    },
    plugins,
  };
};

module.exports = createVariants({}, { minify: [false, true] }, createConfig);
<commit_msg>Fix arrow parens<commit_after>/*
  ONLY RUN BUILDS WITH `npm run webpack`!
  DO NOT USE NORMAL WEBPACK! IT WILL NOT WORK!
*/

const webpack = require('webpack');
const createVariants = require('parallel-webpack').createVariants;
const version = require('./package.json').version;

const createConfig = options => {
  const plugins = [
    new webpack.DefinePlugin({ 'global.GENTLY': false }),
  ];

  if (options.minify) plugins.push(new webpack.optimize.UglifyJsPlugin({ minimize: true }));

  const filename = `./webpack/discord${process.env.VERSIONED === 'false' ? '' : '.' + version}${options.minify ? '.min' : ''}.js`; // eslint-disable-line

  return {
    entry: './src/index.js',
    output: {
      path: __dirname,
      filename,
    },
    module: {
      rules: [
        { test: /\.md$/, loader: 'ignore-loader' },
      ],
    },
    node: {
      fs: 'empty',
      dns: 'mock',
      tls: 'mock',
      child_process: 'empty',
      dgram: 'empty',
      zlib: 'empty',
      __dirname: true,
    },
    plugins,
  };
};

module.exports = createVariants({}, { minify: [false, true] }, createConfig);
<|endoftext|>


<commit_before>module.exports = {
  entry: './src/init.js',
  devtool: 'source-map',
  output: {
    filename: __dirname + '/build/build.js',
    library: 'RemoteStorage',
    libraryTarget: 'umd',
    umdNamedDefine: true
  },
  resolve: {
    extensions: ['', '.js']
  }
};
<commit_msg>xmlhttprequest require fix !!<commit_after>module.exports = {
  entry: './src/init.js',
  devtool: 'source-map',
  output: {
    filename: __dirname + '/build/build.js',
    library: 'RemoteStorage',
    libraryTarget: 'umd',
    umdNamedDefine: true
  },
  externals: [
    {xmlhttprequest: "XMLHttpRequest"}
  ],
  resolve: {
    extensions: ['', '.js']
  }
};
<|endoftext|>


<commit_before>/*------------------------------------------------------------------

  [Globally Applied Application Script]

  [Table of Contents]

	1. Make Bootstrap Modals Draggable
	2. Make Bootstrap Alerts Hideable
	3. MsgGrowl: Not Implemented Yet
	4. Generic Ajax File Modal Listener
	5. Generic Ajax Form Modal Listener
	6. Generic Ajax Form Poster
	7. Remove Form Validation Feedback
	8. All Form Validation Feedback To Success
	9. Allow Form Submit Using Enter Key
	10. MsgGrowl: Generic Ajax Fetch Errors

-------------------------------------------------------------------*/

/*------------------------------------------------------------------
* 1. Make Bootstrap Modals Draggable (using jQuery-UI)
* ---------------------------------------------------------------*/
$(document).ready(function() {
	$(".modal-dialog").draggable({
		handle: ".modal-header"
	})
})

/*------------------------------------------------------------------
 * 2. Make Bootstrap Alerts Hideable
 *
 * Use jQuery for hiding the alerts on close instead of removing
 * them from DOM completely (as done by Bootstrap) to allow re-use.
 * ---------------------------------------------------------------*/
$(document).ready(function() {
	$('.alert .close').on('click',function(){
		$(this).parent().hide();
	})
})

/*------------------------------------------------------------------
 * 3. MsgGrowl: Not Implemented Yet
 * ---------------------------------------------------------------*/
$(document).ready(function() {
	$('.todo').on('click', function () {
		$.msgGrowl ({
			type: 'error',
			title: 'Not Implemented Yet',
			text: "Feel free to submit a PR to speed things up."
		})
	})
})

/*------------------------------------------------------------------
 * 4. Generic Ajax File Modal Listener
 * ---------------------------------------------------------------*/
$(document).ready(function() {
	$('.ajax-file-modal').on('click', function () {
		var modal = $('#ajaxModal')
		var title = S($(this).attr('id')).humanize().s
		var link = $(this).attr('rel')
		$('.modal-title').html(title)

		var jqxhr = $.getJSON(link, function(data) {
			modal.find('.modal-body').html('
' + data.fileContent + '
')
			modal.modal('show')
		})
		.fail(function() {
			ajaxFetchError()
		})
	})
})

/*------------------------------------------------------------------
 * 5. Generic Ajax Form Modal Listener
 * ---------------------------------------------------------------*/
$(document).ready(function() {
	$('.ajax-form-modal').on('click', function () {
		var modal = $($(this).attr('data-target'))
		var title = $(this).attr('alt')
		$('.modal-title').html(title)
		modal.modal('show')
	})
})

/*------------------------------------------------------------------
 * 6. Generic Ajax Form Poster (including CSRF token)
 * ---------------------------------------------------------------*/
$(document).ready(function() {
	$('#form-submit').click(function() {
		var form = $(this).closest('.modal-content').find('form')
		var url = form.attr('action')
		var data = form.serialize();

		$.ajax({
			url: url,
			type: "POST",
			// Note => explicit X-CSRF header disabled for now because we are
			//         passing the token as part of the form fields as well.
			// headers: {
			// 	'X-CSRF-Token': $('input[name="_csrfToken"]').attr('value')
			// },
			data: data
		})
		.fail(function( msg ) {
			var response = msg.responseJSON
			var validationErrors = response.validation_errors
			clearFormFeedback(form)

			// Display error message only if all fields validated
			if (!validationErrors) {
				setFormToValidated(form)
				form.find('.alert > span').html(msg.responseJSON.message)
				form.find('.alert').show()
				return
			}

			// One or more fields did not pass validation
			var inputs = form.find(".form-group.has-feedback :input")
			$.each(inputs, function (index, input) {
				var formGroup = $('input[name="' + input.name + '"]').closest('.form-group')

				// set to success if no validation errors are set
				if(!validationErrors[input.name]) {
					formGroup.addClass('has-success')
					formGroup.append('')
					return true
				}

				// set validation errors
				var list = ''
				$.each(validationErrors[input.name], function (validationRule, validationMessage) {
					list += '
' + validationMessage + '
'
				})
				formGroup.addClass('has-error')
				formGroup.append('')
				formGroup.append('
' + list + '')

			})
		})
		.success(function( msg ) {
			var target = $('.index-main .alert span.message')
			target.html(msg.message)
			target.closest('div').show()
			$('.modal.in').modal('hide')
		})
	})
})

/*------------------------------------------------------------------
 * 7. Remove Form Validation Feedback
 * ---------------------------------------------------------------*/
function clearFormFeedback(form) {
	form.find(".form-group.has-feedback :input").each( function(index, input) {
	//form.find(":input.has-feedback").each( function(index, input) {
		var formGroup = $('input[name="' + input.name + '"]').closest('.form-group')
		formGroup.removeClass('has-error has-success')
		formGroup.find('.form-control-feedback').remove()
		formGroup.find('.help-block').remove()

	})
}

/*------------------------------------------------------------------
 * 8. All Form Validation Feedback To Success
 * ---------------------------------------------------------------*/
function setFormToValidated(form) {
	form.find(".form-group.has-feedback :input").each( function(index, input) {
		var formGroup = $('input[name="' + input.name + '"]').closest('.form-group .has-feedback')
		//formGroup.addClass('has-feedback has-success')
		formGroup.addClass('has-success')
		formGroup.append('')
	})
}

/*------------------------------------------------------------------
 * 9. Allow Form Submit Using Enter Key
 * ---------------------------------------------------------------*/
$(document).ready(function() {
	$('form').keypress(function(e) {
		if (e.keyCode == 13) {
			$(this).closest('.modal-content').find('#form-submit').trigger('click')
		}
	})
})

/*------------------------------------------------------------------
 * 10. MsgGrowl: Generic Ajax Fetch Errors
 * ---------------------------------------------------------------*/
function ajaxFetchError(event) {
	$.msgGrowl ({
		type: 'error',
		title: 'Error fetching data',
		text: 'So sorry... something went wrong fetching the remote data'
	});
}
<commit_msg>Wording<commit_after>/*------------------------------------------------------------------

  [Globally Applied Application Script]

  [Table of Contents]

	1. Make Bootstrap Modals Draggable
	2. Make Bootstrap Alerts Hideable
	3. MsgGrowl: Not Implemented Yet
	4. Generic Ajax File Modal Listener
	5. Generic Ajax Form Modal Listener
	6. Generic Ajax Form Poster
	7. Remove Form Validation Feedback
	8. All Form Validation Feedback To Success
	9. Allow Form Submit Using Enter Key
	10. MsgGrowl: Generic Ajax Fetch Errors

-------------------------------------------------------------------*/

/*------------------------------------------------------------------
* 1. Make Bootstrap Modals Draggable (using jQuery-UI)
* ---------------------------------------------------------------*/
$(document).ready(function() {
	$(".modal-dialog").draggable({
		handle: ".modal-header"
	})
})

/*------------------------------------------------------------------
 * 2. Make Bootstrap Alerts Hideable
 *
 * Use jQuery for hiding the alerts on close instead of removing
 * them from DOM completely (as done by Bootstrap) to allow re-use.
 * ---------------------------------------------------------------*/
$(document).ready(function() {
	$('.alert .close').on('click',function(){
		$(this).parent().hide();
	})
})

/*------------------------------------------------------------------
 * 3. MsgGrowl: Not Implemented Yet
 * ---------------------------------------------------------------*/
$(document).ready(function() {
	$('.todo').on('click', function () {
		$.msgGrowl ({
			type: 'error',
			title: 'Not Implemented Yet',
			text: "Feel free to submit a PR"
		})
	})
})

/*------------------------------------------------------------------
 * 4. Generic Ajax File Modal Listener
 * ---------------------------------------------------------------*/
$(document).ready(function() {
	$('.ajax-file-modal').on('click', function () {
		var modal = $('#ajaxModal')
		var title = S($(this).attr('id')).humanize().s
		var link = $(this).attr('rel')
		$('.modal-title').html(title)

		var jqxhr = $.getJSON(link, function(data) {
			modal.find('.modal-body').html('
' + data.fileContent + '
')
			modal.modal('show')
		})
		.fail(function() {
			ajaxFetchError()
		})
	})
})

/*------------------------------------------------------------------
 * 5. Generic Ajax Form Modal Listener
 * ---------------------------------------------------------------*/
$(document).ready(function() {
	$('.ajax-form-modal').on('click', function () {
		var modal = $($(this).attr('data-target'))
		var title = $(this).attr('alt')
		$('.modal-title').html(title)
		modal.modal('show')
	})
})

/*------------------------------------------------------------------
 * 6. Generic Ajax Form Poster (including CSRF token)
 * ---------------------------------------------------------------*/
$(document).ready(function() {
	$('#form-submit').click(function() {
		var form = $(this).closest('.modal-content').find('form')
		var url = form.attr('action')
		var data = form.serialize();

		$.ajax({
			url: url,
			type: "POST",
			// Note => explicit X-CSRF header disabled for now because we are
			//         passing the token as part of the form fields as well.
			// headers: {
			// 	'X-CSRF-Token': $('input[name="_csrfToken"]').attr('value')
			// },
			data: data
		})
		.fail(function( msg ) {
			var response = msg.responseJSON
			var validationErrors = response.validation_errors
			clearFormFeedback(form)

			// Display error message only if all fields validated
			if (!validationErrors) {
				setFormToValidated(form)
				form.find('.alert > span').html(msg.responseJSON.message)
				form.find('.alert').show()
				return
			}

			// One or more fields did not pass validation
			var inputs = form.find(".form-group.has-feedback :input")
			$.each(inputs, function (index, input) {
				var formGroup = $('input[name="' + input.name + '"]').closest('.form-group')

				// set to success if no validation errors are set
				if(!validationErrors[input.name]) {
					formGroup.addClass('has-success')
					formGroup.append('')
					return true
				}

				// set validation errors
				var list = ''
				$.each(validationErrors[input.name], function (validationRule, validationMessage) {
					list += '
' + validationMessage + '
'
				})
				formGroup.addClass('has-error')
				formGroup.append('')
				formGroup.append('
' + list + '')

			})
		})
		.success(function( msg ) {
			var target = $('.index-main .alert span.message')
			target.html(msg.message)
			target.closest('div').show()
			$('.modal.in').modal('hide')
		})
	})
})

/*------------------------------------------------------------------
 * 7. Remove Form Validation Feedback
 * ---------------------------------------------------------------*/
function clearFormFeedback(form) {
	form.find(".form-group.has-feedback :input").each( function(index, input) {
	//form.find(":input.has-feedback").each( function(index, input) {
		var formGroup = $('input[name="' + input.name + '"]').closest('.form-group')
		formGroup.removeClass('has-error has-success')
		formGroup.find('.form-control-feedback').remove()
		formGroup.find('.help-block').remove()

	})
}

/*------------------------------------------------------------------
 * 8. All Form Validation Feedback To Success
 * ---------------------------------------------------------------*/
function setFormToValidated(form) {
	form.find(".form-group.has-feedback :input").each( function(index, input) {
		var formGroup = $('input[name="' + input.name + '"]').closest('.form-group .has-feedback')
		//formGroup.addClass('has-feedback has-success')
		formGroup.addClass('has-success')
		formGroup.append('')
	})
}

/*------------------------------------------------------------------
 * 9. Allow Form Submit Using Enter Key
 * ---------------------------------------------------------------*/
$(document).ready(function() {
	$('form').keypress(function(e) {
		if (e.keyCode == 13) {
			$(this).closest('.modal-content').find('#form-submit').trigger('click')
		}
	})
})

/*------------------------------------------------------------------
 * 10. MsgGrowl: Generic Ajax Fetch Errors
 * ---------------------------------------------------------------*/
function ajaxFetchError(event) {
	$.msgGrowl ({
		type: 'error',
		title: 'Error fetching data',
		text: 'So sorry... something went wrong fetching the remote data'
	});
}
<|endoftext|>


<commit_before>var polyfillio = require('../lib');
var express = require('express');
var app = express().enable("strict routing");
var origamijson = require('../origami.json');
var PolyfillSet = require('./PolyfillSet');
var fs = require('fs');
var path = require('path');
var URL = require('url');
var Raven = require('raven');
var metrics = require('./metrics');
var testing = require('./testing');
var docs = require('./docs');
var morgan = require('morgan');
var appVersion = require(path.join(__dirname,'../package.json')).version;
var hostname = require("os").hostname();

'use strict';

var one_day = 60 * 60 * 24;
var one_week = one_day * 7;
var one_year = one_day * 365;
var contentTypes = {".js": 'application/javascript', ".css": 'text/css'};
var dateDeployed;

require('fs').stat(path.join(__dirname,'../package.json'), function(err, stat) {
	dateDeployed = stat.mtime;
});

// Log requests
if (process.env.ENABLE_ACCESS_LOG) {
	app.use(morgan('method=:method path=":url" request_id=:req[X-Request-ID] status=:status service=:response-time bytes=:res[content-length]'));
}

// Set up Sentry (getsentry.com) to collect JS errors.
if (process.env.SENTRY_DSN) {
	var ravenClient = new Raven.Client(process.env.SENTRY_DSN, {
		release: appVersion
	});
	ravenClient.patchGlobal();
	app.use(Raven.middleware.express.requestHandler(process.env.SENTRY_DSN));
}

// Default cache control policy
app.use(function(req, res, next) {
	res.set('Cache-Control', 'public, max-age='+one_week+', stale-while-revalidate='+one_week+', stale-if-error='+one_week);
	res.set('Timing-Allow-Origin', '*');
	res.removeHeader("x-powered-by");
	return next();
});

/* Tests */

app.use('/test/libs/mocha', express.static(path.join(__dirname, '/../node_modules/mocha')));
app.use('/test/libs/expect', express.static(path.join(__dirname, '/../node_modules/expect.js/')));

app.get(/\/test\/director\/?$/, testing.createEndpoint('director', polyfillio));
app.get(/\/test\/tests\/?$/, testing.createEndpoint('runner', polyfillio));

/* Documentation and version routing */

app.get(/^\/(?:v([12])(?:\/(?:docs\/?(?:([^\/]+)\/?)?)?)?)?$/, docs.route);
app.use(/^\/v[12]\/docs\/assets/, express.static(__dirname + '/../docs/assets'));

/* Endpoints for health, application metadata and availability status
 * compliant with FT Origami standard
 * http://origami.ft.com/docs/syntax/web-service-description/ */

// Allow robots to index docs only (avoid indexing API endpoints linked from websites that are using the service)
app.get('/robots.txt', function (req, res) {
    res.type('text/plain');
    res.send("User-agent: *\nAllow: /v1/docs\nAllow: /v2/docs\nDisallow: /");
});

app.get(/^\/__about$/, function(req, res) {
	var info = {
		"schemaVersion": 1,
		"name": "polyfill-service",
		"systemCode": "origami-polyfill-service",
		"purpose": "Stores a library of FT-approved polyfills and serves them to FT websites that need them in older browsers.",
		"audience": "public",
		"primaryUrl": "https://polyfill.webservices.ft.com",
		"serviceTier": "silver",
		"appVersion": appVersion,
		"apiVersion": 2,
		"apiVersions": [
			{ "path": "/v1", "supportStatus": "deprecated", "dateTerminated": "2016-01-01T00:00:00Z" },
			{ "path": "/v2", "supportStatus": "active" }
		],
		"hostname": hostname,
		"dateCreated": "2014-07-14T10:28:45Z",
		"dateDeployed": dateDeployed,
		"contacts": [
			{ "name": "Origami team", "email": "origami-support@ft.com", "rel": "owner", "domain": "All support enquiries" }
		],
		"links": [
			{"url": "https://github.com/Financial-Times/polyfill-service/issues", "category": "issues"},
			{"url": "https://github.com/Financial-Times/polyfill-service", "category": "repo"},
			{"url": "https://dashboard.heroku.com/apps/ft-polyfill-service", "category": "deployment", "description": "Production Heroku app control panel"},
			{"url": "https://dashboard.heroku.com/apps/ft-polyfill-service-qa", "category": "deployment", "description": "QA Heroku app control panel"},
			{"url": "http://grafana.ft.com/dashboard/db/origami-polyfill-service", "category": "monitoring", "description": "Grafana dashboard"},
			{"url": "https://app.fastly.com/#stats/service/4E1GeTez3EFH3cnwfyMAog", "category": "deployment", "description": "Fastly CDN app"},
			{"url": "https://my.pingdom.com/reports/uptime#check=1338405", "category": "monitoring", "description": "Pingdom check"},
			{"url": "https://docs.google.com/drawings/d/1eA_sYaSRkvOqIxdkN6LRpyHeOzv8Mxr51WMfXM1sS3Q/edit", "category": "documentation", "description": "Architecture diagram"},
			{"url": "https://github.com/Financial-Times/polyfill-service/blob/master/README.md", "category": "documentation", "description": "README"},
			{"url": "https://travis-ci.org/Financial-Times/polyfill-service", "category": "testing", "description": "Continuous Integration status on Travis"}
		]
	};

	res.set("Content-Type", "application/json;charset=utf-8");
	res.send(JSON.stringify(info));
});

// "Good to go" endpoint
app.get(/^\/__gtg$/, function(req, res) {
	res.set("Content-Type", "text/plain;charset=utf-8");
	res.set("Cache-Control", "no-cache");
	res.send("OK");
});

// Healthcheck
app.get(/^\/__health$/, function(req, res) {
	var info = {
		"schemaVersion": 1,
		"name": "polyfill-service",
		"description": "Open API endpoint for retrieving Javascript polyfill libraries based on the user's user agent.  More at http://github.com/Financial-Times/polyfill-service.",
		"checks": [
			{
				"name": "Server is up",
				"ok": true,
				"severity": 2,
				"businessImpact": "Web page rendering may degrade for customers using certain browsers. Dynamic client side behaviour is likely to fail.",
				"technicalSummary": "Tests that the Node JS process is up.",
				"panicGuide": "This application consists of Node JS processes on any number of nodes in an environment.  The process must have read permissions on files within its deployment.",
				"checkOutput": "None",
				"lastUpdated": new Date().toISOString()
			}
		],
	};

	res.set('Cache-Control', 'no-cache');
	res.set('Content-Type', 'application/json;charset=utf-8');
	res.send(JSON.stringify(info));
});

/* API endpoints */

app.get(/^\/v1\/(.*)/, function(req, res) {

	var qs = Object.keys(req.query).reduce(function(out, key) {
		if (key !== 'libVersion' && key !== 'gated') {
			out.push(key+'='+encodeURIComponent(req.query[key]));
		}
		return out;
	}, []).join('&');
	var redirPath = '/v2/' + req.params[0] + (qs.length ? '?'+qs : '');

	res.status(301);
	res.set('Location', redirPath);
	res.set('Deprecation-Notice', 'API version 1 has been decommissioned - see the body of this response for more information.');
	res.send('API version 1 has been decommissioned. Your request is being redirected to v2.  The `libVersion` and `gated` query string parameters are no longer supported and if present have been removed from your request.\n\nA deprecation period for v1 existed between August and December 2015, during which time v1 requests were honoured but a deprecation warning was added to output.');
});

app.get(/^\/v2\/polyfill(\.\w+)(\.\w+)?/, function(req, res) {
	metrics.counter('hits').inc();
	var respTimeTimer = metrics.timer('respTime').start();
	var firstParameter = req.params[0].toLowerCase();
	var minified =  firstParameter === '.min';
	var fileExtension = req.params[1] ? req.params[1].toLowerCase() : firstParameter;
	var uaString = (typeof req.query.ua === 'string' && req.query.ua) || req.header('user-agent');
	var flags = (typeof req.query.flags === 'string') ? req.query.flags.split(',') : [];
	var warnings = [];

	// Currently don't support CSS
	if (fileExtension !== '.js') {
		res.status(404);
		res.set('Content-Type', 'text/plain;charset=utf-8');
		res.send('/* Type not supported.  Only .js is supported at the moment */');
		return;
	}

	var polyfills = PolyfillSet.fromQueryParam(req.query.features, flags);

	// If inbound request did not specify UA on the query string, the cache key must use the HTTP header
	if (!req.query.ua) {
		res.set('Vary', 'User-Agent');
	}

	var params = {
		features: polyfills.get(),
		minify: minified
	};
	if (req.query.unknown) {
		params.unknown = req.query.unknown;
	}
	if (uaString) {
		params.uaString = uaString;
		metrics.counter('useragentcount.'+polyfillio.normalizeUserAgent(uaString).replace(/^(.*?)\/(\d+)(\..*)?$/, '$1.$2')).inc();
	}

	polyfillio.getPolyfillString(params).then(function(op) {
		if (warnings.length) {
			op = '/* WARNINGS:\n\n- ' + warnings.join('\n- ') + '\n\n*/\n\n' + op;
		}
		if (req.query.callback && req.query.callback.match(/^[\w\.]+$/)) {
			op += "\ntypeof "+req.query.callback+"==='function' && "+req.query.callback+"();";
		}
		res.set('Content-Type', contentTypes[fileExtension]+';charset=utf-8');
		res.set('Access-Control-Allow-Origin', '*');
		res.send(op);
		respTimeTimer.end();
	});

});

app.get("/v2/normalizeUa", function(req, res, next) {

	if (req.query.ua) {
		res.status(200);
		res.set('Cache-Control', 'public, max-age='+one_year+', stale-if-error='+(one_year+one_week));
		res.set('Normalized-User-Agent', encodeURIComponent(polyfillio.normalizeUserAgent(req.query.ua)));
		res.send();
	} else {
		res.status(400);
		res.send('ua query param required');
	}
});

if (process.env.SENTRY_DSN) {
	app.use(Raven.middleware.express.errorHandler(process.env.SENTRY_DSN));
}

function startService(port, callback) {
	callback = callback || function() {};

	app
		.listen(port, function (err) {
			callback(err, app);
		})
		.on('error', function (err) {
			callback(err);
		})
		.on('clientError', function (ex, sock) {
			console.log('HTTP clientError: ', ex.code);
		});
}

module.exports = startService;
<commit_msg>Allow full indexing, fixes #621<commit_after>var polyfillio = require('../lib');
var express = require('express');
var app = express().enable("strict routing");
var origamijson = require('../origami.json');
var PolyfillSet = require('./PolyfillSet');
var fs = require('fs');
var path = require('path');
var URL = require('url');
var Raven = require('raven');
var metrics = require('./metrics');
var testing = require('./testing');
var docs = require('./docs');
var morgan = require('morgan');
var appVersion = require(path.join(__dirname,'../package.json')).version;
var hostname = require("os").hostname();

'use strict';

var one_day = 60 * 60 * 24;
var one_week = one_day * 7;
var one_year = one_day * 365;
var contentTypes = {".js": 'application/javascript', ".css": 'text/css'};
var dateDeployed;

require('fs').stat(path.join(__dirname,'../package.json'), function(err, stat) {
	dateDeployed = stat.mtime;
});

// Log requests
if (process.env.ENABLE_ACCESS_LOG) {
	app.use(morgan('method=:method path=":url" request_id=:req[X-Request-ID] status=:status service=:response-time bytes=:res[content-length]'));
}

// Set up Sentry (getsentry.com) to collect JS errors.
if (process.env.SENTRY_DSN) {
	var ravenClient = new Raven.Client(process.env.SENTRY_DSN, {
		release: appVersion
	});
	ravenClient.patchGlobal();
	app.use(Raven.middleware.express.requestHandler(process.env.SENTRY_DSN));
}

// Default cache control policy
app.use(function(req, res, next) {
	res.set('Cache-Control', 'public, max-age='+one_week+', stale-while-revalidate='+one_week+', stale-if-error='+one_week);
	res.set('Timing-Allow-Origin', '*');
	res.removeHeader("x-powered-by");
	return next();
});

/* Tests */

app.use('/test/libs/mocha', express.static(path.join(__dirname, '/../node_modules/mocha')));
app.use('/test/libs/expect', express.static(path.join(__dirname, '/../node_modules/expect.js/')));

app.get(/\/test\/director\/?$/, testing.createEndpoint('director', polyfillio));
app.get(/\/test\/tests\/?$/, testing.createEndpoint('runner', polyfillio));

/* Documentation and version routing */

app.get(/^\/(?:v([12])(?:\/(?:docs\/?(?:([^\/]+)\/?)?)?)?)?$/, docs.route);
app.use(/^\/v[12]\/docs\/assets/, express.static(__dirname + '/../docs/assets'));

/* Endpoints for health, application metadata and availability status
 * compliant with FT Origami standard
 * http://origami.ft.com/docs/syntax/web-service-description/ */

// Allow robots to index the site, including polyfill bundles as some sites need polyfills in order to be indexable!
app.get('/robots.txt', function (req, res) {
    res.type('text/plain');
    res.send("User-agent: *\nDisallow:");
});

app.get(/^\/__about$/, function(req, res) {
	var info = {
		"schemaVersion": 1,
		"name": "polyfill-service",
		"systemCode": "origami-polyfill-service",
		"purpose": "Stores a library of FT-approved polyfills and serves them to FT websites that need them in older browsers.",
		"audience": "public",
		"primaryUrl": "https://polyfill.webservices.ft.com",
		"serviceTier": "silver",
		"appVersion": appVersion,
		"apiVersion": 2,
		"apiVersions": [
			{ "path": "/v1", "supportStatus": "deprecated", "dateTerminated": "2016-01-01T00:00:00Z" },
			{ "path": "/v2", "supportStatus": "active" }
		],
		"hostname": hostname,
		"dateCreated": "2014-07-14T10:28:45Z",
		"dateDeployed": dateDeployed,
		"contacts": [
			{ "name": "Origami team", "email": "origami-support@ft.com", "rel": "owner", "domain": "All support enquiries" }
		],
		"links": [
			{"url": "https://github.com/Financial-Times/polyfill-service/issues", "category": "issues"},
			{"url": "https://github.com/Financial-Times/polyfill-service", "category": "repo"},
			{"url": "https://dashboard.heroku.com/apps/ft-polyfill-service", "category": "deployment", "description": "Production Heroku app control panel"},
			{"url": "https://dashboard.heroku.com/apps/ft-polyfill-service-qa", "category": "deployment", "description": "QA Heroku app control panel"},
			{"url": "http://grafana.ft.com/dashboard/db/origami-polyfill-service", "category": "monitoring", "description": "Grafana dashboard"},
			{"url": "https://app.fastly.com/#stats/service/4E1GeTez3EFH3cnwfyMAog", "category": "deployment", "description": "Fastly CDN app"},
			{"url": "https://my.pingdom.com/reports/uptime#check=1338405", "category": "monitoring", "description": "Pingdom check"},
			{"url": "https://docs.google.com/drawings/d/1eA_sYaSRkvOqIxdkN6LRpyHeOzv8Mxr51WMfXM1sS3Q/edit", "category": "documentation", "description": "Architecture diagram"},
			{"url": "https://github.com/Financial-Times/polyfill-service/blob/master/README.md", "category": "documentation", "description": "README"},
			{"url": "https://travis-ci.org/Financial-Times/polyfill-service", "category": "testing", "description": "Continuous Integration status on Travis"}
		]
	};

	res.set("Content-Type", "application/json;charset=utf-8");
	res.send(JSON.stringify(info));
});

// "Good to go" endpoint
app.get(/^\/__gtg$/, function(req, res) {
	res.set("Content-Type", "text/plain;charset=utf-8");
	res.set("Cache-Control", "no-cache");
	res.send("OK");
});

// Healthcheck
app.get(/^\/__health$/, function(req, res) {
	var info = {
		"schemaVersion": 1,
		"name": "polyfill-service",
		"description": "Open API endpoint for retrieving Javascript polyfill libraries based on the user's user agent.  More at http://github.com/Financial-Times/polyfill-service.",
		"checks": [
			{
				"name": "Server is up",
				"ok": true,
				"severity": 2,
				"businessImpact": "Web page rendering may degrade for customers using certain browsers. Dynamic client side behaviour is likely to fail.",
				"technicalSummary": "Tests that the Node JS process is up.",
				"panicGuide": "This application consists of Node JS processes on any number of nodes in an environment.  The process must have read permissions on files within its deployment.",
				"checkOutput": "None",
				"lastUpdated": new Date().toISOString()
			}
		],
	};

	res.set('Cache-Control', 'no-cache');
	res.set('Content-Type', 'application/json;charset=utf-8');
	res.send(JSON.stringify(info));
});

/* API endpoints */

app.get(/^\/v1\/(.*)/, function(req, res) {

	var qs = Object.keys(req.query).reduce(function(out, key) {
		if (key !== 'libVersion' && key !== 'gated') {
			out.push(key+'='+encodeURIComponent(req.query[key]));
		}
		return out;
	}, []).join('&');
	var redirPath = '/v2/' + req.params[0] + (qs.length ? '?'+qs : '');

	res.status(301);
	res.set('Location', redirPath);
	res.set('Deprecation-Notice', 'API version 1 has been decommissioned - see the body of this response for more information.');
	res.send('API version 1 has been decommissioned. Your request is being redirected to v2.  The `libVersion` and `gated` query string parameters are no longer supported and if present have been removed from your request.\n\nA deprecation period for v1 existed between August and December 2015, during which time v1 requests were honoured but a deprecation warning was added to output.');
});

app.get(/^\/v2\/polyfill(\.\w+)(\.\w+)?/, function(req, res) {
	metrics.counter('hits').inc();
	var respTimeTimer = metrics.timer('respTime').start();
	var firstParameter = req.params[0].toLowerCase();
	var minified =  firstParameter === '.min';
	var fileExtension = req.params[1] ? req.params[1].toLowerCase() : firstParameter;
	var uaString = (typeof req.query.ua === 'string' && req.query.ua) || req.header('user-agent');
	var flags = (typeof req.query.flags === 'string') ? req.query.flags.split(',') : [];
	var warnings = [];

	// Currently don't support CSS
	if (fileExtension !== '.js') {
		res.status(404);
		res.set('Content-Type', 'text/plain;charset=utf-8');
		res.send('/* Type not supported.  Only .js is supported at the moment */');
		return;
	}

	var polyfills = PolyfillSet.fromQueryParam(req.query.features, flags);

	// If inbound request did not specify UA on the query string, the cache key must use the HTTP header
	if (!req.query.ua) {
		res.set('Vary', 'User-Agent');
	}

	var params = {
		features: polyfills.get(),
		minify: minified
	};
	if (req.query.unknown) {
		params.unknown = req.query.unknown;
	}
	if (uaString) {
		params.uaString = uaString;
		metrics.counter('useragentcount.'+polyfillio.normalizeUserAgent(uaString).replace(/^(.*?)\/(\d+)(\..*)?$/, '$1.$2')).inc();
	}

	polyfillio.getPolyfillString(params).then(function(op) {
		if (warnings.length) {
			op = '/* WARNINGS:\n\n- ' + warnings.join('\n- ') + '\n\n*/\n\n' + op;
		}
		if (req.query.callback && req.query.callback.match(/^[\w\.]+$/)) {
			op += "\ntypeof "+req.query.callback+"==='function' && "+req.query.callback+"();";
		}
		res.set('Content-Type', contentTypes[fileExtension]+';charset=utf-8');
		res.set('Access-Control-Allow-Origin', '*');
		res.send(op);
		respTimeTimer.end();
	});

});

app.get("/v2/normalizeUa", function(req, res, next) {

	if (req.query.ua) {
		res.status(200);
		res.set('Cache-Control', 'public, max-age='+one_year+', stale-if-error='+(one_year+one_week));
		res.set('Normalized-User-Agent', encodeURIComponent(polyfillio.normalizeUserAgent(req.query.ua)));
		res.send();
	} else {
		res.status(400);
		res.send('ua query param required');
	}
});

if (process.env.SENTRY_DSN) {
	app.use(Raven.middleware.express.errorHandler(process.env.SENTRY_DSN));
}

function startService(port, callback) {
	callback = callback || function() {};

	app
		.listen(port, function (err) {
			callback(err, app);
		})
		.on('error', function (err) {
			callback(err);
		})
		.on('clientError', function (ex, sock) {
			console.log('HTTP clientError: ', ex.code);
		});
}

module.exports = startService;
<|endoftext|>


<commit_before>'use strict';

var User = require('../models/user');
var secrets = require('../config/secrets');
var restify = require('restify');
var nodemailer = require('nodemailer');
var mailgunApiTransport = require('nodemailer-mailgunapi-transport');
var moment = require('moment');

var knownEvents = {
  'invoice.payment_succeeded': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    if(req.stripeEvent.data && req.stripeEvent.data.object && req.stripeEvent.data.object.customer){
      // find user where stripeEvent.data.object.customer
      User.findOne({
        'stripe.customerId': req.stripeEvent.data.object.customer
      }, function (err, user) {
        if (err) return next(err);
        if(!user){
          // user does not exist, no need to process
          return res.status(200).end();
        } else {

            var t = moment(new Date( req.stripeEvent.data.object.period_end * 1000 ));
            var expiration = t.format("YYYY/MM/DD HH:mm:ss");
            var client = restify.createStringClient({
              url: secrets.vpnht.url,
            });

            client.basicAuth(secrets.vpnht.key, secrets.vpnht.secret);
            client.put('/activate/' + user.username, { expiration: expiration }, function (err, req2, res2, obj) {

                if (err) return next(err);

                var transporter = nodemailer.createTransport(
                  mailgunApiTransport({
                    apiKey: secrets.mailgun.password,
                    domain: secrets.mailgun.user
                  }));

                var mailOptions = {
                  to: user.email,
                  from: 'noreply@vpn.ht',
                  subject: 'VPN Account enabled',
                  text: 'You are receiving this email because your account has been activated till ' + expiration + '.\n\n' +
                    'You can read the documentation how to get started on:\n\n' +
                    'https://vpn.ht/documentation\n\n' +
                    'If you need help, feel free to contact us at support@vpn.ht.\n'
                };
                transporter.sendMail(mailOptions, function(err) {
                    console.log(err);
                  if (err) return next(err);

                  console.log('user: ' + user.username + ' subscription was successfully updated and expire on ' + expiration);
                  return res.status(200).end();

                });

            });

        }
      });
    } else {
      return next(new Error('stripeEvent.data.object.customer is undefined'));
    }
  },

  'account.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'account.application.deauthorized': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'application_fee.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'application_fee.refunded': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'balance.available': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.succeeded': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.failed': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.refunded': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.captured': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.dispute.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.dispute.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.dispute.closed': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.card.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.card.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.card.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.subscription.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.subscription.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.subscription.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');

    if(req.stripeEvent.data && req.stripeEvent.data.object && req.stripeEvent.data.object.customer){
      // find user where stripeEvent.data.object.customer
      User.findOne({
        'stripe.customerId': req.stripeEvent.data.object.customer
      }, function (err, user) {
        if (err) return next(err);
        if(!user){
          // user does not exist, no need to process
          return res.status(200).end();
        } else {
          user.stripe.last4 = '';
          user.stripe.plan = 'free';
          user.stripe.subscriptionId = '';
          user.save(function(err) {
            if (err) return next(err);
            console.log('user: ' + user.email + ' subscription was successfully cancelled.');
            return res.status(200).end();
          });
        }
      });
    } else {
      return next(new Error('stripeEvent.data.object.customer is undefined'));
    }
  },
  'customer.subscription.trial_will_end': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.discount.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.discount.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.discount.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'invoice.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'invoice.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'invoice.payment_failed ': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'invoiceitem.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'invoiceitem.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'invoiceitem.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'plan.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'plan.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'plan.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'coupon.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'coupon.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'recipient.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'recipient.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'recipient.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'transfer.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'transfer.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'transfer.paid': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'transfer.failed': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'ping': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  }
};

module.exports = function(req, res, next) {
  if(req.stripeEvent && req.stripeEvent.type && knownEvents[req.stripeEvent.type]){
    knownEvents[req.stripeEvent.type](req, res, next);
  } else {
    return next(new Error('Stripe Event not found'));
  }
};
<commit_msg>use right end date<commit_after>'use strict';

var User = require('../models/user');
var secrets = require('../config/secrets');
var restify = require('restify');
var nodemailer = require('nodemailer');
var mailgunApiTransport = require('nodemailer-mailgunapi-transport');
var moment = require('moment');

var knownEvents = {
  'invoice.payment_succeeded': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    if(req.stripeEvent.data && req.stripeEvent.data.object && req.stripeEvent.data.object.customer){
      // find user where stripeEvent.data.object.customer
      User.findOne({
        'stripe.customerId': req.stripeEvent.data.object.customer
      }, function (err, user) {
        if (err) return next(err);
        if(!user){
          // user does not exist, no need to process
          return res.status(200).end();
        } else {

            var t = moment(new Date( req.stripeEvent.data.object.lines.data[0].period.end * 1000 ));
            var expiration = t.format("YYYY/MM/DD HH:mm:ss");
            var client = restify.createStringClient({
              url: secrets.vpnht.url,
            });

            client.basicAuth(secrets.vpnht.key, secrets.vpnht.secret);
            client.put('/activate/' + user.username, { expiration: expiration }, function (err, req2, res2, obj) {

                if (err) return next(err);

                var transporter = nodemailer.createTransport(
                  mailgunApiTransport({
                    apiKey: secrets.mailgun.password,
                    domain: secrets.mailgun.user
                  }));

                var mailOptions = {
                  to: user.email,
                  from: 'noreply@vpn.ht',
                  subject: 'VPN Account enabled',
                  text: 'You are receiving this email because your account has been activated till ' + expiration + '.\n\n' +
                    'You can read the documentation how to get started on:\n\n' +
                    'https://vpn.ht/documentation\n\n' +
                    'If you need help, feel free to contact us at support@vpn.ht.\n'
                };
                transporter.sendMail(mailOptions, function(err) {
                  if (err) return next(err);

                  console.log('user: ' + user.username + ' subscription was successfully updated and expire on ' + expiration);
                  return res.status(200).end();

                });

            });

        }
      });
    } else {
      return next(new Error('stripeEvent.data.object.customer is undefined'));
    }
  },

  'account.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'account.application.deauthorized': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'application_fee.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'application_fee.refunded': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'balance.available': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.succeeded': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.failed': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.refunded': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.captured': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.dispute.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.dispute.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'charge.dispute.closed': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.card.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.card.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.card.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.subscription.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.subscription.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.subscription.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');

    if(req.stripeEvent.data && req.stripeEvent.data.object && req.stripeEvent.data.object.customer){
      // find user where stripeEvent.data.object.customer
      User.findOne({
        'stripe.customerId': req.stripeEvent.data.object.customer
      }, function (err, user) {
        if (err) return next(err);
        if(!user){
          // user does not exist, no need to process
          return res.status(200).end();
        } else {
          user.stripe.last4 = '';
          user.stripe.plan = 'free';
          user.stripe.subscriptionId = '';
          user.save(function(err) {
            if (err) return next(err);
            console.log('user: ' + user.email + ' subscription was successfully cancelled.');
            return res.status(200).end();
          });
        }
      });
    } else {
      return next(new Error('stripeEvent.data.object.customer is undefined'));
    }
  },
  'customer.subscription.trial_will_end': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.discount.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.discount.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'customer.discount.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'invoice.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'invoice.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'invoice.payment_failed ': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'invoiceitem.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'invoiceitem.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'invoiceitem.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'plan.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'plan.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'plan.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'coupon.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'coupon.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'recipient.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'recipient.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'recipient.deleted': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'transfer.created': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'transfer.updated': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'transfer.paid': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'transfer.failed': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  },
  'ping': function(req, res, next) {
    console.log(req.stripeEvent.type + ': event processed');
    res.status(200).end();
  }
};

module.exports = function(req, res, next) {
  if(req.stripeEvent && req.stripeEvent.type && knownEvents[req.stripeEvent.type]){
    knownEvents[req.stripeEvent.type](req, res, next);
  } else {
    return next(new Error('Stripe Event not found'));
  }
};
<|endoftext|>


<commit_before>'use strict';

var Task            = require('./-task');
var cordovaPath     = require('../utils/cordova-path');
var camelize        = require('../../lib/utils/string.js').camelize;
var path            = require('path');
var fs              = require('fs');
var chalk           = require('chalk');
var Promise         = require('ember-cli/lib/ext/promise');

var cordovaProj     = require('cordova-lib').cordova;

module.exports = Task.extend({
  id: undefined,
  name: undefined,
  project: undefined,
  ui: undefined,

  run: function(templatePath) {
    return new Promise(function(resolve) {
      var emberCdvPath = cordovaPath(this.project, true);

      if (!fs.existsSync(emberCdvPath)) {
        this.ui.writeLine('Initting ember-cordova directory');
        fs.mkdirSync(emberCdvPath);
      }

      var cdvPath = path.join(emberCdvPath, 'cordova');
      if (!fs.existsSync(cdvPath)) {
        var id = camelize(this.id);
        var name = camelize(this.name);

        var config = {};
        if (templatePath !== undefined) {
          config = {
            lib: {
              www: { url: templatePath, template: true }
            }
          };
        }

        return cordovaProj.raw.create(cdvPath, id, name, config).then(resolve);
      } else {
        this.ui.writeLine(chalk.yellow(
          'Warning: ember-cordova/cordova project already exists. ' +
          'Please ensure it is a real cordova project.'
        ));

        resolve();
      }
    }.bind(this));
  }
});

<commit_msg>feat(cordova-template): init with default ember-cordova-template<commit_after>'use strict';

var Task            = require('./-task');
var cordovaPath     = require('../utils/cordova-path');
var camelize        = require('../../lib/utils/string.js').camelize;
var path            = require('path');
var fs              = require('fs');
var chalk           = require('chalk');
var Promise         = require('ember-cli/lib/ext/promise');

var cordovaProj     = require('cordova-lib').cordova;

module.exports = Task.extend({
  id: undefined,
  name: undefined,
  project: undefined,
  ui: undefined,

  run: function(templatePath) {
    return new Promise(function(resolve) {
      var emberCdvPath = cordovaPath(this.project, true);

      if (!fs.existsSync(emberCdvPath)) {
        this.ui.writeLine('Initting ember-cordova directory');
        fs.mkdirSync(emberCdvPath);
      }

      var cdvPath = path.join(emberCdvPath, 'cordova');
      if (!fs.existsSync(cdvPath)) {
        var id = camelize(this.id);
        var name = camelize(this.name);

        var config = {
          lib: {
            www: { url: 'ember-cordova-template', template: true }
          }
        };

        if (templatePath !== undefined) {
          config.lib.www.url = templatePath;
        }

        return cordovaProj.raw.create(cdvPath, id, name, config).then(resolve);
      } else {
        this.ui.writeLine(chalk.yellow(
          'Warning: ember-cordova/cordova project already exists. ' +
          'Please ensure it is a real cordova project.'
        ));

        resolve();
      }
    }.bind(this));
  }
});

<|endoftext|>