add frame express app
This commit is contained in:
0
frame/.env_template
Normal file
0
frame/.env_template
Normal file
67
frame/.gitignore
vendored
Normal file
67
frame/.gitignore
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# Build folder
|
||||
build/
|
||||
|
||||
# Dist folder
|
||||
dist/
|
28
frame/package.json
Normal file
28
frame/package.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "frame",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "yarn build && node --inspect ./build/bin/www",
|
||||
"typescript": "tsc && cp -R ./src/views ./build/ && cp -R ./src/public ./build/",
|
||||
"build": "yarn typescript",
|
||||
"dist": "yarn build && cp -R ./build ./dist/ && cp -R ./node_modules ./dist/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "^14.0.13",
|
||||
"cookie-parser": "~1.4.4",
|
||||
"cors": "^2.8.5",
|
||||
"debug": "~2.6.9",
|
||||
"dotenv": "^8.2.0",
|
||||
"ejs": "~2.6.1",
|
||||
"express": "~4.16.1",
|
||||
"express-mysql-session": "^2.1.4",
|
||||
"express-session": "^1.17.1",
|
||||
"helmet": "^3.23.0",
|
||||
"http-errors": "~1.6.3",
|
||||
"morgan": "~1.9.1",
|
||||
"passport": "^0.4.1",
|
||||
"passport-oauth2": "^1.5.0",
|
||||
"passport-oauth2-refresh": "^2.0.0"
|
||||
}
|
||||
}
|
57
frame/src/app.ts
Normal file
57
frame/src/app.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import * as createError from 'http-errors';
|
||||
import * as express from 'express';
|
||||
import * as path from 'path';
|
||||
import * as cookieParser from 'cookie-parser';
|
||||
import * as logger from 'morgan';
|
||||
import * as passport from 'passport';
|
||||
import * as helmet from 'helmet';
|
||||
|
||||
require('./components/authentication/passportSetup'); // runs some passport initialization
|
||||
import { sessionsSetup } from './components/sessions/sessions';
|
||||
|
||||
var indexRouter = require('./routes/index');
|
||||
var usersRouter = require('./components/users/usersRoutes');
|
||||
// SYSTEM-BUILDER-router.require
|
||||
|
||||
|
||||
const debug = require('debug')('frame:app-root');
|
||||
var app = express();
|
||||
|
||||
sessionsSetup(app);
|
||||
app.use(helmet());
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
|
||||
// view engine setup
|
||||
app.set('views', path.join(__dirname, 'views'));
|
||||
app.set('view engine', 'ejs');
|
||||
|
||||
app.use(logger('dev'));
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
app.use(cookieParser());
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
|
||||
app.use('/', indexRouter);
|
||||
app.use('/api/v1/users', usersRouter);
|
||||
|
||||
// SYSTEM-BUILDER-app.use
|
||||
|
||||
|
||||
// catch 404 and forward to error handler
|
||||
app.use(function(req, res, next) {
|
||||
next(createError(404));
|
||||
});
|
||||
|
||||
// error handler
|
||||
app.use(function(err, req, res, next) {
|
||||
// set locals, only providing error in development
|
||||
res.locals.message = err.message;
|
||||
res.locals.error = req.app.get('env') === 'development' ? err : {};
|
||||
|
||||
// render the error page
|
||||
res.status(err.status || 500);
|
||||
res.render('error');
|
||||
});
|
||||
|
||||
module.exports = app;
|
95
frame/src/bin/www.ts
Normal file
95
frame/src/bin/www.ts
Normal file
@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import '../env';
|
||||
import { appReady } from '../initializeServices';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var app = require('../app');
|
||||
var debug = require('debug')('frame:server');
|
||||
var http = require('http');
|
||||
|
||||
/**
|
||||
* Get port from environment and store in Express.
|
||||
*/
|
||||
|
||||
var port = normalizePort(process.env.PORT || '3000');
|
||||
app.set('port', port);
|
||||
|
||||
/**
|
||||
* Create HTTP server.
|
||||
*/
|
||||
|
||||
var server = http.createServer(app);
|
||||
|
||||
/**
|
||||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
|
||||
appReady.then(() => {
|
||||
server.listen(port);
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
});
|
||||
|
||||
/**
|
||||
* Normalize a port into a number, string, or false.
|
||||
*/
|
||||
|
||||
function normalizePort(val) {
|
||||
var port = parseInt(val, 10);
|
||||
|
||||
if (isNaN(port)) {
|
||||
// named pipe
|
||||
return val;
|
||||
}
|
||||
|
||||
if (port >= 0) {
|
||||
// port number
|
||||
return port;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "error" event.
|
||||
*/
|
||||
|
||||
function onError(error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
var bind = typeof port === 'string'
|
||||
? 'Pipe ' + port
|
||||
: 'Port ' + port;
|
||||
|
||||
// handle specific listen errors with friendly messages
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error(bind + ' requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error(bind + ' is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "listening" event.
|
||||
*/
|
||||
|
||||
function onListening() {
|
||||
var addr = server.address();
|
||||
var bind = typeof addr === 'string'
|
||||
? 'pipe ' + addr
|
||||
: 'port ' + addr.port;
|
||||
debug('Listening on ' + bind);
|
||||
}
|
17
frame/src/components/Bergx/bergxService.ts
Normal file
17
frame/src/components/Bergx/bergxService.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import BergxSDK, { TryResponse } from 'bergx-sdk';
|
||||
import { userService } from '../users/userService';
|
||||
import { DBUser } from '../users/usersMapper';
|
||||
|
||||
const bergxService = new BergxSDK({
|
||||
clientId: process.env.BX_CLIENT_ID,
|
||||
clientSecret: process.env.BX_CLIENT_SECRET,
|
||||
updateAccessTokenCallback: (userSub: string, newAccessToken: string) => {
|
||||
// finds the user in the database and updates the accessToken
|
||||
userService.find(userSub).then((user: DBUser) => {
|
||||
user.accessToken = newAccessToken;
|
||||
userService.update(user);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export default bergxService;
|
20
frame/src/components/authentication/authenticationRoutes.ts
Normal file
20
frame/src/components/authentication/authenticationRoutes.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import * as express from 'express';
|
||||
import * as passport from 'passport';
|
||||
var router = express.Router();
|
||||
|
||||
const debug = require('debug')('frame:passportSetup');
|
||||
|
||||
router.get('/callback', [
|
||||
passport.authenticate('oauth2', { failureRedirect: '/login' }),
|
||||
(req, res, next) => {
|
||||
res.redirect('/');
|
||||
}
|
||||
]);
|
||||
|
||||
router.get('/logout', (req, res, next) => {
|
||||
req.session.destroy((err) => {
|
||||
res.redirect('/');
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = router;
|
43
frame/src/components/authentication/passportSetup.ts
Normal file
43
frame/src/components/authentication/passportSetup.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import * as passport from 'passport';
|
||||
import * as refresh from 'passport-oauth2-refresh';
|
||||
import * as OAuth2Strategy from 'passport-oauth2';
|
||||
|
||||
import { userService } from '../users/userService';
|
||||
|
||||
passport.serializeUser((user, done) => {
|
||||
done(null, user.sub);
|
||||
});
|
||||
|
||||
passport.deserializeUser((sub, done) => {
|
||||
userService.find(sub).then((user) => {
|
||||
if (typeof user !== 'undefined') {
|
||||
done(null, user);
|
||||
} else {
|
||||
done('User not found');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var strategy = new OAuth2Strategy({
|
||||
authorizationURL: process.env.AUTHORIZATION_URL,
|
||||
tokenURL: process.env.TOKEN_URL,
|
||||
clientID: process.env.CLIENT_ID,
|
||||
clientSecret: process.env.CLIENT_SECRET,
|
||||
callbackURL: process.env.CALLBACK_URL,
|
||||
state: true,
|
||||
pkce: true
|
||||
},
|
||||
function(accessToken, refreshToken, params, _, cb) {
|
||||
console.log(params);
|
||||
userService.findOrCreate(params.profile).then((user) => {
|
||||
user.refreshToken = refreshToken;
|
||||
user.accessToken = accessToken;
|
||||
return cb(null, user);
|
||||
}).catch((err) => {
|
||||
return cb(err);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
passport.use(strategy);
|
||||
refresh.use(strategy);
|
42
frame/src/components/sessions/sessions.ts
Normal file
42
frame/src/components/sessions/sessions.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import * as session from 'express-session';
|
||||
import * as mySQLSession from 'express-mysql-session';
|
||||
|
||||
const debug = require('debug')('frame:session');
|
||||
|
||||
function sessionsSetup(app) {
|
||||
// setup sessions
|
||||
let MySQLStore = mySQLSession(session);
|
||||
const DOMAIN = process.env.DOMAIN || 'localhost';
|
||||
debug(`Domain: ${DOMAIN}`);
|
||||
let mysqlSessionOptions = {
|
||||
host: process.env.DB_HOST,
|
||||
port: process.env.DB_PORT || 3306,
|
||||
user: process.env.SESSION_DB_USER,
|
||||
password: process.env.SESSION_DB_PASSWORD,
|
||||
database: process.env.SESSION_DB_NAME
|
||||
};
|
||||
let sessionStore = new MySQLStore(mysqlSessionOptions);
|
||||
let sess = {
|
||||
secret: process.env.SESSION_SECRET, // can be an array. Use an array when rolling this key
|
||||
cookie: {
|
||||
secure: false,
|
||||
domain: DOMAIN
|
||||
},
|
||||
resave: false,
|
||||
store: sessionStore,
|
||||
saveUninitialized: false
|
||||
};
|
||||
|
||||
debug(`Environment: ${app.get('env')}`);
|
||||
if (app.get('env') === 'production') {
|
||||
app.set('trust proxy', 1) // trust first proxy (usually nginx or loadbalancer)
|
||||
// sess.cookie.secure = true // serve secure cookies
|
||||
sess.cookie.secure = false // serve insecure cookies
|
||||
}
|
||||
|
||||
app.use(session(sess));
|
||||
}
|
||||
|
||||
export {
|
||||
sessionsSetup
|
||||
}
|
45
frame/src/components/users/userService.ts
Normal file
45
frame/src/components/users/userService.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { db } from '../../databases';
|
||||
import { UsersMapper, DBUser } from './usersMapper';
|
||||
|
||||
|
||||
class UserService {
|
||||
private userMapper = new UsersMapper(db);
|
||||
|
||||
public initialize() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public create(profile: DBUser) {
|
||||
return this.userMapper.createUser(profile.sub, profile.email, profile.accessToken, profile.refreshToken);
|
||||
}
|
||||
|
||||
public find(sub: string): Promise<DBUser> {
|
||||
return this.userMapper.findUserBySub(sub).then((matchingUsers) => {
|
||||
if (matchingUsers.length) {
|
||||
return matchingUsers[0];
|
||||
} else {
|
||||
throw new Error('User Not Found');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public update(profile: DBUser) {
|
||||
return this.userMapper.updateUser(profile.sub, profile.email, profile.accessToken, profile.refreshToken);
|
||||
}
|
||||
|
||||
public findOrCreate(profile: DBUser) {
|
||||
return this.find(profile.sub).then((matchingUser: DBUser) => {
|
||||
return this.update(profile);
|
||||
}).catch((err) => {
|
||||
return this.create(profile);
|
||||
});
|
||||
}
|
||||
|
||||
// SYSTEM-BUILDER-userService
|
||||
}
|
||||
|
||||
const userService = new UserService();
|
||||
|
||||
export {
|
||||
userService
|
||||
}
|
29
frame/src/components/users/usersMapper.ts
Normal file
29
frame/src/components/users/usersMapper.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { Mapper } from '../../db/Mapper';
|
||||
|
||||
class UsersMapper extends Mapper {
|
||||
|
||||
public findUserBySub(sub: string): Promise<DBUser[]> {
|
||||
return super.runQuery('SELECT * FROM Users WHERE sub = ?', sub);
|
||||
}
|
||||
|
||||
public createUser(sub: string, email: string, accessToken: string, refreshToken: string) {
|
||||
|
||||
}
|
||||
|
||||
public updateUser(sub: string, email: string, accessToken: string, refreshToken: string) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interface DBUser {
|
||||
sub: string;
|
||||
email: string;
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
}
|
||||
|
||||
export {
|
||||
UsersMapper,
|
||||
DBUser
|
||||
}
|
25
frame/src/components/users/usersRoutes.ts
Normal file
25
frame/src/components/users/usersRoutes.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import * as express from 'express';
|
||||
import * as passport from 'passport';
|
||||
import bergxService from '../Bergx/bergxService';
|
||||
|
||||
var router = express.Router();
|
||||
|
||||
const debug = require('debug')('frame:usersRoutes');
|
||||
|
||||
router.get('/profile/me', [
|
||||
passport.authenticate('oauth2'),
|
||||
(req, res, next) => {
|
||||
bergxService.getProfile(req.user).then((info) => {
|
||||
res.status(200);
|
||||
res.json(info);
|
||||
}).catch((err) => {
|
||||
res.status(500);
|
||||
res.json({
|
||||
status: 'error',
|
||||
message: err.message
|
||||
});
|
||||
});
|
||||
}
|
||||
]);
|
||||
|
||||
module.exports = router;
|
@ -0,0 +1,9 @@
|
||||
import { Mapper } from '../../db/Mapper';
|
||||
|
||||
class {{Component}}Mapper extends Mapper {
|
||||
// SYSTEM-BUILDER-{{component}}-mapper
|
||||
}
|
||||
|
||||
export {
|
||||
{{Component}}Mapper
|
||||
}
|
10
frame/src/components/{{component}}/{{component}}Routes.ts
Normal file
10
frame/src/components/{{component}}/{{component}}Routes.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import * as express from 'express';
|
||||
import * as passport from 'passport';
|
||||
|
||||
var router = express.Router();
|
||||
|
||||
const debug = require('debug')('frame:{{component}}Routes');
|
||||
|
||||
// SYSTEM-BUILDER-{{component}}-routes
|
||||
|
||||
module.exports = router;
|
18
frame/src/components/{{component}}/{{component}}Service.ts
Normal file
18
frame/src/components/{{component}}/{{component}}Service.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { db } from '../../databases';
|
||||
import { {{Component}}Mapper } from './componentMapper';
|
||||
|
||||
class {{Component}}Service {
|
||||
private {{component}}Mapper = new {{Component}}Mapper(db);
|
||||
|
||||
public initialize() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// SYSTEM-BUILDER-{{component}}-service
|
||||
}
|
||||
|
||||
const {{component}}Service = new {{Component}}Service();
|
||||
|
||||
export {
|
||||
{{component}}Service
|
||||
}
|
24
frame/src/databases.ts
Normal file
24
frame/src/databases.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { Database } from './db/db';
|
||||
import { Mapper } from './db/Mapper';
|
||||
import { Altitude, Job } from './db/migrations/Altitude';
|
||||
import jobs from './migrationJobs';
|
||||
|
||||
let db = new Database({
|
||||
host: process.env.DB_HOST,
|
||||
port: process.env.DB_PORT || '3306',
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_NAME,
|
||||
});
|
||||
let mapper = new Mapper(db);
|
||||
let altitude = new Altitude(mapper);
|
||||
|
||||
jobs.map((job) => {
|
||||
altitude.addMigration(job);
|
||||
});
|
||||
|
||||
export {
|
||||
altitude,
|
||||
db,
|
||||
mapper
|
||||
};
|
25
frame/src/db/Mapper.ts
Normal file
25
frame/src/db/Mapper.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { Database } from '../db/db';
|
||||
|
||||
class Mapper {
|
||||
constructor(public database: Database) {}
|
||||
|
||||
public runQuery(query: string, values: any): Promise<any[]> {
|
||||
let defer = new Promise<any[]>((resolve, reject) => {
|
||||
let connection = this.database.getConnection();
|
||||
connection.connect();
|
||||
connection.query(query, values, (error, results, fields) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(results);
|
||||
}
|
||||
});
|
||||
connection.end();
|
||||
});
|
||||
return defer;
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
Mapper
|
||||
};
|
23
frame/src/db/db.ts
Normal file
23
frame/src/db/db.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import * as mysql from 'mysql';
|
||||
|
||||
interface DbInfo {
|
||||
host: string;
|
||||
port: string;
|
||||
user: string;
|
||||
password: string;
|
||||
database: string;
|
||||
}
|
||||
|
||||
class Database {
|
||||
|
||||
constructor(public connectionOptions: DbInfo) {}
|
||||
|
||||
public getConnection() {
|
||||
return mysql.createConnection(this.connectionOptions);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
DbInfo,
|
||||
Database
|
||||
};
|
243
frame/src/db/migrations/Altitude.ts
Normal file
243
frame/src/db/migrations/Altitude.ts
Normal file
@ -0,0 +1,243 @@
|
||||
import { Mapper } from '../Mapper';
|
||||
|
||||
class Altitude {
|
||||
private migrations: Job[];
|
||||
private ready: Promise<any>;
|
||||
constructor(private mapper: Mapper) {
|
||||
let self = this;
|
||||
this.migrations = [];
|
||||
this.ready = new Promise((resolve, reject) => {
|
||||
this.shouldInitDB().then((shouldInit: boolean) => {
|
||||
if (shouldInit) {
|
||||
console.log(`Initializing ${this.mapper.database.connectionOptions.database}`);
|
||||
this.mapper.runQuery(`CREATE TABLE CHANGE_LOG (
|
||||
id int NOT NULL AUTO_INCREMENT,
|
||||
name VARCHAR(255),
|
||||
creator VARCHAR(255),
|
||||
UpdatedTime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id)
|
||||
);`, []).then(() => {
|
||||
console.log(`Created CHANGE_LOG table.`);
|
||||
resolve(true);
|
||||
});
|
||||
} else {
|
||||
resolve(true);
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public addMigration(newMigration: Job) {
|
||||
if (this.validateJob(newMigration)) {
|
||||
this.migrations.push(newMigration);
|
||||
} else {
|
||||
throw `The provided migration job (${newMigration.name}) is not valid.`;
|
||||
}
|
||||
}
|
||||
|
||||
public removeMigration(migrationName: string) {
|
||||
this.migrations = this.migrations.filter((migration: Job) => {
|
||||
return migration.name !== migrationName;
|
||||
});
|
||||
}
|
||||
|
||||
public runMigrationByName(jobName: string) {
|
||||
let migrationsToRun: Job[] = this.migrations.filter((job: Job) => {
|
||||
return job.name === jobName;
|
||||
});
|
||||
|
||||
return this.runMigrations(migrationsToRun);
|
||||
}
|
||||
|
||||
public runMigrations(migrationsToRun: Job[] = this.migrations) {
|
||||
let self = this;
|
||||
let defer = this.ready;
|
||||
migrationsToRun.forEach((job: Job) => {
|
||||
defer = defer.then((): Promise<any> => {
|
||||
return self.runMigration(job);
|
||||
});
|
||||
});
|
||||
return defer;
|
||||
}
|
||||
|
||||
private validateJob(job: Job) {
|
||||
let valid = true;
|
||||
if (job.preCondition) {
|
||||
valid = valid && typeof job.preCondition === 'string';
|
||||
}
|
||||
if (job.preConditionFieldName) {
|
||||
valid = valid && typeof job.preConditionFieldName === 'string';
|
||||
}
|
||||
if (job.preConditionValidation) {
|
||||
valid = valid && typeof job.preConditionValidation === 'function';
|
||||
}
|
||||
if (job.postCondition) {
|
||||
valid = valid && typeof job.postCondition === 'string';
|
||||
}
|
||||
if (job.postConditionFieldName) {
|
||||
valid = valid && typeof job.postConditionFieldName === 'string';
|
||||
}
|
||||
if (job.postConditionValidation) {
|
||||
valid = valid && typeof job.postConditionValidation === 'function';
|
||||
}
|
||||
if (job.rollback) {
|
||||
valid = valid && typeof job.rollback === 'string';
|
||||
}
|
||||
valid = valid && typeof job.name === 'string';
|
||||
valid = valid && typeof job.query === 'string';
|
||||
valid = valid && typeof job.creator === 'string';
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
private shouldInitDB() {
|
||||
return this.mapper.runQuery(`SELECT table_name FROM information_schema.tables WHERE table_schema = '${this.mapper.database.connectionOptions.database}' AND table_name = 'CHANGE_LOG';`, [])
|
||||
.then((results: any[]) => {
|
||||
return results.length === 0;
|
||||
});
|
||||
}
|
||||
|
||||
private alreadyRun(migration: Job) {
|
||||
return this.mapper.runQuery(`SELECT name FROM CHANGE_LOG WHERE name = '${migration.name}';`, [])
|
||||
.then((results: any[]) => {
|
||||
return results.length !== 0;
|
||||
});
|
||||
}
|
||||
|
||||
private runMigration(migration: Job) {
|
||||
let self = this;
|
||||
return this.alreadyRun(migration)
|
||||
.then((alreadyRun: boolean) => {
|
||||
if (alreadyRun) {
|
||||
return `Skipping migration ${migration.name} because it has already been run.`;
|
||||
} else {
|
||||
return doMigration();
|
||||
}
|
||||
});
|
||||
|
||||
function doMigration() {
|
||||
return self.runPreCondition(migration)
|
||||
.then((preConditionResult) => {
|
||||
if (preConditionResult) {
|
||||
let defer: Promise<any> = Promise.resolve();
|
||||
let queries: string[] = migration.query.split(';');
|
||||
queries = queries.filter((query) => query.length);
|
||||
queries.forEach((query: string) => {
|
||||
defer = defer.then((result) => {
|
||||
if (result) console.log(result);
|
||||
return self.mapper.runQuery(query, []);
|
||||
});
|
||||
});
|
||||
return defer;
|
||||
} else {
|
||||
throw 'PreCondition was not met.';
|
||||
}
|
||||
})
|
||||
.then((mainQueryResult) => {
|
||||
console.log(mainQueryResult);
|
||||
return self.runPostCondition(migration);
|
||||
})
|
||||
.then((postConditionResult) => {
|
||||
if (!postConditionResult) {
|
||||
return self.runRollback(migration);
|
||||
} else {
|
||||
return self.recordRun(migration)
|
||||
.then(() => {
|
||||
return 'Success';
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private recordRun(migration: Job) {
|
||||
return this.mapper.runQuery(`INSERT INTO CHANGE_LOG SET ?;`, [new ChangeLog(migration)]);
|
||||
}
|
||||
|
||||
private runPreCondition(migration: Job) {
|
||||
let defer = new Promise((resolve, reject) => {
|
||||
if (migration.preCondition) {
|
||||
this.mapper.runQuery(migration.preCondition, []).then((result) => {
|
||||
console.log(result);
|
||||
let isValid = typeof migration.preConditionValidation === 'function' ? migration.preConditionValidation(result) : result.length > 0 && result[0][migration.preConditionFieldName || 'precondition'] !== 0;
|
||||
console.log(isValid);
|
||||
resolve(isValid);
|
||||
});
|
||||
} else {
|
||||
resolve(true);
|
||||
}
|
||||
});
|
||||
|
||||
return defer;
|
||||
}
|
||||
|
||||
private runPostCondition(migration: Job) {
|
||||
let defer = new Promise((resolve, reject) => {
|
||||
if (migration.postCondition) {
|
||||
this.mapper.runQuery(migration.postCondition, []).then((result) => {
|
||||
console.log(result);
|
||||
console.log(result[0][migration.postConditionFieldName || 'postcondition'] !== 0);
|
||||
resolve(result[0][migration.postConditionFieldName || 'postcondition'] !== 0);
|
||||
});
|
||||
} else {
|
||||
resolve(true);
|
||||
}
|
||||
});
|
||||
|
||||
return defer;
|
||||
}
|
||||
|
||||
private runRollback(migration: Job) {
|
||||
let defer = new Promise((resolve, reject) => {
|
||||
if (migration.rollback) {
|
||||
this.mapper.runQuery(migration.rollback, []).then((result) => {
|
||||
resolve(result);
|
||||
}).catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
} else {
|
||||
resolve(true);
|
||||
}
|
||||
});
|
||||
|
||||
return defer;
|
||||
}
|
||||
}
|
||||
|
||||
interface ValidationFunction {
|
||||
(results: any[]): boolean;
|
||||
}
|
||||
|
||||
interface Job {
|
||||
preCondition?: string;
|
||||
preConditionFieldName?: string;
|
||||
preConditionValidation?: ValidationFunction;
|
||||
postCondition?: string;
|
||||
postConditionFieldName?: string;
|
||||
postConditionValidation?: ValidationFunction;
|
||||
rollback?: string;
|
||||
name: string;
|
||||
query: string;
|
||||
creator: string;
|
||||
}
|
||||
|
||||
class ChangeLog {
|
||||
public name: string;
|
||||
public creator: string;
|
||||
|
||||
constructor(migration: Job) {
|
||||
this.name = migration.name;
|
||||
this.creator = migration.creator;
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
Altitude,
|
||||
Job
|
||||
}
|
42
frame/src/db/migrations/README.md
Normal file
42
frame/src/db/migrations/README.md
Normal file
@ -0,0 +1,42 @@
|
||||
# Altitude
|
||||
|
||||
Altitude is a custom migration tool for updating a database with migrations. The only dependency is the MySQL library. Migrations are simple. Just create jobs for Altitude to do.
|
||||
|
||||
```Typescript
|
||||
interface Job {
|
||||
preCondition?: string;
|
||||
preConditionFieldName?: stirng;
|
||||
postCondition?: string;
|
||||
postConditionFieldName?: stirng;
|
||||
rollback?: string;
|
||||
name: string;
|
||||
query: string;
|
||||
}
|
||||
```
|
||||
|
||||
Then add the job to Altitude and tell it to run the migration.
|
||||
|
||||
```Typescript
|
||||
let altitude = new Altitude();
|
||||
|
||||
let job: Job = {
|
||||
name: 'test',
|
||||
query: 'CREATE TABLE test_table (test VARCHAR(20));'
|
||||
};
|
||||
|
||||
altitude.addMigration(job);
|
||||
|
||||
altitude.runMigrationByName('test');
|
||||
```
|
||||
|
||||
All options are optional except for `name` and `query`. `query` can have multiple queries in the string as long as each are separated with a semicolon `;`. `name` must be unique otherwise only the first migration with that name will ever be run.
|
||||
|
||||
```Typescript
|
||||
// optional properties
|
||||
|
||||
preCondition: `SELECT @@version NOT LIKE '5.0%' AND @@version NOT LIKE '5.1%' AS precondition;`, // query ran before the migration to check the current state of the database.
|
||||
preConditionFieldName: 'precondition', // if the field in the precondition that needs to be checked isn't named precondition you can specify the correct field name here.
|
||||
postCondition: `SELECT COUNT(*) as postcondition FROM StormTest.Users;` // same thing as precondition except run after the migration
|
||||
postConditionFieldName: string; // same thing as the preConditionFieldName except for the postCondition
|
||||
rollback: `DROP TABLE test_table;` // query that is run if the post condition fails.
|
||||
```
|
2
frame/src/env.ts
Normal file
2
frame/src/env.ts
Normal file
@ -0,0 +1,2 @@
|
||||
import { config } from 'dotenv';
|
||||
config({ silent: true })
|
18
frame/src/initializeServices.ts
Normal file
18
frame/src/initializeServices.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { userService } from './components/users/userService';
|
||||
|
||||
// SYSTEM-BUILDER-initialize-import
|
||||
|
||||
import { altitude } from './databases';
|
||||
|
||||
const appReady = altitude.runMigrations().then(() => {
|
||||
let servicesPromise = [
|
||||
userService.initialize(),
|
||||
|
||||
// SYSTEM-BUILDER-initialize-service
|
||||
];
|
||||
return Promise.all(servicesPromise);
|
||||
});
|
||||
|
||||
export {
|
||||
appReady
|
||||
}
|
12
frame/src/migrationJobs/index.ts
Normal file
12
frame/src/migrationJobs/index.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Job } from '../db/migrations/Altitude';
|
||||
|
||||
let jobs: Job[] = [];
|
||||
jobs.push({
|
||||
creator: 'Mason Payne',
|
||||
name: 'initializeDB',
|
||||
query: `CREATE TABLE Users (sub VARCHAR(36) NOT NULL UNIQUE, email VARCHAR(255) NOT NULL UNIQUE, accessToken VARCHAR(255), refreshToken VARCHAR(255), CreationTime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (sub));`
|
||||
});
|
||||
|
||||
// SYSTEM-BUILDER-jobs.push
|
||||
|
||||
export default jobs;
|
8
frame/src/public/stylesheets/style.css
Normal file
8
frame/src/public/stylesheets/style.css
Normal file
@ -0,0 +1,8 @@
|
||||
body {
|
||||
padding: 50px;
|
||||
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #00B7FF;
|
||||
}
|
9
frame/src/routes/index.ts
Normal file
9
frame/src/routes/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
var express = require('express');
|
||||
var router = express.Router();
|
||||
|
||||
/* GET home page. */
|
||||
router.get('/', function(req, res, next) {
|
||||
res.render('index', { title: 'Express' });
|
||||
});
|
||||
|
||||
module.exports = router;
|
3
frame/src/views/error.ejs
Normal file
3
frame/src/views/error.ejs
Normal file
@ -0,0 +1,3 @@
|
||||
<h1><%= message %></h1>
|
||||
<h2><%= error.status %></h2>
|
||||
<pre><%= error.stack %></pre>
|
11
frame/src/views/index.ejs
Normal file
11
frame/src/views/index.ejs
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title><%= title %></title>
|
||||
<link rel='stylesheet' href='/stylesheets/style.css' />
|
||||
</head>
|
||||
<body>
|
||||
<h1><%= title %></h1>
|
||||
<p>Welcome to <%= title %></p>
|
||||
</body>
|
||||
</html>
|
28
frame/tsconfig.json
Normal file
28
frame/tsconfig.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"isolatedModules": false,
|
||||
"jsx": "react",
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"declaration": false,
|
||||
"noImplicitAny": false,
|
||||
"noImplicitUseStrict": false,
|
||||
"removeComments": true,
|
||||
"noLib": false,
|
||||
"preserveConstEnums": true,
|
||||
"suppressImplicitAnyIndexErrors": true,
|
||||
"outDir": "./build",
|
||||
"rootDir": "./src/",
|
||||
"sourceMap": false
|
||||
},
|
||||
"compileOnSave": true,
|
||||
"buildOnSave": true,
|
||||
"exclue": [
|
||||
"node_modules",
|
||||
"typings/browser",
|
||||
"typings/browser.d.ts"
|
||||
]
|
||||
}
|
717
frame/yarn.lock
Normal file
717
frame/yarn.lock
Normal file
@ -0,0 +1,717 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@types/node@^14.0.13":
|
||||
version "14.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.13.tgz#ee1128e881b874c371374c1f72201893616417c9"
|
||||
integrity sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==
|
||||
|
||||
accepts@~1.3.5:
|
||||
version "1.3.7"
|
||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
|
||||
integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
|
||||
dependencies:
|
||||
mime-types "~2.1.24"
|
||||
negotiator "0.6.2"
|
||||
|
||||
array-flatten@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
||||
integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
|
||||
|
||||
base64url@3.x.x:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d"
|
||||
integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==
|
||||
|
||||
basic-auth@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a"
|
||||
integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==
|
||||
dependencies:
|
||||
safe-buffer "5.1.2"
|
||||
|
||||
bignumber.js@9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075"
|
||||
integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==
|
||||
|
||||
body-parser@1.18.3:
|
||||
version "1.18.3"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4"
|
||||
integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=
|
||||
dependencies:
|
||||
bytes "3.0.0"
|
||||
content-type "~1.0.4"
|
||||
debug "2.6.9"
|
||||
depd "~1.1.2"
|
||||
http-errors "~1.6.3"
|
||||
iconv-lite "0.4.23"
|
||||
on-finished "~2.3.0"
|
||||
qs "6.5.2"
|
||||
raw-body "2.3.3"
|
||||
type-is "~1.6.16"
|
||||
|
||||
bowser@2.9.0:
|
||||
version "2.9.0"
|
||||
resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.9.0.tgz#3bed854233b419b9a7422d9ee3e85504373821c9"
|
||||
integrity sha512-2ld76tuLBNFekRgmJfT2+3j5MIrP6bFict8WAIT3beq+srz1gcKNAdNKMqHqauQt63NmAa88HfP1/Ypa9Er3HA==
|
||||
|
||||
bytes@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
|
||||
integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
|
||||
|
||||
camelize@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b"
|
||||
integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=
|
||||
|
||||
content-disposition@0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
|
||||
integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ=
|
||||
|
||||
content-security-policy-builder@2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/content-security-policy-builder/-/content-security-policy-builder-2.1.0.tgz#0a2364d769a3d7014eec79ff7699804deb8cfcbb"
|
||||
integrity sha512-/MtLWhJVvJNkA9dVLAp6fg9LxD2gfI6R2Fi1hPmfjYXSahJJzcfvoeDOxSyp4NvxMuwWv3WMssE9o31DoULHrQ==
|
||||
|
||||
content-type@~1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
|
||||
|
||||
cookie-parser@~1.4.4:
|
||||
version "1.4.5"
|
||||
resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.5.tgz#3e572d4b7c0c80f9c61daf604e4336831b5d1d49"
|
||||
integrity sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==
|
||||
dependencies:
|
||||
cookie "0.4.0"
|
||||
cookie-signature "1.0.6"
|
||||
|
||||
cookie-signature@1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
||||
integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
|
||||
|
||||
cookie@0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
|
||||
integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=
|
||||
|
||||
cookie@0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
|
||||
integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
cors@^2.8.5:
|
||||
version "2.8.5"
|
||||
resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
|
||||
integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
|
||||
dependencies:
|
||||
object-assign "^4"
|
||||
vary "^1"
|
||||
|
||||
dasherize@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dasherize/-/dasherize-2.0.0.tgz#6d809c9cd0cf7bb8952d80fc84fa13d47ddb1308"
|
||||
integrity sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg=
|
||||
|
||||
debug@2.6.9, debug@~2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
depd@2.0.0, depd@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
|
||||
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
|
||||
|
||||
depd@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
||||
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
|
||||
|
||||
destroy@~1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
|
||||
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
|
||||
|
||||
dns-prefetch-control@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/dns-prefetch-control/-/dns-prefetch-control-0.2.0.tgz#73988161841f3dcc81f47686d539a2c702c88624"
|
||||
integrity sha512-hvSnros73+qyZXhHFjx2CMLwoj3Fe7eR9EJsFsqmcI1bB2OBWL/+0YzaEaKssCHnj/6crawNnUyw74Gm2EKe+Q==
|
||||
|
||||
dont-sniff-mimetype@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/dont-sniff-mimetype/-/dont-sniff-mimetype-1.1.0.tgz#c7d0427f8bcb095762751252af59d148b0a623b2"
|
||||
integrity sha512-ZjI4zqTaxveH2/tTlzS1wFp+7ncxNZaIEWYg3lzZRHkKf5zPT/MnEG6WL0BhHMJUabkh8GeU5NL5j+rEUCb7Ug==
|
||||
|
||||
dotenv@^8.2.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
|
||||
integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==
|
||||
|
||||
ee-first@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
|
||||
|
||||
ejs@~2.6.1:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.2.tgz#3a32c63d1cd16d11266cd4703b14fec4e74ab4f6"
|
||||
integrity sha512-PcW2a0tyTuPHz3tWyYqtK6r1fZ3gp+3Sop8Ph+ZYN81Ob5rwmbHEzaqs10N3BEsaGTkh/ooniXK+WwszGlc2+Q==
|
||||
|
||||
encodeurl@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
|
||||
|
||||
escape-html@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
|
||||
integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
|
||||
|
||||
etag@~1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
||||
|
||||
expect-ct@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/expect-ct/-/expect-ct-0.2.0.tgz#3a54741b6ed34cc7a93305c605f63cd268a54a62"
|
||||
integrity sha512-6SK3MG/Bbhm8MsgyJAylg+ucIOU71/FzyFalcfu5nY19dH8y/z0tBJU0wrNBXD4B27EoQtqPF/9wqH0iYAd04g==
|
||||
|
||||
express-mysql-session@^2.1.4:
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/express-mysql-session/-/express-mysql-session-2.1.4.tgz#fa32cb9035dbfbff57daaa6bd310f583819e1f7b"
|
||||
integrity sha512-Fcq168xVI8jtIJLhVHLJvBCvJlHnFWCcPmtt93UrWH38T2YsB919KrMCCh57/YkECkfff/L5zTQ95K1DxfOixg==
|
||||
dependencies:
|
||||
debug "4.1.1"
|
||||
express-session "1.17.0"
|
||||
mysql "2.18.1"
|
||||
underscore "1.9.2"
|
||||
|
||||
express-session@1.17.0:
|
||||
version "1.17.0"
|
||||
resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.17.0.tgz#9b50dbb5e8a03c3537368138f072736150b7f9b3"
|
||||
integrity sha512-t4oX2z7uoSqATbMfsxWMbNjAL0T5zpvcJCk3Z9wnPPN7ibddhnmDZXHfEcoBMG2ojKXZoCyPMc5FbtK+G7SoDg==
|
||||
dependencies:
|
||||
cookie "0.4.0"
|
||||
cookie-signature "1.0.6"
|
||||
debug "2.6.9"
|
||||
depd "~2.0.0"
|
||||
on-headers "~1.0.2"
|
||||
parseurl "~1.3.3"
|
||||
safe-buffer "5.2.0"
|
||||
uid-safe "~2.1.5"
|
||||
|
||||
express-session@^1.17.1:
|
||||
version "1.17.1"
|
||||
resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.17.1.tgz#36ecbc7034566d38c8509885c044d461c11bf357"
|
||||
integrity sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==
|
||||
dependencies:
|
||||
cookie "0.4.0"
|
||||
cookie-signature "1.0.6"
|
||||
debug "2.6.9"
|
||||
depd "~2.0.0"
|
||||
on-headers "~1.0.2"
|
||||
parseurl "~1.3.3"
|
||||
safe-buffer "5.2.0"
|
||||
uid-safe "~2.1.5"
|
||||
|
||||
express@~4.16.1:
|
||||
version "4.16.4"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e"
|
||||
integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==
|
||||
dependencies:
|
||||
accepts "~1.3.5"
|
||||
array-flatten "1.1.1"
|
||||
body-parser "1.18.3"
|
||||
content-disposition "0.5.2"
|
||||
content-type "~1.0.4"
|
||||
cookie "0.3.1"
|
||||
cookie-signature "1.0.6"
|
||||
debug "2.6.9"
|
||||
depd "~1.1.2"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
finalhandler "1.1.1"
|
||||
fresh "0.5.2"
|
||||
merge-descriptors "1.0.1"
|
||||
methods "~1.1.2"
|
||||
on-finished "~2.3.0"
|
||||
parseurl "~1.3.2"
|
||||
path-to-regexp "0.1.7"
|
||||
proxy-addr "~2.0.4"
|
||||
qs "6.5.2"
|
||||
range-parser "~1.2.0"
|
||||
safe-buffer "5.1.2"
|
||||
send "0.16.2"
|
||||
serve-static "1.13.2"
|
||||
setprototypeof "1.1.0"
|
||||
statuses "~1.4.0"
|
||||
type-is "~1.6.16"
|
||||
utils-merge "1.0.1"
|
||||
vary "~1.1.2"
|
||||
|
||||
feature-policy@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/feature-policy/-/feature-policy-0.3.0.tgz#7430e8e54a40da01156ca30aaec1a381ce536069"
|
||||
integrity sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ==
|
||||
|
||||
finalhandler@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
|
||||
integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
on-finished "~2.3.0"
|
||||
parseurl "~1.3.2"
|
||||
statuses "~1.4.0"
|
||||
unpipe "~1.0.0"
|
||||
|
||||
forwarded@~0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
|
||||
integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
|
||||
|
||||
frameguard@3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/frameguard/-/frameguard-3.1.0.tgz#bd1442cca1d67dc346a6751559b6d04502103a22"
|
||||
integrity sha512-TxgSKM+7LTA6sidjOiSZK9wxY0ffMPY3Wta//MqwmX0nZuEHc8QrkV8Fh3ZhMJeiH+Uyh/tcaarImRy8u77O7g==
|
||||
|
||||
fresh@0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||
integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
|
||||
|
||||
helmet-crossdomain@0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz#5f1fe5a836d0325f1da0a78eaa5fd8429078894e"
|
||||
integrity sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA==
|
||||
|
||||
helmet-csp@2.10.0:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/helmet-csp/-/helmet-csp-2.10.0.tgz#685dde1747bc16c5e28ad9d91e229a69f0a85e84"
|
||||
integrity sha512-Rz953ZNEFk8sT2XvewXkYN0Ho4GEZdjAZy4stjiEQV3eN7GDxg1QKmYggH7otDyIA7uGA6XnUMVSgeJwbR5X+w==
|
||||
dependencies:
|
||||
bowser "2.9.0"
|
||||
camelize "1.0.0"
|
||||
content-security-policy-builder "2.1.0"
|
||||
dasherize "2.0.0"
|
||||
|
||||
helmet@^3.23.0:
|
||||
version "3.23.0"
|
||||
resolved "https://registry.yarnpkg.com/helmet/-/helmet-3.23.0.tgz#b9377e96f8f9b8e42ff902238af28fa44b4b91bd"
|
||||
integrity sha512-/AKPymGd+mJsFN43IkX+nf8J11V51bxLNYReQZmWrVx7M/FEOs2OEE6U1YIt8Y00rpOupbIeVWv5woEGja1Pug==
|
||||
dependencies:
|
||||
depd "2.0.0"
|
||||
dns-prefetch-control "0.2.0"
|
||||
dont-sniff-mimetype "1.1.0"
|
||||
expect-ct "0.2.0"
|
||||
feature-policy "0.3.0"
|
||||
frameguard "3.1.0"
|
||||
helmet-crossdomain "0.4.0"
|
||||
helmet-csp "2.10.0"
|
||||
hide-powered-by "1.1.0"
|
||||
hpkp "2.0.0"
|
||||
hsts "2.2.0"
|
||||
ienoopen "1.1.0"
|
||||
nocache "2.1.0"
|
||||
referrer-policy "1.2.0"
|
||||
x-xss-protection "1.3.0"
|
||||
|
||||
hide-powered-by@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/hide-powered-by/-/hide-powered-by-1.1.0.tgz#be3ea9cab4bdb16f8744be873755ca663383fa7a"
|
||||
integrity sha512-Io1zA2yOA1YJslkr+AJlWSf2yWFkKjvkcL9Ni1XSUqnGLr/qRQe2UI3Cn/J9MsJht7yEVCe0SscY1HgVMujbgg==
|
||||
|
||||
hpkp@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/hpkp/-/hpkp-2.0.0.tgz#10e142264e76215a5d30c44ec43de64dee6d1672"
|
||||
integrity sha1-EOFCJk52IVpdMMROxD3mTe5tFnI=
|
||||
|
||||
hsts@2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/hsts/-/hsts-2.2.0.tgz#09119d42f7a8587035d027dda4522366fe75d964"
|
||||
integrity sha512-ToaTnQ2TbJkochoVcdXYm4HOCliNozlviNsg+X2XQLQvZNI/kCHR9rZxVYpJB3UPcHz80PgxRyWQ7PdU1r+VBQ==
|
||||
dependencies:
|
||||
depd "2.0.0"
|
||||
|
||||
http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3:
|
||||
version "1.6.3"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
|
||||
integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=
|
||||
dependencies:
|
||||
depd "~1.1.2"
|
||||
inherits "2.0.3"
|
||||
setprototypeof "1.1.0"
|
||||
statuses ">= 1.4.0 < 2"
|
||||
|
||||
iconv-lite@0.4.23:
|
||||
version "0.4.23"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
|
||||
integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==
|
||||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3"
|
||||
|
||||
ienoopen@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ienoopen/-/ienoopen-1.1.0.tgz#411e5d530c982287dbdc3bb31e7a9c9e32630974"
|
||||
integrity sha512-MFs36e/ca6ohEKtinTJ5VvAJ6oDRAYFdYXweUnGY9L9vcoqFOU4n2ZhmJ0C4z/cwGZ3YIQRSB3XZ1+ghZkY5NQ==
|
||||
|
||||
inherits@2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
||||
|
||||
inherits@~2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
||||
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
|
||||
|
||||
isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
||||
media-typer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
|
||||
|
||||
merge-descriptors@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||
integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
|
||||
|
||||
methods@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
|
||||
|
||||
mime-db@1.44.0:
|
||||
version "1.44.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92"
|
||||
integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==
|
||||
|
||||
mime-types@~2.1.24:
|
||||
version "2.1.27"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f"
|
||||
integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==
|
||||
dependencies:
|
||||
mime-db "1.44.0"
|
||||
|
||||
mime@1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
|
||||
integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==
|
||||
|
||||
morgan@~1.9.1:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.9.1.tgz#0a8d16734a1d9afbc824b99df87e738e58e2da59"
|
||||
integrity sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==
|
||||
dependencies:
|
||||
basic-auth "~2.0.0"
|
||||
debug "2.6.9"
|
||||
depd "~1.1.2"
|
||||
on-finished "~2.3.0"
|
||||
on-headers "~1.0.1"
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
||||
|
||||
ms@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
mysql@2.18.1:
|
||||
version "2.18.1"
|
||||
resolved "https://registry.yarnpkg.com/mysql/-/mysql-2.18.1.tgz#2254143855c5a8c73825e4522baf2ea021766717"
|
||||
integrity sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==
|
||||
dependencies:
|
||||
bignumber.js "9.0.0"
|
||||
readable-stream "2.3.7"
|
||||
safe-buffer "5.1.2"
|
||||
sqlstring "2.3.1"
|
||||
|
||||
negotiator@0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
||||
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
|
||||
|
||||
nocache@2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/nocache/-/nocache-2.1.0.tgz#120c9ffec43b5729b1d5de88cd71aa75a0ba491f"
|
||||
integrity sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==
|
||||
|
||||
oauth@0.9.x:
|
||||
version "0.9.15"
|
||||
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
|
||||
integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=
|
||||
|
||||
object-assign@^4:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
on-finished@~2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
|
||||
integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
|
||||
dependencies:
|
||||
ee-first "1.1.1"
|
||||
|
||||
on-headers@~1.0.1, on-headers@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
|
||||
integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
|
||||
|
||||
parseurl@~1.3.2, parseurl@~1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
|
||||
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
|
||||
|
||||
passport-oauth2-refresh@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-oauth2-refresh/-/passport-oauth2-refresh-2.0.0.tgz#7b19c77ff3cc000819c69f6ad9e318450f57b85e"
|
||||
integrity sha512-yXvCB6nem/O+WThhiyI3TlPXpzSGY+9+hy9OTx9QF8e9GInplyRHxHaaOhFylKvnof9UmWHAufQFZk8cO1Fb2g==
|
||||
|
||||
passport-oauth2@^1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.5.0.tgz#64babbb54ac46a4dcab35e7f266ed5294e3c4108"
|
||||
integrity sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ==
|
||||
dependencies:
|
||||
base64url "3.x.x"
|
||||
oauth "0.9.x"
|
||||
passport-strategy "1.x.x"
|
||||
uid2 "0.0.x"
|
||||
utils-merge "1.x.x"
|
||||
|
||||
passport-strategy@1.x.x:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
|
||||
integrity sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=
|
||||
|
||||
passport@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270"
|
||||
integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==
|
||||
dependencies:
|
||||
passport-strategy "1.x.x"
|
||||
pause "0.0.1"
|
||||
|
||||
path-to-regexp@0.1.7:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||
integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
|
||||
|
||||
pause@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d"
|
||||
integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||
|
||||
proxy-addr@~2.0.4:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
|
||||
integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==
|
||||
dependencies:
|
||||
forwarded "~0.1.2"
|
||||
ipaddr.js "1.9.1"
|
||||
|
||||
qs@6.5.2:
|
||||
version "6.5.2"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
|
||||
|
||||
random-bytes@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b"
|
||||
integrity sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=
|
||||
|
||||
range-parser@~1.2.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
||||
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
|
||||
|
||||
raw-body@2.3.3:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3"
|
||||
integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==
|
||||
dependencies:
|
||||
bytes "3.0.0"
|
||||
http-errors "1.6.3"
|
||||
iconv-lite "0.4.23"
|
||||
unpipe "1.0.0"
|
||||
|
||||
readable-stream@2.3.7:
|
||||
version "2.3.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.3"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~2.0.0"
|
||||
safe-buffer "~5.1.1"
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
referrer-policy@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/referrer-policy/-/referrer-policy-1.2.0.tgz#b99cfb8b57090dc454895ef897a4cc35ef67a98e"
|
||||
integrity sha512-LgQJIuS6nAy1Jd88DCQRemyE3mS+ispwlqMk3b0yjZ257fI1v9c+/p6SD5gP5FGyXUIgrNOAfmyioHwZtYv2VA==
|
||||
|
||||
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
||||
safe-buffer@5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
|
||||
integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
|
||||
|
||||
"safer-buffer@>= 2.1.2 < 3":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
send@0.16.2:
|
||||
version "0.16.2"
|
||||
resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
|
||||
integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
depd "~1.1.2"
|
||||
destroy "~1.0.4"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
fresh "0.5.2"
|
||||
http-errors "~1.6.2"
|
||||
mime "1.4.1"
|
||||
ms "2.0.0"
|
||||
on-finished "~2.3.0"
|
||||
range-parser "~1.2.0"
|
||||
statuses "~1.4.0"
|
||||
|
||||
serve-static@1.13.2:
|
||||
version "1.13.2"
|
||||
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1"
|
||||
integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==
|
||||
dependencies:
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
parseurl "~1.3.2"
|
||||
send "0.16.2"
|
||||
|
||||
setprototypeof@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
|
||||
integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
|
||||
|
||||
sqlstring@2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.1.tgz#475393ff9e91479aea62dcaf0ca3d14983a7fb40"
|
||||
integrity sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=
|
||||
|
||||
"statuses@>= 1.4.0 < 2":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
|
||||
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
|
||||
|
||||
statuses@~1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
|
||||
integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
type-is@~1.6.16:
|
||||
version "1.6.18"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
|
||||
dependencies:
|
||||
media-typer "0.3.0"
|
||||
mime-types "~2.1.24"
|
||||
|
||||
uid-safe@~2.1.5:
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a"
|
||||
integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==
|
||||
dependencies:
|
||||
random-bytes "~1.0.0"
|
||||
|
||||
uid2@0.0.x:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82"
|
||||
integrity sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=
|
||||
|
||||
underscore@1.9.2:
|
||||
version "1.9.2"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.2.tgz#0c8d6f536d6f378a5af264a72f7bec50feb7cf2f"
|
||||
integrity sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ==
|
||||
|
||||
unpipe@1.0.0, unpipe@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||
integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
|
||||
|
||||
util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
|
||||
utils-merge@1.0.1, utils-merge@1.x.x:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
||||
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
|
||||
|
||||
vary@^1, vary@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
|
||||
|
||||
x-xss-protection@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/x-xss-protection/-/x-xss-protection-1.3.0.tgz#3e3a8dd638da80421b0e9fff11a2dbe168f6d52c"
|
||||
integrity sha512-kpyBI9TlVipZO4diReZMAHWtS0MMa/7Kgx8hwG/EuZLiA6sg4Ah/4TRdASHhRRN3boobzcYgFRUFSgHRge6Qhg==
|
Reference in New Issue
Block a user