Type models
authorChocobozzz <florian.bigard@gmail.com>
Mon, 22 May 2017 18:58:25 +0000 (20:58 +0200)
committerChocobozzz <florian.bigard@gmail.com>
Thu, 25 May 2017 15:32:16 +0000 (17:32 +0200)
76 files changed:
package.json
server.ts
server/controllers/api/clients.ts
server/controllers/api/config.ts
server/controllers/api/pods.ts
server/controllers/api/remote/pods.ts
server/controllers/api/remote/videos.ts
server/controllers/api/users.ts
server/controllers/api/videos/abuse.ts
server/controllers/api/videos/blacklist.ts
server/controllers/api/videos/index.ts
server/controllers/api/videos/rate.ts
server/controllers/client.ts
server/helpers/database-utils.ts
server/helpers/logger.ts
server/helpers/utils.ts
server/initializers/checker.ts
server/initializers/constants.ts
server/initializers/database.ts
server/initializers/installer.ts
server/initializers/migrator.ts
server/lib/friends.ts
server/lib/jobs/handlers/video-transcoder.ts
server/lib/jobs/job-scheduler.ts
server/lib/oauth-model.ts
server/lib/request/base-request-scheduler.ts
server/lib/request/request-scheduler.ts
server/lib/request/request-video-event-scheduler.ts
server/lib/request/request-video-qadu-scheduler.ts
server/middlewares/admin.ts
server/middlewares/oauth.ts
server/middlewares/pagination.ts
server/middlewares/pods.ts
server/middlewares/secure.ts
server/middlewares/validators/pods.ts
server/middlewares/validators/users.ts
server/middlewares/validators/videos.ts
server/models/application-interface.ts [new file with mode: 0644]
server/models/application.ts
server/models/author-interface.ts [new file with mode: 0644]
server/models/author.ts
server/models/index.ts [new file with mode: 0644]
server/models/job-interface.ts [new file with mode: 0644]
server/models/job.ts
server/models/oauth-client-interface.ts [new file with mode: 0644]
server/models/oauth-client.ts
server/models/oauth-token-interface.ts [new file with mode: 0644]
server/models/oauth-token.ts
server/models/pod-interface.ts [new file with mode: 0644]
server/models/pod.ts
server/models/request-interface.ts [new file with mode: 0644]
server/models/request-to-pod-interface.ts [new file with mode: 0644]
server/models/request-to-pod.ts
server/models/request-video-event-interface.ts [new file with mode: 0644]
server/models/request-video-event.ts
server/models/request-video-qadu-interface.ts [new file with mode: 0644]
server/models/request-video-qadu.ts
server/models/request.ts
server/models/tag-interface.ts [new file with mode: 0644]
server/models/tag.ts
server/models/user-interface.ts [new file with mode: 0644]
server/models/user-video-rate-interface.ts [new file with mode: 0644]
server/models/user-video-rate.ts
server/models/user.ts
server/models/utils.ts
server/models/video-abuse-interface.ts [new file with mode: 0644]
server/models/video-abuse.ts
server/models/video-blacklist-interface.ts [new file with mode: 0644]
server/models/video-blacklist.ts
server/models/video-interface.ts [new file with mode: 0644]
server/models/video-tag-interface.ts [new file with mode: 0644]
server/models/video-tag.ts
server/models/video.ts
server/tests/api/video-transcoder.js
server/tests/utils/servers.js
yarn.lock

index 00d0bb5ee2303a48bdbdac5b623e111617e6768f..118a0aef6452d64307e9d8a60040b83fb8a73e8b 100644 (file)
@@ -69,7 +69,7 @@
     "rimraf": "^2.5.4",
     "safe-buffer": "^5.0.1",
     "scripty": "^1.5.0",
-    "sequelize": "^3.27.0",
+    "sequelize": "4.0.0-2",
     "typescript": "~2.2.0",
     "winston": "^2.1.1",
     "ws": "^2.0.0"
     "@types/morgan": "^1.7.32",
     "@types/node": "^7.0.18",
     "@types/request": "^0.0.43",
-    "@types/sequelize": "3",
+    "@types/sequelize": "^4.0.55",
     "@types/winston": "^2.3.2",
     "@types/ws": "^0.0.41",
     "chai": "^3.3.0",
     "commander": "^2.9.0",
     "mocha": "^3.0.1",
+    "source-map-support": "^0.4.15",
     "standard": "^10.0.0",
     "supertest": "^3.0.0",
     "tslint": "^5.2.0",
index 119c0c61df17a516612dd271b2e04b17f3dc0a36..f5413b8e33fd7c5ce1ddf9e2f4cf4e776fc3decd 100644 (file)
--- a/server.ts
+++ b/server.ts
@@ -1,3 +1,7 @@
+if ([ 'dev', 'test'].indexOf(process.env.NODE_ENV) !== -1) {
+  require('source-map-support').install()
+}
+
 // ----------- Node modules -----------
 import bodyParser = require('body-parser')
 import express = require('express')
@@ -20,8 +24,8 @@ const app = express()
 import { logger } from './server/helpers/logger'
 import { API_VERSION, CONFIG } from './server/initializers/constants'
 // Initialize database and models
-const db = require('./server/initializers/database')
-db.init(onDatabaseInitDone)
+import { database as db } from './server/initializers/database'
+db.init(false, onDatabaseInitDone)
 
 // ----------- Checker -----------
 import { checkMissedConfig, checkFFmpeg, checkConfig } from './server/initializers/checker'
@@ -52,7 +56,9 @@ import { apiRouter, clientsRouter, staticRouter } from './server/controllers'
 // ----------- App -----------
 
 // For the logger
-// app.use(morgan('combined', { stream: logger.stream }))
+app.use(morgan('combined', {
+  stream: { write: logger.info }
+}))
 // For body requests
 app.use(bodyParser.json({ limit: '500kb' }))
 app.use(bodyParser.urlencoded({ extended: false }))
@@ -75,7 +81,7 @@ app.use('/', staticRouter)
 
 // Always serve index client page (the client is a single page application, let it handle routing)
 app.use('/*', function (req, res, next) {
-  res.sendFile(path.join(__dirname, './client/dist/index.html'))
+  res.sendFile(path.join(__dirname, '../client/dist/index.html'))
 })
 
 // ----------- Tracker -----------
index 902f62995d5bbcf688563c73ce09c36b782ff521..614163c8371c3ba99cf11ef3521b539b7a6b3798 100644 (file)
@@ -2,7 +2,7 @@ import express = require('express')
 
 import { CONFIG } from '../../initializers';
 import { logger } from '../../helpers'
-const db = require('../../initializers/database')
+import { database as db } from '../../initializers/database'
 
 const clientsRouter = express.Router()
 
index 8f3fa24736ab02bf65d0e77741bc5653c015f559..8bdde61b38f08ab9276f957c15d062f51fba6329 100644 (file)
@@ -1,6 +1,6 @@
 import express = require('express')
 
-import { CONFIG } from '../../initializers';
+import { CONFIG } from '../../initializers'
 
 const configRouter = express.Router()
 
index 06dfd829519962aa639655bee32f28db9a6c3202..4ff1f5d9fa6dd8b237d493f3dfa8fa2b2c663425 100644 (file)
@@ -1,7 +1,7 @@
 import express = require('express')
 import { waterfall } from 'async'
 
