aboutsummaryrefslogtreecommitdiffhomepage
path: root/packages/models/src/server
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-07-31 14:34:36 +0200
committerChocobozzz <me@florianbigard.com>2023-08-11 15:02:33 +0200
commit3a4992633ee62d5edfbb484d9c6bcb3cf158489d (patch)
treee4510b39bdac9c318fdb4b47018d08f15368b8f0 /packages/models/src/server
parent04d1da5621d25d59bd5fa1543b725c497bf5d9a8 (diff)
downloadPeerTube-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 'packages/models/src/server')
-rw-r--r--packages/models/src/server/about.model.ts20
-rw-r--r--packages/models/src/server/broadcast-message-level.type.ts1
-rw-r--r--packages/models/src/server/client-log-create.model.ts11
-rw-r--r--packages/models/src/server/client-log-level.type.ts1
-rw-r--r--packages/models/src/server/contact-form.model.ts6
-rw-r--r--packages/models/src/server/custom-config.model.ts259
-rw-r--r--packages/models/src/server/debug.model.ts12
-rw-r--r--packages/models/src/server/emailer.model.ts49
-rw-r--r--packages/models/src/server/index.ts16
-rw-r--r--packages/models/src/server/job.model.ts303
-rw-r--r--packages/models/src/server/peertube-problem-document.model.ts32
-rw-r--r--packages/models/src/server/server-config.model.ts305
-rw-r--r--packages/models/src/server/server-debug.model.ts4
-rw-r--r--packages/models/src/server/server-error-code.enum.ts92
-rw-r--r--packages/models/src/server/server-follow-create.model.ts4
-rw-r--r--packages/models/src/server/server-log-level.type.ts1
-rw-r--r--packages/models/src/server/server-stats.model.ts47
17 files changed, 1163 insertions, 0 deletions
diff --git a/packages/models/src/server/about.model.ts b/packages/models/src/server/about.model.ts
new file mode 100644
index 000000000..6d4ba63c4
--- /dev/null
+++ b/packages/models/src/server/about.model.ts
@@ -0,0 +1,20 @@
1export interface About {
2 instance: {
3 name: string
4 shortDescription: string
5 description: string
6 terms: string
7
8 codeOfConduct: string
9 hardwareInformation: string
10
11 creationReason: string
12 moderationInformation: string
13 administrator: string
14 maintenanceLifetime: string
15 businessModel: string
16
17 languages: string[]
18 categories: number[]
19 }
20}
diff --git a/packages/models/src/server/broadcast-message-level.type.ts b/packages/models/src/server/broadcast-message-level.type.ts
new file mode 100644
index 000000000..bf43e18b5
--- /dev/null
+++ b/packages/models/src/server/broadcast-message-level.type.ts
@@ -0,0 +1 @@
export type BroadcastMessageLevel = 'info' | 'warning' | 'error'
diff --git a/packages/models/src/server/client-log-create.model.ts b/packages/models/src/server/client-log-create.model.ts
new file mode 100644
index 000000000..543af0d3d
--- /dev/null
+++ b/packages/models/src/server/client-log-create.model.ts
@@ -0,0 +1,11 @@
1import { ClientLogLevel } from './client-log-level.type.js'
2
3export interface ClientLogCreate {
4 message: string
5 url: string
6 level: ClientLogLevel
7
8 stackTrace?: string
9 userAgent?: string
10 meta?: string
11}
diff --git a/packages/models/src/server/client-log-level.type.ts b/packages/models/src/server/client-log-level.type.ts
new file mode 100644
index 000000000..18dea2751
--- /dev/null
+++ b/packages/models/src/server/client-log-level.type.ts
@@ -0,0 +1 @@
export type ClientLogLevel = 'warn' | 'error'
diff --git a/packages/models/src/server/contact-form.model.ts b/packages/models/src/server/contact-form.model.ts
new file mode 100644
index 000000000..c23e6d1ba
--- /dev/null
+++ b/packages/models/src/server/contact-form.model.ts
@@ -0,0 +1,6 @@
1export interface ContactForm {
2 fromEmail: string
3 fromName: string
4 subject: string
5 body: string
6}
diff --git a/packages/models/src/server/custom-config.model.ts b/packages/models/src/server/custom-config.model.ts
new file mode 100644
index 000000000..df4176ba7
--- /dev/null
+++ b/packages/models/src/server/custom-config.model.ts
@@ -0,0 +1,259 @@
1import { NSFWPolicyType } from '../videos/nsfw-policy.type.js'
2import { BroadcastMessageLevel } from './broadcast-message-level.type.js'
3
4export type ConfigResolutions = {
5 '144p': boolean
6 '240p': boolean
7 '360p': boolean
8 '480p': boolean
9 '720p': boolean
10 '1080p': boolean
11 '1440p': boolean
12 '2160p': boolean
13}
14
15export interface CustomConfig {
16 instance: {
17 name: string
18 shortDescription: string
19 description: string
20 terms: string
21 codeOfConduct: string
22
23 creationReason: string
24 moderationInformation: string
25 administrator: string
26 maintenanceLifetime: string
27 businessModel: string
28 hardwareInformation: string
29
30 languages: string[]
31 categories: number[]
32
33 isNSFW: boolean
34 defaultNSFWPolicy: NSFWPolicyType
35
36 defaultClientRoute: string
37
38 customizations: {
39 javascript?: string
40 css?: string
41 }
42 }
43
44 theme: {
45 default: string
46 }
47
48 services: {
49 twitter: {
50 username: string
51 whitelisted: boolean
52 }
53 }
54
55 client: {
56 videos: {
57 miniature: {
58 preferAuthorDisplayName: boolean
59 }
60 }
61
62 menu: {
63 login: {
64 redirectOnSingleExternalAuth: boolean
65 }
66 }
67 }
68
69 cache: {
70 previews: {
71 size: number
72 }
73
74 captions: {
75 size: number
76 }
77
78 torrents: {
79 size: number
80 }
81
82 storyboards: {
83 size: number
84 }
85 }
86
87 signup: {
88 enabled: boolean
89 limit: number
90 requiresApproval: boolean
91 requiresEmailVerification: boolean
92 minimumAge: number
93 }
94
95 admin: {
96 email: string
97 }
98
99 contactForm: {
100 enabled: boolean
101 }
102
103 user: {
104 history: {
105 videos: {
106 enabled: boolean
107 }
108 }
109 videoQuota: number
110 videoQuotaDaily: number
111 }
112
113 videoChannels: {
114 maxPerUser: number
115 }
116
117 transcoding: {
118 enabled: boolean
119
120 allowAdditionalExtensions: boolean
121 allowAudioFiles: boolean
122
123 remoteRunners: {
124 enabled: boolean
125 }
126
127 threads: number
128 concurrency: number
129
130 profile: string
131
132 resolutions: ConfigResolutions & { '0p': boolean }
133
134 alwaysTranscodeOriginalResolution: boolean
135
136 webVideos: {
137 enabled: boolean
138 }
139
140 hls: {
141 enabled: boolean
142 }
143 }
144
145 live: {
146 enabled: boolean
147
148 allowReplay: boolean
149
150 latencySetting: {
151 enabled: boolean
152 }
153
154 maxDuration: number
155 maxInstanceLives: number
156 maxUserLives: number
157
158 transcoding: {
159 enabled: boolean
160 remoteRunners: {
161 enabled: boolean
162 }
163 threads: number
164 profile: string
165 resolutions: ConfigResolutions
166 alwaysTranscodeOriginalResolution: boolean
167 }
168 }
169
170 videoStudio: {
171 enabled: boolean
172
173 remoteRunners: {
174 enabled: boolean
175 }
176 }
177
178 videoFile: {
179 update: {
180 enabled: boolean
181 }
182 }
183
184 import: {
185 videos: {
186 concurrency: number
187
188 http: {
189 enabled: boolean
190 }
191 torrent: {
192 enabled: boolean
193 }
194 }
195 videoChannelSynchronization: {
196 enabled: boolean
197 maxPerUser: number
198 }
199 }
200
201 trending: {
202 videos: {
203 algorithms: {
204 enabled: string[]
205 default: string
206 }
207 }
208 }
209
210 autoBlacklist: {
211 videos: {
212 ofUsers: {
213 enabled: boolean
214 }
215 }
216 }
217
218 followers: {
219 instance: {
220 enabled: boolean
221 manualApproval: boolean
222 }
223 }
224
225 followings: {
226 instance: {
227 autoFollowBack: {
228 enabled: boolean
229 }
230
231 autoFollowIndex: {
232 enabled: boolean
233 indexUrl: string
234 }
235 }
236 }
237
238 broadcastMessage: {
239 enabled: boolean
240 message: string
241 level: BroadcastMessageLevel
242 dismissable: boolean
243 }
244
245 search: {
246 remoteUri: {
247 users: boolean
248 anonymous: boolean
249 }
250
251 searchIndex: {
252 enabled: boolean
253 url: string
254 disableLocalSearch: boolean
255 isDefaultSearch: boolean
256 }
257 }
258
259}
diff --git a/packages/models/src/server/debug.model.ts b/packages/models/src/server/debug.model.ts
new file mode 100644
index 000000000..41f2109af
--- /dev/null
+++ b/packages/models/src/server/debug.model.ts
@@ -0,0 +1,12 @@
1export interface Debug {
2 ip: string
3 activityPubMessagesWaiting: number
4}
5
6export interface SendDebugCommand {
7 command: 'remove-dandling-resumable-uploads'
8 | 'process-video-views-buffer'
9 | 'process-video-viewers'
10 | 'process-video-channel-sync-latest'
11 | 'process-update-videos-scheduler'
12}
diff --git a/packages/models/src/server/emailer.model.ts b/packages/models/src/server/emailer.model.ts
new file mode 100644
index 000000000..39512d306
--- /dev/null
+++ b/packages/models/src/server/emailer.model.ts
@@ -0,0 +1,49 @@
1type From = string | { name?: string, address: string }
2
3interface Base extends Partial<SendEmailDefaultMessageOptions> {
4 to: string[] | string
5}
6
7interface MailTemplate extends Base {
8 template: string
9 locals?: { [key: string]: any }
10 text?: undefined
11}
12
13interface MailText extends Base {
14 text: string
15
16 locals?: Partial<SendEmailDefaultLocalsOptions> & {
17 title?: string
18 action?: {
19 url: string
20 text: string
21 }
22 }
23}
24
25interface SendEmailDefaultLocalsOptions {
26 instanceName: string
27 text: string
28 subject: string
29}
30
31interface SendEmailDefaultMessageOptions {
32 to: string[] | string
33 from: From
34 subject: string
35 replyTo: string
36}
37
38export type SendEmailDefaultOptions = {
39 template: 'common'
40
41 message: SendEmailDefaultMessageOptions
42
43 locals: SendEmailDefaultLocalsOptions & {
44 WEBSERVER: any
45 EMAIL: any
46 }
47}
48
49export type SendEmailOptions = MailTemplate | MailText
diff --git a/packages/models/src/server/index.ts b/packages/models/src/server/index.ts
new file mode 100644
index 000000000..ba6af8f6f
--- /dev/null
+++ b/packages/models/src/server/index.ts
@@ -0,0 +1,16 @@
1export * from './about.model.js'
2export * from './broadcast-message-level.type.js'
3export * from './client-log-create.model.js'
4export * from './client-log-level.type.js'
5export * from './contact-form.model.js'
6export * from './custom-config.model.js'
7export * from './debug.model.js'
8export * from './emailer.model.js'
9export * from './job.model.js'
10export * from './peertube-problem-document.model.js'
11export * from './server-config.model.js'
12export * from './server-debug.model.js'
13export * from './server-error-code.enum.js'
14export * from './server-follow-create.model.js'
15export * from './server-log-level.type.js'
16export * from './server-stats.model.js'
diff --git a/packages/models/src/server/job.model.ts b/packages/models/src/server/job.model.ts
new file mode 100644
index 000000000..f86a20e28
--- /dev/null
+++ b/packages/models/src/server/job.model.ts
@@ -0,0 +1,303 @@
1import { ContextType } from '../activitypub/context.js'
2import { VideoStateType } from '../videos/index.js'
3import { VideoStudioTaskCut } from '../videos/studio/index.js'
4import { SendEmailOptions } from './emailer.model.js'
5
6export type JobState = 'active' | 'completed' | 'failed' | 'waiting' | 'delayed' | 'paused' | 'waiting-children'
7
8export type JobType =
9 | 'activitypub-cleaner'
10 | 'activitypub-follow'
11 | 'activitypub-http-broadcast-parallel'
12 | 'activitypub-http-broadcast'
13 | 'activitypub-http-fetcher'
14 | 'activitypub-http-unicast'
15 | 'activitypub-refresher'
16 | 'actor-keys'
17 | 'after-video-channel-import'
18 | 'email'
19 | 'federate-video'
20 | 'transcoding-job-builder'
21 | 'manage-video-torrent'
22 | 'move-to-object-storage'
23 | 'notify'
24 | 'video-channel-import'
25 | 'video-file-import'
26 | 'video-import'
27 | 'video-live-ending'
28 | 'video-redundancy'
29 | 'video-studio-edition'
30 | 'video-transcoding'
31 | 'videos-views-stats'
32 | 'generate-video-storyboard'
33
34export interface Job {
35 id: number | string
36 state: JobState | 'unknown'
37 type: JobType
38 data: any
39 priority: number
40 progress: number
41 error: any
42 createdAt: Date | string
43 finishedOn: Date | string
44 processedOn: Date | string
45
46 parent?: {
47 id: string
48 }
49}
50
51export type ActivitypubHttpBroadcastPayload = {
52 uris: string[]
53 contextType: ContextType
54 body: any
55 signatureActorId?: number
56}
57
58export type ActivitypubFollowPayload = {
59 followerActorId: number
60 name: string
61 host: string
62 isAutoFollow?: boolean
63 assertIsChannel?: boolean
64}
65
66export type FetchType = 'activity' | 'video-shares' | 'video-comments' | 'account-playlists'
67export type ActivitypubHttpFetcherPayload = {
68 uri: string
69 type: FetchType
70 videoId?: number
71}
72
73export type ActivitypubHttpUnicastPayload = {
74 uri: string
75 contextType: ContextType
76 signatureActorId?: number
77 body: object
78}
79
80export type RefreshPayload = {
81 type: 'video' | 'video-playlist' | 'actor'
82 url: string
83}
84
85export type EmailPayload = SendEmailOptions
86
87export type VideoFileImportPayload = {
88 videoUUID: string
89 filePath: string
90}
91
92// ---------------------------------------------------------------------------
93
94export type VideoImportTorrentPayloadType = 'magnet-uri' | 'torrent-file'
95export type VideoImportYoutubeDLPayloadType = 'youtube-dl'
96
97export interface VideoImportYoutubeDLPayload {
98 type: VideoImportYoutubeDLPayloadType
99 videoImportId: number
100
101 fileExt?: string
102}
103
104export interface VideoImportTorrentPayload {
105 type: VideoImportTorrentPayloadType
106 videoImportId: number
107}
108
109export type VideoImportPayload = (VideoImportYoutubeDLPayload | VideoImportTorrentPayload) & {
110 preventException: boolean
111}
112
113export interface VideoImportPreventExceptionResult {
114 resultType: 'success' | 'error'
115}
116
117// ---------------------------------------------------------------------------
118
119export type VideoRedundancyPayload = {
120 videoId: number
121}
122
123export type ManageVideoTorrentPayload =
124 {
125 action: 'create'
126 videoId: number
127 videoFileId: number
128 } | {
129 action: 'update-metadata'
130
131 videoId?: number
132 streamingPlaylistId?: number
133
134 videoFileId: number
135 }
136
137// Video transcoding payloads
138
139interface BaseTranscodingPayload {
140 videoUUID: string
141 isNewVideo?: boolean
142}
143
144export interface HLSTranscodingPayload extends BaseTranscodingPayload {
145 type: 'new-resolution-to-hls'
146 resolution: number
147 fps: number
148 copyCodecs: boolean
149
150 deleteWebVideoFiles: boolean
151}
152
153export interface NewWebVideoResolutionTranscodingPayload extends BaseTranscodingPayload {
154 type: 'new-resolution-to-web-video'
155 resolution: number
156 fps: number
157}
158
159export interface MergeAudioTranscodingPayload extends BaseTranscodingPayload {
160 type: 'merge-audio-to-web-video'
161
162 resolution: number
163 fps: number
164
165 hasChildren: boolean
166}
167
168export interface OptimizeTranscodingPayload extends BaseTranscodingPayload {
169 type: 'optimize-to-web-video'
170
171 quickTranscode: boolean
172
173 hasChildren: boolean
174}
175
176export type VideoTranscodingPayload =
177 HLSTranscodingPayload
178 | NewWebVideoResolutionTranscodingPayload
179 | OptimizeTranscodingPayload
180 | MergeAudioTranscodingPayload
181
182export interface VideoLiveEndingPayload {
183 videoId: number
184 publishedAt: string
185 liveSessionId: number
186 streamingPlaylistId: number
187
188 replayDirectory?: string
189}
190
191export interface ActorKeysPayload {
192 actorId: number
193}
194
195export interface DeleteResumableUploadMetaFilePayload {
196 filepath: string
197}
198
199export interface MoveObjectStoragePayload {
200 videoUUID: string
201 isNewVideo: boolean
202 previousVideoState: VideoStateType
203}
204
205export type VideoStudioTaskCutPayload = VideoStudioTaskCut
206
207export type VideoStudioTaskIntroPayload = {
208 name: 'add-intro'
209
210 options: {
211 file: string
212 }
213}
214
215export type VideoStudioTaskOutroPayload = {
216 name: 'add-outro'
217
218 options: {
219 file: string
220 }
221}
222
223export type VideoStudioTaskWatermarkPayload = {
224 name: 'add-watermark'
225
226 options: {
227 file: string
228
229 watermarkSizeRatio: number
230 horitonzalMarginRatio: number
231 verticalMarginRatio: number
232 }
233}
234
235export type VideoStudioTaskPayload =
236 VideoStudioTaskCutPayload |
237 VideoStudioTaskIntroPayload |
238 VideoStudioTaskOutroPayload |
239 VideoStudioTaskWatermarkPayload
240
241export interface VideoStudioEditionPayload {
242 videoUUID: string
243 tasks: VideoStudioTaskPayload[]
244}
245
246// ---------------------------------------------------------------------------
247
248export interface VideoChannelImportPayload {
249 externalChannelUrl: string
250 videoChannelId: number
251
252 partOfChannelSyncId?: number
253}
254
255export interface AfterVideoChannelImportPayload {
256 channelSyncId: number
257}
258
259// ---------------------------------------------------------------------------
260
261export type NotifyPayload =
262 {
263 action: 'new-video'
264 videoUUID: string
265 }
266
267// ---------------------------------------------------------------------------
268
269export interface FederateVideoPayload {
270 videoUUID: string
271 isNewVideo: boolean
272}
273
274// ---------------------------------------------------------------------------
275
276export interface TranscodingJobBuilderPayload {
277 videoUUID: string
278
279 optimizeJob?: {
280 isNewVideo: boolean
281 }
282
283 // Array of jobs to create
284 jobs?: {
285 type: 'video-transcoding'
286 payload: VideoTranscodingPayload
287 priority?: number
288 }[]
289
290 // Array of sequential jobs to create
291 sequentialJobs?: {
292 type: 'video-transcoding'
293 payload: VideoTranscodingPayload
294 priority?: number
295 }[][]
296}
297
298// ---------------------------------------------------------------------------
299
300export interface GenerateStoryboardPayload {
301 videoUUID: string
302 federate: boolean
303}
diff --git a/packages/models/src/server/peertube-problem-document.model.ts b/packages/models/src/server/peertube-problem-document.model.ts
new file mode 100644
index 000000000..c717fc152
--- /dev/null
+++ b/packages/models/src/server/peertube-problem-document.model.ts
@@ -0,0 +1,32 @@
1import { HttpStatusCodeType } from '../http/http-status-codes.js'
2import { OAuth2ErrorCodeType, ServerErrorCodeType } from './server-error-code.enum.js'
3
4export interface PeerTubeProblemDocumentData {
5 'invalid-params'?: Record<string, object>
6
7 originUrl?: string
8
9 keyId?: string
10
11 targetUrl?: string
12
13 actorUrl?: string
14
15 // Feeds
16 format?: string
17 url?: string
18}
19
20export interface PeerTubeProblemDocument extends PeerTubeProblemDocumentData {
21 type: string
22 title: string
23
24 detail: string
25 // FIXME: Compat PeerTube <= 3.2
26 error: string
27
28 status: HttpStatusCodeType
29
30 docs?: string
31 code?: OAuth2ErrorCodeType | ServerErrorCodeType
32}
diff --git a/packages/models/src/server/server-config.model.ts b/packages/models/src/server/server-config.model.ts
new file mode 100644
index 000000000..a2a2bd5aa
--- /dev/null
+++ b/packages/models/src/server/server-config.model.ts
@@ -0,0 +1,305 @@
1import { ClientScriptJSON } from '../plugins/plugin-package-json.model.js'
2import { NSFWPolicyType } from '../videos/nsfw-policy.type.js'
3import { VideoPrivacyType } from '../videos/video-privacy.enum.js'
4import { BroadcastMessageLevel } from './broadcast-message-level.type.js'
5
6export interface ServerConfigPlugin {
7 name: string
8 npmName: string
9 version: string
10 description: string
11 clientScripts: { [name: string]: ClientScriptJSON }
12}
13
14export interface ServerConfigTheme extends ServerConfigPlugin {
15 css: string[]
16}
17
18export interface RegisteredExternalAuthConfig {
19 npmName: string
20 name: string
21 version: string
22 authName: string
23 authDisplayName: string
24}
25
26export interface RegisteredIdAndPassAuthConfig {
27 npmName: string
28 name: string
29 version: string
30 authName: string
31 weight: number
32}
33
34export interface ServerConfig {
35 serverVersion: string
36 serverCommit?: string
37
38 client: {
39 videos: {
40 miniature: {
41 displayAuthorAvatar: boolean
42 preferAuthorDisplayName: boolean
43 }
44 resumableUpload: {
45 maxChunkSize: number
46 }
47 }
48
49 menu: {
50 login: {
51 redirectOnSingleExternalAuth: boolean
52 }
53 }
54 }
55
56 defaults: {
57 publish: {
58 downloadEnabled: boolean
59 commentsEnabled: boolean
60 privacy: VideoPrivacyType
61 licence: number
62 }
63
64 p2p: {
65 webapp: {
66 enabled: boolean
67 }
68
69 embed: {
70 enabled: boolean
71 }
72 }
73 }
74
75 webadmin: {
76 configuration: {
77 edition: {
78 allowed: boolean
79 }
80 }
81 }
82
83 instance: {
84 name: string
85 shortDescription: string
86 isNSFW: boolean
87 defaultNSFWPolicy: NSFWPolicyType
88 defaultClientRoute: string
89 customizations: {
90 javascript: string
91 css: string
92 }
93 }
94
95 search: {
96 remoteUri: {
97 users: boolean
98 anonymous: boolean
99 }
100
101 searchIndex: {
102 enabled: boolean
103 url: string
104 disableLocalSearch: boolean
105 isDefaultSearch: boolean
106 }
107 }
108
109 plugin: {
110 registered: ServerConfigPlugin[]
111
112 registeredExternalAuths: RegisteredExternalAuthConfig[]
113
114 registeredIdAndPassAuths: RegisteredIdAndPassAuthConfig[]
115 }
116
117 theme: {
118 registered: ServerConfigTheme[]
119 default: string
120 }
121
122 email: {
123 enabled: boolean
124 }
125
126 contactForm: {
127 enabled: boolean
128 }
129
130 signup: {
131 allowed: boolean
132 allowedForCurrentIP: boolean
133 requiresEmailVerification: boolean
134 requiresApproval: boolean
135 minimumAge: number
136 }
137
138 transcoding: {
139 hls: {
140 enabled: boolean
141 }
142
143 web_videos: {
144 enabled: boolean
145 }
146
147 enabledResolutions: number[]
148
149 profile: string
150 availableProfiles: string[]
151
152 remoteRunners: {
153 enabled: boolean
154 }
155 }
156
157 live: {
158 enabled: boolean
159
160 allowReplay: boolean
161 latencySetting: {
162 enabled: boolean
163 }
164
165 maxDuration: number
166 maxInstanceLives: number
167 maxUserLives: number
168
169 transcoding: {
170 enabled: boolean
171
172 remoteRunners: {
173 enabled: boolean
174 }
175
176 enabledResolutions: number[]
177
178 profile: string
179 availableProfiles: string[]
180 }
181
182 rtmp: {
183 port: number
184 }
185 }
186
187 videoStudio: {
188 enabled: boolean
189
190 remoteRunners: {
191 enabled: boolean
192 }
193 }
194
195 videoFile: {
196 update: {
197 enabled: boolean
198 }
199 }
200
201 import: {
202 videos: {
203 http: {
204 enabled: boolean
205 }
206 torrent: {
207 enabled: boolean
208 }
209 }
210 videoChannelSynchronization: {
211 enabled: boolean
212 }
213 }
214
215 autoBlacklist: {
216 videos: {
217 ofUsers: {
218 enabled: boolean
219 }
220 }
221 }
222
223 avatar: {
224 file: {
225 size: {
226 max: number
227 }
228 extensions: string[]
229 }
230 }
231
232 banner: {
233 file: {
234 size: {
235 max: number
236 }
237 extensions: string[]
238 }
239 }
240
241 video: {
242 image: {
243 size: {
244 max: number
245 }
246 extensions: string[]
247 }
248 file: {
249 extensions: string[]
250 }
251 }
252
253 videoCaption: {
254 file: {
255 size: {
256 max: number
257 }
258 extensions: string[]
259 }
260 }
261
262 user: {
263 videoQuota: number
264 videoQuotaDaily: number
265 }
266
267 videoChannels: {
268 maxPerUser: number
269 }
270
271 trending: {
272 videos: {
273 intervalDays: number
274 algorithms: {
275 enabled: string[]
276 default: string
277 }
278 }
279 }
280
281 tracker: {
282 enabled: boolean
283 }
284
285 followings: {
286 instance: {
287 autoFollowIndex: {
288 indexUrl: string
289 }
290 }
291 }
292
293 broadcastMessage: {
294 enabled: boolean
295 message: string
296 level: BroadcastMessageLevel
297 dismissable: boolean
298 }
299
300 homepage: {
301 enabled: boolean
302 }
303}
304
305export type HTMLServerConfig = Omit<ServerConfig, 'signup'>
diff --git a/packages/models/src/server/server-debug.model.ts b/packages/models/src/server/server-debug.model.ts
new file mode 100644
index 000000000..4b731bb90
--- /dev/null
+++ b/packages/models/src/server/server-debug.model.ts
@@ -0,0 +1,4 @@
1export interface ServerDebug {
2 ip: string
3 activityPubMessagesWaiting: number
4}
diff --git a/packages/models/src/server/server-error-code.enum.ts b/packages/models/src/server/server-error-code.enum.ts
new file mode 100644
index 000000000..dc200c1ea
--- /dev/null
+++ b/packages/models/src/server/server-error-code.enum.ts
@@ -0,0 +1,92 @@
1export const ServerErrorCode = {
2 /**
3 * The simplest form of payload too large: when the file size is over the
4 * global file size limit
5 */
6 MAX_FILE_SIZE_REACHED:'max_file_size_reached',
7
8 /**
9 * The payload is too large for the user quota set
10 */
11 QUOTA_REACHED:'quota_reached',
12
13 /**
14 * Error yielded upon trying to access a video that is not federated, nor can
15 * be. This may be due to: remote videos on instances that are not followed by
16 * yours, and with your instance disallowing unknown instances being accessed.
17 */
18 DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS:'does_not_respect_follow_constraints',
19
20 LIVE_NOT_ENABLED:'live_not_enabled',
21 LIVE_NOT_ALLOWING_REPLAY:'live_not_allowing_replay',
22 LIVE_CONFLICTING_PERMANENT_AND_SAVE_REPLAY:'live_conflicting_permanent_and_save_replay',
23 /**
24 * Pretty self-explanatory: the set maximum number of simultaneous lives was
25 * reached, and this error is typically there to inform the user trying to
26 * broadcast one.
27 */
28 MAX_INSTANCE_LIVES_LIMIT_REACHED:'max_instance_lives_limit_reached',
29 /**
30 * Pretty self-explanatory: the set maximum number of simultaneous lives FOR
31 * THIS USER was reached, and this error is typically there to inform the user
32 * trying to broadcast one.
33 */
34 MAX_USER_LIVES_LIMIT_REACHED:'max_user_lives_limit_reached',
35
36 /**
37 * A torrent should have at most one correct video file. Any more and we will
38 * not be able to choose automatically.
39 */
40 INCORRECT_FILES_IN_TORRENT:'incorrect_files_in_torrent',
41
42 COMMENT_NOT_ASSOCIATED_TO_VIDEO:'comment_not_associated_to_video',
43
44 MISSING_TWO_FACTOR:'missing_two_factor',
45 INVALID_TWO_FACTOR:'invalid_two_factor',
46
47 ACCOUNT_WAITING_FOR_APPROVAL:'account_waiting_for_approval',
48 ACCOUNT_APPROVAL_REJECTED:'account_approval_rejected',
49
50 RUNNER_JOB_NOT_IN_PROCESSING_STATE:'runner_job_not_in_processing_state',
51 RUNNER_JOB_NOT_IN_PENDING_STATE:'runner_job_not_in_pending_state',
52 UNKNOWN_RUNNER_TOKEN:'unknown_runner_token',
53
54 VIDEO_REQUIRES_PASSWORD:'video_requires_password',
55 INCORRECT_VIDEO_PASSWORD:'incorrect_video_password',
56
57 VIDEO_ALREADY_BEING_TRANSCODED:'video_already_being_transcoded'
58} as const
59
60/**
61 * oauthjs/oauth2-server error codes
62 * @see https://datatracker.ietf.org/doc/html/rfc6749#section-5.2
63 **/
64export const OAuth2ErrorCode = {
65 /**
66 * The provided authorization grant (e.g., authorization code, resource owner
67 * credentials) or refresh token is invalid, expired, revoked, does not match
68 * the redirection URI used in the authorization request, or was issued to
69 * another client.
70 *
71 * @see https://github.com/oauthjs/node-oauth2-server/blob/master/lib/errors/invalid-grant-error.js
72 */
73 INVALID_GRANT: 'invalid_grant',
74
75 /**
76 * Client authentication failed (e.g., unknown client, no client authentication
77 * included, or unsupported authentication method).
78 *
79 * @see https://github.com/oauthjs/node-oauth2-server/blob/master/lib/errors/invalid-client-error.js
80 */
81 INVALID_CLIENT: 'invalid_client',
82
83 /**
84 * The access token provided is expired, revoked, malformed, or invalid for other reasons
85 *
86 * @see https://github.com/oauthjs/node-oauth2-server/blob/master/lib/errors/invalid-token-error.js
87 */
88 INVALID_TOKEN: 'invalid_token'
89} as const
90
91export type OAuth2ErrorCodeType = typeof OAuth2ErrorCode[keyof typeof OAuth2ErrorCode]
92export type ServerErrorCodeType = typeof ServerErrorCode[keyof typeof ServerErrorCode]
diff --git a/packages/models/src/server/server-follow-create.model.ts b/packages/models/src/server/server-follow-create.model.ts
new file mode 100644
index 000000000..3f90c7d6f
--- /dev/null
+++ b/packages/models/src/server/server-follow-create.model.ts
@@ -0,0 +1,4 @@
1export interface ServerFollowCreate {
2 hosts?: string[]
3 handles?: string[]
4}
diff --git a/packages/models/src/server/server-log-level.type.ts b/packages/models/src/server/server-log-level.type.ts
new file mode 100644
index 000000000..f0f31a4ae
--- /dev/null
+++ b/packages/models/src/server/server-log-level.type.ts
@@ -0,0 +1 @@
export type ServerLogLevel = 'debug' | 'info' | 'warn' | 'error' | 'audit'
diff --git a/packages/models/src/server/server-stats.model.ts b/packages/models/src/server/server-stats.model.ts
new file mode 100644
index 000000000..5870ee73d
--- /dev/null
+++ b/packages/models/src/server/server-stats.model.ts
@@ -0,0 +1,47 @@
1import { ActivityType } from '../activitypub/index.js'
2import { VideoRedundancyStrategyWithManual } from '../redundancy/index.js'
3
4type ActivityPubMessagesSuccess = Record<`totalActivityPub${ActivityType}MessagesSuccesses`, number>
5type ActivityPubMessagesErrors = Record<`totalActivityPub${ActivityType}MessagesErrors`, number>
6
7export interface ServerStats extends ActivityPubMessagesSuccess, ActivityPubMessagesErrors {
8 totalUsers: number
9 totalDailyActiveUsers: number
10 totalWeeklyActiveUsers: number
11 totalMonthlyActiveUsers: number
12
13 totalLocalVideos: number
14 totalLocalVideoViews: number
15 totalLocalVideoComments: number
16 totalLocalVideoFilesSize: number
17
18 totalVideos: number
19 totalVideoComments: number
20
21 totalLocalVideoChannels: number
22 totalLocalDailyActiveVideoChannels: number
23 totalLocalWeeklyActiveVideoChannels: number
24 totalLocalMonthlyActiveVideoChannels: number
25
26 totalLocalPlaylists: number
27
28 totalInstanceFollowers: number
29 totalInstanceFollowing: number
30
31 videosRedundancy: VideosRedundancyStats[]
32
33 totalActivityPubMessagesProcessed: number
34 totalActivityPubMessagesSuccesses: number
35 totalActivityPubMessagesErrors: number
36
37 activityPubMessagesProcessedPerSecond: number
38 totalActivityPubMessagesWaiting: number
39}
40
41export interface VideosRedundancyStats {
42 strategy: VideoRedundancyStrategyWithManual
43 totalSize: number
44 totalUsed: number
45 totalVideoFiles: number
46 totalVideos: number
47}