Type functions
authorChocobozzz <florian.bigard@gmail.com>
Sat, 10 Jun 2017 20:15:25 +0000 (22:15 +0200)
committerChocobozzz <florian.bigard@gmail.com>
Sat, 10 Jun 2017 20:15:25 +0000 (22:15 +0200)
96 files changed:
package.json
server/controllers/api/clients.ts
server/controllers/api/config.ts
server/controllers/api/index.ts
server/controllers/api/pods.ts
server/controllers/api/remote/pods.ts
server/controllers/api/remote/videos.ts
server/controllers/api/requests.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/custom-validators/misc.ts
server/helpers/custom-validators/pods.ts
server/helpers/custom-validators/remote/index.ts
server/helpers/custom-validators/remote/videos.ts
server/helpers/custom-validators/users.ts
server/helpers/custom-validators/videos.ts
server/helpers/database-utils.ts
server/helpers/peertube-crypto.ts
server/helpers/requests.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/index.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/index.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/index.ts
server/middlewares/oauth.ts
server/middlewares/pagination.ts
server/middlewares/pods.ts
server/middlewares/search.ts
server/middlewares/secure.ts
server/middlewares/sort.ts
server/middlewares/validators/pagination.ts
server/middlewares/validators/pods.ts
server/middlewares/validators/remote/signature.ts
server/middlewares/validators/remote/videos.ts
server/middlewares/validators/sort.ts
server/middlewares/validators/users.ts
server/middlewares/validators/utils.ts
server/middlewares/validators/videos.ts
server/models/application-interface.ts
server/models/application.ts
server/models/author-interface.ts
server/models/author.ts
server/models/job-interface.ts
server/models/job.ts
server/models/oauth-client-interface.ts
server/models/oauth-client.ts
server/models/oauth-token-interface.ts
server/models/oauth-token.ts
server/models/pod-interface.ts
server/models/pod.ts
server/models/request-interface.ts
server/models/request-to-pod-interface.ts
server/models/request-to-pod.ts
server/models/request-video-event-interface.ts
server/models/request-video-event.ts
server/models/request-video-qadu-interface.ts
server/models/request-video-qadu.ts
server/models/request.ts
server/models/tag-interface.ts
server/models/tag.ts
server/models/user-interface.ts
server/models/user-video-rate-interface.ts
server/models/user-video-rate.ts
server/models/user.ts
server/models/utils.ts
server/models/video-abuse-interface.ts
server/models/video-blacklist-interface.ts
server/models/video-blacklist.ts
server/models/video-interface.ts
server/models/video-tag-interface.ts
server/models/video.ts
shared/index.ts [new file with mode: 0644]
shared/models/index.ts [new file with mode: 0644]
shared/models/pod.model.ts [new file with mode: 0644]
shared/models/user.model.ts [new file with mode: 0644]
shared/models/video-abuse.model.ts [new file with mode: 0644]
shared/models/video-blacklist.model.ts [new file with mode: 0644]
shared/models/video.model.ts [new file with mode: 0644]
yarn.lock

index e7d0c39a45577099737a7ca252664352d6bdff3a..71cd789ba305871bdfdaa139a954c4117845c1c9 100644 (file)
     "@types/config": "^0.0.32",
     "@types/express": "^4.0.35",
     "@types/lodash": "^4.14.64",
+    "@types/magnet-uri": "^5.1.1",
     "@types/mkdirp": "^0.3.29",
     "@types/morgan": "^1.7.32",
+    "@types/multer": "^0.0.34",
     "@types/node": "^7.0.18",
     "@types/request": "^0.0.43",
     "@types/sequelize": "^4.0.55",
index f6499556a0d4e249b93fd310722187d4ef2cc231..8c460096bef12ec15c7c9a1d0e8ed5dd49be3825 100644 (file)
@@ -1,6 +1,6 @@
 import * as express from 'express'
 
-import { CONFIG } from '../../initializers';
+import { CONFIG } from '../../initializers'
 import { logger } from '../../helpers'
 import { database as db } from '../../initializers/database'
 
@@ -9,7 +9,7 @@ const clientsRouter = express.Router()
 clientsRouter.get('/local', getLocalClient)
 
 // Get the client credentials for the PeerTube front end
