Cleanup helpers
[oweals/peertube.git] / server / helpers / core-utils.ts
1 /*
2   Different from 'utils' because we don't not import other PeerTube modules.
3   Useful to avoid circular dependencies.
4 */
5
6 import * as bcrypt from 'bcrypt'
7 import * as createTorrent from 'create-torrent'
8 import { pseudoRandomBytes } from 'crypto'
9 import { readdir, readFile, rename, stat, Stats, unlink, writeFile } from 'fs'
10 import * as mkdirp from 'mkdirp'
11 import { join } from 'path'
12 import * as pem from 'pem'
13 import * as rimraf from 'rimraf'
14
15 function isTestInstance () {
16   return process.env.NODE_ENV === 'test'
17 }
18
19 function root () {
20   // We are in /helpers/utils.js
21   const paths = [ __dirname, '..', '..' ]
22
23   // We are under /dist directory
24   if (process.mainModule.filename.endsWith('.ts') === false) {
25     paths.push('..')
26   }
27
28   return join.apply(null, paths)
29 }
30
31 // Thanks: https://stackoverflow.com/a/12034334
32 function escapeHTML (stringParam) {
33   const entityMap = {
34     '&': '&',
35     '<': '&lt;',
36     '>': '&gt;',
37     '"': '&quot;',
38     "'": '&#39;',
39     '/': '&#x2F;',
40     '`': '&#x60;',
41     '=': '&#x3D;'
42   }
43
44   return String(stringParam).replace(/[&<>"'`=\/]/g, s => entityMap[s])
45 }
46
47 function pageToStartAndCount (page: number, itemsPerPage: number) {
48   const start = (page - 1) * itemsPerPage
49
50   return { start, count: itemsPerPage }
51 }
52
53 function promisify0<A> (func: (cb: (err: any, result: A) => void) => void): () => Promise<A> {
54   return function promisified (): Promise<A> {
55     return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => {
56       func.apply(null, [ (err: any, res: A) => err ? reject(err) : resolve(res) ])
57     })
58   }
59 }
60
61 // Thanks to https://gist.github.com/kumasento/617daa7e46f13ecdd9b2
62 function promisify1<T, A> (func: (arg: T, cb: (err: any, result: A) => void) => void): (arg: T) => Promise<A> {
63   return function promisified (arg: T): Promise<A> {
64     return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => {
65       func.apply(null, [ arg, (err: any, res: A) => err ? reject(err) : resolve(res) ])
66     })
67   }
68 }
69
70 function promisify1WithVoid<T> (func: (arg: T, cb: (err: any) => void) => void): (arg: T) => Promise<void> {
71   return function promisified (arg: T): Promise<void> {
72     return new Promise<void>((resolve: () => void, reject: (err: any) => void) => {
73       func.apply(null, [ arg, (err: any) => err ? reject(err) : resolve() ])
74     })
75   }
76 }
77
78 function promisify2<T, U, A> (func: (arg1: T, arg2: U, cb: (err: any, result: A) => void) => void): (arg1: T, arg2: U) => Promise<A> {
79   return function promisified (arg1: T, arg2: U): Promise<A> {
80     return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => {
81       func.apply(null, [ arg1, arg2, (err: any, res: A) => err ? reject(err) : resolve(res) ])
82     })
83   }
84 }
85
86 function promisify2WithVoid<T, U> (func: (arg1: T, arg2: U, cb: (err: any) => void) => void): (arg1: T, arg2: U) => Promise<void> {
87   return function promisified (arg1: T, arg2: U): Promise<void> {
88     return new Promise<void>((resolve: () => void, reject: (err: any) => void) => {
89       func.apply(null, [ arg1, arg2, (err: any) => err ? reject(err) : resolve() ])
90     })
91   }
92 }
93
94 const readFileBufferPromise = promisify1<string, Buffer>(readFile)
95 const unlinkPromise = promisify1WithVoid<string>(unlink)
96 const renamePromise = promisify2WithVoid<string, string>(rename)
97 const writeFilePromise = promisify2WithVoid<string, any>(writeFile)
98 const readdirPromise = promisify1<string, string[]>(readdir)
99 const mkdirpPromise = promisify1<string, string>(mkdirp)
100 const pseudoRandomBytesPromise = promisify1<number, Buffer>(pseudoRandomBytes)
101 const createPrivateKey = promisify1<number, { key: string }>(pem.createPrivateKey)
102 const getPublicKey = promisify1<string, { publicKey: string }>(pem.getPublicKey)
103 const bcryptComparePromise = promisify2<any, string, boolean>(bcrypt.compare)
104 const bcryptGenSaltPromise = promisify1<number, string>(bcrypt.genSalt)
105 const bcryptHashPromise = promisify2<any, string | number, string>(bcrypt.hash)
106 const createTorrentPromise = promisify2<string, any, any>(createTorrent)
107 const rimrafPromise = promisify1WithVoid<string>(rimraf)
108 const statPromise = promisify1<string, Stats>(stat)
109
110 // ---------------------------------------------------------------------------
111
112 export {
113   isTestInstance,
114   root,
115   escapeHTML,
116   pageToStartAndCount,
117
118   promisify0,
119   promisify1,
120
121   readdirPromise,
122   readFileBufferPromise,
123   unlinkPromise,
124   renamePromise,
125   writeFilePromise,
126   mkdirpPromise,
127   pseudoRandomBytesPromise,
128   createPrivateKey,
129   getPublicKey,
130   bcryptComparePromise,
131   bcryptGenSaltPromise,
132   bcryptHashPromise,
133   createTorrentPromise,
134   rimrafPromise,
135   statPromise
136 }