This commit is contained in:
Carlos Jimenez Ruiz 2019-01-27 20:49:21 +01:00
commit 7333cb4114
47 changed files with 3477 additions and 3708 deletions

View File

@ -1,4 +1,3 @@
node_modules
front
services
!services/nginx
front/node_modules
services

3
.gitignore vendored
View File

@ -4,4 +4,5 @@ npm-debug.log
.eslintcache
datasources.*.json
print.*.json
db.json
db.json
junitresults.xml

View File

@ -25,10 +25,8 @@ RUN npm install --only=prod
COPY loopback loopback
COPY back back
COPY modules modules
COPY dist/webpack-assets.json dist/
COPY print print
COPY \
modules.yml \
LICENSE \
README.md \
./

27
Jenkinsfile vendored
View File

@ -45,9 +45,6 @@ pipeline {
}
}
stage('Build') {
environment {
CREDS = credentials('docker-registry')
}
steps {
nodejs('node-lts') {
withEnv(['NODE_ENV=']) {
@ -56,6 +53,29 @@ pipeline {
}
sh 'gulp build'
}
}
}
stage('Test') {
environment {
NODE_ENV = ""
FIREFOX_BIN = "/opt/firefox/firefox-bin"
}
steps {
nodejs('node-lts') {
sh 'karma start --junit'
// FIXME: Docker isn't at localhost
// sh 'gulp docker'
// sh 'gulp backendUnitTest --junit'
// sh 'docker rm -f salix-db'
}
}
}
stage('Docker') {
environment {
CREDS = credentials('docker-registry')
}
steps {
sh 'docker login --username $CREDS_USR --password $CREDS_PSW $REGISTRY'
sh 'docker-compose build --parallel'
sh 'docker-compose push'
@ -98,6 +118,7 @@ pipeline {
}
post {
always {
junit '*/junit.xml'
script {
if (!env.GIT_COMMITTER_EMAIL) return
try {

View File

@ -17,13 +17,10 @@ let SpecReporter = require('jasmine-spec-reporter').SpecReporter;
let serviceSpecs = [
`${__dirname}/**/*[sS]pec.js`,
`${__dirname}/../loopback/**/*[sS]pec.js`
`${__dirname}/../loopback/**/*[sS]pec.js`,
`${__dirname}/../modules/*/back/**/*.[sS]pec.js`
];
let services = require(`../modules.yml`);
for (let service of services)
serviceSpecs.push(`${__dirname}/../modules/${service}/back/**/*[sS]pec.js`);
jasmine.loadConfig({
spec_dir: '.',
spec_files: serviceSpecs,

View File

@ -5,7 +5,7 @@ services:
restart: unless-stopped
build:
context: .
dockerfile: services/nginx/Dockerfile
dockerfile: front/Dockerfile
ports:
- ${PORT}:80
links:

View File

@ -1,10 +1,10 @@
/* eslint no-invalid-this: "off" */
import config from './config.js';
import Nightmare from 'nightmare';
import {URL} from 'url';
let currentUser;
import config from './config.js';
let currentUser;
Nightmare.asyncAction = function(name, func) {
Nightmare.action(name, function(...args) {
@ -25,17 +25,42 @@ Nightmare.asyncAction('clearInput', async function(selector) {
let actions = {
login: function(userName, done) {
this.goto(`${config.url}#!/login`)
.wait(`vn-login input[name=user]`)
.write(`vn-login input[name=user]`, userName)
.write(`vn-login input[name=password]`, 'nightmare')
.click(`vn-login input[type=submit]`)
// FIXME: Wait for dom to be ready: https://github.com/segmentio/nightmare/issues/481
// .wait(1000)
.then(() => {
currentUser = userName;
done();
})
if (currentUser)
this.waitToClick('#logout');
let doLogin = () => {
this.wait(`vn-login input[name=user]`)
.write(`vn-login input[name=user]`, userName)
.write(`vn-login input[name=password]`, 'nightmare')
.click(`vn-login input[type=submit]`)
.then(() => {
currentUser = userName;
done();
})
.catch(done);
};
this.waitForURL('#!/login')
.then(doLogin)
.catch(() => {
this.goto(`${config.url}/#!/login`)
.then(doLogin)
.catch(done);
});
},
waitForLogin: function(userName, done) {
if (currentUser === userName) {
return this.waitToClick('vn-topbar a[ui-sref="home"]')
.waitForURL('#!/')
.then(done)
.catch(done);
}
return this.login(userName)
.waitForURL('#!/')
.url()
.changeLanguageToEnglish()
.then(done)
.catch(done);
},
@ -65,21 +90,6 @@ let actions = {
});
},
waitForLogin: function(userName, done) {
if (currentUser === userName) {
return this.waitToClick('vn-topbar a[ui-sref="home"]')
.waitForURL('#!/')
.then(done)
.catch(done);
}
return this.login(userName)
.waitForURL('#!/')
.url()
.changeLanguageToEnglish()
.then(done)
.catch(done);
},
selectModule: function(moduleName, done) {
this.waitToClick(`vn-home a[ui-sref="${moduleName}.index"]`)
.waitForURL(moduleName)

View File

@ -1,5 +1,6 @@
/* eslint no-console: 0 */
import Nightmare from 'nightmare';
let nightmare;
export default function createNightmare(width = 1280, height = 720) {
@ -22,7 +23,6 @@ export default function createNightmare(width = 1280, height = 720) {
});
nightmare.header('Accept-Language', 'en');
return nightmare;
}

View File

@ -9,7 +9,7 @@ RUN apt-get update \
&& ln -sf /dev/stderr /var/log/nginx/error.log
WORKDIR /etc/nginx
COPY services/nginx/temp/nginx.conf sites-available/salix
COPY front/nginx.conf sites-available/salix
RUN rm sites-enabled/default && ln -s ../sites-available/salix sites-enabled/salix
COPY dist /salix/dist

View File

@ -3,7 +3,6 @@ import './crud';
import './acl-service';
import './storage-services';
import './template';
import './spliting-register';
import './interpolate';
import './copy';
import './equals';

View File

@ -1,5 +1,5 @@
import ngModule from '../module';
import splitingRegister from './spliting-register';
import moduleImport from 'module-import';
factory.$inject = ['$http', '$window', '$ocLazyLoad', '$translatePartialLoader', '$translate', '$q'];
export function factory($http, $window, $ocLazyLoad, $translatePartialLoader, $translate, $q) {
@ -8,6 +8,10 @@ export function factory($http, $window, $ocLazyLoad, $translatePartialLoader, $t
this._loaded = {};
}
load(moduleName, validations) {
let moduleConf = $window.routes.find(i => i && i.module == moduleName);
if (!moduleConf)
return $q.reject(new Error(`Module not found: ${moduleName}`));
let loaded = this._loaded;
if (loaded[moduleName] === true)
@ -19,8 +23,8 @@ export function factory($http, $window, $ocLazyLoad, $translatePartialLoader, $t
loaded[moduleName] = false;
let deps = splitingRegister.getDependencies(moduleName);
let depPromises = [];
let deps = moduleConf.dependencies;
if (deps) {
for (let dep of deps)
@ -48,9 +52,7 @@ export function factory($http, $window, $ocLazyLoad, $translatePartialLoader, $t
}));
}
promises.push(new Promise(resolve => {
splitingRegister.modules[moduleName](resolve);
}));
promises.push(moduleImport(moduleName));
Promise.all(promises).then(() => {
loaded[moduleName] = true;

View File

@ -4,9 +4,10 @@ describe('factory vnModuleLoader', () => {
beforeEach(ngModule('vnCore'));
beforeEach(angular.mock.inject((_vnModuleLoader_, $rootScope) => {
beforeEach(angular.mock.inject((_vnModuleLoader_, $rootScope, $window) => {
vnModuleLoader = _vnModuleLoader_;
$scope = $rootScope;
$window.routes = [{module: 'myModule'}];
}));
describe('load()', () => {

View File

@ -1,12 +0,0 @@
class SplitingRegister {
constructor() {
this.graph = null;
this.modules = {};
}
getDependencies(moduleName) {
return this.graph[moduleName];
}
}
export default new SplitingRegister();

View File

@ -7,7 +7,7 @@ config.$inject = ['$translateProvider', '$translatePartialLoaderProvider'];
export function config($translateProvider, $translatePartialLoaderProvider) {
$translatePartialLoaderProvider.addPart('core');
let conf = {urlTemplate: '/static/locale/{part}/{lang}.json'};
let conf = {urlTemplate: '/locale/{part}/{lang}.json'};
let fallbackLang = 'es';
let langs = ['en', 'es'];

7
front/module-import.js Executable file
View File

@ -0,0 +1,7 @@
export default function moduleImport(moduleName) {
return import(
/* webpackInclude: /modules\/[a-z0-9-]+\/front\/index.js$/ */
`../modules/${moduleName}/front/index.js`
);
}

View File

@ -1,11 +0,0 @@
auth: []
client: []
core: []
item: [client]
salix: []
ticket: [item, client]
order: [item, ticket]
claim: [item, client]
route: []
agency: []
travel: []

View File

@ -7,19 +7,12 @@ server {
root /usr/share/nginx/html;
{{#services}}
location ~ ^/{{.}}(?:/(.*))?$ {
location ~ ^(/[a-zA-Z0-9_-]+)?/(?<path>api(/.*)?)$ {
resolver 127.0.0.11;
proxy_pass http://api:{{defaultPort}}/$1$is_args$args;
proxy_pass http://api:3000/$path$is_args$args;
}
{{/services}}
location ~ ^/static(?:/(.*))?$ {
location ~ ^(?:/(.*))?$ {
alias /salix/dist/$1;
autoindex on;
}
location ~ ^(?:/(.*))?$ {
resolver 127.0.0.11;
proxy_pass http://api:{{defaultPort}}/$1$is_args$args;
}
}

View File

@ -1,6 +1,7 @@
<ul ng-if="::$ctrl.items.length > 0" pad-medium-v>
<li ng-repeat="item in ::$ctrl.items" name="{{::item.description}}">
<a ui-sref="{{::item.state}}" ng-class="{active: item.childs.length == 0 && item.active, expanded: item.active, collapsed: !item.active}"
<a ui-sref="{{::item.state}}"
ng-class="{active: item.active && !item.childs, expanded: item.active, collapsed: !item.active}"
ng-click="$ctrl.setActive(item)">
<vn-icon icon="{{::item.icon}}" ng-if="::item.icon"></vn-icon>
<vn-icon icon="keyboard_arrow_down" ng-if="::item.childs.length > 0"></vn-icon>

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -5,7 +5,6 @@
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=no"/>
<meta name="mobile-web-app-capable" content="yes"/>
<title vn-title translate></title>
<script src="/acl"></script>
</head>
<body>
<vn-app></vn-app>

View File

@ -106,7 +106,7 @@ function $exceptionHandler(vnApp, $window, $state, $injector) {
if (data && data.error instanceof Object)
message = data.error.message;
else
message = `${exception.status}: ${exception.statusText}`;
message = exception.statusText;
}
} else if (exception.name == 'UserError')
messageT = exception.message;

View File

@ -1,7 +1,4 @@
import ngModule from './module';
import deps from 'modules.yml';
import modules from 'spliting';
import splitingRegister from 'core/lib/spliting-register';
import getMainRoute from 'core/lib/get-main-route';
function loader(moduleName, validations) {
@ -14,9 +11,6 @@ function loader(moduleName, validations) {
config.$inject = ['$stateProvider', '$urlRouterProvider'];
function config($stateProvider, $urlRouterProvider) {
splitingRegister.graph = deps;
splitingRegister.modules = modules;
$urlRouterProvider.otherwise('/');
$stateProvider.state('home', {

View File

@ -1,3 +1,4 @@
import './responsive.scss';
import './title.scss';
import './layout.scss';
import './display.scss';

View File

@ -0,0 +1,48 @@
/* Desktop - Laptop 1360x768 */
@media (max-resolution: 119dpi) and (min-device-width: 1340px) and (max-device-width: 1899px)
{
body { font-size: 10pt; }
}
/* Mobile - Low DPI */
@media
(min-resolution: 120dpi),
(-webkit-min-device-pixel-ratio: 1.5)
{
body { font-size: 9pt; }
}
@media
(min-resolution: 144dpi),
(-webkit-min-device-pixel-ratio: 1.5)
{
body { font-size: 11pt; }
}
/* Mobile - Normal DPI */
@media
(max-device-width: 383px) and (min-resolution: 192dpi),
(max-device-width: 383px) and (-webkit-min-device-pixel-ratio: 2)
{
body { font-size: 10pt; }
}
@media
(min-device-width: 384px) and (min-resolution: 192dpi),
(min-device-width: 384px) and (-webkit-min-device-pixel-ratio: 2)
{
body { font-size: 11pt; }
}
/* Mobile - High DPI */
@media
(max-device-width: 411px) and (min-resolution: 249dpi),
(max-device-width: 411px) and (-webkit-min-device-pixel-ratio: 3)
{
body { font-size: 10pt; }
}
@media
(min-device-width: 412px) and (min-resolution: 249dpi),
(min-device-width: 412px) and (-webkit-min-device-pixel-ratio: 3)
{
body { font-size: 11pt; }
}

View File

@ -1,18 +0,0 @@
export default {
client:
cb => require.ensure([], () => cb(require('client/front'))),
route:
cb => require.ensure([], () => cb(require('route/front'))),
item:
cb => require.ensure([], () => cb(require('item/front'))),
ticket:
cb => require.ensure([], () => cb(require('ticket/front'))),
order:
cb => require.ensure([], () => cb(require('order/front'))),
claim:
cb => require.ensure([], () => cb(require('claim/front'))),
agency:
cb => require.ensure([], () => cb(require('agency/front'))),
travel:
cb => require.ensure([], () => cb(require('travel/front')))
};

View File

@ -1,6 +1,5 @@
require('require-yaml');
const gulp = require('gulp');
const fs = require('fs-extra');
const exec = require('child_process').exec;
const PluginError = require('plugin-error');
const argv = require('minimist')(process.argv.slice(2));
@ -13,53 +12,52 @@ let isWindows = /^win/.test(process.platform);
if (argv.NODE_ENV)
process.env.NODE_ENV = argv.NODE_ENV;
let env = process.env.NODE_ENV ? process.env.NODE_ENV : 'development';
let langs = ['es', 'en'];
let srcDir = './front';
let modulesDir = './modules';
let servicesDir = './services';
let modules = require('./modules.yml');
let buildDir = 'dist';
let wpConfig = require('./webpack.config.yml');
let buildDir = wpConfig.buildDir;
let devServerPort = wpConfig.devServerPort;
let nginxDir = `${servicesDir}/nginx`;
let proxyConf = require(`${nginxDir}/config.yml`);
let proxyEnvFile = `${nginxDir}/config.${env}.yml`;
if (fs.existsSync(proxyEnvFile))
Object.assign(proxyConf, require(proxyEnvFile));
let defaultService = proxyConf.main;
let defaultPort = proxyConf.defaultPort;
let backSources = [
'loopback',
'modules/*/back/**',
'back'
];
// Development
const nginx = gulp.series(nginxStart);
nginx.description = `Starts/restarts the nginx process`;
const localesRoutes = gulp.parallel(locales, routes);
localesRoutes.description = `Builds locales and routes`;
const front = gulp.series(buildClean, gulp.parallel(localesRoutes, watch, webpackDevServer));
const front = gulp.series(clean, gulp.parallel(localesRoutes, watch, webpackDevServer));
front.description = `Starts frontend service`;
const back = gulp.series(dockerStart, backOnly, nginx);
function backOnly(done) {
let app = require(`./loopback/server/server`);
app.start();
app.on('started', done);
}
backOnly.description = `Starts backend service`;
function backWatch(done) {
const nodemon = require('gulp-nodemon');
let sleepBin = isWindows ? 'timeout' : 'sleep';
nodemon({
exec: `${sleepBin} 1 && node --inspect ./node_modules/gulp/bin/gulp.js`,
args: ['backOnly'],
watch: backSources,
done: done
});
}
backWatch.description = `Starts backend in waching mode`;
const back = gulp.series(dockerStart, backWatch);
back.description = `Starts backend and database service`;
const defaultTask = gulp.parallel(front, back);
defaultTask.description = `Starts all application services`;
function backOnly(done) {
let app = require(`./loopback/server/server`);
app.start(defaultPort);
app.on('started', done);
}
backOnly.description = `Starts backend service`;
// backend tests
// Backend tests
function backendUnitTest() {
let app = require(`./loopback/server/server`);
@ -98,13 +96,13 @@ function backTest(done) {
nodemon({
exec: gulpBin,
args: ['dockerAndBackTest'],
watch: ['loopback', 'modules/*/back/**', 'back'],
watch: backSources,
done: done
});
}
backTest.description = `Watches for changes in modules to execute backTest task`;
// end to end tests
// End to end tests
function e2eOnly() {
const jasmine = require('gulp-jasmine');
@ -130,9 +128,6 @@ smokesOnly.description = `Runs the smokes tests only`;
smokes = gulp.series(docker, smokesOnly);
smokes.description = `Restarts database and runs the smokes tests`;
const clean = gulp.parallel(buildClean, nginxClean);
clean.description = 'Cleans all generated project files';
function install() {
const install = require('gulp-install');
const print = require('gulp-print');
@ -153,17 +148,17 @@ i.description = `Alias for the 'install' task`;
// Deployment
const build = gulp.series(clean, gulp.parallel(localesRoutes, webpack, nginxConf));
const build = gulp.series(clean, gulp.parallel(localesRoutes, webpack));
build.description = `Generates binaries and configuration files`;
function buildClean() {
function clean() {
const del = require('del');
const files = [
`${buildDir}/*`
];
return del(files, {force: true});
}
buildClean.description = `Cleans all files generated by the 'build' task`;
clean.description = `Cleans all files generated by the 'build' task`;
// Webpack
@ -196,12 +191,14 @@ function webpackDevServer(done) {
for (let entryName in wpConfig.entry) {
let entry = wpConfig.entry[entryName];
let wdsAssets = [`webpack-dev-server/client?http://127.0.0.1:${devServer.port}/`];
if (Array.isArray(entry))
wdsAssets = wdsAssets.concat(entry);
else
wdsAssets.push(entry);
wpConfig.entry[entryName] = wdsAssets;
if (!Array.isArray(entry))
entry = [entry];
let wdsAssets = [
`webpack-dev-server/client?http://localhost:${devServer.port}/`,
`webpack/hot/dev-server`
];
wpConfig.entry[entryName] = wdsAssets.concat(entry);
}
let compiler = webpack(wpConfig);
@ -232,14 +229,16 @@ function locales() {
const mergeJson = require('gulp-merge-json');
const yaml = require('gulp-yaml');
const merge = require('merge-stream');
const fs = require('fs-extra');
let streams = [];
let localePaths = [];
let modules = fs.readdirSync(modulesDir);
for (let mod of modules)
localePaths[mod] = `${modulesDir}/${mod}`;
let baseMods = ['core', 'auth', 'salix'];
let baseMods = ['core', 'salix'];
for (let mod of baseMods)
localePaths[mod] = `${srcDir}/${mod}`;
@ -301,6 +300,8 @@ async function docker() {
await execP(`docker build --build-arg STAMP=${stamp} -t salix-db ./services/db`);
let runChown = process.platform != 'linux';
if (argv['run-chown']) runChown = true;
await execP(`docker run --env RUN_CHOWN=${runChown} -d --name salix-db -p 3306:3306 salix-db`);
if (runChown) await dockerWait();
}
@ -340,7 +341,7 @@ function dockerWait() {
let interval = 100;
let elapsedTime = 0;
let maxInterval = 30 * 60 * 1000;
let maxInterval = 5 * 60 * 1000;
log('Waiting for MySQL init process...');
checker();
@ -379,84 +380,6 @@ function dockerWait() {
}
dockerWait.description = `Waits until database service is ready`;
// Nginx
let nginxConfFile = 'temp/nginx.conf';
let nginxTemp = `${nginxDir}/temp`;
async function nginxStart() {
await nginxConf();
let nginxBin = await nginxGetBin();
if (isWindows)
nginxBin = `start /B ${nginxBin}`;
log(`Application available at http://${proxyConf.host}:${proxyConf.port}/`);
await execP(`${nginxBin} -c "${nginxConfFile}" -p "${nginxDir}"`);
}
nginxStart.description = `Starts the nginx process`;
async function nginxStop() {
try {
let nginxBin = await nginxGetBin();
await fs.stat(`${nginxTemp}/nginx.pid`);
await execP(`${nginxBin} -c "${nginxConfFile}" -p "${nginxDir}" -s stop`);
} catch (e) {}
}
nginxStop.description = `Stops the nginx process`;
/**
* Generates the nginx configuration file. If NODE_ENV is defined and the
* 'nginx.[environment].mst' file exists, it is used as a template, otherwise,
* the 'nginx.mst' template file is used.
*/
async function nginxConf() {
await nginxStop();
const mustache = require('mustache');
if (!await fs.exists(nginxTemp))
await fs.mkdir(nginxTemp);
let params = {
services: modules,
defaultService: defaultService,
defaultPort: defaultPort,
devServerPort: devServerPort,
port: proxyConf.port,
host: proxyConf.host
};
let confFile = `${nginxDir}/nginx.${env}.mst`;
if (!await fs.exists(confFile))
confFile = `${nginxDir}/nginx.mst`;
let template = await fs.readFile(confFile, 'utf8');
let nginxConfData = mustache.render(template, params);
await fs.writeFile(`${nginxTemp}/nginx.conf`, nginxConfData);
}
nginxConf.description = `Generates the nginx configuration file`;
async function nginxClean() {
await nginxStop();
const del = require('del');
return del([`${nginxTemp}/*`], {force: true});
}
nginxClean.description = `Cleans all files generated by nginx`;
async function nginxGetBin() {
if (isWindows)
return 'nginx';
try {
let nginxBin = '/usr/sbin/nginx';
await fs.stat(nginxBin);
return nginxBin;
} catch (e) {
return 'nginx';
}
}
// Helpers
/**
@ -485,6 +408,7 @@ module.exports = {
front,
back,
backOnly,
backWatch,
backendUnitTest,
dockerAndBackTest,
backTest,
@ -492,16 +416,10 @@ module.exports = {
e2e,
smokesOnly,
smokes,
clean,
install,
i,
build,
buildClean,
nginxStart,
nginx,
nginxStop,
nginxConf,
nginxClean,
clean,
webpack,
webpackDevServer,
locales,

View File

@ -79,6 +79,7 @@ module.exports = function(config) {
'karma-webpack',
'karma-chrome-launcher',
'karma-firefox-launcher',
'karma-junit-reporter',
'karma-sourcemap-loader'
],
@ -113,5 +114,15 @@ module.exports = function(config) {
if (process.env.FIREFOX_BIN)
baseConfig.browsers = ['FirefoxHeadless'];
if (config.junit) {
Object.assign(baseConfig, {
singleRun: true,
reporters: ['dots', 'junit'],
junitReporter: {
outputFile: 'junit.xml'
}
});
}
config.set(baseConfig);
};

View File

@ -1,18 +0,0 @@
<!doctype html>
<html ng-app="salix">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=no"/>
<meta name="mobile-web-app-capable" content="yes"/>
<title vn-title translate></title>
</head>
<body>
<vn-app></vn-app>
<script type="text/javascript"
src="/static/routes.js?<%= version %>">
</script>
<% for (let jsFile of assets) { %>
<script type="text/javascript" src="<%= jsFile %>"></script>
<% } %>
</body>
</html>

View File

@ -1,13 +1,4 @@
module.exports = function(app) {
let bootTimestamp = new Date().getTime();
app.get('/', function(req, res) {
res.render('index.ejs', {
assets: app.getWpAssets('salix'),
version: bootTimestamp
});
});
// FIXME: Fix until the original can be used
app.get('/api/modelInfo', function(req, res) {
app.models.Schema.modelInfo({req}).then(json => {

View File

@ -1,18 +1,7 @@
{
"initial:before": {
"loopback#favicon": {
"params": "$!../favicon.ico"
}
},
"initial:before": {},
"initial": {
"compression": {},
"cors": {
"params": {
"origin": "*",
"credentials": true,
"maxAge": 86400
}
},
"helmet#xssFilter": {},
"helmet#frameguard": {
"params": [

View File

@ -1,5 +0,0 @@
let cors = require('cors');
module.exports = function() {
return cors({origin: true});
};

View File

@ -1,5 +1,4 @@
require('require-yaml');
const cookieParser = require('cookie-parser');
const loopback = require('loopback');
const boot = require('loopback-boot');
const DataSource = require('loopback-datasource-juggler').DataSource;
@ -31,12 +30,7 @@ let rootDir = __dirname;
let lbDir = path.resolve(`${rootDir}/..`);
let appDir = path.resolve(`${__dirname}/../..`);
let localeDir = `${lbDir}/locale`;
let viewDir = `${lbDir}/client`;
let buildDir = `${appDir}/dist`;
let servicesDir = `${appDir}/modules`;
let modulesPath = `${appDir}/modules.yml`;
app.use(cookieParser());
let modulesDir = `${appDir}/modules`;
// Internationalization
@ -49,28 +43,6 @@ if (fs.existsSync(localeDir)) {
app.use(i18n.init);
}
// View
if (fs.existsSync(viewDir)) {
app.set('view engine', 'ejs');
app.set('views', viewDir);
app.use(loopback.static(viewDir));
}
app.getWpAssets = entryPoint => {
const wpAssets = require(`${buildDir}/webpack-assets.json`);
let jsFiles = [];
let regex = new RegExp(`(^|~)${entryPoint}($|~)`);
for (let asset in wpAssets) {
if (regex.test(asset))
jsFiles.push(wpAssets[asset].js);
}
return jsFiles;
};
// Initialization
app.disconnect = async function() {
@ -116,9 +88,9 @@ let bootDirs = [
addPath(`${appDir}/back`);
let services = require(modulesPath);
for (let service of services)
addPath(`${servicesDir}/${service}/back`);
let modules = fs.readdirSync(modulesDir);
for (let mod of modules)
addPath(`${modulesDir}/${mod}/back`);
function addPath(path) {
modelConfigFiles.push(`${path}/model-config.json`);

View File

@ -1,10 +0,0 @@
[
client,
item,
ticket,
order,
claim,
route,
agency,
travel
]

View File

@ -3,6 +3,7 @@
"name": "Claims",
"icon": "icon-claims",
"validations": true,
"dependencies": ["item", "client"],
"routes": [
{
"url": "/claim",

View File

@ -3,6 +3,7 @@
"name": "Items",
"icon": "inbox",
"validations" : true,
"dependencies": ["client"],
"routes": [
{
"url": "/item",

View File

@ -3,6 +3,7 @@
"name": "Orders",
"icon": "shopping_cart",
"validations": true,
"dependencies": ["item", "ticket"],
"routes": [
{
"url": "/order",

View File

@ -3,6 +3,7 @@
"name": "Tickets",
"icon": "icon-ticket",
"validations": true,
"dependencies": ["item", "client"],
"routes": [
{
"url": "/ticket",

6528
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,6 @@
"license": "GPL-3.0",
"dependencies": {
"compression": "^1.7.3",
"cookie-parser": "^1.4.3",
"cors": "^2.8.5",
"fs-extra": "^5.0.0",
"helmet": "^3.15.0",
"i18n": "^0.8.3",
@ -22,18 +20,17 @@
"object.pick": "^1.3.0",
"request": "^2.88.0",
"require-yaml": "0.0.1",
"serve-favicon": "^2.5.0",
"strong-error-handler": "^2.3.2",
"uuid": "^3.3.2",
"vn-loopback": "file:./loopback"
},
"devDependencies": {
"@babel/core": "^7.2.2",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/polyfill": "^7.2.5",
"@babel/preset-env": "^7.2.0",
"@babel/register": "^7.0.0",
"angular-mocks": "^1.7.4",
"assets-webpack-plugin": "^3.9.7",
"babel-loader": "^8.0.5",
"css-loader": "^0.25.0",
"del": "^2.2.2",
@ -54,7 +51,6 @@
"gulp-yaml": "^1.0.1",
"html-loader": "^0.4.5",
"html-webpack-plugin": "^4.0.0-beta.5",
"http-proxy-middleware": "^0.19.1",
"jasmine": "^2.99.0",
"jasmine-reporters": "^2.3.2",
"jasmine-spec-reporter": "^4.2.1",
@ -63,11 +59,11 @@
"karma-chrome-launcher": "^2.2.0",
"karma-firefox-launcher": "^1.1.0",
"karma-jasmine": "^2.0.1",
"karma-junit-reporter": "^1.2.0",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^3.0.5",
"merge-stream": "^1.0.1",
"minimist": "^1.2.0",
"mustache": "^2.3.2",
"mysql2": "^1.6.1",
"nightmare": "^3.0.1",
"node-sass": "^4.9.3",

View File

@ -1 +0,0 @@
temp/*

View File

@ -1,2 +0,0 @@
host: salix
port: 80

View File

@ -1,2 +0,0 @@
host: test-salix
port: 80

View File

@ -1,4 +0,0 @@
host: localhost
port: 5000
main: salix
defaultPort: 3000

View File

@ -1,54 +0,0 @@
worker_processes 1;
error_log temp/error.log;
pid temp/nginx.pid;
events {
worker_connections 1024;
}
http {
sendfile on;
gzip on;
default_type application/octet-stream;
access_log temp/access.log;
client_body_temp_path temp/client-body;
proxy_temp_path temp/proxy;
fastcgi_temp_path temp/fastcgi;
uwsgi_temp_path temp/uwsgi;
scgi_temp_path temp/scgi;
server {
listen {{port}};
server_name {{host}};
autoindex off;
{{#services}}
location ~ ^/{{.}}(?:/(.*))?$ {
proxy_pass http://127.0.0.1:{{defaultPort}}/$1$is_args$args;
}
{{/services}}
location ~ ^/static(?:/(.*)?)$ {
proxy_pass http://127.0.0.1:{{devServerPort}}/$1$is_args$args;
}
location ~ ^(?:/(.*))?$ {
proxy_pass http://127.0.0.1:{{defaultPort}}/$1$is_args$args;
}
}
types {
text/html html;
application/json json;
application/javascript js;
text/css css scss;
text/xml xml;
image/x-icon ico;
image/png png;
image/svg+xml svg;
image/gif gif;
image/jpeg jpeg jpg;
}
}

View File

@ -3,20 +3,16 @@ const webpack = require('webpack');
const path = require('path');
const merge = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const AssetsWebpackPlugin = require('assets-webpack-plugin');
const wpConfig = require('./webpack.config.yml');
let env = process.env.NODE_ENV || 'development';
let mode = env == 'development' ? env : 'production';
let outputPath = path.join(__dirname, wpConfig.buildDir);
let baseConfig = {
entry: wpConfig.entry,
entry: {salix: 'salix'},
mode: mode,
output: {
path: outputPath,
publicPath: `${wpConfig.publicPath}/`
path: path.join(__dirname, 'dist'),
publicPath: '/'
},
module: {
rules: [
@ -25,7 +21,8 @@ let baseConfig = {
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['@babel/preset-env']
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-syntax-dynamic-import']
}
}, {
test: /\.yml$/,
@ -74,11 +71,9 @@ let baseConfig = {
}
},
plugins: [
new AssetsWebpackPlugin({
path: outputPath
}),
new HtmlWebpackPlugin({
template: 'front/salix/index.ejs',
favicon: 'front/salix/favicon.ico',
filename: 'index.html',
chunks: ['salix']
})
@ -112,15 +107,26 @@ let devConfig = {
filename: '[name].js',
chunkFilename: '[id].js'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
devServer: {
host: 'localhost',
port: wpConfig.devServerPort,
port: 5000,
publicPath: '/',
contentBase: wpConfig.buildDir,
contentBase: 'dist',
quiet: false,
noInfo: false,
// hot: true,
stats: baseConfig.stats
hot: true,
inline: true,
stats: baseConfig.stats,
proxy: {
'/api': 'http://localhost:3000',
'/*/api/**': {
target: 'http://localhost:3000',
pathRewrite: {'^/[\\w-]+': ''}
}
}
}
};

View File

@ -1,6 +0,0 @@
buildDir: dist
devServerPort: 3500
publicPath: '/static'
entry: {
salix: salix
}