-function getLocalClient (req, res, next) {
+function getLocalClient (req: express.Request, res: express.Response, next: express.NextFunction) {
   const serverHostname = CONFIG.WEBSERVER.HOSTNAME
   const serverPort = CONFIG.WEBSERVER.PORT
   let headerHostShouldBe = serverHostname
index 57c9398ecaafbd57a326b9ee02887fa5ca160dc2..c639817976a7ca6cb1cb1db88a1da9e3e4420a0b 100644 (file)
@@ -7,7 +7,7 @@ const configRouter = express.Router()
 configRouter.get('/', getConfig)
 
 // Get the client credentials for the PeerTube front end
-function getConfig (req, res, next) {
+function getConfig (req: express.Request, res: express.Response, next: express.NextFunction) {
   res.json({
     signup: {
       enabled: CONFIG.SIGNUP.ENABLED
index 98004544d05c1d8aa85ec244918461fd10a73bd5..ac3972ac63d8c00fb2aa5dea60d3ba604337836f 100644 (file)
@@ -28,6 +28,6 @@ export { apiRouter }
 
 // ---------------------------------------------------------------------------
 
-function pong (req, res, next) {
+function pong (req: express.Request, res: express.Response, next: express.NextFunction) {
   return res.send('pong').status(200).end()
 }
index a028c4ab9a1073b0debadf05a557902613199f1d..283105f6c39c8d4fac140167c2917016ae7b37c9 100644 (file)
@@ -21,6 +21,9 @@ import {
   setBodyHostPort,
   setBodyHostsPort
 } from '../../middlewares'
+import {
+  PodInstance
+} from '../../models'
 
 const podsRouter = express.Router()
 
@@ -51,10 +54,10 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function addPods (req, res, next) {
+function addPods (req: express.Request, res: express.Response, next: express.NextFunction) {
   const informations = req.body
 
-  waterfall([
+  waterfall<string, Error>([
     function addPod (callback) {
       const pod = db.Pod.build(informations)
       pod.save().asCallback(function (err, podCreated) {
@@ -63,7 +66,7 @@ function addPods (req, res, next) {
       })
     },
 
-    function sendMyVideos (podCreated, callback) {
+    function sendMyVideos (podCreated: PodInstance, callback) {
       sendOwnedVideosToPod(podCreated.id)
 
       callback(null)
@@ -86,7 +89,7 @@ function addPods (req, res, next) {
   })
 }
 
-function listPods (req, res, next) {
+function listPods (req: express.Request, res: express.Response, next: express.NextFunction) {
   db.Pod.list(function (err, podsList) {
     if (err) return next(err)
 
@@ -94,8 +97,8 @@ function listPods (req, res, next) {
   })
 }
 
-function makeFriendsController (req, res, next) {
-  const hosts = req.body.hosts
+function makeFriendsController (req: express.Request, res: express.Response, next: express.NextFunction) {
+  const hosts = req.body.hosts as string[]
 
   makeFriends(hosts, function (err) {
     if (err) {
@@ -109,7 +112,7 @@ function makeFriendsController (req, res, next) {
   res.type('json').status(204).end()
 }
 
-function quitFriendsController (req, res, next) {
+function quitFriendsController (req: express.Request, res: express.Response, next: express.NextFunction) {
   quitFriends(function (err) {
     if (err) return next(err)
 
index 9c9d2164d9b8b342aacb5e7aff7d703267cbf54c..b0d6642c13bfe71edbad706b5b8fd15ee8c7ed4c 100644 (file)
@@ -21,7 +21,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function removePods (req, res, next) {
+function removePods (req: express.Request, res: express.Response, next: express.NextFunction) {
   const host = req.body.signature.host
 
   waterfall([
index d97a3db31ef0683a34d5c4cd973c74d6be8d0449..d9cc08fb41710c13b92d18aaf07b808eb064679f 100644 (file)
@@ -1,4 +1,5 @@
 import * as express from 'express'
+import * as Sequelize from 'sequelize'
 import { eachSeries, waterfall } from 'async'
 
 import { database as db } from '../../../initializers/database'
@@ -23,6 +24,7 @@ import {
   startSerializableTransaction
 } from '../../../helpers'
 import { quickAndDirtyUpdatesVideoToFriends } from '../../../lib'
+import { PodInstance, VideoInstance } from '../../../models'
 
 const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
 
@@ -64,7 +66,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function remoteVideos (req, res, next) {
+function remoteVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
   const requests = req.body.data
   const fromPod = res.locals.secure.pod
 
@@ -89,7 +91,7 @@ function remoteVideos (req, res, next) {
   return res.type('json').status(204).end()
 }
 
-function remoteVideosQadu (req, res, next) {
+function remoteVideosQadu (req: express.Request, res: express.Response, next: express.NextFunction) {
   const requests = req.body.data
   const fromPod = res.locals.secure.pod
 
@@ -104,7 +106,7 @@ function remoteVideosQadu (req, res, next) {
   return res.type('json').status(204).end()
 }
 
-function remoteVideosEvents (req, res, next) {
+function remoteVideosEvents (req: express.Request, res: express.Response, next: express.NextFunction) {
   const requests = req.body.data
   const fromPod = res.locals.secure.pod
 
@@ -119,7 +121,7 @@ function remoteVideosEvents (req, res, next) {
   return res.type('json').status(204).end()
 }
 
-function processVideosEventsRetryWrapper (eventData, fromPod, finalCallback) {
+function processVideosEventsRetryWrapper (eventData: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
   const options = {
     arguments: [ eventData, fromPod ],
     errorMessage: 'Cannot process videos events with many retries.'
@@ -128,7 +130,7 @@ function processVideosEventsRetryWrapper (eventData, fromPod, finalCallback) {
   retryTransactionWrapper(processVideosEvents, options, finalCallback)
 }
 
-function processVideosEvents (eventData, fromPod, finalCallback) {
+function processVideosEvents (eventData: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
   waterfall([
     startSerializableTransaction,
 
@@ -187,7 +189,7 @@ function processVideosEvents (eventData, fromPod, finalCallback) {
 
     commitTransaction
 
-  ], function (err, t) {
+  ], function (err: Error, t: Sequelize.Transaction) {
     if (err) {
       logger.debug('Cannot process a video event.', { error: err })
       return rollbackTransaction(err, t, finalCallback)
@@ -198,7 +200,7 @@ function processVideosEvents (eventData, fromPod, finalCallback) {
   })
 }
 
-function quickAndDirtyUpdateVideoRetryWrapper (videoData, fromPod, finalCallback) {
+function quickAndDirtyUpdateVideoRetryWrapper (videoData: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
   const options = {
     arguments: [ videoData, fromPod ],
     errorMessage: 'Cannot update quick and dirty the remote video with many retries.'
@@ -207,7 +209,7 @@ function quickAndDirtyUpdateVideoRetryWrapper (videoData, fromPod, finalCallback
   retryTransactionWrapper(quickAndDirtyUpdateVideo, options, finalCallback)
 }
 
-function quickAndDirtyUpdateVideo (videoData, fromPod, finalCallback) {
+function quickAndDirtyUpdateVideo (videoData: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
   let videoName
 
   waterfall([
@@ -243,7 +245,7 @@ function quickAndDirtyUpdateVideo (videoData, fromPod, finalCallback) {
 
     commitTransaction
 
-  ], function (err, t) {
+  ], function (err: Error, t: Sequelize.Transaction) {
     if (err) {
       logger.debug('Cannot quick and dirty update the remote video.', { error: err })
       return rollbackTransaction(err, t, finalCallback)
@@ -255,7 +257,7 @@ function quickAndDirtyUpdateVideo (videoData, fromPod, finalCallback) {
 }
 
 // Handle retries on fail
-function addRemoteVideoRetryWrapper (videoToCreateData, fromPod, finalCallback) {
+function addRemoteVideoRetryWrapper (videoToCreateData: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
   const options = {
     arguments: [ videoToCreateData, fromPod ],
     errorMessage: 'Cannot insert the remote video with many retries.'
@@ -264,7 +266,7 @@ function addRemoteVideoRetryWrapper (videoToCreateData, fromPod, finalCallback)
   retryTransactionWrapper(addRemoteVideo, options, finalCallback)
 }
 
-function addRemoteVideo (videoToCreateData, fromPod, finalCallback) {
+function addRemoteVideo (videoToCreateData: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
   logger.debug('Adding remote video "%s".', videoToCreateData.remoteId)
 
   waterfall([
@@ -359,7 +361,7 @@ function addRemoteVideo (videoToCreateData, fromPod, finalCallback) {
 
     commitTransaction
 
-  ], function (err, t) {
+  ], function (err: Error, t: Sequelize.Transaction) {
     if (err) {
       // This is just a debug because we will retry the insert
       logger.debug('Cannot insert the remote video.', { error: err })
@@ -372,7 +374,7 @@ function addRemoteVideo (videoToCreateData, fromPod, finalCallback) {
 }
 
 // Handle retries on fail
-function updateRemoteVideoRetryWrapper (videoAttributesToUpdate, fromPod, finalCallback) {
+function updateRemoteVideoRetryWrapper (videoAttributesToUpdate: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
   const options = {
     arguments: [ videoAttributesToUpdate, fromPod ],
     errorMessage: 'Cannot update the remote video with many retries'
@@ -381,7 +383,7 @@ function updateRemoteVideoRetryWrapper (videoAttributesToUpdate, fromPod, finalC
   retryTransactionWrapper(updateRemoteVideo, options, finalCallback)
 }
 
-function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) {
+function updateRemoteVideo (videoAttributesToUpdate: any, fromPod: PodInstance, finalCallback: (err: Error) => void) {
   logger.debug('Updating remote video "%s".', videoAttributesToUpdate.remoteId)
 
   waterfall([
@@ -435,7 +437,7 @@ function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) {
 
     commitTransaction
 
-  ], function (err, t) {
+  ], function (err: Error, t: Sequelize.Transaction) {
     if (err) {
       // This is just a debug because we will retry the insert
       logger.debug('Cannot update the remote video.', { error: err })
@@ -447,7 +449,7 @@ function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) {
   })
 }
 
-function removeRemoteVideo (videoToRemoveData, fromPod, callback) {
+function removeRemoteVideo (videoToRemoveData: any, fromPod: PodInstance, callback: (err: Error) => void) {
   // We need the instance because we have to remove some other stuffs (thumbnail etc)
   fetchRemoteVideo(fromPod.host, videoToRemoveData.remoteId, function (err, video) {
     // Do not return the error, continue the process
@@ -465,7 +467,7 @@ function removeRemoteVideo (videoToRemoveData, fromPod, callback) {
   })
 }
 
-function reportAbuseRemoteVideo (reportData, fromPod, callback) {
+function reportAbuseRemoteVideo (reportData: any, fromPod: PodInstance, callback: (err: Error) => void) {
   fetchOwnedVideo(reportData.videoRemoteId, function (err, video) {
     if (err || !video) {
       if (!err) err = new Error('video not found')
@@ -494,7 +496,7 @@ function reportAbuseRemoteVideo (reportData, fromPod, callback) {
   })
 }
 
-function fetchOwnedVideo (id, callback) {
+function fetchOwnedVideo (id: string, callback: (err: Error, video?: VideoInstance) => void) {
   db.Video.load(id, function (err, video) {
     if (err || !video) {
       if (!err) err = new Error('video not found')
@@ -507,7 +509,7 @@ function fetchOwnedVideo (id, callback) {
   })
 }
 
-function fetchRemoteVideo (podHost, remoteId, callback) {
+function fetchRemoteVideo (podHost: string, remoteId: string, callback: (err: Error, video?: VideoInstance) => void) {
   db.Video.loadByHostAndRemoteId(podHost, remoteId, function (err, video) {
     if (err || !video) {
       if (!err) err = new Error('video not found')
index ff4b4ac1ab85e0ad0525645b466bc222a64c5f94..2c18fe04608f6ec79161db35d0e739d44e83b9f7 100644 (file)
@@ -2,6 +2,7 @@ import * as express from 'express'
 import { parallel } from 'async'
 
 import {
+  BaseRequestScheduler,
   getRequestScheduler,
   getRequestVideoQaduScheduler,
   getRequestVideoEventScheduler
@@ -24,7 +25,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function getStatsRequests (req, res, next) {
+function getStatsRequests (req: express.Request, res: express.Response, next: express.NextFunction) {
   parallel({
     requestScheduler: buildRequestSchedulerFunction(getRequestScheduler()),
     requestVideoQaduScheduler: buildRequestSchedulerFunction(getRequestVideoQaduScheduler()),
@@ -38,7 +39,7 @@ function getStatsRequests (req, res, next) {
 
 // ---------------------------------------------------------------------------
 
-function buildRequestSchedulerFunction (requestScheduler) {
+function buildRequestSchedulerFunction (requestScheduler: BaseRequestScheduler) {
   return function (callback) {
     requestScheduler.remainingRequestsCount(function (err, count) {
       if (err) return callback(err)
index 44c5ec13c8f21e2f238ded0e05b00fc5e41c063b..ffe5881e5594040e6a5cb9f99fcaf84cee6e59bd 100644 (file)
@@ -76,7 +76,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function ensureRegistrationEnabled (req, res, next) {
+function ensureRegistrationEnabled (req: express.Request, res: express.Response, next: express.NextFunction) {
   const registrationEnabled = CONFIG.SIGNUP.ENABLED
 
   if (registrationEnabled === true) {
@@ -86,7 +86,7 @@ function ensureRegistrationEnabled (req, res, next) {
   return res.status(400).send('User registration is not enabled.')
 }
 
-function createUser (req, res, next) {
+function createUser (req: express.Request, res: express.Response, next: express.NextFunction) {
   const user = db.User.build({
     username: req.body.username,
     password: req.body.password,
@@ -95,14 +95,14 @@ function createUser (req, res, next) {
     role: USER_ROLES.USER
   })
 
-  user.save().asCallback(function (err, createdUser) {
+  user.save().asCallback(function (err) {
     if (err) return next(err)
 
     return res.type('json').status(204).end()
   })
 }
 
-function getUserInformation (req, res, next) {
+function getUserInformation (req: express.Request, res: express.Response, next: express.NextFunction) {
   db.User.loadByUsername(res.locals.oauth.token.user.username, function (err, user) {
     if (err) return next(err)
 
@@ -110,9 +110,9 @@ function getUserInformation (req, res, next) {
   })
 }
 
-function getUserVideoRating (req, res, next) {
-  const videoId = req.params.videoId
-  const userId = res.locals.oauth.token.User.id
+function getUserVideoRating (req: express.Request, res: express.Response, next: express.NextFunction) {
+  const videoId = '' + req.params.videoId
+  const userId = +res.locals.oauth.token.User.id
 
   db.UserVideoRate.load(userId, videoId, null, function (err, ratingObj) {
     if (err) return next(err)
@@ -126,7 +126,7 @@ function getUserVideoRating (req, res, next) {
   })
 }
 
-function listUsers (req, res, next) {
+function listUsers (req: express.Request, res: express.Response, next: express.NextFunction) {
   db.User.listForApi(req.query.start, req.query.count, req.query.sort, function (err, usersList, usersTotal) {
     if (err) return next(err)
 
@@ -134,7 +134,7 @@ function listUsers (req, res, next) {
   })
 }
 
-function removeUser (req, res, next) {
+function removeUser (req: express.Request, res: express.Response, next: express.NextFunction) {
   waterfall([
     function loadUser (callback) {
       db.User.loadById(req.params.id, callback)
@@ -153,7 +153,7 @@ function removeUser (req, res, next) {
   })
 }
 
-function updateUser (req, res, next) {
+function updateUser (req: express.Request, res: express.Response, next: express.NextFunction) {
   db.User.loadByUsername(res.locals.oauth.token.user.username, function (err, user) {
     if (err) return next(err)
 
@@ -168,6 +168,6 @@ function updateUser (req, res, next) {
   })
 }
 
-function success (req, res, next) {
+function success (req: express.Request, res: express.Response, next: express.NextFunction) {
   res.end()
 }
index 68db025b7f3bf67a0ec079b61039bdd5fdd01171..78e8e8b3d7ed9bf188731640c016e7e44d1d5238 100644 (file)
@@ -1,4 +1,5 @@
 import * as express from 'express'
+import * as Sequelize from 'sequelize'
 import { waterfall } from 'async'
 
 import { database as db } from '../../../initializers/database'
@@ -46,7 +47,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function listVideoAbuses (req, res, next) {
+function listVideoAbuses (req: express.Request, res: express.Response, next: express.NextFunction) {
   db.VideoAbuse.listForApi(req.query.start, req.query.count, req.query.sort, function (err, abusesList, abusesTotal) {
     if (err) return next(err)
 
@@ -54,7 +55,7 @@ function listVideoAbuses (req, res, next) {
   })
 }
 
-function reportVideoAbuseRetryWrapper (req, res, next) {
+function reportVideoAbuseRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
   const options = {
     arguments: [ req, res ],
     errorMessage: 'Cannot report abuse to the video with many retries.'
@@ -67,7 +68,7 @@ function reportVideoAbuseRetryWrapper (req, res, next) {
   })
 }
 
-function reportVideoAbuse (req, res, finalCallback) {
+function reportVideoAbuse (req: express.Request, res: express.Response, finalCallback: (err: Error) => void) {
   const videoInstance = res.locals.video
   const reporterUsername = res.locals.oauth.token.User.username
 
@@ -105,7 +106,7 @@ function reportVideoAbuse (req, res, finalCallback) {
 
     commitTransaction
 
-  ], function andFinally (err, t) {
+  ], function andFinally (err: Error, t: Sequelize.Transaction) {
     if (err) {
       logger.debug('Cannot update the video.', { error: err })
       return rollbackTransaction(err, t, finalCallback)
index 58960798bd503cfd2978f411a9352f3d9a795686..4b42fc2d703c17a3eb867f2db8b5f4fd4166a15d 100644 (file)
@@ -25,7 +25,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function addVideoToBlacklist (req, res, next) {
+function addVideoToBlacklist (req: express.Request, res: express.Response, next: express.NextFunction) {
   const videoInstance = res.locals.video
 
   const toCreate = {
index b82b0936f13674fcae423411ebb73ec6a18053b2..bfa018031d4a767a69e2253d78fafea8c12e646c 100644 (file)
@@ -1,4 +1,5 @@
 import * as express from 'express'
+import * as Sequelize from 'sequelize'
 import * as fs from 'fs'
 import * as multer from 'multer'
 import * as path from 'path'
@@ -124,21 +125,21 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function listVideoCategories (req, res, next) {
+function listVideoCategories (req: express.Request, res: express.Response, next: express.NextFunction) {
   res.json(VIDEO_CATEGORIES)
 }
 
-function listVideoLicences (req, res, next) {
+function listVideoLicences (req: express.Request, res: express.Response, next: express.NextFunction) {
   res.json(VIDEO_LICENCES)
 }
 
-function listVideoLanguages (req, res, next) {
+function listVideoLanguages (req: express.Request, res: express.Response, next: express.NextFunction) {
   res.json(VIDEO_LANGUAGES)
 }
 
 // Wrapper to video add that retry the function if there is a database error
 // We need this because we run the transaction in SERIALIZABLE isolation that can fail
-function addVideoRetryWrapper (req, res, next) {
+function addVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
   const options = {
     arguments: [ req, res, req.files.videofile[0] ],
     errorMessage: 'Cannot insert the video with many retries.'
@@ -152,7 +153,7 @@ function addVideoRetryWrapper (req, res, next) {
   })
 }
 
-function addVideo (req, res, videoFile, finalCallback) {
+function addVideo (req: express.Request, res: express.Response, videoFile: Express.Multer.File, finalCallback: (err: Error) => void) {
   const videoInfos = req.body
 
   waterfall([
@@ -190,7 +191,7 @@ function addVideo (req, res, videoFile, finalCallback) {
         language: videoInfos.language,
         nsfw: videoInfos.nsfw,
         description: videoInfos.description,
-        duration: videoFile.duration,
+        duration: videoFile['duration'], // duration was added by a previous middleware
         authorId: author.id
       }
 
@@ -254,7 +255,7 @@ function addVideo (req, res, videoFile, finalCallback) {
 
     commitTransaction
 
-  ], function andFinally (err, t) {
+  ], function andFinally (err: Error, t: Sequelize.Transaction) {
     if (err) {
       // This is just a debug because we will retry the insert
       logger.debug('Cannot insert the video.', { error: err })
@@ -266,7 +267,7 @@ function addVideo (req, res, videoFile, finalCallback) {
   })
 }
 
-function updateVideoRetryWrapper (req, res, next) {
+function updateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
   const options = {
     arguments: [ req, res ],
     errorMessage: 'Cannot update the video with many retries.'
@@ -280,7 +281,7 @@ function updateVideoRetryWrapper (req, res, next) {
   })
 }
 
-function updateVideo (req, res, finalCallback) {
+function updateVideo (req: express.Request, res: express.Response, finalCallback: (err: Error) => void) {
   const videoInstance = res.locals.video
   const videoFieldsSave = videoInstance.toJSON()
   const videoInfosToUpdate = req.body
@@ -341,7 +342,7 @@ function updateVideo (req, res, finalCallback) {
 
     commitTransaction
 
-  ], function andFinally (err, t) {
+  ], function andFinally (err: Error, t: Sequelize.Transaction) {
     if (err) {
       logger.debug('Cannot update the video.', { error: err })
 
@@ -361,7 +362,7 @@ function updateVideo (req, res, finalCallback) {
   })
 }
 
-function getVideo (req, res, next) {
+function getVideo (req: express.Request, res: express.Response, next: express.NextFunction) {
   const videoInstance = res.locals.video
 
   if (videoInstance.isOwned()) {
@@ -393,7 +394,7 @@ function getVideo (req, res, next) {
   res.json(videoInstance.toFormatedJSON())
 }
 
-function listVideos (req, res, next) {
+function listVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
   db.Video.listForApi(req.query.start, req.query.count, req.query.sort, function (err, videosList, videosTotal) {
     if (err) return next(err)
 
@@ -401,7 +402,7 @@ function listVideos (req, res, next) {
   })
 }
 
-function removeVideo (req, res, next) {
+function removeVideo (req: express.Request, res: express.Response, next: express.NextFunction) {
   const videoInstance = res.locals.video
 
   videoInstance.destroy().asCallback(function (err) {
@@ -414,7 +415,7 @@ function removeVideo (req, res, next) {
   })
 }
 
-function searchVideos (req, res, next) {
+function searchVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
   db.Video.searchAndPopulateAuthorAndPodAndTags(
     req.params.value, req.query.field, req.query.start, req.query.count, req.query.sort,
     function (err, videosList, videosTotal) {
index 1bc575675ae93bb2ff6e1056b97f5b069a062e58..afdd099f8defdb8d875fadbf26cbe760302e45db 100644 (file)
@@ -1,4 +1,5 @@
 import * as express from 'express'
+import * as Sequelize from 'sequelize'
 import { waterfall } from 'async'
 
 import { database as db } from '../../../initializers/database'
@@ -39,7 +40,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function rateVideoRetryWrapper (req, res, next) {
+function rateVideoRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
   const options = {
     arguments: [ req, res ],
     errorMessage: 'Cannot update the user video rate.'
@@ -52,7 +53,7 @@ function rateVideoRetryWrapper (req, res, next) {
   })
 }
 
-function rateVideo (req, res, finalCallback) {
+function rateVideo (req: express.Request, res: express.Response, finalCallback: (err: Error) => void) {
   const rateType = req.body.rating
   const videoInstance = res.locals.video
   const userInstance = res.locals.oauth.token.User
@@ -168,7 +169,7 @@ function rateVideo (req, res, finalCallback) {
 
     commitTransaction
 
-  ], function (err, t) {
+  ], function (err: Error, t: Sequelize.Transaction) {
     if (err) {
       // This is just a debug because we will retry the insert
       logger.debug('Cannot add the user video rate.', { error: err })
index c3d28245c329bfc5d180d0073a21389abc893b1a..503eff75013ab5c58bf80869e3b0b0c24ecde67e 100644 (file)
@@ -12,6 +12,7 @@ import {
   STATIC_MAX_AGE
 } from '../initializers'
 import { root } from '../helpers'
+import { VideoInstance } from '../models'
 
 const clientsRouter = express.Router()
 
@@ -25,7 +26,7 @@ const indexPath = join(distPath, 'index.html')
 // Do not use a template engine for a so little thing
 clientsRouter.use('/videos/watch/:id', generateWatchHtmlPage)
 
-clientsRouter.use('/videos/embed', function (req, res, next) {
+clientsRouter.use('/videos/embed', function (req: express.Request, res: express.Response, next: express.NextFunction) {
   res.sendFile(embedPath)
 })
 
@@ -33,7 +34,7 @@ clientsRouter.use('/videos/embed', function (req, res, next) {
 clientsRouter.use('/client', express.static(distPath, { maxAge: STATIC_MAX_AGE }))
 
 // 404 for static files not found
-clientsRouter.use('/client/*', function (req, res, next) {
+clientsRouter.use('/client/*', function (req: express.Request, res: express.Response, next: express.NextFunction) {
   res.sendStatus(404)
 })
 
@@ -45,7 +46,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function addOpenGraphTags (htmlStringPage, video) {
+function addOpenGraphTags (htmlStringPage: string, video: VideoInstance) {
   let basePreviewUrlHttp
 
   if (video.isOwned()) {
@@ -88,8 +89,8 @@ function addOpenGraphTags (htmlStringPage, video) {
   return htmlStringPage.replace(opengraphComment, tagsString)
 }
 
-function generateWatchHtmlPage (req, res, next) {
-  const videoId = req.params.id
+function generateWatchHtmlPage (req: express.Request, res: express.Response, next: express.NextFunction) {
+  const videoId = '' + req.params.id
 
   // Let Angular application handle errors
   if (!validator.isUUID(videoId, 4)) return res.sendFile(indexPath)
@@ -102,7 +103,7 @@ function generateWatchHtmlPage (req, res, next) {
     video: function (callback) {
       db.Video.loadAndPopulateAuthorAndPodAndTags(videoId, callback)
     }
-  }, function (err, result: any) {
+  }, function (err: Error, result: { file: Buffer, video: VideoInstance }) {
     if (err) return next(err)
 
     const html = result.file.toString()
index 83f50a7fef69e92325d07d5c6fb0e8a29ccaa50f..b1291ba7a5b38a8f91a9e5a6f1d14c068d1731ee 100644 (file)
@@ -1,8 +1,8 @@
-function exists (value) {
+function exists (value: any) {
   return value !== undefined && value !== null
 }
 
-function isArray (value) {
+function isArray (value: any) {
   return Array.isArray(value)
 }
 
@@ -12,3 +12,12 @@ export {
   exists,
   isArray
 }
+
+declare global {
+  namespace ExpressValidator {
+    export interface Validator {
+      exists,
+      isArray
+    }
+  }
+}
index ee939ad04b0053722fd281d7ab12a98326ec5066..ec9f26cc8444caab3671f06870f4fc31ea8ed488 100644 (file)
@@ -1,12 +1,12 @@
 import * as validator from 'validator'
 
-import { isArray } from './misc'
+import { isArray, exists } from './misc'
 
-function isHostValid (host) {
-  return validator.isURL(host) && host.split('://').length === 1
+function isHostValid (host: string) {
+  return exists(host) && validator.isURL(host) && host.split('://').length === 1
 }
 
-function isEachUniqueHostValid (hosts) {
+function isEachUniqueHostValid (hosts: string[]) {
   return isArray(hosts) &&
     hosts.length !== 0 &&
     hosts.every(function (host) {
@@ -20,3 +20,12 @@ export {
   isEachUniqueHostValid,
   isHostValid
 }
+
+declare global {
+  namespace ExpressValidator {
+    export interface Validator {
+      isEachUniqueHostValid
+      isHostValid
+    }
+  }
+}
index d6f9a7e77c86aefdd910299f834923f65582a2c7..e29a9b7670f6e0e0a7393b6f22c6df54784810f9 100644 (file)
@@ -1 +1 @@
-export * from './videos';
+export * from './videos'
index 4b904d011a85328d084d08fdbd3f33326a6b78ef..1df7316aa8cbc2cc7cb766bfa8ea19ed31143adb 100644 (file)
@@ -31,7 +31,7 @@ import {
 
 const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
 
-function isEachRemoteRequestVideosValid (requests) {
+function isEachRemoteRequestVideosValid (requests: any[]) {
   return isArray(requests) &&
     requests.every(function (request) {
       const video = request.data
@@ -61,7 +61,7 @@ function isEachRemoteRequestVideosValid (requests) {
     })
 }
 
-function isEachRemoteRequestVideosQaduValid (requests) {
+function isEachRemoteRequestVideosQaduValid (requests: any[]) {
   return isArray(requests) &&
     requests.every(function (request) {
       const video = request.data
@@ -70,14 +70,14 @@ function isEachRemoteRequestVideosQaduValid (requests) {
 
       return (
         isVideoRemoteIdValid(video.remoteId) &&
-        (has(video, 'views') === false || isVideoViewsValid) &&
-        (has(video, 'likes') === false || isVideoLikesValid) &&
-        (has(video, 'dislikes') === false || isVideoDislikesValid)
+        (has(video, 'views') === false || isVideoViewsValid(video.views)) &&
+        (has(video, 'likes') === false || isVideoLikesValid(video.likes)) &&
+        (has(video, 'dislikes') === false || isVideoDislikesValid(video.dislikes))
       )
     })
 }
 
-function isEachRemoteRequestVideosEventsValid (requests) {
+function isEachRemoteRequestVideosEventsValid (requests: any[]) {
   return isArray(requests) &&
     requests.every(function (request) {
       const eventData = request.data
@@ -100,9 +100,19 @@ export {
   isEachRemoteRequestVideosEventsValid
 }
 
+declare global {
+  namespace ExpressValidator {
+    export interface Validator {
+      isEachRemoteRequestVideosValid,
+      isEachRemoteRequestVideosQaduValid,
+      isEachRemoteRequestVideosEventsValid
+    }
+  }
+}
+
 // ---------------------------------------------------------------------------
 
-function isCommonVideoAttributesValid (video) {
+function isCommonVideoAttributesValid (video: any) {
   return isVideoDateValid(video.createdAt) &&
          isVideoDateValid(video.updatedAt) &&
          isVideoCategoryValid(video.category) &&
@@ -121,18 +131,18 @@ function isCommonVideoAttributesValid (video) {
          isVideoDislikesValid(video.dislikes)
 }
 
-function isRequestTypeAddValid (value) {
+function isRequestTypeAddValid (value: string) {
   return value === ENDPOINT_ACTIONS.ADD
 }
 
-function isRequestTypeUpdateValid (value) {
+function isRequestTypeUpdateValid (value: string) {
   return value === ENDPOINT_ACTIONS.UPDATE
 }
 
-function isRequestTypeRemoveValid (value) {
+function isRequestTypeRemoveValid (value: string) {
   return value === ENDPOINT_ACTIONS.REMOVE
 }
 
-function isRequestTypeReportAbuseValid (value) {
+function isRequestTypeReportAbuseValid (value: string) {
   return value === ENDPOINT_ACTIONS.REPORT_ABUSE
 }
index f303ab8db2f5be4ea43bc69ee0663ce06d687371..7792ffd74eb82865f65dede8f37a36a6373b5dc7 100644 (file)
@@ -1,25 +1,26 @@
 import { values } from 'lodash'
 import * as validator from 'validator'
 
+import { exists } from './misc'
 import { CONSTRAINTS_FIELDS, USER_ROLES } from '../../initializers'
 const USERS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.USERS
 
-function isUserPasswordValid (value) {
+function isUserPasswordValid (value: string) {
   return validator.isLength(value, USERS_CONSTRAINTS_FIELDS.PASSWORD)
 }
 
-function isUserRoleValid (value) {
+function isUserRoleValid (value: string) {
   return values(USER_ROLES).indexOf(value) !== -1
 }
 
-function isUserUsernameValid (value) {
+function isUserUsernameValid (value: string) {
   const max = USERS_CONSTRAINTS_FIELDS.USERNAME.max
   const min = USERS_CONSTRAINTS_FIELDS.USERNAME.min
-  return validator.matches(value, new RegExp(`^[a-zA-Z0-9._]{${min},${max}}$`))
+  return exists(value) && validator.matches(value, new RegExp(`^[a-zA-Z0-9._]{${min},${max}}$`))
 }
 
-function isUserDisplayNSFWValid (value) {
-  return validator.isBoolean(value)
+function isUserDisplayNSFWValid (value: any) {
+  return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value))
 }
 
 // ---------------------------------------------------------------------------
@@ -30,3 +31,14 @@ export {
   isUserUsernameValid,
   isUserDisplayNSFWValid
 }
+
+declare global {
+  namespace ExpressValidator {
+    export interface Validator {
+      isUserPasswordValid,
+      isUserRoleValid,
+      isUserUsernameValid,
+      isUserDisplayNSFWValid
+    }
+  }
+}
index 6389998e1320c831d0891d5cf78f76756c04a1f2..c5ef4cb5f3308fd8d8b8c899ba2f27982dd13ae3 100644 (file)
@@ -9,105 +9,105 @@ import {
   VIDEO_RATE_TYPES
 } from '../../initializers'
 import { isUserUsernameValid } from './users'
-import { isArray } from './misc'
+import { isArray, exists } from './misc'
 
 const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
 const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES
 const VIDEO_EVENTS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_EVENTS
 
-function isVideoAuthorValid (value) {
+function isVideoAuthorValid (value: string) {
   return isUserUsernameValid(value)
 }
 
-function isVideoDateValid (value) {
-  return validator.isDate(value)
+function isVideoDateValid (value: string) {
+  return exists(value) && validator.isISO8601(value)
 }
 
-function isVideoCategoryValid (value) {
+function isVideoCategoryValid (value: number) {
   return VIDEO_CATEGORIES[value] !== undefined
 }
 
-function isVideoLicenceValid (value) {
+function isVideoLicenceValid (value: number) {
   return VIDEO_LICENCES[value] !== undefined
 }
 
-function isVideoLanguageValid (value) {
+function isVideoLanguageValid (value: number) {
   return value === null || VIDEO_LANGUAGES[value] !== undefined
 }
 
-function isVideoNSFWValid (value) {
-  return validator.isBoolean(value)
+function isVideoNSFWValid (value: any) {
+  return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value))
 }
 
-function isVideoDescriptionValid (value) {
-  return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION)
+function isVideoDescriptionValid (value: string) {
+  return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION)
 }
 
-function isVideoDurationValid (value) {
-  return validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
+function isVideoDurationValid (value: string) {
+  return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
 }
 
-function isVideoExtnameValid (value) {
+function isVideoExtnameValid (value: string) {
   return VIDEOS_CONSTRAINTS_FIELDS.EXTNAME.indexOf(value) !== -1
 }
 
-function isVideoInfoHashValid (value) {
-  return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
+function isVideoInfoHashValid (value: string) {
+  return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
 }
 
-function isVideoNameValid (value) {
-  return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
+function isVideoNameValid (value: string) {
+  return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
 }
 
-function isVideoTagsValid (tags) {
+function isVideoTagsValid (tags: string[]) {
   return isArray(tags) &&
-         validator.isInt(tags.length, VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
+         validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
          tags.every(function (tag) {
-           return validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
+           return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
          })
 }
 
-function isVideoThumbnailValid (value) {
-  return validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL)
+function isVideoThumbnailValid (value: string) {
+  return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL)
 }
 
-function isVideoThumbnailDataValid (value) {
-  return validator.isByteLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL_DATA)
+function isVideoThumbnailDataValid (value: string) {
+  return exists(value) && validator.isByteLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL_DATA)
 }
 
-function isVideoRemoteIdValid (value) {
-  return validator.isUUID(value, 4)
+function isVideoRemoteIdValid (value: string) {
+  return exists(value) && validator.isUUID(value, 4)
 }
 
-function isVideoAbuseReasonValid (value) {
-  return validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON)
+function isVideoAbuseReasonValid (value: string) {
+  return exists(value) && validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON)
 }
 
-function isVideoAbuseReporterUsernameValid (value) {
+function isVideoAbuseReporterUsernameValid (value: string) {
   return isUserUsernameValid(value)
 }
 
-function isVideoViewsValid (value) {
-  return validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
+function isVideoViewsValid (value: string) {
+  return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
 }
 
-function isVideoLikesValid (value) {
-  return validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.LIKES)
+function isVideoLikesValid (value: string) {
+  return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.LIKES)
 }
 
-function isVideoDislikesValid (value) {
-  return validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DISLIKES)
+function isVideoDislikesValid (value: string) {
+  return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DISLIKES)
 }
 
-function isVideoEventCountValid (value) {
-  return validator.isInt(value + '', VIDEO_EVENTS_CONSTRAINTS_FIELDS.COUNT)
+function isVideoEventCountValid (value: string) {
+  return exists(value) && validator.isInt(value + '', VIDEO_EVENTS_CONSTRAINTS_FIELDS.COUNT)
 }
 
-function isVideoRatingTypeValid (value) {
+function isVideoRatingTypeValid (value: string) {
   return values(VIDEO_RATE_TYPES).indexOf(value) !== -1
 }
 
-function isVideoFile (value, files) {
+function isVideoFile (value: string, files: { [ fieldname: string ]: Express.Multer.File[] }) {
   // Should have files
   if (!files) return false
 
@@ -149,3 +149,33 @@ export {
   isVideoDislikesValid,
   isVideoEventCountValid
 }
+
+declare global {
+  namespace ExpressValidator {
+    export interface Validator {
+      isVideoAuthorValid,
+      isVideoDateValid,
+      isVideoCategoryValid,
+      isVideoLicenceValid,
+      isVideoLanguageValid,
+      isVideoNSFWValid,
+      isVideoDescriptionValid,
+      isVideoDurationValid,
+      isVideoInfoHashValid,
+      isVideoNameValid,
+      isVideoTagsValid,
+      isVideoThumbnailValid,
+      isVideoThumbnailDataValid,
+      isVideoExtnameValid,
+      isVideoRemoteIdValid,
+      isVideoAbuseReasonValid,
+      isVideoAbuseReporterUsernameValid,
+      isVideoFile,
+      isVideoViewsValid,
+      isVideoLikesValid,
+      isVideoRatingTypeValid,
+      isVideoDislikesValid,
+      isVideoEventCountValid
+    }
+  }
+}
index 4f49c58250abae92c230f737429008e7a287425e..f8ee9a45424e6c9e69fa70635e350cadeec1df17 100644 (file)
@@ -1,14 +1,15 @@
+import * as Sequelize from 'sequelize'
 // TODO: import from ES6 when retry typing file will include errorFilter function
 import * as retry from 'async/retry'
 
 import { database as db } from '../initializers/database'
 import { logger } from './logger'
 
-function commitTransaction (t, callback) {
+function commitTransaction (t: Sequelize.Transaction, callback: (err: Error) => void) {
   return t.commit().asCallback(callback)
 }
 
-function rollbackTransaction (err, t, callback) {
+function rollbackTransaction (err: Error, t: Sequelize.Transaction, callback: (err: Error) => void) {
   // Try to rollback transaction
   if (t) {
     // Do not catch err, report the original one
@@ -20,8 +21,8 @@ function rollbackTransaction (err, t, callback) {
   }
 }
 
-// { arguments, errorMessage }
-function retryTransactionWrapper (functionToRetry, options, finalCallback) {
+type RetryTransactionWrapperOptions = { errorMessage: string, arguments?: any[] }
+function retryTransactionWrapper (functionToRetry: Function, options: RetryTransactionWrapperOptions, finalCallback: Function) {
   const args = options.arguments ? options.arguments : []
 
   transactionRetryer(
@@ -39,7 +40,7 @@ function retryTransactionWrapper (functionToRetry, options, finalCallback) {
   )
 }
 
-function transactionRetryer (func, callback) {
+function transactionRetryer (func: Function, callback: (err: Error) => void) {
   retry({
     times: 5,
 
@@ -51,7 +52,7 @@ function transactionRetryer (func, callback) {
   }, func, callback)
 }
 
-function startSerializableTransaction (callback) {
+function startSerializableTransaction (callback: (err: Error, t: Sequelize.Transaction) => void) {
   db.sequelize.transaction(/* { isolationLevel: 'SERIALIZABLE' } */).asCallback(function (err, t) {
     // We force to return only two parameters
     return callback(err, t)
index feb32a4cd7a2374425c4342a8bdce0a03b904cb1..0ac87512704177f28fff94c7c90f38f6f883c4c4 100644 (file)
@@ -14,7 +14,7 @@ import {
 } from '../initializers'
 import { logger } from './logger'
 
-function checkSignature (publicKey, data, hexSignature) {
+function checkSignature (publicKey: string, data: string, hexSignature: string) {
   const verify = crypto.createVerify(SIGNATURE_ALGORITHM)
 
   let dataString
@@ -35,10 +35,10 @@ function checkSignature (publicKey, data, hexSignature) {
   return isValid
 }
 
-function sign (data) {
+function sign (data: string|Object) {
   const sign = crypto.createSign(SIGNATURE_ALGORITHM)
 
-  let dataString
+  let dataString: string
   if (typeof data === 'string') {
     dataString = data
   } else {
@@ -60,7 +60,7 @@ function sign (data) {
   return signature
 }
 
-function comparePassword (plainPassword, hashPassword, callback) {
+function comparePassword (plainPassword: string, hashPassword: string, callback: (err: Error, match?: boolean) => void) {
   bcrypt.compare(plainPassword, hashPassword, function (err, isPasswordMatch) {
     if (err) return callback(err)
 
@@ -68,7 +68,7 @@ function comparePassword (plainPassword, hashPassword, callback) {
   })
 }
 
-function createCertsIfNotExist (callback) {
+function createCertsIfNotExist (callback: (err: Error) => void) {
   certsExist(function (err, exist) {
     if (err) return callback(err)
 
@@ -82,7 +82,7 @@ function createCertsIfNotExist (callback) {
   })
 }
 
-function cryptPassword (password, callback) {
+function cryptPassword (password: string, callback: (err: Error, hash?: string) => void) {
   bcrypt.genSalt(BCRYPT_SALT_SIZE, function (err, salt) {
     if (err) return callback(err)
 
@@ -92,12 +92,12 @@ function cryptPassword (password, callback) {
   })
 }
 
-function getMyPrivateCert (callback) {
+function getMyPrivateCert (callback: (err: Error, privateCert: string) => void) {
   const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
   fs.readFile(certPath, 'utf8', callback)
 }
 
-function getMyPublicCert (callback) {
+function getMyPublicCert (callback: (err: Error, publicCert: string) => void) {
   const certPath = join(CONFIG.STORAGE.CERT_DIR, PUBLIC_CERT_NAME)
   fs.readFile(certPath, 'utf8', callback)
 }
@@ -116,7 +116,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function certsExist (callback) {
+function certsExist (callback: (err: Error, certsExist: boolean) => void) {
   const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
   fs.access(certPath, function (err) {
     // If there is an error the certificates do not exist
@@ -125,14 +125,14 @@ function certsExist (callback) {
   })
 }
 
-function createCerts (callback) {
+function createCerts (callback: (err: Error) => void) {
   certsExist(function (err, exist) {
     if (err) return callback(err)
 
     if (exist === true) {
-      const string = 'Certs already exist.'
-      logger.warning(string)
-      return callback(new Error(string))
+      const errorMessage = 'Certs already exist.'
+      logger.warning(errorMessage)
+      return callback(new Error(errorMessage))
     }
 
     logger.info('Generating a RSA key...')
index 48b1fd703122e1c4cb9013ccfa7f3409bca8c33a..b40fc8e39083101de377f64c70a9c60f35348e0f 100644 (file)
@@ -6,9 +6,15 @@ import {
   REMOTE_SCHEME,
   CONFIG
 } from '../initializers'
+import { PodInstance } from '../models'
 import { sign } from './peertube-crypto'
 
-function makeRetryRequest (params, callback) {
+type MakeRetryRequestParams = {
+  url: string,
+  method: 'GET'|'POST',
+  json: Object
+}
+function makeRetryRequest (params: MakeRetryRequestParams, callback: request.RequestCallback) {
   replay(
     request(params, callback),
     {
@@ -20,14 +26,21 @@ function makeRetryRequest (params, callback) {
   )
 }
 
-function makeSecureRequest (params, callback) {
+type MakeSecureRequestParams = {
+  method: 'GET'|'POST'
+  toPod: PodInstance
+  path: string
+  sign: boolean
+  data?: Object
+}
+function makeSecureRequest (params: MakeSecureRequestParams, callback: request.RequestCallback) {
   const requestParams = {
     url: REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path,
     json: {}
   }
 
   if (params.method !== 'POST') {
-    return callback(new Error('Cannot make a secure request with a non POST method.'))
+    return callback(new Error('Cannot make a secure request with a non POST method.'), null, null)
   }
 
   // Add signature if it is specified in the params
index bc76cfb267fabe92fd22b08c2e4cf007b04f0ed1..1dcbd31c4c8ad1a7f463502a30ed1ca883277aeb 100644 (file)
@@ -1,13 +1,15 @@
+import * as express from 'express'
+
 import { pseudoRandomBytes } from 'crypto'
 import { join } from 'path'
 
 import { logger } from './logger'
 
-function badRequest (req, res, next) {
+function badRequest (req: express.Request, res: express.Response, next: express.NextFunction) {
   res.type('json').status(400).end()
 }
 
-function generateRandomString (size, callback) {
+function generateRandomString (size: number, callback: (err: Error, randomString?: string) => void) {
   pseudoRandomBytes(size, function (err, raw) {
     if (err) return callback(err)
 
@@ -15,11 +17,6 @@ function generateRandomString (size, callback) {
   })
 }
 
-function cleanForExit (webtorrentProcess) {
-  logger.info('Gracefully exiting.')
-  process.kill(-webtorrentProcess.pid)
-}
-
 function createEmptyCallback () {
   return function (err) {
     if (err) logger.error('Error in empty callback.', { error: err })
@@ -27,10 +24,10 @@ function createEmptyCallback () {
 }
 
 function isTestInstance () {
-  return (process.env.NODE_ENV === 'test')
+  return process.env.NODE_ENV === 'test'
 }
 
-function getFormatedObjects (objects, objectsTotal) {
+function getFormatedObjects (objects: any[], objectsTotal: number) {
   const formatedObjects = []
 
   objects.forEach(function (object) {
@@ -53,7 +50,6 @@ function root () {
 export {
   badRequest,
   createEmptyCallback,
-  cleanForExit,
   generateRandomString,
   isTestInstance,
   getFormatedObjects,
index 8c3d64b6004b2c187a59b4eb4db73946b39ef060..7007f2c0b2fa92abbfc9ff6025fa2612e574541d 100644 (file)
@@ -23,7 +23,7 @@ function checkMissedConfig () {
     'storage.certs', 'storage.videos', 'storage.logs', 'storage.thumbnails', 'storage.previews',
     'admin.email', 'signup.enabled', 'transcoding.enabled', 'transcoding.threads'
   ]
-  const miss = []
+  const miss: string[] = []
 
   for (const key of required) {
     if (!config.has(key)) {
@@ -35,7 +35,7 @@ function checkMissedConfig () {
 }
 
 // Check the available codecs
-function checkFFmpeg (callback) {
+function checkFFmpeg (callback: (err: Error) => void) {
   const Ffmpeg = require('fluent-ffmpeg')
 
   Ffmpeg.getAvailableCodecs(function (err, codecs) {
@@ -57,7 +57,7 @@ function checkFFmpeg (callback) {
   })
 }
 
-function clientsExist (callback) {
+function clientsExist (callback: (err: Error, clientsExist?: boolean) => void) {
   db.OAuthClient.countTotal(function (err, totalClients) {
     if (err) return callback(err)
 
@@ -65,7 +65,7 @@ function clientsExist (callback) {
   })
 }
 
-function usersExist (callback) {
+function usersExist (callback: (err: Error, usersExist?: boolean) => void) {
   db.User.countTotal(function (err, totalUsers) {
     if (err) return callback(err)
 
index 7ab019f4446e682865b215a1b736b6be50f1cce2..6dcb4bb91ef2a6b01a18395cf086e52eb2a2df14 100644 (file)
@@ -202,7 +202,7 @@ const REQUEST_ENDPOINTS = {
   VIDEOS: 'videos'
 }
 
-const REQUEST_ENDPOINT_ACTIONS = {}
+const REQUEST_ENDPOINT_ACTIONS: { [ id: string ]: any } = {}
 REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS] = {
   ADD: 'add',
   UPDATE: 'update',
index b0f47876e93d48d114c4d807b20d5b43d04cc86e..78ca5ab84879fb0361552fb1b5a5de6b372f9868 100644 (file)
@@ -59,7 +59,7 @@ const sequelize = new Sequelize(dbname, username, password, {
   port: CONFIG.DATABASE.PORT,
   benchmark: isTestInstance(),
 
-  logging: function (message, benchmark) {
+  logging: function (message: string, benchmark: number) {
     let newMessage = message
     if (benchmark !== undefined) {
       newMessage += ' | ' + benchmark + 'ms'
@@ -71,7 +71,7 @@ const sequelize = new Sequelize(dbname, username, password, {
 
 database.sequelize = sequelize
 
-database.init = function (silent, callback) {
+database.init = function (silent: boolean, callback: (err: Error) => void) {
 
   const modelDirectory = join(__dirname, '..', 'models')
   fs.readdir(modelDirectory, function (err, files) {
index 2f9b589916b9bc6e28c0f50b945639f70cd31656..f105c82924d52e248c514802285034597cc18ded 100644 (file)
@@ -9,7 +9,7 @@ import { USER_ROLES, CONFIG, LAST_MIGRATION_VERSION } from './constants'
 import { clientsExist, usersExist } from './checker'
 import { logger, createCertsIfNotExist, root } from '../helpers'
 
-function installApplication (callback) {
+function installApplication (callback: (err: Error) => void) {
   series([
     function createDatabase (callbackAsync) {
       db.sequelize.sync().asCallback(callbackAsync)
@@ -42,7 +42,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function createDirectoriesIfNotExist (callback) {
+function createDirectoriesIfNotExist (callback: (err: Error) => void) {
   const storages = config.get('storage')
 
   each(Object.keys(storages), function (key, callbackEach) {
@@ -51,7 +51,7 @@ function createDirectoriesIfNotExist (callback) {
   }, callback)
 }
 
-function createOAuthClientIfNotExist (callback) {
+function createOAuthClientIfNotExist (callback: (err: Error) => void) {
   clientsExist(function (err, exist) {
     if (err) return callback(err)
 
@@ -80,7 +80,7 @@ function createOAuthClientIfNotExist (callback) {
   })
 }
 
-function createOAuthAdminIfNotExist (callback) {
+function createOAuthAdminIfNotExist (callback: (err: Error) => void) {
   usersExist(function (err, exist) {
     if (err) return callback(err)
 
index 379d43af528f0e16456dd9e8c7a635870620dadf..d72c60638a2c58a23290a1308446d3abb7bc5e6c 100644 (file)
@@ -8,7 +8,7 @@ import { LAST_MIGRATION_VERSION } from './constants'
 import { logger } from '../helpers'
 import { ApplicationInstance } from '../models'
 
-function migrate (finalCallback) {
+function migrate (finalCallback: (err: Error) => void) {
   waterfall([
 
     function checkApplicationTableExists (callback) {
@@ -56,7 +56,7 @@ function migrate (finalCallback) {
     },
 
     function doMigrations (actualVersion, migrationScripts, callback) {
-      eachSeries(migrationScripts, function (entity, callbackEach) {
+      eachSeries(migrationScripts, function (entity: any, callbackEach) {
         executeMigration(actualVersion, entity, callbackEach)
       }, function (err) {
         if (err) return callback(err)
@@ -76,7 +76,8 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function getMigrationScripts (callback) {
+type GetMigrationScriptsCallback = (err: Error, filesToMigrate?: { version: string, script: string }[]) => void
+function getMigrationScripts (callback: GetMigrationScriptsCallback) {
   fs.readdir(path.join(__dirname, 'migrations'), function (err, files) {
     if (err) return callback(err)
 
@@ -95,7 +96,7 @@ function getMigrationScripts (callback) {
   })
 }
 
-function executeMigration (actualVersion, entity, callback) {
+function executeMigration (actualVersion: number, entity: { version: string, script: string }, callback: (err: Error) => void) {
   const versionScript = parseInt(entity.version, 10)
 
   // Do not execute old migration scripts
index 6b0fbd2bfc29fb20a46a2e9ca6a403afd5d994cc..e097f925488c8c108f19b24c69a7a8da1fdb7014 100644 (file)
@@ -1,5 +1,6 @@
 import { each, eachLimit, eachSeries, series, waterfall } from 'async'
 import * as request from 'request'
+import * as Sequelize from 'sequelize'
 
 import { database as db } from '../initializers/database'
 import {
@@ -19,9 +20,18 @@ import {
 } from '../helpers'
 import {
   RequestScheduler,
+  RequestSchedulerOptions,
+
   RequestVideoQaduScheduler,
-  RequestVideoEventScheduler
+  RequestVideoQaduSchedulerOptions,
+
+  RequestVideoEventScheduler,
+  RequestVideoEventSchedulerOptions
 } from './request'
+import { PodInstance, VideoInstance } from '../models'
+
+type QaduParam = { videoId: string, type: string }
+type EventParam = { videoId: string, type: string }
 
 const ENDPOINT_ACTIONS = REQUEST_ENDPOINT_ACTIONS[REQUEST_ENDPOINTS.VIDEOS]
 
@@ -35,7 +45,7 @@ function activateSchedulers () {
   requestVideoEventScheduler.activate()
 }
 
-function addVideoToFriends (videoData, transaction, callback) {
+function addVideoToFriends (videoData: Object, transaction: Sequelize.Transaction, callback: (err: Error) => void) {
   const options = {
     type: ENDPOINT_ACTIONS.ADD,
     endpoint: REQUEST_ENDPOINTS.VIDEOS,
@@ -45,7 +55,7 @@ function addVideoToFriends (videoData, transaction, callback) {
   createRequest(options, callback)
 }
 
-function updateVideoToFriends (videoData, transaction, callback) {
+function updateVideoToFriends (videoData: Object, transaction: Sequelize.Transaction, callback: (err: Error) => void) {
   const options = {
     type: ENDPOINT_ACTIONS.UPDATE,
     endpoint: REQUEST_ENDPOINTS.VIDEOS,
@@ -55,35 +65,37 @@ function updateVideoToFriends (videoData, transaction, callback) {
   createRequest(options, callback)
 }
 
-function removeVideoToFriends (videoParams) {
+function removeVideoToFriends (videoParams: Object) {
   const options = {
     type: ENDPOINT_ACTIONS.REMOVE,
     endpoint: REQUEST_ENDPOINTS.VIDEOS,
-    data: videoParams
+    data: videoParams,
+    transaction: null
   }
   createRequest(options)
 }
 
-function reportAbuseVideoToFriend (reportData, video) {
+function reportAbuseVideoToFriend (reportData: Object, video: VideoInstance) {
   const options = {
     type: ENDPOINT_ACTIONS.REPORT_ABUSE,
     endpoint: REQUEST_ENDPOINTS.VIDEOS,
     data: reportData,
-    toIds: [ video.Author.podId ]
+    toIds: [ video.Author.podId ],
+    transaction: null
   }
   createRequest(options)
 }
 
-function quickAndDirtyUpdateVideoToFriends (qaduParams, transaction?, callback?) {
+function quickAndDirtyUpdateVideoToFriends (qaduParam: QaduParam, transaction?: Sequelize.Transaction, callback?: (err: Error) => void) {
   const options = {
-    videoId: qaduParams.videoId,
-    type: qaduParams.type,
+    videoId: qaduParam.videoId,
+    type: qaduParam.type,
     transaction
   }
   return createVideoQaduRequest(options, callback)
 }
 
-function quickAndDirtyUpdatesVideoToFriends (qadusParams, transaction, finalCallback) {
+function quickAndDirtyUpdatesVideoToFriends (qadusParams: QaduParam[], transaction: Sequelize.Transaction, finalCallback: (err: Error) => void) {
   const tasks = []
 
   qadusParams.forEach(function (qaduParams) {
@@ -97,16 +109,16 @@ function quickAndDirtyUpdatesVideoToFriends (qadusParams, transaction, finalCall
   series(tasks, finalCallback)
 }
 
-function addEventToRemoteVideo (eventParams, transaction?, callback?) {
+function addEventToRemoteVideo (eventParam: EventParam, transaction?: Sequelize.Transaction, callback?: (err: Error) => void) {
   const options = {
-    videoId: eventParams.videoId,
-    type: eventParams.type,
+    videoId: eventParam.videoId,
+    type: eventParam.type,
     transaction
   }
   createVideoEventRequest(options, callback)
 }
 
-function addEventsToRemoteVideo (eventsParams, transaction, finalCallback) {
+function addEventsToRemoteVideo (eventsParams: EventParam[], transaction: Sequelize.Transaction, finalCallback: (err: Error) => void) {
   const tasks = []
 
   eventsParams.forEach(function (eventParams) {
@@ -120,7 +132,7 @@ function addEventsToRemoteVideo (eventsParams, transaction, finalCallback) {
   series(tasks, finalCallback)
 }
 
-function hasFriends (callback) {
+function hasFriends (callback: (err: Error, hasFriends?: boolean) => void) {
   db.Pod.countAll(function (err, count) {
     if (err) return callback(err)
 
@@ -129,7 +141,7 @@ function hasFriends (callback) {
   })
 }
 
-function makeFriends (hosts, callback) {
+function makeFriends (hosts: string[], callback: (err: Error) => void) {
   const podsScore = {}
 
   logger.info('Make friends!')
@@ -141,7 +153,7 @@ function makeFriends (hosts, callback) {
 
     eachSeries(hosts, function (host, callbackEach) {
       computeForeignPodsList(host, podsScore, callbackEach)
-    }, function (err) {
+    }, function (err: Error) {
       if (err) return callback(err)
 
       logger.debug('Pods scores computed.', { podsScore: podsScore })
@@ -153,7 +165,7 @@ function makeFriends (hosts, callback) {
   })
 }
 
-function quitFriends (callback) {
+function quitFriends (callback: (err: Error) => void) {
   // Stop pool requests
   requestScheduler.deactivate()
 
@@ -172,7 +184,7 @@ function quitFriends (callback) {
 
     function announceIQuitMyFriends (pods, callbackAsync) {
       const requestParams = {
-        method: 'POST',
+        method: 'POST' as 'POST',
         path: '/api/' + API_VERSION + '/remote/pods/remove',
         sign: true,
         toPod: null
@@ -199,7 +211,7 @@ function quitFriends (callback) {
         pod.destroy().asCallback(callbackEach)
       }, callbackAsync)
     }
-  ], function (err) {
+  ], function (err: Error) {
     // Don't forget to re activate the scheduler, even if there was an error
     requestScheduler.activate()
 
@@ -210,7 +222,7 @@ function quitFriends (callback) {
   })
 }
 
-function sendOwnedVideosToPod (podId) {
+function sendOwnedVideosToPod (podId: number) {
   db.Video.listOwnedAndPopulateAuthorAndTags(function (err, videosList) {
     if (err) {
       logger.error('Cannot get the list of videos we own.')
@@ -229,7 +241,8 @@ function sendOwnedVideosToPod (podId) {
           type: 'add',
           endpoint: REQUEST_ENDPOINTS.VIDEOS,
           data: remoteVideo,
-          toIds: [ podId ]
+          toIds: [ podId ],
+          transaction: null
         }
         createRequest(options)
       })
@@ -272,7 +285,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function computeForeignPodsList (host, podsScore, callback) {
+function computeForeignPodsList (host: string, podsScore: { [ host: string ]: number }, callback: (err: Error) => void) {
   getForeignPodsList(host, function (err, res) {
     if (err) return callback(err)
 
@@ -288,11 +301,11 @@ function computeForeignPodsList (host, podsScore, callback) {
       else podsScore[foreignPodHost] = 1
     })
 
-    return callback()
+    return callback(null)
   })
 }
 
-function computeWinningPods (hosts, podsScore) {
+function computeWinningPods (hosts: string[], podsScore: { [ host: string ]: number }) {
   // Build the list of pods to add
   // Only add a pod if it exists in more than a half base pods
   const podsList = []
@@ -308,7 +321,7 @@ function computeWinningPods (hosts, podsScore) {
   return podsList
 }
 
-function getForeignPodsList (host, callback) {
+function getForeignPodsList (host: string, callback: (err: Error, foreignPodsList?: any) => void) {
   const path = '/api/' + API_VERSION + '/pods'
 
   request.get(REMOTE_SCHEME.HTTP + '://' + host + path, function (err, response, body) {
@@ -323,16 +336,16 @@ function getForeignPodsList (host, callback) {
   })
 }
 
-function makeRequestsToWinningPods (cert, podsList, callback) {
+function makeRequestsToWinningPods (cert: string, podsList: PodInstance[], callback: (err: Error) => void) {
   // Stop pool requests
   requestScheduler.deactivate()
   // Flush pool requests
   requestScheduler.forceSend()
 
-  eachLimit(podsList, REQUESTS_IN_PARALLEL, function (pod: { host: string }, callbackEach) {
+  eachLimit(podsList, REQUESTS_IN_PARALLEL, function (pod: PodInstance, callbackEach) {
     const params = {
       url: REMOTE_SCHEME.HTTP + '://' + pod.host + '/api/' + API_VERSION + '/pods/',
-      method: 'POST',
+      method: 'POST' as 'POST',
       json: {
         host: CONFIG.WEBSERVER.HOST,
         email: CONFIG.ADMIN.EMAIL,
@@ -371,15 +384,22 @@ function makeRequestsToWinningPods (cert, podsList, callback) {
     requestScheduler.activate()
 
     logger.debug('makeRequestsToWinningPods finished.')
-    return callback()
+    return callback(null)
   })
 }
 
 // Wrapper that populate "toIds" argument with all our friends if it is not specified
-// { type, endpoint, data, toIds, transaction }
-function createRequest (options, callback?) {
+type CreateRequestOptions = {
+  type: string
+  endpoint: string
+  data: Object
+  toIds?: number[]
+  transaction: Sequelize.Transaction
+}
+function createRequest (options: CreateRequestOptions, callback?: (err: Error) => void) {
   if (!callback) callback = function () { /* empty */ }
-  if (options.toIds) return requestScheduler.createRequest(options, callback)
+
+  if (options.toIds !== undefined) return requestScheduler.createRequest(options as RequestSchedulerOptions, callback)
 
   // If the "toIds" pods is not specified, we send the request to all our friends
   db.Pod.listAllIds(options.transaction, function (err, podIds) {
@@ -393,18 +413,18 @@ function createRequest (options, callback?) {
   })
 }
 
-function createVideoQaduRequest (options, callback) {
+function createVideoQaduRequest (options: RequestVideoQaduSchedulerOptions, callback: (err: Error) => void) {
   if (!callback) callback = createEmptyCallback()
 
   requestVideoQaduScheduler.createRequest(options, callback)
 }
 
-function createVideoEventRequest (options, callback) {
+function createVideoEventRequest (options: RequestVideoEventSchedulerOptions, callback: (err: Error) => void) {
   if (!callback) callback = createEmptyCallback()
 
   requestVideoEventScheduler.createRequest(options, callback)
 }
 
-function isMe (host) {
+function isMe (host: string) {
   return host === CONFIG.WEBSERVER.HOST
 }
index ae5440031ce81b5d8c1a7415d78801ddd7ce76f5..7d0263b1554e9053ab6b64fcb74322f6c0ae023b 100644 (file)
@@ -1,6 +1,14 @@
 import * as videoTranscoder from './video-transcoder'
 
-const jobHandlers = {
+import { VideoInstance } from '../../../models'
+
+export interface JobHandler<T> {
+  process (data: object, callback: (err: Error, videoInstance?: T) => void)
+  onError (err: Error, jobId: number, video: T, callback: (err: Error) => void)
+  onSuccess (data: any, jobId: number, video: T, callback: (err: Error) => void)
+}
+
+const jobHandlers: { [ handlerName: string ]: JobHandler<any> } = {
   videoTranscoder
 }
 
index 43599356a729df8723e172395b7a916c2a4c4c1a..efa18ef2d66e3b4017ca619cbfbf873f94a2f024 100644 (file)
@@ -1,8 +1,9 @@
 import { database as db } from '../../../initializers/database'
 import { logger } from '../../../helpers'
 import { addVideoToFriends } from '../../../lib'
+import { VideoInstance } from '../../../models'
 
-function process (data, callback) {
+function process (data: { id: string }, callback: (err: Error, videoInstance?: VideoInstance) => void) {
   db.Video.loadAndPopulateAuthorAndPodAndTags(data.id, function (err, video) {
     if (err) return callback(err)
 
@@ -12,12 +13,12 @@ function process (data, callback) {
   })
 }
 
-function onError (err, jobId, video, callback) {
+function onError (err: Error, jobId: number, video: VideoInstance, callback: () => void) {
   logger.error('Error when transcoding video file in job %d.', jobId, { error: err })
   return callback()
 }
 
-function onSuccess (data, jobId, video, callback) {
+function onSuccess (data: any, jobId: number, video: VideoInstance, callback: (err: Error) => void) {
   logger.info('Job %d is a success.', jobId)
 
   video.toAddRemoteJSON(function (err, remoteVideo) {
index ad5f7f6d98bb0afcd137c472e1b1775427f6b8c0..2f01387e7258cfc2722efc47ed84f439e289a106 100644 (file)
@@ -1,4 +1,5 @@
 import { forever, queue } from 'async'
+import * as Sequelize from 'sequelize'
 
 import { database as db } from '../../initializers/database'
 import {
@@ -7,7 +8,10 @@ import {
   JOB_STATES
 } from '../../initializers'
 import { logger } from '../../helpers'
-import { jobHandlers } from './handlers'
+import { JobInstance } from '../../models'
+import { JobHandler, jobHandlers } from './handlers'
+
+type JobQueueCallback = (err: Error) => void
 
 class JobScheduler {
 
@@ -24,7 +28,7 @@ class JobScheduler {
 
     logger.info('Jobs scheduler activated.')
 
-    const jobsQueue = queue(this.processJob.bind(this))
+    const jobsQueue = queue<JobInstance, JobQueueCallback>(this.processJob.bind(this))
 
     // Finish processing jobs from a previous start
     const state = JOB_STATES.PROCESSING
@@ -58,7 +62,7 @@ class JobScheduler {
     })
   }
 
-  createJob (transaction, handlerName: string, handlerInputData: object, callback) {
+  createJob (transaction: Sequelize.Transaction, handlerName: string, handlerInputData: object, callback: (err: Error) => void) {
     const createQuery = {
       state: JOB_STATES.PENDING,
       handlerName,
@@ -69,7 +73,7 @@ class JobScheduler {
     db.Job.create(createQuery, options).asCallback(callback)
   }
 
-  private enqueueJobs (err, jobsQueue, jobs) {
+  private enqueueJobs (err: Error, jobsQueue: AsyncQueue<JobInstance>, jobs: JobInstance[]) {
     if (err) {
       logger.error('Cannot list pending jobs.', { error: err })
     } else {
@@ -79,7 +83,7 @@ class JobScheduler {
     }
   }
 
-  private processJob (job, callback) {
+  private processJob (job: JobInstance, callback: (err: Error) => void) {
     const jobHandler = jobHandlers[job.handlerName]
 
     logger.info('Processing job %d with handler %s.', job.id, job.handlerName)
@@ -89,8 +93,8 @@ class JobScheduler {
       if (err) return this.cannotSaveJobError(err, callback)
 
       if (jobHandler === undefined) {
-        logger.error('Unknown job handler for job %s.', jobHandler.handlerName)
-        return callback()
+        logger.error('Unknown job handler for job %s.', job.handlerName)
+        return callback(null)
       }
 
       return jobHandler.process(job.handlerInputData, (err, result) => {
@@ -104,7 +108,7 @@ class JobScheduler {
     })
   }
 
-  private onJobError (jobHandler, job, jobResult, callback) {
+  private onJobError (jobHandler: JobHandler<any>, job: JobInstance, jobResult: any, callback: (err: Error) => void) {
     job.state = JOB_STATES.ERROR
 
     job.save().asCallback(err => {
@@ -114,7 +118,7 @@ class JobScheduler {
     })
   }
 
-  private onJobSuccess (jobHandler, job, jobResult, callback) {
+  private onJobSuccess (jobHandler: JobHandler<any>, job: JobInstance, jobResult: any, callback: (err: Error) => void) {
     job.state = JOB_STATES.SUCCESS
 
     job.save().asCallback(err => {
@@ -124,7 +128,7 @@ class JobScheduler {
     })
   }
 
-  private cannotSaveJobError (err, callback) {
+  private cannotSaveJobError (err: Error, callback: (err: Error) => void) {
     logger.error('Cannot save new job state.', { error: err })
     return callback(err)
   }
index 3bdf0f47867973682aa7aa823c5172ef2d424e58..7cf42e94c284ed9b7a169403bdf5efcea91e291a 100644 (file)
@@ -1,27 +1,30 @@
+import { OAuthClientInstance, UserInstance } from '../models'
 import { database as db } from '../initializers/database'
 import { logger } from '../helpers'
 
+type TokenInfo = { accessToken: string, refreshToken: string, accessTokenExpiresAt: Date, refreshTokenExpiresAt: Date }
+
 // ---------------------------------------------------------------------------
 
-function getAccessToken (bearerToken) {
+function getAccessToken (bearerToken: string) {
   logger.debug('Getting access token (bearerToken: ' + bearerToken + ').')
 
   return db.OAuthToken.getByTokenAndPopulateUser(bearerToken)
 }
 
-function getClient (clientId, clientSecret) {
+function getClient (clientId: string, clientSecret: string) {
   logger.debug('Getting Client (clientId: ' + clientId + ', clientSecret: ' + clientSecret + ').')
 
   return db.OAuthClient.getByIdAndSecret(clientId, clientSecret)
 }
 
-function getRefreshToken (refreshToken) {
+function getRefreshToken (refreshToken: string) {
   logger.debug('Getting RefreshToken (refreshToken: ' + refreshToken + ').')
 
   return db.OAuthToken.getByRefreshTokenAndPopulateClient(refreshToken)
 }
 
-function getUser (username, password) {
+function getUser (username: string, password: string) {
   logger.debug('Getting User (username: ' + username + ', password: ' + password + ').')
 
   return db.User.getByUsername(username).then(function (user) {
@@ -42,7 +45,7 @@ function getUser (username, password) {
   })
 }
 
-function revokeToken (token) {
+function revokeToken (token: TokenInfo) {
   return db.OAuthToken.getByRefreshTokenAndPopulateUser(token.refreshToken).then(function (tokenDB) {
     if (tokenDB) tokenDB.destroy()
 
@@ -60,7 +63,7 @@ function revokeToken (token) {
   })
 }
 
-function saveToken (token, client, user) {
+function saveToken (token: TokenInfo, client: OAuthClientInstance, user: UserInstance) {
   logger.debug('Saving token ' + token.accessToken + ' for client ' + client.id + ' and user ' + user.id + '.')
 
   const tokenToCreate = {
index b7ef6abf902e7b5011a4e83310a421b475cb5875..26bdc2bff7e13544db6407ad9b81594b2b48f318 100644 (file)
@@ -2,6 +2,7 @@ import * as eachLimit from 'async/eachLimit'
 
 import { database as db } from '../../initializers/database'
 import { logger, makeSecureRequest } from '../../helpers'
+import { PodInstance } from '../../models'
 import {
   API_VERSION,
   REQUESTS_IN_PARALLEL,
@@ -9,11 +10,12 @@ import {
 } from '../../initializers'
 
 abstract class BaseRequestScheduler {
+  requestInterval: number
+  limitPods: number
+  limitPerPod: number
+
   protected lastRequestTimestamp: number
   protected timer: NodeJS.Timer
-  protected requestInterval: number
-  protected limitPods: number
-  protected limitPerPod: number
   protected description: string
 
   constructor () {
@@ -53,24 +55,24 @@ abstract class BaseRequestScheduler {
     return REQUESTS_INTERVAL - (Date.now() - this.lastRequestTimestamp)
   }
 
-  remainingRequestsCount (callback) {
+  remainingRequestsCount (callback: (err: Error, total: number) => void) {
     return this.getRequestModel().countTotalRequests(callback)
   }
 
-  flush (callback) {
+  flush (callback: (err: Error) => void) {
     this.getRequestModel().removeAll(callback)
   }
 
   // ---------------------------------------------------------------------------
 
   // Make a requests to friends of a certain type
-  protected makeRequest (toPod, requestEndpoint, requestsToMake, callback) {
+  protected makeRequest (toPod: PodInstance, requestEndpoint: string, requestsToMake: Object, callback) {
     if (!callback) callback = function () { /* empty */ }
 
     const params = {
       toPod: toPod,
       sign: true, // Prove our identity
-      method: 'POST',
+      method: 'POST' as 'POST',
       path: '/api/' + API_VERSION + '/remote/' + requestEndpoint,
       data: requestsToMake // Requests we need to make
     }
index c98f956db79935d0ad55934a75a7ee273b184e0f..110d0ed78befc55b1afb839b853873ad18bee8b0 100644 (file)
@@ -1,3 +1,4 @@
+export * from './base-request-scheduler'
 export * from './request-scheduler'
 export * from './request-video-event-scheduler'
 export * from './request-video-qadu-scheduler'
index 26ffbfb868f892e5f384a3caf059dd728600d15d..69d840eeb140705547c14ab15b19e63fb56f011d 100644 (file)
@@ -1,3 +1,5 @@
+import * as Sequelize from 'sequelize'
+
 import { database as db } from '../../initializers/database'
 import { BaseRequestScheduler } from './base-request-scheduler'
 import { logger } from '../../helpers'
@@ -6,6 +8,14 @@ import {
   REQUESTS_LIMIT_PER_POD
 } from '../../initializers'
 
+export type RequestSchedulerOptions = {
+  type: string
+  endpoint: string
+  data: Object
+  toIds: number[]
+  transaction: Sequelize.Transaction
+}
+
 class RequestScheduler extends BaseRequestScheduler {
   constructor () {
     super()
@@ -25,7 +35,7 @@ class RequestScheduler extends BaseRequestScheduler {
     return db.RequestToPod
   }
 
-  buildRequestObjects (requests) {
+  buildRequestObjects (requests: { [ toPodId: number ]: any }) {
     const requestsToMakeGrouped = {}
 
     Object.keys(requests).forEach(toPodId => {
@@ -51,14 +61,7 @@ class RequestScheduler extends BaseRequestScheduler {
     return requestsToMakeGrouped
   }
 
-  // { type, endpoint, data, toIds, transaction }
-  createRequest (options, callback) {
-    const type = options.type
-    const endpoint = options.endpoint
-    const data = options.data
-    const toIds = options.toIds
-    const transaction = options.transaction
-
+  createRequest ({ type, endpoint, data, toIds, transaction }: RequestSchedulerOptions, callback: (err: Error) => void) {
     // TODO: check the setPods works
     const podIds = []
 
@@ -77,7 +80,7 @@ class RequestScheduler extends BaseRequestScheduler {
       }
     }
 
-    const dbRequestOptions = {
+    const dbRequestOptions: Sequelize.CreateOptions = {
       transaction
     }
 
index bde50b1d33dfc3ae9c619758f249c89d54257f5c..9da82585ef321b8103fa789af4306a057e5d8f5d 100644 (file)
@@ -1,3 +1,5 @@
+import * as Sequelize from 'sequelize'
+
 import { database as db } from '../../initializers/database'
 import { BaseRequestScheduler } from './base-request-scheduler'
 import {
@@ -6,6 +8,13 @@ import {
   REQUEST_VIDEO_EVENT_ENDPOINT
 } from '../../initializers'
 
+export type RequestVideoEventSchedulerOptions = {
+  type: string
+  videoId: string
+  count?: number
+  transaction?: Sequelize.Transaction
+}
+
 class RequestVideoEventScheduler extends BaseRequestScheduler {
   constructor () {
     super()
@@ -25,7 +34,7 @@ class RequestVideoEventScheduler extends BaseRequestScheduler {
     return db.RequestVideoEvent
   }
 
-  buildRequestObjects (eventsToProcess) {
+  buildRequestObjects (eventsToProcess: { [ toPodId: number ]: any }[]) {
     const requestsToMakeGrouped = {}
 
     /* Example:
@@ -87,16 +96,10 @@ class RequestVideoEventScheduler extends BaseRequestScheduler {
     return requestsToMakeGrouped
   }
 
-  // { type, videoId, count?, transaction? }
-  createRequest (options, callback) {
-    const type = options.type
-    const videoId = options.videoId
-    const transaction = options.transaction
-    let count = options.count
-
+  createRequest ({ type, videoId, count, transaction }: RequestVideoEventSchedulerOptions, callback: (err: Error) => void) {
     if (count === undefined) count = 1
 
-    const dbRequestOptions: { transaction?: any } = {}
+    const dbRequestOptions: Sequelize.CreateOptions = {}
     if (transaction) dbRequestOptions.transaction = transaction
 
     const createQuery = {
index dab526088f6703e8f6da429516e27db6d8b0ca95..436fd8e5035755370bbdf50acafdfc8ffbd002dc 100644 (file)
@@ -1,3 +1,5 @@
+import * as Sequelize from 'sequelize'
+
 import { database as db } from '../../initializers/database'
 import { BaseRequestScheduler } from './base-request-scheduler'
 import { logger } from '../../helpers'
@@ -8,6 +10,12 @@ import {
   REQUEST_VIDEO_QADU_TYPES
 } from '../../initializers'
 
+export type RequestVideoQaduSchedulerOptions = {
+  type: string
+  videoId: string
+  transaction?: Sequelize.Transaction
+}
+
 class RequestVideoQaduScheduler extends BaseRequestScheduler {
   constructor () {
     super()
@@ -27,7 +35,7 @@ class RequestVideoQaduScheduler extends BaseRequestScheduler {
     return db.RequestVideoQadu
   }
 
-  buildRequestObjects (requests) {
+  buildRequestObjects (requests: { [ toPodId: number ]: any }[]) {
     const requestsToMakeGrouped = {}
 
     Object.keys(requests).forEach(toPodId => {
@@ -96,17 +104,12 @@ class RequestVideoQaduScheduler extends BaseRequestScheduler {
     return requestsToMakeGrouped
   }
 
-  // { type, videoId, transaction? }
-  createRequest (options, callback) {
-    const type = options.type
-    const videoId = options.videoId
-    const transaction = options.transaction
-
-    const dbRequestOptions: { transaction?: any } = {}
+  createRequest ({ type, videoId, transaction }: RequestVideoQaduSchedulerOptions, callback: (err: Error) => void) {
+    const dbRequestOptions: Sequelize.BulkCreateOptions = {}
     if (transaction) dbRequestOptions.transaction = transaction
 
     // Send the update to all our friends
-    db.Pod.listAllIds(options.transaction, function (err, podIds) {
+    db.Pod.listAllIds(transaction, function (err, podIds) {
       if (err) return callback(err)
 
       const queries = []
index 28b6a9a120a24b8a23fb953fe463504cae897125..812397352c6d62588297f64ef6227f7c44fb38fb 100644 (file)
@@ -1,6 +1,9 @@
+import 'express-validator'
+import * as express from 'express'
+
 import { logger } from '../helpers'
 
-function ensureIsAdmin (req, res, next) {
+function ensureIsAdmin (req: express.Request, res: express.Response, next: express.NextFunction) {
   const user = res.locals.oauth.token.user
   if (user.isAdmin() === false) {
     logger.info('A non admin user is trying to access to an admin content.')
index 2c1c5fa536c1cd922b198261024f8d23bbe7678d..d71dd245265a6fbbebef6bf1acf2ef3188304a98 100644 (file)
@@ -1,8 +1,8 @@
-export * from './validators';
-export * from './admin';
-export * from './oauth';
-export * from './pagination';
-export * from './pods';
-export * from './search';
-export * from './secure';
-export * from './sort';
+export * from './validators'
+export * from './admin'
+export * from './oauth'
+export * from './pagination'
+export * from './pods'
+export * from './search'
+export * from './secure'
+export * from './sort'
index 468e418106c69c84ceb596b705665ebadfd7de40..d545b3e58f55f4ff150a2078e400646b520346f3 100644 (file)
@@ -1,3 +1,5 @@
+import 'express-validator'
+import * as express from 'express'
 import * as OAuthServer from 'express-oauth-server'
 
 import { OAUTH_LIFETIME } from '../initializers'
@@ -9,7 +11,7 @@ const oAuthServer = new OAuthServer({
   model: require('../lib/oauth-model')
 })
 
-function authenticate (req, res, next) {
+function authenticate (req: express.Request, res: express.Response, next: express.NextFunction) {
   oAuthServer.authenticate()(req, res, function (err) {
     if (err) {
       logger.error('Cannot authenticate.', { error: err })
@@ -22,7 +24,7 @@ function authenticate (req, res, next) {
   })
 }
 
-function token (req, res, next) {
+function token (req: express.Request, res: express.Response, next: express.NextFunction) {
   return oAuthServer.token()(req, res, next)
 }
 
index cadd769805ae7f393e14187a867db86c6d60f56d..26a8cacf0bf532d34121760eb6092a3537e95670 100644 (file)
@@ -1,6 +1,9 @@
+import 'express-validator'
+import * as express from 'express'
+
 import { PAGINATION_COUNT_DEFAULT } from '../initializers'
 
-function setPagination (req, res, next) {
+function setPagination (req: express.Request, res: express.Response, next: express.NextFunction) {
   if (!req.query.start) req.query.start = 0
   else req.query.start = parseInt(req.query.start, 10)
 
index c255be8998023a7bb8672b1cb8149fe78727c4fb..eaf9aa144a7806b9532b8356d1375543e9c1ec50 100644 (file)
@@ -1,6 +1,9 @@
+import 'express-validator'
+import * as express from 'express'
+
 import { REMOTE_SCHEME } from '../initializers'
 
-function setBodyHostsPort (req, res, next) {
+function setBodyHostsPort (req: express.Request, res: express.Response, next: express.NextFunction) {
   if (!req.body.hosts) return next()
 
   for (let i = 0; i < req.body.hosts.length; i++) {
@@ -17,7 +20,7 @@ function setBodyHostsPort (req, res, next) {
   return next()
 }
 
-function setBodyHostPort (req, res, next) {
+function setBodyHostPort (req: express.Request, res: express.Response, next: express.NextFunction) {
   if (!req.body.host) return next()
 
   const hostWithPort = getHostWithPort(req.body.host)
@@ -41,7 +44,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function getHostWithPort (host) {
+function getHostWithPort (host: string) {
   const splitted = host.split(':')
 
   // The port was not specified
index 05a2e744273077df1984909b6e192ff4fc7212da..6fe83d25b43e01e5969536548e357d467a05b0e0 100644 (file)
@@ -1,4 +1,7 @@
-function setVideosSearch (req, res, next) {
+import 'express-validator'
+import * as express from 'express'
+
+function setVideosSearch (req: express.Request, res: express.Response, next: express.NextFunction) {
   if (!req.query.field) req.query.field = 'name'
 
   return next()
index bd7cfa918159247bb5ef0c70f3b1eb5ae6b6a826..fbfd08c7b4cb7c44a410dd923b4164a3a948477d 100644 (file)
@@ -1,10 +1,13 @@
+import 'express-validator'
+import * as express from 'express'
+
 import { database as db } from '../initializers'
 import {
   logger,
   checkSignature as peertubeCryptoCheckSignature
 } from '../helpers'
 
-function checkSignature (req, res, next) {
+function checkSignature (req: express.Request, res: express.Response, next: express.NextFunction) {
   const host = req.body.signature.host
   db.Pod.loadByHost(host, function (err, pod) {
     if (err) {
index ab9ccf5242bee9af0f6f56eab779534037dd19f1..632b2fae4158fd2bbfa0ff18e4dbb23844f9d0ca 100644 (file)
@@ -1,16 +1,19 @@
-function setUsersSort (req, res, next) {
+import 'express-validator'
+import * as express from 'express'
+
+function setUsersSort (req: express.Request, res: express.Response, next: express.NextFunction) {
   if (!req.query.sort) req.query.sort = '-createdAt'
 
   return next()
 }
 
-function setVideoAbusesSort (req, res, next) {
+function setVideoAbusesSort (req: express.Request, res: express.Response, next: express.NextFunction) {
   if (!req.query.sort) req.query.sort = '-createdAt'
 
   return next()
 }
 
-function setVideosSort (req, res, next) {
+function setVideosSort (req: express.Request, res: express.Response, next: express.NextFunction) {
   if (!req.query.sort) req.query.sort = '-createdAt'
 
   return next()
index de719c05bc42fd7f80c2a414332205c535655e5d..cca8295ffddc731bc309c3e189fb58210b9fffb0 100644 (file)
@@ -1,7 +1,10 @@
+import 'express-validator'
+import * as express from 'express'
+
 import { checkErrors } from './utils'
 import { logger } from '../../helpers'
 
-function paginationValidator (req, res, next) {
+function paginationValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkQuery('start', 'Should have a number start').optional().isInt()
   req.checkQuery('count', 'Should have a number count').optional().isInt()
 
index c55a88b85c6d29d0e582f2a7b304c394df7c83a5..d8eb90168a1c1014453461fc1d0d25fe80683432 100644 (file)
@@ -1,3 +1,6 @@
+import 'express-validator'
+import * as express from 'express'
+
 import { database as db } from '../../initializers/database'
 import { checkErrors } from './utils'
 import { logger } from '../../helpers'
@@ -5,7 +8,7 @@ import { CONFIG } from '../../initializers'
 import { hasFriends } from '../../lib'
 import { isTestInstance } from '../../helpers'
 
-function makeFriendsValidator (req, res, next) {
+function makeFriendsValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   // Force https if the administrator wants to make friends
   if (isTestInstance() === false && CONFIG.WEBSERVER.SCHEME === 'http') {
     return res.status(400).send('Cannot make friends with a non HTTPS webserver.')
@@ -32,7 +35,7 @@ function makeFriendsValidator (req, res, next) {
   })
 }
 
-function podsAddValidator (req, res, next) {
+function podsAddValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkBody('host', 'Should have a host').isHostValid()
   req.checkBody('email', 'Should have an email').isEmail()
   req.checkBody('publicKey', 'Should have a public key').notEmpty()
index 6e3ebe7db3b747c927887bfef2790e40b2cc518c..eb5c196ebd6c67236e1771eef885a375a26552a1 100644 (file)
@@ -1,7 +1,10 @@
+import 'express-validator'
+import * as express from 'express'
+
 import { logger } from '../../../helpers'
 import { checkErrors } from '../utils'
 
-function signatureValidator (req, res, next) {
+function signatureValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkBody('signature.host', 'Should have a signature host').isURL()
   req.checkBody('signature.signature', 'Should have a signature').notEmpty()
 
index 3380c29e27850a5785bc87075fd72e06a50512b6..2037c0085e98b9cf71f2e44b673c6e9bdc3b84f5 100644 (file)
@@ -1,7 +1,10 @@
+import 'express-validator'
+import * as express from 'express'
+
 import { logger } from '../../../helpers'
 import { checkErrors } from '../utils'
 
-function remoteVideosValidator (req, res, next) {
+function remoteVideosValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkBody('data').isEachRemoteRequestVideosValid()
 
   logger.debug('Checking remoteVideos parameters', { parameters: req.body })
@@ -9,7 +12,7 @@ function remoteVideosValidator (req, res, next) {
   checkErrors(req, res, next)
 }
 
-function remoteQaduVideosValidator (req, res, next) {
+function remoteQaduVideosValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkBody('data').isEachRemoteRequestVideosQaduValid()
 
   logger.debug('Checking remoteQaduVideos parameters', { parameters: req.body })
@@ -17,7 +20,7 @@ function remoteQaduVideosValidator (req, res, next) {
   checkErrors(req, res, next)
 }
 
-function remoteEventsVideosValidator (req, res, next) {
+function remoteEventsVideosValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkBody('data').isEachRemoteRequestVideosEventsValid()
 
   logger.debug('Checking remoteEventsVideos parameters', { parameters: req.body })
index ebc7333c7c07a88104474b55dac130c42981fd20..3baee9fb3df437236e675b0d4223f2fe61c26721 100644 (file)
@@ -1,3 +1,6 @@
+import 'express-validator'
+import * as express from 'express'
+
 import { checkErrors } from './utils'
 import { logger } from '../../helpers'
 import { SORTABLE_COLUMNS } from '../../initializers'
@@ -7,15 +10,15 @@ const SORTABLE_USERS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.USERS)
 const SORTABLE_VIDEO_ABUSES_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEO_ABUSES)
 const SORTABLE_VIDEOS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEOS)
 
-function usersSortValidator (req, res, next) {
+function usersSortValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   checkSort(req, res, next, SORTABLE_USERS_COLUMNS)
 }
 
-function videoAbusesSortValidator (req, res, next) {
+function videoAbusesSortValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   checkSort(req, res, next, SORTABLE_VIDEO_ABUSES_COLUMNS)
 }
 
-function videosSortValidator (req, res, next) {
+function videosSortValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   checkSort(req, res, next, SORTABLE_VIDEOS_COLUMNS)
 }
 
@@ -29,7 +32,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function checkSort (req, res, next, sortableColumns) {
+function checkSort (req: express.Request, res: express.Response, next: express.NextFunction, sortableColumns: string[]) {
   req.checkQuery('sort', 'Should have correct sortable column').optional().isIn(sortableColumns)
 
   logger.debug('Checking sort parameters', { parameters: req.query })
@@ -37,7 +40,7 @@ function checkSort (req, res, next, sortableColumns) {
   checkErrors(req, res, next)
 }
 
-function createSortableColumns (sortableColumns) {
+function createSortableColumns (sortableColumns: string[]) {
   const sortableColumnDesc = sortableColumns.map(sortableColumn => '-' + sortableColumn)
 
   return sortableColumns.concat(sortableColumnDesc)
index e0d1d917a31d81e03b25167460d279ae7832d296..b7b9ef370079197fc390a78e1cf78bf4db013b7f 100644 (file)
@@ -1,8 +1,11 @@
+import 'express-validator'
+import * as express from 'express'
+
 import { database as db } from '../../initializers/database'
 import { checkErrors } from './utils'
 import { logger } from '../../helpers'
 
-function usersAddValidator (req, res, next) {
+function usersAddValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkBody('username', 'Should have a valid username').isUserUsernameValid()
   req.checkBody('password', 'Should have a valid password').isUserPasswordValid()
   req.checkBody('email', 'Should have a valid email').isEmail()
@@ -23,7 +26,7 @@ function usersAddValidator (req, res, next) {
   })
 }
 
-function usersRemoveValidator (req, res, next) {
+function usersRemoveValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkParams('id', 'Should have a valid id').notEmpty().isInt()
 
   logger.debug('Checking usersRemove parameters', { parameters: req.params })
@@ -44,7 +47,7 @@ function usersRemoveValidator (req, res, next) {
   })
 }
 
-function usersUpdateValidator (req, res, next) {
+function usersUpdateValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkParams('id', 'Should have a valid id').notEmpty().isInt()
   // Add old password verification
   req.checkBody('password', 'Should have a valid password').optional().isUserPasswordValid()
@@ -55,7 +58,7 @@ function usersUpdateValidator (req, res, next) {
   checkErrors(req, res, next)
 }
 
-function usersVideoRatingValidator (req, res, next) {
+function usersVideoRatingValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkParams('videoId', 'Should have a valid video id').notEmpty().isUUID(4)
 
   logger.debug('Checking usersVideoRating parameters', { parameters: req.params })
index 710e65529684d5633a03fb630da7d7ab00328818..0424d59429f6e914fa7f855db71afcb1af4519cb 100644 (file)
@@ -1,9 +1,10 @@
+import 'express-validator'
+import * as express from 'express'
 import { inspect } from 'util'
 
 import { logger } from '../../helpers'
 
-function checkErrors (req, res, next, statusCode?) {
-  if (statusCode === undefined) statusCode = 400
+function checkErrors (req: express.Request, res: express.Response, next: express.NextFunction, statusCode = 400) {
   const errors = req.validationErrors()
 
   if (errors) {
index 47825975c002798c65722ef65035ca9f3a2fff86..e99cdefb18e37f1d1bdfe82b6c7f9436ff379c7f 100644 (file)
@@ -1,9 +1,13 @@
+import 'express-validator'
+import * as multer from 'multer'
+import * as express from 'express'
+
 import { database as db } from '../../initializers/database'
 import { checkErrors } from './utils'
 import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers'
 import { logger, isVideoDurationValid } from '../../helpers'
 
-function videosAddValidator (req, res, next) {
+function videosAddValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkBody('videofile', 'Should have a valid file').isVideoFile(req.files)
   req.checkBody('name', 'Should have a valid name').isVideoNameValid()
   req.checkBody('category', 'Should have a valid category').isVideoCategoryValid()
@@ -27,13 +31,13 @@ function videosAddValidator (req, res, next) {
         return res.status(400).send('Duration of the video file is too big (max: ' + CONSTRAINTS_FIELDS.VIDEOS.DURATION.max + 's).')
       }
 
-      videoFile.duration = duration
+      videoFile['duration'] = duration
       next()
     })
   })
 }
 
-function videosUpdateValidator (req, res, next) {
+function videosUpdateValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
   req.checkBody('name', 'Should have a valid name').optional().isVideoNameValid()
   req.checkBody('category', 'Should have a valid category').optional().isVideoCategoryValid()
@@ -61,7 +65,7 @@ function videosUpdateValidator (req, res, next) {
   })
 }
 
-function videosGetValidator (req, res, next) {
+function videosGetValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
 
   logger.debug('Checking videosGet parameters', { parameters: req.params })
@@ -71,7 +75,7 @@ function videosGetValidator (req, res, next) {
   })
 }
 
-function videosRemoveValidator (req, res, next) {
+function videosRemoveValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
 
   logger.debug('Checking videosRemove parameters', { parameters: req.params })
@@ -88,7 +92,7 @@ function videosRemoveValidator (req, res, next) {
   })
 }
 
-function videosSearchValidator (req, res, next) {
+function videosSearchValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   const searchableColumns = SEARCHABLE_COLUMNS.VIDEOS
   req.checkParams('value', 'Should have a valid search').notEmpty()
   req.checkQuery('field', 'Should have correct searchable column').optional().isIn(searchableColumns)
@@ -98,7 +102,7 @@ function videosSearchValidator (req, res, next) {
   checkErrors(req, res, next)
 }
 
-function videoAbuseReportValidator (req, res, next) {
+function videoAbuseReportValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
   req.checkBody('reason', 'Should have a valid reason').isVideoAbuseReasonValid()
 
@@ -109,7 +113,7 @@ function videoAbuseReportValidator (req, res, next) {
   })
 }
 
-function videoRateValidator (req, res, next) {
+function videoRateValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
   req.checkBody('rating', 'Should have a valid rate type').isVideoRatingTypeValid()
 
@@ -120,7 +124,7 @@ function videoRateValidator (req, res, next) {
   })
 }
 
-function videosBlacklistValidator (req, res, next) {
+function videosBlacklistValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
   req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
 
   logger.debug('Checking videosBlacklist parameters', { parameters: req.params })
@@ -150,7 +154,7 @@ export {
 
 // ---------------------------------------------------------------------------
 
-function checkVideoExists (id, res, callback) {
+function checkVideoExists (id: string, res: express.Response, callback: () => void) {
   db.Video.loadAndPopulateAuthorAndPodAndTags(id, function (err, video) {
     if (err) {
       logger.error('Error in video request validator.', { error: err })
@@ -164,7 +168,7 @@ function checkVideoExists (id, res, callback) {
   })
 }
 
-function checkUserCanDeleteVideo (userId, res, callback) {
+function checkUserCanDeleteVideo (userId: number, res: express.Response, callback: () => void) {
   // Retrieve the user who did the request
   db.User.loadById(userId, function (err, user) {
     if (err) {
@@ -190,7 +194,7 @@ function checkUserCanDeleteVideo (userId, res, callback) {
   })
 }
 
-function checkVideoIsBlacklistable (req, res, callback) {
+function checkVideoIsBlacklistable (req: express.Request, res: express.Response, callback: () => void) {
   if (res.locals.video.isOwned() === true) {
     return res.status(403).send('Cannot blacklist a local video')
   }
index 826d25df02026f70fdee2df09bd0b1450eb459af..c03513db17bd2bbf65b7894fe9f44070deebb84a 100644 (file)
@@ -1,8 +1,11 @@
 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 type LoadMigrationVersionCallback = (err: Error, version: number) => void
+  export type LoadMigrationVersion = (callback: LoadMigrationVersionCallback) => void
+
+  export type UpdateMigrationVersionCallback = (err: Error, applicationInstance: ApplicationAttributes) => void
+  export type UpdateMigrationVersion = (newVersion: number, transaction: Sequelize.Transaction, callback: UpdateMigrationVersionCallback) => void
 }
 
 export interface ApplicationClass {
index acd0dfbf2e38fb9d8c5f651dd29a9b64046027ca..14b87777ac61c44d08236b070770d873d84824a9 100644 (file)
@@ -35,7 +35,7 @@ export default function defineApplication (sequelize: Sequelize.Sequelize, DataT
 
 // ---------------------------------------------------------------------------
 
-loadMigrationVersion = function (callback: (err: Error, version: number) => void) {
+loadMigrationVersion = function (callback: ApplicationMethods.LoadMigrationVersionCallback) {
   const query = {
     attributes: [ 'migrationVersion' ]
   }
@@ -47,15 +47,10 @@ loadMigrationVersion = function (callback: (err: Error, version: number) => void
   })
 }
 
-updateMigrationVersion = function (newVersion: number, transaction: any, callback: any) {
+updateMigrationVersion = function (newVersion: number, transaction: Sequelize.Transaction, callback: ApplicationMethods.UpdateMigrationVersionCallback) {
   const options: Sequelize.UpdateOptions = {
-    where: {}
-  }
-
-  if (!callback) {
-    transaction = callback
-  } else {
-    options.transaction = transaction
+    where: {},
+    transaction: transaction
   }
 
   return Application.update({ migrationVersion: newVersion }, options).asCallback(callback)
index d2475c3bde981ebf7f8a4faaf5faeaeee8ae0761..b57ce2a6b46a7299ae244f7977f6edbac56d4515 100644 (file)
@@ -1,7 +1,10 @@
 import * as Sequelize from 'sequelize'
 
+import { PodInstance } from './pod-interface'
+
 export namespace AuthorMethods {
-  export type FindOrCreateAuthor = (name, podId, userId, transaction, callback) => void
+  export type FindOrCreateAuthorCallback = (err: Error, authorInstance?: AuthorInstance) => void
+  export type FindOrCreateAuthor = (name: string, podId: number, userId: number, transaction: Sequelize.Transaction, callback: FindOrCreateAuthorCallback) => void
 }
 
 export interface AuthorClass {
@@ -16,6 +19,9 @@ export interface AuthorInstance extends AuthorClass, AuthorAttributes, Sequelize
   id: number
   createdAt: Date
   updatedAt: Date
+
+  podId: number
+  Pod: PodInstance
 }
 
 export interface AuthorModel extends AuthorClass, Sequelize.Model<AuthorInstance, AuthorAttributes> {}
index b543d17a0f57448039b6df492fd8d62ee6d6432d..3264d3a880fde51c9913754b75bd381822aa0d58 100644 (file)
@@ -74,12 +74,13 @@ function associate (models) {
   })
 }
 
-findOrCreateAuthor = function (name, podId, userId, transaction, callback) {
-  if (!callback) {
-    callback = transaction
-    transaction = null
-  }
-
+findOrCreateAuthor = function (
+  name: string,
+  podId: number,
+  userId: number,
+  transaction: Sequelize.Transaction,
+  callback: AuthorMethods.FindOrCreateAuthorCallback
+) {
   const author = {
     name,
     podId,
@@ -91,7 +92,7 @@ findOrCreateAuthor = function (name, podId, userId, transaction, callback) {
     defaults: author
   }
 
-  if (transaction) query.transaction = transaction
+  if (transaction !== null) query.transaction = transaction
 
   Author.findOrCreate(query).asCallback(function (err, result) {
     if (err) return callback(err)
index ad4e2d2b0e4a8e3abf18fc5e2e71ecead99c867a..ab66782571e2c34cdc33467f2a2c1fd4fa79b46a 100644 (file)
@@ -1,7 +1,8 @@
 import * as Sequelize from 'sequelize'
 
 export namespace JobMethods {
-  export type ListWithLimit = (limit, state, callback) => void
+  export type ListWithLimitCallback = (err: Error, jobInstances: JobInstance[]) => void
+  export type ListWithLimit = (limit: number, state: string, callback: ListWithLimitCallback) => void
 }
 
 export interface JobClass {
index 982b51499e2cc152ad2fc03707dceaac79a66d11..1afae8f0866f9e6bebec9a2f1f46297d3f2d4b6e 100644 (file)
@@ -48,7 +48,7 @@ export default function defineJob (sequelize: Sequelize.Sequelize, DataTypes) {
 
 // ---------------------------------------------------------------------------
 
-listWithLimit = function (limit, state, callback) {
+listWithLimit = function (limit: number, state: string, callback: JobMethods.ListWithLimitCallback) {
   const query = {
     order: [
       [ 'id', 'ASC' ]
index 4efd6212ad547561cc0df47aa72e6a7e0ba17eb6..3b4325740bca26675dd8d3b478dd9e35770fc866 100644 (file)
@@ -1,8 +1,12 @@
 import * as Sequelize from 'sequelize'
 
 export namespace OAuthClientMethods {
-  export type CountTotal = (callback) => void
-  export type LoadFirstClient = (callback) => void
+  export type CountTotalCallback = (err: Error, total: number) => void
+  export type CountTotal = (callback: CountTotalCallback) => void
+
+  export type LoadFirstClientCallback = (err: Error, client: OAuthClientInstance) => void
+  export type LoadFirstClient = (callback: LoadFirstClientCallback) => void
+
   export type GetByIdAndSecret = (clientId, clientSecret) => void
 }
 
index 2cefb5cb9ab6a058e14c3a64005538347f0844ab..22fae284271924b627f728109ae4085d1f8161a8 100644 (file)
@@ -67,15 +67,15 @@ function associate (models) {
   })
 }
 
-countTotal = function (callback) {
+countTotal = function (callback: OAuthClientMethods.CountTotalCallback) {
   return OAuthClient.count().asCallback(callback)
 }
 
-loadFirstClient = function (callback) {
+loadFirstClient = function (callback: OAuthClientMethods.LoadFirstClientCallback) {
   return OAuthClient.findOne().asCallback(callback)
 }
 
-getByIdAndSecret = function (clientId, clientSecret) {
+getByIdAndSecret = function (clientId: string, clientSecret: string) {
   const query = {
     where: {
       clientId: clientId,
index a0cd1ffe7dcce86dda56f822bb6b281970cd94e6..88526697e0422481de176324c9ee32ab75dc0f30 100644 (file)
@@ -1,11 +1,25 @@
 import * as Sequelize from 'sequelize'
+import * as Bluebird from 'bluebird'
 
 import { UserModel } from './user-interface'
 
+export type OAuthTokenInfo = {
+  refreshToken: string
+  refreshTokenExpiresAt: Date,
+  client: {
+    id: number
+  },
+  user: {
+    id: number
+  }
+}
+
 export namespace OAuthTokenMethods {
-  export type GetByRefreshTokenAndPopulateClient = (refreshToken) => void
-  export type GetByTokenAndPopulateUser = (bearerToken) => void
-  export type GetByRefreshTokenAndPopulateUser = (refreshToken) => any
+  export type GetByRefreshTokenAndPopulateClient = (refreshToken: string) => Bluebird<OAuthTokenInfo>
+  export type GetByTokenAndPopulateUser = (bearerToken: string) => Bluebird<OAuthTokenInstance>
+  export type GetByRefreshTokenAndPopulateUser = (refreshToken: string) => Bluebird<OAuthTokenInstance>
+
+  export type RemoveByUserIdCallback = (err: Error) => void
   export type RemoveByUserId = (userId, callback) => void
 }
 
index 567df1c12c3df91b676cd00a9d21ec981c4198b7..d70bd2bce87dee407e1c45806910ce6359a56edb 100644 (file)
@@ -8,7 +8,8 @@ import {
   OAuthTokenInstance,
   OAuthTokenAttributes,
 
-  OAuthTokenMethods
+  OAuthTokenMethods,
+  OAuthTokenInfo
 } from './oauth-token-interface'
 
 let OAuthToken: Sequelize.Model<OAuthTokenInstance, OAuthTokenAttributes>
@@ -90,7 +91,7 @@ function associate (models) {
   })
 }
 
-getByRefreshTokenAndPopulateClient = function (refreshToken) {
+getByRefreshTokenAndPopulateClient = function (refreshToken: string) {
   const query = {
     where: {
       refreshToken: refreshToken
@@ -99,9 +100,9 @@ getByRefreshTokenAndPopulateClient = function (refreshToken) {
   }
 
   return OAuthToken.findOne(query).then(function (token) {
-    if (!token) return token
+    if (!token) return null
 
-    const tokenInfos = {
+    const tokenInfos: OAuthTokenInfo = {
       refreshToken: token.refreshToken,
       refreshTokenExpiresAt: token.refreshTokenExpiresAt,
       client: {
@@ -118,7 +119,7 @@ getByRefreshTokenAndPopulateClient = function (refreshToken) {
   })
 }
 
-getByTokenAndPopulateUser = function (bearerToken) {
+getByTokenAndPopulateUser = function (bearerToken: string) {
   const query = {
     where: {
       accessToken: bearerToken
@@ -133,7 +134,7 @@ getByTokenAndPopulateUser = function (bearerToken) {
   })
 }
 
-getByRefreshTokenAndPopulateUser = function (refreshToken) {
+getByRefreshTokenAndPopulateUser = function (refreshToken: string) {
   const query = {
     where: {
       refreshToken: refreshToken
index 14c88bec6257526942fddfc5f00189aacda3efed..8f362bd5cbca8d12100bab4daf8396e8439c5adc 100644 (file)
@@ -1,18 +1,39 @@
 import * as Sequelize from 'sequelize'
 
+// Don't use barrel, import just what we need
+import { Pod as FormatedPod } from '../../shared/models/pod.model'
+
 export namespace PodMethods {
-  export type ToFormatedJSON = () => void
+  export type ToFormatedJSON = () => FormatedPod
 
+  export type CountAllCallback = (err: Error, total: number) => 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 type IncrementScoresCallback = (err: Error) => void
+  export type IncrementScores = (ids: number[], value: number, callback?: IncrementScoresCallback) => void
+
+  export type ListCallback = (err: Error, podInstances?: PodInstance[]) => void
+  export type List = (callback: ListCallback) => void
+
+  export type ListAllIdsCallback = (err: Error, ids?: number[]) => void
+  export type ListAllIds = (transaction: Sequelize.Transaction, callback: ListAllIdsCallback) => void
+
+  export type ListRandomPodIdsWithRequestCallback = (err: Error, podInstanceIds?: number[]) => void
+  export type ListRandomPodIdsWithRequest = (limit: number, tableWithPods: string, tableWithPodsJoins: string, callback: ListRandomPodIdsWithRequestCallback) => void
+
+  export type ListBadPodsCallback = (err: Error, podInstances?: PodInstance[]) => void
+  export type ListBadPods = (callback: ListBadPodsCallback) => void
+
+  export type LoadCallback = (err: Error, podInstance: PodInstance) => void
+  export type Load = (id: number, callback: LoadCallback) => void
+
+  export type LoadByHostCallback = (err: Error, podInstance: PodInstance) => void
+  export type LoadByHost = (host: string, callback: LoadByHostCallback) => void
+
+  export type RemoveAllCallback = (err: Error) => void
+  export type RemoveAll = (callback: RemoveAllCallback) => void
+
+  export type UpdatePodsScore = (goodPods: number[], badPods: number[]) => void
 }
 
 export interface PodClass {
index 2df32e4a4470028eb8987a1a1cf0c8069dd9ad02..107744c43063eb5c25307acc29b66540368aa247 100644 (file)
@@ -118,11 +118,11 @@ function associate (models) {
   })
 }
 
-countAll = function (callback) {
+countAll = function (callback: PodMethods.CountAllCallback) {
   return Pod.count().asCallback(callback)
 }
 
-incrementScores = function (ids, value, callback) {
+incrementScores = function (ids: number[], value: number, callback?: PodMethods.IncrementScoresCallback) {
   if (!callback) callback = function () { /* empty */ }
 
   const update = {
@@ -142,35 +142,25 @@ incrementScores = function (ids, value, callback) {
   return Pod.update(update, options).asCallback(callback)
 }
 
-list = function (callback) {
+list = function (callback: PodMethods.ListCallback) {
   return Pod.findAll().asCallback(callback)
 }
 
-listAllIds = function (transaction, callback) {
-  if (!callback) {
-    callback = transaction
-    transaction = null
-  }
-
+listAllIds = function (transaction: Sequelize.Transaction, callback: PodMethods.ListAllIdsCallback) {
   const query: any = {
     attributes: [ 'id' ]
   }
 
-  if (transaction) query.transaction = transaction
+  if (transaction !== null) query.transaction = transaction
 
-  return Pod.findAll(query).asCallback(function (err, pods) {
+  return Pod.findAll(query).asCallback(function (err: Error, pods) {
     if (err) return callback(err)
 
     return callback(null, map(pods, 'id'))
   })
 }
 
-listRandomPodIdsWithRequest = function (limit, tableWithPods, tableWithPodsJoins, callback) {
-  if (!callback) {
-    callback = tableWithPodsJoins
-    tableWithPodsJoins = ''
-  }
-
+listRandomPodIdsWithRequest = function (limit: number, tableWithPods: string, tableWithPodsJoins: string, callback: PodMethods.ListRandomPodIdsWithRequestCallback) {
   Pod.count().asCallback(function (err, count) {
     if (err) return callback(err)
 
@@ -204,7 +194,7 @@ listRandomPodIdsWithRequest = function (limit, tableWithPods, tableWithPodsJoins
   })
 }
 
-listBadPods = function (callback) {
+listBadPods = function (callback: PodMethods.ListBadPodsCallback) {
   const query = {
     where: {
       score: { $lte: 0 }
@@ -214,11 +204,11 @@ listBadPods = function (callback) {
   return Pod.findAll(query).asCallback(callback)
 }
 
-load = function (id, callback) {
+load = function (id: number, callback: PodMethods.LoadCallback) {
   return Pod.findById(id).asCallback(callback)
 }
 
-loadByHost = function (host, callback) {
+loadByHost = function (host: string, callback: PodMethods.LoadByHostCallback) {
   const query = {
     where: {
       host: host
@@ -228,11 +218,11 @@ loadByHost = function (host, callback) {
   return Pod.findOne(query).asCallback(callback)
 }
 
-removeAll = function (callback) {
+removeAll = function (callback: PodMethods.RemoveAllCallback) {
   return Pod.destroy().asCallback(callback)
 }
 
-updatePodsScore = function (goodPods, badPods) {
+updatePodsScore = function (goodPods: number[], badPods: number[]) {
   logger.info('Updating %d good pods and %d bad pods scores.', goodPods.length, badPods.length)
 
   if (goodPods.length !== 0) {
index 2bba8ce7fff42f08ce03007bba58cce727f086fe..4bbd79966b6d24a862bff855bb8b643bac25aaf7 100644 (file)
@@ -1,12 +1,26 @@
 import * as Sequelize from 'sequelize'
 
-import { PodAttributes } from './pod-interface'
+import { PodInstance, PodAttributes } from './pod-interface'
+
+export type RequestsGrouped = {
+  [ podId: number ]: {
+    request: RequestInstance,
+    pod: PodInstance
+  }[]
+}
 
 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 type CountTotalRequestsCallback = (err: Error, total: number) => void
+  export type CountTotalRequests = (callback: CountTotalRequestsCallback) => void
+
+  export type ListWithLimitAndRandomCallback = (err: Error, requestsGrouped?: RequestsGrouped) => void
+  export type ListWithLimitAndRandom = (limitPods, limitRequestsPerPod, callback: ListWithLimitAndRandomCallback) => void
+
+  export type RemoveWithEmptyToCallback = (err: Error) => void
+  export type RemoveWithEmptyTo = (callback: RemoveWithEmptyToCallback) => void
+
+  export type RemoveAllCallback = (err: Error) => void
+  export type RemoveAll = (callback: RemoveAllCallback) => void
 }
 
 export interface RequestClass {
@@ -21,12 +35,13 @@ export interface RequestAttributes {
   endpoint: string
 }
 
-export interface RequestInstance extends Sequelize.Instance<RequestAttributes> {
+export interface RequestInstance extends RequestClass, RequestAttributes, Sequelize.Instance<RequestAttributes> {
   id: number
   createdAt: Date
   updatedAt: Date
 
   setPods: Sequelize.HasManySetAssociationsMixin<PodAttributes, number>
+  Pods: PodInstance[]
 }
 
 export interface RequestModel extends RequestClass, Sequelize.Model<RequestInstance, RequestAttributes> {}
index 52116d6c4d2853d9e7756b7a8198b2c3810be52d..6d75ca6e51f6986e7ce4fc540cbb684e7939c836 100644 (file)
@@ -1,7 +1,8 @@
 import * as Sequelize from 'sequelize'
 
 export namespace RequestToPodMethods {
-  export type RemoveByRequestIdsAndPod = (requestsIds, podId, callback) => void
+  export type RemoveByRequestIdsAndPodCallback = (err: Error) => void
+  export type RemoveByRequestIdsAndPod = (requestsIds: number[], podId: number, callback?: RemoveByRequestIdsAndPodCallback) => void
 }
 
 export interface RequestToPodClass {
@@ -11,7 +12,7 @@ export interface RequestToPodClass {
 export interface RequestToPodAttributes {
 }
 
-export interface RequestToPodInstance extends Sequelize.Instance<RequestToPodAttributes> {
+export interface RequestToPodInstance extends RequestToPodClass, RequestToPodAttributes, Sequelize.Instance<RequestToPodAttributes> {
   id: number
   createdAt: Date
   updatedAt: Date
index 681f808b7ebce082b86fcff73aa17a2e9a33d241..3562069cc761b17fe8c80b523301a29b9dda48d6 100644 (file)
@@ -38,7 +38,7 @@ export default function (sequelize, DataTypes) {
 
 // ---------------------------------------------------------------------------
 
-removeByRequestIdsAndPod = function (requestsIds, podId, callback) {
+removeByRequestIdsAndPod = function (requestsIds: number[], podId: number, callback?: RequestToPodMethods.RemoveByRequestIdsAndPodCallback) {
   if (!callback) callback = function () { /* empty */ }
 
   const query = {
index a31c7108f1e6246da7a7be2b5149a69130031a23..ad576a2b1cef869526bccc92f214c02966abe72f 100644 (file)
@@ -1,10 +1,30 @@
 import * as Sequelize from 'sequelize'
 
+import { VideoInstance } from './video-interface'
+import { PodInstance } from './pod-interface'
+
+export type RequestsVideoEventGrouped = {
+  [ podId: number ]: {
+    id: number
+    type: string
+    count: number
+    video: VideoInstance
+    pod: PodInstance
+  }[]
+}
+
 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 type CountTotalRequestsCallback = (err: Error, total: number) => void
+  export type CountTotalRequests = (callback: CountTotalRequestsCallback) => void
+
+  export type ListWithLimitAndRandomCallback = (err: Error, requestsGrouped?: RequestsVideoEventGrouped) => void
+  export type ListWithLimitAndRandom = (limitPods: number, limitRequestsPerPod: number, callback: ListWithLimitAndRandomCallback) => void
+
+  export type RemoveByRequestIdsAndPodCallback = () => void
+  export type RemoveByRequestIdsAndPod = (ids: number[], podId: number, callback: RemoveByRequestIdsAndPodCallback) => void
+
+  export type RemoveAllCallback = () => void
+  export type RemoveAll = (callback: RemoveAllCallback) => void
 }
 
 export interface RequestVideoEventClass {
@@ -19,8 +39,10 @@ export interface RequestVideoEventAttributes {
   count: number
 }
 
-export interface RequestVideoEventInstance extends Sequelize.Instance<RequestVideoEventAttributes> {
+export interface RequestVideoEventInstance extends RequestVideoEventClass, RequestVideoEventAttributes, Sequelize.Instance<RequestVideoEventAttributes> {
   id: number
+
+  Video: VideoInstance
 }
 
 export interface RequestVideoEventModel extends RequestVideoEventClass, Sequelize.Model<RequestVideoEventInstance, RequestVideoEventAttributes> {}
index 234e2a8a9ea117ca4b21f7be6d90fde307f0aefa..e422649afc0b4072588b20efd98b4beffc91a80b 100644 (file)
@@ -5,16 +5,17 @@
 import { values } from 'lodash'
 import * as Sequelize from 'sequelize'
 
+import { database as db } from '../initializers/database'
 import { REQUEST_VIDEO_EVENT_TYPES } from '../initializers'
 import { isVideoEventCountValid } from '../helpers'
-
 import { addMethodsToModel } from './utils'
 import {
   RequestVideoEventClass,
   RequestVideoEventInstance,
   RequestVideoEventAttributes,
 
-  RequestVideoEventMethods
+  RequestVideoEventMethods,
+  RequestsVideoEventGrouped
 } from './request-video-event-interface'
 
 let RequestVideoEvent: Sequelize.Model<RequestVideoEventInstance, RequestVideoEventAttributes>
@@ -76,13 +77,13 @@ function associate (models) {
   })
 }
 
-countTotalRequests = function (callback) {
+countTotalRequests = function (callback: RequestVideoEventMethods.CountTotalRequestsCallback) {
   const query = {}
   return RequestVideoEvent.count(query).asCallback(callback)
 }
 
-listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
-  const Pod = RequestVideoEvent['sequelize'].models.Pod
+listWithLimitAndRandom = function (limitPods: number, limitRequestsPerPod: number, callback: RequestVideoEventMethods.ListWithLimitAndRandomCallback) {
+  const Pod = db.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" ' +
@@ -129,7 +130,7 @@ listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
   })
 }
 
-removeByRequestIdsAndPod = function (ids, podId, callback) {
+removeByRequestIdsAndPod = function (ids: number[], podId: number, callback: RequestVideoEventMethods.RemoveByRequestIdsAndPodCallback) {
   const query = {
     where: {
       id: {
@@ -154,15 +155,15 @@ removeByRequestIdsAndPod = function (ids, podId, callback) {
   RequestVideoEvent.destroy(query).asCallback(callback)
 }
 
-removeAll = function (callback) {
+removeAll = function (callback: RequestVideoEventMethods.RemoveAllCallback) {
   // Delete all requests
   RequestVideoEvent.truncate({ cascade: true }).asCallback(callback)
 }
 
 // ---------------------------------------------------------------------------
 
-function groupAndTruncateRequests (events, limitRequestsPerPod) {
-  const eventsGrouped = {}
+function groupAndTruncateRequests (events: RequestVideoEventInstance[], limitRequestsPerPod: number) {
+  const eventsGrouped: RequestsVideoEventGrouped = {}
 
   events.forEach(function (event) {
     const pod = event.Video.Author.Pod
index 6fe34ee9127ebd149a175f4da77b6ea4b310f6ee..04de7f159f85b1fe3fc8655a415b1b2de480934c 100644 (file)
@@ -1,10 +1,28 @@
 import * as Sequelize from 'sequelize'
 
+import { VideoInstance } from './video-interface'
+import { PodInstance } from './pod-interface'
+
+export type RequestsVideoQaduGrouped = {
+  [ podId: number ]: {
+    request: RequestVideoQaduInstance
+    video: VideoInstance
+    pod: PodInstance
+  }
+}
+
 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 type CountTotalRequestsCallback = (err: Error, total: number) => void
+  export type CountTotalRequests = (callback: CountTotalRequestsCallback) => void
+
+  export type ListWithLimitAndRandomCallback = (err: Error, requestsGrouped?: RequestsVideoQaduGrouped) => void
+  export type ListWithLimitAndRandom = (limitPods: number, limitRequestsPerPod: number, callback: ListWithLimitAndRandomCallback) => void
+
+  export type RemoveByRequestIdsAndPodCallback = () => void
+  export type RemoveByRequestIdsAndPod = (ids: number[], podId: number, callback: RemoveByRequestIdsAndPodCallback) => void
+
+  export type RemoveAllCallback = () => void
+  export type RemoveAll = (callback: RemoveAllCallback) => void
 }
 
 export interface RequestVideoQaduClass {
@@ -18,8 +36,11 @@ export interface RequestVideoQaduAttributes {
   type: string
 }
 
-export interface RequestVideoQaduInstance extends Sequelize.Instance<RequestVideoQaduAttributes> {
+export interface RequestVideoQaduInstance extends RequestVideoQaduClass, RequestVideoQaduAttributes, Sequelize.Instance<RequestVideoQaduAttributes> {
   id: number
+
+  Pod: PodInstance
+  Video: VideoInstance
 }
 
 export interface RequestVideoQaduModel extends RequestVideoQaduClass, Sequelize.Model<RequestVideoQaduInstance, RequestVideoQaduAttributes> {}
index e914e06cd19f66ccf603767f5747c8e80cb99e83..38627ad55f3fde4c2f9996390f856090f653b40d 100644 (file)
@@ -12,8 +12,8 @@
 import { values } from 'lodash'
 import * as Sequelize from 'sequelize'
 
+import { database as db } from '../initializers/database'
 import { REQUEST_VIDEO_QADU_TYPES } from '../initializers'
-
 import { addMethodsToModel } from './utils'
 import {
   RequestVideoQaduClass,
@@ -83,15 +83,16 @@ function associate (models) {
   })
 }
 
-countTotalRequests = function (callback) {
+countTotalRequests = function (callback: RequestVideoQaduMethods.CountTotalRequestsCallback) {
   const query = {}
   return RequestVideoQadu.count(query).asCallback(callback)
 }
 
-listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
-  const Pod = RequestVideoQadu['sequelize'].models.Pod
+listWithLimitAndRandom = function (limitPods: number, limitRequestsPerPod: number, callback: RequestVideoQaduMethods.ListWithLimitAndRandomCallback) {
+  const Pod = db.Pod
+  const tableJoin = ''
 
-  Pod.listRandomPodIdsWithRequest(limitPods, 'RequestVideoQadus', function (err, podIds) {
+  Pod.listRandomPodIdsWithRequest(limitPods, 'RequestVideoQadus', tableJoin, function (err, podIds) {
     if (err) return callback(err)
 
     // We don't have friends that have requests
@@ -122,7 +123,7 @@ listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
   })
 }
 
-removeByRequestIdsAndPod = function (ids, podId, callback) {
+removeByRequestIdsAndPod = function (ids: number[], podId: number, callback: RequestVideoQaduMethods.RemoveByRequestIdsAndPodCallback) {
   const query = {
     where: {
       id: {
@@ -135,14 +136,14 @@ removeByRequestIdsAndPod = function (ids, podId, callback) {
   RequestVideoQadu.destroy(query).asCallback(callback)
 }
 
-removeAll = function (callback) {
+removeAll = function (callback: RequestVideoQaduMethods.RemoveAllCallback) {
   // Delete all requests
   RequestVideoQadu.truncate({ cascade: true }).asCallback(callback)
 }
 
 // ---------------------------------------------------------------------------
 
-function groupAndTruncateRequests (requests, limitRequestsPerPod) {
+function groupAndTruncateRequests (requests: RequestVideoQaduInstance[], limitRequestsPerPod: number) {
   const requestsGrouped = {}
 
   requests.forEach(function (request) {
index 18fa291fa4a9acae8cbced3b26f7754164ca0f6b..71f81ae66fd78044f6f1c00a9e8a0a2db5b4fc44 100644 (file)
@@ -1,15 +1,16 @@
 import { values } from 'lodash'
 import * as Sequelize from 'sequelize'
 
+import { database as db } from '../initializers/database'
 import { REQUEST_ENDPOINTS } from '../initializers'
-
 import { addMethodsToModel } from './utils'
 import {
   RequestClass,
   RequestInstance,
   RequestAttributes,
 
-  RequestMethods
+  RequestMethods,
+  RequestsGrouped
 } from './request-interface'
 
 let Request: Sequelize.Model<RequestInstance, RequestAttributes>
@@ -59,7 +60,7 @@ function associate (models) {
   })
 }
 
-countTotalRequests = function (callback) {
+countTotalRequests = function (callback: RequestMethods.CountTotalRequestsCallback) {
   // 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 = {
@@ -69,10 +70,11 @@ countTotalRequests = function (callback) {
   return Request.count(query).asCallback(callback)
 }
 
-listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
-  const Pod = Request['sequelize'].models.Pod
+listWithLimitAndRandom = function (limitPods: number, limitRequestsPerPod: number, callback: RequestMethods.ListWithLimitAndRandomCallback) {
+  const Pod = db.Pod
+  const tableJoin = ''
 
-  Pod.listRandomPodIdsWithRequest(limitPods, 'RequestToPods', function (err, podIds) {
+  Pod.listRandomPodIdsWithRequest(limitPods, 'RequestToPods', '', function (err, podIds) {
     if (err) return callback(err)
 
     // We don't have friends that have requests
@@ -105,12 +107,12 @@ listWithLimitAndRandom = function (limitPods, limitRequestsPerPod, callback) {
   })
 }
 
-removeAll = function (callback) {
+removeAll = function (callback: RequestMethods.RemoveAllCallback) {
   // Delete all requests
   Request.truncate({ cascade: true }).asCallback(callback)
 }
 
-removeWithEmptyTo = function (callback) {
+removeWithEmptyTo = function (callback?: RequestMethods.RemoveWithEmptyToCallback) {
   if (!callback) callback = function () { /* empty */ }
 
   const query = {
@@ -128,8 +130,8 @@ removeWithEmptyTo = function (callback) {
 
 // ---------------------------------------------------------------------------
 
-function groupAndTruncateRequests (requests, limitRequestsPerPod) {
-  const requestsGrouped = {}
+function groupAndTruncateRequests (requests: RequestInstance[], limitRequestsPerPod: number) {
+  const requestsGrouped: RequestsGrouped = {}
 
   requests.forEach(function (request) {
     request.Pods.forEach(function (pod) {
index f96e1e9c54283f2fb4843ab21aa69216eeed850a..e045e7ca56411ac094a9a96e8e44b113ff9bf325 100644 (file)
@@ -1,7 +1,8 @@
 import * as Sequelize from 'sequelize'
 
 export namespace TagMethods {
-  export type FindOrCreateTags = (tags, transaction, callback) => void
+  export type FindOrCreateTagsCallback = (err: Error, tagInstances: TagInstance[]) => void
+  export type FindOrCreateTags = (tags: string[], transaction: Sequelize.Transaction, callback: FindOrCreateTagsCallback) => void
 }
 
 export interface TagClass {
index b2a9c9f81ddbfb3a8bd853ef735a73a3ded95584..c4402e83c2d19e2d5aa4e6581a8e274718b73e02 100644 (file)
@@ -52,15 +52,10 @@ function associate (models) {
   })
 }
 
-findOrCreateTags = function (tags, transaction, callback) {
-  if (!callback) {
-    callback = transaction
-    transaction = null
-  }
-
+findOrCreateTags = function (tags: string[], transaction: Sequelize.Transaction, callback: TagMethods.FindOrCreateTagsCallback) {
   const tagInstances = []
 
-  each(tags, function (tag, callbackEach) {
+  each<string, Error>(tags, function (tag, callbackEach) {
     const query: any = {
       where: {
         name: tag
index a504f42a1bca74a68bb99e44f1d71f49b6980877..98963b7438f346e9267c8390ef17560b9fd69d11 100644 (file)
@@ -1,17 +1,35 @@
 import * as Sequelize from 'sequelize'
+import * as Bluebird from 'bluebird'
+
+// Don't use barrel, import just what we need
+import { User as FormatedUser } from '../../shared/models/user.model'
 
 export namespace UserMethods {
-  export type IsPasswordMatch = (password, callback) => void
-  export type ToFormatedJSON = () => void
+  export type IsPasswordMatchCallback = (err: Error, same: boolean) => void
+  export type IsPasswordMatch = (password: string, callback: IsPasswordMatchCallback) => void
+
+  export type ToFormatedJSON = () => FormatedUser
   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 type CountTotalCallback = (err: Error, total: number) => void
+  export type CountTotal = (callback: CountTotalCallback) => void
+
+  export type GetByUsername = (username: string) => Bluebird<UserInstance>
+
+  export type ListCallback = (err: Error, userInstances: UserInstance[]) => void
+  export type List = (callback: ListCallback) => void
+
+  export type ListForApiCallback = (err: Error, userInstances?: UserInstance[], total?: number) => void
+  export type ListForApi = (start: number, count: number, sort: string, callback: ListForApiCallback) => void
+
+  export type LoadByIdCallback = (err: Error, userInstance: UserInstance) => void
+  export type LoadById = (id: number, callback: LoadByIdCallback) => void
+
+  export type LoadByUsernameCallback = (err: Error, userInstance: UserInstance) => void
+  export type LoadByUsername = (username: string, callback: LoadByUsernameCallback) => void
+
+  export type LoadByUsernameOrEmailCallback = (err: Error, userInstance: UserInstance) => void
+  export type LoadByUsernameOrEmail = (username: string, email: string, callback: LoadByUsernameOrEmailCallback) => void
 }
 
 export interface UserClass {
index 57d2e2b91d39b69fbac45acc50a2a022887a002e..e48869fd22a676d6d6a928579fb6b44f08cc3ffd 100644 (file)
@@ -1,6 +1,7 @@
 import * as Sequelize from 'sequelize'
 
 export namespace UserVideoRateMethods {
+  export type LoadCallback = (err: Error, userVideoRateInstance: UserVideoRateInstance) => void
   export type Load = (userId, videoId, transaction, callback) => void
 }
 
@@ -12,7 +13,7 @@ export interface UserVideoRateAttributes {
   type: string
 }
 
-export interface UserVideoRateInstance extends Sequelize.Instance<UserVideoRateAttributes> {
+export interface UserVideoRateInstance extends UserVideoRateClass, UserVideoRateAttributes, Sequelize.Instance<UserVideoRateAttributes> {
   id: number
   createdAt: Date
   updatedAt: Date
index 87886d8d00960c053cbd29918ab4a63af2dfa5b1..6b71e841263db7a1ea66ecdd95314305b8042782 100644 (file)
@@ -67,7 +67,7 @@ function associate (models) {
   })
 }
 
-load = function (userId, videoId, transaction, callback) {
+load = function (userId: number, videoId: number, transaction: Sequelize.Transaction, callback: UserVideoRateMethods.LoadCallback) {
   const options: Sequelize.FindOptions = {
     where: {
       userId,
index 12ddaaeb7ec2a861e27d276abb71fd82b9cb5c31..0fbfdda50e005f92dbea0be10ed3f50fa7a784a2 100644 (file)
@@ -117,7 +117,7 @@ export default function (sequelize, DataTypes) {
   return User
 }
 
-function beforeCreateOrUpdate (user, options) {
+function beforeCreateOrUpdate (user: UserInstance) {
   return new Promise(function (resolve, reject) {
     cryptPassword(user.password, function (err, hash) {
       if (err) return reject(err)
@@ -131,7 +131,7 @@ function beforeCreateOrUpdate (user, options) {
 
 // ------------------------------ METHODS ------------------------------
 
-isPasswordMatch = function (password, callback) {
+isPasswordMatch = function (password: string, callback: UserMethods.IsPasswordMatchCallback) {
   return comparePassword(password, this.password, callback)
 }
 
@@ -164,11 +164,11 @@ function associate (models) {
   })
 }
 
-countTotal = function (callback) {
+countTotal = function (callback: UserMethods.CountTotalCallback) {
   return this.count().asCallback(callback)
 }
 
-getByUsername = function (username) {
+getByUsername = function (username: string) {
   const query = {
     where: {
       username: username
@@ -178,11 +178,11 @@ getByUsername = function (username) {
   return User.findOne(query)
 }
 
-list = function (callback) {
+list = function (callback: UserMethods.ListCallback) {
   return User.find().asCallback(callback)
 }
 
-listForApi = function (start, count, sort, callback) {
+listForApi = function (start: number, count: number, sort: string, callback: UserMethods.ListForApiCallback) {
   const query = {
     offset: start,
     limit: count,
@@ -196,11 +196,11 @@ listForApi = function (start, count, sort, callback) {
   })
 }
 
-loadById = function (id, callback) {
+loadById = function (id: number, callback: UserMethods.LoadByIdCallback) {
   return User.findById(id).asCallback(callback)
 }
 
-loadByUsername = function (username, callback) {
+loadByUsername = function (username: string, callback: UserMethods.LoadByUsernameCallback) {
   const query = {
     where: {
       username: username
@@ -210,7 +210,7 @@ loadByUsername = function (username, callback) {
   return User.findOne(query).asCallback(callback)
 }
 
-loadByUsernameOrEmail = function (username, email, callback) {
+loadByUsernameOrEmail = function (username: string, email: string, callback: UserMethods.LoadByUsernameOrEmailCallback) {
   const query = {
     where: {
       $or: [ { username }, { email } ]
index fd84a92399e5f2aaefab3ef826d022f4e4f5be32..7ba96815e282a512db020243c68816ea6899ca8a 100644 (file)
@@ -1,7 +1,7 @@
 // Translate for example "-name" to [ 'name', 'DESC' ]
-function getSort (value) {
-  let field
-  let direction
+function getSort (value: string) {
+  let field: string
+  let direction: 'ASC' | 'DESC'
 
   if (value.substring(0, 1) === '-') {
     direction = 'DESC'
index 9b77fc6f5907ee66aacaad42b03c5aab7148dc47..d9cb93b42a32f5823967f78e6b306d6c366e7d16 100644 (file)
@@ -1,9 +1,13 @@
 import * as Sequelize from 'sequelize'
 
+// Don't use barrel, import just what we need
+import { VideoAbuse as FormatedVideoAbuse } from '../../shared/models/video-abuse.model'
+
 export namespace VideoAbuseMethods {
-  export type toFormatedJSON = () => void
+  export type toFormatedJSON = () => FormatedVideoAbuse
 
-  export type ListForApi = (start, count, sort, callback) => void
+  export type ListForApiCallback = (err: Error, videoAbuseInstances?: VideoAbuseInstance[], total?: number) => void
+  export type ListForApi = (start: number, count: number, sort: string, callback: ListForApiCallback) => void
 }
 
 export interface VideoAbuseClass {
@@ -15,7 +19,7 @@ export interface VideoAbuseAttributes {
   reason: string
 }
 
-export interface VideoAbuseInstance extends Sequelize.Instance<VideoAbuseAttributes> {
+export interface VideoAbuseInstance extends VideoAbuseClass, VideoAbuseAttributes, Sequelize.Instance<VideoAbuseAttributes> {
   id: number
   createdAt: Date
   updatedAt: Date
index ae2cd6748e824068ae4b69f221158f146b3945a8..9747181926302425ca8803605d61919a07c7b97d 100644 (file)
@@ -1,13 +1,25 @@
 import * as Sequelize from 'sequelize'
 
+// Don't use barrel, import just what we need
+import { BlacklistedVideo as FormatedBlacklistedVideo } from '../../shared/models/video-blacklist.model'
+
 export namespace BlacklistedVideoMethods {
-  export type ToFormatedJSON = () => void
+  export type ToFormatedJSON = () => FormatedBlacklistedVideo
+
+  export type CountTotalCallback = (err: Error, total: number) => void
+  export type CountTotal = (callback: CountTotalCallback) => void
+
+  export type ListCallback = (err: Error, backlistedVideoInstances: BlacklistedVideoInstance[]) => void
+  export type List = (callback: ListCallback) => void
+
+  export type ListForApiCallback = (err: Error, blacklistedVIdeoInstances?: BlacklistedVideoInstance[], total?: number) => void
+  export type ListForApi = (start: number, count: number, sort: string, callback: ListForApiCallback) => void
+
+  export type LoadByIdCallback = (err: Error, blacklistedVideoInstance: BlacklistedVideoInstance) => void
+  export type LoadById = (id: number, callback: LoadByIdCallback) => 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 type LoadByVideoIdCallback = (err: Error, blacklistedVideoInstance: BlacklistedVideoInstance) => void
+  export type LoadByVideoId = (id: string, callback: LoadByVideoIdCallback) => void
 }
 
 export interface BlacklistedVideoClass {
index fe72d5d46eb46be11a911f0c32270e2d661d9691..f3675608573f7ed974ce0288e901054b88fefe85 100644 (file)
@@ -66,15 +66,15 @@ function associate (models) {
   })
 }
 
-countTotal = function (callback) {
+countTotal = function (callback: BlacklistedVideoMethods.CountTotalCallback) {
   return BlacklistedVideo.count().asCallback(callback)
 }
 
-list = function (callback) {
+list = function (callback: BlacklistedVideoMethods.ListCallback) {
   return BlacklistedVideo.findAll().asCallback(callback)
 }
 
-listForApi = function (start, count, sort, callback) {
+listForApi = function (start: number, count: number, sort: string, callback: BlacklistedVideoMethods.ListForApiCallback) {
   const query = {
     offset: start,
     limit: count,
@@ -88,11 +88,11 @@ listForApi = function (start, count, sort, callback) {
   })
 }
 
-loadById = function (id, callback) {
+loadById = function (id: number, callback: BlacklistedVideoMethods.LoadByIdCallback) {
   return BlacklistedVideo.findById(id).asCallback(callback)
 }
 
-loadByVideoId = function (id, callback) {
+loadByVideoId = function (id: string, callback: BlacklistedVideoMethods.LoadByIdCallback) {
   const query = {
     where: {
       videoId: id
index b8dbeea357353409033bf5de2fc8d2a25179309f..7005f213c481bfdc88fcd2578ce6ccdb4654e825 100644 (file)
 import * as Sequelize from 'sequelize'
 
+import { AuthorInstance } from './author-interface'
+import { VideoTagInstance } from './video-tag-interface'
+
+// Don't use barrel, import just what we need
+import { Video as FormatedVideo } from '../../shared/models/video.model'
+
+export type FormatedAddRemoteVideo = {
+  name: string
+  category: number
+  licence: number
+  language: number
+  nsfw: boolean
+  description: string
+  infoHash: string
+  remoteId: string
+  author: string
+  duration: number
+  thumbnailData: string
+  tags: string[]
+  createdAt: Date
+  updatedAt: Date
+  extname: string
+  views: number
+  likes: number
+  dislikes: number
+}
+
+export type FormatedUpdateRemoteVideo = {
+  name: string
+  category: number
+  licence: number
+  language: number
+  nsfw: boolean
+  description: string
+  infoHash: string
+  remoteId: string
+  author: string
+  duration: number
+  tags: string[]
+  createdAt: Date
+  updatedAt: Date
+  extname: string
+  views: number
+  likes: number
+  dislikes: number
+}
+
 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 GenerateMagnetUri = () => string
+  export type GetVideoFilename = () => string
+  export type GetThumbnailName = () => string
+  export type GetPreviewName = () => string
+  export type GetTorrentName = () => string
+  export type IsOwned = () => boolean
+  export type ToFormatedJSON = () => FormatedVideo
+
+  export type ToAddRemoteJSONCallback = (err: Error, videoFormated?: FormatedAddRemoteVideo) => void
+  export type ToAddRemoteJSON = (callback: ToAddRemoteJSONCallback) => void
+
+  export type ToUpdateRemoteJSON = () => FormatedUpdateRemoteVideo
+
+  export type TranscodeVideofileCallback = (err: Error) => void
+  export type TranscodeVideofile = (callback: TranscodeVideofileCallback) => void
+
+  export type GenerateThumbnailFromDataCallback = (err: Error, thumbnailName?: string) => void
+  export type GenerateThumbnailFromData = (video: VideoInstance, thumbnailData: string, callback: GenerateThumbnailFromDataCallback) => void
+
+  export type GetDurationFromFileCallback = (err: Error, duration?: number) => 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 type ListCallback = () => void
+  export type List = (callback: ListCallback) => void
+
+  export type ListForApiCallback = (err: Error, videoInstances?: VideoInstance[], total?: number) => void
+  export type ListForApi = (start: number, count: number, sort: string, callback: ListForApiCallback) => void
+
+  export type LoadByHostAndRemoteIdCallback = (err: Error, videoInstance: VideoInstance) => void
+  export type LoadByHostAndRemoteId = (fromHost: string, remoteId: string, callback: LoadByHostAndRemoteIdCallback) => void
+
+  export type ListOwnedAndPopulateAuthorAndTagsCallback = (err: Error, videoInstances: VideoInstance[]) => void
+  export type ListOwnedAndPopulateAuthorAndTags = (callback: ListOwnedAndPopulateAuthorAndTagsCallback) => void
+
+  export type ListOwnedByAuthorCallback = (err: Error, videoInstances: VideoInstance[]) => void
+  export type ListOwnedByAuthor = (author: string, callback: ListOwnedByAuthorCallback) => void
+
+  export type LoadCallback = (err: Error, videoInstance: VideoInstance) => void
+  export type Load = (id: string, callback: LoadCallback) => void
+
+  export type LoadAndPopulateAuthorCallback = (err: Error, videoInstance: VideoInstance) => void
+  export type LoadAndPopulateAuthor = (id: string, callback: LoadAndPopulateAuthorCallback) => void
+
+  export type LoadAndPopulateAuthorAndPodAndTagsCallback = (err: Error, videoInstance: VideoInstance) => void
+  export type LoadAndPopulateAuthorAndPodAndTags = (id: string, callback: LoadAndPopulateAuthorAndPodAndTagsCallback) => void
+
+  export type SearchAndPopulateAuthorAndPodAndTagsCallback = (err: Error, videoInstances?: VideoInstance[], total?: number) => void
+  export type SearchAndPopulateAuthorAndPodAndTags = (value: string, field: string, start: number, count: number, sort: string, callback: SearchAndPopulateAuthorAndPodAndTagsCallback) => void
 }
 
 export interface VideoClass {
@@ -64,6 +137,9 @@ export interface VideoAttributes {
   views?: number
   likes?: number
   dislikes?: number
+
+  Author?: AuthorInstance
+  Tags?: VideoTagInstance[]
 }
 
 export interface VideoInstance extends VideoClass, VideoAttributes, Sequelize.Instance<VideoAttributes> {
index 468827b8c77093521424a522f13107f100e0a615..f928cecffd0d5efcca59af4dd82c8bc08da4225d 100644 (file)
@@ -9,7 +9,7 @@ export interface VideoTagClass {
 export interface VideoTagAttributes {
 }
 
-export interface VideoTagInstance extends Sequelize.Instance<VideoTagAttributes> {
+export interface VideoTagInstance extends VideoTagClass, VideoTagAttributes, Sequelize.Instance<VideoTagAttributes> {
   id: number
   createdAt: Date
   updatedAt: Date
index 5558a7c3bf1391dd78c7b4acd27945d388681f3c..3f808b811f9d4b63b571d97fa5b62c59ddb98776 100644 (file)
@@ -11,6 +11,7 @@ import { join } from 'path'
 import * as Sequelize from 'sequelize'
 
 import { database as db } from '../initializers/database'
+import { VideoTagInstance } from './video-tag-interface'
 import {
   logger,
   isVideoNameValid,
@@ -266,7 +267,7 @@ export default function (sequelize, DataTypes) {
   return Video
 }
 
-function beforeValidate (video, options) {
+function beforeValidate (video: VideoInstance) {
   // Put a fake infoHash if it does not exists yet
   if (video.isOwned() && !video.infoHash) {
     // 40 hexa length
@@ -274,7 +275,7 @@ function beforeValidate (video, options) {
   }
 }
 
-function beforeCreate (video, options) {
+function beforeCreate (video: VideoInstance, options: { transaction: Sequelize.Transaction }) {
   return new Promise(function (resolve, reject) {
     const tasks = []
 
@@ -318,7 +319,7 @@ function beforeCreate (video, options) {
   })
 }
 
-function afterDestroy (video, options) {
+function afterDestroy (video: VideoInstance) {
   return new Promise(function (resolve, reject) {
     const tasks = []
 
@@ -401,7 +402,7 @@ generateMagnetUri = function () {
   }
 
   const xs = baseUrlHttp + STATIC_PATHS.TORRENTS + this.getTorrentName()
-  const announce = baseUrlWs + '/tracker/socket'
+  const announce = [ baseUrlWs + '/tracker/socket' ]
   const urlList = [ baseUrlHttp + STATIC_PATHS.WEBSEED + this.getVideoFilename() ]
 
   const magnetHash = {
@@ -496,7 +497,7 @@ toFormatedJSON = function () {
   return json
 }
 
-toAddRemoteJSON = function (callback) {
+toAddRemoteJSON = function (callback: VideoMethods.ToAddRemoteJSONCallback) {
   // Get thumbnail data to send to the other pod
   const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, this.getThumbnailName())
   fs.readFile(thumbnailPath, (err, thumbnailData) => {
@@ -517,7 +518,7 @@ toAddRemoteJSON = function (callback) {
       author: this.Author.name,
       duration: this.duration,
       thumbnailData: thumbnailData.toString('binary'),
-      tags: map(this.Tags, 'name'),
+      tags: map<VideoTagInstance, string>(this.Tags, 'name'),
       createdAt: this.createdAt,
       updatedAt: this.updatedAt,
       extname: this.extname,
@@ -530,7 +531,7 @@ toAddRemoteJSON = function (callback) {
   })
 }
 
-toUpdateRemoteJSON = function (callback) {
+toUpdateRemoteJSON = function () {
   const json = {
     name: this.name,
     category: this.category,
@@ -542,7 +543,7 @@ toUpdateRemoteJSON = function (callback) {
     remoteId: this.id,
     author: this.Author.name,
     duration: this.duration,
-    tags: map(this.Tags, 'name'),
+    tags: map<VideoTagInstance, string>(this.Tags, 'name'),
     createdAt: this.createdAt,
     updatedAt: this.updatedAt,
     extname: this.extname,
@@ -554,7 +555,7 @@ toUpdateRemoteJSON = function (callback) {
   return json
 }
 
-transcodeVideofile = function (finalCallback) {
+transcodeVideofile = function (finalCallback: VideoMethods.TranscodeVideofileCallback) {
   const video = this
 
   const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR
@@ -591,9 +592,9 @@ transcodeVideofile = function (finalCallback) {
           video.save().asCallback(callback)
         }
 
-      ], function (err) {
+      ], function (err: Error) {
         if (err) {
-          // Autodescruction...
+          // Autodesctruction...
           video.destroy().asCallback(function (err) {
             if (err) logger.error('Cannot destruct video after transcoding failure.', { error: err })
           })
@@ -609,7 +610,7 @@ transcodeVideofile = function (finalCallback) {
 
 // ------------------------------ STATICS ------------------------------
 
-generateThumbnailFromData = function (video, thumbnailData, callback) {
+generateThumbnailFromData = function (video: VideoInstance, thumbnailData: string, callback: VideoMethods.GenerateThumbnailFromDataCallback) {
   // Creating the thumbnail for a remote video
 
   const thumbnailName = video.getThumbnailName()
@@ -621,7 +622,7 @@ generateThumbnailFromData = function (video, thumbnailData, callback) {
   })
 }
 
-getDurationFromFile = function (videoPath, callback) {
+getDurationFromFile = function (videoPath: string, callback: VideoMethods.GetDurationFromFileCallback) {
   ffmpeg.ffprobe(videoPath, function (err, metadata) {
     if (err) return callback(err)
 
@@ -629,11 +630,11 @@ getDurationFromFile = function (videoPath, callback) {
   })
 }
 
-list = function (callback) {
+list = function (callback: VideoMethods.ListCallback) {
   return Video.findAll().asCallback(callback)
 }
 
-listForApi = function (start, count, sort, callback) {
+listForApi = function (start: number, count: number, sort: string, callback: VideoMethods.ListForApiCallback) {
   // Exclude Blakclisted videos from the list
   const query = {
     distinct: true,
@@ -658,7 +659,7 @@ listForApi = function (start, count, sort, callback) {
   })
 }
 
-loadByHostAndRemoteId = function (fromHost, remoteId, callback) {
+loadByHostAndRemoteId = function (fromHost: string, remoteId: string, callback: VideoMethods.LoadByHostAndRemoteIdCallback) {
   const query = {
     where: {
       remoteId: remoteId
@@ -682,7 +683,7 @@ loadByHostAndRemoteId = function (fromHost, remoteId, callback) {
   return Video.findOne(query).asCallback(callback)
 }
 
-listOwnedAndPopulateAuthorAndTags = function (callback) {
+listOwnedAndPopulateAuthorAndTags = function (callback: VideoMethods.ListOwnedAndPopulateAuthorAndTagsCallback) {
   // If remoteId is null this is *our* video
   const query = {
     where: {
@@ -694,7 +695,7 @@ listOwnedAndPopulateAuthorAndTags = function (callback) {
   return Video.findAll(query).asCallback(callback)
 }
 
-listOwnedByAuthor = function (author, callback) {
+listOwnedByAuthor = function (author: string, callback: VideoMethods.ListOwnedByAuthorCallback) {
   const query = {
     where: {
       remoteId: null
@@ -712,11 +713,11 @@ listOwnedByAuthor = function (author, callback) {
   return Video.findAll(query).asCallback(callback)
 }
 
-load = function (id, callback) {
+load = function (id: string, callback: VideoMethods.LoadCallback) {
   return Video.findById(id).asCallback(callback)
 }
 
-loadAndPopulateAuthor = function (id, callback) {
+loadAndPopulateAuthor = function (id: string, callback: VideoMethods.LoadAndPopulateAuthorCallback) {
   const options = {
     include: [ Video['sequelize'].models.Author ]
   }
@@ -724,7 +725,7 @@ loadAndPopulateAuthor = function (id, callback) {
   return Video.findById(id, options).asCallback(callback)
 }
 
-loadAndPopulateAuthorAndPodAndTags = function (id, callback) {
+loadAndPopulateAuthorAndPodAndTags = function (id: string, callback: VideoMethods.LoadAndPopulateAuthorAndPodAndTagsCallback) {
   const options = {
     include: [
       {
@@ -738,7 +739,14 @@ loadAndPopulateAuthorAndPodAndTags = function (id, callback) {
   return Video.findById(id, options).asCallback(callback)
 }
 
-searchAndPopulateAuthorAndPodAndTags = function (value, field, start, count, sort, callback) {
+searchAndPopulateAuthorAndPodAndTags = function (
+  value: string,
+  field: string,
+  start: number,
+  count: number,
+  sort: string,
+  callback: VideoMethods.SearchAndPopulateAuthorAndPodAndTagsCallback
+) {
   const podInclude: any = {
     model: Video['sequelize'].models.Pod,
     required: false
@@ -821,27 +829,27 @@ function createBaseVideosWhere () {
   }
 }
 
-function removeThumbnail (video, callback) {
+function removeThumbnail (video: VideoInstance, callback: (err: Error) => void) {
   const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, video.getThumbnailName())
   fs.unlink(thumbnailPath, callback)
 }
 
-function removeFile (video, callback) {
+function removeFile (video: VideoInstance, callback: (err: Error) => void) {
   const filePath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename())
   fs.unlink(filePath, callback)
 }
 
-function removeTorrent (video, callback) {
+function removeTorrent (video: VideoInstance, callback: (err: Error) => void) {
   const torrenPath = join(CONFIG.STORAGE.TORRENTS_DIR, video.getTorrentName())
   fs.unlink(torrenPath, callback)
 }
 
-function removePreview (video, callback) {
+function removePreview (video: VideoInstance, callback: (err: Error) => void) {
   // Same name than video thumnail
   fs.unlink(CONFIG.STORAGE.PREVIEWS_DIR + video.getPreviewName(), callback)
 }
 
-function createTorrentFromVideo (video, videoPath, callback) {
+function createTorrentFromVideo (video: VideoInstance, videoPath: string, callback: (err: Error) => void) {
   const options = {
     announceList: [
       [ CONFIG.WEBSERVER.WS + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT + '/tracker/socket' ]
@@ -865,24 +873,23 @@ function createTorrentFromVideo (video, videoPath, callback) {
   })
 }
 
-function createPreview (video, videoPath, callback) {
-  generateImage(video, videoPath, CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName(), callback)
+function createPreview (video: VideoInstance, videoPath: string, callback: (err: Error) => void) {
+  generateImage(video, videoPath, CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName(), null, callback)
 }
 
-function createThumbnail (video, videoPath, callback) {
+function createThumbnail (video: VideoInstance, videoPath: string, callback: (err: Error) => void) {
   generateImage(video, videoPath, CONFIG.STORAGE.THUMBNAILS_DIR, video.getThumbnailName(), THUMBNAILS_SIZE, callback)
 }
 
-function generateImage (video, videoPath, folder, imageName, size, callback?) {
+type GenerateImageCallback = (err: Error, imageName: string) => void
+function generateImage (video: VideoInstance, videoPath: string, folder: string, imageName: string, size: string, callback?: GenerateImageCallback) {
   const options: any = {
     filename: imageName,
     count: 1,
     folder
   }
 
-  if (!callback) {
-    callback = size
-  } else {
+  if (size) {
     options.size = size
   }
 
@@ -894,7 +901,7 @@ function generateImage (video, videoPath, folder, imageName, size, callback?) {
     .thumbnail(options)
 }
 
-function removeFromBlacklist (video, callback) {
+function removeFromBlacklist (video: VideoInstance, callback: (err: Error) => void) {
   // Find the blacklisted video
   db.BlacklistedVideo.loadByVideoId(video.id, function (err, video) {
     // If an error occured, stop here
@@ -908,7 +915,7 @@ function removeFromBlacklist (video, callback) {
       video.destroy().asCallback(callback)
     } else {
       // If haven't found it, simply ignore it and do nothing
-      return callback()
+      return callback(null)
     }
   })
 }
diff --git a/shared/index.ts b/shared/index.ts
new file mode 100644 (file)
index 0000000..ad200c5
--- /dev/null
@@ -0,0 +1 @@
+export * from './models'
diff --git a/shared/models/index.ts b/shared/models/index.ts
new file mode 100644 (file)
index 0000000..b498d62
--- /dev/null
@@ -0,0 +1,5 @@
+export * from './pod.model'
+export * from './user.model'
+export * from './video-abuse.model'
+export * from './video-blacklist.model'
+export * from './video.model'
diff --git a/shared/models/pod.model.ts b/shared/models/pod.model.ts
new file mode 100644 (file)
index 0000000..d254219
--- /dev/null
@@ -0,0 +1,7 @@
+export interface Pod {
+  id: number,
+  host: string,
+  email: string,
+  score: number,
+  createdAt: Date
+}
diff --git a/shared/models/user.model.ts b/shared/models/user.model.ts
new file mode 100644 (file)
index 0000000..01cc380
--- /dev/null
@@ -0,0 +1,8 @@
+export interface User {
+  id: number
+  username: string
+  email: string
+  displayNSFW: boolean
+  role: string[]
+  createdAt: Date
+}
diff --git a/shared/models/video-abuse.model.ts b/shared/models/video-abuse.model.ts
new file mode 100644 (file)
index 0000000..e005a1f
--- /dev/null
@@ -0,0 +1,8 @@
+export interface VideoAbuse {
+  id: number
+  reporterPodHost: string
+  reason: string
+  reporterUsername: string
+  videoId: number
+  createdAt: Date
+}
diff --git a/shared/models/video-blacklist.model.ts b/shared/models/video-blacklist.model.ts
new file mode 100644 (file)
index 0000000..6086250
--- /dev/null
@@ -0,0 +1,5 @@
+export interface BlacklistedVideo {
+  id: number
+  videoId: number
+  createdAt: Date
+}
diff --git a/shared/models/video.model.ts b/shared/models/video.model.ts
new file mode 100644 (file)
index 0000000..355e912
--- /dev/null
@@ -0,0 +1,3 @@
+export interface Video {
+
+}
index 28d33fa975d2e86902b8d43ef870840027b0faf4..c219dcea3a0fae2735f6ef8df63e3bcbba7c3700 100644 (file)
--- a/yarn.lock
+++ b/yarn.lock
   version "4.14.64"
   resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.64.tgz#979cf3a3d4a368670840bf9b3e448dc33ffe84ee"
 
+"@types/magnet-uri@^5.1.1":
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/@types/magnet-uri/-/magnet-uri-5.1.1.tgz#861aaf64c92a3137dd848fefc55cd352a8ea851a"
+  dependencies:
+    "@types/node" "*"
+
 "@types/mime@*":
   version "0.0.29"
   resolved "https://registry.yarnpkg.com/@types/mime/-/mime-0.0.29.tgz#fbcfd330573b912ef59eeee14602bface630754b"
   dependencies:
     "@types/express" "*"
 
+"@types/multer@^0.0.34":
+  version "0.0.34"
+  resolved "https://registry.yarnpkg.com/@types/multer/-/multer-0.0.34.tgz#4b542b380dcf59bced8b66294654dc67a7fab383"
+  dependencies:
+    "@types/express" "*"
+
 "@types/node@*", "@types/node@^7.0.18":
   version "7.0.22"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.22.tgz#4593f4d828bdd612929478ea40c67b4f403ca255"