-const db = require('../../initializers/database')
+import { database as db } from '../../initializers/database'
 import { CONFIG } from '../../initializers'
 import {
   logger,
@@ -35,12 +35,12 @@ podsRouter.post('/makefriends',
   ensureIsAdmin,
   makeFriendsValidator,
   setBodyHostsPort,
-  makeFriends
+  makeFriendsController
 )
 podsRouter.get('/quitfriends',
   authenticate,
   ensureIsAdmin,
-  quitFriends
+  quitFriendsController
 )
 
 // ---------------------------------------------------------------------------
index 85ef7bb42c03d5c64116e4de86ad660eea46d61e..7a9a0c4f06552273e96699584609e1f81ca8edee 100644 (file)
@@ -1,7 +1,7 @@
 import express = require('express')
-import { waterfall } from 'async/waterfall'
+import * as waterfall from 'async/waterfall'
 
-const db = require('../../../initializers/database')
+import { database as db } from '../../../initializers/database'
 import { checkSignature, signatureValidator } from '../../../middlewares'
 
 const remotePodsRouter = express.Router()
index df4ba8309f04561f6dd35ad04bf787decdb56259..178a21e7c56bbb0e1738f0bd3c59b5dccb4ba010 100644 (file)
@@ -1,7 +1,7 @@
 import express = require('express')
 import { eachSeries, waterfall } from 'async'
 
-const db = require('../../../initializers/database')
+import { database as db } from '../../../initializers/database'
 import {
   REQUEST_ENDPOINT_ACTIONS,
   REQUEST_ENDPOINTS,
index 981a4706a171c5ef18cb9e5269bdadb7738f4b65..97a744f54391c56c9c7f77ee6b97c666d44f54bb 100644 (file)
@@ -1,7 +1,7 @@
 import express = require('express')
 import { waterfall } from 'async'
 
-const db = require('../../initializers/database')
+import { database as db } from '../../initializers/database'
 import { CONFIG, USER_ROLES } from '../../initializers'
 import { logger, getFormatedObjects } from '../../helpers'
 import {
@@ -114,7 +114,7 @@ function getUserVideoRating (req, res, next) {
   const videoId = req.params.videoId
   const userId = res.locals.oauth.token.User.id
 
-  db.UserVideoRate.load(userId, videoId, function (err, ratingObj) {
+  db.UserVideoRate.load(userId, videoId, null, function (err, ratingObj) {
     if (err) return next(err)
 
     const rating = ratingObj ? ratingObj.type : 'none'
index 88204120fb4a42ce8cb3185e23e687c5713682cf..3dd884354a7ff9940d6b999b4416ba182d8532ab 100644 (file)
@@ -1,7 +1,7 @@
 import express = require('express')
 import { waterfall } from 'async'
 
-const db = require('../../../initializers/database')
+import { database as db } from '../../../initializers/database'
 import friends = require('../../../lib/friends')
 import {
   logger,
index db6d95e73d907af47f512f1012d44c75ba62fd33..fb4d57d7ba6077b200d32b52104298997b4d00e1 100644 (file)
@@ -1,6 +1,6 @@
 import express = require('express')
 
-const db = require('../../../initializers/database')
+import { database as db } from '../../../initializers/database'
 import { logger } from '../../../helpers'
 import {
   authenticate,
index 5fbf03676ff4ebcf0b74d4e97e34b7ac9ba29653..6eda7159bb26cfe44bb624f83d6e88cb022e4f6c 100644 (file)
@@ -4,7 +4,7 @@ import multer = require('multer')
 import path = require('path')
 import { waterfall } from 'async'
 
-const db = require('../../../initializers/database')
+import { database as db } from '../../../initializers/database'
 import {
   CONFIG,
   REQUEST_VIDEO_QADU_TYPES,
index 21053792a42197f43268fefb9f2ff8b92f64464c..571ff68e3ffb0c254c1113cde697f15ff1fad9a9 100644 (file)
@@ -1,7 +1,7 @@
 import express = require('express')
 import { waterfall } from 'async'
 
-const db = require('../../../initializers/database')
+import { database as db } from '../../../initializers/database'
 import {
   logger,
   retryTransactionWrapper,
index aaa04889a1fca94ff7540268d8ef934f8e28ca27..ce5608c9b7145e5f78d58a82424c6f9842b13f83 100644 (file)
@@ -6,20 +6,21 @@ import expressValidator = require('express-validator')
 // TODO: use .validator when express-validator typing will have validator field
 const validator = expressValidator['validator']
 
-const db = require('../initializers/database')
+import { database as db } from '../initializers/database'
 import {
   CONFIG,
   REMOTE_SCHEME,
   STATIC_PATHS,
   STATIC_MAX_AGE
 } from '../initializers'
+import { root } from '../helpers'
 
 const clientsRouter = express.Router()
 
 // TODO: move to constants
 const opengraphComment = '<!-- opengraph tags -->'
-const distPath = join(__dirname, '..', '..', 'client/dist')
-const embedPath = join(distPath, 'standalone/videos/embed.html')
+const distPath = join(root(), 'client', 'dist')
+const embedPath = join(distPath, 'standalone', 'videos', 'embed.html')
 const indexPath = join(distPath, 'index.html')
 
 // Special route that add OpenGraph tags
index b842ab9ece3d5eed0085cf2a426c67d7644c00ac..7d6ce4ec894cd1040ae2346016476bbac1f756e3 100644 (file)
@@ -1,7 +1,7 @@
 // TODO: import from ES6 when retry typing file will include errorFilter function
 import retry = require('async/retry')
 
-const db = require('../initializers/database')
+import { database as db } from '../initializers/database'
 import { logger } from './logger'
 
 function commitTransaction (t, callback) {
@@ -52,7 +52,7 @@ function transactionRetryer (func, callback) {
 }
 
 function startSerializableTransaction (callback) {
-  db.sequelize.transaction({ isolationLevel: 'SERIALIZABLE' }).asCallback(function (err, t) {
+  db.sequelize.transaction(/* { isolationLevel: 'SERIALIZABLE' } */).asCallback(function (err, t) {
     // We force to return only two parameters
     return callback(err, t)
   })
index 3c35e41e066952622d820e0f3b66170edd7c29a4..7c99db55fac3509a8bf531e01f83e528677f2f88 100644 (file)
@@ -36,13 +36,6 @@ const logger = new winston.Logger({
   exitOnError: true
 })
 
-// TODO: useful?
-// logger.stream = {
-//   write: function (message) {
-//     logger.info(message)
-//   }
-// }
-
 // ---------------------------------------------------------------------------
 
 export { logger }
index 09c35a5335ba07f7a7e94937564a0c99e0fdca0f..bc76cfb267fabe92fd22b08c2e4cf007b04f0ed1 100644 (file)
@@ -1,4 +1,5 @@
 import { pseudoRandomBytes } from 'crypto'
+import { join } from 'path'
 
 import { logger } from './logger'
 
@@ -42,6 +43,11 @@ function getFormatedObjects (objects, objectsTotal) {
   }
 }
 
+function root () {
+  // We are in /dist/helpers/utils.js
+  return join(__dirname, '..', '..', '..')
+}
+
 // ---------------------------------------------------------------------------
 
 export {
@@ -50,5 +56,6 @@ export {
   cleanForExit,
   generateRandomString,
   isTestInstance,
-  getFormatedObjects
+  getFormatedObjects,
+  root
 }
index 370dff2d407ae72674136a9c4e6af679ef5945b8..0ee01b0e3720e1e153c2910fa19efb6ecb520b4e 100644 (file)
@@ -1,6 +1,6 @@
 import config = require('config')
 
-const db = require('./database')
+import { database as db } from './database'
 import { CONFIG } from './constants'
 
 // Some checks on configuration files
index 6bdc261ad7040a47ae79bea99acccf4c86002ace..1072d0de0bf341cda6904b342935383e4f2bcbbb 100644 (file)
@@ -1,6 +1,9 @@
 import config = require('config')
 import { join } from 'path'
 
+// Do not use barrels, remain constants as independent as possible
+import { root, isTestInstance } from '../helpers/utils'
+
 // ---------------------------------------------------------------------------
 
 const LAST_MIGRATION_VERSION = 50
@@ -44,12 +47,12 @@ const CONFIG = {
     PASSWORD: config.get<string>('database.password')
   },
   STORAGE: {
-    CERT_DIR: join(__dirname, '..', '..', config.get<string>('storage.certs')),
-    LOG_DIR: join(__dirname, '..', '..', config.get<string>('storage.logs')),
-    VIDEOS_DIR: join(__dirname, '..', '..', config.get<string>('storage.videos')),
-    THUMBNAILS_DIR: join(__dirname, '..', '..', config.get<string>('storage.thumbnails')),
-    PREVIEWS_DIR: join(__dirname, '..', '..', config.get<string>('storage.previews')),
-    TORRENTS_DIR: join(__dirname, '..', '..', config.get<string>('storage.torrents'))
+    CERT_DIR: join(root(), config.get<string>('storage.certs')),
+    LOG_DIR: join(root(), config.get<string>('storage.logs')),
+    VIDEOS_DIR: join(root(), config.get<string>('storage.videos')),
+    THUMBNAILS_DIR: join(root(), config.get<string>('storage.thumbnails')),
+    PREVIEWS_DIR: join(root(), config.get<string>('storage.previews')),
+    TORRENTS_DIR: join(root(), config.get<string>('storage.torrents'))
   },
   WEBSERVER: {
     SCHEME: config.get<boolean>('webserver.https') === true ? 'https' : 'http',
@@ -334,10 +337,3 @@ export {
   VIDEO_LICENCES,
   VIDEO_RATE_TYPES
 }
-
-// ---------------------------------------------------------------------------
-
-// This method exists in utils module but we want to let the constants module independent
-function isTestInstance () {
-  return (process.env.NODE_ENV === 'test')
-}
index 753a06669a107b131952c2763ef2c1c722f5a6fb..c89a8b23c70780eec2384d13648021d0db0de5bc 100644 (file)
@@ -6,12 +6,52 @@ import { CONFIG } from './constants'
 // Do not use barrel, we need to load database first
 import { logger } from '../helpers/logger'
 import { isTestInstance } from '../helpers/utils'
+import {
+  ApplicationModel,
+  AuthorModel,
+  JobModel,
+  OAuthClientModel,
+  OAuthTokenModel,
+  PodModel,
+  RequestModel,
+  RequestToPodModel,
+  RequestVideoEventModel,
+  RequestVideoQaduModel,
+  TagModel,
+  UserModel,
+  UserVideoRateModel,
+  VideoAbuseModel,
+  BlacklistedVideoModel,
+  VideoTagModel,
+  VideoModel
+} from '../models'
 
 const dbname = CONFIG.DATABASE.DBNAME
 const username = CONFIG.DATABASE.USERNAME
 const password = CONFIG.DATABASE.PASSWORD
 
-const database: any = {}
+const database: {
+  sequelize?: Sequelize.Sequelize,
+  init?: (silent: any, callback: any) => void,
+
+  Application?: ApplicationModel,
+  Author?: AuthorModel,
+  Job?: JobModel,
+  OAuthClient?: OAuthClientModel,
+  OAuthToken?: OAuthTokenModel,
+  Pod?: PodModel,
+  RequestToPod?: RequestToPodModel,
+  RequestVideoEvent?: RequestVideoEventModel,
+  RequestVideoQadu?: RequestVideoQaduModel,
+  Request?: RequestModel,
+  Tag?: TagModel,
+  UserVideoRate?: UserVideoRateModel,
+  User?: UserModel,
+  VideoAbuse?: VideoAbuseModel,
+  BlacklistedVideo?: BlacklistedVideoModel,
+  VideoTag?: VideoTagModel,
+  Video?: VideoModel
+} = {}
 
 const sequelize = new Sequelize(dbname, username, password, {
   dialect: 'postgres',
@@ -32,12 +72,6 @@ const sequelize = new Sequelize(dbname, username, password, {
 database.sequelize = sequelize
 
 database.init = function (silent, callback) {
-  if (!callback) {
-    callback = silent
-    silent = false
-  }
-
-  if (!callback) callback = function () { /* empty */ }
 
   const modelDirectory = join(__dirname, '..', 'models')
   fs.readdir(modelDirectory, function (err, files) {
@@ -45,7 +79,12 @@ database.init = function (silent, callback) {
 
     files.filter(function (file) {
       // For all models but not utils.js
-      if (file === 'utils.js') return false
+      if (
+        file === 'index.js' ||
+        file === 'utils.js' ||
+        file.endsWith('-interface.js') ||
+        file.endsWith('.js.map')
+      ) return false
 
       return true
     })
@@ -69,4 +108,6 @@ database.init = function (silent, callback) {
 
 // ---------------------------------------------------------------------------
 
-module.exports = database
+export {
+  database
+}
index cd1404d48ded2383b2153b21a7a27741a6411a2a..46716410718a69519ccbd1bad36f89156b920189 100644 (file)
@@ -4,10 +4,10 @@ import { each, series } from 'async'
 import mkdirp = require('mkdirp')
 import passwordGenerator = require('password-generator')
 
-const db = require('./database')
+import { database as db } from './database'
 import { USER_ROLES, CONFIG, LAST_MIGRATION_VERSION } from './constants'
 import { clientsExist, usersExist } from './checker'
-import { logger, createCertsIfNotExist } from '../helpers'
+import { logger, createCertsIfNotExist, root } from '../helpers'
 
 function installApplication (callback) {
   series([
@@ -47,7 +47,7 @@ function createDirectoriesIfNotExist (callback) {
 
   each(Object.keys(storages), function (key, callbackEach) {
     const dir = storages[key]
-    mkdirp(join(__dirname, '..', '..', dir), callbackEach)
+    mkdirp(join(root(), dir), callbackEach)
   }, callback)
 }
 
@@ -65,7 +65,8 @@ function createOAuthClientIfNotExist (callback) {
     const client = db.OAuthClient.build({
       clientId: id,
       clientSecret: secret,
-      grants: [ 'password', 'refresh_token' ]
+      grants: [ 'password', 'refresh_token' ],
+      redirectUris: null
     })
 
     client.save().asCallback(function (err, createdClient) {
index cfa3220e073a8d3a4d4a149afe30dc66804d1d7a..d42cb3ccc5120f1f5bd8f8204c5c3e6752957964 100644 (file)
@@ -1,10 +1,12 @@
 import { waterfall, eachSeries } from 'async'
 import fs = require('fs')
 import path = require('path')
+import * as Sequelize from 'sequelize'
 
-const db = require('./database')
+import { database as db } from './database'
 import { LAST_MIGRATION_VERSION } from './constants'
 import { logger } from '../helpers'
+import { ApplicationInstance } from '../models'
 
 function migrate (finalCallback) {
   waterfall([
@@ -94,7 +96,7 @@ function getMigrationScripts (callback) {
 }
 
 function executeMigration (actualVersion, entity, callback) {
-  const versionScript = parseInt(entity.version)
+  const versionScript = parseInt(entity.version, 10)
 
   // Do not execute old migration scripts
   if (versionScript <= actualVersion) return callback(null)
@@ -112,7 +114,7 @@ function executeMigration (actualVersion, entity, callback) {
       transaction: t,
       queryInterface: db.sequelize.getQueryInterface(),
       sequelize: db.sequelize,
-      Sequelize: db.Sequelize
+      Sequelize: Sequelize
     }
     migrationScript.up(options, function (err) {
       if (err) {
index b32783019b57db25ef2b09b4ffdacc59abdfe84f..08b776e83c8ed3c506b0d6b77572fa7639455fe9 100644 (file)
@@ -1,7 +1,7 @@
 import { each, eachLimit, eachSeries, series, waterfall } from 'async'
 import request = require('request')
 
-const db = require('../initializers/database')
+import { database as db } from '../initializers/database'
 import {
   API_VERSION,
   CONFIG,
@@ -329,7 +329,7 @@ function makeRequestsToWinningPods (cert, podsList, callback) {
   // Flush pool requests
   requestScheduler.forceSend()
 
-  eachLimit(podsList, REQUESTS_IN_PARALLEL, function (pod: any, callbackEach) {
+  eachLimit(podsList, REQUESTS_IN_PARALLEL, function (pod: { host: string }, callbackEach) {
     const params = {
       url: REMOTE_SCHEME.HTTP + '://' + pod.host + '/api/' + API_VERSION + '/pods/',
       method: 'POST',
@@ -340,7 +340,7 @@ function makeRequestsToWinningPods (cert, podsList, callback) {
       }
     }
 
-    makeRetryRequest(params, function (err, res, body) {
+    makeRetryRequest(params, function (err, res, body: { cert: string, email: string }) {
       if (err) {
         logger.error('Error with adding %s pod.', pod.host, { error: err })
         // Don't break the process
index 35db5fb967c81e0c12444717da69ea5c2dece8ef..43599356a729df8723e172395b7a916c2a4c4c1a 100644 (file)
@@ -1,4 +1,4 @@
-const db = require('../../../initializers/database')
+import { database as db } from '../../../initializers/database'
 import { logger } from '../../../helpers'
 import { addVideoToFriends } from '../../../lib'
 
index 7b8c6faf9581b3f38f9cca8b964cfaaaaaeb28b6..ad5f7f6d98bb0afcd137c472e1b1775427f6b8c0 100644 (file)
@@ -1,6 +1,6 @@
 import { forever, queue } from 'async'
 
-const db = require('../../initializers/database')
+import { database as db } from '../../initializers/database'
 import {
   JOBS_FETCHING_INTERVAL,
   JOBS_FETCH_LIMIT_PER_CYCLE,
@@ -24,7 +24,7 @@ class JobScheduler {
 
     logger.info('Jobs scheduler activated.')
 
-    const jobsQueue = queue(this.processJob)
+    const jobsQueue = queue(this.processJob.bind(this))
 
     // Finish processing jobs from a previous start
     const state = JOB_STATES.PROCESSING
@@ -58,7 +58,7 @@ class JobScheduler {
     })
   }
 
-  createJob (transaction, handlerName, handlerInputData, callback) {
+  createJob (transaction, handlerName: string, handlerInputData: object, callback) {
     const createQuery = {
       state: JOB_STATES.PENDING,
       handlerName,
index 00b1afcf50561b92ef5b4b2a52170ffe9c6c5326..3bdf0f47867973682aa7aa823c5172ef2d424e58 100644 (file)
@@ -1,4 +1,4 @@
-const db = require('../initializers/database')
+import { database as db } from '../initializers/database'
 import { logger } from '../helpers'
 
 // ---------------------------------------------------------------------------
@@ -72,7 +72,7 @@ function saveToken (token, client, user) {
     userId: user.id
   }
 
-  return db.OAuthToken.create(tokenToCreate).then(function (tokenCreated) {
+  return db.OAuthToken.create(tokenToCreate).then(function (tokenCreated: any) {
     tokenCreated.client = client
     tokenCreated.user = user
 
index 7fc88b5f150066c84f28f18b14eb7a7e8ff6c1c7..b7ef6abf902e7b5011a4e83310a421b475cb5875 100644 (file)
@@ -1,6 +1,6 @@
-import { eachLimit } from 'async/eachLimit'
+import * as eachLimit from 'async/eachLimit'
 
-const db = require('../../initializers/database')
+import { database as db } from '../../initializers/database'
 import { logger, makeSecureRequest } from '../../helpers'
 import {
   API_VERSION,
index 2006a6f0398f3b26954aaf507b1526c8c9ff91ff..26ffbfb868f892e5f384a3caf059dd728600d15d 100644 (file)
@@ -1,4 +1,4 @@
-const db = require('../../initializers/database')
+import { database as db } from '../../initializers/database'
 import { BaseRequestScheduler } from './base-request-scheduler'
 import { logger } from '../../helpers'
 import {
@@ -59,13 +59,14 @@ class RequestScheduler extends BaseRequestScheduler {
     const toIds = options.toIds
     const transaction = options.transaction
 
-    const pods = []
+    // TODO: check the setPods works
+    const podIds = []
 
     // If there are no destination pods abort
     if (toIds.length === 0) return callback(null)
 
     toIds.forEach(toPod => {
-      pods.push(db.Pod.build({ id: toPod }))
+      podIds.push(toPod)
     })
 
     const createQuery = {
@@ -83,7 +84,7 @@ class RequestScheduler extends BaseRequestScheduler {
     return db.Request.create(createQuery, dbRequestOptions).asCallback((err, request) => {
       if (err) return callback(err)
 
-      return request.setPods(pods, dbRequestOptions).asCallback(callback)
+      return request.setPods(podIds, dbRequestOptions).asCallback(callback)
     })
   }
 
index 6e5306c7d1ac31ad784097221bf7de8ee657302b..bde50b1d33dfc3ae9c619758f249c89d54257f5c 100644 (file)
@@ -1,4 +1,4 @@
-const db = require('../../initializers/database')
+import { database as db } from '../../initializers/database'
 import { BaseRequestScheduler } from './base-request-scheduler'
 import {
   REQUESTS_VIDEO_EVENT_LIMIT_PODS,
index d818227238a8b638980a0dd847bde7c81af458a4..dab526088f6703e8f6da429516e27db6d8b0ca95 100644 (file)
@@ -1,4 +1,4 @@
-const db = require('../../initializers/database')
+import { database as db } from '../../initializers/database'
 import { BaseRequestScheduler } from './base-request-scheduler'
 import { logger } from '../../helpers'
 import {
index ebafa36a4f90d04f7bb0278ec7b9654001cfca8b..28b6a9a120a24b8a23fb953fe463504cae897125 100644 (file)
@@ -1,4 +1,4 @@
-const logger = require('../helpers/logger')
+import { logger } from '../helpers'
 
 function ensureIsAdmin (req, res, next) {
   const user = res.locals.oauth.token.user
index 31ae1e000984c2878f4980f36cb7fc01bcbe4904..07bbded57d636d3a5999c46cc7b94621981c4c72 100644 (file)
@@ -1,11 +1,11 @@
 import OAuthServer = require('express-oauth-server')
 
-const constants = require('../initializers/constants')
-const logger = require('../helpers/logger')
+import { OAUTH_LIFETIME } from '../initializers'
+import { logger } from '../helpers'
 
 const oAuthServer = new OAuthServer({
-  accessTokenLifetime: constants.OAUTH_LIFETIME.ACCESS_TOKEN,
-  refreshTokenLifetime: constants.OAUTH_LIFETIME.REFRESH_TOKEN,
+  accessTokenLifetime: OAUTH_LIFETIME.ACCESS_TOKEN,
+  refreshTokenLifetime: OAUTH_LIFETIME.REFRESH_TOKEN,
   model: require('../lib/oauth-model')
 })
 
index 8fe9f9082b343886ceb063878018f004c7e7ae0f..cadd769805ae7f393e14187a867db86c6d60f56d 100644 (file)
@@ -1,10 +1,10 @@
-const constants = require('../initializers/constants')
+import { PAGINATION_COUNT_DEFAULT } from '../initializers'
 
 function setPagination (req, res, next) {
   if (!req.query.start) req.query.start = 0
   else req.query.start = parseInt(req.query.start, 10)
 
-  if (!req.query.count) req.query.count = constants.PAGINATION_COUNT_DEFAULT
+  if (!req.query.count) req.query.count = PAGINATION_COUNT_DEFAULT
   else req.query.count = parseInt(req.query.count, 10)
 
   return next()
index e405f265ec2dec60d5f5392dc5600368512a6e6c..c255be8998023a7bb8672b1cb8149fe78727c4fb 100644 (file)
@@ -1,6 +1,4 @@
-'use strict'
-
-const constants = require('../initializers/constants')
+import { REMOTE_SCHEME } from '../initializers'
 
 function setBodyHostsPort (req, res, next) {
   if (!req.body.hosts) return next()
@@ -48,7 +46,7 @@ function getHostWithPort (host) {
 
   // The port was not specified
   if (splitted.length === 1) {
-    if (constants.REMOTE_SCHEME.HTTP === 'https') return host + ':443'
+    if (REMOTE_SCHEME.HTTP === 'https') return host + ':443'
 
     return host + ':80'
   }
index ee8545028085894341a7d975c5f1de2d24349fdc..bd7cfa918159247bb5ef0c70f3b1eb5ae6b6a826 100644 (file)
@@ -1,6 +1,8 @@
-const db = require('../initializers/database')
-const logger = require('../helpers/logger')
-const peertubeCrypto = require('../helpers/peertube-crypto')
+import { database as db } from '../initializers'
+import {
+  logger,
+  checkSignature as peertubeCryptoCheckSignature
+} from '../helpers'
 
 function checkSignature (req, res, next) {
   const host = req.body.signature.host
@@ -26,7 +28,7 @@ function checkSignature (req, res, next) {
       signatureShouldBe = host
     }
 
-    const signatureOk = peertubeCrypto.checkSignature(pod.publicKey, signatureShouldBe, req.body.signature.signature)
+    const signatureOk = peertubeCryptoCheckSignature(pod.publicKey, signatureShouldBe, req.body.signature.signature)
 
     if (signatureOk === true) {
       res.locals.secure = {
index fbfd268d05e1d9a2b572cb072a2ccf4d8751dfdf..c55a88b85c6d29d0e582f2a7b304c394df7c83a5 100644 (file)
@@ -1,4 +1,4 @@
-const db = require('../../initializers/database')
+import { database as db } from '../../initializers/database'
 import { checkErrors } from './utils'
 import { logger } from '../../helpers'
 import { CONFIG } from '../../initializers'
index a9149fe1bcecdd056e2ce40038d718c8e5dd762e..e0d1d917a31d81e03b25167460d279ae7832d296 100644 (file)
@@ -1,4 +1,4 @@
-const db = require('../../initializers/database')
+import { database as db } from '../../initializers/database'
 import { checkErrors } from './utils'
 import { logger } from '../../helpers'
 
index 5a49cf73ce901aa8a7f1cd4944b97ecb96fcb0c2..47825975c002798c65722ef65035ca9f3a2fff86 100644 (file)
@@ -1,4 +1,4 @@
-const db = require('../../initializers/database')
+import { database as db } from '../../initializers/database'
 import { checkErrors } from './utils'
 import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers'
 import { logger, isVideoDurationValid } from '../../helpers'
diff --git a/server/models/application-interface.ts b/server/models/application-interface.ts
new file mode 100644 (file)
index 0000000..826d25d
--- /dev/null
@@ -0,0 +1,23 @@
+import * as Sequelize from 'sequelize'
+
+export namespace ApplicationMethods {
+  export type LoadMigrationVersion = (callback: (err: Error, version: number) => void) => void
+  export type UpdateMigrationVersion = (newVersion: number, transaction: any, callback: any) => void
+}
+
+export interface ApplicationClass {
+  loadMigrationVersion: ApplicationMethods.LoadMigrationVersion
+  updateMigrationVersion: ApplicationMethods.UpdateMigrationVersion
+}
+
+export interface ApplicationAttributes {
+  migrationVersion: number
+}
+
+export interface ApplicationInstance extends ApplicationClass, ApplicationAttributes, Sequelize.Instance<ApplicationAttributes> {
+  id: number
+  createdAt: Date
+  updatedAt: Date
+}
+
+export interface ApplicationModel extends ApplicationClass, Sequelize.Model<ApplicationInstance, ApplicationAttributes> {}
index 38a57e3275ab3108ec12793a83261a38248640eb..acd0dfbf2e38fb9d8c5f651dd29a9b64046027ca 100644 (file)
@@ -1,5 +1,20 @@
-module.exports = function (sequelize, DataTypes) {
-  const Application = sequelize.define('Application',
+import * as Sequelize from 'sequelize'
+
+import { addMethodsToModel } from './utils'
+import {
+  ApplicationClass,
+  ApplicationAttributes,
+  ApplicationInstance,
+
+  ApplicationMethods
+} from './application-interface'
+
+let Application: Sequelize.Model<ApplicationInstance, ApplicationAttributes>
+let loadMigrationVersion: ApplicationMethods.LoadMigrationVersion
+let updateMigrationVersion: ApplicationMethods.UpdateMigrationVersion
+
+export default function defineApplication (sequelize: Sequelize.Sequelize, DataTypes) {
+  Application = sequelize.define<ApplicationInstance, ApplicationAttributes>('Application',
     {
       migrationVersion: {
         type: DataTypes.INTEGER,
@@ -9,34 +24,31 @@ module.exports = function (sequelize, DataTypes) {
           isInt: true
         }
       }
-    },
-    {
-      classMethods: {
-        loadMigrationVersion,
-        updateMigrationVersion
-      }
     }
   )
 
+  const classMethods = [ loadMigrationVersion, updateMigrationVersion ]
+  addMethodsToModel(Application, classMethods)
+
   return Application
 }
 
 // ---------------------------------------------------------------------------
 
-function loadMigrationVersion (callback) {
+loadMigrationVersion = function (callback: (err: Error, version: number) => void) {
   const query = {
     attributes: [ 'migrationVersion' ]
   }
 
-  return this.findOne(query).asCallback(function (err, data) {
+  return Application.findOne(query).asCallback(function (err, data) {
     const version = data ? data.migrationVersion : null
 
     return callback(err, version)
   })
 }
 
-function updateMigrationVersion (newVersion, transaction, callback) {
-  const options: { where?: any, transaction?: any } = {
+updateMigrationVersion = function (newVersion: number, transaction: any, callback: any) {
+  const options: Sequelize.UpdateOptions = {
     where: {}
   }
 
@@ -46,5 +58,5 @@ function updateMigrationVersion (newVersion, transaction, callback) {
     options.transaction = transaction
   }
 
-  return this.update({ migrationVersion: newVersion }, options).asCallback(callback)
+  return Application.update({ migrationVersion: newVersion }, options).asCallback(callback)
 }
diff --git a/server/models/author-interface.ts b/server/models/author-interface.ts
new file mode 100644 (file)
index 0000000..d2475c3
--- /dev/null
@@ -0,0 +1,21 @@
+import * as Sequelize from 'sequelize'
+
+export namespace AuthorMethods {
+  export type FindOrCreateAuthor = (name, podId, userId, transaction, callback) => void
+}
+
+export interface AuthorClass {
+  findOrCreateAuthor: AuthorMethods.FindOrCreateAuthor
+}
+
+export interface AuthorAttributes {
+  name: string
+}
+
+export interface AuthorInstance extends AuthorClass, AuthorAttributes, Sequelize.Instance<AuthorAttributes> {
+  id: number
+  createdAt: Date
+  updatedAt: Date
+}
+
+export interface AuthorModel extends AuthorClass, Sequelize.Model<AuthorInstance, AuthorAttributes> {}
index 4a73969299526d5c09d548c75a243280ee84e47a..b543d17a0f57448039b6df492fd8d62ee6d6432d 100644 (file)
@@ -1,7 +1,21 @@
+import * as Sequelize from 'sequelize'
+
 import { isUserUsernameValid } from '../helpers'
 
-module.exports = function (sequelize, DataTypes) {
-  const Author = sequelize.define('Author',
+import { addMethodsToModel } from './utils'
+import {
+  AuthorClass,
+  AuthorInstance,
+  AuthorAttributes,
+
+  AuthorMethods
+} from './author-interface'
+
+let Author: Sequelize.Model<AuthorInstance, AuthorAttributes>
+let findOrCreateAuthor: AuthorMethods.FindOrCreateAuthor
+
+export default function defineAuthor (sequelize: Sequelize.Sequelize, DataTypes) {
+  Author = sequelize.define<AuthorInstance, AuthorAttributes>('Author',
     {
       name: {
         type: DataTypes.STRING,
@@ -30,22 +44,20 @@ module.exports = function (sequelize, DataTypes) {
           fields: [ 'name', 'podId' ],
           unique: true
         }
-      ],
-      classMethods: {
-        associate,
-
-        findOrCreateAuthor
-      }
+      ]
     }
   )
 
+  const classMethods = [ associate, findOrCreateAuthor ]
+  addMethodsToModel(Author, classMethods)
+
   return Author
 }
 
 // ---------------------------------------------------------------------------
 
 function associate (models) {
-  this.belongsTo(models.Pod, {
+  Author.belongsTo(models.Pod, {
     foreignKey: {
       name: 'podId',
       allowNull: true
@@ -53,7 +65,7 @@ function associate (models) {
     onDelete: 'cascade'
   })
 
-  this.belongsTo(models.User, {
+  Author.belongsTo(models.User, {
     foreignKey: {
       name: 'userId',
       allowNull: true
@@ -62,7 +74,7 @@ function associate (models) {
   })
 }
 
-function findOrCreateAuthor (name, podId, userId, transaction, callback) {
+findOrCreateAuthor = function (name, podId, userId, transaction, callback) {
   if (!callback) {
     callback = transaction
     transaction = null
@@ -81,7 +93,7 @@ function findOrCreateAuthor (name, podId, userId, transaction, callback) {
 
   if (transaction) query.transaction = transaction
 
-  this.findOrCreate(query).asCallback(function (err, result) {
+  Author.findOrCreate(query).asCallback(function (err, result) {
     if (err) return callback(err)
 
     // [ instance, wasCreated ]
diff --git a/server/models/index.ts b/server/models/index.ts
new file mode 100644 (file)
index 0000000..432c0dc
--- /dev/null
@@ -0,0 +1,17 @@
+export * from './application-interface'
+export * from './author-interface'
+export * from './job-interface'
+export * from './oauth-client-interface'
+export * from './oauth-token-interface'
+export * from './pod-interface'
+export * from './request-interface'
+export * from './request-to-pod-interface'
+export * from './request-video-event-interface'
+export * from './request-video-qadu-interface'
+export * from './tag-interface'
+export * from './user-video-rate-interface'
+export * from './user-interface'
+export * from './video-abuse-interface'
+export * from './video-blacklist-interface'
+export * from './video-tag-interface'
+export * from './video-interface'
diff --git a/server/models/job-interface.ts b/server/models/job-interface.ts
new file mode 100644 (file)
index 0000000..ad4e2d2
--- /dev/null
@@ -0,0 +1,23 @@
+import * as Sequelize from 'sequelize'
+
+export namespace JobMethods {
+  export type ListWithLimit = (limit, state, callback) => void
+}
+
+export interface JobClass {
+  listWithLimit: JobMethods.ListWithLimit
+}
+
+export interface JobAttributes {
+  state: string
+  handlerName: string
+  handlerInputData: object
+}
+
+export interface JobInstance extends JobClass, JobAttributes, Sequelize.Instance<JobAttributes> {
+  id: number
+  createdAt: Date
+  updatedAt: Date
+}
+
+export interface JobModel extends JobClass, Sequelize.Model<JobInstance, JobAttributes> {}
index 6843e399b04ddfedd360c0040207cc737d0b4cfa..982b51499e2cc152ad2fc03707dceaac79a66d11 100644 (file)
@@ -1,11 +1,22 @@
 import { values } from 'lodash'
+import * as Sequelize from 'sequelize'
 
 import { JOB_STATES } from '../initializers'
 
-// ---------------------------------------------------------------------------
+import { addMethodsToModel } from './utils'
+import {
+  JobClass,
+  JobInstance,
+  JobAttributes,
+
+  JobMethods
+} from './job-interface'
+
+let Job: Sequelize.Model<JobInstance, JobAttributes>
+let listWithLimit: JobMethods.ListWithLimit
 
-module.exports = function (sequelize, DataTypes) {
-  const Job = sequelize.define('Job',
+export default function defineJob (sequelize: Sequelize.Sequelize, DataTypes) {
+  Job = sequelize.define<JobInstance, JobAttributes>('Job',
     {
       state: {
         type: DataTypes.ENUM(values(JOB_STATES)),
@@ -25,19 +36,19 @@ module.exports = function (sequelize, DataTypes) {
         {
           fields: [ 'state' ]
         }
-      ],
-      classMethods: {
-        listWithLimit
-      }
+      ]
     }
   )
 
+  const classMethods = [ listWithLimit ]
+  addMethodsToModel(Job, classMethods)
+
   return Job
 }
 
 // ---------------------------------------------------------------------------
 
-function listWithLimit (limit, state, callback) {
+listWithLimit = function (limit, state, callback) {
   const query = {
     order: [
       [ 'id', 'ASC' ]
@@ -48,5 +59,5 @@ function listWithLimit (limit, state, callback) {
     }
   }
 
-  return this.findAll(query).asCallback(callback)
+  return Job.findAll(query).asCallback(callback)
 }
diff --git a/server/models/oauth-client-interface.ts b/server/models/oauth-client-interface.ts
new file mode 100644 (file)
index 0000000..4efd621
--- /dev/null
@@ -0,0 +1,28 @@
+import * as Sequelize from 'sequelize'
+
+export namespace OAuthClientMethods {
+  export type CountTotal = (callback) => void
+  export type LoadFirstClient = (callback) => void
+  export type GetByIdAndSecret = (clientId, clientSecret) => void
+}
+
+export interface OAuthClientClass {
+  countTotal: OAuthClientMethods.CountTotal
+  loadFirstClient: OAuthClientMethods.LoadFirstClient
+  getByIdAndSecret: OAuthClientMethods.GetByIdAndSecret
+}
+
+export interface OAuthClientAttributes {
+  clientId: string
+  clientSecret: string
+  grants: string[]
+  redirectUris: string[]
+}
+
+export interface OAuthClientInstance extends OAuthClientClass, OAuthClientAttributes, Sequelize.Instance<OAuthClientAttributes> {
+  id: number
+  createdAt: Date
+  updatedAt: Date
+}
+
+export interface OAuthClientModel extends OAuthClientClass, Sequelize.Model<OAuthClientInstance, OAuthClientAttributes> {}
index 3198a85efcbae3677c9503256b5b0d42ae203b43..2cefb5cb9ab6a058e14c3a64005538347f0844ab 100644 (file)
@@ -1,5 +1,21 @@
-module.exports = function (sequelize, DataTypes) {
-  const OAuthClient = sequelize.define('OAuthClient',
+import * as Sequelize from 'sequelize'
+
+import { addMethodsToModel } from './utils'
+import {
+  OAuthClientClass,
+  OAuthClientInstance,
+  OAuthClientAttributes,
+
+  OAuthClientMethods
+} from './oauth-client-interface'
+
+let OAuthClient: Sequelize.Model<OAuthClientInstance, OAuthClientAttributes>
+let countTotal: OAuthClientMethods.CountTotal
+let loadFirstClient: OAuthClientMethods.LoadFirstClient
+let getByIdAndSecret: OAuthClientMethods.GetByIdAndSecret
+
+export default function (sequelize, DataTypes) {
+  OAuthClient = sequelize.define('OAuthClient',
     {
       clientId: {
         type: DataTypes.STRING,
@@ -26,29 +42,40 @@ module.exports = function (sequelize, DataTypes) {
           fields: [ 'clientId', 'clientSecret' ],
           unique: true
         }
-      ],
-      classMethods: {
-        countTotal,
-        getByIdAndSecret,
-        loadFirstClient
-      }
+      ]
     }
   )
 
+  const classMethods = [
+    associate,
+
+    countTotal,
+    getByIdAndSecret,
+    loadFirstClient
+  ]
+  addMethodsToModel(OAuthClient, classMethods)
+
   return OAuthClient
 }
 
 // ---------------------------------------------------------------------------
 
-function countTotal (callback) {
-  return this.count().asCallback(callback)
+function associate (models) {
+  OAuthClient.hasMany(models.OAuthToken, {
+    foreignKey: 'oAuthClientId',
+    onDelete: 'cascade'
+  })
+}
+
+countTotal = function (callback) {
+  return OAuthClient.count().asCallback(callback)
 }
 
-function loadFirstClient (callback) {
-  return this.findOne().asCallback(callback)
+loadFirstClient = function (callback) {
+  return OAuthClient.findOne().asCallback(callback)
 }
 
-function getByIdAndSecret (clientId, clientSecret) {
+getByIdAndSecret = function (clientId, clientSecret) {
   const query = {
     where: {
       clientId: clientId,
@@ -56,5 +83,5 @@ function getByIdAndSecret (clientId, clientSecret) {
     }
   }
 
-  return this.findOne(query)
+  return OAuthClient.findOne(query)
 }
diff --git a/server/models/oauth-token-interface.ts b/server/models/oauth-token-interface.ts
new file mode 100644 (file)
index 0000000..a0cd1ff
--- /dev/null
@@ -0,0 +1,34 @@
+import * as Sequelize from 'sequelize'
+
+import { UserModel } from './user-interface'
+
+export namespace OAuthTokenMethods {
+  export type GetByRefreshTokenAndPopulateClient = (refreshToken) => void
+  export type GetByTokenAndPopulateUser = (bearerToken) => void
+  export type GetByRefreshTokenAndPopulateUser = (refreshToken) => any
+  export type RemoveByUserId = (userId, callback) => void
+}
+
+export interface OAuthTokenClass {
+  getByRefreshTokenAndPopulateClient: OAuthTokenMethods.GetByRefreshTokenAndPopulateClient
+  getByTokenAndPopulateUser: OAuthTokenMethods.GetByTokenAndPopulateUser
+  getByRefreshTokenAndPopulateUser: OAuthTokenMethods.GetByRefreshTokenAndPopulateUser
+  removeByUserId: OAuthTokenMethods.RemoveByUserId
+}
+
+export interface OAuthTokenAttributes {
+  accessToken: string
+  accessTokenExpiresAt: Date
+  refreshToken: string
+  refreshTokenExpiresAt: Date
+
+  User?: UserModel
+}
+
+export interface OAuthTokenInstance extends OAuthTokenClass, OAuthTokenAttributes, Sequelize.Instance<OAuthTokenAttributes> {
+  id: number
+  createdAt: Date
+  updatedAt: Date
+}
+
+export interface OAuthTokenModel extends OAuthTokenClass, Sequelize.Model<OAuthTokenInstance, OAuthTokenAttributes> {}
index 74c9180eb9c0a824314489e4c5a1a9e5caf6a45f..567df1c12c3df91b676cd00a9d21ec981c4198b7 100644 (file)
@@ -1,9 +1,24 @@
+import * as Sequelize from 'sequelize'
+
 import { logger } from '../helpers'
 
-// ---------------------------------------------------------------------------
+import { addMethodsToModel } from './utils'
+import {
+  OAuthTokenClass,
+  OAuthTokenInstance,
+  OAuthTokenAttributes,
+
+  OAuthTokenMethods
+} from './oauth-token-interface'
+
+let OAuthToken: Sequelize.Model<OAuthTokenInstance, OAuthTokenAttributes>
+let getByRefreshTokenAndPopulateClient: OAuthTokenMethods.GetByRefreshTokenAndPopulateClient
+let getByTokenAndPopulateUser: OAuthTokenMethods.GetByTokenAndPopulateUser
+let getByRefreshTokenAndPopulateUser: OAuthTokenMethods.GetByRefreshTokenAndPopulateUser
+let removeByUserId: OAuthTokenMethods.RemoveByUserId
 
-module.exports = function (sequelize, DataTypes) {
-  const OAuthToken = sequelize.define('OAuthToken',
+export default function (sequelize, DataTypes) {
+  OAuthToken = sequelize.define('OAuthToken',
     {
       accessToken: {
         type: DataTypes.STRING,
@@ -38,25 +53,27 @@ module.exports = function (sequelize, DataTypes) {
         {
           fields: [ 'oAuthClientId' ]
         }
-      ],
-      classMethods: {
-        associate,
-
-        getByRefreshTokenAndPopulateClient,
-        getByTokenAndPopulateUser,
-        getByRefreshTokenAndPopulateUser,
-        removeByUserId
-      }
+      ]
     }
   )
 
+  const classMethods = [
+    associate,
+
+    getByRefreshTokenAndPopulateClient,
+    getByTokenAndPopulateUser,
+    getByRefreshTokenAndPopulateUser,
+    removeByUserId
+  ]
+  addMethodsToModel(OAuthToken, classMethods)
+
   return OAuthToken
 }
 
 // ---------------------------------------------------------------------------
 
 function associate (models) {
-  this.belongsTo(models.User, {
+  OAuthToken.belongsTo(models.User, {
     foreignKey: {
       name: 'userId',
       allowNull: false
@@ -64,7 +81,7 @@ function associate (models) {
     onDelete: 'cascade'
   })
 
-  this.belongsTo(models.OAuthClient, {
+  OAuthToken.belongsTo(models.OAuthClient, {
     foreignKey: {
       name: 'oAuthClientId',
       allowNull: false
@@ -73,25 +90,25 @@ function associate (models) {
   })
 }
 
-function getByRefreshTokenAndPopulateClient (refreshToken) {
+getByRefreshTokenAndPopulateClient = function (refreshToken) {
   const query = {
     where: {
       refreshToken: refreshToken
     },
-    include: [ this.associations.OAuthClient ]
+    include: [ OAuthToken['sequelize'].models.OAuthClient ]
   }
 
-  return this.findOne(query).then(function (token) {
+  return OAuthToken.findOne(query).then(function (token) {
     if (!token) return token
 
     const tokenInfos = {
       refreshToken: token.refreshToken,
       refreshTokenExpiresAt: token.refreshTokenExpiresAt,
       client: {
-        id: token.client.id
+        id: token['client'].id
       },
       user: {
-        id: token.user
+        id: token['user']
       }
     }
 
@@ -101,42 +118,42 @@ function getByRefreshTokenAndPopulateClient (refreshToken) {
   })
 }
 
-function getByTokenAndPopulateUser (bearerToken) {
+getByTokenAndPopulateUser = function (bearerToken) {
   const query = {
     where: {
       accessToken: bearerToken
     },
-    include: [ this.sequelize.models.User ]
+    include: [ OAuthToken['sequelize'].models.User ]
   }
 
-  return this.findOne(query).then(function (token) {
-    if (token) token.user = token.User
+  return OAuthToken.findOne(query).then(function (token) {
+    if (token) token['user'] = token.User
 
     return token
   })
 }
 
-function getByRefreshTokenAndPopulateUser (refreshToken) {
+getByRefreshTokenAndPopulateUser = function (refreshToken) {
   const query = {
     where: {
       refreshToken: refreshToken
     },
-    include: [ this.sequelize.models.User ]
+    include: [ OAuthToken['sequelize'].models.User ]
   }
 
-  return this.findOne(query).then(function (token) {
-    token.user = token.User
+  return OAuthToken.findOne(query).then(function (token) {
+    token['user'] = token.User
 
     return token
   })
 }
 
-function removeByUserId (userId, callback) {
+removeByUserId = function (userId, callback) {
   const query = {
     where: {
       userId: userId
     }
   }
 
-  return this.destroy(query).asCallback(callback)
+  return OAuthToken.destroy(query).asCallback(callback)
 }
diff --git a/server/models/pod-interface.ts b/server/models/pod-interface.ts
new file mode 100644 (file)
index 0000000..14c88be
--- /dev/null
@@ -0,0 +1,46 @@
+import * as Sequelize from 'sequelize'
+
+export namespace PodMethods {
+  export type ToFormatedJSON = () => void
+
+  export type CountAll = (callback) => void
+  export type IncrementScores = (ids, value, callback) => void
+  export type List = (callback) => void
+  export type ListAllIds = (transaction, callback) => void
+  export type ListRandomPodIdsWithRequest = (limit, tableWithPods, tableWithPodsJoins, callback) => void
+  export type ListBadPods = (callback) => void
+  export type Load = (id, callback) => void
+  export type LoadByHost = (host, callback) => void
+  export type RemoveAll = (callback) => void
+  export type UpdatePodsScore = (goodPods, badPods) => void
+}
+
+export interface PodClass {
+  countAll: PodMethods.CountAll
+  incrementScores: PodMethods.IncrementScores
+  list: PodMethods.List
+  listAllIds: PodMethods.ListAllIds
+  listRandomPodIdsWithRequest: PodMethods.ListRandomPodIdsWithRequest
+  listBadPods: PodMethods.ListBadPods
+  load: PodMethods.Load
+  loadByHost: PodMethods.LoadByHost
+  removeAll: PodMethods.RemoveAll
+  updatePodsScore: PodMethods.UpdatePodsScore
+}
+
+export interface PodAttributes {
+  host?: string
+  publicKey?: string
+  score?: number | Sequelize.literal // Sequelize literal for 'score +' + value
+  email?: string
+}
+
+export interface PodInstance extends PodClass, PodAttributes, Sequelize.Instance<PodAttributes> {
+  id: number
+  createdAt: Date
+  updatedAt: Date
+
+  toFormatedJSON: PodMethods.ToFormatedJSON,
+}
+
+export interface PodModel extends PodClass, Sequelize.Model<PodInstance, PodAttributes> {}
index 0e0262978517649359cabbf765c1d39a87956b94..2df32e4a4470028eb8987a1a1cf0c8069dd9ad02 100644 (file)
@@ -1,13 +1,34 @@
 import { each, waterfall } from 'async'
 import { map } from 'lodash'
+import * as Sequelize from 'sequelize'
 
 import { FRIEND_SCORE, PODS_SCORE } from '../initializers'
 import { logger, isHostValid } from '../helpers'
 
-// ---------------------------------------------------------------------------
-
-module.exports = function (sequelize, DataTypes) {
-  const Pod = sequelize.define('Pod',
+import { addMethodsToModel } from './utils'
+import {
+  PodClass,
+  PodInstance,
+  PodAttributes,
+
+  PodMethods
+} from './pod-interface'
+
+let Pod: Sequelize.Model<PodInstance, PodAttributes>
+let toFormatedJSON: PodMethods.ToFormatedJSON
+let countAll: PodMethods.CountAll
+let incrementScores: PodMethods.IncrementScores
+let list: PodMethods.List
+let listAllIds: PodMethods.ListAllIds
+let listRandomPodIdsWithRequest: PodMethods.ListRandomPodIdsWithRequest
+let listBadPods: PodMethods.ListBadPods
+let load: PodMethods.Load
+let loadByHost: PodMethods.LoadByHost
+let removeAll: PodMethods.RemoveAll
+let updatePodsScore: PodMethods.UpdatePodsScore
+
+export default function (sequelize, DataTypes) {
+  Pod = sequelize.define('Pod',
     {
       host: {
         type: DataTypes.STRING,
@@ -49,33 +70,33 @@ module.exports = function (sequelize, DataTypes) {
         {
           fields: [ 'score' ]
         }
-      ],
-      classMethods: {
-        associate,
-
-        countAll,
-        incrementScores,
-        list,
-        listAllIds,
-        listRandomPodIdsWithRequest,
-        listBadPods,
-        load,
-        loadByHost,
-        updatePodsScore,
-        removeAll
-      },
-      instanceMethods: {
-        toFormatedJSON
-      }
+      ]
     }
   )
 
+  const classMethods = [
+    associate,
+
+    countAll,
+    incrementScores,
+    list,
+    listAllIds,
+    listRandomPodIdsWithRequest,
+    listBadPods,
+    load,
+    loadByHost,
+    updatePodsScore,
+    removeAll
+  ]
+  const instanceMethods = [ toFormatedJSON ]
+  addMethodsToModel(Pod, classMethods, instanceMethods)
+
   return Pod
 }
 
 // ------------------------------ METHODS ------------------------------
 
-function toFormatedJSON () {
+toFormatedJSON = function () {
   const json = {
     id: this.id,
     host: this.host,
@@ -90,22 +111,22 @@ function toFormatedJSON () {
 // ------------------------------ Statics ------------------------------
 
 function associate (models) {
-  this.belongsToMany(models.Request, {
+  Pod.belongsToMany(models.Request, {
     foreignKey: 'podId',
     through: models.RequestToPod,
     onDelete: 'cascade'
   })
 }
 
-function countAll (callback) {
-  return this.count().asCallback(callback)
+countAll = function (callback) {
+  return Pod.count().asCallback(callback)
 }
 
-function incrementScores (ids, value, callback) {
+incrementScores = function (ids, value, callback) {
   if (!callback) callback = function () { /* empty */ }
 
   const update = {
-    score: this.sequelize.literal('score +' + value)
+    score: Sequelize.literal('score +' + value)
   }
 
   const options = {
@@ -118,14 +139,14 @@ function incrementScores (ids, value, callback) {
     validate: false
   }
 
-  return this.update(update, options).asCallback(callback)
+  return Pod.update(update, options).asCallback(callback)
 }
 
-function list (callback) {
-  return this.findAll().asCallback(callback)
+list = function (callback) {
+  return Pod.findAll().asCallback(callback)
 }
 
-function listAllIds (transaction, callback) {
+listAllIds = function (transaction, callback) {
   if (!callback) {
     callback = transaction
     transaction = null
@@ -137,22 +158,20 @@ function listAllIds (transaction, callback) {
 
   if (transaction) query.transaction = transaction
 
-  return this.findAll(query).asCallback(function (err, pods) {
+  return Pod.findAll(query).asCallback(function (err, pods) {
     if (err) return callback(err)
 
     return callback(null, map(pods, 'id'))
   })
 }
 
-function listRandomPodIdsWithRequest (limit, tableWithPods, tableWithPodsJoins, callback) {
+listRandomPodIdsWithRequest = function (limit, tableWithPods, tableWithPodsJoins, callback) {
   if (!callback) {
     callback = tableWithPodsJoins
     tableWithPodsJoins = ''
   }
 
-  const self = this
-
-  self.count().asCallback(function (err, count) {
+  Pod.count().asCallback(function (err, count) {
     if (err) return callback(err)
 
     // Optimization...
@@ -171,13 +190,13 @@ function listRandomPodIdsWithRequest (limit, tableWithPods, tableWithPodsJoins,
       where: {
         id: {
           $in: [
-            this.sequelize.literal(`SELECT DISTINCT "${tableWithPods}"."podId" FROM "${tableWithPods}" ${tableWithPodsJoins}`)
+            Sequelize.literal(`SELECT DISTINCT "${tableWithPods}"."podId" FROM "${tableWithPods}" ${tableWithPodsJoins}`)
           ]
         }
       }
     }
 
-    return this.findAll(query).asCallback(function (err, pods) {
+    return Pod.findAll(query).asCallback(function (err, pods) {
       if (err) return callback(err)
 
       return callback(null, map(pods, 'id'))
@@ -185,49 +204,47 @@ function listRandomPodIdsWithRequest (limit, tableWithPods, tableWithPodsJoins,
   })
 }
 
-function listBadPods (callback) {
+listBadPods = function (callback) {
   const query = {
     where: {
       score: { $lte: 0 }
     }
   }
 
-  return this.findAll(query).asCallback(callback)
+  return Pod.findAll(query).asCallback(callback)
 }
 
-function load (id, callback) {
-  return this.findById(id).asCallback(callback)
+load = function (id, callback) {
+  return Pod.findById(id).asCallback(callback)
 }
 
-function loadByHost (host, callback) {
+loadByHost = function (host, callback) {
   const query = {
     where: {
       host: host
     }
   }
 
-  return this.findOne(query).asCallback(callback)
+  return Pod.findOne(query).asCallback(callback)
 }
 
-function removeAll (callback) {
-  return this.destroy().asCallback(callback)
+removeAll = function (callback) {
+  return Pod.destroy().asCallback(callback)
 }
 
-function updatePodsScore (goodPods, badPods) {
-  const self = this
-
+updatePodsScore = function (goodPods, badPods) {
   logger.info('Updating %d good pods and %d bad pods scores.', goodPods.length, badPods.length)
 
   if (goodPods.length !== 0) {
-    this.incrementScores(goodPods, PODS_SCORE.BONUS, function (err) {
+    incrementScores(goodPods, PODS_SCORE.BONUS, function (err) {
       if (err) logger.error('Cannot increment scores of good pods.', { error: err })
     })
   }
 
   if (badPods.length !== 0) {
-    this.incrementScores(badPods, PODS_SCORE.MALUS, function (err) {
+    incrementScores(badPods, PODS_SCORE.MALUS, function (err) {
       if (err) logger.error('Cannot decrement scores of bad pods.', { error: err })
-      removeBadPods.call(self)
+      removeBadPods()
     })
   }
 }
@@ -236,11 +253,9 @@ function updatePodsScore (goodPods, badPods) {
 
 // Remove pods with a score of 0 (too many requests where they were unreachable)
 function removeBadPods () {
-  const self = this
-
   waterfall([
     function findBadPods (callback) {
-      self.sequelize.models.Pod.listBadPods(function (err, pods) {
+      listBadPods(function (err, pods) {
         if (err) {
           logger.error('Cannot find bad pods.', { error: err })
           return callback(err)
diff --git a/server/models/request-interface.ts b/server/models/request-interface.ts
new file mode 100644 (file)
index 0000000..2bba8ce
--- /dev/null
@@ -0,0 +1,32 @@
+import * as Sequelize from 'sequelize'
+
+import { PodAttributes } from './pod-interface'
+
+export namespace RequestMethods {
+  export type CountTotalRequests = (callback) => void
+  export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void
+  export type RemoveWithEmptyTo = (callback) => void
+  export type RemoveAll = (callback) => void
+}
+
+export interface RequestClass {
+  countTotalRequests: RequestMethods.CountTotalRequests
+  listWithLimitAndRandom: RequestMethods.ListWithLimitAndRandom
+  removeWithEmptyTo: RequestMethods.RemoveWithEmptyTo
+  removeAll: RequestMethods.RemoveAll
+}
+
+export interface RequestAttributes {
+  request: object
+  endpoint: string
+}
+
+export interface RequestInstance extends Sequelize.Instance<RequestAttributes> {
+  id: number
+  createdAt: Date
+  updatedAt: Date
+
+  setPods: Sequelize.HasManySetAssociationsMixin<PodAttributes, number>
+}
+
+export interface RequestModel extends RequestClass, Sequelize.Model<RequestInstance, RequestAttributes> {}
diff --git a/server/models/request-to-pod-interface.ts b/server/models/request-to-pod-interface.ts
new file mode 100644 (file)
index 0000000..52116d6
--- /dev/null
@@ -0,0 +1,20 @@
+import * as Sequelize from 'sequelize'
+
+export namespace RequestToPodMethods {
+  export type RemoveByRequestIdsAndPod = (requestsIds, podId, callback) => void
+}
+
+export interface RequestToPodClass {
+  removeByRequestIdsAndPod: RequestToPodMethods.RemoveByRequestIdsAndPod
+}
+
+export interface RequestToPodAttributes {
+}
+
+export interface RequestToPodInstance extends Sequelize.Instance<RequestToPodAttributes> {
+  id: number
+  createdAt: Date
+  updatedAt: Date
+}
+
+export interface RequestToPodModel extends RequestToPodClass, Sequelize.Model<RequestToPodInstance, RequestToPodAttributes> {}
index 479202e40431f2cb522347b0595257f8603cbe98..681f808b7ebce082b86fcff73aa17a2e9a33d241 100644 (file)
@@ -1,5 +1,19 @@
-module.exports = function (sequelize, DataTypes) {
-  const RequestToPod = sequelize.define('RequestToPod', {}, {
+import * as Sequelize from 'sequelize'
+
+import { addMethodsToModel } from './utils'
+import {
+  RequestToPodClass,
+  RequestToPodInstance,
+  RequestToPodAttributes,
+
+  RequestToPodMethods
+} from './request-to-pod-interface'
+
+let RequestToPod: Sequelize.Model<RequestToPodInstance, RequestToPodAttributes>
+let removeByRequestIdsAndPod: RequestToPodMethods.RemoveByRequestIdsAndPod
+
+export default function (sequelize, DataTypes) {
+  RequestToPod = sequelize.define('RequestToPod', {}, {
     indexes: [
       {
         fields: [ 'requestId' ]
@@ -11,18 +25,20 @@ module.exports = function (sequelize, DataTypes) {
         fields: [ 'requestId', 'podId' ],
         unique: true
       }
-    ],
-    classMethods: {
-      removeByRequestIdsAndPod
-    }
+    ]
   })
 
+  const classMethods = [
+    removeByRequestIdsAndPod
+  ]
+  addMethodsToModel(RequestToPod, classMethods)
+
   return RequestToPod
 }
 
 // ---------------------------------------------------------------------------
 
-function removeByRequestIdsAndPod (requestsIds, podId, callback) {
+removeByRequestIdsAndPod = function (requestsIds, podId, callback) {
   if (!callback) callback = function () { /* empty */ }
 
   const query = {
@@ -34,5 +50,5 @@ function removeByRequestIdsAndPod (requestsIds, podId, callback) {
     }
   }
 
-  this.destroy(query).asCallback(callback)
+  RequestToPod.destroy(query).asCallback(callback)
 }
diff --git a/server/models/request-video-event-interface.ts b/server/models/request-video-event-interface.ts
new file mode 100644 (file)
index 0000000..a31c710
--- /dev/null
@@ -0,0 +1,26 @@
+import * as Sequelize from 'sequelize'
+
+export namespace RequestVideoEventMethods {
+  export type CountTotalRequests = (callback) => void
+  export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void
+  export type RemoveByRequestIdsAndPod = (ids, podId, callback) => void
+  export type RemoveAll = (callback) => void
+}
+
+export interface RequestVideoEventClass {
+  countTotalRequests: RequestVideoEventMethods.CountTotalRequests
+  listWithLimitAndRandom: RequestVideoEventMethods.ListWithLimitAndRandom
+  removeByRequestIdsAndPod: RequestVideoEventMethods.RemoveByRequestIdsAndPod
+  removeAll: RequestVideoEventMethods.RemoveAll
+}
+
+export interface RequestVideoEventAttributes {
+  type: string
+  count: number
+}
+
+export interface RequestVideoEventInstance extends Sequelize.Instance<RequestVideoEventAttributes> {
+  id: number
+}
+
+export interface RequestVideoEventModel extends RequestVideoEventClass, Sequelize.Model<RequestVideoEventInstance, RequestVideoEventAttributes> {}
index c615250290b9fb9fd3941b0d82fea2a56c7ad606..234e2a8a9ea117ca4b21f7be6d90fde307f0aefa 100644 (file)
@@ -3,14 +3,28 @@
 */
 
 import { values } from 'lodash'
+import * as Sequelize from 'sequelize'
 
 import { REQUEST_VIDEO_EVENT_TYPES } from '../initializers'
 import { isVideoEventCountValid } from '../helpers'
 
-// ---------------------------------------------------------------------------
+import { addMethodsToModel } from './utils'
+import {
+  RequestVideoEventClass,
+  RequestVideoEventInstance,
+  RequestVideoEventAttributes,
+
+  RequestVideoEventMethods
+} from './request-video-event-interface'
+
+let RequestVideoEvent: Sequelize.Model<RequestVideoEventInstance, RequestVideoEventAttributes>
+let countTotalRequests: RequestVideoEventMethods.CountTotalRequests
+let listWithLimitAndRandom: RequestVideoEventMethods.ListWithLimitAndRandom
+let removeByRequestIdsAndPod: RequestVideoEventMethods.RemoveByRequestIdsAndPod
+let removeAll: RequestVideoEventMethods.RemoveAll
 
-module.exports = function (sequelize, DataTypes) {
-  const RequestVideoEvent = sequelize.define('RequestVideoEvent',
+export default function (sequelize, DataTypes) {
+  RequestVideoEvent = sequelize.define('RequestVideoEvent',
     {
       type: {
         type: DataTypes.ENUM(values(REQUEST_VIDEO_EVENT_TYPES)),
@@ -33,26 +47,27 @@ module.exports = function (sequelize, DataTypes) {
         {
           fields: [ 'videoId' ]
         }
-      ],
-      classMethods: {
-        associate,
-
-        listWithLimitAndRandom,
-
-        countTotalRequests,
-        removeAll,
-        removeByRequestIdsAndPod
-      }
+      ]
     }
   )
 
+  const classMethods = [
+    associate,
+
+    listWithLimitAndRandom,
+    countTotalRequests,
+    removeAll,
+    removeByRequestIdsAndPod
+  ]
+  addMethodsToModel(RequestVideoEvent, classMethods)
+
   return RequestVideoEvent
 }
 
 // ------------------------------ STATICS ------------------------------
 
 function associate (models) {
-  this.belongsTo(models.Video, {
+  RequestVideoEvent.belongsTo(models.Video, {
     foreignKey: {
       name: 'videoId',
       allowNull: false
@@ -61,14 +76,13 @@ function associate (models) {
   })
 }
 
-function countTotalRequests (callback) {
+countTotalRequests = function (callback) {
   const query = {}
-  return this.count(query).asCallback(callback)
+  return RequestVideoEvent.count(query).asCallback(callback)
 }
 
-function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
-  const self = this
-  const Pod = this.sequelize.models.Pod
+listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
+  const Pod = RequestVideoEvent['sequelize'].models.Pod
 
   // We make a join between videos and authors to find the podId of our video event requests
   const podJoins = 'INNER JOIN "Videos" ON "Videos"."authorId" = "Authors"."id" ' +
@@ -86,13 +100,13 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
       ],
       include: [
         {
-          model: self.sequelize.models.Video,
+          model: RequestVideoEvent['sequelize'].models.Video,
           include: [
             {
-              model: self.sequelize.models.Author,
+              model: RequestVideoEvent['sequelize'].models.Author,
               include: [
                 {
-                  model: self.sequelize.models.Pod,
+                  model: RequestVideoEvent['sequelize'].models.Pod,
                   where: {
                     id: {
                       $in: podIds
@@ -106,7 +120,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
       ]
     }
 
-    self.findAll(query).asCallback(function (err, requests) {
+    RequestVideoEvent.findAll(query).asCallback(function (err, requests) {
       if (err) return callback(err)
 
       const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod)
@@ -115,7 +129,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
   })
 }
 
-function removeByRequestIdsAndPod (ids, podId, callback) {
+removeByRequestIdsAndPod = function (ids, podId, callback) {
   const query = {
     where: {
       id: {
@@ -124,10 +138,10 @@ function removeByRequestIdsAndPod (ids, podId, callback) {
     },
     include: [
       {
-        model: this.sequelize.models.Video,
+        model: RequestVideoEvent['sequelize'].models.Video,
         include: [
           {
-            model: this.sequelize.models.Author,
+            model: RequestVideoEvent['sequelize'].models.Author,
             where: {
               podId
             }
@@ -137,12 +151,12 @@ function removeByRequestIdsAndPod (ids, podId, callback) {
     ]
   }
 
-  this.destroy(query).asCallback(callback)
+  RequestVideoEvent.destroy(query).asCallback(callback)
 }
 
-function removeAll (callback) {
+removeAll = function (callback) {
   // Delete all requests
-  this.truncate({ cascade: true }).asCallback(callback)
+  RequestVideoEvent.truncate({ cascade: true }).asCallback(callback)
 }
 
 // ---------------------------------------------------------------------------
diff --git a/server/models/request-video-qadu-interface.ts b/server/models/request-video-qadu-interface.ts
new file mode 100644 (file)
index 0000000..6fe34ee
--- /dev/null
@@ -0,0 +1,25 @@
+import * as Sequelize from 'sequelize'
+
+export namespace RequestVideoQaduMethods {
+  export type CountTotalRequests = (callback) => void
+  export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback) => void
+  export type RemoveByRequestIdsAndPod = (ids, podId, callback) => void
+  export type RemoveAll = (callback) => void
+}
+
+export interface RequestVideoQaduClass {
+  countTotalRequests: RequestVideoQaduMethods.CountTotalRequests
+  listWithLimitAndRandom: RequestVideoQaduMethods.ListWithLimitAndRandom
+  removeByRequestIdsAndPod: RequestVideoQaduMethods.RemoveByRequestIdsAndPod
+  removeAll: RequestVideoQaduMethods.RemoveAll
+}
+
+export interface RequestVideoQaduAttributes {
+  type: string
+}
+
+export interface RequestVideoQaduInstance extends Sequelize.Instance<RequestVideoQaduAttributes> {
+  id: number
+}
+
+export interface RequestVideoQaduModel extends RequestVideoQaduClass, Sequelize.Model<RequestVideoQaduInstance, RequestVideoQaduAttributes> {}
index 2b1ed07c9eb3a24820d2beeae078aa7abe6413d3..e914e06cd19f66ccf603767f5747c8e80cb99e83 100644 (file)
 */
 
 import { values } from 'lodash'
+import * as Sequelize from 'sequelize'
 
 import { REQUEST_VIDEO_QADU_TYPES } from '../initializers'
 
-// ---------------------------------------------------------------------------
+import { addMethodsToModel } from './utils'
+import {
+  RequestVideoQaduClass,
+  RequestVideoQaduInstance,
+  RequestVideoQaduAttributes,
+
+  RequestVideoQaduMethods
+} from './request-video-qadu-interface'
+
+let RequestVideoQadu: Sequelize.Model<RequestVideoQaduInstance, RequestVideoQaduAttributes>
+let countTotalRequests: RequestVideoQaduMethods.CountTotalRequests
+let listWithLimitAndRandom: RequestVideoQaduMethods.ListWithLimitAndRandom
+let removeByRequestIdsAndPod: RequestVideoQaduMethods.RemoveByRequestIdsAndPod
+let removeAll: RequestVideoQaduMethods.RemoveAll
 
-module.exports = function (sequelize, DataTypes) {
-  const RequestVideoQadu = sequelize.define('RequestVideoQadu',
+export default function (sequelize, DataTypes) {
+  RequestVideoQadu = sequelize.define('RequestVideoQadu',
     {
       type: {
         type: DataTypes.ENUM(values(REQUEST_VIDEO_QADU_TYPES)),
@@ -32,26 +46,27 @@ module.exports = function (sequelize, DataTypes) {
         {
           fields: [ 'videoId' ]
         }
-      ],
-      classMethods: {
-        associate,
-
-        listWithLimitAndRandom,
-
-        countTotalRequests,
-        removeAll,
-        removeByRequestIdsAndPod
-      }
+      ]
     }
   )
 
+  const classMethods = [
+    associate,
+
+    listWithLimitAndRandom,
+    countTotalRequests,
+    removeAll,
+    removeByRequestIdsAndPod
+  ]
+  addMethodsToModel(RequestVideoQadu, classMethods)
+
   return RequestVideoQadu
 }
 
 // ------------------------------ STATICS ------------------------------
 
 function associate (models) {
-  this.belongsTo(models.Pod, {
+  RequestVideoQadu.belongsTo(models.Pod, {
     foreignKey: {
       name: 'podId',
       allowNull: false
@@ -59,7 +74,7 @@ function associate (models) {
     onDelete: 'CASCADE'
   })
 
-  this.belongsTo(models.Video, {
+  RequestVideoQadu.belongsTo(models.Video, {
     foreignKey: {
       name: 'videoId',
       allowNull: false
@@ -68,14 +83,13 @@ function associate (models) {
   })
 }
 
-function countTotalRequests (callback) {
+countTotalRequests = function (callback) {
   const query = {}
-  return this.count(query).asCallback(callback)
+  return RequestVideoQadu.count(query).asCallback(callback)
 }
 
-function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
-  const self = this
-  const Pod = this.sequelize.models.Pod
+listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
+  const Pod = RequestVideoQadu['sequelize'].models.Pod
 
   Pod.listRandomPodIdsWithRequest(limitPods, 'RequestVideoQadus', function (err, podIds) {
     if (err) return callback(err)
@@ -86,7 +100,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
     const query = {
       include: [
         {
-          model: self.sequelize.models.Pod,
+          model: RequestVideoQadu['sequelize'].models.Pod,
           where: {
             id: {
               $in: podIds
@@ -94,12 +108,12 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
           }
         },
         {
-          model: self.sequelize.models.Video
+          model: RequestVideoQadu['sequelize'].models.Video
         }
       ]
     }
 
-    self.findAll(query).asCallback(function (err, requests) {
+    RequestVideoQadu.findAll(query).asCallback(function (err, requests) {
       if (err) return callback(err)
 
       const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod)
@@ -108,7 +122,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
   })
 }
 
-function removeByRequestIdsAndPod (ids, podId, callback) {
+removeByRequestIdsAndPod = function (ids, podId, callback) {
   const query = {
     where: {
       id: {
@@ -118,12 +132,12 @@ function removeByRequestIdsAndPod (ids, podId, callback) {
     }
   }
 
-  this.destroy(query).asCallback(callback)
+  RequestVideoQadu.destroy(query).asCallback(callback)
 }
 
-function removeAll (callback) {
+removeAll = function (callback) {
   // Delete all requests
-  this.truncate({ cascade: true }).asCallback(callback)
+  RequestVideoQadu.truncate({ cascade: true }).asCallback(callback)
 }
 
 // ---------------------------------------------------------------------------
index 672f79d115e88c2925885e7cfaa9d3671083b4df..18fa291fa4a9acae8cbced3b26f7754164ca0f6b 100644 (file)
@@ -1,11 +1,25 @@
 import { values } from 'lodash'
+import * as Sequelize from 'sequelize'
 
 import { REQUEST_ENDPOINTS } from '../initializers'
 
-// ---------------------------------------------------------------------------
+import { addMethodsToModel } from './utils'
+import {
+  RequestClass,
+  RequestInstance,
+  RequestAttributes,
+
+  RequestMethods
+} from './request-interface'
+
+let Request: Sequelize.Model<RequestInstance, RequestAttributes>
+let countTotalRequests: RequestMethods.CountTotalRequests
+let listWithLimitAndRandom: RequestMethods.ListWithLimitAndRandom
+let removeWithEmptyTo: RequestMethods.RemoveWithEmptyTo
+let removeAll: RequestMethods.RemoveAll
 
-module.exports = function (sequelize, DataTypes) {
-  const Request = sequelize.define('Request',
+export default function (sequelize, DataTypes) {
+  Request = sequelize.define('Request',
     {
       request: {
         type: DataTypes.JSON,
@@ -15,27 +29,27 @@ module.exports = function (sequelize, DataTypes) {
         type: DataTypes.ENUM(values(REQUEST_ENDPOINTS)),
         allowNull: false
       }
-    },
-    {
-      classMethods: {
-        associate,
-
-        listWithLimitAndRandom,
-
-        countTotalRequests,
-        removeAll,
-        removeWithEmptyTo
-      }
     }
   )
 
+  const classMethods = [
+    associate,
+
+    listWithLimitAndRandom,
+
+    countTotalRequests,
+    removeAll,
+    removeWithEmptyTo
+  ]
+  addMethodsToModel(Request, classMethods)
+
   return Request
 }
 
 // ------------------------------ STATICS ------------------------------
 
 function associate (models) {
-  this.belongsToMany(models.Pod, {
+  Request.belongsToMany(models.Pod, {
     foreignKey: {
       name: 'requestId',
       allowNull: false
@@ -45,19 +59,18 @@ function associate (models) {
   })
 }
 
-function countTotalRequests (callback) {
+countTotalRequests = function (callback) {
   // We need to include Pod because there are no cascade delete when a pod is removed
   // So we could count requests that do not have existing pod anymore
   const query = {
-    include: [ this.sequelize.models.Pod ]
+    include: [ Request['sequelize'].models.Pod ]
   }
 
-  return this.count(query).asCallback(callback)
+  return Request.count(query).asCallback(callback)
 }
 
-function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
-  const self = this
-  const Pod = this.sequelize.models.Pod
+listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
+  const Pod = Request['sequelize'].models.Pod
 
   Pod.listRandomPodIdsWithRequest(limitPods, 'RequestToPods', function (err, podIds) {
     if (err) return callback(err)
@@ -73,7 +86,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
       ],
       include: [
         {
-          model: self.sequelize.models.Pod,
+          model: Request['sequelize'].models.Pod,
           where: {
             id: {
               $in: podIds
@@ -83,7 +96,7 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
       ]
     }
 
-    self.findAll(query).asCallback(function (err, requests) {
+    Request.findAll(query).asCallback(function (err, requests) {
       if (err) return callback(err)
 
       const requestsGrouped = groupAndTruncateRequests(requests, limitRequestsPerPod)
@@ -92,25 +105,25 @@ function listWithLimitAndRandom (limitPods, limitRequestsPerPod, callback) {
   })
 }
 
-function removeAll (callback) {
+removeAll = function (callback) {
   // Delete all requests
-  this.truncate({ cascade: true }).asCallback(callback)
+  Request.truncate({ cascade: true }).asCallback(callback)
 }
 
-function removeWithEmptyTo (callback) {
+removeWithEmptyTo = function (callback) {
   if (!callback) callback = function () { /* empty */ }
 
   const query = {
     where: {
       id: {
         $notIn: [
-          this.sequelize.literal('SELECT "requestId" FROM "RequestToPods"')
+          Sequelize.literal('SELECT "requestId" FROM "RequestToPods"')
         ]
       }
     }
   }
 
-  this.destroy(query).asCallback(callback)
+  Request.destroy(query).asCallback(callback)
 }
 
 // ---------------------------------------------------------------------------
diff --git a/server/models/tag-interface.ts b/server/models/tag-interface.ts
new file mode 100644 (file)
index 0000000..f96e1e9
--- /dev/null
@@ -0,0 +1,19 @@
+import * as Sequelize from 'sequelize'
+
+export namespace TagMethods {
+  export type FindOrCreateTags = (tags, transaction, callback) => void
+}
+
+export interface TagClass {
+  findOrCreateTags: TagMethods.FindOrCreateTags
+}
+
+export interface TagAttributes {
+  name: string
+}
+
+export interface TagInstance extends TagClass, TagAttributes, Sequelize.Instance<TagAttributes> {
+  id: number
+}
+
+export interface TagModel extends TagClass, Sequelize.Model<TagInstance, TagAttributes> {}
index 85a0442d203c14ec9221d99f7047807aafa64d20..b2a9c9f81ddbfb3a8bd853ef735a73a3ded95584 100644 (file)
@@ -1,9 +1,20 @@
 import { each } from 'async'
+import * as Sequelize from 'sequelize'
 
-// ---------------------------------------------------------------------------
+import { addMethodsToModel } from './utils'
+import {
+  TagClass,
+  TagInstance,
+  TagAttributes,
+
+  TagMethods
+} from './tag-interface'
 
-module.exports = function (sequelize, DataTypes) {
-  const Tag = sequelize.define('Tag',
+let Tag: Sequelize.Model<TagInstance, TagAttributes>
+let findOrCreateTags: TagMethods.FindOrCreateTags
+
+export default function (sequelize, DataTypes) {
+  Tag = sequelize.define('Tag',
     {
       name: {
         type: DataTypes.STRING,
@@ -17,35 +28,36 @@ module.exports = function (sequelize, DataTypes) {
           fields: [ 'name' ],
           unique: true
         }
-      ],
-      classMethods: {
-        associate,
-
-        findOrCreateTags
-      }
+      ]
     }
   )
 
+  const classMethods = [
+    associate,
+
+    findOrCreateTags
+  ]
+  addMethodsToModel(Tag, classMethods)
+
   return Tag
 }
 
 // ---------------------------------------------------------------------------
 
 function associate (models) {
-  this.belongsToMany(models.Video, {
+  Tag.belongsToMany(models.Video, {
     foreignKey: 'tagId',
     through: models.VideoTag,
     onDelete: 'cascade'
   })
 }
 
-function findOrCreateTags (tags, transaction, callback) {
+findOrCreateTags = function (tags, transaction, callback) {
   if (!callback) {
     callback = transaction
     transaction = null
   }
 
-  const self = this
   const tagInstances = []
 
   each(tags, function (tag, callbackEach) {
@@ -60,7 +72,7 @@ function findOrCreateTags (tags, transaction, callback) {
 
     if (transaction) query.transaction = transaction
 
-    self.findOrCreate(query).asCallback(function (err, res) {
+    Tag.findOrCreate(query).asCallback(function (err, res) {
       if (err) return callbackEach(err)
 
       // res = [ tag, isCreated ]
diff --git a/server/models/user-interface.ts b/server/models/user-interface.ts
new file mode 100644 (file)
index 0000000..a504f42
--- /dev/null
@@ -0,0 +1,45 @@
+import * as Sequelize from 'sequelize'
+
+export namespace UserMethods {
+  export type IsPasswordMatch = (password, callback) => void
+  export type ToFormatedJSON = () => void
+  export type IsAdmin = () => boolean
+
+  export type CountTotal = (callback) => void
+  export type GetByUsername = (username) => any
+  export type List = (callback) => void
+  export type ListForApi = (start, count, sort, callback) => void
+  export type LoadById = (id, callback) => void
+  export type LoadByUsername = (username, callback) => void
+  export type LoadByUsernameOrEmail = (username, email, callback) => void
+}
+
+export interface UserClass {
+  isPasswordMatch: UserMethods.IsPasswordMatch,
+  toFormatedJSON: UserMethods.ToFormatedJSON,
+  isAdmin: UserMethods.IsAdmin,
+
+  countTotal: UserMethods.CountTotal,
+  getByUsername: UserMethods.GetByUsername,
+  list: UserMethods.List,
+  listForApi: UserMethods.ListForApi,
+  loadById: UserMethods.LoadById,
+  loadByUsername: UserMethods.LoadByUsername,
+  loadByUsernameOrEmail: UserMethods.LoadByUsernameOrEmail
+}
+
+export interface UserAttributes {
+  password: string
+  username: string
+  email: string
+  displayNSFW?: boolean
+  role: string
+}
+
+export interface UserInstance extends UserClass, UserAttributes, Sequelize.Instance<UserAttributes> {
+  id: number
+  createdAt: Date
+  updatedAt: Date
+}
+
+export interface UserModel extends UserClass, Sequelize.Model<UserInstance, UserAttributes> {}
diff --git a/server/models/user-video-rate-interface.ts b/server/models/user-video-rate-interface.ts
new file mode 100644 (file)
index 0000000..57d2e2b
--- /dev/null
@@ -0,0 +1,21 @@
+import * as Sequelize from 'sequelize'
+
+export namespace UserVideoRateMethods {
+  export type Load = (userId, videoId, transaction, callback) => void
+}
+
+export interface UserVideoRateClass {
+  load: UserVideoRateMethods.Load
+}
+
+export interface UserVideoRateAttributes {
+  type: string
+}
+
+export interface UserVideoRateInstance extends Sequelize.Instance<UserVideoRateAttributes> {
+  id: number
+  createdAt: Date
+  updatedAt: Date
+}
+
+export interface UserVideoRateModel extends UserVideoRateClass, Sequelize.Model<UserVideoRateInstance, UserVideoRateAttributes> {}
index 6603c7862d6f3e7f9943508598a763d7c55d63ba..87886d8d00960c053cbd29918ab4a63af2dfa5b1 100644 (file)
@@ -3,13 +3,24 @@
 
 */
 import { values } from 'lodash'
+import * as Sequelize from 'sequelize'
 
 import { VIDEO_RATE_TYPES } from '../initializers'
 
-// ---------------------------------------------------------------------------
+import { addMethodsToModel } from './utils'
+import {
+  UserVideoRateClass,
+  UserVideoRateInstance,
+  UserVideoRateAttributes,
 
-module.exports = function (sequelize, DataTypes) {
-  const UserVideoRate = sequelize.define('UserVideoRate',
+  UserVideoRateMethods
+} from './user-video-rate-interface'
+
+let UserVideoRate: Sequelize.Model<UserVideoRateInstance, UserVideoRateAttributes>
+let load: UserVideoRateMethods.Load
+
+export default function (sequelize, DataTypes) {
+  UserVideoRate = sequelize.define('UserVideoRate',
     {
       type: {
         type: DataTypes.ENUM(values(VIDEO_RATE_TYPES)),
@@ -22,22 +33,24 @@ module.exports = function (sequelize, DataTypes) {
           fields: [ 'videoId', 'userId', 'type' ],
           unique: true
         }
-      ],
-      classMethods: {
-        associate,
-
-        load
-      }
+      ]
     }
   )
 
+  const classMethods = [
+    associate,
+
+    load
+  ]
+  addMethodsToModel(UserVideoRate, classMethods)
+
   return UserVideoRate
 }
 
 // ------------------------------ STATICS ------------------------------
 
 function associate (models) {
-  this.belongsTo(models.Video, {
+  UserVideoRate.belongsTo(models.Video, {
     foreignKey: {
       name: 'videoId',
       allowNull: false
@@ -45,7 +58,7 @@ function associate (models) {
     onDelete: 'CASCADE'
   })
 
-  this.belongsTo(models.User, {
+  UserVideoRate.belongsTo(models.User, {
     foreignKey: {
       name: 'userId',
       allowNull: false
@@ -54,21 +67,14 @@ function associate (models) {
   })
 }
 
-function load (userId, videoId, transaction, callback) {
-  if (!callback) {
-    callback = transaction
-    transaction = null
-  }
-
-  const query = {
+load = function (userId, videoId, transaction, callback) {
+  const options: Sequelize.FindOptions = {
     where: {
       userId,
       videoId
     }
   }
-
-  const options: any = {}
   if (transaction) options.transaction = transaction
 
-  return this.findOne(query, options).asCallback(callback)
+  return UserVideoRate.findOne(options).asCallback(callback)
 }
index d63a50cc4152428ac5e802792d3ea3c1cb5f7ab5..12ddaaeb7ec2a861e27d276abb71fd82b9cb5c31 100644 (file)
@@ -1,4 +1,5 @@
 import { values } from 'lodash'
+import * as Sequelize from 'sequelize'
 
 import { getSort } from './utils'
 import { USER_ROLES } from '../initializers'
@@ -10,10 +11,29 @@ import {
   isUserDisplayNSFWValid
 } from '../helpers'
 
-// ---------------------------------------------------------------------------
-
-module.exports = function (sequelize, DataTypes) {
-  const User = sequelize.define('User',
+import { addMethodsToModel } from './utils'
+import {
+  UserClass,
+  UserInstance,
+  UserAttributes,
+
+  UserMethods
+} from './user-interface'
+
+let User: Sequelize.Model<UserInstance, UserAttributes>
+let isPasswordMatch: UserMethods.IsPasswordMatch
+let toFormatedJSON: UserMethods.ToFormatedJSON
+let isAdmin: UserMethods.IsAdmin
+let countTotal: UserMethods.CountTotal
+let getByUsername: UserMethods.GetByUsername
+let list: UserMethods.List
+let listForApi: UserMethods.ListForApi
+let loadById: UserMethods.LoadById
+let loadByUsername: UserMethods.LoadByUsername
+let loadByUsernameOrEmail: UserMethods.LoadByUsernameOrEmail
+
+export default function (sequelize, DataTypes) {
+  User = sequelize.define('User',
     {
       password: {
         type: DataTypes.STRING,
@@ -69,22 +89,6 @@ module.exports = function (sequelize, DataTypes) {
           unique: true
         }
       ],
-      classMethods: {
-        associate,
-
-        countTotal,
-        getByUsername,
-        list,
-        listForApi,
-        loadById,
-        loadByUsername,
-        loadByUsernameOrEmail
-      },
-      instanceMethods: {
-        isPasswordMatch,
-        toFormatedJSON,
-        isAdmin
-      },
       hooks: {
         beforeCreate: beforeCreateOrUpdate,
         beforeUpdate: beforeCreateOrUpdate
@@ -92,26 +96,46 @@ module.exports = function (sequelize, DataTypes) {
     }
   )
 
+  const classMethods = [
+    associate,
+
+    countTotal,
+    getByUsername,
+    list,
+    listForApi,
+    loadById,
+    loadByUsername,
+    loadByUsernameOrEmail
+  ]
+  const instanceMethods = [
+    isPasswordMatch,
+    toFormatedJSON,
+    isAdmin
+  ]
+  addMethodsToModel(User, classMethods, instanceMethods)
+
   return User
 }
 
-function beforeCreateOrUpdate (user, options, next) {
-  cryptPassword(user.password, function (err, hash) {
-    if (err) return next(err)
+function beforeCreateOrUpdate (user, options) {
+  return new Promise(function (resolve, reject) {
+    cryptPassword(user.password, function (err, hash) {
+      if (err) return reject(err)
 
-    user.password = hash
+      user.password = hash
 
-    return next()
+      return resolve()
+    })
   })
 }
 
 // ------------------------------ METHODS ------------------------------
 
-function isPasswordMatch (password, callback) {
+isPasswordMatch = function (password, callback) {
   return comparePassword(password, this.password, callback)
 }
 
-function toFormatedJSON () {
+toFormatedJSON = function () {
   return {
     id: this.id,
     username: this.username,
@@ -122,76 +146,76 @@ function toFormatedJSON () {
   }
 }
 
-function isAdmin () {
+isAdmin = function () {
   return this.role === USER_ROLES.ADMIN
 }
 
 // ------------------------------ STATICS ------------------------------
 
 function associate (models) {
-  this.hasOne(models.Author, {
+  User.hasOne(models.Author, {
     foreignKey: 'userId',
     onDelete: 'cascade'
   })
 
-  this.hasMany(models.OAuthToken, {
+  User.hasMany(models.OAuthToken, {
     foreignKey: 'userId',
     onDelete: 'cascade'
   })
 }
 
-function countTotal (callback) {
+countTotal = function (callback) {
   return this.count().asCallback(callback)
 }
 
-function getByUsername (username) {
+getByUsername = function (username) {
   const query = {
     where: {
       username: username
     }
   }
 
-  return this.findOne(query)
+  return User.findOne(query)
 }
 
-function list (callback) {
-  return this.find().asCallback(callback)
+list = function (callback) {
+  return User.find().asCallback(callback)
 }
 
-function listForApi (start, count, sort, callback) {
+listForApi = function (start, count, sort, callback) {
   const query = {
     offset: start,
     limit: count,
     order: [ getSort(sort) ]
   }
 
-  return this.findAndCountAll(query).asCallback(function (err, result) {
+  return User.findAndCountAll(query).asCallback(function (err, result) {
     if (err) return callback(err)
 
     return callback(null, result.rows, result.count)
   })
 }
 
-function loadById (id, callback) {
-  return this.findById(id).asCallback(callback)
+loadById = function (id, callback) {
+  return User.findById(id).asCallback(callback)
 }
 
-function loadByUsername (username, callback) {
+loadByUsername = function (username, callback) {
   const query = {
     where: {
       username: username
     }
   }
 
-  return this.findOne(query).asCallback(callback)
+  return User.findOne(query).asCallback(callback)
 }
 
-function loadByUsernameOrEmail (username, email, callback) {
+loadByUsernameOrEmail = function (username, email, callback) {
   const query = {
     where: {
       $or: [ { username }, { email } ]
     }
   }
 
-  return this.findOne(query).asCallback(callback)
+  return User.findOne(query).asCallback(callback)
 }
index 601811913d5d24dde4aedcd7486882638ab3ef86..fd84a92399e5f2aaefab3ef826d022f4e4f5be32 100644 (file)
@@ -14,8 +14,14 @@ function getSort (value) {
   return [ field, direction ]
 }
 
+function addMethodsToModel (model: any, classMethods: Function[], instanceMethods: Function[] = []) {
+  classMethods.forEach(m => model[m.name] = m)
+  instanceMethods.forEach(m => model.prototype[m.name] = m)
+}
+
 // ---------------------------------------------------------------------------
 
 export {
+  addMethodsToModel,
   getSort
 }
diff --git a/server/models/video-abuse-interface.ts b/server/models/video-abuse-interface.ts
new file mode 100644 (file)
index 0000000..9b77fc6
--- /dev/null
@@ -0,0 +1,24 @@
+import * as Sequelize from 'sequelize'
+
+export namespace VideoAbuseMethods {
+  export type toFormatedJSON = () => void
+
+  export type ListForApi = (start, count, sort, callback) => void
+}
+
+export interface VideoAbuseClass {
+  listForApi: VideoAbuseMethods.ListForApi
+}
+
+export interface VideoAbuseAttributes {
+  reporterUsername: string
+  reason: string
+}
+
+export interface VideoAbuseInstance extends Sequelize.Instance<VideoAbuseAttributes> {
+  id: number
+  createdAt: Date
+  updatedAt: Date
+}
+
+export interface VideoAbuseModel extends VideoAbuseClass, Sequelize.Model<VideoAbuseInstance, VideoAbuseAttributes> {}
index 2a18a293d09cf934534a8e08975ebb1eb08c2615..92168439c54f5157fddac5d2f561712923c6cd18 100644 (file)
@@ -1,9 +1,22 @@
+import * as Sequelize from 'sequelize'
+
 import { CONFIG } from '../initializers'
 import { isVideoAbuseReporterUsernameValid, isVideoAbuseReasonValid } from '../helpers'
-import { getSort } from './utils'
 
-module.exports = function (sequelize, DataTypes) {
-  const VideoAbuse = sequelize.define('VideoAbuse',
+import { addMethodsToModel, getSort } from './utils'
+import {
+  VideoAbuseClass,
+  VideoAbuseInstance,
+  VideoAbuseAttributes,
+
+  VideoAbuseMethods
+} from './video-abuse-interface'
+
+let VideoAbuse: Sequelize.Model<VideoAbuseInstance, VideoAbuseAttributes>
+let listForApi: VideoAbuseMethods.ListForApi
+
+export default function (sequelize, DataTypes) {
+  VideoAbuse = sequelize.define('VideoAbuse',
     {
       reporterUsername: {
         type: DataTypes.STRING,
@@ -34,25 +47,51 @@ module.exports = function (sequelize, DataTypes) {
         {
           fields: [ 'reporterPodId' ]
         }
-      ],
-      classMethods: {
-        associate,
-
-        listForApi
-      },
-      instanceMethods: {
-        toFormatedJSON
-      }
+      ]
     }
   )
 
+  const classMethods = [
+    associate,
+
+    listForApi
+  ]
+  const instanceMethods = [
+    toFormatedJSON
+  ]
+  addMethodsToModel(VideoAbuse, classMethods, instanceMethods)
+
   return VideoAbuse
 }
 
-// ---------------------------------------------------------------------------
+// ------------------------------ METHODS ------------------------------
+
+function toFormatedJSON () {
+  let reporterPodHost
+
+  if (this.Pod) {
+    reporterPodHost = this.Pod.host
+  } else {
+    // It means it's our video
+    reporterPodHost = CONFIG.WEBSERVER.HOST
+  }
+
+  const json = {
+    id: this.id,
+    reporterPodHost,
+    reason: this.reason,
+    reporterUsername: this.reporterUsername,
+    videoId: this.videoId,
+    createdAt: this.createdAt
+  }
+
+  return json
+}
+
+// ------------------------------ STATICS ------------------------------
 
 function associate (models) {
-  this.belongsTo(models.Pod, {
+  VideoAbuse.belongsTo(models.Pod, {
     foreignKey: {
       name: 'reporterPodId',
       allowNull: true
@@ -60,7 +99,7 @@ function associate (models) {
     onDelete: 'cascade'
   })
 
-  this.belongsTo(models.Video, {
+  VideoAbuse.belongsTo(models.Video, {
     foreignKey: {
       name: 'videoId',
       allowNull: false
@@ -69,44 +108,24 @@ function associate (models) {
   })
 }
 
-function listForApi (start, count, sort, callback) {
+listForApi = function (start, count, sort, callback) {
   const query = {
     offset: start,
     limit: count,
     order: [ getSort(sort) ],
     include: [
       {
-        model: this.sequelize.models.Pod,
+        model: VideoAbuse['sequelize'].models.Pod,
         required: false
       }
     ]
   }
 
-  return this.findAndCountAll(query).asCallback(function (err, result) {
+  return VideoAbuse.findAndCountAll(query).asCallback(function (err, result) {
     if (err) return callback(err)
 
     return callback(null, result.rows, result.count)
   })
 }
 
-function toFormatedJSON () {
-  let reporterPodHost
-
-  if (this.Pod) {
-    reporterPodHost = this.Pod.host
-  } else {
-    // It means it's our video
-    reporterPodHost = CONFIG.WEBSERVER.HOST
-  }
-
-  const json = {
-    id: this.id,
-    reporterPodHost,
-    reason: this.reason,
-    reporterUsername: this.reporterUsername,
-    videoId: this.videoId,
-    createdAt: this.createdAt
-  }
 
-  return json
-}
diff --git a/server/models/video-blacklist-interface.ts b/server/models/video-blacklist-interface.ts
new file mode 100644 (file)
index 0000000..ae2cd67
--- /dev/null
@@ -0,0 +1,31 @@
+import * as Sequelize from 'sequelize'
+
+export namespace BlacklistedVideoMethods {
+  export type ToFormatedJSON = () => void
+
+  export type CountTotal = (callback) => void
+  export type List = (callback) => void
+  export type ListForApi = (start, count, sort, callback) => void
+  export type LoadById = (id, callback) => void
+  export type LoadByVideoId = (id, callback) => void
+}
+
+export interface BlacklistedVideoClass {
+  toFormatedJSON: BlacklistedVideoMethods.ToFormatedJSON
+  countTotal: BlacklistedVideoMethods.CountTotal
+  list: BlacklistedVideoMethods.List
+  listForApi: BlacklistedVideoMethods.ListForApi
+  loadById: BlacklistedVideoMethods.LoadById
+  loadByVideoId: BlacklistedVideoMethods.LoadByVideoId
+}
+
+export interface BlacklistedVideoAttributes {
+}
+
+export interface BlacklistedVideoInstance extends BlacklistedVideoClass, BlacklistedVideoAttributes, Sequelize.Instance<BlacklistedVideoAttributes> {
+  id: number
+  createdAt: Date
+  updatedAt: Date
+}
+
+export interface BlacklistedVideoModel extends BlacklistedVideoClass, Sequelize.Model<BlacklistedVideoInstance, BlacklistedVideoAttributes> {}
index 1f00702c7c955bf369f8f88da072f86a4dc4d069..fe72d5d46eb46be11a911f0c32270e2d661d9691 100644 (file)
@@ -1,9 +1,24 @@
-import { getSort } from './utils'
-
-// ---------------------------------------------------------------------------
-
-module.exports = function (sequelize, DataTypes) {
-  const BlacklistedVideo = sequelize.define('BlacklistedVideo',
+import * as Sequelize from 'sequelize'
+
+import { addMethodsToModel, getSort } from './utils'
+import {
+  BlacklistedVideoClass,
+  BlacklistedVideoInstance,
+  BlacklistedVideoAttributes,
+
+  BlacklistedVideoMethods
+} from './video-blacklist-interface'
+
+let BlacklistedVideo: Sequelize.Model<BlacklistedVideoInstance, BlacklistedVideoAttributes>
+let toFormatedJSON: BlacklistedVideoMethods.ToFormatedJSON
+let countTotal: BlacklistedVideoMethods.CountTotal
+let list: BlacklistedVideoMethods.List
+let listForApi: BlacklistedVideoMethods.ListForApi
+let loadById: BlacklistedVideoMethods.LoadById
+let loadByVideoId: BlacklistedVideoMethods.LoadByVideoId
+
+export default function (sequelize, DataTypes) {
+  BlacklistedVideo = sequelize.define('BlacklistedVideo',
     {},
     {
       indexes: [
@@ -11,29 +26,30 @@ module.exports = function (sequelize, DataTypes) {
           fields: [ 'videoId' ],
           unique: true
         }
-      ],
-      classMethods: {
-        associate,
-
-        countTotal,
-        list,
-        listForApi,
-        loadById,
-        loadByVideoId
-      },
-      instanceMethods: {
-        toFormatedJSON
-      },
-      hooks: {}
+      ]
     }
   )
 
+  const classMethods = [
+    associate,
+
+    countTotal,
+    list,
+    listForApi,
+    loadById,
+    loadByVideoId
+  ]
+  const instanceMethods = [
+    toFormatedJSON
+  ]
+  addMethodsToModel(BlacklistedVideo, classMethods, instanceMethods)
+
   return BlacklistedVideo
 }
 
 // ------------------------------ METHODS ------------------------------
 
-function toFormatedJSON () {
+toFormatedJSON = function () {
   return {
     id: this.id,
     videoId: this.videoId,
@@ -44,44 +60,44 @@ function toFormatedJSON () {
 // ------------------------------ STATICS ------------------------------
 
 function associate (models) {
-  this.belongsTo(models.Video, {
+  BlacklistedVideo.belongsTo(models.Video, {
     foreignKey: 'videoId',
     onDelete: 'cascade'
   })
 }
 
-function countTotal (callback) {
-  return this.count().asCallback(callback)
+countTotal = function (callback) {
+  return BlacklistedVideo.count().asCallback(callback)
 }
 
-function list (callback) {
-  return this.findAll().asCallback(callback)
+list = function (callback) {
+  return BlacklistedVideo.findAll().asCallback(callback)
 }
 
-function listForApi (start, count, sort, callback) {
+listForApi = function (start, count, sort, callback) {
   const query = {
     offset: start,
     limit: count,
     order: [ getSort(sort) ]
   }
 
-  return this.findAndCountAll(query).asCallback(function (err, result) {
+  return BlacklistedVideo.findAndCountAll(query).asCallback(function (err, result) {
     if (err) return callback(err)
 
     return callback(null, result.rows, result.count)
   })
 }
 
-function loadById (id, callback) {
-  return this.findById(id).asCallback(callback)
+loadById = function (id, callback) {
+  return BlacklistedVideo.findById(id).asCallback(callback)
 }
 
-function loadByVideoId (id, callback) {
+loadByVideoId = function (id, callback) {
   const query = {
     where: {
       videoId: id
     }
   }
 
-  return this.find(query).asCallback(callback)
+  return BlacklistedVideo.find(query).asCallback(callback)
 }
diff --git a/server/models/video-interface.ts b/server/models/video-interface.ts
new file mode 100644 (file)
index 0000000..b8dbeea
--- /dev/null
@@ -0,0 +1,75 @@
+import * as Sequelize from 'sequelize'
+
+export namespace VideoMethods {
+  export type GenerateMagnetUri = () => void
+  export type GetVideoFilename = () => void
+  export type GetThumbnailName = () => void
+  export type GetPreviewName = () => void
+  export type GetTorrentName = () => void
+  export type IsOwned = () => void
+  export type ToFormatedJSON = () => void
+  export type ToAddRemoteJSON = (callback) => void
+  export type ToUpdateRemoteJSON = (callback) => void
+  export type TranscodeVideofile = (callback) => void
+
+  export type GenerateThumbnailFromData = (video, thumbnailData, callback) => void
+  export type GetDurationFromFile = (videoPath, callback) => void
+  export type List = (callback) => void
+  export type ListForApi = (start, count, sort, callback) => void
+  export type LoadByHostAndRemoteId = (fromHost, remoteId, callback) => void
+  export type ListOwnedAndPopulateAuthorAndTags = (callback) => void
+  export type ListOwnedByAuthor = (author, callback) => void
+  export type Load = (id, callback) => void
+  export type LoadAndPopulateAuthor = (id, callback) => void
+  export type LoadAndPopulateAuthorAndPodAndTags = (id, callback) => void
+  export type SearchAndPopulateAuthorAndPodAndTags = (value, field, start, count, sort, callback) => void
+}
+
+export interface VideoClass {
+  generateMagnetUri: VideoMethods.GenerateMagnetUri
+  getVideoFilename: VideoMethods.GetVideoFilename
+  getThumbnailName: VideoMethods.GetThumbnailName
+  getPreviewName: VideoMethods.GetPreviewName
+  getTorrentName: VideoMethods.GetTorrentName
+  isOwned: VideoMethods.IsOwned
+  toFormatedJSON: VideoMethods.ToFormatedJSON
+  toAddRemoteJSON: VideoMethods.ToAddRemoteJSON
+  toUpdateRemoteJSON: VideoMethods.ToUpdateRemoteJSON
+  transcodeVideofile: VideoMethods.TranscodeVideofile
+
+  generateThumbnailFromData: VideoMethods.GenerateThumbnailFromData
+  getDurationFromFile: VideoMethods.GetDurationFromFile
+  list: VideoMethods.List
+  listForApi: VideoMethods.ListForApi
+  loadByHostAndRemoteId: VideoMethods.LoadByHostAndRemoteId
+  listOwnedAndPopulateAuthorAndTags: VideoMethods.ListOwnedAndPopulateAuthorAndTags
+  listOwnedByAuthor: VideoMethods.ListOwnedByAuthor
+  load: VideoMethods.Load
+  loadAndPopulateAuthor: VideoMethods.LoadAndPopulateAuthor
+  loadAndPopulateAuthorAndPodAndTags: VideoMethods.LoadAndPopulateAuthorAndPodAndTags
+  searchAndPopulateAuthorAndPodAndTags: VideoMethods.SearchAndPopulateAuthorAndPodAndTags
+}
+
+export interface VideoAttributes {
+  name: string
+  extname: string
+  remoteId: string
+  category: number
+  licence: number
+  language: number
+  nsfw: boolean
+  description: string
+  infoHash?: string
+  duration: number
+  views?: number
+  likes?: number
+  dislikes?: number
+}
+
+export interface VideoInstance extends VideoClass, VideoAttributes, Sequelize.Instance<VideoAttributes> {
+  id: string
+  createdAt: Date
+  updatedAt: Date
+}
+
+export interface VideoModel extends VideoClass, Sequelize.Model<VideoInstance, VideoAttributes> {}
diff --git a/server/models/video-tag-interface.ts b/server/models/video-tag-interface.ts
new file mode 100644 (file)
index 0000000..468827b
--- /dev/null
@@ -0,0 +1,18 @@
+import * as Sequelize from 'sequelize'
+
+export namespace VideoTagMethods {
+}
+
+export interface VideoTagClass {
+}
+
+export interface VideoTagAttributes {
+}
+
+export interface VideoTagInstance extends Sequelize.Instance<VideoTagAttributes> {
+  id: number
+  createdAt: Date
+  updatedAt: Date
+}
+
+export interface VideoTagModel extends VideoTagClass, Sequelize.Model<VideoTagInstance, VideoTagAttributes> {}
index 83ff6053fb0f718869edee4ee8ae6bedc740f799..2ccaf820d361eeff5cea1c0843b2710438ecfd20 100644 (file)
@@ -1,5 +1,18 @@
-module.exports = function (sequelize, DataTypes) {
-  const VideoTag = sequelize.define('VideoTag', {}, {
+import * as Sequelize from 'sequelize'
+
+import { addMethodsToModel } from './utils'
+import {
+  VideoTagClass,
+  VideoTagInstance,
+  VideoTagAttributes,
+
+  VideoTagMethods
+} from './video-tag-interface'
+
+let VideoTag: Sequelize.Model<VideoTagInstance, VideoTagAttributes>
+
+export default function (sequelize, DataTypes) {
+  VideoTag = sequelize.define('VideoTag', {}, {
     indexes: [
       {
         fields: [ 'videoId' ]
index 1e29f13555022b8b43e2cf10d4707d2fe10f4dda..9284dfeba10c83ffbf7159ab68943cc153fe5dcb 100644 (file)
@@ -8,8 +8,9 @@ import { map, values } from 'lodash'
 import { parallel, series } from 'async'
 import parseTorrent = require('parse-torrent')
 import { join } from 'path'
+import * as Sequelize from 'sequelize'
 
-const db = require('../initializers/database')
+import { database as db } from '../initializers/database'
 import {
   logger,
   isVideoNameValid,
@@ -32,12 +33,42 @@ import {
   THUMBNAILS_SIZE
 } from '../initializers'
 import { JobScheduler, removeVideoToFriends } from '../lib'
-import { getSort } from './utils'
 
-// ---------------------------------------------------------------------------
-
-module.exports = function (sequelize, DataTypes) {
-  const Video = sequelize.define('Video',
+import { addMethodsToModel, getSort } from './utils'
+import {
+  VideoClass,
+  VideoInstance,
+  VideoAttributes,
+
+  VideoMethods
+} from './video-interface'
+
+let Video: Sequelize.Model<VideoInstance, VideoAttributes>
+let generateMagnetUri: VideoMethods.GenerateMagnetUri
+let getVideoFilename: VideoMethods.GetVideoFilename
+let getThumbnailName: VideoMethods.GetThumbnailName
+let getPreviewName: VideoMethods.GetPreviewName
+let getTorrentName: VideoMethods.GetTorrentName
+let isOwned: VideoMethods.IsOwned
+let toFormatedJSON: VideoMethods.ToFormatedJSON
+let toAddRemoteJSON: VideoMethods.ToAddRemoteJSON
+let toUpdateRemoteJSON: VideoMethods.ToUpdateRemoteJSON
+let transcodeVideofile: VideoMethods.TranscodeVideofile
+
+let generateThumbnailFromData: VideoMethods.GenerateThumbnailFromData
+let getDurationFromFile: VideoMethods.GetDurationFromFile
+let list: VideoMethods.List
+let listForApi: VideoMethods.ListForApi
+let loadByHostAndRemoteId: VideoMethods.LoadByHostAndRemoteId
+let listOwnedAndPopulateAuthorAndTags: VideoMethods.ListOwnedAndPopulateAuthorAndTags
+let listOwnedByAuthor: VideoMethods.ListOwnedByAuthor
+let load: VideoMethods.Load
+let loadAndPopulateAuthor: VideoMethods.LoadAndPopulateAuthor
+let loadAndPopulateAuthorAndPodAndTags: VideoMethods.LoadAndPopulateAuthorAndPodAndTags
+let searchAndPopulateAuthorAndPodAndTags: VideoMethods.SearchAndPopulateAuthorAndPodAndTags
+
+export default function (sequelize, DataTypes) {
+  Video = sequelize.define('Video',
     {
       id: {
         type: DataTypes.UUID,
@@ -194,34 +225,6 @@ module.exports = function (sequelize, DataTypes) {
           fields: [ 'likes' ]
         }
       ],
-      classMethods: {
-        associate,
-
-        generateThumbnailFromData,
-        getDurationFromFile,
-        list,
-        listForApi,
-        listOwnedAndPopulateAuthorAndTags,
-        listOwnedByAuthor,
-        load,
-        loadByHostAndRemoteId,
-        loadAndPopulateAuthor,
-        loadAndPopulateAuthorAndPodAndTags,
-        searchAndPopulateAuthorAndPodAndTags
-      },
-      instanceMethods: {
-        generateMagnetUri,
-        getVideoFilename,
-        getThumbnailName,
-        getPreviewName,
-        getTorrentName,
-        isOwned,
-        toFormatedJSON,
-        toAddRemoteJSON,
-        toUpdateRemoteJSON,
-        transcodeVideofile,
-        removeFromBlacklist
-      },
       hooks: {
         beforeValidate,
         beforeCreate,
@@ -230,99 +233,139 @@ module.exports = function (sequelize, DataTypes) {
     }
   )
 
+  const classMethods = [
+    associate,
+
+    generateThumbnailFromData,
+    getDurationFromFile,
+    list,
+    listForApi,
+    listOwnedAndPopulateAuthorAndTags,
+    listOwnedByAuthor,
+    load,
+    loadByHostAndRemoteId,
+    loadAndPopulateAuthor,
+    loadAndPopulateAuthorAndPodAndTags,
+    searchAndPopulateAuthorAndPodAndTags
+  ]
+  const instanceMethods = [
+    generateMagnetUri,
+    getVideoFilename,
+    getThumbnailName,
+    getPreviewName,
+    getTorrentName,
+    isOwned,
+    toFormatedJSON,
+    toAddRemoteJSON,
+    toUpdateRemoteJSON,
+    transcodeVideofile,
+    removeFromBlacklist
+  ]
+  addMethodsToModel(Video, classMethods, instanceMethods)
+
   return Video
 }
 
-function beforeValidate (video, options, next) {
+function beforeValidate (video, options) {
   // Put a fake infoHash if it does not exists yet
   if (video.isOwned() && !video.infoHash) {
     // 40 hexa length
     video.infoHash = '0123456789abcdef0123456789abcdef01234567'
   }
-
-  return next(null)
 }
 
-function beforeCreate (video, options, next) {
-  const tasks = []
-
-  if (video.isOwned()) {
-    const videoPath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename())
-
-    tasks.push(
-      function createVideoTorrent (callback) {
-        createTorrentFromVideo(video, videoPath, callback)
-      },
-
-      function createVideoThumbnail (callback) {
-        createThumbnail(video, videoPath, callback)
-      },
+function beforeCreate (video, options) {
+  return new Promise(function (resolve, reject) {
+    const tasks = []
 
-      function createVideoPreview (callback) {
-        createPreview(video, videoPath, callback)
-      }
-    )
+    if (video.isOwned()) {
+      const videoPath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename())
 
-    if (CONFIG.TRANSCODING.ENABLED === true) {
       tasks.push(
-        function createVideoTranscoderJob (callback) {
-          const dataInput = {
-            id: video.id
-          }
+        function createVideoTorrent (callback) {
+          createTorrentFromVideo(video, videoPath, callback)
+        },
+
+        function createVideoThumbnail (callback) {
+          createThumbnail(video, videoPath, callback)
+        },
 
-          JobScheduler.Instance.createJob(options.transaction, 'videoTranscoder', dataInput, callback)
+        function createVideoPreview (callback) {
+          createPreview(video, videoPath, callback)
         }
       )
-    }
 
-    return parallel(tasks, next)
-  }
+      if (CONFIG.TRANSCODING.ENABLED === true) {
+        tasks.push(
+          function createVideoTranscoderJob (callback) {
+            const dataInput = {
+              id: video.id
+            }
 
-  return next()
-}
+            JobScheduler.Instance.createJob(options.transaction, 'videoTranscoder', dataInput, callback)
+          }
+        )
+      }
 
-function afterDestroy (video, options, next) {
-  const tasks = []
+      return parallel(tasks, function (err) {
+        if (err) return reject(err)
 
-  tasks.push(
-    function (callback) {
-      removeThumbnail(video, callback)
+        return resolve()
+      })
     }
-  )
 
-  if (video.isOwned()) {
+    return resolve()
+  })
+}
+
+function afterDestroy (video, options) {
+  return new Promise(function (resolve, reject) {
+    const tasks = []
+
     tasks.push(
-      function removeVideoFile (callback) {
-        removeFile(video, callback)
-      },
+      function (callback) {
+        removeThumbnail(video, callback)
+      }
+    )
 
-      function removeVideoTorrent (callback) {
-        removeTorrent(video, callback)
-      },
+    if (video.isOwned()) {
+      tasks.push(
+        function removeVideoFile (callback) {
+          removeFile(video, callback)
+        },
 
-      function removeVideoPreview (callback) {
-        removePreview(video, callback)
-      },
+        function removeVideoTorrent (callback) {
+          removeTorrent(video, callback)
+        },
 
-      function removeVideoToFriends (callback) {
-        const params = {
-          remoteId: video.id
-        }
+        function removeVideoPreview (callback) {
+          removePreview(video, callback)
+        },
 
-        removeVideoToFriends(params)
+        function notifyFriends (callback) {
+          const params = {
+            remoteId: video.id
+          }
 
-        return callback()
-      }
-    )
-  }
+          removeVideoToFriends(params)
 
-  parallel(tasks, next)
+          return callback()
+        }
+      )
+    }
+
+    parallel(tasks, function (err) {
+      if (err) return reject(err)
+
+      return resolve()
+    })
+  })
 }
 
 // ------------------------------ METHODS ------------------------------
 
 function associate (models) {
-  this.belongsTo(models.Author, {
+  Video.belongsTo(models.Author, {
     foreignKey: {
       name: 'authorId',
       allowNull: false
@@ -330,13 +373,13 @@ function associate (models) {
     onDelete: 'cascade'
   })
 
-  this.belongsToMany(models.Tag, {
+  Video.belongsToMany(models.Tag, {
     foreignKey: 'videoId',
     through: models.VideoTag,
     onDelete: 'cascade'
   })
 
-  this.hasMany(models.VideoAbuse, {
+  Video.hasMany(models.VideoAbuse, {
     foreignKey: {
       name: 'videoId',
       allowNull: false
@@ -345,7 +388,7 @@ function associate (models) {
   })
 }
 
-function generateMagnetUri () {
+generateMagnetUri = function () {
   let baseUrlHttp
   let baseUrlWs
 
@@ -372,18 +415,18 @@ function generateMagnetUri () {
   return magnetUtil.encode(magnetHash)
 }
 
-function getVideoFilename () {
+getVideoFilename = function () {
   if (this.isOwned()) return this.id + this.extname
 
   return this.remoteId + this.extname
 }
 
-function getThumbnailName () {
+getThumbnailName = function () {
   // We always have a copy of the thumbnail
   return this.id + '.jpg'
 }
 
-function getPreviewName () {
+getPreviewName = function () {
   const extension = '.jpg'
 
   if (this.isOwned()) return this.id + extension
@@ -391,7 +434,7 @@ function getPreviewName () {
   return this.remoteId + extension
 }
 
-function getTorrentName () {
+getTorrentName = function () {
   const extension = '.torrent'
 
   if (this.isOwned()) return this.id + extension
@@ -399,11 +442,11 @@ function getTorrentName () {
   return this.remoteId + extension
 }
 
-function isOwned () {
+isOwned = function () {
   return this.remoteId === null
 }
 
-function toFormatedJSON () {
+toFormatedJSON = function () {
   let podHost
 
   if (this.Author.Pod) {
@@ -453,43 +496,41 @@ function toFormatedJSON () {
   return json
 }
 
-function toAddRemoteJSON (callback) {
-  const self = this
-
+toAddRemoteJSON = function (callback) {
   // Get thumbnail data to send to the other pod
   const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, this.getThumbnailName())
-  fs.readFile(thumbnailPath, function (err, thumbnailData) {
+  fs.readFile(thumbnailPath, (err, thumbnailData) => {
     if (err) {
       logger.error('Cannot read the thumbnail of the video')
       return callback(err)
     }
 
     const remoteVideo = {
-      name: self.name,
-      category: self.category,
-      licence: self.licence,
-      language: self.language,
-      nsfw: self.nsfw,
-      description: self.description,
-      infoHash: self.infoHash,
-      remoteId: self.id,
-      author: self.Author.name,
-      duration: self.duration,
+      name: this.name,
+      category: this.category,
+      licence: this.licence,
+      language: this.language,
+      nsfw: this.nsfw,
+      description: this.description,
+      infoHash: this.infoHash,
+      remoteId: this.id,
+      author: this.Author.name,
+      duration: this.duration,
       thumbnailData: thumbnailData.toString('binary'),
-      tags: map(self.Tags, 'name'),
-      createdAt: self.createdAt,
-      updatedAt: self.updatedAt,
-      extname: self.extname,
-      views: self.views,
-      likes: self.likes,
-      dislikes: self.dislikes
+      tags: map(this.Tags, 'name'),
+      createdAt: this.createdAt,
+      updatedAt: this.updatedAt,
+      extname: this.extname,
+      views: this.views,
+      likes: this.likes,
+      dislikes: this.dislikes
     }
 
     return callback(null, remoteVideo)
   })
 }
 
-function toUpdateRemoteJSON (callback) {
+toUpdateRemoteJSON = function (callback) {
   const json = {
     name: this.name,
     category: this.category,
@@ -513,7 +554,7 @@ function toUpdateRemoteJSON (callback) {
   return json
 }
 
-function transcodeVideofile (finalCallback) {
+transcodeVideofile = function (finalCallback) {
   const video = this
 
   const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR
@@ -568,7 +609,7 @@ function transcodeVideofile (finalCallback) {
 
 // ------------------------------ STATICS ------------------------------
 
-function generateThumbnailFromData (video, thumbnailData, callback) {
+generateThumbnailFromData = function (video, thumbnailData, callback) {
   // Creating the thumbnail for a remote video
 
   const thumbnailName = video.getThumbnailName()
@@ -580,7 +621,7 @@ function generateThumbnailFromData (video, thumbnailData, callback) {
   })
 }
 
-function getDurationFromFile (videoPath, callback) {
+getDurationFromFile = function (videoPath, callback) {
   ffmpeg.ffprobe(videoPath, function (err, metadata) {
     if (err) return callback(err)
 
@@ -588,46 +629,46 @@ function getDurationFromFile (videoPath, callback) {
   })
 }
 
-function list (callback) {
-  return this.findAll().asCallback(callback)
+list = function (callback) {
+  return Video.findAll().asCallback(callback)
 }
 
-function listForApi (start, count, sort, callback) {
+listForApi = function (start, count, sort, callback) {
   // Exclude Blakclisted videos from the list
   const query = {
+    distinct: true,
     offset: start,
     limit: count,
-    distinct: true, // For the count, a video can have many tags
-    order: [ getSort(sort), [ this.sequelize.models.Tag, 'name', 'ASC' ] ],
+    order: [ getSort(sort), [ Video['sequelize'].models.Tag, 'name', 'ASC' ] ],
     include: [
       {
-        model: this.sequelize.models.Author,
-        include: [ { model: this.sequelize.models.Pod, required: false } ]
+        model: Video['sequelize'].models.Author,
+        include: [ { model: Video['sequelize'].models.Pod, required: false } ]
       },
 
-      this.sequelize.models.Tag
+      Video['sequelize'].models.Tag
     ],
-    where: createBaseVideosWhere.call(this)
+    where: createBaseVideosWhere()
   }
 
-  return this.findAndCountAll(query).asCallback(function (err, result) {
+  return Video.findAndCountAll(query).asCallback(function (err, result) {
     if (err) return callback(err)
 
     return callback(null, result.rows, result.count)
   })
 }
 
-function loadByHostAndRemoteId (fromHost, remoteId, callback) {
+loadByHostAndRemoteId = function (fromHost, remoteId, callback) {
   const query = {
     where: {
       remoteId: remoteId
     },
     include: [
       {
-        model: this.sequelize.models.Author,
+        model: Video['sequelize'].models.Author,
         include: [
           {
-            model: this.sequelize.models.Pod,
+            model: Video['sequelize'].models.Pod,
             required: true,
             where: {
               host: fromHost
@@ -638,29 +679,29 @@ function loadByHostAndRemoteId (fromHost, remoteId, callback) {
     ]
   }
 
-  return this.findOne(query).asCallback(callback)
+  return Video.findOne(query).asCallback(callback)
 }
 
-function listOwnedAndPopulateAuthorAndTags (callback) {
+listOwnedAndPopulateAuthorAndTags = function (callback) {
   // If remoteId is null this is *our* video
   const query = {
     where: {
       remoteId: null
     },
-    include: [ this.sequelize.models.Author, this.sequelize.models.Tag ]
+    include: [ Video['sequelize'].models.Author, Video['sequelize'].models.Tag ]
   }
 
-  return this.findAll(query).asCallback(callback)
+  return Video.findAll(query).asCallback(callback)
 }
 
-function listOwnedByAuthor (author, callback) {
+listOwnedByAuthor = function (author, callback) {
   const query = {
     where: {
       remoteId: null
     },
     include: [
       {
-        model: this.sequelize.models.Author,
+        model: Video['sequelize'].models.Author,
         where: {
           name: author
         }
@@ -668,58 +709,58 @@ function listOwnedByAuthor (author, callback) {
     ]
   }
 
-  return this.findAll(query).asCallback(callback)
+  return Video.findAll(query).asCallback(callback)
 }
 
-function load (id, callback) {
-  return this.findById(id).asCallback(callback)
+load = function (id, callback) {
+  return Video.findById(id).asCallback(callback)
 }
 
-function loadAndPopulateAuthor (id, callback) {
+loadAndPopulateAuthor = function (id, callback) {
   const options = {
-    include: [ this.sequelize.models.Author ]
+    include: [ Video['sequelize'].models.Author ]
   }
 
-  return this.findById(id, options).asCallback(callback)
+  return Video.findById(id, options).asCallback(callback)
 }
 
-function loadAndPopulateAuthorAndPodAndTags (id, callback) {
+loadAndPopulateAuthorAndPodAndTags = function (id, callback) {
   const options = {
     include: [
       {
-        model: this.sequelize.models.Author,
-        include: [ { model: this.sequelize.models.Pod, required: false } ]
+        model: Video['sequelize'].models.Author,
+        include: [ { model: Video['sequelize'].models.Pod, required: false } ]
       },
-      this.sequelize.models.Tag
+      Video['sequelize'].models.Tag
     ]
   }
 
-  return this.findById(id, options).asCallback(callback)
+  return Video.findById(id, options).asCallback(callback)
 }
 
-function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort, callback) {
+searchAndPopulateAuthorAndPodAndTags = function (value, field, start, count, sort, callback) {
   const podInclude: any = {
-    model: this.sequelize.models.Pod,
+    model: Video['sequelize'].models.Pod,
     required: false
   }
 
   const authorInclude: any = {
-    model: this.sequelize.models.Author,
+    model: Video['sequelize'].models.Author,
     include: [
       podInclude
     ]
   }
 
   const tagInclude: any = {
-    model: this.sequelize.models.Tag
+    model: Video['sequelize'].models.Tag
   }
 
   const query: any = {
-    where: createBaseVideosWhere.call(this),
+    distinct: true,
+    where: createBaseVideosWhere(),
     offset: start,
     limit: count,
-    distinct: true, // For the count, a video can have many tags
-    order: [ getSort(sort), [ this.sequelize.models.Tag, 'name', 'ASC' ] ]
+    order: [ getSort(sort), [ Video['sequelize'].models.Tag, 'name', 'ASC' ] ]
   }
 
   // Make an exact search with the magnet
@@ -727,8 +768,8 @@ function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort,
     const infoHash = magnetUtil.decode(value).infoHash
     query.where.infoHash = infoHash
   } else if (field === 'tags') {
-    const escapedValue = this.sequelize.escape('%' + value + '%')
-    query.where.id.$in = this.sequelize.literal(
+    const escapedValue = Video['sequelize'].escape('%' + value + '%')
+    query.where.id.$in = Video['sequelize'].literal(
       '(SELECT "VideoTags"."videoId" FROM "Tags" INNER JOIN "VideoTags" ON "Tags"."id" = "VideoTags"."tagId" WHERE name LIKE ' + escapedValue + ')'
     )
   } else if (field === 'host') {
@@ -758,10 +799,10 @@ function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort,
   ]
 
   if (tagInclude.where) {
-    // query.include.push([ this.sequelize.models.Tag ])
+    // query.include.push([ Video['sequelize'].models.Tag ])
   }
 
-  return this.findAndCountAll(query).asCallback(function (err, result) {
+  return Video.findAndCountAll(query).asCallback(function (err, result) {
     if (err) return callback(err)
 
     return callback(null, result.rows, result.count)
@@ -773,7 +814,7 @@ function searchAndPopulateAuthorAndPodAndTags (value, field, start, count, sort,
 function createBaseVideosWhere () {
   return {
     id: {
-      $notIn: this.sequelize.literal(
+      $notIn: Video['sequelize'].literal(
         '(SELECT "BlacklistedVideos"."videoId" FROM "BlacklistedVideos")'
       )
     }
index 3ff7b230a9a86b5a8718bfb70e52a2cddced4dbf..c0b59766897323081f1472039f52d00ad27ffcf3 100644 (file)
@@ -12,7 +12,7 @@ const loginUtils = require('../utils/login')
 const serversUtils = require('../utils/servers')
 const videosUtils = require('../utils/videos')
 
-describe('Test video blacklists', function () {
+describe('Test video transcoding', function () {
   let servers = []
 
   before(function (done) {
index afb08e6fc86fe56b013e78fbda982f20e703e535..c753c1f1dbe5546f1bd07f25f7ceaf572913d57c 100644 (file)
@@ -82,7 +82,7 @@ function runServer (number, callback) {
     detached: true
   }
 
-  server.app = fork(pathUtils.join(__dirname, '..', '..', '..', 'server.js'), [], options)
+  server.app = fork(pathUtils.join(__dirname, '..', '..', '..', 'dist', 'server.js'), [], options)
   server.app.stdout.on('data', function onStdout (data) {
     let dontContinue = false
 
index c0ce443b39ea9100c2d0c91f110b0efbff271959..857aa92e6cb51316573a29492f3ffe8a515fb717 100644 (file)
--- a/yarn.lock
+++ b/yarn.lock
@@ -26,8 +26,8 @@
   resolved "https://registry.yarnpkg.com/@types/config/-/config-0.0.32.tgz#c106055802d78e234e28374adc4dad460d098558"
 
 "@types/express-serve-static-core@*":
-  version "4.0.44"
-  resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.0.44.tgz#a1c3bd5d80e93c72fba91a03f5412c47f21d4ae7"
+  version "4.0.45"
+  resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.0.45.tgz#71bb1f87d7187482d0d8851f5b294458e1c78667"
   dependencies:
     "@types/node" "*"
 
@@ -67,8 +67,8 @@
     "@types/express" "*"
 
 "@types/node@*", "@types/node@^7.0.18":
-  version "7.0.18"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.18.tgz#cd67f27d3dc0cfb746f0bdd5e086c4c5d55be173"
+  version "7.0.22"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.22.tgz#4593f4d828bdd612929478ea40c67b4f403ca255"
 
 "@types/request@^0.0.43":
   version "0.0.43"
@@ -77,9 +77,9 @@
     "@types/form-data" "*"
     "@types/node" "*"
 
-"@types/sequelize@3":
-  version "3.4.48"
-  resolved "https://registry.yarnpkg.com/@types/sequelize/-/sequelize-3.4.48.tgz#f88fac7cc4717d2e87f20f69ebb64aa869e7e4d1"
+"@types/sequelize@^4.0.55":
+  version "4.0.55"
+  resolved "https://registry.yarnpkg.com/@types/sequelize/-/sequelize-4.0.55.tgz#957335a9de537f17ed9c9e16c088cc147b8805af"
   dependencies:
     "@types/bluebird" "*"
     "@types/lodash" "*"
@@ -142,8 +142,8 @@ ajv-keywords@^1.0.0:
   resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
 
 ajv@^4.7.0, ajv@^4.9.1:
-  version "4.11.7"
-  resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.7.tgz#8655a5d86d0824985cc471a1d913fb6729a0ec48"
+  version "4.11.8"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
   dependencies:
     co "^4.6.0"
     json-stable-stringify "^1.0.1"
@@ -243,8 +243,8 @@ assertion-error@^1.0.1:
   resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c"
 
 async@>=0.2.9, async@^2.0.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/async/-/async-2.3.0.tgz#1013d1051047dd320fe24e494d5c66ecaf6147d9"
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/async/-/async-2.4.1.tgz#62a56b279c98a11d0987096a01cc3eeb8eb7bbd7"
   dependencies:
     lodash "^4.14.0"
 
@@ -381,8 +381,8 @@ bittorrent-tracker@^9.0.0:
     bufferutil "^3.0.0"
 
 bl@^1.0.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.0.tgz#1397e7ec42c5f5dc387470c500e34a9f6be9ea98"
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e"
   dependencies:
     readable-stream "^2.0.5"
 
@@ -408,7 +408,7 @@ bluebird@^2.10.0, bluebird@^2.9.13:
   version "2.11.0"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
 
-bluebird@^3.0.5, bluebird@^3.3.4, bluebird@^3.4.0, bluebird@^3.4.6:
+bluebird@^3.0.5, bluebird@^3.4.0, bluebird@^3.4.6:
   version "3.5.0"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
 
@@ -417,19 +417,19 @@ bn.js@^4.4.0:
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215"
 
 body-parser@^1.12.4:
-  version "1.17.1"
-  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.1.tgz#75b3bc98ddd6e7e0d8ffe750dfaca5c66993fa47"
+  version "1.17.2"
+  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.2.tgz#f8892abc8f9e627d42aedafbca66bf5ab99104ee"
   dependencies:
     bytes "2.4.0"
     content-type "~1.0.2"
-    debug "2.6.1"
+    debug "2.6.7"
     depd "~1.1.0"
     http-errors "~1.6.1"
     iconv-lite "0.4.15"
     on-finished "~2.3.0"
     qs "6.4.0"
     raw-body "~2.2.0"
-    type-is "~1.6.14"
+    type-is "~1.6.15"
 
 boom@2.x.x:
   version "2.10.1"
@@ -437,7 +437,7 @@ boom@2.x.x:
   dependencies:
     hoek "2.x.x"
 
-brace-expansion@^1.0.0:
+brace-expansion@^1.1.7:
   version "1.1.7"
   resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59"
   dependencies:
@@ -570,6 +570,13 @@ closest-to@~2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/closest-to/-/closest-to-2.0.0.tgz#bb2a860edb7769b62d04821748ae50da24dbefaa"
 
+cls-bluebird@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/cls-bluebird/-/cls-bluebird-2.0.1.tgz#c259a480ae02c0e506134307bb13db30446ee2e7"
+  dependencies:
+    is-bluebird "^1.0.2"
+    shimmer "^1.1.0"
+
 co-bluebird@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/co-bluebird/-/co-bluebird-1.1.0.tgz#c8b9f3a9320a7ed30987dcca1a5c3cff59655c7c"
@@ -649,10 +656,11 @@ concurrently@^3.1.0:
     tree-kill "^1.1.0"
 
 config@^1.14.0:
-  version "1.25.1"
-  resolved "https://registry.yarnpkg.com/config/-/config-1.25.1.tgz#72ac51cde81e2c77c6b3b66d0130dae527a19c92"
+  version "1.26.1"
+  resolved "https://registry.yarnpkg.com/config/-/config-1.26.1.tgz#f647ce32c345e80ba73a8eaa7a9a4b4e5b290ca1"
   dependencies:
     json5 "0.4.0"
+    os-homedir "1.0.2"
 
 console-control-strings@^1.0.0, console-control-strings@~1.1.0:
   version "1.1.0"
@@ -750,8 +758,8 @@ dashdash@^1.12.0:
     assert-plus "^1.0.0"
 
 date-fns@^1.23.0:
-  version "1.28.4"
-  resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.4.tgz#7938aec34ba31fc8bd134d2344bc2e0bbfd95165"
+  version "1.28.5"
+  resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.5.tgz#257cfc45d322df45ef5658665967ee841cd73faf"
 
 debug-log@^1.0.0:
   version "1.0.1"
@@ -769,17 +777,17 @@ debug@2.6.0:
   dependencies:
     ms "0.7.2"
 
-debug@2.6.1:
-  version "2.6.1"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.1.tgz#79855090ba2c4e3115cc7d8769491d58f0491351"
+debug@2.6.7:
+  version "2.6.7"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e"
   dependencies:
-    ms "0.7.2"
+    ms "2.0.0"
 
-debug@2.6.4, debug@^2.0.0, debug@^2.1.0, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.5.2:
-  version "2.6.4"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.4.tgz#7586a9b3c39741c0282ae33445c4e8ac74734fe0"
+debug@2.6.8, debug@^2.0.0, debug@^2.1.0, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.5.2:
+  version "2.6.8"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
   dependencies:
-    ms "0.7.3"
+    ms "2.0.0"
 
 deep-eql@^0.1.3:
   version "0.1.3"
@@ -788,8 +796,8 @@ deep-eql@^0.1.3:
     type-detect "0.1.1"
 
 deep-extend@~0.4.0:
-  version "0.4.1"
-  resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253"
+  version "0.4.2"
+  resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f"
 
 deep-is@~0.1.3:
   version "0.1.3"
@@ -932,8 +940,8 @@ es-to-primitive@^1.1.1:
     is-symbol "^1.0.1"
 
 es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14:
-  version "0.10.15"
-  resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.15.tgz#c330a5934c1ee21284a7c081a86e5fd937c91ea6"
+  version "0.10.21"
+  resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.21.tgz#19a725f9e51d0300bbc1e8e821109fd9daf55925"
   dependencies:
     es6-iterator "2"
     es6-symbol "~3.1"
@@ -1107,8 +1115,8 @@ eslint@~3.19.0:
     user-home "^2.0.0"
 
 espree@^3.4.0:
-  version "3.4.2"
-  resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.2.tgz#38dbdedbedc95b8961a1fbf04734a8f6a9c8c592"
+  version "3.4.3"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.3.tgz#2910b5ccd49ce893c2ffffaab4fd8b3a31b82374"
   dependencies:
     acorn "^5.0.1"
     acorn-jsx "^3.0.0"
@@ -1185,8 +1193,8 @@ express-validator@^3.1.0:
     validator "~6.2.0"
 
 express@^4.12.4, express@^4.13.3:
-  version "4.15.2"
-  resolved "https://registry.yarnpkg.com/express/-/express-4.15.2.tgz#af107fc148504457f2dca9a6f2571d7129b97b35"
+  version "4.15.3"
+  resolved "https://registry.yarnpkg.com/express/-/express-4.15.3.tgz#bab65d0f03aa80c358408972fc700f916944b662"
   dependencies:
     accepts "~1.3.3"
     array-flatten "1.1.1"
@@ -1194,32 +1202,32 @@ express@^4.12.4, express@^4.13.3:
     content-type "~1.0.2"
     cookie "0.3.1"
     cookie-signature "1.0.6"
-    debug "2.6.1"
+    debug "2.6.7"
     depd "~1.1.0"
     encodeurl "~1.0.1"
     escape-html "~1.0.3"
     etag "~1.8.0"
-    finalhandler "~1.0.0"
+    finalhandler "~1.0.3"
     fresh "0.5.0"
     merge-descriptors "1.0.1"
     methods "~1.1.2"
     on-finished "~2.3.0"
     parseurl "~1.3.1"
     path-to-regexp "0.1.7"
-    proxy-addr "~1.1.3"
+    proxy-addr "~1.1.4"
     qs "6.4.0"
     range-parser "~1.2.0"
-    send "0.15.1"
-    serve-static "1.12.1"
+    send "0.15.3"
+    serve-static "1.12.3"
     setprototypeof "1.0.3"
     statuses "~1.3.1"
-    type-is "~1.6.14"
+    type-is "~1.6.15"
     utils-merge "1.0.0"
-    vary "~1.1.0"
+    vary "~1.1.1"
 
 extend@^3.0.0, extend@~3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4"
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
 
 extsprintf@1.0.2:
   version "1.0.2"
@@ -1256,11 +1264,11 @@ filestream@^4.0.0:
     typedarray-to-buffer "^3.0.0"
     xtend "^4.0.1"
 
-finalhandler@~1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.2.tgz#d0e36f9dbc557f2de14423df6261889e9d60c93a"
+finalhandler@~1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89"
   dependencies:
-    debug "2.6.4"
+    debug "2.6.7"
     encodeurl "~1.0.1"
     escape-html "~1.0.3"
     on-finished "~2.3.0"
@@ -1285,12 +1293,6 @@ find-up@^2.0.0:
   dependencies:
     locate-path "^2.0.0"
 
-findup-sync@~0.3.0:
-  version "0.3.0"
-  resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.3.0.tgz#37930aa5d816b777c03445e1966cc6790a4c0b16"
-  dependencies:
-    glob "~5.0.0"
-
 flat-cache@^1.2.1:
   version "1.2.2"
   resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96"
@@ -1375,7 +1377,7 @@ function-bind@^1.0.2, function-bind@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
 
-gauge@~2.7.1:
+gauge@~2.7.3:
   version "2.7.4"
   resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
   dependencies:
@@ -1424,7 +1426,7 @@ github-from-package@0.0.0:
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
 
-glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
+glob@7.1.1:
   version "7.1.1"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
   dependencies:
@@ -1435,13 +1437,14 @@ glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
-glob@~5.0.0:
-  version "5.0.15"
-  resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
+  version "7.1.2"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
   dependencies:
+    fs.realpath "^1.0.0"
     inflight "^1.0.4"
     inherits "2"
-    minimatch "2 || 3"
+    minimatch "^3.0.4"
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
@@ -1544,8 +1547,8 @@ iconv-lite@0.4.15:
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb"
 
 ignore@^3.0.11, ignore@^3.0.9, ignore@^3.2.0:
-  version "3.2.7"
-  resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.7.tgz#4810ca5f1d8eca5595213a34b94f2eb4ed926bbd"
+  version "3.3.3"
+  resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d"
 
 immediate-chunk-store@^1.0.8:
   version "1.0.8"
@@ -1555,9 +1558,9 @@ imurmurhash@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
 
-inflection@^1.6.0:
-  version "1.12.0"
-  resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416"
+inflection@1.10.0:
+  version "1.10.0"
+  resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.10.0.tgz#5bffcb1197ad3e81050f8e17e21668087ee9eb2f"
 
 inflight@^1.0.4:
   version "1.0.6"
@@ -1618,6 +1621,10 @@ is-ascii@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/is-ascii/-/is-ascii-1.0.0.tgz#f02ad0259a0921cd199ff21ce1b09e0f6b4e3929"
 
+is-bluebird@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-bluebird/-/is-bluebird-1.0.2.tgz#096439060f4aa411abee19143a84d6a55346d6e2"
+
 is-callable@^1.1.1, is-callable@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2"
@@ -1694,8 +1701,8 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0:
   resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
 
 is-windows@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.0.tgz#c61d61020c3ebe99261b781bd3d1622395f547f8"
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9"
 
 isarray@0.0.1:
   version "0.0.1"
@@ -1724,8 +1731,8 @@ js-tokens@^3.0.0:
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
 
 js-yaml@^3.5.1, js-yaml@^3.5.4:
-  version "3.8.3"
-  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.3.tgz#33a05ec481c850c8875929166fe1beb61c728766"
+  version "3.8.4"
+  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6"
   dependencies:
     argparse "^1.0.7"
     esprima "^3.1.1"
@@ -1887,9 +1894,9 @@ lodash.keys@^3.0.0:
     lodash.isarguments "^3.0.0"
     lodash.isarray "^3.0.0"
 
-lodash@4.12.0:
-  version "4.12.0"
-  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.12.0.tgz#2bd6dc46a040f59e686c972ed21d93dc59053258"
+lodash@4.15.0:
+  version "4.15.0"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.15.0.tgz#3162391d8f0140aa22cf8f6b3c34d6b7f63d3aa9"
 
 lodash@^3.3.1:
   version "3.10.1"
@@ -1959,15 +1966,19 @@ mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.7:
   dependencies:
     mime-db "~1.27.0"
 
-mime@1.3.4, mime@^1.3.4:
+mime@1.3.4:
   version "1.3.4"
   resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
 
-"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3:
-  version "3.0.3"
-  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
+mime@^1.3.4:
+  version "1.3.6"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0"
+
+minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
   dependencies:
-    brace-expansion "^1.0.0"
+    brace-expansion "^1.1.7"
 
 minimist@0.0.8, minimist@~0.0.1:
   version "0.0.8"
@@ -1984,8 +1995,8 @@ mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1:
     minimist "0.0.8"
 
 mocha@^3.0.1:
-  version "3.3.0"
-  resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.3.0.tgz#d29b7428d3f52c82e2e65df1ecb7064e1aabbfb5"
+  version "3.4.2"
+  resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.4.2.tgz#d0ef4d332126dbf18d0d640c9b382dd48be97594"
   dependencies:
     browser-stdout "1.3.0"
     commander "2.9.0"
@@ -2010,11 +2021,11 @@ moment-timezone@^0.5.4:
   resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"
 
 morgan@^1.5.3:
-  version "1.8.1"
-  resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.8.1.tgz#f93023d3887bd27b78dfd6023cea7892ee27a4b1"
+  version "1.8.2"
+  resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.8.2.tgz#784ac7734e4a453a9c6e6e8680a9329275c8b687"
   dependencies:
     basic-auth "~1.1.0"
-    debug "2.6.1"
+    debug "2.6.8"
     depd "~1.1.0"
     on-finished "~2.3.0"
     on-headers "~1.0.1"
@@ -2042,9 +2053,9 @@ ms@0.7.2:
   version "0.7.2"
   resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
 
-ms@0.7.3:
-  version "0.7.3"
-  resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff"
+ms@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
 
 multer@^1.1.0:
   version "1.3.0"
@@ -2091,8 +2102,8 @@ next-event@^1.0.0:
   resolved "https://registry.yarnpkg.com/next-event/-/next-event-1.0.0.tgz#e7778acde2e55802e0ad1879c39cf6f75eda61d8"
 
 node-abi@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.0.0.tgz#443bfd151b599231028ae425e592e76cd31cb537"
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.0.2.tgz#00f3e0a58100eb480133b48c99a32cc1f9e6c93e"
 
 node-pre-gyp@0.6.32:
   version "0.6.32"
@@ -2108,6 +2119,10 @@ node-pre-gyp@0.6.32:
     tar "~2.2.1"
     tar-pack "~3.3.0"
 
+node-uuid@~1.4.4:
+  version "1.4.8"
+  resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907"
+
 noop-logger@^0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
@@ -2119,12 +2134,12 @@ nopt@~3.0.6:
     abbrev "1"
 
 npmlog@^4.0.1:
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.2.tgz#d03950e0e78ce1527ba26d2a7592e9348ac3e75f"
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.0.tgz#dc59bee85f64f00ed424efb2af0783df25d1c0b5"
   dependencies:
     are-we-there-yet "~1.1.2"
     console-control-strings "~1.1.0"
-    gauge "~2.7.1"
+    gauge "~2.7.3"
     set-blocking "~2.0.0"
 
 number-is-nan@^1.0.0:
@@ -2220,7 +2235,7 @@ optionator@^0.8.2:
     type-check "~0.3.2"
     wordwrap "~1.0.0"
 
-os-homedir@^1.0.0, os-homedir@^1.0.1:
+os-homedir@1.0.2, os-homedir@^1.0.0, os-homedir@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
 
@@ -2240,9 +2255,9 @@ package-json-versionify@^1.0.2:
   dependencies:
     browserify-package-json "^1.0.0"
 
-packet-reader@0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.2.0.tgz#819df4d010b82d5ea5671f8a1a3acf039bcd7700"
+packet-reader@0.3.1:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.3.1.tgz#cd62e60af8d7fea8a705ec4ff990871c46871f27"
 
 parse-json@^2.2.0:
   version "2.2.0"
@@ -2336,11 +2351,11 @@ pg-types@1.*:
     postgres-interval "~1.0.0"
 
 pg@^6.1.0:
-  version "6.1.5"
-  resolved "https://registry.yarnpkg.com/pg/-/pg-6.1.5.tgz#204fa40c1252ab7220d7cf6992886b20d77862b8"
+  version "6.2.3"
+  resolved "https://registry.yarnpkg.com/pg/-/pg-6.2.3.tgz#8988b7c69a1875a997d73b92036c42590b5f8024"
   dependencies:
     buffer-writer "1.0.1"
-    packet-reader "0.2.0"
+    packet-reader "0.3.1"
     pg-connection-string "0.1.3"
     pg-pool "1.*"
     pg-types "1.*"
@@ -2348,8 +2363,8 @@ pg@^6.1.0:
     semver "4.3.2"
 
 pgpass@1.x:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.1.tgz#0de8b5bef993295d90a7e17d976f568dcd25d49f"
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306"
   dependencies:
     split "^1.0.0"
 
@@ -2461,7 +2476,7 @@ promisify-any@2.0.1:
     co-bluebird "^1.1.0"
     is-generator "^1.0.2"
 
-proxy-addr@~1.1.3:
+proxy-addr@~1.1.4:
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.4.tgz#27e545f6960a44a627d9b44467e35c1b6b4ce2f3"
   dependencies:
@@ -2488,8 +2503,8 @@ qs@6.4.0, qs@^6.1.0, qs@~6.4.0:
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
 
 random-access-file@^1.0.1:
-  version "1.7.0"
-  resolved "https://registry.yarnpkg.com/random-access-file/-/random-access-file-1.7.0.tgz#3746e28dc27fe24e406ac0a396ffaeef22751983"
+  version "1.7.2"
+  resolved "https://registry.yarnpkg.com/random-access-file/-/random-access-file-1.7.2.tgz#053e2e8ec7670370a8e8b10da962e45753f22dbc"
   dependencies:
     buffer-alloc-unsafe "^1.0.0"
     debug "^2.5.2"
@@ -2690,8 +2705,8 @@ run-series@^1.0.2:
   resolved "https://registry.yarnpkg.com/run-series/-/run-series-1.1.4.tgz#89a73ddc5e75c9ef8ab6320c0a1600d6a41179b9"
 
 rusha@^0.8.1:
-  version "0.8.5"
-  resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.5.tgz#a30ae9bd5a4e80fbc96fbe7a13232b944be24f84"
+  version "0.8.6"
+  resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.6.tgz#b264ddaa4d49a1d67300061858ba9358c4adca14"
 
 rx-lite@^3.1.2:
   version "3.1.2"
@@ -2721,11 +2736,11 @@ semver@5.3.0, semver@^5.0.1, semver@^5.3.0, semver@~5.3.0:
   version "5.3.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
 
-send@0.15.1:
-  version "0.15.1"
-  resolved "https://registry.yarnpkg.com/send/-/send-0.15.1.tgz#8a02354c26e6f5cca700065f5f0cdeba90ec7b5f"
+send@0.15.3:
+  version "0.15.3"
+  resolved "https://registry.yarnpkg.com/send/-/send-0.15.3.tgz#5013f9f99023df50d1bd9892c19e3defd1d53309"
   dependencies:
-    debug "2.6.1"
+    debug "2.6.7"
     depd "~1.1.0"
     destroy "~1.0.4"
     encodeurl "~1.0.1"
@@ -2734,7 +2749,7 @@ send@0.15.1:
     fresh "0.5.0"
     http-errors "~1.6.1"
     mime "1.3.4"
-    ms "0.7.2"
+    ms "2.0.0"
     on-finished "~2.3.0"
     range-parser "~1.2.0"
     statuses "~1.3.1"
@@ -2745,35 +2760,36 @@ sentence-case@^1.1.1:
   dependencies:
     lower-case "^1.1.1"
 
-sequelize@^3.27.0:
-  version "3.30.4"
-  resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-3.30.4.tgz#bda2df1e31854b099e4149a111e9fc0a5ca1d1a4"
+sequelize@4.0.0-2:
+  version "4.0.0-2"
+  resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.0.0-2.tgz#8143f50fa00ac62ba95394f4c81bd97e7c3600d5"
   dependencies:
-    bluebird "^3.3.4"
+    bluebird "^3.4.6"
+    cls-bluebird "^2.0.1"
+    debug "^2.2.0"
     depd "^1.1.0"
     dottie "^1.0.0"
     generic-pool "2.4.2"
-    inflection "^1.6.0"
-    lodash "4.12.0"
+    inflection "1.10.0"
+    lodash "4.15.0"
     moment "^2.13.0"
     moment-timezone "^0.5.4"
+    node-uuid "~1.4.4"
     retry-as-promised "^2.0.0"
     semver "^5.0.1"
-    shimmer "1.1.0"
-    terraformer-wkt-parser "^1.1.0"
+    terraformer-wkt-parser "^1.1.2"
     toposort-class "^1.0.1"
-    uuid "^3.0.0"
-    validator "^5.2.0"
-    wkx "0.2.0"
+    validator "^5.6.0"
+    wkx "0.3.0"
 
-serve-static@1.12.1:
-  version "1.12.1"
-  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.1.tgz#7443a965e3ced647aceb5639fa06bf4d1bbe0039"
+serve-static@1.12.3:
+  version "1.12.3"
+  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.3.tgz#9f4ba19e2f3030c547f8af99107838ec38d5b1e2"
   dependencies:
     encodeurl "~1.0.1"
     escape-html "~1.0.3"
     parseurl "~1.3.1"
-    send "0.15.1"
+    send "0.15.3"
 
 set-blocking@~2.0.0:
   version "2.0.0"
@@ -2801,7 +2817,7 @@ shelljs@^0.7.5:
     interpret "^1.0.0"
     rechoir "^0.6.2"
 
-shimmer@1.1.0:
+shimmer@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.1.0.tgz#97d7377137ffbbab425522e429fe0aa89a488b35"
 
@@ -2866,6 +2882,16 @@ sntp@1.x.x:
   dependencies:
     hoek "2.x.x"
 
+source-map-support@^0.4.15:
+  version "0.4.15"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1"
+  dependencies:
+    source-map "^0.5.6"
+
+source-map@^0.5.6:
+  version "0.5.6"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
+
 spawn-command@^0.0.2-1:
   version "0.0.2"
   resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e"
@@ -2900,8 +2926,8 @@ sshpk@^1.7.0:
     tweetnacl "~0.14.0"
 
 stack-trace@0.0.x:
-  version "0.0.9"
-  resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695"
+  version "0.0.10"
+  resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
 
 standard-engine@~7.0.0:
   version "7.0.0"
@@ -2962,7 +2988,7 @@ streamsearch@0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
 
-string-width@^1.0.1:
+string-width@^1.0.1, string-width@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
   dependencies:
@@ -2989,10 +3015,10 @@ string_decoder@~0.10.x:
   resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
 
 string_decoder@~1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.0.tgz#f06f41157b664d86069f84bdbdc9b0d8ab281667"
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.1.tgz#62e200f039955a6810d8df0a33ffc0f013662d98"
   dependencies:
-    buffer-shims "~1.0.0"
+    safe-buffer "^5.0.1"
 
 stringstream@~0.0.4:
   version "0.0.5"
@@ -3094,8 +3120,8 @@ tar-pack@~3.3.0:
     uid-number "~0.0.6"
 
 tar-stream@^1.1.2:
-  version "1.5.2"
-  resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.2.tgz#fbc6c6e83c1a19d4cb48c7d96171fc248effc7bf"
+  version "1.5.4"
+  resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.4.tgz#36549cf04ed1aee9b2a30c0143252238daf94016"
   dependencies:
     bl "^1.0.0"
     end-of-stream "^1.0.0"
@@ -3110,7 +3136,7 @@ tar@~2.2.1:
     fstream "^1.0.2"
     inherits "2"
 
-terraformer-wkt-parser@^1.1.0:
+terraformer-wkt-parser@^1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/terraformer-wkt-parser/-/terraformer-wkt-parser-1.1.2.tgz#336a0c8fc82094a5aff83288f69aedecd369bf0c"
   dependencies:
@@ -3127,8 +3153,8 @@ text-table@~0.2.0:
   resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
 
 thenify@^3.0.0:
-  version "3.2.1"
-  resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.2.1.tgz#251fd1c80aff6e5cf57cb179ab1fcb724269bd11"
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839"
   dependencies:
     any-promise "^1.0.0"
 
@@ -3182,8 +3208,8 @@ tryit@^1.0.1:
   resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb"
 
 tslib@^1.0.0, tslib@^1.6.0:
-  version "1.7.0"
-  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.0.tgz#6e8366695f72961252b35167b0dd4fbeeafba491"
+  version "1.7.1"
+  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.1.tgz#bc8004164691923a79fe8378bbeb3da2017538ec"
 
 tslint-config-standard@^5.0.2:
   version "5.0.2"
@@ -3192,31 +3218,34 @@ tslint-config-standard@^5.0.2:
     tslint-eslint-rules "^4.0.0"
 
 tslint-eslint-rules@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/tslint-eslint-rules/-/tslint-eslint-rules-4.0.0.tgz#4e0e59ecd5701c9a48c66ed47bdcafb1c635d27b"
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/tslint-eslint-rules/-/tslint-eslint-rules-4.1.0.tgz#8fee295c42f4c8078139deb16ee7b4510fd516b7"
   dependencies:
     doctrine "^0.7.2"
     tslib "^1.0.0"
     tsutils "^1.4.0"
 
 tslint@^5.2.0:
-  version "5.2.0"
-  resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.2.0.tgz#16a2addf20cb748385f544e9a0edab086bc34114"
+  version "5.3.2"
+  resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.3.2.tgz#e56459fb095a7307f103b84052174f5e3bbef6ed"
   dependencies:
     babel-code-frame "^6.22.0"
     colors "^1.1.2"
     diff "^3.2.0"
-    findup-sync "~0.3.0"
     glob "^7.1.1"
     optimist "~0.6.0"
     resolve "^1.3.2"
     semver "^5.3.0"
     tslib "^1.6.0"
-    tsutils "^1.8.0"
+    tsutils "^2.0.0"
 
-tsutils@^1.4.0, tsutils@^1.8.0:
-  version "1.8.0"
-  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.8.0.tgz#bf8118ed8e80cd5c9fc7d75728c7963d44ed2f52"
+tsutils@^1.4.0:
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.9.1.tgz#b9f9ab44e55af9681831d5f28d0aeeaf5c750cb0"
+
+tsutils@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.1.0.tgz#5be8376c929528f65b302de9e17b0004e4c1eb20"
 
 tunnel-agent@^0.4.3:
   version "0.4.3"
@@ -3246,7 +3275,7 @@ type-detect@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2"
 
-type-is@^1.6.0, type-is@^1.6.4, type-is@~1.6.14:
+type-is@^1.6.0, type-is@^1.6.4, type-is@~1.6.15:
   version "1.6.15"
   resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410"
   dependencies:
@@ -3349,7 +3378,7 @@ validator.js@^1.1.1:
   version "1.2.3"
   resolved "https://registry.yarnpkg.com/validator.js/-/validator.js-1.2.3.tgz#f8e623f60e53bada54880333649970996a3446e1"
 
-validator@^5.2.0:
+validator@^5.6.0:
   version "5.7.0"
   resolved "https://registry.yarnpkg.com/validator/-/validator-5.7.0.tgz#7a87a58146b695ac486071141c0c49d67da05e5c"
 
@@ -3357,7 +3386,7 @@ validator@~6.2.0:
   version "6.2.1"
   resolved "https://registry.yarnpkg.com/validator/-/validator-6.2.1.tgz#bc575b78d15beb2e338a665ba9530c7f409ef667"
 
-vary@^1, vary@~1.1.0:
+vary@^1, vary@~1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"
 
@@ -3434,10 +3463,10 @@ which@^1.1.1, which@^1.2.9:
     isexe "^2.0.0"
 
 wide-align@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.0.tgz#40edde802a71fea1f070da3e62dcda2e7add96ad"
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710"
   dependencies:
-    string-width "^1.0.1"
+    string-width "^1.0.2"
 
 winston@^2.1.1:
   version "2.3.1"
@@ -3450,9 +3479,9 @@ winston@^2.1.1:
     isstream "0.1.x"
     stack-trace "0.0.x"
 
-wkx@0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.2.0.tgz#76c24f16acd0cd8f93cd34aa331e0f7961256e84"
+wkx@0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.3.0.tgz#4f24948d879aca65e501674469855e04c2ad78dd"
 
 wordwrap@~0.0.2:
   version "0.0.3"