diff options
78 files changed, 583 insertions, 485 deletions
diff --git a/.eslintrc.json b/.eslintrc.json index a49a9e71b..c7597cef3 100644 --- a/.eslintrc.json +++ b/.eslintrc.json | |||
@@ -102,6 +102,9 @@ | |||
102 | "parserOptions": { | 102 | "parserOptions": { |
103 | "project": [ | 103 | "project": [ |
104 | "./tsconfig.json", | 104 | "./tsconfig.json", |
105 | "./shared/tsconfig.json", | ||
106 | "./scripts/tsconfig.json", | ||
107 | "./server/tsconfig.json", | ||
105 | "./server/tools/tsconfig.json" | 108 | "./server/tools/tsconfig.json" |
106 | ] | 109 | ] |
107 | } | 110 | } |
diff --git a/.gitignore b/.gitignore index 3027b6058..cd7d3f59b 100644 --- a/.gitignore +++ b/.gitignore | |||
@@ -50,3 +50,6 @@ yarn-error.log | |||
50 | /server/tools/import-mediacore.ts | 50 | /server/tools/import-mediacore.ts |
51 | /docker-volume/ | 51 | /docker-volume/ |
52 | /init.mp4 | 52 | /init.mp4 |
53 | |||
54 | # TypeScript | ||
55 | *.tsbuildinfo | ||
diff --git a/scripts/build/server.sh b/scripts/build/server.sh index b903f8250..865bdd095 100755 --- a/scripts/build/server.sh +++ b/scripts/build/server.sh | |||
@@ -4,7 +4,10 @@ set -eu | |||
4 | 4 | ||
5 | rm -rf ./dist | 5 | rm -rf ./dist |
6 | 6 | ||
7 | npm run tsc | 7 | npm run tsc -- -b --verbose |
8 | cp "./tsconfig.json" "./dist" | 8 | cp "./tsconfig.base.json" "./tsconfig.json" "./dist/" |
9 | cp "./scripts/tsconfig.json" "./dist/scripts/" | ||
10 | cp "./server/tsconfig.json" "./dist/server/" | ||
11 | cp "./shared/tsconfig.json" "./dist/shared/" | ||
9 | cp -r "./server/static" "./server/assets" "./dist/server" | 12 | cp -r "./server/static" "./server/assets" "./dist/server" |
10 | cp -r "./server/lib/emails" "./dist/server/lib" | 13 | cp -r "./server/lib/emails" "./dist/server/lib" |
diff --git a/scripts/client-build-stats.ts b/scripts/client-build-stats.ts index 70ceda975..91844dfcd 100644 --- a/scripts/client-build-stats.ts +++ b/scripts/client-build-stats.ts | |||
@@ -3,7 +3,7 @@ registerTSPaths() | |||
3 | 3 | ||
4 | import { readdir, stat } from 'fs-extra' | 4 | import { readdir, stat } from 'fs-extra' |
5 | import { join } from 'path' | 5 | import { join } from 'path' |
6 | import { root } from '@server/helpers/core-utils' | 6 | import { root } from '@shared/core-utils' |
7 | 7 | ||
8 | async function run () { | 8 | async function run () { |
9 | const result = { | 9 | const result = { |
diff --git a/scripts/setup/cli.sh b/scripts/setup/cli.sh index ea327e5a1..d0ad2ec5f 100755 --- a/scripts/setup/cli.sh +++ b/scripts/setup/cli.sh | |||
@@ -11,6 +11,6 @@ rm -rf ./dist/server/tools/ | |||
11 | yarn install --pure-lockfile | 11 | yarn install --pure-lockfile |
12 | ) | 12 | ) |
13 | 13 | ||
14 | npm run tsc -- --build ./server/tools/tsconfig.json | 14 | npm run tsc -- --build --verbose ./server/tools/tsconfig.json |
15 | cp -r "./server/tools/node_modules" "./dist/server/tools" | 15 | cp -r "./server/tools/node_modules" "./dist/server/tools" |
16 | cp "./tsconfig.json" "./dist" | 16 | cp "./tsconfig.json" "./dist" |
diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json new file mode 100644 index 000000000..0d9716f2d --- /dev/null +++ b/scripts/tsconfig.json | |||
@@ -0,0 +1,10 @@ | |||
1 | { | ||
2 | "extends": "../tsconfig.base.json", | ||
3 | "compilerOptions": { | ||
4 | "outDir": "../dist/scripts", | ||
5 | }, | ||
6 | "references": [ | ||
7 | { "path": "../shared" }, | ||
8 | { "path": "../server" } | ||
9 | ] | ||
10 | } | ||
diff --git a/server/controllers/api/users/token.ts b/server/controllers/api/users/token.ts index 1d4004ce0..42f4f6096 100644 --- a/server/controllers/api/users/token.ts +++ b/server/controllers/api/users/token.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import RateLimit from 'express-rate-limit' | 2 | import RateLimit from 'express-rate-limit' |
3 | import { logger } from '@server/helpers/logger' | 3 | import { logger } from '@server/helpers/logger' |
4 | import { buildUUID } from '@server/helpers/uuid' | 4 | import { buildUUID } from '@shared/core-utils/uuid' |
5 | import { CONFIG } from '@server/initializers/config' | 5 | import { CONFIG } from '@server/initializers/config' |
6 | import { getAuthNameFromRefreshGrant, getBypassFromExternalAuth, getBypassFromPasswordGrant } from '@server/lib/auth/external-auth' | 6 | import { getAuthNameFromRefreshGrant, getBypassFromExternalAuth, getBypassFromPasswordGrant } from '@server/lib/auth/external-auth' |
7 | import { handleOAuthToken } from '@server/lib/auth/oauth' | 7 | import { handleOAuthToken } from '@server/lib/auth/oauth' |
diff --git a/server/controllers/api/video-playlist.ts b/server/controllers/api/video-playlist.ts index 8b7a76718..f8f07b1c6 100644 --- a/server/controllers/api/video-playlist.ts +++ b/server/controllers/api/video-playlist.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { join } from 'path' | 2 | import { join } from 'path' |
3 | import { uuidToShort } from '@server/helpers/uuid' | 3 | import { uuidToShort } from '@shared/core-utils/uuid' |
4 | import { scheduleRefreshIfNeeded } from '@server/lib/activitypub/playlists' | 4 | import { scheduleRefreshIfNeeded } from '@server/lib/activitypub/playlists' |
5 | import { Hooks } from '@server/lib/plugins/hooks' | 5 | import { Hooks } from '@server/lib/plugins/hooks' |
6 | import { getServerActor } from '@server/models/application/application' | 6 | import { getServerActor } from '@server/models/application/application' |
diff --git a/server/controllers/api/videos/live.ts b/server/controllers/api/videos/live.ts index 3e1480cf2..e466d041b 100644 --- a/server/controllers/api/videos/live.ts +++ b/server/controllers/api/videos/live.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { createReqFiles } from '@server/helpers/express-utils' | 2 | import { createReqFiles } from '@server/helpers/express-utils' |
3 | import { buildUUID, uuidToShort } from '@server/helpers/uuid' | 3 | import { buildUUID, uuidToShort } from '@shared/core-utils/uuid' |
4 | import { CONFIG } from '@server/initializers/config' | 4 | import { CONFIG } from '@server/initializers/config' |
5 | import { ASSETS_PATH, MIMETYPES } from '@server/initializers/constants' | 5 | import { ASSETS_PATH, MIMETYPES } from '@server/initializers/constants' |
6 | import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url' | 6 | import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url' |
diff --git a/server/controllers/api/videos/upload.ts b/server/controllers/api/videos/upload.ts index 1be87f746..a4d0f980f 100644 --- a/server/controllers/api/videos/upload.ts +++ b/server/controllers/api/videos/upload.ts | |||
@@ -1,9 +1,9 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { move } from 'fs-extra' | 2 | import { move } from 'fs-extra' |
3 | import { basename } from 'path' | 3 | import { basename } from 'path' |
4 | import { getLowercaseExtension } from '@server/helpers/core-utils' | 4 | import { getLowercaseExtension } from '@shared/core-utils' |
5 | import { getResumableUploadPath } from '@server/helpers/upload' | 5 | import { getResumableUploadPath } from '@server/helpers/upload' |
6 | import { uuidToShort } from '@server/helpers/uuid' | 6 | import { uuidToShort } from '@shared/core-utils/uuid' |
7 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' | 7 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' |
8 | import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url' | 8 | import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url' |
9 | import { generateWebTorrentVideoFilename } from '@server/lib/paths' | 9 | import { generateWebTorrentVideoFilename } from '@server/lib/paths' |
diff --git a/server/controllers/client.ts b/server/controllers/client.ts index 2157ae533..8a56f2f75 100644 --- a/server/controllers/client.ts +++ b/server/controllers/client.ts | |||
@@ -7,7 +7,7 @@ import { CONFIG } from '@server/initializers/config' | |||
7 | import { Hooks } from '@server/lib/plugins/hooks' | 7 | import { Hooks } from '@server/lib/plugins/hooks' |
8 | import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '@shared/core-utils/i18n' | 8 | import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '@shared/core-utils/i18n' |
9 | import { HttpStatusCode } from '@shared/models' | 9 | import { HttpStatusCode } from '@shared/models' |
10 | import { root } from '../helpers/core-utils' | 10 | import { root } from '@shared/core-utils' |
11 | import { STATIC_MAX_AGE } from '../initializers/constants' | 11 | import { STATIC_MAX_AGE } from '../initializers/constants' |
12 | import { ClientHtml, sendHTML, serveIndexHTML } from '../lib/client-html' | 12 | import { ClientHtml, sendHTML, serveIndexHTML } from '../lib/client-html' |
13 | import { asyncMiddleware, embedCSP } from '../middlewares' | 13 | import { asyncMiddleware, embedCSP } from '../middlewares' |
diff --git a/server/controllers/static.ts b/server/controllers/static.ts index 0d94cac9b..87bceba7a 100644 --- a/server/controllers/static.ts +++ b/server/controllers/static.ts | |||
@@ -5,7 +5,7 @@ import { serveIndexHTML } from '@server/lib/client-html' | |||
5 | import { ServerConfigManager } from '@server/lib/server-config-manager' | 5 | import { ServerConfigManager } from '@server/lib/server-config-manager' |
6 | import { HttpStatusCode } from '@shared/models' | 6 | import { HttpStatusCode } from '@shared/models' |
7 | import { HttpNodeinfoDiasporaSoftwareNsSchema20 } from '../../shared/models/nodeinfo/nodeinfo.model' | 7 | import { HttpNodeinfoDiasporaSoftwareNsSchema20 } from '../../shared/models/nodeinfo/nodeinfo.model' |
8 | import { root } from '../helpers/core-utils' | 8 | import { root } from '@shared/core-utils' |
9 | import { CONFIG, isEmailEnabled } from '../initializers/config' | 9 | import { CONFIG, isEmailEnabled } from '../initializers/config' |
10 | import { | 10 | import { |
11 | CONSTRAINTS_FIELDS, | 11 | CONSTRAINTS_FIELDS, |
diff --git a/server/helpers/core-utils.ts b/server/helpers/core-utils.ts index 2cbf0f8fe..531ccfba9 100644 --- a/server/helpers/core-utils.ts +++ b/server/helpers/core-utils.ts | |||
@@ -6,9 +6,8 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | import { exec, ExecOptions } from 'child_process' | 8 | import { exec, ExecOptions } from 'child_process' |
9 | import { BinaryToTextEncoding, createHash, randomBytes } from 'crypto' | 9 | import { randomBytes } from 'crypto' |
10 | import { truncate } from 'lodash' | 10 | import { truncate } from 'lodash' |
11 | import { basename, extname, isAbsolute, join, resolve } from 'path' | ||
12 | import { createPrivateKey as createPrivateKey_1, getPublicKey as getPublicKey_1 } from 'pem' | 11 | import { createPrivateKey as createPrivateKey_1, getPublicKey as getPublicKey_1 } from 'pem' |
13 | import { pipeline } from 'stream' | 12 | import { pipeline } from 'stream' |
14 | import { URL } from 'url' | 13 | import { URL } from 'url' |
@@ -159,34 +158,6 @@ function getAppNumber () { | |||
159 | 158 | ||
160 | // --------------------------------------------------------------------------- | 159 | // --------------------------------------------------------------------------- |
161 | 160 | ||
162 | let rootPath: string | ||
163 | |||
164 | function root () { | ||
165 | if (rootPath) return rootPath | ||
166 | |||
167 | rootPath = __dirname | ||
168 | |||
169 | if (basename(rootPath) === 'helpers') rootPath = resolve(rootPath, '..') | ||
170 | if (basename(rootPath) === 'server') rootPath = resolve(rootPath, '..') | ||
171 | if (basename(rootPath) === 'dist') rootPath = resolve(rootPath, '..') | ||
172 | |||
173 | return rootPath | ||
174 | } | ||
175 | |||
176 | function buildPath (path: string) { | ||
177 | if (isAbsolute(path)) return path | ||
178 | |||
179 | return join(root(), path) | ||
180 | } | ||
181 | |||
182 | function getLowercaseExtension (filename: string) { | ||
183 | const ext = extname(filename) || '' | ||
184 | |||
185 | return ext.toLowerCase() | ||
186 | } | ||
187 | |||
188 | // --------------------------------------------------------------------------- | ||
189 | |||
190 | // Consistent with .length, lodash truncate function is not | 161 | // Consistent with .length, lodash truncate function is not |
191 | function peertubeTruncate (str: string, options: { length: number, separator?: RegExp, omission?: string }) { | 162 | function peertubeTruncate (str: string, options: { length: number, separator?: RegExp, omission?: string }) { |
192 | const truncatedStr = truncate(str, options) | 163 | const truncatedStr = truncate(str, options) |
@@ -221,16 +192,6 @@ function parseSemVersion (s: string) { | |||
221 | 192 | ||
222 | // --------------------------------------------------------------------------- | 193 | // --------------------------------------------------------------------------- |
223 | 194 | ||
224 | function sha256 (str: string | Buffer, encoding: BinaryToTextEncoding = 'hex') { | ||
225 | return createHash('sha256').update(str).digest(encoding) | ||
226 | } | ||
227 | |||
228 | function sha1 (str: string | Buffer, encoding: BinaryToTextEncoding = 'hex') { | ||
229 | return createHash('sha1').update(str).digest(encoding) | ||
230 | } | ||
231 | |||
232 | // --------------------------------------------------------------------------- | ||
233 | |||
234 | function execShell (command: string, options?: ExecOptions) { | 195 | function execShell (command: string, options?: ExecOptions) { |
235 | return new Promise<{ err?: Error, stdout: string, stderr: string }>((res, rej) => { | 196 | return new Promise<{ err?: Error, stdout: string, stderr: string }>((res, rej) => { |
236 | exec(command, options, (err, stdout, stderr) => { | 197 | exec(command, options, (err, stdout, stderr) => { |
@@ -298,9 +259,6 @@ export { | |||
298 | objectConverter, | 259 | objectConverter, |
299 | mapToJSON, | 260 | mapToJSON, |
300 | 261 | ||
301 | root, | ||
302 | buildPath, | ||
303 | getLowercaseExtension, | ||
304 | sanitizeUrl, | 262 | sanitizeUrl, |
305 | sanitizeHost, | 263 | sanitizeHost, |
306 | 264 | ||
@@ -309,9 +267,6 @@ export { | |||
309 | pageToStartAndCount, | 267 | pageToStartAndCount, |
310 | peertubeTruncate, | 268 | peertubeTruncate, |
311 | 269 | ||
312 | sha256, | ||
313 | sha1, | ||
314 | |||
315 | promisify0, | 270 | promisify0, |
316 | promisify1, | 271 | promisify1, |
317 | promisify2, | 272 | promisify2, |
diff --git a/server/helpers/custom-validators/misc.ts b/server/helpers/custom-validators/misc.ts index c19a3e5eb..eaabdbbea 100644 --- a/server/helpers/custom-validators/misc.ts +++ b/server/helpers/custom-validators/misc.ts | |||
@@ -2,7 +2,7 @@ import 'multer' | |||
2 | import { UploadFilesForCheck } from 'express' | 2 | import { UploadFilesForCheck } from 'express' |
3 | import { sep } from 'path' | 3 | import { sep } from 'path' |
4 | import validator from 'validator' | 4 | import validator from 'validator' |
5 | import { isShortUUID, shortToUUID } from '../uuid' | 5 | import { isShortUUID, shortToUUID } from '@shared/core-utils/uuid' |
6 | 6 | ||
7 | function exists (value: any) { | 7 | function exists (value: any) { |
8 | return value !== undefined && value !== null | 8 | return value !== undefined && value !== null |
diff --git a/server/helpers/express-utils.ts b/server/helpers/express-utils.ts index 7b81ed71b..780fd6345 100644 --- a/server/helpers/express-utils.ts +++ b/server/helpers/express-utils.ts | |||
@@ -1,9 +1,9 @@ | |||
1 | import express from 'express' | 1 | import express, { RequestHandler } from 'express' |
2 | import multer, { diskStorage } from 'multer' | 2 | import multer, { diskStorage } from 'multer' |
3 | import { HttpStatusCode } from '../../shared/models/http/http-error-codes' | 3 | import { HttpStatusCode } from '../../shared/models/http/http-error-codes' |
4 | import { CONFIG } from '../initializers/config' | 4 | import { CONFIG } from '../initializers/config' |
5 | import { REMOTE_SCHEME } from '../initializers/constants' | 5 | import { REMOTE_SCHEME } from '../initializers/constants' |
6 | import { getLowercaseExtension } from './core-utils' | 6 | import { getLowercaseExtension } from '@shared/core-utils' |
7 | import { isArray } from './custom-validators/misc' | 7 | import { isArray } from './custom-validators/misc' |
8 | import { logger } from './logger' | 8 | import { logger } from './logger' |
9 | import { deleteFileAndCatch, generateRandomString } from './utils' | 9 | import { deleteFileAndCatch, generateRandomString } from './utils' |
@@ -69,7 +69,7 @@ function createReqFiles ( | |||
69 | fieldNames: string[], | 69 | fieldNames: string[], |
70 | mimeTypes: { [id: string]: string | string[] }, | 70 | mimeTypes: { [id: string]: string | string[] }, |
71 | destinations: { [fieldName: string]: string } | 71 | destinations: { [fieldName: string]: string } |
72 | ) { | 72 | ): RequestHandler { |
73 | const storage = diskStorage({ | 73 | const storage = diskStorage({ |
74 | destination: (req, file, cb) => { | 74 | destination: (req, file, cb) => { |
75 | cb(null, destinations[file.fieldname]) | 75 | cb(null, destinations[file.fieldname]) |
diff --git a/server/helpers/ffprobe-utils.ts b/server/helpers/ffprobe-utils.ts index e15628e2a..595112bce 100644 --- a/server/helpers/ffprobe-utils.ts +++ b/server/helpers/ffprobe-utils.ts | |||
@@ -1,9 +1,22 @@ | |||
1 | import { ffprobe, FfprobeData } from 'fluent-ffmpeg' | 1 | import { FfprobeData } from 'fluent-ffmpeg' |
2 | import { getMaxBitrate } from '@shared/core-utils' | 2 | import { getMaxBitrate } from '@shared/core-utils' |
3 | import { VideoFileMetadata, VideoResolution, VideoTranscodingFPS } from '../../shared/models/videos' | 3 | import { VideoResolution, VideoTranscodingFPS } from '../../shared/models/videos' |
4 | import { CONFIG } from '../initializers/config' | 4 | import { CONFIG } from '../initializers/config' |
5 | import { VIDEO_TRANSCODING_FPS } from '../initializers/constants' | 5 | import { VIDEO_TRANSCODING_FPS } from '../initializers/constants' |
6 | import { logger } from './logger' | 6 | import { logger } from './logger' |
7 | import { | ||
8 | canDoQuickAudioTranscode, | ||
9 | ffprobePromise, | ||
10 | getDurationFromVideoFile, | ||
11 | getAudioStream, | ||
12 | getMaxAudioBitrate, | ||
13 | getMetadataFromFile, | ||
14 | getVideoFileBitrate, | ||
15 | getVideoFileFPS, | ||
16 | getVideoFileResolution, | ||
17 | getVideoStreamFromFile, | ||
18 | getVideoStreamSize | ||
19 | } from '@shared/extra-utils/ffprobe' | ||
7 | 20 | ||
8 | /** | 21 | /** |
9 | * | 22 | * |
@@ -11,79 +24,6 @@ import { logger } from './logger' | |||
11 | * | 24 | * |
12 | */ | 25 | */ |
13 | 26 | ||
14 | function ffprobePromise (path: string) { | ||
15 | return new Promise<FfprobeData>((res, rej) => { | ||
16 | ffprobe(path, (err, data) => { | ||
17 | if (err) return rej(err) | ||
18 | |||
19 | return res(data) | ||
20 | }) | ||
21 | }) | ||
22 | } | ||
23 | |||
24 | async function getAudioStream (videoPath: string, existingProbe?: FfprobeData) { | ||
25 | // without position, ffprobe considers the last input only | ||
26 | // we make it consider the first input only | ||
27 | // if you pass a file path to pos, then ffprobe acts on that file directly | ||
28 | const data = existingProbe || await ffprobePromise(videoPath) | ||
29 | |||
30 | if (Array.isArray(data.streams)) { | ||
31 | const audioStream = data.streams.find(stream => stream['codec_type'] === 'audio') | ||
32 | |||
33 | if (audioStream) { | ||
34 | return { | ||
35 | absolutePath: data.format.filename, | ||
36 | audioStream, | ||
37 | bitrate: parseInt(audioStream['bit_rate'] + '', 10) | ||
38 | } | ||
39 | } | ||
40 | } | ||
41 | |||
42 | return { absolutePath: data.format.filename } | ||
43 | } | ||
44 | |||
45 | function getMaxAudioBitrate (type: 'aac' | 'mp3' | string, bitrate: number) { | ||
46 | const maxKBitrate = 384 | ||
47 | const kToBits = (kbits: number) => kbits * 1000 | ||
48 | |||
49 | // If we did not manage to get the bitrate, use an average value | ||
50 | if (!bitrate) return 256 | ||
51 | |||
52 | if (type === 'aac') { | ||
53 | switch (true) { | ||
54 | case bitrate > kToBits(maxKBitrate): | ||
55 | return maxKBitrate | ||
56 | |||
57 | default: | ||
58 | return -1 // we interpret it as a signal to copy the audio stream as is | ||
59 | } | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | a 192kbit/sec mp3 doesn't hold as much information as a 192kbit/sec aac. | ||
64 | That's why, when using aac, we can go to lower kbit/sec. The equivalences | ||
65 | made here are not made to be accurate, especially with good mp3 encoders. | ||
66 | */ | ||
67 | switch (true) { | ||
68 | case bitrate <= kToBits(192): | ||
69 | return 128 | ||
70 | |||
71 | case bitrate <= kToBits(384): | ||
72 | return 256 | ||
73 | |||
74 | default: | ||
75 | return maxKBitrate | ||
76 | } | ||
77 | } | ||
78 | |||
79 | async function getVideoStreamSize (path: string, existingProbe?: FfprobeData): Promise<{ width: number, height: number }> { | ||
80 | const videoStream = await getVideoStreamFromFile(path, existingProbe) | ||
81 | |||
82 | return videoStream === null | ||
83 | ? { width: 0, height: 0 } | ||
84 | : { width: videoStream.width, height: videoStream.height } | ||
85 | } | ||
86 | |||
87 | async function getVideoStreamCodec (path: string) { | 27 | async function getVideoStreamCodec (path: string) { |
88 | const videoStream = await getVideoStreamFromFile(path) | 28 | const videoStream = await getVideoStreamFromFile(path) |
89 | 29 | ||
@@ -143,69 +83,6 @@ async function getAudioStreamCodec (path: string, existingProbe?: FfprobeData) { | |||
143 | return 'mp4a.40.2' // Fallback | 83 | return 'mp4a.40.2' // Fallback |
144 | } | 84 | } |
145 | 85 | ||
146 | async function getVideoFileResolution (path: string, existingProbe?: FfprobeData) { | ||
147 | const size = await getVideoStreamSize(path, existingProbe) | ||
148 | |||
149 | return { | ||
150 | width: size.width, | ||
151 | height: size.height, | ||
152 | ratio: Math.max(size.height, size.width) / Math.min(size.height, size.width), | ||
153 | resolution: Math.min(size.height, size.width), | ||
154 | isPortraitMode: size.height > size.width | ||
155 | } | ||
156 | } | ||
157 | |||
158 | async function getVideoFileFPS (path: string, existingProbe?: FfprobeData) { | ||
159 | const videoStream = await getVideoStreamFromFile(path, existingProbe) | ||
160 | if (videoStream === null) return 0 | ||
161 | |||
162 | for (const key of [ 'avg_frame_rate', 'r_frame_rate' ]) { | ||
163 | const valuesText: string = videoStream[key] | ||
164 | if (!valuesText) continue | ||
165 | |||
166 | const [ frames, seconds ] = valuesText.split('/') | ||
167 | if (!frames || !seconds) continue | ||
168 | |||
169 | const result = parseInt(frames, 10) / parseInt(seconds, 10) | ||
170 | if (result > 0) return Math.round(result) | ||
171 | } | ||
172 | |||
173 | return 0 | ||
174 | } | ||
175 | |||
176 | async function getMetadataFromFile (path: string, existingProbe?: FfprobeData) { | ||
177 | const metadata = existingProbe || await ffprobePromise(path) | ||
178 | |||
179 | return new VideoFileMetadata(metadata) | ||
180 | } | ||
181 | |||
182 | async function getVideoFileBitrate (path: string, existingProbe?: FfprobeData): Promise<number> { | ||
183 | const metadata = await getMetadataFromFile(path, existingProbe) | ||
184 | |||
185 | let bitrate = metadata.format.bit_rate as number | ||
186 | if (bitrate && !isNaN(bitrate)) return bitrate | ||
187 | |||
188 | const videoStream = await getVideoStreamFromFile(path, existingProbe) | ||
189 | if (!videoStream) return undefined | ||
190 | |||
191 | bitrate = videoStream?.bit_rate | ||
192 | if (bitrate && !isNaN(bitrate)) return bitrate | ||
193 | |||
194 | return undefined | ||
195 | } | ||
196 | |||
197 | async function getDurationFromVideoFile (path: string, existingProbe?: FfprobeData) { | ||
198 | const metadata = await getMetadataFromFile(path, existingProbe) | ||
199 | |||
200 | return Math.round(metadata.format.duration) | ||
201 | } | ||
202 | |||
203 | async function getVideoStreamFromFile (path: string, existingProbe?: FfprobeData) { | ||
204 | const metadata = await getMetadataFromFile(path, existingProbe) | ||
205 | |||
206 | return metadata.streams.find(s => s.codec_type === 'video') || null | ||
207 | } | ||
208 | |||
209 | function computeLowerResolutionsToTranscode (videoFileResolution: number, type: 'vod' | 'live') { | 86 | function computeLowerResolutionsToTranscode (videoFileResolution: number, type: 'vod' | 'live') { |
210 | const configResolutions = type === 'vod' | 87 | const configResolutions = type === 'vod' |
211 | ? CONFIG.TRANSCODING.RESOLUTIONS | 88 | ? CONFIG.TRANSCODING.RESOLUTIONS |
@@ -263,26 +140,6 @@ async function canDoQuickVideoTranscode (path: string, probe?: FfprobeData): Pro | |||
263 | return true | 140 | return true |
264 | } | 141 | } |
265 | 142 | ||
266 | async function canDoQuickAudioTranscode (path: string, probe?: FfprobeData): Promise<boolean> { | ||
267 | const parsedAudio = await getAudioStream(path, probe) | ||
268 | |||
269 | if (!parsedAudio.audioStream) return true | ||
270 | |||
271 | if (parsedAudio.audioStream['codec_name'] !== 'aac') return false | ||
272 | |||
273 | const audioBitrate = parsedAudio.bitrate | ||
274 | if (!audioBitrate) return false | ||
275 | |||
276 | const maxAudioBitrate = getMaxAudioBitrate('aac', audioBitrate) | ||
277 | if (maxAudioBitrate !== -1 && audioBitrate > maxAudioBitrate) return false | ||
278 | |||
279 | const channelLayout = parsedAudio.audioStream['channel_layout'] | ||
280 | // Causes playback issues with Chrome | ||
281 | if (!channelLayout || channelLayout === 'unknown') return false | ||
282 | |||
283 | return true | ||
284 | } | ||
285 | |||
286 | function getClosestFramerateStandard <K extends keyof Pick<VideoTranscodingFPS, 'HD_STANDARD' | 'STANDARD'>> (fps: number, type: K) { | 143 | function getClosestFramerateStandard <K extends keyof Pick<VideoTranscodingFPS, 'HD_STANDARD' | 'STANDARD'>> (fps: number, type: K) { |
287 | return VIDEO_TRANSCODING_FPS[type].slice(0) | 144 | return VIDEO_TRANSCODING_FPS[type].slice(0) |
288 | .sort((a, b) => fps % a - fps % b)[0] | 145 | .sort((a, b) => fps % a - fps % b)[0] |
diff --git a/server/helpers/image-utils.ts b/server/helpers/image-utils.ts index 4305584d5..ced288045 100644 --- a/server/helpers/image-utils.ts +++ b/server/helpers/image-utils.ts | |||
@@ -1,9 +1,9 @@ | |||
1 | import { copy, readFile, remove, rename } from 'fs-extra' | 1 | import { copy, readFile, remove, rename } from 'fs-extra' |
2 | import Jimp, { read } from 'jimp' | 2 | import Jimp, { read } from 'jimp' |
3 | import { getLowercaseExtension } from './core-utils' | 3 | import { getLowercaseExtension } from '@shared/core-utils' |
4 | import { convertWebPToJPG, processGIF } from './ffmpeg-utils' | 4 | import { convertWebPToJPG, processGIF } from './ffmpeg-utils' |
5 | import { logger } from './logger' | 5 | import { logger } from './logger' |
6 | import { buildUUID } from './uuid' | 6 | import { buildUUID } from '@shared/core-utils/uuid' |
7 | 7 | ||
8 | function generateImageFilename (extension = '.jpg') { | 8 | function generateImageFilename (extension = '.jpg') { |
9 | return buildUUID() + extension | 9 | return buildUUID() + extension |
diff --git a/server/helpers/peertube-crypto.ts b/server/helpers/peertube-crypto.ts index 44d90d9f1..31705e7fa 100644 --- a/server/helpers/peertube-crypto.ts +++ b/server/helpers/peertube-crypto.ts | |||
@@ -4,7 +4,8 @@ import { Request } from 'express' | |||
4 | import { cloneDeep } from 'lodash' | 4 | import { cloneDeep } from 'lodash' |
5 | import { BCRYPT_SALT_SIZE, HTTP_SIGNATURE, PRIVATE_RSA_KEY_SIZE } from '../initializers/constants' | 5 | import { BCRYPT_SALT_SIZE, HTTP_SIGNATURE, PRIVATE_RSA_KEY_SIZE } from '../initializers/constants' |
6 | import { MActor } from '../types/models' | 6 | import { MActor } from '../types/models' |
7 | import { createPrivateKey, getPublicKey, promisify1, promisify2, sha256 } from './core-utils' | 7 | import { sha256 } from '@shared/core-utils/crypto' |
8 | import { createPrivateKey, getPublicKey, promisify1, promisify2 } from './core-utils' | ||
8 | import { jsonld } from './custom-jsonld-signature' | 9 | import { jsonld } from './custom-jsonld-signature' |
9 | import { logger } from './logger' | 10 | import { logger } from './logger' |
10 | 11 | ||
diff --git a/server/helpers/utils.ts b/server/helpers/utils.ts index 6c95a43b6..882f808ab 100644 --- a/server/helpers/utils.ts +++ b/server/helpers/utils.ts | |||
@@ -3,7 +3,8 @@ import { Instance as ParseTorrent } from 'parse-torrent' | |||
3 | import { join } from 'path' | 3 | import { join } from 'path' |
4 | import { ResultList } from '../../shared' | 4 | import { ResultList } from '../../shared' |
5 | import { CONFIG } from '../initializers/config' | 5 | import { CONFIG } from '../initializers/config' |
6 | import { execPromise, execPromise2, randomBytesPromise, sha256 } from './core-utils' | 6 | import { sha256 } from '@shared/core-utils/crypto' |
7 | import { execPromise, execPromise2, randomBytesPromise } from './core-utils' | ||
7 | import { logger } from './logger' | 8 | import { logger } from './logger' |
8 | 9 | ||
9 | function deleteFileAndCatch (path: string) { | 10 | function deleteFileAndCatch (path: string) { |
diff --git a/server/helpers/webtorrent.ts b/server/helpers/webtorrent.ts index ecc703646..67cb3971d 100644 --- a/server/helpers/webtorrent.ts +++ b/server/helpers/webtorrent.ts | |||
@@ -14,7 +14,8 @@ import { MVideo } from '@server/types/models/video/video' | |||
14 | import { MVideoFile, MVideoFileRedundanciesOpt } from '@server/types/models/video/video-file' | 14 | import { MVideoFile, MVideoFileRedundanciesOpt } from '@server/types/models/video/video-file' |
15 | import { MStreamingPlaylistVideo } from '@server/types/models/video/video-streaming-playlist' | 15 | import { MStreamingPlaylistVideo } from '@server/types/models/video/video-streaming-playlist' |
16 | import { CONFIG } from '../initializers/config' | 16 | import { CONFIG } from '../initializers/config' |
17 | import { promisify2, sha1 } from './core-utils' | 17 | import { promisify2 } from './core-utils' |
18 | import { sha1 } from '@shared/core-utils/crypto' | ||
18 | import { logger } from './logger' | 19 | import { logger } from './logger' |
19 | import { generateVideoImportTmpPath } from './utils' | 20 | import { generateVideoImportTmpPath } from './utils' |
20 | import { extractVideo } from './video' | 21 | import { extractVideo } from './video' |
diff --git a/server/initializers/config.ts b/server/initializers/config.ts index 70179d25c..e3e8c426e 100644 --- a/server/initializers/config.ts +++ b/server/initializers/config.ts | |||
@@ -6,7 +6,8 @@ import { VideoRedundancyConfigFilter } from '@shared/models/redundancy/video-red | |||
6 | import { BroadcastMessageLevel } from '@shared/models/server' | 6 | import { BroadcastMessageLevel } from '@shared/models/server' |
7 | import { VideoPrivacy, VideosRedundancyStrategy } from '../../shared/models' | 7 | import { VideoPrivacy, VideosRedundancyStrategy } from '../../shared/models' |
8 | import { NSFWPolicyType } from '../../shared/models/videos/nsfw-policy.type' | 8 | import { NSFWPolicyType } from '../../shared/models/videos/nsfw-policy.type' |
9 | import { buildPath, parseBytes, parseDurationToMs, root } from '../helpers/core-utils' | 9 | import { buildPath, root } from '../../shared/core-utils' |
10 | import { parseBytes, parseDurationToMs } from '../helpers/core-utils' | ||
10 | 11 | ||
11 | // Use a variable to reload the configuration if we need | 12 | // Use a variable to reload the configuration if we need |
12 | let config: IConfig = require('config') | 13 | let config: IConfig = require('config') |
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 70b8e3d27..026c715c2 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -18,8 +18,9 @@ import { FollowState } from '../../shared/models/actors' | |||
18 | import { NSFWPolicyType } from '../../shared/models/videos/nsfw-policy.type' | 18 | import { NSFWPolicyType } from '../../shared/models/videos/nsfw-policy.type' |
19 | import { VideoPlaylistPrivacy } from '../../shared/models/videos/playlist/video-playlist-privacy.model' | 19 | import { VideoPlaylistPrivacy } from '../../shared/models/videos/playlist/video-playlist-privacy.model' |
20 | import { VideoPlaylistType } from '../../shared/models/videos/playlist/video-playlist-type.model' | 20 | import { VideoPlaylistType } from '../../shared/models/videos/playlist/video-playlist-type.model' |
21 | import { root } from '../../shared/core-utils' | ||
21 | // Do not use barrels, remain constants as independent as possible | 22 | // Do not use barrels, remain constants as independent as possible |
22 | import { isTestInstance, root, sanitizeHost, sanitizeUrl } from '../helpers/core-utils' | 23 | import { isTestInstance, sanitizeHost, sanitizeUrl } from '../helpers/core-utils' |
23 | import { CONFIG, registerConfigChangedHandler } from './config' | 24 | import { CONFIG, registerConfigChangedHandler } from './config' |
24 | 25 | ||
25 | // --------------------------------------------------------------------------- | 26 | // --------------------------------------------------------------------------- |
diff --git a/server/initializers/migrations/0080-video-channels.ts b/server/initializers/migrations/0080-video-channels.ts index 0e6952350..82971c9f5 100644 --- a/server/initializers/migrations/0080-video-channels.ts +++ b/server/initializers/migrations/0080-video-channels.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { buildUUID } from '@server/helpers/uuid' | 1 | import { buildUUID } from '@shared/core-utils/uuid' |
2 | import * as Sequelize from 'sequelize' | 2 | import * as Sequelize from 'sequelize' |
3 | 3 | ||
4 | async function up (utils: { | 4 | async function up (utils: { |
diff --git a/server/initializers/migrations/0345-video-playlists.ts b/server/initializers/migrations/0345-video-playlists.ts index 8dd631dff..5cc52e7ee 100644 --- a/server/initializers/migrations/0345-video-playlists.ts +++ b/server/initializers/migrations/0345-video-playlists.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import * as Sequelize from 'sequelize' | 1 | import * as Sequelize from 'sequelize' |
2 | import { buildUUID } from '@server/helpers/uuid' | 2 | import { buildUUID } from '@shared/core-utils/uuid' |
3 | import { VideoPlaylistPrivacy, VideoPlaylistType } from '../../../shared/models/videos' | 3 | import { VideoPlaylistPrivacy, VideoPlaylistType } from '../../../shared/models/videos' |
4 | import { WEBSERVER } from '../constants' | 4 | import { WEBSERVER } from '../constants' |
5 | 5 | ||
diff --git a/server/initializers/migrations/0560-user-feed-token.ts b/server/initializers/migrations/0560-user-feed-token.ts index 042301352..961777e35 100644 --- a/server/initializers/migrations/0560-user-feed-token.ts +++ b/server/initializers/migrations/0560-user-feed-token.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import * as Sequelize from 'sequelize' | 1 | import * as Sequelize from 'sequelize' |
2 | import { buildUUID } from '@server/helpers/uuid' | 2 | import { buildUUID } from '@shared/core-utils/uuid' |
3 | 3 | ||
4 | async function up (utils: { | 4 | async function up (utils: { |
5 | transaction: Sequelize.Transaction | 5 | transaction: Sequelize.Transaction |
diff --git a/server/lib/activitypub/actors/shared/object-to-model-attributes.ts b/server/lib/activitypub/actors/shared/object-to-model-attributes.ts index 1612b3ad0..1ad89ac56 100644 --- a/server/lib/activitypub/actors/shared/object-to-model-attributes.ts +++ b/server/lib/activitypub/actors/shared/object-to-model-attributes.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { getLowercaseExtension } from '@server/helpers/core-utils' | 1 | import { getLowercaseExtension } from '@shared/core-utils' |
2 | import { isActivityPubUrlValid } from '@server/helpers/custom-validators/activitypub/misc' | 2 | import { isActivityPubUrlValid } from '@server/helpers/custom-validators/activitypub/misc' |
3 | import { buildUUID } from '@server/helpers/uuid' | 3 | import { buildUUID } from '@shared/core-utils/uuid' |
4 | import { MIMETYPES } from '@server/initializers/constants' | 4 | import { MIMETYPES } from '@server/initializers/constants' |
5 | import { ActorModel } from '@server/models/actor/actor' | 5 | import { ActorModel } from '@server/models/actor/actor' |
6 | import { FilteredModelAttributes } from '@server/types' | 6 | import { FilteredModelAttributes } from '@server/types' |
diff --git a/server/lib/auth/oauth.ts b/server/lib/auth/oauth.ts index 497773536..47bc8c055 100644 --- a/server/lib/auth/oauth.ts +++ b/server/lib/auth/oauth.ts | |||
@@ -8,7 +8,8 @@ import { | |||
8 | UnauthorizedClientError, | 8 | UnauthorizedClientError, |
9 | UnsupportedGrantTypeError | 9 | UnsupportedGrantTypeError |
10 | } from 'oauth2-server' | 10 | } from 'oauth2-server' |
11 | import { randomBytesPromise, sha1 } from '@server/helpers/core-utils' | 11 | import { sha1 } from '@shared/core-utils/crypto' |
12 | import { randomBytesPromise } from '@server/helpers/core-utils' | ||
12 | import { MOAuthClient } from '@server/types/models' | 13 | import { MOAuthClient } from '@server/types/models' |
13 | import { OAUTH_LIFETIME } from '../../initializers/constants' | 14 | import { OAUTH_LIFETIME } from '../../initializers/constants' |
14 | import { BypassLogin, getClient, getRefreshToken, getUser, revokeToken, saveToken } from './oauth-model' | 15 | import { BypassLogin, getClient, getRefreshToken, getUser, revokeToken, saveToken } from './oauth-model' |
diff --git a/server/lib/client-html.ts b/server/lib/client-html.ts index adc3d712e..dee7ca8ed 100644 --- a/server/lib/client-html.ts +++ b/server/lib/client-html.ts | |||
@@ -8,7 +8,8 @@ import { HTMLServerConfig } from '@shared/models' | |||
8 | import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n' | 8 | import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n' |
9 | import { HttpStatusCode } from '../../shared/models/http/http-error-codes' | 9 | import { HttpStatusCode } from '../../shared/models/http/http-error-codes' |
10 | import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos' | 10 | import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos' |
11 | import { isTestInstance, sha256 } from '../helpers/core-utils' | 11 | import { isTestInstance } from '../helpers/core-utils' |
12 | import { sha256 } from '@shared/core-utils/crypto' | ||
12 | import { logger } from '../helpers/logger' | 13 | import { logger } from '../helpers/logger' |
13 | import { mdToPlainText } from '../helpers/markdown' | 14 | import { mdToPlainText } from '../helpers/markdown' |
14 | import { CONFIG } from '../initializers/config' | 15 | import { CONFIG } from '../initializers/config' |
diff --git a/server/lib/emailer.ts b/server/lib/emailer.ts index 60284ea28..ebad43650 100644 --- a/server/lib/emailer.ts +++ b/server/lib/emailer.ts | |||
@@ -4,7 +4,8 @@ import { createTransport, Transporter } from 'nodemailer' | |||
4 | import { join } from 'path' | 4 | import { join } from 'path' |
5 | import { EmailPayload } from '@shared/models' | 5 | import { EmailPayload } from '@shared/models' |
6 | import { SendEmailDefaultOptions } from '../../shared/models/server/emailer.model' | 6 | import { SendEmailDefaultOptions } from '../../shared/models/server/emailer.model' |
7 | import { isTestInstance, root } from '../helpers/core-utils' | 7 | import { isTestInstance } from '../helpers/core-utils' |
8 | import { root } from '@shared/core-utils' | ||
8 | import { bunyanLogger, logger } from '../helpers/logger' | 9 | import { bunyanLogger, logger } from '../helpers/logger' |
9 | import { CONFIG, isEmailEnabled } from '../initializers/config' | 10 | import { CONFIG, isEmailEnabled } from '../initializers/config' |
10 | import { WEBSERVER } from '../initializers/constants' | 11 | import { WEBSERVER } from '../initializers/constants' |
diff --git a/server/lib/hls.ts b/server/lib/hls.ts index f2fe893a9..220b7733b 100644 --- a/server/lib/hls.ts +++ b/server/lib/hls.ts | |||
@@ -2,7 +2,7 @@ import { close, ensureDir, move, open, outputJSON, read, readFile, remove, stat, | |||
2 | import { flatten, uniq } from 'lodash' | 2 | import { flatten, uniq } from 'lodash' |
3 | import { basename, dirname, join } from 'path' | 3 | import { basename, dirname, join } from 'path' |
4 | import { MStreamingPlaylistFilesVideo, MVideo, MVideoUUID } from '@server/types/models' | 4 | import { MStreamingPlaylistFilesVideo, MVideo, MVideoUUID } from '@server/types/models' |
5 | import { sha256 } from '../helpers/core-utils' | 5 | import { sha256 } from '@shared/core-utils/crypto' |
6 | import { getAudioStreamCodec, getVideoStreamCodec, getVideoStreamSize } from '../helpers/ffprobe-utils' | 6 | import { getAudioStreamCodec, getVideoStreamCodec, getVideoStreamSize } from '../helpers/ffprobe-utils' |
7 | import { logger } from '../helpers/logger' | 7 | import { logger } from '../helpers/logger' |
8 | import { doRequest, doRequestAndSaveToFile } from '../helpers/requests' | 8 | import { doRequest, doRequestAndSaveToFile } from '../helpers/requests' |
diff --git a/server/lib/job-queue/handlers/video-file-import.ts b/server/lib/job-queue/handlers/video-file-import.ts index a91c2ef80..0d9e80cb8 100644 --- a/server/lib/job-queue/handlers/video-file-import.ts +++ b/server/lib/job-queue/handlers/video-file-import.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { Job } from 'bull' | 1 | import { Job } from 'bull' |
2 | import { copy, stat } from 'fs-extra' | 2 | import { copy, stat } from 'fs-extra' |
3 | import { getLowercaseExtension } from '@server/helpers/core-utils' | 3 | import { getLowercaseExtension } from '@shared/core-utils' |
4 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' | 4 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' |
5 | import { CONFIG } from '@server/initializers/config' | 5 | import { CONFIG } from '@server/initializers/config' |
6 | import { federateVideoIfNeeded } from '@server/lib/activitypub/videos' | 6 | import { federateVideoIfNeeded } from '@server/lib/activitypub/videos' |
diff --git a/server/lib/job-queue/handlers/video-import.ts b/server/lib/job-queue/handlers/video-import.ts index 4ce1a6c30..e5730e746 100644 --- a/server/lib/job-queue/handlers/video-import.ts +++ b/server/lib/job-queue/handlers/video-import.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { Job } from 'bull' | 1 | import { Job } from 'bull' |
2 | import { move, remove, stat } from 'fs-extra' | 2 | import { move, remove, stat } from 'fs-extra' |
3 | import { getLowercaseExtension } from '@server/helpers/core-utils' | 3 | import { getLowercaseExtension } from '@shared/core-utils' |
4 | import { retryTransactionWrapper } from '@server/helpers/database-utils' | 4 | import { retryTransactionWrapper } from '@server/helpers/database-utils' |
5 | import { YoutubeDLWrapper } from '@server/helpers/youtube-dl' | 5 | import { YoutubeDLWrapper } from '@server/helpers/youtube-dl' |
6 | import { isPostImportVideoAccepted } from '@server/lib/moderation' | 6 | import { isPostImportVideoAccepted } from '@server/lib/moderation' |
diff --git a/server/lib/local-actor.ts b/server/lib/local-actor.ts index 821a92b91..572696f2a 100644 --- a/server/lib/local-actor.ts +++ b/server/lib/local-actor.ts | |||
@@ -2,8 +2,8 @@ import 'multer' | |||
2 | import { queue } from 'async' | 2 | import { queue } from 'async' |
3 | import LRUCache from 'lru-cache' | 3 | import LRUCache from 'lru-cache' |
4 | import { join } from 'path' | 4 | import { join } from 'path' |
5 | import { getLowercaseExtension } from '@server/helpers/core-utils' | 5 | import { getLowercaseExtension } from '@shared/core-utils' |
6 | import { buildUUID } from '@server/helpers/uuid' | 6 | import { buildUUID } from '@shared/core-utils/uuid' |
7 | import { ActorModel } from '@server/models/actor/actor' | 7 | import { ActorModel } from '@server/models/actor/actor' |
8 | import { ActivityPubActorType, ActorImageType } from '@shared/models' | 8 | import { ActivityPubActorType, ActorImageType } from '@shared/models' |
9 | import { retryTransactionWrapper } from '../helpers/database-utils' | 9 | import { retryTransactionWrapper } from '../helpers/database-utils' |
diff --git a/server/lib/paths.ts b/server/lib/paths.ts index 434e637c6..d8cf812e3 100644 --- a/server/lib/paths.ts +++ b/server/lib/paths.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { join } from 'path' | 1 | import { join } from 'path' |
2 | import { buildUUID } from '@server/helpers/uuid' | 2 | import { buildUUID } from '@shared/core-utils/uuid' |
3 | import { CONFIG } from '@server/initializers/config' | 3 | import { CONFIG } from '@server/initializers/config' |
4 | import { HLS_REDUNDANCY_DIRECTORY, HLS_STREAMING_PLAYLIST_DIRECTORY } from '@server/initializers/constants' | 4 | import { HLS_REDUNDANCY_DIRECTORY, HLS_STREAMING_PLAYLIST_DIRECTORY } from '@server/initializers/constants' |
5 | import { isStreamingPlaylist, MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoUUID } from '@server/types/models' | 5 | import { isStreamingPlaylist, MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoUUID } from '@server/types/models' |
diff --git a/server/lib/user.ts b/server/lib/user.ts index 936403692..230bf37d0 100644 --- a/server/lib/user.ts +++ b/server/lib/user.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { Transaction } from 'sequelize/types' | 1 | import { Transaction } from 'sequelize/types' |
2 | import { buildUUID } from '@server/helpers/uuid' | 2 | import { buildUUID } from '@shared/core-utils/uuid' |
3 | import { UserModel } from '@server/models/user/user' | 3 | import { UserModel } from '@server/models/user/user' |
4 | import { MActorDefault } from '@server/types/models/actor' | 4 | import { MActorDefault } from '@server/types/models/actor' |
5 | import { ActivityPubActorType } from '../../shared/models/activitypub' | 5 | import { ActivityPubActorType } from '../../shared/models/activitypub' |
diff --git a/server/lib/video-path-manager.ts b/server/lib/video-path-manager.ts index 27058005c..429b36df9 100644 --- a/server/lib/video-path-manager.ts +++ b/server/lib/video-path-manager.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { remove } from 'fs-extra' | 1 | import { remove } from 'fs-extra' |
2 | import { extname, join } from 'path' | 2 | import { extname, join } from 'path' |
3 | import { buildUUID } from '@server/helpers/uuid' | 3 | import { buildUUID } from '@shared/core-utils/uuid' |
4 | import { extractVideo } from '@server/helpers/video' | 4 | import { extractVideo } from '@server/helpers/video' |
5 | import { CONFIG } from '@server/initializers/config' | 5 | import { CONFIG } from '@server/initializers/config' |
6 | import { | 6 | import { |
diff --git a/server/models/actor/actor.ts b/server/models/actor/actor.ts index 8df49951d..cbd3f0e4a 100644 --- a/server/models/actor/actor.ts +++ b/server/models/actor/actor.ts | |||
@@ -16,9 +16,8 @@ import { | |||
16 | Table, | 16 | Table, |
17 | UpdatedAt | 17 | UpdatedAt |
18 | } from 'sequelize-typescript' | 18 | } from 'sequelize-typescript' |
19 | import { getLowercaseExtension } from '@server/helpers/core-utils' | ||
20 | import { ModelCache } from '@server/models/model-cache' | 19 | import { ModelCache } from '@server/models/model-cache' |
21 | import { AttributesOnly } from '@shared/core-utils' | 20 | import { getLowercaseExtension, AttributesOnly } from '@shared/core-utils' |
22 | import { ActivityIconObject, ActivityPubActorType } from '../../../shared/models/activitypub' | 21 | import { ActivityIconObject, ActivityPubActorType } from '../../../shared/models/activitypub' |
23 | import { ActorImage } from '../../../shared/models/actors/actor-image.model' | 22 | import { ActorImage } from '../../../shared/models/actors/actor-image.model' |
24 | import { activityPubContextify } from '../../helpers/activitypub' | 23 | import { activityPubContextify } from '../../helpers/activitypub' |
diff --git a/server/models/user/user-notification.ts b/server/models/user/user-notification.ts index 04c5513a9..55d65d6b2 100644 --- a/server/models/user/user-notification.ts +++ b/server/models/user/user-notification.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { FindOptions, ModelIndexesOptions, Op, WhereOptions } from 'sequelize' | 1 | import { FindOptions, ModelIndexesOptions, Op, WhereOptions } from 'sequelize' |
2 | import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { uuidToShort } from '@server/helpers/uuid' | 3 | import { uuidToShort } from '@shared/core-utils/uuid' |
4 | import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user' | 4 | import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user' |
5 | import { AttributesOnly } from '@shared/core-utils' | 5 | import { AttributesOnly } from '@shared/core-utils' |
6 | import { UserNotification, UserNotificationType } from '../../../shared' | 6 | import { UserNotification, UserNotificationType } from '../../../shared' |
diff --git a/server/models/video/formatter/video-format-utils.ts b/server/models/video/formatter/video-format-utils.ts index fd4da68ed..f6c750ccf 100644 --- a/server/models/video/formatter/video-format-utils.ts +++ b/server/models/video/formatter/video-format-utils.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { uuidToShort } from '@server/helpers/uuid' | 1 | import { uuidToShort } from '@shared/core-utils/uuid' |
2 | import { generateMagnetUri } from '@server/helpers/webtorrent' | 2 | import { generateMagnetUri } from '@server/helpers/webtorrent' |
3 | import { getLocalVideoFileMetadataUrl } from '@server/lib/video-urls' | 3 | import { getLocalVideoFileMetadataUrl } from '@server/lib/video-urls' |
4 | import { VideoViews } from '@server/lib/video-views' | 4 | import { VideoViews } from '@server/lib/video-views' |
diff --git a/server/models/video/video-caption.ts b/server/models/video/video-caption.ts index d24be56c3..590e72e52 100644 --- a/server/models/video/video-caption.ts +++ b/server/models/video/video-caption.ts | |||
@@ -15,7 +15,7 @@ import { | |||
15 | Table, | 15 | Table, |
16 | UpdatedAt | 16 | UpdatedAt |
17 | } from 'sequelize-typescript' | 17 | } from 'sequelize-typescript' |
18 | import { buildUUID } from '@server/helpers/uuid' | 18 | import { buildUUID } from '@shared/core-utils/uuid' |
19 | import { MVideo, MVideoCaption, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models' | 19 | import { MVideo, MVideoCaption, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models' |
20 | import { AttributesOnly } from '@shared/core-utils' | 20 | import { AttributesOnly } from '@shared/core-utils' |
21 | import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model' | 21 | import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model' |
diff --git a/server/models/video/video-playlist.ts b/server/models/video/video-playlist.ts index 630684a88..d0c73cbd1 100644 --- a/server/models/video/video-playlist.ts +++ b/server/models/video/video-playlist.ts | |||
@@ -17,7 +17,7 @@ import { | |||
17 | Table, | 17 | Table, |
18 | UpdatedAt | 18 | UpdatedAt |
19 | } from 'sequelize-typescript' | 19 | } from 'sequelize-typescript' |
20 | import { buildUUID, uuidToShort } from '@server/helpers/uuid' | 20 | import { buildUUID, uuidToShort } from '@shared/core-utils/uuid' |
21 | import { MAccountId, MChannelId } from '@server/types/models' | 21 | import { MAccountId, MChannelId } from '@server/types/models' |
22 | import { AttributesOnly, buildPlaylistEmbedPath, buildPlaylistWatchPath, pick } from '@shared/core-utils' | 22 | import { AttributesOnly, buildPlaylistEmbedPath, buildPlaylistWatchPath, pick } from '@shared/core-utils' |
23 | import { ActivityIconObject } from '../../../shared/models/activitypub/objects' | 23 | import { ActivityIconObject } from '../../../shared/models/activitypub/objects' |
diff --git a/server/models/video/video-streaming-playlist.ts b/server/models/video/video-streaming-playlist.ts index e36852cad..23b3fbcbe 100644 --- a/server/models/video/video-streaming-playlist.ts +++ b/server/models/video/video-streaming-playlist.ts | |||
@@ -21,7 +21,7 @@ import { MStreamingPlaylist, MVideo } from '@server/types/models' | |||
21 | import { AttributesOnly } from '@shared/core-utils' | 21 | import { AttributesOnly } from '@shared/core-utils' |
22 | import { VideoStorage } from '@shared/models' | 22 | import { VideoStorage } from '@shared/models' |
23 | import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type' | 23 | import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type' |
24 | import { sha1 } from '../../helpers/core-utils' | 24 | import { sha1 } from '@shared/core-utils/crypto' |
25 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 25 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
26 | import { isArrayOf } from '../../helpers/custom-validators/misc' | 26 | import { isArrayOf } from '../../helpers/custom-validators/misc' |
27 | import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos' | 27 | import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos' |
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 1050463d2..efd4d8462 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -25,7 +25,7 @@ import { | |||
25 | UpdatedAt | 25 | UpdatedAt |
26 | } from 'sequelize-typescript' | 26 | } from 'sequelize-typescript' |
27 | import { buildNSFWFilter } from '@server/helpers/express-utils' | 27 | import { buildNSFWFilter } from '@server/helpers/express-utils' |
28 | import { uuidToShort } from '@server/helpers/uuid' | 28 | import { uuidToShort } from '@shared/core-utils/uuid' |
29 | import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video' | 29 | import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video' |
30 | import { LiveManager } from '@server/lib/live/live-manager' | 30 | import { LiveManager } from '@server/lib/live/live-manager' |
31 | import { removeHLSObjectStorage, removeWebTorrentObjectStorage } from '@server/lib/object-storage' | 31 | import { removeHLSObjectStorage, removeWebTorrentObjectStorage } from '@server/lib/object-storage' |
diff --git a/server/tests/api/activitypub/security.ts b/server/tests/api/activitypub/security.ts index 94d946563..2700cff13 100644 --- a/server/tests/api/activitypub/security.ts +++ b/server/tests/api/activitypub/security.ts | |||
@@ -7,7 +7,7 @@ import { buildDigest } from '@server/helpers/peertube-crypto' | |||
7 | import { HTTP_SIGNATURE } from '@server/initializers/constants' | 7 | import { HTTP_SIGNATURE } from '@server/initializers/constants' |
8 | import { buildGlobalHeaders } from '@server/lib/job-queue/handlers/utils/activitypub-http-utils' | 8 | import { buildGlobalHeaders } from '@server/lib/job-queue/handlers/utils/activitypub-http-utils' |
9 | import { buildAbsoluteFixturePath, cleanupTests, createMultipleServers, killallServers, PeerTubeServer, wait } from '@shared/extra-utils' | 9 | import { buildAbsoluteFixturePath, cleanupTests, createMultipleServers, killallServers, PeerTubeServer, wait } from '@shared/extra-utils' |
10 | import { makeFollowRequest, makePOSTAPRequest } from '@shared/extra-utils/requests/activitypub' | 10 | import { makeFollowRequest, makePOSTAPRequest } from '@server/tests/shared' |
11 | import { HttpStatusCode } from '@shared/models' | 11 | import { HttpStatusCode } from '@shared/models' |
12 | 12 | ||
13 | const expect = chai.expect | 13 | const expect = chai.expect |
diff --git a/server/tests/api/notifications/moderation-notifications.ts b/server/tests/api/notifications/moderation-notifications.ts index 81ce8061b..6d8e5359b 100644 --- a/server/tests/api/notifications/moderation-notifications.ts +++ b/server/tests/api/notifications/moderation-notifications.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | 1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ |
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import { buildUUID } from '@server/helpers/uuid' | 4 | import { buildUUID } from '@shared/core-utils/uuid' |
5 | import { | 5 | import { |
6 | checkAbuseStateChange, | 6 | checkAbuseStateChange, |
7 | checkAutoInstanceFollowing, | 7 | checkAutoInstanceFollowing, |
diff --git a/server/tests/api/notifications/user-notifications.ts b/server/tests/api/notifications/user-notifications.ts index 9af20843e..6db0347cc 100644 --- a/server/tests/api/notifications/user-notifications.ts +++ b/server/tests/api/notifications/user-notifications.ts | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { buildUUID } from '@server/helpers/uuid' | 5 | import { buildUUID } from '@shared/core-utils/uuid' |
6 | import { | 6 | import { |
7 | CheckerBaseParams, | 7 | CheckerBaseParams, |
8 | checkMyVideoImportIsFinished, | 8 | checkMyVideoImportIsFinished, |
diff --git a/server/tests/api/server/follows.ts b/server/tests/api/server/follows.ts index 832ba561a..748f4cd35 100644 --- a/server/tests/api/server/follows.ts +++ b/server/tests/api/server/follows.ts | |||
@@ -4,7 +4,6 @@ import 'mocha' | |||
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { | 5 | import { |
6 | cleanupTests, | 6 | cleanupTests, |
7 | completeVideoCheck, | ||
8 | createMultipleServers, | 7 | createMultipleServers, |
9 | dateIsValid, | 8 | dateIsValid, |
10 | expectAccountFollows, | 9 | expectAccountFollows, |
@@ -15,6 +14,7 @@ import { | |||
15 | waitJobs | 14 | waitJobs |
16 | } from '@shared/extra-utils' | 15 | } from '@shared/extra-utils' |
17 | import { VideoCreateResult, VideoPrivacy } from '@shared/models' | 16 | import { VideoCreateResult, VideoPrivacy } from '@shared/models' |
17 | import { completeVideoCheck } from '@server/tests/shared/video' | ||
18 | 18 | ||
19 | const expect = chai.expect | 19 | const expect = chai.expect |
20 | 20 | ||
diff --git a/server/tests/api/server/handle-down.ts b/server/tests/api/server/handle-down.ts index fa1da8fe0..2d059c0ed 100644 --- a/server/tests/api/server/handle-down.ts +++ b/server/tests/api/server/handle-down.ts | |||
@@ -5,7 +5,6 @@ import * as chai from 'chai' | |||
5 | import { | 5 | import { |
6 | cleanupTests, | 6 | cleanupTests, |
7 | CommentsCommand, | 7 | CommentsCommand, |
8 | completeVideoCheck, | ||
9 | createMultipleServers, | 8 | createMultipleServers, |
10 | killallServers, | 9 | killallServers, |
11 | PeerTubeServer, | 10 | PeerTubeServer, |
@@ -14,6 +13,7 @@ import { | |||
14 | waitJobs | 13 | waitJobs |
15 | } from '@shared/extra-utils' | 14 | } from '@shared/extra-utils' |
16 | import { HttpStatusCode, JobState, VideoCreateResult, VideoPrivacy } from '@shared/models' | 15 | import { HttpStatusCode, JobState, VideoCreateResult, VideoPrivacy } from '@shared/models' |
16 | import { completeVideoCheck } from '@server/tests/shared/video' | ||
17 | 17 | ||
18 | const expect = chai.expect | 18 | const expect = chai.expect |
19 | 19 | ||
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts index c6c279064..9e7b39cfa 100644 --- a/server/tests/api/videos/multiple-servers.ts +++ b/server/tests/api/videos/multiple-servers.ts | |||
@@ -8,7 +8,6 @@ import { | |||
8 | checkTmpIsEmpty, | 8 | checkTmpIsEmpty, |
9 | checkVideoFilesWereRemoved, | 9 | checkVideoFilesWereRemoved, |
10 | cleanupTests, | 10 | cleanupTests, |
11 | completeVideoCheck, | ||
12 | createMultipleServers, | 11 | createMultipleServers, |
13 | dateIsValid, | 12 | dateIsValid, |
14 | doubleFollow, | 13 | doubleFollow, |
@@ -21,6 +20,7 @@ import { | |||
21 | webtorrentAdd | 20 | webtorrentAdd |
22 | } from '@shared/extra-utils' | 21 | } from '@shared/extra-utils' |
23 | import { HttpStatusCode, VideoCommentThreadTree, VideoPrivacy } from '@shared/models' | 22 | import { HttpStatusCode, VideoCommentThreadTree, VideoPrivacy } from '@shared/models' |
23 | import { completeVideoCheck } from '@server/tests/shared/video' | ||
24 | 24 | ||
25 | const expect = chai.expect | 25 | const expect = chai.expect |
26 | 26 | ||
diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts index a0e4a156c..100067f18 100644 --- a/server/tests/api/videos/single-server.ts +++ b/server/tests/api/videos/single-server.ts | |||
@@ -5,7 +5,6 @@ import * as chai from 'chai' | |||
5 | import { | 5 | import { |
6 | checkVideoFilesWereRemoved, | 6 | checkVideoFilesWereRemoved, |
7 | cleanupTests, | 7 | cleanupTests, |
8 | completeVideoCheck, | ||
9 | createSingleServer, | 8 | createSingleServer, |
10 | PeerTubeServer, | 9 | PeerTubeServer, |
11 | setAccessTokensToServers, | 10 | setAccessTokensToServers, |
@@ -13,6 +12,7 @@ import { | |||
13 | wait | 12 | wait |
14 | } from '@shared/extra-utils' | 13 | } from '@shared/extra-utils' |
15 | import { Video, VideoPrivacy } from '@shared/models' | 14 | import { Video, VideoPrivacy } from '@shared/models' |
15 | import { completeVideoCheck } from '@server/tests/shared/video' | ||
16 | 16 | ||
17 | const expect = chai.expect | 17 | const expect = chai.expect |
18 | 18 | ||
diff --git a/server/tests/cli/prune-storage.ts b/server/tests/cli/prune-storage.ts index 1c0282da9..4b4f75527 100644 --- a/server/tests/cli/prune-storage.ts +++ b/server/tests/cli/prune-storage.ts | |||
@@ -4,7 +4,7 @@ import 'mocha' | |||
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { createFile, readdir } from 'fs-extra' | 5 | import { createFile, readdir } from 'fs-extra' |
6 | import { join } from 'path' | 6 | import { join } from 'path' |
7 | import { buildUUID } from '@server/helpers/uuid' | 7 | import { buildUUID } from '@shared/core-utils/uuid' |
8 | import { | 8 | import { |
9 | cleanupTests, | 9 | cleanupTests, |
10 | CLICommand, | 10 | CLICommand, |
diff --git a/server/tests/shared/index.ts b/server/tests/shared/index.ts new file mode 100644 index 000000000..938817268 --- /dev/null +++ b/server/tests/shared/index.ts | |||
@@ -0,0 +1,2 @@ | |||
1 | export * from './requests' | ||
2 | export * from './video' | ||
diff --git a/shared/extra-utils/requests/activitypub.ts b/server/tests/shared/requests.ts index 4ae878384..9eb596029 100644 --- a/shared/extra-utils/requests/activitypub.ts +++ b/server/tests/shared/requests.ts | |||
@@ -1,9 +1,9 @@ | |||
1 | import { activityPubContextify } from '../../../server/helpers/activitypub' | 1 | import { doRequest } from '@server/helpers/requests' |
2 | import { doRequest } from '../../../server/helpers/requests' | 2 | import { activityPubContextify } from '@server/helpers/activitypub' |
3 | import { HTTP_SIGNATURE } from '../../../server/initializers/constants' | 3 | import { HTTP_SIGNATURE } from '@server/initializers/constants' |
4 | import { buildGlobalHeaders } from '../../../server/lib/job-queue/handlers/utils/activitypub-http-utils' | 4 | import { buildGlobalHeaders } from '@server/lib/job-queue/handlers/utils/activitypub-http-utils' |
5 | 5 | ||
6 | function makePOSTAPRequest (url: string, body: any, httpSignature: any, headers: any) { | 6 | export function makePOSTAPRequest (url: string, body: any, httpSignature: any, headers: any) { |
7 | const options = { | 7 | const options = { |
8 | method: 'POST' as 'POST', | 8 | method: 'POST' as 'POST', |
9 | json: body, | 9 | json: body, |
@@ -14,7 +14,7 @@ function makePOSTAPRequest (url: string, body: any, httpSignature: any, headers: | |||
14 | return doRequest(url, options) | 14 | return doRequest(url, options) |
15 | } | 15 | } |
16 | 16 | ||
17 | async function makeFollowRequest (to: { url: string }, by: { url: string, privateKey }) { | 17 | export async function makeFollowRequest (to: { url: string }, by: { url: string, privateKey }) { |
18 | const follow = { | 18 | const follow = { |
19 | type: 'Follow', | 19 | type: 'Follow', |
20 | id: by.url + '/' + new Date().getTime(), | 20 | id: by.url + '/' + new Date().getTime(), |
@@ -35,8 +35,3 @@ async function makeFollowRequest (to: { url: string }, by: { url: string, privat | |||
35 | 35 | ||
36 | return makePOSTAPRequest(to.url + '/inbox', body, httpSignature, headers) | 36 | return makePOSTAPRequest(to.url + '/inbox', body, httpSignature, headers) |
37 | } | 37 | } |
38 | |||
39 | export { | ||
40 | makePOSTAPRequest, | ||
41 | makeFollowRequest | ||
42 | } | ||
diff --git a/server/tests/shared/video.ts b/server/tests/shared/video.ts new file mode 100644 index 000000000..0e6a00f5c --- /dev/null +++ b/server/tests/shared/video.ts | |||
@@ -0,0 +1,148 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions */ | ||
2 | import { dateIsValid, makeRawRequest, PeerTubeServer, testImage, webtorrentAdd } from '@shared/extra-utils' | ||
3 | import { expect } from 'chai' | ||
4 | import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '@server/initializers/constants' | ||
5 | import { getLowercaseExtension, uuidRegex } from '@shared/core-utils' | ||
6 | |||
7 | export async function completeVideoCheck ( | ||
8 | server: PeerTubeServer, | ||
9 | video: any, | ||
10 | attributes: { | ||
11 | name: string | ||
12 | category: number | ||
13 | licence: number | ||
14 | language: string | ||
15 | nsfw: boolean | ||
16 | commentsEnabled: boolean | ||
17 | downloadEnabled: boolean | ||
18 | description: string | ||
19 | publishedAt?: string | ||
20 | support: string | ||
21 | originallyPublishedAt?: string | ||
22 | account: { | ||
23 | name: string | ||
24 | host: string | ||
25 | } | ||
26 | isLocal: boolean | ||
27 | tags: string[] | ||
28 | privacy: number | ||
29 | likes?: number | ||
30 | dislikes?: number | ||
31 | duration: number | ||
32 | channel: { | ||
33 | displayName: string | ||
34 | name: string | ||
35 | description: string | ||
36 | isLocal: boolean | ||
37 | } | ||
38 | fixture: string | ||
39 | files: { | ||
40 | resolution: number | ||
41 | size: number | ||
42 | }[] | ||
43 | thumbnailfile?: string | ||
44 | previewfile?: string | ||
45 | } | ||
46 | ) { | ||
47 | if (!attributes.likes) attributes.likes = 0 | ||
48 | if (!attributes.dislikes) attributes.dislikes = 0 | ||
49 | |||
50 | const host = new URL(server.url).host | ||
51 | const originHost = attributes.account.host | ||
52 | |||
53 | expect(video.name).to.equal(attributes.name) | ||
54 | expect(video.category.id).to.equal(attributes.category) | ||
55 | expect(video.category.label).to.equal(attributes.category !== null ? VIDEO_CATEGORIES[attributes.category] : 'Misc') | ||
56 | expect(video.licence.id).to.equal(attributes.licence) | ||
57 | expect(video.licence.label).to.equal(attributes.licence !== null ? VIDEO_LICENCES[attributes.licence] : 'Unknown') | ||
58 | expect(video.language.id).to.equal(attributes.language) | ||
59 | expect(video.language.label).to.equal(attributes.language !== null ? VIDEO_LANGUAGES[attributes.language] : 'Unknown') | ||
60 | expect(video.privacy.id).to.deep.equal(attributes.privacy) | ||
61 | expect(video.privacy.label).to.deep.equal(VIDEO_PRIVACIES[attributes.privacy]) | ||
62 | expect(video.nsfw).to.equal(attributes.nsfw) | ||
63 | expect(video.description).to.equal(attributes.description) | ||
64 | expect(video.account.id).to.be.a('number') | ||
65 | expect(video.account.host).to.equal(attributes.account.host) | ||
66 | expect(video.account.name).to.equal(attributes.account.name) | ||
67 | expect(video.channel.displayName).to.equal(attributes.channel.displayName) | ||
68 | expect(video.channel.name).to.equal(attributes.channel.name) | ||
69 | expect(video.likes).to.equal(attributes.likes) | ||
70 | expect(video.dislikes).to.equal(attributes.dislikes) | ||
71 | expect(video.isLocal).to.equal(attributes.isLocal) | ||
72 | expect(video.duration).to.equal(attributes.duration) | ||
73 | expect(video.url).to.contain(originHost) | ||
74 | expect(dateIsValid(video.createdAt)).to.be.true | ||
75 | expect(dateIsValid(video.publishedAt)).to.be.true | ||
76 | expect(dateIsValid(video.updatedAt)).to.be.true | ||
77 | |||
78 | if (attributes.publishedAt) { | ||
79 | expect(video.publishedAt).to.equal(attributes.publishedAt) | ||
80 | } | ||
81 | |||
82 | if (attributes.originallyPublishedAt) { | ||
83 | expect(video.originallyPublishedAt).to.equal(attributes.originallyPublishedAt) | ||
84 | } else { | ||
85 | expect(video.originallyPublishedAt).to.be.null | ||
86 | } | ||
87 | |||
88 | const videoDetails = await server.videos.get({ id: video.uuid }) | ||
89 | |||
90 | expect(videoDetails.files).to.have.lengthOf(attributes.files.length) | ||
91 | expect(videoDetails.tags).to.deep.equal(attributes.tags) | ||
92 | expect(videoDetails.account.name).to.equal(attributes.account.name) | ||
93 | expect(videoDetails.account.host).to.equal(attributes.account.host) | ||
94 | expect(video.channel.displayName).to.equal(attributes.channel.displayName) | ||
95 | expect(video.channel.name).to.equal(attributes.channel.name) | ||
96 | expect(videoDetails.channel.host).to.equal(attributes.account.host) | ||
97 | expect(videoDetails.channel.isLocal).to.equal(attributes.channel.isLocal) | ||
98 | expect(dateIsValid(videoDetails.channel.createdAt.toString())).to.be.true | ||
99 | expect(dateIsValid(videoDetails.channel.updatedAt.toString())).to.be.true | ||
100 | expect(videoDetails.commentsEnabled).to.equal(attributes.commentsEnabled) | ||
101 | expect(videoDetails.downloadEnabled).to.equal(attributes.downloadEnabled) | ||
102 | |||
103 | for (const attributeFile of attributes.files) { | ||
104 | const file = videoDetails.files.find(f => f.resolution.id === attributeFile.resolution) | ||
105 | expect(file).not.to.be.undefined | ||
106 | |||
107 | let extension = getLowercaseExtension(attributes.fixture) | ||
108 | // Transcoding enabled: extension will always be .mp4 | ||
109 | if (attributes.files.length > 1) extension = '.mp4' | ||
110 | |||
111 | expect(file.magnetUri).to.have.lengthOf.above(2) | ||
112 | |||
113 | expect(file.torrentDownloadUrl).to.match(new RegExp(`http://${host}/download/torrents/${uuidRegex}-${file.resolution.id}.torrent`)) | ||
114 | expect(file.torrentUrl).to.match(new RegExp(`http://${host}/lazy-static/torrents/${uuidRegex}-${file.resolution.id}.torrent`)) | ||
115 | |||
116 | expect(file.fileUrl).to.match(new RegExp(`http://${originHost}/static/webseed/${uuidRegex}-${file.resolution.id}${extension}`)) | ||
117 | expect(file.fileDownloadUrl).to.match(new RegExp(`http://${originHost}/download/videos/${uuidRegex}-${file.resolution.id}${extension}`)) | ||
118 | |||
119 | await Promise.all([ | ||
120 | makeRawRequest(file.torrentUrl, 200), | ||
121 | makeRawRequest(file.torrentDownloadUrl, 200), | ||
122 | makeRawRequest(file.metadataUrl, 200) | ||
123 | ]) | ||
124 | |||
125 | expect(file.resolution.id).to.equal(attributeFile.resolution) | ||
126 | expect(file.resolution.label).to.equal(attributeFile.resolution + 'p') | ||
127 | |||
128 | const minSize = attributeFile.size - ((10 * attributeFile.size) / 100) | ||
129 | const maxSize = attributeFile.size + ((10 * attributeFile.size) / 100) | ||
130 | expect( | ||
131 | file.size, | ||
132 | 'File size for resolution ' + file.resolution.label + ' outside confidence interval (' + minSize + '> size <' + maxSize + ')' | ||
133 | ).to.be.above(minSize).and.below(maxSize) | ||
134 | |||
135 | const torrent = await webtorrentAdd(file.magnetUri, true) | ||
136 | expect(torrent.files).to.be.an('array') | ||
137 | expect(torrent.files.length).to.equal(1) | ||
138 | expect(torrent.files[0].path).to.exist.and.to.not.equal('') | ||
139 | } | ||
140 | |||
141 | expect(videoDetails.thumbnailPath).to.exist | ||
142 | await testImage(server.url, attributes.thumbnailfile || attributes.fixture, videoDetails.thumbnailPath) | ||
143 | |||
144 | if (attributes.previewfile) { | ||
145 | expect(videoDetails.previewPath).to.exist | ||
146 | await testImage(server.url, attributes.previewfile, videoDetails.previewPath) | ||
147 | } | ||
148 | } | ||
diff --git a/server/tools/cli.ts b/server/tools/cli.ts index 52e6ea593..7c763734f 100644 --- a/server/tools/cli.ts +++ b/server/tools/cli.ts | |||
@@ -5,7 +5,9 @@ import { createLogger, format, transports } from 'winston' | |||
5 | import { PeerTubeServer } from '@shared/extra-utils' | 5 | import { PeerTubeServer } from '@shared/extra-utils' |
6 | import { UserRole } from '@shared/models' | 6 | import { UserRole } from '@shared/models' |
7 | import { VideoPrivacy } from '../../shared/models/videos' | 7 | import { VideoPrivacy } from '../../shared/models/videos' |
8 | import { getAppNumber, isTestInstance, root } from '../helpers/core-utils' | 8 | import { getAppNumber, isTestInstance } from '../helpers/core-utils' |
9 | import { root } from '@shared/core-utils' | ||
10 | import { loadLanguages } from '@server/initializers/constants' | ||
9 | 11 | ||
10 | let configName = 'PeerTube/CLI' | 12 | let configName = 'PeerTube/CLI' |
11 | if (isTestInstance()) configName += `-${getAppNumber()}` | 13 | if (isTestInstance()) configName += `-${getAppNumber()}` |
@@ -180,6 +182,7 @@ function getServerCredentials (program: Command) { | |||
180 | } | 182 | } |
181 | 183 | ||
182 | function buildServer (url: string) { | 184 | function buildServer (url: string) { |
185 | loadLanguages() | ||
183 | return new PeerTubeServer({ url }) | 186 | return new PeerTubeServer({ url }) |
184 | } | 187 | } |
185 | 188 | ||
diff --git a/server/tools/peertube-import-videos.ts b/server/tools/peertube-import-videos.ts index a758beef9..223bf7f1b 100644 --- a/server/tools/peertube-import-videos.ts +++ b/server/tools/peertube-import-videos.ts | |||
@@ -5,7 +5,7 @@ import { program } from 'commander' | |||
5 | import { accessSync, constants } from 'fs' | 5 | import { accessSync, constants } from 'fs' |
6 | import { remove } from 'fs-extra' | 6 | import { remove } from 'fs-extra' |
7 | import { join } from 'path' | 7 | import { join } from 'path' |
8 | import { sha256 } from '../helpers/core-utils' | 8 | import { sha256 } from '@shared/core-utils/crypto' |
9 | import { doRequestAndSaveToFile } from '../helpers/requests' | 9 | import { doRequestAndSaveToFile } from '../helpers/requests' |
10 | import { | 10 | import { |
11 | assignToken, | 11 | assignToken, |
diff --git a/server/tools/tsconfig.json b/server/tools/tsconfig.json index 156a8ed22..575133ec8 100644 --- a/server/tools/tsconfig.json +++ b/server/tools/tsconfig.json | |||
@@ -1,5 +1,11 @@ | |||
1 | { | 1 | { |
2 | "extends": "../../tsconfig.json", | 2 | "extends": "../../tsconfig.json", |
3 | "compilerOptions": { | ||
4 | "outDir": "../../dist/server/tools" | ||
5 | }, | ||
3 | "include": [ ".", "../typings" ], | 6 | "include": [ ".", "../typings" ], |
7 | "references": [ | ||
8 | { "path": "../" }, | ||
9 | ], | ||
4 | "exclude": [ ] // Overwrite exclude property | 10 | "exclude": [ ] // Overwrite exclude property |
5 | } | 11 | } |
diff --git a/server/tsconfig.json b/server/tsconfig.json new file mode 100644 index 000000000..4be7ae2f4 --- /dev/null +++ b/server/tsconfig.json | |||
@@ -0,0 +1,12 @@ | |||
1 | { | ||
2 | "extends": "../tsconfig.base.json", | ||
3 | "compilerOptions": { | ||
4 | "outDir": "../dist/server" | ||
5 | }, | ||
6 | "references": [ | ||
7 | { "path": "../shared" } | ||
8 | ], | ||
9 | "exclude": [ | ||
10 | "tools/" | ||
11 | ] | ||
12 | } | ||
diff --git a/shared/core-utils/crypto.ts b/shared/core-utils/crypto.ts new file mode 100644 index 000000000..d6d1150d0 --- /dev/null +++ b/shared/core-utils/crypto.ts | |||
@@ -0,0 +1,14 @@ | |||
1 | import { BinaryToTextEncoding, createHash } from 'crypto' | ||
2 | |||
3 | function sha256 (str: string | Buffer, encoding: BinaryToTextEncoding = 'hex') { | ||
4 | return createHash('sha256').update(str).digest(encoding) | ||
5 | } | ||
6 | |||
7 | function sha1 (str: string | Buffer, encoding: BinaryToTextEncoding = 'hex') { | ||
8 | return createHash('sha1').update(str).digest(encoding) | ||
9 | } | ||
10 | |||
11 | export { | ||
12 | sha256, | ||
13 | sha1 | ||
14 | } | ||
diff --git a/shared/core-utils/index.ts b/shared/core-utils/index.ts index e0a6a8087..ee5cd4412 100644 --- a/shared/core-utils/index.ts +++ b/shared/core-utils/index.ts | |||
@@ -1,8 +1,10 @@ | |||
1 | export * from './abuse' | 1 | export * from './abuse' |
2 | export * from './common' | 2 | export * from './common' |
3 | export * from './i18n' | 3 | export * from './i18n' |
4 | export * from './path' | ||
4 | export * from './plugins' | 5 | export * from './plugins' |
5 | export * from './renderer' | 6 | export * from './renderer' |
6 | export * from './users' | 7 | export * from './users' |
7 | export * from './utils' | 8 | export * from './utils' |
8 | export * from './videos' | 9 | export * from './videos' |
10 | export * from './uuid' | ||
diff --git a/shared/core-utils/path.ts b/shared/core-utils/path.ts new file mode 100644 index 000000000..b1a45d69b --- /dev/null +++ b/shared/core-utils/path.ts | |||
@@ -0,0 +1,34 @@ | |||
1 | import { basename, extname, isAbsolute, join, resolve } from 'path' | ||
2 | |||
3 | let rootPath: string | ||
4 | |||
5 | function root () { | ||
6 | if (rootPath) return rootPath | ||
7 | |||
8 | rootPath = __dirname | ||
9 | |||
10 | if (basename(rootPath) === 'core-utils') rootPath = resolve(rootPath, '..') | ||
11 | if (basename(rootPath) === 'shared') rootPath = resolve(rootPath, '..') | ||
12 | if (basename(rootPath) === 'server') rootPath = resolve(rootPath, '..') | ||
13 | if (basename(rootPath) === 'dist') rootPath = resolve(rootPath, '..') | ||
14 | |||
15 | return rootPath | ||
16 | } | ||
17 | |||
18 | function buildPath (path: string) { | ||
19 | if (isAbsolute(path)) return path | ||
20 | |||
21 | return join(root(), path) | ||
22 | } | ||
23 | |||
24 | function getLowercaseExtension (filename: string) { | ||
25 | const ext = extname(filename) || '' | ||
26 | |||
27 | return ext.toLowerCase() | ||
28 | } | ||
29 | |||
30 | export { | ||
31 | root, | ||
32 | buildPath, | ||
33 | getLowercaseExtension | ||
34 | } | ||
diff --git a/server/helpers/uuid.ts b/shared/core-utils/uuid.ts index f3c80e046..f3c80e046 100644 --- a/server/helpers/uuid.ts +++ b/shared/core-utils/uuid.ts | |||
diff --git a/shared/extra-utils/ffprobe.ts b/shared/extra-utils/ffprobe.ts new file mode 100644 index 000000000..9257bbd5f --- /dev/null +++ b/shared/extra-utils/ffprobe.ts | |||
@@ -0,0 +1,180 @@ | |||
1 | import { ffprobe, FfprobeData } from 'fluent-ffmpeg' | ||
2 | import { VideoFileMetadata } from '@shared/models/videos' | ||
3 | |||
4 | /** | ||
5 | * | ||
6 | * Helpers to run ffprobe and extract data from the JSON output | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | function ffprobePromise (path: string) { | ||
11 | return new Promise<FfprobeData>((res, rej) => { | ||
12 | ffprobe(path, (err, data) => { | ||
13 | if (err) return rej(err) | ||
14 | |||
15 | return res(data) | ||
16 | }) | ||
17 | }) | ||
18 | } | ||
19 | |||
20 | async function getAudioStream (videoPath: string, existingProbe?: FfprobeData) { | ||
21 | // without position, ffprobe considers the last input only | ||
22 | // we make it consider the first input only | ||
23 | // if you pass a file path to pos, then ffprobe acts on that file directly | ||
24 | const data = existingProbe || await ffprobePromise(videoPath) | ||
25 | |||
26 | if (Array.isArray(data.streams)) { | ||
27 | const audioStream = data.streams.find(stream => stream['codec_type'] === 'audio') | ||
28 | |||
29 | if (audioStream) { | ||
30 | return { | ||
31 | absolutePath: data.format.filename, | ||
32 | audioStream, | ||
33 | bitrate: parseInt(audioStream['bit_rate'] + '', 10) | ||
34 | } | ||
35 | } | ||
36 | } | ||
37 | |||
38 | return { absolutePath: data.format.filename } | ||
39 | } | ||
40 | |||
41 | function getMaxAudioBitrate (type: 'aac' | 'mp3' | string, bitrate: number) { | ||
42 | const maxKBitrate = 384 | ||
43 | const kToBits = (kbits: number) => kbits * 1000 | ||
44 | |||
45 | // If we did not manage to get the bitrate, use an average value | ||
46 | if (!bitrate) return 256 | ||
47 | |||
48 | if (type === 'aac') { | ||
49 | switch (true) { | ||
50 | case bitrate > kToBits(maxKBitrate): | ||
51 | return maxKBitrate | ||
52 | |||
53 | default: | ||
54 | return -1 // we interpret it as a signal to copy the audio stream as is | ||
55 | } | ||
56 | } | ||
57 | |||
58 | /* | ||
59 | a 192kbit/sec mp3 doesn't hold as much information as a 192kbit/sec aac. | ||
60 | That's why, when using aac, we can go to lower kbit/sec. The equivalences | ||
61 | made here are not made to be accurate, especially with good mp3 encoders. | ||
62 | */ | ||
63 | switch (true) { | ||
64 | case bitrate <= kToBits(192): | ||
65 | return 128 | ||
66 | |||
67 | case bitrate <= kToBits(384): | ||
68 | return 256 | ||
69 | |||
70 | default: | ||
71 | return maxKBitrate | ||
72 | } | ||
73 | } | ||
74 | |||
75 | async function getVideoStreamSize (path: string, existingProbe?: FfprobeData): Promise<{ width: number, height: number }> { | ||
76 | const videoStream = await getVideoStreamFromFile(path, existingProbe) | ||
77 | |||
78 | return videoStream === null | ||
79 | ? { width: 0, height: 0 } | ||
80 | : { width: videoStream.width, height: videoStream.height } | ||
81 | } | ||
82 | |||
83 | async function getVideoFileResolution (path: string, existingProbe?: FfprobeData) { | ||
84 | const size = await getVideoStreamSize(path, existingProbe) | ||
85 | |||
86 | return { | ||
87 | width: size.width, | ||
88 | height: size.height, | ||
89 | ratio: Math.max(size.height, size.width) / Math.min(size.height, size.width), | ||
90 | resolution: Math.min(size.height, size.width), | ||
91 | isPortraitMode: size.height > size.width | ||
92 | } | ||
93 | } | ||
94 | |||
95 | async function getVideoFileFPS (path: string, existingProbe?: FfprobeData) { | ||
96 | const videoStream = await getVideoStreamFromFile(path, existingProbe) | ||
97 | if (videoStream === null) return 0 | ||
98 | |||
99 | for (const key of [ 'avg_frame_rate', 'r_frame_rate' ]) { | ||
100 | const valuesText: string = videoStream[key] | ||
101 | if (!valuesText) continue | ||
102 | |||
103 | const [ frames, seconds ] = valuesText.split('/') | ||
104 | if (!frames || !seconds) continue | ||
105 | |||
106 | const result = parseInt(frames, 10) / parseInt(seconds, 10) | ||
107 | if (result > 0) return Math.round(result) | ||
108 | } | ||
109 | |||
110 | return 0 | ||
111 | } | ||
112 | |||
113 | async function getMetadataFromFile (path: string, existingProbe?: FfprobeData) { | ||
114 | const metadata = existingProbe || await ffprobePromise(path) | ||
115 | |||
116 | return new VideoFileMetadata(metadata) | ||
117 | } | ||
118 | |||
119 | async function getVideoFileBitrate (path: string, existingProbe?: FfprobeData): Promise<number> { | ||
120 | const metadata = await getMetadataFromFile(path, existingProbe) | ||
121 | |||
122 | let bitrate = metadata.format.bit_rate as number | ||
123 | if (bitrate && !isNaN(bitrate)) return bitrate | ||
124 | |||
125 | const videoStream = await getVideoStreamFromFile(path, existingProbe) | ||
126 | if (!videoStream) return undefined | ||
127 | |||
128 | bitrate = videoStream?.bit_rate | ||
129 | if (bitrate && !isNaN(bitrate)) return bitrate | ||
130 | |||
131 | return undefined | ||
132 | } | ||
133 | |||
134 | async function getDurationFromVideoFile (path: string, existingProbe?: FfprobeData) { | ||
135 | const metadata = await getMetadataFromFile(path, existingProbe) | ||
136 | |||
137 | return Math.round(metadata.format.duration) | ||
138 | } | ||
139 | |||
140 | async function getVideoStreamFromFile (path: string, existingProbe?: FfprobeData) { | ||
141 | const metadata = await getMetadataFromFile(path, existingProbe) | ||
142 | |||
143 | return metadata.streams.find(s => s.codec_type === 'video') || null | ||
144 | } | ||
145 | |||
146 | async function canDoQuickAudioTranscode (path: string, probe?: FfprobeData): Promise<boolean> { | ||
147 | const parsedAudio = await getAudioStream(path, probe) | ||
148 | |||
149 | if (!parsedAudio.audioStream) return true | ||
150 | |||
151 | if (parsedAudio.audioStream['codec_name'] !== 'aac') return false | ||
152 | |||
153 | const audioBitrate = parsedAudio.bitrate | ||
154 | if (!audioBitrate) return false | ||
155 | |||
156 | const maxAudioBitrate = getMaxAudioBitrate('aac', audioBitrate) | ||
157 | if (maxAudioBitrate !== -1 && audioBitrate > maxAudioBitrate) return false | ||
158 | |||
159 | const channelLayout = parsedAudio.audioStream['channel_layout'] | ||
160 | // Causes playback issues with Chrome | ||
161 | if (!channelLayout || channelLayout === 'unknown') return false | ||
162 | |||
163 | return true | ||
164 | } | ||
165 | |||
166 | // --------------------------------------------------------------------------- | ||
167 | |||
168 | export { | ||
169 | getVideoStreamSize, | ||
170 | getVideoFileResolution, | ||
171 | getMetadataFromFile, | ||
172 | getMaxAudioBitrate, | ||
173 | getVideoStreamFromFile, | ||
174 | getDurationFromVideoFile, | ||
175 | getAudioStream, | ||
176 | getVideoFileFPS, | ||
177 | ffprobePromise, | ||
178 | getVideoFileBitrate, | ||
179 | canDoQuickAudioTranscode | ||
180 | } | ||
diff --git a/shared/extra-utils/miscs/checks.ts b/shared/extra-utils/miscs/checks.ts index b1be214b1..589928997 100644 --- a/shared/extra-utils/miscs/checks.ts +++ b/shared/extra-utils/miscs/checks.ts | |||
@@ -3,7 +3,7 @@ | |||
3 | import { expect } from 'chai' | 3 | import { expect } from 'chai' |
4 | import { pathExists, readFile } from 'fs-extra' | 4 | import { pathExists, readFile } from 'fs-extra' |
5 | import { join } from 'path' | 5 | import { join } from 'path' |
6 | import { root } from '@server/helpers/core-utils' | 6 | import { root } from '@shared/core-utils' |
7 | import { HttpStatusCode } from '@shared/models' | 7 | import { HttpStatusCode } from '@shared/models' |
8 | import { makeGetRequest } from '../requests' | 8 | import { makeGetRequest } from '../requests' |
9 | import { PeerTubeServer } from '../server' | 9 | import { PeerTubeServer } from '../server' |
diff --git a/shared/extra-utils/miscs/generate.ts b/shared/extra-utils/miscs/generate.ts index 3b29c0ad4..93673a063 100644 --- a/shared/extra-utils/miscs/generate.ts +++ b/shared/extra-utils/miscs/generate.ts | |||
@@ -2,7 +2,7 @@ import { expect } from 'chai' | |||
2 | import ffmpeg from 'fluent-ffmpeg' | 2 | import ffmpeg from 'fluent-ffmpeg' |
3 | import { ensureDir, pathExists } from 'fs-extra' | 3 | import { ensureDir, pathExists } from 'fs-extra' |
4 | import { dirname } from 'path' | 4 | import { dirname } from 'path' |
5 | import { getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '@server/helpers/ffprobe-utils' | 5 | import { getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '@shared/extra-utils/ffprobe' |
6 | import { getMaxBitrate } from '@shared/core-utils' | 6 | import { getMaxBitrate } from '@shared/core-utils' |
7 | import { buildAbsoluteFixturePath } from './tests' | 7 | import { buildAbsoluteFixturePath } from './tests' |
8 | 8 | ||
diff --git a/shared/extra-utils/server/directories.ts b/shared/extra-utils/server/directories.ts index b6465cbf4..e6f72d6fc 100644 --- a/shared/extra-utils/server/directories.ts +++ b/shared/extra-utils/server/directories.ts | |||
@@ -3,7 +3,7 @@ | |||
3 | import { expect } from 'chai' | 3 | import { expect } from 'chai' |
4 | import { pathExists, readdir } from 'fs-extra' | 4 | import { pathExists, readdir } from 'fs-extra' |
5 | import { join } from 'path' | 5 | import { join } from 'path' |
6 | import { root } from '@server/helpers/core-utils' | 6 | import { root } from '@shared/core-utils' |
7 | import { PeerTubeServer } from './server' | 7 | import { PeerTubeServer } from './server' |
8 | 8 | ||
9 | async function checkTmpIsEmpty (server: PeerTubeServer) { | 9 | async function checkTmpIsEmpty (server: PeerTubeServer) { |
diff --git a/shared/extra-utils/server/plugins-command.ts b/shared/extra-utils/server/plugins-command.ts index 9bf24afff..1c44711da 100644 --- a/shared/extra-utils/server/plugins-command.ts +++ b/shared/extra-utils/server/plugins-command.ts | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | import { readJSON, writeJSON } from 'fs-extra' | 3 | import { readJSON, writeJSON } from 'fs-extra' |
4 | import { join } from 'path' | 4 | import { join } from 'path' |
5 | import { root } from '@server/helpers/core-utils' | 5 | import { root } from '@shared/core-utils' |
6 | import { | 6 | import { |
7 | HttpStatusCode, | 7 | HttpStatusCode, |
8 | PeerTubePlugin, | 8 | PeerTubePlugin, |
diff --git a/shared/extra-utils/server/server.ts b/shared/extra-utils/server/server.ts index 9da293877..339b9cabb 100644 --- a/shared/extra-utils/server/server.ts +++ b/shared/extra-utils/server/server.ts | |||
@@ -1,8 +1,7 @@ | |||
1 | import { ChildProcess, fork } from 'child_process' | 1 | import { ChildProcess, fork } from 'child_process' |
2 | import { copy } from 'fs-extra' | 2 | import { copy } from 'fs-extra' |
3 | import { join } from 'path' | 3 | import { join } from 'path' |
4 | import { root } from '@server/helpers/core-utils' | 4 | import { root, randomInt } from '@shared/core-utils' |
5 | import { randomInt } from '@shared/core-utils' | ||
6 | import { Video, VideoChannel, VideoCreateResult, VideoDetails } from '../../models/videos' | 5 | import { Video, VideoChannel, VideoCreateResult, VideoDetails } from '../../models/videos' |
7 | import { BulkCommand } from '../bulk' | 6 | import { BulkCommand } from '../bulk' |
8 | import { CLICommand } from '../cli' | 7 | import { CLICommand } from '../cli' |
diff --git a/shared/extra-utils/server/servers-command.ts b/shared/extra-utils/server/servers-command.ts index 776d2123c..47420c95f 100644 --- a/shared/extra-utils/server/servers-command.ts +++ b/shared/extra-utils/server/servers-command.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import { exec } from 'child_process' | 1 | import { exec } from 'child_process' |
2 | import { copy, ensureDir, readFile, remove } from 'fs-extra' | 2 | import { copy, ensureDir, readFile, remove } from 'fs-extra' |
3 | import { basename, join } from 'path' | 3 | import { basename, join } from 'path' |
4 | import { root } from '@server/helpers/core-utils' | 4 | import { root } from '@shared/core-utils' |
5 | import { HttpStatusCode } from '@shared/models' | 5 | import { HttpStatusCode } from '@shared/models' |
6 | import { getFileSize, isGithubCI, wait } from '../miscs' | 6 | import { getFileSize, isGithubCI, wait } from '../miscs' |
7 | import { AbstractCommand, OverrideCommandOptions } from '../shared' | 7 | import { AbstractCommand, OverrideCommandOptions } from '../shared' |
diff --git a/shared/extra-utils/server/tracker.ts b/shared/extra-utils/server/tracker.ts index f04e8f8a1..ed43a5924 100644 --- a/shared/extra-utils/server/tracker.ts +++ b/shared/extra-utils/server/tracker.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { expect } from 'chai' | 1 | import { expect } from 'chai' |
2 | import { sha1 } from '@server/helpers/core-utils' | 2 | import { sha1 } from '@shared/core-utils/crypto' |
3 | import { makeGetRequest } from '../requests' | 3 | import { makeGetRequest } from '../requests' |
4 | 4 | ||
5 | async function hlsInfohashExist (serverUrl: string, masterPlaylistUrl: string, fileNumber: number) { | 5 | async function hlsInfohashExist (serverUrl: string, masterPlaylistUrl: string, fileNumber: number) { |
diff --git a/shared/extra-utils/users/actors.ts b/shared/extra-utils/users/actors.ts index cfcc7d0a7..12c3e078a 100644 --- a/shared/extra-utils/users/actors.ts +++ b/shared/extra-utils/users/actors.ts | |||
@@ -3,7 +3,7 @@ | |||
3 | import { expect } from 'chai' | 3 | import { expect } from 'chai' |
4 | import { pathExists, readdir } from 'fs-extra' | 4 | import { pathExists, readdir } from 'fs-extra' |
5 | import { join } from 'path' | 5 | import { join } from 'path' |
6 | import { root } from '@server/helpers/core-utils' | 6 | import { root } from '@shared/core-utils' |
7 | import { Account, VideoChannel } from '@shared/models' | 7 | import { Account, VideoChannel } from '@shared/models' |
8 | import { PeerTubeServer } from '../server' | 8 | import { PeerTubeServer } from '../server' |
9 | 9 | ||
diff --git a/shared/extra-utils/videos/streaming-playlists.ts b/shared/extra-utils/videos/streaming-playlists.ts index 6671e3fa6..0451c0efe 100644 --- a/shared/extra-utils/videos/streaming-playlists.ts +++ b/shared/extra-utils/videos/streaming-playlists.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { expect } from 'chai' | 1 | import { expect } from 'chai' |
2 | import { basename } from 'path' | 2 | import { basename } from 'path' |
3 | import { sha256 } from '@server/helpers/core-utils' | 3 | import { sha256 } from '@shared/core-utils/crypto' |
4 | import { removeFragmentedMP4Ext } from '@shared/core-utils' | 4 | import { removeFragmentedMP4Ext } from '@shared/core-utils' |
5 | import { HttpStatusCode, VideoStreamingPlaylist } from '@shared/models' | 5 | import { HttpStatusCode, VideoStreamingPlaylist } from '@shared/models' |
6 | import { PeerTubeServer } from '../server' | 6 | import { PeerTubeServer } from '../server' |
diff --git a/shared/extra-utils/videos/videos-command.ts b/shared/extra-utils/videos/videos-command.ts index 7ec9c3647..8ea828b40 100644 --- a/shared/extra-utils/videos/videos-command.ts +++ b/shared/extra-utils/videos/videos-command.ts | |||
@@ -5,8 +5,7 @@ import { createReadStream, stat } from 'fs-extra' | |||
5 | import got, { Response as GotResponse } from 'got' | 5 | import got, { Response as GotResponse } from 'got' |
6 | import { omit } from 'lodash' | 6 | import { omit } from 'lodash' |
7 | import validator from 'validator' | 7 | import validator from 'validator' |
8 | import { buildUUID } from '@server/helpers/uuid' | 8 | import { buildUUID } from '@shared/core-utils/uuid' |
9 | import { loadLanguages } from '@server/initializers/constants' | ||
10 | import { pick } from '@shared/core-utils' | 9 | import { pick } from '@shared/core-utils' |
11 | import { | 10 | import { |
12 | HttpStatusCode, | 11 | HttpStatusCode, |
@@ -23,7 +22,7 @@ import { | |||
23 | } from '@shared/models' | 22 | } from '@shared/models' |
24 | import { buildAbsoluteFixturePath, wait } from '../miscs' | 23 | import { buildAbsoluteFixturePath, wait } from '../miscs' |
25 | import { unwrapBody } from '../requests' | 24 | import { unwrapBody } from '../requests' |
26 | import { PeerTubeServer, waitJobs } from '../server' | 25 | import { waitJobs } from '../server' |
27 | import { AbstractCommand, OverrideCommandOptions } from '../shared' | 26 | import { AbstractCommand, OverrideCommandOptions } from '../shared' |
28 | 27 | ||
29 | export type VideoEdit = Partial<Omit<VideoCreate, 'thumbnailfile' | 'previewfile'>> & { | 28 | export type VideoEdit = Partial<Omit<VideoCreate, 'thumbnailfile' | 'previewfile'>> & { |
@@ -33,13 +32,6 @@ export type VideoEdit = Partial<Omit<VideoCreate, 'thumbnailfile' | 'previewfile | |||
33 | } | 32 | } |
34 | 33 | ||
35 | export class VideosCommand extends AbstractCommand { | 34 | export class VideosCommand extends AbstractCommand { |
36 | |||
37 | constructor (server: PeerTubeServer) { | ||
38 | super(server) | ||
39 | |||
40 | loadLanguages() | ||
41 | } | ||
42 | |||
43 | getCategories (options: OverrideCommandOptions = {}) { | 35 | getCategories (options: OverrideCommandOptions = {}) { |
44 | const path = '/api/v1/videos/categories' | 36 | const path = '/api/v1/videos/categories' |
45 | 37 | ||
diff --git a/shared/extra-utils/videos/videos.ts b/shared/extra-utils/videos/videos.ts index c05c2be6c..2c3464aa8 100644 --- a/shared/extra-utils/videos/videos.ts +++ b/shared/extra-utils/videos/videos.ts | |||
@@ -3,12 +3,7 @@ | |||
3 | import { expect } from 'chai' | 3 | import { expect } from 'chai' |
4 | import { pathExists, readdir } from 'fs-extra' | 4 | import { pathExists, readdir } from 'fs-extra' |
5 | import { basename, join } from 'path' | 5 | import { basename, join } from 'path' |
6 | import { getLowercaseExtension } from '@server/helpers/core-utils' | ||
7 | import { uuidRegex } from '@shared/core-utils' | ||
8 | import { HttpStatusCode, VideoCaption, VideoDetails } from '@shared/models' | 6 | import { HttpStatusCode, VideoCaption, VideoDetails } from '@shared/models' |
9 | import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../server/initializers/constants' | ||
10 | import { dateIsValid, testImage, webtorrentAdd } from '../miscs' | ||
11 | import { makeRawRequest } from '../requests/requests' | ||
12 | import { waitJobs } from '../server' | 7 | import { waitJobs } from '../server' |
13 | import { PeerTubeServer } from '../server/server' | 8 | import { PeerTubeServer } from '../server/server' |
14 | import { VideoEdit } from './videos-command' | 9 | import { VideoEdit } from './videos-command' |
@@ -85,150 +80,6 @@ function checkUploadVideoParam ( | |||
85 | : server.videos.buildResumeUpload({ token, attributes, expectedStatus }) | 80 | : server.videos.buildResumeUpload({ token, attributes, expectedStatus }) |
86 | } | 81 | } |
87 | 82 | ||
88 | async function completeVideoCheck ( | ||
89 | server: PeerTubeServer, | ||
90 | video: any, | ||
91 | attributes: { | ||
92 | name: string | ||
93 | category: number | ||
94 | licence: number | ||
95 | language: string | ||
96 | nsfw: boolean | ||
97 | commentsEnabled: boolean | ||
98 | downloadEnabled: boolean | ||
99 | description: string | ||
100 | publishedAt?: string | ||
101 | support: string | ||
102 | originallyPublishedAt?: string | ||
103 | account: { | ||
104 | name: string | ||
105 | host: string | ||
106 | } | ||
107 | isLocal: boolean | ||
108 | tags: string[] | ||
109 | privacy: number | ||
110 | likes?: number | ||
111 | dislikes?: number | ||
112 | duration: number | ||
113 | channel: { | ||
114 | displayName: string | ||
115 | name: string | ||
116 | description: string | ||
117 | isLocal: boolean | ||
118 | } | ||
119 | fixture: string | ||
120 | files: { | ||
121 | resolution: number | ||
122 | size: number | ||
123 | }[] | ||
124 | thumbnailfile?: string | ||
125 | previewfile?: string | ||
126 | } | ||
127 | ) { | ||
128 | if (!attributes.likes) attributes.likes = 0 | ||
129 | if (!attributes.dislikes) attributes.dislikes = 0 | ||
130 | |||
131 | const host = new URL(server.url).host | ||
132 | const originHost = attributes.account.host | ||
133 | |||
134 | expect(video.name).to.equal(attributes.name) | ||
135 | expect(video.category.id).to.equal(attributes.category) | ||
136 | expect(video.category.label).to.equal(attributes.category !== null ? VIDEO_CATEGORIES[attributes.category] : 'Misc') | ||
137 | expect(video.licence.id).to.equal(attributes.licence) | ||
138 | expect(video.licence.label).to.equal(attributes.licence !== null ? VIDEO_LICENCES[attributes.licence] : 'Unknown') | ||
139 | expect(video.language.id).to.equal(attributes.language) | ||
140 | expect(video.language.label).to.equal(attributes.language !== null ? VIDEO_LANGUAGES[attributes.language] : 'Unknown') | ||
141 | expect(video.privacy.id).to.deep.equal(attributes.privacy) | ||
142 | expect(video.privacy.label).to.deep.equal(VIDEO_PRIVACIES[attributes.privacy]) | ||
143 | expect(video.nsfw).to.equal(attributes.nsfw) | ||
144 | expect(video.description).to.equal(attributes.description) | ||
145 | expect(video.account.id).to.be.a('number') | ||
146 | expect(video.account.host).to.equal(attributes.account.host) | ||
147 | expect(video.account.name).to.equal(attributes.account.name) | ||
148 | expect(video.channel.displayName).to.equal(attributes.channel.displayName) | ||
149 | expect(video.channel.name).to.equal(attributes.channel.name) | ||
150 | expect(video.likes).to.equal(attributes.likes) | ||
151 | expect(video.dislikes).to.equal(attributes.dislikes) | ||
152 | expect(video.isLocal).to.equal(attributes.isLocal) | ||
153 | expect(video.duration).to.equal(attributes.duration) | ||
154 | expect(video.url).to.contain(originHost) | ||
155 | expect(dateIsValid(video.createdAt)).to.be.true | ||
156 | expect(dateIsValid(video.publishedAt)).to.be.true | ||
157 | expect(dateIsValid(video.updatedAt)).to.be.true | ||
158 | |||
159 | if (attributes.publishedAt) { | ||
160 | expect(video.publishedAt).to.equal(attributes.publishedAt) | ||
161 | } | ||
162 | |||
163 | if (attributes.originallyPublishedAt) { | ||
164 | expect(video.originallyPublishedAt).to.equal(attributes.originallyPublishedAt) | ||
165 | } else { | ||
166 | expect(video.originallyPublishedAt).to.be.null | ||
167 | } | ||
168 | |||
169 | const videoDetails = await server.videos.get({ id: video.uuid }) | ||
170 | |||
171 | expect(videoDetails.files).to.have.lengthOf(attributes.files.length) | ||
172 | expect(videoDetails.tags).to.deep.equal(attributes.tags) | ||
173 | expect(videoDetails.account.name).to.equal(attributes.account.name) | ||
174 | expect(videoDetails.account.host).to.equal(attributes.account.host) | ||
175 | expect(video.channel.displayName).to.equal(attributes.channel.displayName) | ||
176 | expect(video.channel.name).to.equal(attributes.channel.name) | ||
177 | expect(videoDetails.channel.host).to.equal(attributes.account.host) | ||
178 | expect(videoDetails.channel.isLocal).to.equal(attributes.channel.isLocal) | ||
179 | expect(dateIsValid(videoDetails.channel.createdAt.toString())).to.be.true | ||
180 | expect(dateIsValid(videoDetails.channel.updatedAt.toString())).to.be.true | ||
181 | expect(videoDetails.commentsEnabled).to.equal(attributes.commentsEnabled) | ||
182 | expect(videoDetails.downloadEnabled).to.equal(attributes.downloadEnabled) | ||
183 | |||
184 | for (const attributeFile of attributes.files) { | ||
185 | const file = videoDetails.files.find(f => f.resolution.id === attributeFile.resolution) | ||
186 | expect(file).not.to.be.undefined | ||
187 | |||
188 | let extension = getLowercaseExtension(attributes.fixture) | ||
189 | // Transcoding enabled: extension will always be .mp4 | ||
190 | if (attributes.files.length > 1) extension = '.mp4' | ||
191 | |||
192 | expect(file.magnetUri).to.have.lengthOf.above(2) | ||
193 | |||
194 | expect(file.torrentDownloadUrl).to.match(new RegExp(`http://${host}/download/torrents/${uuidRegex}-${file.resolution.id}.torrent`)) | ||
195 | expect(file.torrentUrl).to.match(new RegExp(`http://${host}/lazy-static/torrents/${uuidRegex}-${file.resolution.id}.torrent`)) | ||
196 | |||
197 | expect(file.fileUrl).to.match(new RegExp(`http://${originHost}/static/webseed/${uuidRegex}-${file.resolution.id}${extension}`)) | ||
198 | expect(file.fileDownloadUrl).to.match(new RegExp(`http://${originHost}/download/videos/${uuidRegex}-${file.resolution.id}${extension}`)) | ||
199 | |||
200 | await Promise.all([ | ||
201 | makeRawRequest(file.torrentUrl, 200), | ||
202 | makeRawRequest(file.torrentDownloadUrl, 200), | ||
203 | makeRawRequest(file.metadataUrl, 200) | ||
204 | ]) | ||
205 | |||
206 | expect(file.resolution.id).to.equal(attributeFile.resolution) | ||
207 | expect(file.resolution.label).to.equal(attributeFile.resolution + 'p') | ||
208 | |||
209 | const minSize = attributeFile.size - ((10 * attributeFile.size) / 100) | ||
210 | const maxSize = attributeFile.size + ((10 * attributeFile.size) / 100) | ||
211 | expect( | ||
212 | file.size, | ||
213 | 'File size for resolution ' + file.resolution.label + ' outside confidence interval (' + minSize + '> size <' + maxSize + ')' | ||
214 | ).to.be.above(minSize).and.below(maxSize) | ||
215 | |||
216 | const torrent = await webtorrentAdd(file.magnetUri, true) | ||
217 | expect(torrent.files).to.be.an('array') | ||
218 | expect(torrent.files.length).to.equal(1) | ||
219 | expect(torrent.files[0].path).to.exist.and.to.not.equal('') | ||
220 | expect(torrent.files[0].name).to.equal(`${videoDetails.name} ${file.resolution.id}p${extension}`) | ||
221 | } | ||
222 | |||
223 | expect(videoDetails.thumbnailPath).to.exist | ||
224 | await testImage(server.url, attributes.thumbnailfile || attributes.fixture, videoDetails.thumbnailPath) | ||
225 | |||
226 | if (attributes.previewfile) { | ||
227 | expect(videoDetails.previewPath).to.exist | ||
228 | await testImage(server.url, attributes.previewfile, videoDetails.previewPath) | ||
229 | } | ||
230 | } | ||
231 | |||
232 | // serverNumber starts from 1 | 83 | // serverNumber starts from 1 |
233 | async function uploadRandomVideoOnServers ( | 84 | async function uploadRandomVideoOnServers ( |
234 | servers: PeerTubeServer[], | 85 | servers: PeerTubeServer[], |
@@ -247,7 +98,6 @@ async function uploadRandomVideoOnServers ( | |||
247 | 98 | ||
248 | export { | 99 | export { |
249 | checkUploadVideoParam, | 100 | checkUploadVideoParam, |
250 | completeVideoCheck, | ||
251 | uploadRandomVideoOnServers, | 101 | uploadRandomVideoOnServers, |
252 | checkVideoFilesWereRemoved, | 102 | checkVideoFilesWereRemoved, |
253 | saveVideoInServers | 103 | saveVideoInServers |
diff --git a/shared/tsconfig.json b/shared/tsconfig.json new file mode 100644 index 000000000..95892077b --- /dev/null +++ b/shared/tsconfig.json | |||
@@ -0,0 +1,6 @@ | |||
1 | { | ||
2 | "extends": "../tsconfig.base.json", | ||
3 | "compilerOptions": { | ||
4 | "outDir": "../dist/shared" | ||
5 | } | ||
6 | } | ||
diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 000000000..ef86b9797 --- /dev/null +++ b/tsconfig.base.json | |||
@@ -0,0 +1,35 @@ | |||
1 | { | ||
2 | "compilerOptions": { | ||
3 | "module": "commonjs", | ||
4 | "target": "es2015", | ||
5 | "noImplicitAny": false, | ||
6 | "sourceMap": false, | ||
7 | "experimentalDecorators": true, | ||
8 | "emitDecoratorMetadata": true, | ||
9 | "importHelpers": true, | ||
10 | "removeComments": true, | ||
11 | "strictBindCallApply": true, | ||
12 | "esModuleInterop": true, | ||
13 | "forceConsistentCasingInFileNames": true, | ||
14 | "lib": [ | ||
15 | "es2015", | ||
16 | "es2016", | ||
17 | "es2017", | ||
18 | "es2018", | ||
19 | "es2019" | ||
20 | ], | ||
21 | "typeRoots": [ | ||
22 | "node_modules/@types", | ||
23 | ], | ||
24 | "baseUrl": "./", | ||
25 | "outDir": "./dist/", | ||
26 | "paths": { | ||
27 | "@server/*": [ "server/*" ], | ||
28 | "@shared/*": [ "shared/*" ] | ||
29 | }, | ||
30 | "resolveJsonModule": true, | ||
31 | "strict": false, | ||
32 | "skipLibCheck": true, | ||
33 | "composite": true | ||
34 | } | ||
35 | } | ||
diff --git a/tsconfig.json b/tsconfig.json index 075a3d86e..a14a97dfb 100644 --- a/tsconfig.json +++ b/tsconfig.json | |||
@@ -1,46 +1,9 @@ | |||
1 | { | 1 | { |
2 | "compilerOptions": { | 2 | "extends": "./tsconfig.base.json", |
3 | "module": "commonjs", | 3 | "references": [ |
4 | "target": "es2015", | 4 | { "path": "./shared" }, |
5 | "noImplicitAny": false, | 5 | { "path": "./server" }, |
6 | "sourceMap": false, | 6 | { "path": "./scripts" } |
7 | "experimentalDecorators": true, | 7 | ], |
8 | "emitDecoratorMetadata": true, | 8 | "files": ["server.ts"] |
9 | "importHelpers": true, | ||
10 | "removeComments": true, | ||
11 | "strictBindCallApply": true, | ||
12 | "esModuleInterop": true, | ||
13 | "forceConsistentCasingInFileNames": true, | ||
14 | "outDir": "./dist", | ||
15 | "lib": [ | ||
16 | "dom", | ||
17 | "es2015", | ||
18 | "es2016", | ||
19 | "es2017", | ||
20 | "es2018", | ||
21 | "es2019" | ||
22 | ], | ||
23 | "typeRoots": [ | ||
24 | "node_modules/@types", | ||
25 | "server/typings" | ||
26 | ], | ||
27 | "baseUrl": "./", | ||
28 | "paths": { | ||
29 | "@server/*": [ "server/*" ], | ||
30 | "@shared/*": [ "shared/*" ] | ||
31 | } | ||
32 | }, | ||
33 | "exclude": [ | ||
34 | "server/tools/", | ||
35 | "node_modules", | ||
36 | "dist", | ||
37 | "storage", | ||
38 | "client", | ||
39 | "test1", | ||
40 | "test2", | ||
41 | "test3", | ||
42 | "test4", | ||
43 | "test5", | ||
44 | "test6" | ||
45 | ] | ||
46 | } | 9 | } |
diff --git a/tsconfig.types.json b/tsconfig.types.json new file mode 100644 index 000000000..c9447d86d --- /dev/null +++ b/tsconfig.types.json | |||
@@ -0,0 +1,19 @@ | |||
1 | { | ||
2 | "extends": "./tsconfig.base.json", | ||
3 | "compilerOptions": { | ||
4 | "incremental": true, | ||
5 | "sourceMap": true, | ||
6 | "stripInternal": true, | ||
7 | "removeComments": false, | ||
8 | "declaration": true, | ||
9 | "declarationMap": true, | ||
10 | "emitDeclarationOnly": true | ||
11 | }, | ||
12 | "references": [ | ||
13 | { "path": "./shared/tsconfig.types.json" }, | ||
14 | { "path": "./server/tsconfig.types.json" }, | ||
15 | { "path": "./scripts/tsconfig.types.json" } | ||
16 | ], | ||
17 | "files": [] | ||
18 | } | ||
19 | |||