diff options
author | Chocobozzz <me@florianbigard.com> | 2023-07-31 14:34:36 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2023-08-11 15:02:33 +0200 |
commit | 3a4992633ee62d5edfbb484d9c6bcb3cf158489d (patch) | |
tree | e4510b39bdac9c318fdb4b47018d08f15368b8f0 /shared/core-utils/common | |
parent | 04d1da5621d25d59bd5fa1543b725c497bf5d9a8 (diff) | |
download | PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.gz PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.zst PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.zip |
Migrate server to ESM
Sorry for the very big commit that may lead to git log issues and merge
conflicts, but it's a major step forward:
* Server can be faster at startup because imports() are async and we can
easily lazy import big modules
* Angular doesn't seem to support ES import (with .js extension), so we
had to correctly organize peertube into a monorepo:
* Use yarn workspace feature
* Use typescript reference projects for dependencies
* Shared projects have been moved into "packages", each one is now a
node module (with a dedicated package.json/tsconfig.json)
* server/tools have been moved into apps/ and is now a dedicated app
bundled and published on NPM so users don't have to build peertube
cli tools manually
* server/tests have been moved into packages/ so we don't compile
them every time we want to run the server
* Use isolatedModule option:
* Had to move from const enum to const
(https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums)
* Had to explictely specify "type" imports when used in decorators
* Prefer tsx (that uses esbuild under the hood) instead of ts-node to
load typescript files (tests with mocha or scripts):
* To reduce test complexity as esbuild doesn't support decorator
metadata, we only test server files that do not import server
models
* We still build tests files into js files for a faster CI
* Remove unmaintained peertube CLI import script
* Removed some barrels to speed up execution (less imports)
Diffstat (limited to 'shared/core-utils/common')
-rw-r--r-- | shared/core-utils/common/array.ts | 41 | ||||
-rw-r--r-- | shared/core-utils/common/date.ts | 114 | ||||
-rw-r--r-- | shared/core-utils/common/env.ts | 46 | ||||
-rw-r--r-- | shared/core-utils/common/index.ts | 12 | ||||
-rw-r--r-- | shared/core-utils/common/number.ts | 13 | ||||
-rw-r--r-- | shared/core-utils/common/object.ts | 86 | ||||
-rw-r--r-- | shared/core-utils/common/path.ts | 48 | ||||
-rw-r--r-- | shared/core-utils/common/promises.ts | 58 | ||||
-rw-r--r-- | shared/core-utils/common/random.ts | 8 | ||||
-rw-r--r-- | shared/core-utils/common/regexp.ts | 5 | ||||
-rw-r--r-- | shared/core-utils/common/time.ts | 7 | ||||
-rw-r--r-- | shared/core-utils/common/url.ts | 150 | ||||
-rw-r--r-- | shared/core-utils/common/version.ts | 11 |
13 files changed, 0 insertions, 599 deletions
diff --git a/shared/core-utils/common/array.ts b/shared/core-utils/common/array.ts deleted file mode 100644 index 878ed1ffe..000000000 --- a/shared/core-utils/common/array.ts +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | function findCommonElement <T> (array1: T[], array2: T[]) { | ||
2 | for (const a of array1) { | ||
3 | for (const b of array2) { | ||
4 | if (a === b) return a | ||
5 | } | ||
6 | } | ||
7 | |||
8 | return null | ||
9 | } | ||
10 | |||
11 | // Avoid conflict with other toArray() functions | ||
12 | function arrayify <T> (element: T | T[]) { | ||
13 | if (Array.isArray(element)) return element | ||
14 | |||
15 | return [ element ] | ||
16 | } | ||
17 | |||
18 | // Avoid conflict with other uniq() functions | ||
19 | function uniqify <T> (elements: T[]) { | ||
20 | return Array.from(new Set(elements)) | ||
21 | } | ||
22 | |||
23 | // Thanks: https://stackoverflow.com/a/12646864 | ||
24 | function shuffle <T> (elements: T[]) { | ||
25 | const shuffled = [ ...elements ] | ||
26 | |||
27 | for (let i = shuffled.length - 1; i > 0; i--) { | ||
28 | const j = Math.floor(Math.random() * (i + 1)); | ||
29 | |||
30 | [ shuffled[i], shuffled[j] ] = [ shuffled[j], shuffled[i] ] | ||
31 | } | ||
32 | |||
33 | return shuffled | ||
34 | } | ||
35 | |||
36 | export { | ||
37 | uniqify, | ||
38 | findCommonElement, | ||
39 | shuffle, | ||
40 | arrayify | ||
41 | } | ||
diff --git a/shared/core-utils/common/date.ts b/shared/core-utils/common/date.ts deleted file mode 100644 index f0684ff86..000000000 --- a/shared/core-utils/common/date.ts +++ /dev/null | |||
@@ -1,114 +0,0 @@ | |||
1 | function isToday (d: Date) { | ||
2 | const today = new Date() | ||
3 | |||
4 | return areDatesEqual(d, today) | ||
5 | } | ||
6 | |||
7 | function isYesterday (d: Date) { | ||
8 | const yesterday = new Date() | ||
9 | yesterday.setDate(yesterday.getDate() - 1) | ||
10 | |||
11 | return areDatesEqual(d, yesterday) | ||
12 | } | ||
13 | |||
14 | function isThisWeek (d: Date) { | ||
15 | const minDateOfThisWeek = new Date() | ||
16 | minDateOfThisWeek.setHours(0, 0, 0) | ||
17 | |||
18 | // getDay() -> Sunday - Saturday : 0 - 6 | ||
19 | // We want to start our week on Monday | ||
20 | let dayOfWeek = minDateOfThisWeek.getDay() - 1 | ||
21 | if (dayOfWeek < 0) dayOfWeek = 6 // Sunday | ||
22 | |||
23 | minDateOfThisWeek.setDate(minDateOfThisWeek.getDate() - dayOfWeek) | ||
24 | |||
25 | return d >= minDateOfThisWeek | ||
26 | } | ||
27 | |||
28 | function isThisMonth (d: Date) { | ||
29 | const thisMonth = new Date().getMonth() | ||
30 | |||
31 | return d.getMonth() === thisMonth | ||
32 | } | ||
33 | |||
34 | function isLastMonth (d: Date) { | ||
35 | const now = new Date() | ||
36 | |||
37 | return getDaysDifferences(now, d) <= 30 | ||
38 | } | ||
39 | |||
40 | function isLastWeek (d: Date) { | ||
41 | const now = new Date() | ||
42 | |||
43 | return getDaysDifferences(now, d) <= 7 | ||
44 | } | ||
45 | |||
46 | // --------------------------------------------------------------------------- | ||
47 | |||
48 | function timeToInt (time: number | string) { | ||
49 | if (!time) return 0 | ||
50 | if (typeof time === 'number') return time | ||
51 | |||
52 | const reg = /^((\d+)[h:])?((\d+)[m:])?((\d+)s?)?$/ | ||
53 | const matches = time.match(reg) | ||
54 | |||
55 | if (!matches) return 0 | ||
56 | |||
57 | const hours = parseInt(matches[2] || '0', 10) | ||
58 | const minutes = parseInt(matches[4] || '0', 10) | ||
59 | const seconds = parseInt(matches[6] || '0', 10) | ||
60 | |||
61 | return hours * 3600 + minutes * 60 + seconds | ||
62 | } | ||
63 | |||
64 | function secondsToTime (seconds: number, full = false, symbol?: string) { | ||
65 | let time = '' | ||
66 | |||
67 | if (seconds === 0 && !full) return '0s' | ||
68 | |||
69 | const hourSymbol = (symbol || 'h') | ||
70 | const minuteSymbol = (symbol || 'm') | ||
71 | const secondsSymbol = full ? '' : 's' | ||
72 | |||
73 | const hours = Math.floor(seconds / 3600) | ||
74 | if (hours >= 1) time = hours + hourSymbol | ||
75 | else if (full) time = '0' + hourSymbol | ||
76 | |||
77 | seconds %= 3600 | ||
78 | const minutes = Math.floor(seconds / 60) | ||
79 | if (minutes >= 1 && minutes < 10 && full) time += '0' + minutes + minuteSymbol | ||
80 | else if (minutes >= 1) time += minutes + minuteSymbol | ||
81 | else if (full) time += '00' + minuteSymbol | ||
82 | |||
83 | seconds %= 60 | ||
84 | if (seconds >= 1 && seconds < 10 && full) time += '0' + seconds + secondsSymbol | ||
85 | else if (seconds >= 1) time += seconds + secondsSymbol | ||
86 | else if (full) time += '00' | ||
87 | |||
88 | return time | ||
89 | } | ||
90 | |||
91 | // --------------------------------------------------------------------------- | ||
92 | |||
93 | export { | ||
94 | isYesterday, | ||
95 | isThisWeek, | ||
96 | isThisMonth, | ||
97 | isToday, | ||
98 | isLastMonth, | ||
99 | isLastWeek, | ||
100 | timeToInt, | ||
101 | secondsToTime | ||
102 | } | ||
103 | |||
104 | // --------------------------------------------------------------------------- | ||
105 | |||
106 | function areDatesEqual (d1: Date, d2: Date) { | ||
107 | return d1.getFullYear() === d2.getFullYear() && | ||
108 | d1.getMonth() === d2.getMonth() && | ||
109 | d1.getDate() === d2.getDate() | ||
110 | } | ||
111 | |||
112 | function getDaysDifferences (d1: Date, d2: Date) { | ||
113 | return (d1.getTime() - d2.getTime()) / (86400000) | ||
114 | } | ||
diff --git a/shared/core-utils/common/env.ts b/shared/core-utils/common/env.ts deleted file mode 100644 index 973f895d4..000000000 --- a/shared/core-utils/common/env.ts +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | function parallelTests () { | ||
2 | return process.env.MOCHA_PARALLEL === 'true' | ||
3 | } | ||
4 | |||
5 | function isGithubCI () { | ||
6 | return !!process.env.GITHUB_WORKSPACE | ||
7 | } | ||
8 | |||
9 | function areHttpImportTestsDisabled () { | ||
10 | const disabled = process.env.DISABLE_HTTP_IMPORT_TESTS === 'true' | ||
11 | |||
12 | if (disabled) console.log('DISABLE_HTTP_IMPORT_TESTS env set to "true" so import tests are disabled') | ||
13 | |||
14 | return disabled | ||
15 | } | ||
16 | |||
17 | function areMockObjectStorageTestsDisabled () { | ||
18 | const disabled = process.env.ENABLE_OBJECT_STORAGE_TESTS !== 'true' | ||
19 | |||
20 | if (disabled) console.log('ENABLE_OBJECT_STORAGE_TESTS env is not set to "true" so object storage tests are disabled') | ||
21 | |||
22 | return disabled | ||
23 | } | ||
24 | |||
25 | function areScalewayObjectStorageTestsDisabled () { | ||
26 | if (areMockObjectStorageTestsDisabled()) return true | ||
27 | |||
28 | const enabled = process.env.OBJECT_STORAGE_SCALEWAY_KEY_ID && process.env.OBJECT_STORAGE_SCALEWAY_ACCESS_KEY | ||
29 | if (!enabled) { | ||
30 | console.log( | ||
31 | 'OBJECT_STORAGE_SCALEWAY_KEY_ID and/or OBJECT_STORAGE_SCALEWAY_ACCESS_KEY are not set, so scaleway object storage tests are disabled' | ||
32 | ) | ||
33 | |||
34 | return true | ||
35 | } | ||
36 | |||
37 | return false | ||
38 | } | ||
39 | |||
40 | export { | ||
41 | parallelTests, | ||
42 | isGithubCI, | ||
43 | areHttpImportTestsDisabled, | ||
44 | areMockObjectStorageTestsDisabled, | ||
45 | areScalewayObjectStorageTestsDisabled | ||
46 | } | ||
diff --git a/shared/core-utils/common/index.ts b/shared/core-utils/common/index.ts deleted file mode 100644 index 8d63ee1b2..000000000 --- a/shared/core-utils/common/index.ts +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | export * from './array' | ||
2 | export * from './random' | ||
3 | export * from './date' | ||
4 | export * from './env' | ||
5 | export * from './number' | ||
6 | export * from './object' | ||
7 | export * from './path' | ||
8 | export * from './regexp' | ||
9 | export * from './time' | ||
10 | export * from './promises' | ||
11 | export * from './url' | ||
12 | export * from './version' | ||
diff --git a/shared/core-utils/common/number.ts b/shared/core-utils/common/number.ts deleted file mode 100644 index ce5a6041a..000000000 --- a/shared/core-utils/common/number.ts +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | export function forceNumber (value: any) { | ||
2 | return parseInt(value + '') | ||
3 | } | ||
4 | |||
5 | export function isOdd (num: number) { | ||
6 | return (num % 2) !== 0 | ||
7 | } | ||
8 | |||
9 | export function toEven (num: number) { | ||
10 | if (isOdd(num)) return num + 1 | ||
11 | |||
12 | return num | ||
13 | } | ||
diff --git a/shared/core-utils/common/object.ts b/shared/core-utils/common/object.ts deleted file mode 100644 index 1276bfcc7..000000000 --- a/shared/core-utils/common/object.ts +++ /dev/null | |||
@@ -1,86 +0,0 @@ | |||
1 | function pick <O extends object, K extends keyof O> (object: O, keys: K[]): Pick<O, K> { | ||
2 | const result: any = {} | ||
3 | |||
4 | for (const key of keys) { | ||
5 | if (Object.prototype.hasOwnProperty.call(object, key)) { | ||
6 | result[key] = object[key] | ||
7 | } | ||
8 | } | ||
9 | |||
10 | return result | ||
11 | } | ||
12 | |||
13 | function omit <O extends object, K extends keyof O> (object: O, keys: K[]): Exclude<O, K> { | ||
14 | const result: any = {} | ||
15 | const keysSet = new Set(keys) as Set<string> | ||
16 | |||
17 | for (const [ key, value ] of Object.entries(object)) { | ||
18 | if (keysSet.has(key)) continue | ||
19 | |||
20 | result[key] = value | ||
21 | } | ||
22 | |||
23 | return result | ||
24 | } | ||
25 | |||
26 | function objectKeysTyped <O extends object, K extends keyof O> (object: O): K[] { | ||
27 | return (Object.keys(object) as K[]) | ||
28 | } | ||
29 | |||
30 | function getKeys <O extends object, K extends keyof O> (object: O, keys: K[]): K[] { | ||
31 | return (Object.keys(object) as K[]).filter(k => keys.includes(k)) | ||
32 | } | ||
33 | |||
34 | function hasKey <T extends object> (obj: T, k: keyof any): k is keyof T { | ||
35 | return k in obj | ||
36 | } | ||
37 | |||
38 | function sortObjectComparator (key: string, order: 'asc' | 'desc') { | ||
39 | return (a: any, b: any) => { | ||
40 | if (a[key] < b[key]) { | ||
41 | return order === 'asc' ? -1 : 1 | ||
42 | } | ||
43 | |||
44 | if (a[key] > b[key]) { | ||
45 | return order === 'asc' ? 1 : -1 | ||
46 | } | ||
47 | |||
48 | return 0 | ||
49 | } | ||
50 | } | ||
51 | |||
52 | function shallowCopy <T> (o: T): T { | ||
53 | return Object.assign(Object.create(Object.getPrototypeOf(o)), o) | ||
54 | } | ||
55 | |||
56 | function simpleObjectsDeepEqual (a: any, b: any) { | ||
57 | if (a === b) return true | ||
58 | |||
59 | if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) { | ||
60 | return false | ||
61 | } | ||
62 | |||
63 | const keysA = Object.keys(a) | ||
64 | const keysB = Object.keys(b) | ||
65 | |||
66 | if (keysA.length !== keysB.length) return false | ||
67 | |||
68 | for (const key of keysA) { | ||
69 | if (!keysB.includes(key)) return false | ||
70 | |||
71 | if (!simpleObjectsDeepEqual(a[key], b[key])) return false | ||
72 | } | ||
73 | |||
74 | return true | ||
75 | } | ||
76 | |||
77 | export { | ||
78 | pick, | ||
79 | omit, | ||
80 | objectKeysTyped, | ||
81 | getKeys, | ||
82 | hasKey, | ||
83 | shallowCopy, | ||
84 | sortObjectComparator, | ||
85 | simpleObjectsDeepEqual | ||
86 | } | ||
diff --git a/shared/core-utils/common/path.ts b/shared/core-utils/common/path.ts deleted file mode 100644 index 006505316..000000000 --- a/shared/core-utils/common/path.ts +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
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) === 'tools') rootPath = resolve(rootPath, '..') | ||
11 | if (basename(rootPath) === 'scripts') rootPath = resolve(rootPath, '..') | ||
12 | if (basename(rootPath) === 'common') rootPath = resolve(rootPath, '..') | ||
13 | if (basename(rootPath) === 'core-utils') rootPath = resolve(rootPath, '..') | ||
14 | if (basename(rootPath) === 'shared') rootPath = resolve(rootPath, '..') | ||
15 | if (basename(rootPath) === 'server') rootPath = resolve(rootPath, '..') | ||
16 | if (basename(rootPath) === 'dist') rootPath = resolve(rootPath, '..') | ||
17 | |||
18 | return rootPath | ||
19 | } | ||
20 | |||
21 | function buildPath (path: string) { | ||
22 | if (isAbsolute(path)) return path | ||
23 | |||
24 | return join(root(), path) | ||
25 | } | ||
26 | |||
27 | function getLowercaseExtension (filename: string) { | ||
28 | const ext = extname(filename) || '' | ||
29 | |||
30 | return ext.toLowerCase() | ||
31 | } | ||
32 | |||
33 | function buildAbsoluteFixturePath (path: string, customCIPath = false) { | ||
34 | if (isAbsolute(path)) return path | ||
35 | |||
36 | if (customCIPath && process.env.GITHUB_WORKSPACE) { | ||
37 | return join(process.env.GITHUB_WORKSPACE, 'fixtures', path) | ||
38 | } | ||
39 | |||
40 | return join(root(), 'server', 'tests', 'fixtures', path) | ||
41 | } | ||
42 | |||
43 | export { | ||
44 | root, | ||
45 | buildPath, | ||
46 | buildAbsoluteFixturePath, | ||
47 | getLowercaseExtension | ||
48 | } | ||
diff --git a/shared/core-utils/common/promises.ts b/shared/core-utils/common/promises.ts deleted file mode 100644 index e3792d12e..000000000 --- a/shared/core-utils/common/promises.ts +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | export function isPromise <T = unknown> (value: T | Promise<T>): value is Promise<T> { | ||
2 | return value && typeof (value as Promise<T>).then === 'function' | ||
3 | } | ||
4 | |||
5 | export function isCatchable (value: any) { | ||
6 | return value && typeof value.catch === 'function' | ||
7 | } | ||
8 | |||
9 | export function timeoutPromise <T> (promise: Promise<T>, timeoutMs: number) { | ||
10 | let timer: ReturnType<typeof setTimeout> | ||
11 | |||
12 | return Promise.race([ | ||
13 | promise, | ||
14 | |||
15 | new Promise((_res, rej) => { | ||
16 | timer = setTimeout(() => rej(new Error('Timeout')), timeoutMs) | ||
17 | }) | ||
18 | ]).finally(() => clearTimeout(timer)) | ||
19 | } | ||
20 | |||
21 | export function promisify0<A> (func: (cb: (err: any, result: A) => void) => void): () => Promise<A> { | ||
22 | return function promisified (): Promise<A> { | ||
23 | return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => { | ||
24 | // eslint-disable-next-line no-useless-call | ||
25 | func.apply(null, [ (err: any, res: A) => err ? reject(err) : resolve(res) ]) | ||
26 | }) | ||
27 | } | ||
28 | } | ||
29 | |||
30 | // Thanks to https://gist.github.com/kumasento/617daa7e46f13ecdd9b2 | ||
31 | export function promisify1<T, A> (func: (arg: T, cb: (err: any, result: A) => void) => void): (arg: T) => Promise<A> { | ||
32 | return function promisified (arg: T): Promise<A> { | ||
33 | return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => { | ||
34 | // eslint-disable-next-line no-useless-call | ||
35 | func.apply(null, [ arg, (err: any, res: A) => err ? reject(err) : resolve(res) ]) | ||
36 | }) | ||
37 | } | ||
38 | } | ||
39 | |||
40 | // eslint-disable-next-line max-len | ||
41 | export function promisify2<T, U, A> (func: (arg1: T, arg2: U, cb: (err: any, result: A) => void) => void): (arg1: T, arg2: U) => Promise<A> { | ||
42 | return function promisified (arg1: T, arg2: U): Promise<A> { | ||
43 | return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => { | ||
44 | // eslint-disable-next-line no-useless-call | ||
45 | func.apply(null, [ arg1, arg2, (err: any, res: A) => err ? reject(err) : resolve(res) ]) | ||
46 | }) | ||
47 | } | ||
48 | } | ||
49 | |||
50 | // eslint-disable-next-line max-len | ||
51 | export function promisify3<T, U, V, A> (func: (arg1: T, arg2: U, arg3: V, cb: (err: any, result: A) => void) => void): (arg1: T, arg2: U, arg3: V) => Promise<A> { | ||
52 | return function promisified (arg1: T, arg2: U, arg3: V): Promise<A> { | ||
53 | return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => { | ||
54 | // eslint-disable-next-line no-useless-call | ||
55 | func.apply(null, [ arg1, arg2, arg3, (err: any, res: A) => err ? reject(err) : resolve(res) ]) | ||
56 | }) | ||
57 | } | ||
58 | } | ||
diff --git a/shared/core-utils/common/random.ts b/shared/core-utils/common/random.ts deleted file mode 100644 index 705735d09..000000000 --- a/shared/core-utils/common/random.ts +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | // high excluded | ||
2 | function randomInt (low: number, high: number) { | ||
3 | return Math.floor(Math.random() * (high - low) + low) | ||
4 | } | ||
5 | |||
6 | export { | ||
7 | randomInt | ||
8 | } | ||
diff --git a/shared/core-utils/common/regexp.ts b/shared/core-utils/common/regexp.ts deleted file mode 100644 index 59eb87eb6..000000000 --- a/shared/core-utils/common/regexp.ts +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | export const uuidRegex = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' | ||
2 | |||
3 | export function removeFragmentedMP4Ext (path: string) { | ||
4 | return path.replace(/-fragmented.mp4$/i, '') | ||
5 | } | ||
diff --git a/shared/core-utils/common/time.ts b/shared/core-utils/common/time.ts deleted file mode 100644 index 2992609ca..000000000 --- a/shared/core-utils/common/time.ts +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | function wait (milliseconds: number) { | ||
2 | return new Promise(resolve => setTimeout(resolve, milliseconds)) | ||
3 | } | ||
4 | |||
5 | export { | ||
6 | wait | ||
7 | } | ||
diff --git a/shared/core-utils/common/url.ts b/shared/core-utils/common/url.ts deleted file mode 100644 index 33fc5ee3a..000000000 --- a/shared/core-utils/common/url.ts +++ /dev/null | |||
@@ -1,150 +0,0 @@ | |||
1 | import { Video, VideoPlaylist } from '../../models' | ||
2 | import { secondsToTime } from './date' | ||
3 | |||
4 | function addQueryParams (url: string, params: { [ id: string ]: string }) { | ||
5 | const objUrl = new URL(url) | ||
6 | |||
7 | for (const key of Object.keys(params)) { | ||
8 | objUrl.searchParams.append(key, params[key]) | ||
9 | } | ||
10 | |||
11 | return objUrl.toString() | ||
12 | } | ||
13 | |||
14 | function removeQueryParams (url: string) { | ||
15 | const objUrl = new URL(url) | ||
16 | |||
17 | objUrl.searchParams.forEach((_v, k) => objUrl.searchParams.delete(k)) | ||
18 | |||
19 | return objUrl.toString() | ||
20 | } | ||
21 | |||
22 | function buildPlaylistLink (playlist: Pick<VideoPlaylist, 'shortUUID'>, base?: string) { | ||
23 | return (base ?? window.location.origin) + buildPlaylistWatchPath(playlist) | ||
24 | } | ||
25 | |||
26 | function buildPlaylistWatchPath (playlist: Pick<VideoPlaylist, 'shortUUID'>) { | ||
27 | return '/w/p/' + playlist.shortUUID | ||
28 | } | ||
29 | |||
30 | function buildVideoWatchPath (video: Pick<Video, 'shortUUID'>) { | ||
31 | return '/w/' + video.shortUUID | ||
32 | } | ||
33 | |||
34 | function buildVideoLink (video: Pick<Video, 'shortUUID'>, base?: string) { | ||
35 | return (base ?? window.location.origin) + buildVideoWatchPath(video) | ||
36 | } | ||
37 | |||
38 | function buildPlaylistEmbedPath (playlist: Pick<VideoPlaylist, 'uuid'>) { | ||
39 | return '/video-playlists/embed/' + playlist.uuid | ||
40 | } | ||
41 | |||
42 | function buildPlaylistEmbedLink (playlist: Pick<VideoPlaylist, 'uuid'>, base?: string) { | ||
43 | return (base ?? window.location.origin) + buildPlaylistEmbedPath(playlist) | ||
44 | } | ||
45 | |||
46 | function buildVideoEmbedPath (video: Pick<Video, 'uuid'>) { | ||
47 | return '/videos/embed/' + video.uuid | ||
48 | } | ||
49 | |||
50 | function buildVideoEmbedLink (video: Pick<Video, 'uuid'>, base?: string) { | ||
51 | return (base ?? window.location.origin) + buildVideoEmbedPath(video) | ||
52 | } | ||
53 | |||
54 | function decorateVideoLink (options: { | ||
55 | url: string | ||
56 | |||
57 | startTime?: number | ||
58 | stopTime?: number | ||
59 | |||
60 | subtitle?: string | ||
61 | |||
62 | loop?: boolean | ||
63 | autoplay?: boolean | ||
64 | muted?: boolean | ||
65 | |||
66 | // Embed options | ||
67 | title?: boolean | ||
68 | warningTitle?: boolean | ||
69 | |||
70 | controls?: boolean | ||
71 | controlBar?: boolean | ||
72 | |||
73 | peertubeLink?: boolean | ||
74 | p2p?: boolean | ||
75 | }) { | ||
76 | const { url } = options | ||
77 | |||
78 | const params = new URLSearchParams() | ||
79 | |||
80 | if (options.startTime !== undefined && options.startTime !== null) { | ||
81 | const startTimeInt = Math.floor(options.startTime) | ||
82 | params.set('start', secondsToTime(startTimeInt)) | ||
83 | } | ||
84 | |||
85 | if (options.stopTime) { | ||
86 | const stopTimeInt = Math.floor(options.stopTime) | ||
87 | params.set('stop', secondsToTime(stopTimeInt)) | ||
88 | } | ||
89 | |||
90 | if (options.subtitle) params.set('subtitle', options.subtitle) | ||
91 | |||
92 | if (options.loop === true) params.set('loop', '1') | ||
93 | if (options.autoplay === true) params.set('autoplay', '1') | ||
94 | if (options.muted === true) params.set('muted', '1') | ||
95 | if (options.title === false) params.set('title', '0') | ||
96 | if (options.warningTitle === false) params.set('warningTitle', '0') | ||
97 | |||
98 | if (options.controls === false) params.set('controls', '0') | ||
99 | if (options.controlBar === false) params.set('controlBar', '0') | ||
100 | |||
101 | if (options.peertubeLink === false) params.set('peertubeLink', '0') | ||
102 | if (options.p2p !== undefined) params.set('p2p', options.p2p ? '1' : '0') | ||
103 | |||
104 | return buildUrl(url, params) | ||
105 | } | ||
106 | |||
107 | function decoratePlaylistLink (options: { | ||
108 | url: string | ||
109 | |||
110 | playlistPosition?: number | ||
111 | }) { | ||
112 | const { url } = options | ||
113 | |||
114 | const params = new URLSearchParams() | ||
115 | |||
116 | if (options.playlistPosition) params.set('playlistPosition', '' + options.playlistPosition) | ||
117 | |||
118 | return buildUrl(url, params) | ||
119 | } | ||
120 | |||
121 | // --------------------------------------------------------------------------- | ||
122 | |||
123 | export { | ||
124 | addQueryParams, | ||
125 | removeQueryParams, | ||
126 | |||
127 | buildPlaylistLink, | ||
128 | buildVideoLink, | ||
129 | |||
130 | buildVideoWatchPath, | ||
131 | buildPlaylistWatchPath, | ||
132 | |||
133 | buildPlaylistEmbedPath, | ||
134 | buildVideoEmbedPath, | ||
135 | |||
136 | buildPlaylistEmbedLink, | ||
137 | buildVideoEmbedLink, | ||
138 | |||
139 | decorateVideoLink, | ||
140 | decoratePlaylistLink | ||
141 | } | ||
142 | |||
143 | function buildUrl (url: string, params: URLSearchParams) { | ||
144 | let hasParams = false | ||
145 | params.forEach(() => { hasParams = true }) | ||
146 | |||
147 | if (hasParams) return url + '?' + params.toString() | ||
148 | |||
149 | return url | ||
150 | } | ||
diff --git a/shared/core-utils/common/version.ts b/shared/core-utils/common/version.ts deleted file mode 100644 index 305287233..000000000 --- a/shared/core-utils/common/version.ts +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | // Thanks https://gist.github.com/iwill/a83038623ba4fef6abb9efca87ae9ccb | ||
2 | function compareSemVer (a: string, b: string) { | ||
3 | if (a.startsWith(b + '-')) return -1 | ||
4 | if (b.startsWith(a + '-')) return 1 | ||
5 | |||
6 | return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'case', caseFirst: 'upper' }) | ||
7 | } | ||
8 | |||
9 | export { | ||
10 | compareSemVer | ||
11 | } | ||