pull/6266/head
Chocobozzz 2024-02-22 10:12:04 +01:00
parent 780f17f116
commit 9e2700b89d
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
108 changed files with 315 additions and 359 deletions

View File

@ -118,6 +118,8 @@
"@typescript-eslint/consistent-type-exports": "off",
"@typescript-eslint/key-spacing": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/ban-types": [
"error",
{

View File

@ -61,7 +61,7 @@ export function downloadFile (options: {
// ---------------------------------------------------------------------------
function getRequest (url: string) {
if (url.startsWith('https://')) return https.request
if (url.startsWith('https://')) return https.request.bind(https)
return http.request
return http.request.bind(http)
}

View File

@ -160,7 +160,11 @@
"error",
"consistent-as-needed"
],
"no-constant-binary-expression": "error"
"no-constant-binary-expression": "error",
"@typescript-eslint/unbound-method": [
"error",
{ "ignoreStatic": true }
]
}
},
{

View File

@ -2,7 +2,6 @@
"extends": "stylelint-config-sass-guidelines",
"rules": {
"scss/at-import-no-partial-leading-underscore": null,
"color-hex-case": null,
"color-hex-length": null,
"selector-pseudo-element-no-unknown": [
true,
@ -19,10 +18,10 @@
"selector-max-compound-selectors": 9,
"selector-no-qualifying-type": null,
"scss/at-extend-no-missing-placeholder": null,
"number-leading-zero": null,
"rule-empty-line-before": null,
"selector-max-id": null,
"scss/at-function-pattern": null,
"scss/load-no-partial-leading-underscore": null,
"property-no-vendor-prefix": [
true,
{

View File

@ -51,15 +51,15 @@ describe('Videos list', () => {
async function checkCommonVideoListPages (policy: NSFWPolicy) {
const promisesWithFilters = [
videoListPage.goOnRootAccount,
videoListPage.goOnLocal,
videoListPage.goOnRecentlyAdded,
videoListPage.goOnTrending,
videoListPage.goOnRootChannel
videoListPage.goOnRootAccount.bind(videoListPage),
videoListPage.goOnLocal.bind(videoListPage),
videoListPage.goOnRecentlyAdded.bind(videoListPage),
videoListPage.goOnTrending.bind(videoListPage),
videoListPage.goOnRootChannel.bind(videoListPage)
]
for (const p of promisesWithFilters) {
await p.call(videoListPage)
await p()
const filter = await videoListPage.getNSFWFilter()
const filterText = await filter.getText()
@ -69,11 +69,11 @@ describe('Videos list', () => {
}
const promisesWithoutFilters = [
videoListPage.goOnRootAccountChannels,
videoListPage.goOnHomepage
videoListPage.goOnRootAccountChannels.bind(videoListPage),
videoListPage.goOnHomepage.bind(videoListPage)
]
for (const p of promisesWithoutFilters) {
await p.call(videoListPage)
await p()
await checkNormalVideo()
await checkNSFWVideo(policy)

View File

@ -109,6 +109,7 @@
"linkifyjs": "^4.0.2",
"lodash-es": "^4.17.4",
"markdown-it": "14.0.0",
"markdown-it-emoji": "^3.0.0",
"mini-css-extract-plugin": "^2.2.0",
"ngx-uploadx": "^6.1.0",
"path-browserify": "^1.0.0",

View File

@ -35,8 +35,8 @@ export class JobService {
return this.authHttp.get<ResultList<Job>>(JobService.BASE_JOB_URL + `/${jobState || ''}`, { params })
.pipe(
map(res => this.restExtractor.convertResultListDateToHuman(res, [ 'createdAt', 'processedOn', 'finishedOn' ], 'precise')),
map(res => this.restExtractor.applyToResultListData(res, this.prettyPrintData)),
map(res => this.restExtractor.applyToResultListData(res, this.buildUniqId)),
map(res => this.restExtractor.applyToResultListData(res, this.prettyPrintData.bind(this))),
map(res => this.restExtractor.applyToResultListData(res, this.buildUniqId.bind(this))),
catchError(err => this.restExtractor.handleError(err))
)
}

View File

@ -104,22 +104,22 @@ export class VideoRateComponent implements OnInit, OnChanges, OnDestroy {
private setRating (nextRating: UserVideoRateType) {
const ratingMethods: { [id in UserVideoRateType]: (id: string, videoPassword: string) => Observable<any> } = {
like: this.videoService.setVideoLike,
dislike: this.videoService.setVideoDislike,
none: this.videoService.unsetVideoLike
like: this.videoService.setVideoLike.bind(this.videoService),
dislike: this.videoService.setVideoDislike.bind(this.videoService),
none: this.videoService.unsetVideoLike.bind(this.videoService)
}
ratingMethods[nextRating].call(this.videoService, this.video.uuid, this.videoPassword)
.subscribe({
next: () => {
// Update the video like attribute
this.updateVideoRating(this.userRating, nextRating)
this.userRating = nextRating
this.rateUpdated.emit(this.userRating)
},
ratingMethods[nextRating](this.video.uuid, this.videoPassword)
.subscribe({
next: () => {
// Update the video like attribute
this.updateVideoRating(this.userRating, nextRating)
this.userRating = nextRating
this.rateUpdated.emit(this.userRating)
},
error: err => this.notifier.error(err.message)
})
error: err => this.notifier.error(err.message)
})
}
private updateVideoRating (oldRating: UserVideoRateType, newRating: UserVideoRateType) {

View File

@ -85,7 +85,7 @@ export class VideoCommentAddComponent extends FormReactive implements OnChanges,
getEmojiMarkupList () {
if (this.emojiMarkupList) return this.emojiMarkupList
const emojiMarkupObjectList = require('markdown-it-emoji/lib/data/light.json')
const emojiMarkupObjectList = require('markdown-it-emoji/lib/data/light.mjs').default
this.emojiMarkupList = []
for (const name of Object.keys(emojiMarkupObjectList)) {

View File

@ -200,7 +200,7 @@ routes.push({
@NgModule({
imports: [
RouterModule.forRoot(routes, {
useHash: Boolean(history.pushState) === false,
useHash: false,
// Redefined in app component
scrollPositionRestoration: 'disabled',
preloadingStrategy: PreloadSelectedModulesList,

View File

@ -32,7 +32,7 @@ export class RestExtractor {
fieldsToConvert: string[] = [ 'createdAt' ],
format?: DateFormat
): ResultList<T> {
return this.applyToResultListData(result, this.convertDateToHuman, [ fieldsToConvert, format ])
return this.applyToResultListData(result, this.convertDateToHuman.bind(this), [ fieldsToConvert, format ])
}
convertDateToHuman (target: any, fieldsToConvert: string[], format?: DateFormat) {

View File

@ -3,7 +3,7 @@ import { MenuService } from '../menu'
import { ScreenService } from '../wrappers'
abstract class MenuGuard {
canDeactivate = this.canActivate
canDeactivate = this.canActivate.bind(this)
constructor (protected menu: MenuService, protected screen: ScreenService, protected display: boolean) {

View File

@ -244,8 +244,10 @@ export class MenuComponent implements OnInit, OnDestroy {
if (opened) {
window.addEventListener('scroll', onWindowScroll)
document.querySelector('nav').scrollTo(0, 0) // Reset menu scroll to easy lock
// eslint-disable-next-line @typescript-eslint/unbound-method
document.querySelector('nav').addEventListener('scroll', this.onMenuScrollEvent)
} else {
// eslint-disable-next-line @typescript-eslint/unbound-method
document.querySelector('nav').removeEventListener('scroll', this.onMenuScrollEvent)
}
}

View File

@ -67,6 +67,7 @@ export class NotificationComponent implements OnInit, OnDestroy {
this.opened = true
document.querySelector('nav').scrollTo(0, 0) // Reset menu scroll to easy lock
// eslint-disable-next-line @typescript-eslint/unbound-method
document.querySelector('nav').addEventListener('scroll', this.onMenuScrollEvent)
}
@ -74,6 +75,7 @@ export class NotificationComponent implements OnInit, OnDestroy {
this.loaded = false
this.opened = false
// eslint-disable-next-line @typescript-eslint/unbound-method
document.querySelector('nav').removeEventListener('scroll', this.onMenuScrollEvent)
}

View File

@ -41,12 +41,12 @@ export class VideoOwnershipService {
acceptOwnership (id: number, input: VideoChangeOwnershipAccept) {
const url = VideoOwnershipService.BASE_VIDEO_CHANGE_OWNERSHIP_URL + 'ownership/' + id + '/accept'
return this.authHttp.post(url, input)
.pipe(catchError(this.restExtractor.handleError))
.pipe(catchError(err => this.restExtractor.handleError(err)))
}
refuseOwnership (id: number) {
const url = VideoOwnershipService.BASE_VIDEO_CHANGE_OWNERSHIP_URL + 'ownership/' + id + '/refuse'
return this.authHttp.post(url, {})
.pipe(catchError(this.restExtractor.handleError))
.pipe(catchError(err => this.restExtractor.handleError(err)))
}
}

View File

@ -244,6 +244,7 @@ class SettingsButton extends Button {
// Hide children to avoid sub menus stacking on top of each other
// or having multiple menus open
// eslint-disable-next-line @typescript-eslint/unbound-method
settingsMenuItem.on('click', videojs.bind(this, this.hideChildren))
// Whether to add or remove selected class on the settings sub menu element

View File

@ -6,4 +6,4 @@ interface NodeModule {
id: string
}
declare module 'markdown-it-emoji/light'
declare module 'markdown-it-emoji/lib/light.mjs'

View File

@ -7555,6 +7555,11 @@ map-stream@~0.1.0:
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==
markdown-it-emoji@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/markdown-it-emoji/-/markdown-it-emoji-3.0.0.tgz#8475a04d671d7c93f931b76fb90c582768b7f0b5"
integrity sha512-+rUD93bXHubA4arpEZO3q80so0qgoFJEKRkRbjKX8RTdca89v2kfyF+xR3i2sQTwql9tpPZPOQN5B+PunspXRg==
markdown-it@14.0.0:
version "14.0.0"
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.0.0.tgz#b4b2ddeb0f925e88d981f84c183b59bac9e3741b"

View File

@ -18,8 +18,8 @@ async function waitJobs (
let servers: PeerTubeServer[]
if (Array.isArray(serversArg) === false) servers = [ serversArg as PeerTubeServer ]
else servers = serversArg as PeerTubeServer[]
if (Array.isArray(serversArg) === false) servers = [ serversArg ]
else servers = serversArg
const states: JobState[] = [ 'waiting', 'active' ]
if (!skipDelayed) states.push('delayed')

View File

@ -35,6 +35,7 @@ async function cleanupTests (servers: PeerTubeServer[]) {
for (const server of servers) {
if (!server) continue
// eslint-disable-next-line @typescript-eslint/no-floating-promises
p = p.concat(server.servers.cleanupTests())
}

View File

@ -149,7 +149,7 @@ describe('Test my user API validators', function () {
await makePutBodyRequest({
url: server.url,
path: path + 'me',
token: 'super token',
token: 'supertoken',
fields,
expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})

View File

@ -187,7 +187,7 @@ describe('Test users admin API validators', function () {
await makePostBodyRequest({
url: server.url,
path,
token: 'super token',
token: 'supertoken',
fields: baseCorrectParams,
expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
@ -309,7 +309,7 @@ describe('Test users admin API validators', function () {
await makeGetRequest({
url: server.url,
path: path + userId,
token: 'super token',
token: 'supertoken',
expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
@ -383,7 +383,7 @@ describe('Test users admin API validators', function () {
await makePutBodyRequest({
url: server.url,
path: path + userId,
token: 'super token',
token: 'supertoken',
fields,
expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})

View File

@ -226,7 +226,7 @@ describe('Test video blacklist API validators', function () {
it('Should fail with a non authenticated user', async function () {
await command.remove({
token: 'fake token',
token: 'faketoken',
videoId: servers[0].store.videoCreated.uuid,
expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
@ -258,7 +258,7 @@ describe('Test video blacklist API validators', function () {
const basePath = '/api/v1/videos/blacklist/'
it('Should fail with a non authenticated user', async function () {
await servers[0].blacklist.list({ token: 'fake token', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
await servers[0].blacklist.list({ token: 'faketoken', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
})
it('Should fail with a non admin user', async function () {

View File

@ -24,6 +24,7 @@ describe('Test video NSFW policy', function () {
let promises: Promise<ResultList<Video>>[]
if (token) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
promises = [
server.search.advancedVideoSearch({ token, search: { search: 'n', sort: '-publishedAt', ...query } }),
server.videos.listWithToken({ token, ...query }),
@ -34,13 +35,14 @@ describe('Test video NSFW policy', function () {
// Overviews do not support video filters
if (!hasQuery) {
const p = server.overviews.getVideos({ page: 1, token })
.then(res => createOverviewRes(res))
.then(res => createOverviewRes(res))
promises.push(p)
}
return Promise.all(promises)
}
// eslint-disable-next-line @typescript-eslint/no-floating-promises
promises = [
server.search.searchVideos({ search: 'n', sort: '-publishedAt' }),
server.videos.list(),
@ -51,7 +53,8 @@ describe('Test video NSFW policy', function () {
// Overviews do not support video filters
if (!hasQuery) {
const p = server.overviews.getVideos({ page: 1 })
.then(res => createOverviewRes(res))
.then(res => createOverviewRes(res))
promises.push(p)
}

View File

@ -226,7 +226,7 @@ async function listAccountVideos (req: express.Request, res: express.Response) {
}, 'filter:api.accounts.videos.list.params')
const resultList = await Hooks.wrapPromiseFun(
VideoModel.listForApi,
VideoModel.listForApi.bind(VideoModel),
apiOptions,
'filter:api.accounts.videos.list.result'
)

View File

@ -130,7 +130,7 @@ async function getVideos (
}, 'filter:api.overviews.videos.list.params')
const { data } = await Hooks.wrapPromiseFun(
VideoModel.listForApi,
VideoModel.listForApi.bind(VideoModel),
query,
'filter:api.overviews.videos.list.result'
)

View File

@ -102,7 +102,7 @@ async function searchVideoChannelsDB (query: VideoChannelsSearchQueryAfterSaniti
}, 'filter:api.search.video-channels.local.list.params')
const resultList = await Hooks.wrapPromiseFun(
VideoChannelModel.searchForApi,
VideoChannelModel.searchForApi.bind(VideoChannelModel),
apiOptions,
'filter:api.search.video-channels.local.list.result'
)

View File

@ -93,7 +93,7 @@ async function searchVideoPlaylistsDB (query: VideoPlaylistsSearchQueryAfterSani
}, 'filter:api.search.video-playlists.local.list.params')
const resultList = await Hooks.wrapPromiseFun(
VideoPlaylistModel.searchForApi,
VideoPlaylistModel.searchForApi.bind(VideoPlaylistModel),
apiOptions,
'filter:api.search.video-playlists.local.list.result'
)

View File

@ -121,7 +121,7 @@ async function searchVideosDB (query: VideosSearchQueryAfterSanitize, req: expre
}, 'filter:api.search.videos.local.list.params')
const resultList = await Hooks.wrapPromiseFun(
VideoModel.searchAndPopulateAccountAndServer,
VideoModel.searchAndPopulateAccountAndServer.bind(VideoModel),
apiOptions,
'filter:api.search.videos.local.list.result'
)

View File

@ -131,7 +131,7 @@ async function getUserVideos (req: express.Request, res: express.Response) {
}, 'filter:api.user.me.videos.list.params')
const resultList = await Hooks.wrapPromiseFun(
VideoModel.listUserVideosForApi,
VideoModel.listUserVideosForApi.bind(VideoModel),
apiOptions,
'filter:api.user.me.videos.list.result'
)

View File

@ -184,7 +184,7 @@ async function getUserSubscriptionVideos (req: express.Request, res: express.Res
}, 'filter:api.user.me.subscription-videos.list.params')
const resultList = await Hooks.wrapPromiseFun(
VideoModel.listForApi,
VideoModel.listForApi.bind(VideoModel),
apiOptions,
'filter:api.user.me.subscription-videos.list.result'
)

View File

@ -200,7 +200,7 @@ async function listVideoChannels (req: express.Request, res: express.Response) {
}, 'filter:api.video-channels.list.params')
const resultList = await Hooks.wrapPromiseFun(
VideoChannelModel.listForApi,
VideoChannelModel.listForApi.bind(VideoChannelModel),
apiOptions,
'filter:api.video-channels.list.result'
)
@ -409,7 +409,7 @@ async function listVideoChannelVideos (req: express.Request, res: express.Respon
}, 'filter:api.video-channels.videos.list.params')
const resultList = await Hooks.wrapPromiseFun(
VideoModel.listForApi,
VideoModel.listForApi.bind(VideoModel),
apiOptions,
'filter:api.video-channels.videos.list.result'
)

View File

@ -472,7 +472,7 @@ async function getVideoPlaylistVideos (req: express.Request, res: express.Respon
}, 'filter:api.video-playlist.videos.list.params')
const resultList = await Hooks.wrapPromiseFun(
VideoPlaylistElementModel.listForApi,
VideoPlaylistElementModel.listForApi.bind(VideoPlaylistElementModel),
apiOptions,
'filter:api.video-playlist.videos.list.result'
)

View File

@ -128,7 +128,7 @@ async function listVideoThreads (req: express.Request, res: express.Response) {
}, 'filter:api.video-threads.list.params')
resultList = await Hooks.wrapPromiseFun(
VideoCommentModel.listThreadsForApi,
VideoCommentModel.listThreadsForApi.bind(VideoCommentModel),
apiOptions,
'filter:api.video-threads.list.result'
)
@ -160,7 +160,7 @@ async function listVideoThreadComments (req: express.Request, res: express.Respo
}, 'filter:api.video-thread-comments.list.params')
resultList = await Hooks.wrapPromiseFun(
VideoCommentModel.listThreadCommentsForApi,
VideoCommentModel.listThreadCommentsForApi.bind(VideoCommentModel),
apiOptions,
'filter:api.video-thread-comments.list.result'
)

View File

@ -194,7 +194,7 @@ async function listVideos (req: express.Request, res: express.Response) {
}, 'filter:api.videos.list.params')
const resultList = await Hooks.wrapPromiseFun(
VideoModel.listForApi,
VideoModel.listForApi.bind(VideoModel),
apiOptions,
'filter:api.videos.list.result'
)

View File

@ -133,7 +133,7 @@ async function downloadVideoFile (req: express.Request, res: express.Response) {
async function downloadHLSVideoFile (req: express.Request, res: express.Response) {
const video = res.locals.videoAll
const streamingPlaylist = getHLSPlaylist(video)
if (!streamingPlaylist) return res.status(HttpStatusCode.NOT_FOUND_404).end
if (!streamingPlaylist) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
const videoFile = getVideoFile(req, streamingPlaylist.VideoFiles)
if (!videoFile) {

View File

@ -121,10 +121,10 @@ const bunyanLogger = {
// ---------------------------------------------------------------------------
type LoggerTags = { tags: string[] }
type LoggerTagsFn = (...tags: string[]) => LoggerTags
function loggerTagsFactory (...defaultTags: string[]): LoggerTagsFn {
return (...tags: string[]) => {
type LoggerTags = { tags: (string | number)[] }
type LoggerTagsFn = (...tags: (string | number)[]) => LoggerTags
function loggerTagsFactory (...defaultTags: (string | number)[]): LoggerTagsFn {
return (...tags: (string | number)[]) => {
return { tags: defaultTags.concat(tags) }
}
}

View File

@ -14,7 +14,7 @@ export abstract class AbstractSimpleFileCache <T> {
protected abstract loadRemoteFile (key: string): Promise<GetFilePathResult>
init (max: number, maxAge: number) {
this.getFilePath = memoizee(this.getFilePathImpl, {
this.getFilePath = memoizee(this.getFilePathImpl.bind(this), {
maxAge,
max,
promise: true,

View File

@ -7,7 +7,7 @@ import { MVideoWithAllFiles } from '@server/types/models/index.js'
export async function moveToJob (options: {
jobId: string
videoUUID: string
loggerTags: string[]
loggerTags: (number | string)[]
moveWebVideoFiles: (video: MVideoWithAllFiles) => Promise<void>
moveHLSFiles: (video: MVideoWithAllFiles) => Promise<void>

View File

@ -95,7 +95,7 @@ type TaskProcessorOptions <T extends VideoStudioTaskPayload = VideoStudioTaskPay
outputPath: string
video: MVideo
task: T
lTags: { tags: string[] }
lTags: { tags: (string | number)[] }
}
const taskProcessors: { [id in VideoStudioTask['name']]: (options: TaskProcessorOptions) => Promise<any> } = {

View File

@ -86,7 +86,7 @@ class LiveManager {
.catch(err => logger.error('Cannot handle sessions.', { err, ...lTags(sessionId) }))
})
events.on('donePublish', sessionId => {
events.on('donePublish', (sessionId: string) => {
logger.info('Live session ended.', { sessionId, ...lTags(sessionId) })
// Force session aborting, so we kill ffmpeg even if it still has data to process (slow CPU)
@ -405,7 +405,7 @@ class LiveManager {
})
}
private async publishAndFederateLive (live: MVideoLiveVideo, localLTags: { tags: string[] }) {
private async publishAndFederateLive (live: MVideoLiveVideo, localLTags: { tags: (string | number)[] }) {
const videoId = live.videoId
try {

View File

@ -11,7 +11,7 @@ import { getInternalUrl } from '../urls.js'
import { getClient } from './client.js'
import { lTags } from './logger.js'
import type { _Object, CompleteMultipartUploadCommandOutput, ObjectCannedACL, PutObjectCommandInput, S3Client } from '@aws-sdk/client-s3'
import type { _Object, ObjectCannedACL, PutObjectCommandInput, S3Client } from '@aws-sdk/client-s3'
type BucketInfo = {
BUCKET_NAME: string
@ -317,7 +317,7 @@ async function uploadToStorage (options: {
params: input
})
const response = (await parallelUploads3.done()) as CompleteMultipartUploadCommandOutput
const response = await parallelUploads3.done()
// Check is needed even if the HTTP status code is 200 OK
// For more information, see https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html
if (!response.Bucket) {

View File

@ -42,14 +42,16 @@ class PeerTubeSocket {
this.liveVideosNamespace = io.of('/live-videos')
.on('connection', socket => {
socket.on('subscribe', ({ videoId }) => {
socket.on('subscribe', params => {
const videoId = params.videoId + ''
if (!isIdValid(videoId)) return
/* eslint-disable @typescript-eslint/no-floating-promises */
socket.join(videoId)
})
socket.on('unsubscribe', ({ videoId }) => {
socket.on('unsubscribe', params => {
const videoId = params.videoId + ''
if (!isIdValid(videoId)) return
/* eslint-disable @typescript-eslint/no-floating-promises */
@ -93,7 +95,7 @@ class PeerTubeSocket {
logger.debug('Sending video live new state notification of %s.', video.url, { state: video.state })
this.liveVideosNamespace
.in(video.id)
.in(video.id + '')
.emit(type, data)
}
@ -104,7 +106,7 @@ class PeerTubeSocket {
logger.debug('Sending video live views update notification of %s.', video.url, { viewers: numViewers })
this.liveVideosNamespace
.in(video.id)
.in(video.id + '')
.emit(type, data)
}

View File

@ -15,7 +15,7 @@ function asyncMiddleware (fun: RequestPromiseHandler | RequestPromiseHandler[])
}
try {
for (const f of (fun as RequestPromiseHandler[])) {
for (const f of fun) {
await new Promise<void>((resolve, reject) => {
return asyncMiddleware(f)(req, res, err => {
if (err) return reject(err)

View File

@ -189,9 +189,9 @@ export class ApiCache {
const self = this
res.locals.apicache = {
write: res.write,
writeHead: res.writeHead,
end: res.end,
write: res.write.bind(res),
writeHead: res.writeHead.bind(res),
end: res.end.bind(res),
cacheable: true,
content: undefined,
headers: undefined

View File

@ -9,7 +9,7 @@ function areValidationErrors (
options: {
omitLog?: boolean
omitBodyLog?: boolean
tags?: string[]
tags?: (number | string)[]
} = {}) {
const { omitLog = false, omitBodyLog = false, tags = [] } = options

View File

@ -1,11 +1,10 @@
import { FindOptions } from 'sequelize'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Table, UpdatedAt } from 'sequelize-typescript'
import { isAbuseMessageValid } from '@server/helpers/custom-validators/abuses.js'
import { MAbuseMessage, MAbuseMessageFormattable } from '@server/types/models/index.js'
import { AbuseMessage } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { AccountModel, ScopeNames as AccountScopeNames } from '../account/account.js'
import { getSort, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, getSort, throwIfNotValid } from '../shared/index.js'
import { AbuseModel } from './abuse.js'
@Table({
@ -19,7 +18,7 @@ import { AbuseModel } from './abuse.js'
}
]
})
export class AbuseMessageModel extends Model<Partial<AttributesOnly<AbuseMessageModel>>> {
export class AbuseMessageModel extends SequelizeModel<AbuseMessageModel> {
@AllowNull(false)
@Is('AbuseMessage', value => throwIfNotValid(value, isAbuseMessageValid, 'message'))

View File

@ -12,7 +12,6 @@ import {
UserVideoAbuse,
type AbuseStateType
} from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses.js'
import invert from 'lodash-es/invert.js'
import { Op, QueryTypes, literal } from 'sequelize'
@ -25,9 +24,7 @@ import {
Default,
ForeignKey,
HasOne,
Is,
Model,
Scopes,
Is, Scopes,
Table,
UpdatedAt
} from 'sequelize-typescript'
@ -41,7 +38,7 @@ import {
MUserAccountId
} from '../../types/models/index.js'
import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account.js'
import { getSort, parseAggregateResult, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, getSort, parseAggregateResult, throwIfNotValid } from '../shared/index.js'
import { ThumbnailModel } from '../video/thumbnail.js'
import { VideoBlacklistModel } from '../video/video-blacklist.js'
import { SummaryOptions as ChannelSummaryOptions, VideoChannelModel, ScopeNames as VideoChannelScopeNames } from '../video/video-channel.js'
@ -195,7 +192,7 @@ export enum ScopeNames {
}
]
})
export class AbuseModel extends Model<Partial<AttributesOnly<AbuseModel>>> {
export class AbuseModel extends SequelizeModel<AbuseModel> {
@AllowNull(false)
@Default(null)

View File

@ -1,8 +1,8 @@
import { type VideoDetails } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Table, UpdatedAt } from 'sequelize-typescript'
import { VideoModel } from '../video/video.js'
import { AbuseModel } from './abuse.js'
import { SequelizeModel } from '../shared/index.js'
@Table({
tableName: 'videoAbuse',
@ -15,7 +15,7 @@ import { AbuseModel } from './abuse.js'
}
]
})
export class VideoAbuseModel extends Model<Partial<AttributesOnly<VideoAbuseModel>>> {
export class VideoAbuseModel extends SequelizeModel<VideoAbuseModel> {
@CreatedAt
createdAt: Date

View File

@ -1,7 +1,7 @@
import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { BelongsTo, Column, CreatedAt, ForeignKey, Table, UpdatedAt } from 'sequelize-typescript'
import { VideoCommentModel } from '../video/video-comment.js'
import { AbuseModel } from './abuse.js'
import { SequelizeModel } from '../shared/index.js'
@Table({
tableName: 'commentAbuse',
@ -14,7 +14,7 @@ import { AbuseModel } from './abuse.js'
}
]
})
export class VideoCommentAbuseModel extends Model<Partial<AttributesOnly<VideoCommentAbuseModel>>> {
export class VideoCommentAbuseModel extends SequelizeModel<VideoCommentAbuseModel> {
@CreatedAt
createdAt: Date

View File

@ -1,12 +1,11 @@
import { FindOptions, Op, QueryTypes } from 'sequelize'
import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { BelongsTo, Column, CreatedAt, ForeignKey, Table, UpdatedAt } from 'sequelize-typescript'
import { AccountBlock } from '@peertube/peertube-models'
import { handlesToNameAndHost } from '@server/helpers/actors.js'
import { MAccountBlocklist, MAccountBlocklistFormattable } from '@server/types/models/index.js'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { ActorModel } from '../actor/actor.js'
import { ServerModel } from '../server/server.js'
import { createSafeIn, getSort, searchAttribute } from '../shared/index.js'
import { SequelizeModel, createSafeIn, getSort, searchAttribute } from '../shared/index.js'
import { AccountModel } from './account.js'
import { WEBSERVER } from '@server/initializers/constants.js'
@ -22,7 +21,7 @@ import { WEBSERVER } from '@server/initializers/constants.js'
}
]
})
export class AccountBlocklistModel extends Model<Partial<AttributesOnly<AccountBlocklistModel>>> {
export class AccountBlocklistModel extends SequelizeModel<AccountBlocklistModel> {
@CreatedAt
createdAt: Date

View File

@ -1,5 +1,4 @@
import { AccountVideoRate, type VideoRateType } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import {
MAccountVideoRate,
MAccountVideoRateAccountUrl,
@ -8,11 +7,11 @@ import {
MAccountVideoRateVideoUrl
} from '@server/types/models/index.js'
import { FindOptions, Op, QueryTypes, Transaction } from 'sequelize'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Table, UpdatedAt } from 'sequelize-typescript'
import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc.js'
import { CONSTRAINTS_FIELDS, VIDEO_RATE_TYPES } from '../../initializers/constants.js'
import { ActorModel } from '../actor/actor.js'
import { getSort, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, getSort, throwIfNotValid } from '../shared/index.js'
import { SummaryOptions, VideoChannelModel, ScopeNames as VideoChannelScopeNames } from '../video/video-channel.js'
import { VideoModel } from '../video/video.js'
import { AccountModel } from './account.js'
@ -42,7 +41,7 @@ import { AccountModel } from './account.js'
}
]
})
export class AccountVideoRateModel extends Model<Partial<AttributesOnly<AccountVideoRateModel>>> {
export class AccountVideoRateModel extends SequelizeModel<AccountVideoRateModel> {
@AllowNull(false)
@Column(DataType.ENUM(...Object.values(VIDEO_RATE_TYPES)))

View File

@ -10,15 +10,12 @@ import {
DefaultScope,
ForeignKey,
HasMany,
Is,
Model,
Scopes,
Is, Scopes,
Table,
UpdatedAt
} from 'sequelize-typescript'
import { Account, AccountSummary } from '@peertube/peertube-models'
import { ModelCache } from '@server/models/shared/model-cache.js'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { isAccountDescriptionValid } from '../../helpers/custom-validators/accounts.js'
import { CONSTRAINTS_FIELDS, SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants.js'
import { sendDeleteActor } from '../../lib/activitypub/send/send-delete.js'
@ -36,7 +33,7 @@ import { ActorModel } from '../actor/actor.js'
import { ApplicationModel } from '../application/application.js'
import { ServerBlocklistModel } from '../server/server-blocklist.js'
import { ServerModel } from '../server/server.js'
import { buildSQLAttributes, getSort, throwIfNotValid } from '../shared/index.js'
import { buildSQLAttributes, getSort, SequelizeModel, throwIfNotValid } from '../shared/index.js'
import { UserModel } from '../user/user.js'
import { VideoChannelModel } from '../video/video-channel.js'
import { VideoCommentModel } from '../video/video-comment.js'
@ -144,7 +141,7 @@ export type SummaryOptions = {
}
]
})
export class AccountModel extends Model<Partial<AttributesOnly<AccountModel>>> {
export class AccountModel extends SequelizeModel<AccountModel> {
@AllowNull(false)
@Column

View File

@ -1,7 +1,8 @@
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Table, UpdatedAt } from 'sequelize-typescript'
import { CustomPage } from '@peertube/peertube-models'
import { ActorModel } from '../actor/actor.js'
import { getServerActor } from '../application/application.js'
import { SequelizeModel } from '../shared/index.js'
@Table({
tableName: 'actorCustomPage',
@ -12,7 +13,7 @@ import { getServerActor } from '../application/application.js'
}
]
})
export class ActorCustomPageModel extends Model {
export class ActorCustomPageModel extends SequelizeModel<ActorCustomPageModel> {
@AllowNull(true)
@Column(DataType.TEXT)

View File

@ -1,5 +1,4 @@
import { ActorFollow, type FollowState } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { isActivityPubUrlValid } from '@server/helpers/custom-validators/activitypub/misc.js'
import { afterCommitIfTransaction } from '@server/helpers/database-utils.js'
import { getServerActor } from '@server/models/application/application.js'
@ -27,16 +26,14 @@ import {
ForeignKey,
Is,
IsInt,
Max,
Model,
Table,
Max, Table,
UpdatedAt
} from 'sequelize-typescript'
import { logger } from '../../helpers/logger.js'
import { ACTOR_FOLLOW_SCORE, CONSTRAINTS_FIELDS, FOLLOW_STATES, SERVER_ACTOR_NAME, SORTABLE_COLUMNS } from '../../initializers/constants.js'
import { AccountModel } from '../account/account.js'
import { ServerModel } from '../server/server.js'
import { buildSQLAttributes, createSafeIn, getSort, searchAttribute, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, buildSQLAttributes, createSafeIn, getSort, searchAttribute, throwIfNotValid } from '../shared/index.js'
import { doesExist } from '../shared/query.js'
import { VideoChannelModel } from '../video/video-channel.js'
import { ActorModel, unusedActorAttributesForAPI } from './actor.js'
@ -65,7 +62,7 @@ import { InstanceListFollowingQueryBuilder, ListFollowingOptions } from './sql/i
}
]
})
export class ActorFollowModel extends Model<Partial<AttributesOnly<ActorFollowModel>>> {
export class ActorFollowModel extends SequelizeModel<ActorFollowModel> {
@AllowNull(false)
@Column(DataType.ENUM(...Object.values(FOLLOW_STATES)))

View File

@ -1,6 +1,5 @@
import { ActivityIconObject, ActorImage, ActorImageType, type ActorImageType_Type } from '@peertube/peertube-models'
import { getLowercaseExtension } from '@peertube/peertube-node-utils'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { MActorId, MActorImage, MActorImageFormattable } from '@server/types/models/index.js'
import { remove } from 'fs-extra/esm'
import { join } from 'path'
@ -12,16 +11,14 @@ import {
CreatedAt,
Default,
ForeignKey,
Is,
Model,
Table,
Is, Table,
UpdatedAt
} from 'sequelize-typescript'
import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc.js'
import { logger } from '../../helpers/logger.js'
import { CONFIG } from '../../initializers/config.js'
import { LAZY_STATIC_PATHS, MIMETYPES, WEBSERVER } from '../../initializers/constants.js'
import { buildSQLAttributes, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, buildSQLAttributes, throwIfNotValid } from '../shared/index.js'
import { ActorModel } from './actor.js'
@Table({
@ -37,7 +34,7 @@ import { ActorModel } from './actor.js'
}
]
})
export class ActorImageModel extends Model<Partial<AttributesOnly<ActorImageModel>>> {
export class ActorImageModel extends SequelizeModel<ActorImageModel> {
@AllowNull(false)
@Column

View File

@ -17,9 +17,7 @@ import {
ForeignKey,
HasMany,
HasOne,
Is,
Model,
Scopes,
Is, Scopes,
Table,
UpdatedAt
} from 'sequelize-typescript'
@ -58,7 +56,7 @@ import {
import { AccountModel } from '../account/account.js'
import { getServerActor } from '../application/application.js'
import { ServerModel } from '../server/server.js'
import { buildSQLAttributes, isOutdated, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, buildSQLAttributes, isOutdated, throwIfNotValid } from '../shared/index.js'
import { VideoChannelModel } from '../video/video-channel.js'
import { VideoModel } from '../video/video.js'
import { ActorFollowModel } from './actor-follow.js'
@ -165,7 +163,7 @@ export const unusedActorAttributesForAPI: (keyof AttributesOnly<ActorModel>)[] =
}
]
})
export class ActorModel extends Model<Partial<AttributesOnly<ActorModel>>> {
export class ActorModel extends SequelizeModel<ActorModel> {
@AllowNull(false)
@Column(DataType.ENUM(...Object.values(ACTIVITY_PUB_ACTOR_TYPES)))

View File

@ -1,8 +1,8 @@
import memoizee from 'memoizee'
import { AllowNull, Column, Default, DefaultScope, HasOne, IsInt, Model, Table } from 'sequelize-typescript'
import { AllowNull, Column, Default, DefaultScope, HasOne, IsInt, Table } from 'sequelize-typescript'
import { getNodeABIVersion } from '@server/helpers/version.js'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { AccountModel } from '../account/account.js'
import { SequelizeModel } from '../shared/index.js'
export const getServerActor = memoizee(async function () {
const application = await ApplicationModel.load()
@ -26,7 +26,7 @@ export const getServerActor = memoizee(async function () {
tableName: 'application',
timestamps: false
})
export class ApplicationModel extends Model<Partial<AttributesOnly<ApplicationModel>>> {
export class ApplicationModel extends SequelizeModel<ApplicationModel> {
@AllowNull(false)
@Default(0)

View File

@ -1,6 +1,6 @@
import { AllowNull, Column, CreatedAt, DataType, HasMany, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { AllowNull, Column, CreatedAt, DataType, HasMany, Table, UpdatedAt } from 'sequelize-typescript'
import { OAuthTokenModel } from './oauth-token.js'
import { SequelizeModel } from '../shared/index.js'
@Table({
tableName: 'oAuthClient',
@ -15,7 +15,7 @@ import { OAuthTokenModel } from './oauth-token.js'
}
]
})
export class OAuthClientModel extends Model<Partial<AttributesOnly<OAuthClientModel>>> {
export class OAuthClientModel extends SequelizeModel<OAuthClientModel> {
@AllowNull(false)
@Column

View File

@ -6,21 +6,19 @@ import {
BelongsTo,
Column,
CreatedAt,
ForeignKey,
Model,
Scopes,
ForeignKey, Scopes,
Table,
UpdatedAt
} from 'sequelize-typescript'
import { TokensCache } from '@server/lib/auth/tokens-cache.js'
import { MUserAccountId } from '@server/types/models/index.js'
import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token.js'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { logger } from '../../helpers/logger.js'
import { AccountModel } from '../account/account.js'
import { ActorModel } from '../actor/actor.js'
import { UserModel } from '../user/user.js'
import { OAuthClientModel } from './oauth-client.js'
import { SequelizeModel } from '../shared/index.js'
export type OAuthTokenInfo = {
refreshToken: string
@ -80,7 +78,7 @@ enum ScopeNames {
}
]
})
export class OAuthTokenModel extends Model<Partial<AttributesOnly<OAuthTokenModel>>> {
export class OAuthTokenModel extends SequelizeModel<OAuthTokenModel> {
@AllowNull(false)
@Column

View File

@ -8,9 +8,7 @@ import {
CreatedAt,
DataType,
ForeignKey,
Is,
Model,
Scopes,
Is, Scopes,
Table,
UpdatedAt
} from 'sequelize-typescript'
@ -26,7 +24,6 @@ import {
VideoRedundancyStrategyWithManual
} from '@peertube/peertube-models'
import { isTestInstance } from '@peertube/peertube-node-utils'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { getServerActor } from '@server/models/application/application.js'
import { MActor, MVideoForRedundancyAPI, MVideoRedundancy, MVideoRedundancyAP, MVideoRedundancyVideo } from '@server/types/models/index.js'
import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validators/activitypub/misc.js'
@ -35,7 +32,7 @@ import { CONFIG } from '../../initializers/config.js'
import { CONSTRAINTS_FIELDS } from '../../initializers/constants.js'
import { ActorModel } from '../actor/actor.js'
import { ServerModel } from '../server/server.js'
import { getSort, getVideoSort, parseAggregateResult, throwIfNotValid } from '../shared/index.js'
import { getSort, getVideoSort, parseAggregateResult, SequelizeModel, throwIfNotValid } from '../shared/index.js'
import { ScheduleVideoUpdateModel } from '../video/schedule-video-update.js'
import { VideoChannelModel } from '../video/video-channel.js'
import { VideoFileModel } from '../video/video-file.js'
@ -92,7 +89,7 @@ export enum ScopeNames {
}
]
})
export class VideoRedundancyModel extends Model<Partial<AttributesOnly<VideoRedundancyModel>>> {
export class VideoRedundancyModel extends SequelizeModel<VideoRedundancyModel> {
@CreatedAt
createdAt: Date

View File

@ -7,7 +7,6 @@ import {
type RunnerJobStateType,
type RunnerJobType
} from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { isArray, isUUIDValid } from '@server/helpers/custom-validators/misc.js'
import { CONSTRAINTS_FIELDS, RUNNER_JOB_STATES } from '@server/initializers/constants.js'
import { MRunnerJob, MRunnerJobRunner, MRunnerJobRunnerParent } from '@server/types/models/runners/index.js'
@ -20,13 +19,11 @@ import {
DataType,
Default,
ForeignKey,
IsUUID,
Model,
Scopes,
IsUUID, Scopes,
Table,
UpdatedAt
} from 'sequelize-typescript'
import { getSort, searchAttribute } from '../shared/index.js'
import { SequelizeModel, getSort, searchAttribute } from '../shared/index.js'
import { RunnerModel } from './runner.js'
enum ScopeNames {
@ -68,7 +65,7 @@ enum ScopeNames {
}
]
})
export class RunnerJobModel extends Model<Partial<AttributesOnly<RunnerJobModel>>> {
export class RunnerJobModel extends SequelizeModel<RunnerJobModel> {
@AllowNull(false)
@IsUUID(4)

View File

@ -1,9 +1,8 @@
import { FindOptions, literal } from 'sequelize'
import { AllowNull, Column, CreatedAt, HasMany, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, Column, CreatedAt, HasMany, Table, UpdatedAt } from 'sequelize-typescript'
import { MRunnerRegistrationToken } from '@server/types/models/runners/index.js'
import { RunnerRegistrationToken } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { getSort } from '../shared/index.js'
import { SequelizeModel, getSort } from '../shared/index.js'
import { RunnerModel } from './runner.js'
/**
@ -21,7 +20,7 @@ import { RunnerModel } from './runner.js'
}
]
})
export class RunnerRegistrationTokenModel extends Model<Partial<AttributesOnly<RunnerRegistrationTokenModel>>> {
export class RunnerRegistrationTokenModel extends SequelizeModel<RunnerRegistrationTokenModel> {
@AllowNull(false)
@Column

View File

@ -1,9 +1,8 @@
import { FindOptions } from 'sequelize'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Table, UpdatedAt } from 'sequelize-typescript'
import { MRunner } from '@server/types/models/runners/index.js'
import { Runner } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { getSort } from '../shared/index.js'
import { SequelizeModel, getSort } from '../shared/index.js'
import { RunnerRegistrationTokenModel } from './runner-registration-token.js'
import { CONSTRAINTS_FIELDS } from '@server/initializers/constants.js'
@ -23,7 +22,7 @@ import { CONSTRAINTS_FIELDS } from '@server/initializers/constants.js'
}
]
})
export class RunnerModel extends Model<Partial<AttributesOnly<RunnerModel>>> {
export class RunnerModel extends SequelizeModel<RunnerModel> {
// Used to identify the appropriate runner when it uses the runner REST API
@AllowNull(false)

View File

@ -6,10 +6,9 @@ import {
SettingValue,
type PluginType_Type
} from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { MPlugin, MPluginFormattable } from '@server/types/models/index.js'
import { FindAndCountOptions, json, QueryTypes } from 'sequelize'
import { AllowNull, Column, CreatedAt, DataType, DefaultScope, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, Column, CreatedAt, DataType, DefaultScope, Is, Table, UpdatedAt } from 'sequelize-typescript'
import {
isPluginDescriptionValid,
isPluginHomepage,
@ -18,7 +17,7 @@ import {
isPluginStableVersionValid,
isPluginTypeValid
} from '../../helpers/custom-validators/plugins.js'
import { getSort, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, getSort, throwIfNotValid } from '../shared/index.js'
@DefaultScope(() => ({
attributes: {
@ -35,7 +34,7 @@ import { getSort, throwIfNotValid } from '../shared/index.js'
}
]
})
export class PluginModel extends Model<Partial<AttributesOnly<PluginModel>>> {
export class PluginModel extends SequelizeModel<PluginModel> {
@AllowNull(false)
@Is('PluginName', value => throwIfNotValid(value, isPluginNameValid, 'name'))

View File

@ -1,10 +1,9 @@
import { Op, QueryTypes } from 'sequelize'
import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
import { BelongsTo, Column, CreatedAt, ForeignKey, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/types/models/index.js'
import { ServerBlock } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { AccountModel } from '../account/account.js'
import { createSafeIn, getSort, searchAttribute } from '../shared/index.js'
import { SequelizeModel, createSafeIn, getSort, searchAttribute } from '../shared/index.js'
import { ServerModel } from './server.js'
enum ScopeNames {
@ -43,7 +42,7 @@ enum ScopeNames {
}
]
})
export class ServerBlocklistModel extends Model<Partial<AttributesOnly<ServerBlocklistModel>>> {
export class ServerBlocklistModel extends SequelizeModel<ServerBlocklistModel> {
@CreatedAt
createdAt: Date

View File

@ -1,10 +1,9 @@
import { Transaction } from 'sequelize'
import { AllowNull, Column, CreatedAt, Default, HasMany, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, Column, CreatedAt, Default, HasMany, Is, Table, UpdatedAt } from 'sequelize-typescript'
import { MServer, MServerFormattable } from '@server/types/models/server/index.js'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { isHostValid } from '../../helpers/custom-validators/servers.js'
import { ActorModel } from '../actor/actor.js'
import { buildSQLAttributes, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, buildSQLAttributes, throwIfNotValid } from '../shared/index.js'
import { ServerBlocklistModel } from './server-blocklist.js'
@Table({
@ -16,7 +15,7 @@ import { ServerBlocklistModel } from './server-blocklist.js'
}
]
})
export class ServerModel extends Model<Partial<AttributesOnly<ServerModel>>> {
export class ServerModel extends SequelizeModel<ServerModel> {
@AllowNull(false)
@Is('Host', value => throwIfNotValid(value, isHostValid, 'valid host'))

View File

@ -1,9 +1,9 @@
import { AllowNull, BelongsToMany, Column, CreatedAt, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsToMany, Column, CreatedAt, Table, UpdatedAt } from 'sequelize-typescript'
import { Transaction } from 'sequelize'
import { MTracker } from '@server/types/models/server/tracker.js'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { VideoModel } from '../video/video.js'
import { VideoTrackerModel } from './video-tracker.js'
import { SequelizeModel } from '../shared/sequelize-type.js'
@Table({
tableName: 'tracker',
@ -14,7 +14,7 @@ import { VideoTrackerModel } from './video-tracker.js'
}
]
})
export class TrackerModel extends Model<Partial<AttributesOnly<TrackerModel>>> {
export class TrackerModel extends SequelizeModel<TrackerModel> {
@AllowNull(false)
@Column

View File

@ -1,7 +1,7 @@
import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { Column, CreatedAt, ForeignKey, Table, UpdatedAt } from 'sequelize-typescript'
import { VideoModel } from '../video/video.js'
import { TrackerModel } from './tracker.js'
import { SequelizeModel } from '../shared/index.js'
@Table({
tableName: 'videoTracker',
@ -14,7 +14,7 @@ import { TrackerModel } from './tracker.js'
}
]
})
export class VideoTrackerModel extends Model<Partial<AttributesOnly<VideoTrackerModel>>> {
export class VideoTrackerModel extends SequelizeModel<VideoTrackerModel> {
@CreatedAt
createdAt: Date

View File

@ -3,6 +3,7 @@ export * from './model-builder.js'
export * from './model-cache.js'
export * from './query.js'
export * from './sequelize-helpers.js'
export * from './sequelize-type.js'
export * from './sort.js'
export * from './sql.js'
export * from './update.js'

View File

@ -0,0 +1,6 @@
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { Model } from 'sequelize-typescript'
export abstract class SequelizeModel <T> extends Model<Partial<AttributesOnly<T>>> {
id: number
}

View File

@ -1,7 +1,6 @@
import { FindOptions, Op } from 'sequelize'
import { AllowNull, BeforeDestroy, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BeforeDestroy, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Table, UpdatedAt } from 'sequelize-typescript'
import { MUserAccountId, MUserExport } from '@server/types/models/index.js'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { UserModel } from './user.js'
import { getSort } from '../shared/sort.js'
import { UserExportState, type UserExport, type UserExportStateType, type FileStorageType, FileStorage } from '@peertube/peertube-models'
@ -18,6 +17,7 @@ import { join } from 'path'
import jwt from 'jsonwebtoken'
import { CONFIG } from '@server/initializers/config.js'
import { removeUserExportObjectStorage } from '@server/lib/object-storage/user-export.js'
import { SequelizeModel } from '../shared/sequelize-type.js'
@Table({
tableName: 'userExport',
@ -31,7 +31,7 @@ import { removeUserExportObjectStorage } from '@server/lib/object-storage/user-e
}
]
})
export class UserExportModel extends Model<Partial<AttributesOnly<UserExportModel>>> {
export class UserExportModel extends SequelizeModel<UserExportModel> {
@CreatedAt
createdAt: Date

View File

@ -1,6 +1,6 @@
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Table, UpdatedAt } from 'sequelize-typescript'
import { MUserImport } from '@server/types/models/index.js'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { SequelizeModel } from '../shared/index.js'
import { UserModel } from './user.js'
import type { UserImportResultSummary, UserImportStateType } from '@peertube/peertube-models'
import { getSort } from '../shared/sort.js'
@ -18,7 +18,7 @@ import { USER_IMPORT_STATES } from '@server/initializers/constants.js'
}
]
})
export class UserImportModel extends Model<Partial<AttributesOnly<UserImportModel>>> {
export class UserImportModel extends SequelizeModel<UserImportModel> {
@CreatedAt
createdAt: Date

View File

@ -1,5 +1,4 @@
import { type UserNotificationSetting, type UserNotificationSettingValueType } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { TokensCache } from '@server/lib/auth/tokens-cache.js'
import { MNotificationSettingFormattable } from '@server/types/models/index.js'
import {
@ -11,13 +10,11 @@ import {
CreatedAt,
Default,
ForeignKey,
Is,
Model,
Table,
Is, Table,
UpdatedAt
} from 'sequelize-typescript'
import { isUserNotificationSettingValid } from '../../helpers/custom-validators/user-notifications.js'
import { throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, throwIfNotValid } from '../shared/index.js'
import { UserModel } from './user.js'
@Table({
@ -29,7 +26,7 @@ import { UserModel } from './user.js'
}
]
})
export class UserNotificationSettingModel extends Model<Partial<AttributesOnly<UserNotificationSettingModel>>> {
export class UserNotificationSettingModel extends SequelizeModel<UserNotificationSettingModel> {
@AllowNull(false)
@Default(null)

View File

@ -1,11 +1,10 @@
import { forceNumber } from '@peertube/peertube-core-utils'
import { UserNotification, type UserNotificationType_Type } from '@peertube/peertube-models'
import { uuidToShort } from '@peertube/peertube-node-utils'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { getBiggestActorImage } from '@server/lib/actor-image.js'
import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user/index.js'
import { ModelIndexesOptions, Op, WhereOptions } from 'sequelize'
import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Table, UpdatedAt } from 'sequelize-typescript'
import { isBooleanValid } from '../../helpers/custom-validators/misc.js'
import { isUserNotificationTypeValid } from '../../helpers/custom-validators/user-notifications.js'
import { AbuseModel } from '../abuse/abuse.js'
@ -13,7 +12,7 @@ import { AccountModel } from '../account/account.js'
import { ActorFollowModel } from '../actor/actor-follow.js'
import { ApplicationModel } from '../application/application.js'
import { PluginModel } from '../server/plugin.js'
import { throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, throwIfNotValid } from '../shared/index.js'
import { VideoBlacklistModel } from '../video/video-blacklist.js'
import { VideoCommentModel } from '../video/video-comment.js'
import { VideoImportModel } from '../video/video-import.js'
@ -110,7 +109,7 @@ import { UserModel } from './user.js'
}
] as (ModelIndexesOptions & { where?: WhereOptions })[]
})
export class UserNotificationModel extends Model<Partial<AttributesOnly<UserNotificationModel>>> {
export class UserNotificationModel extends SequelizeModel<UserNotificationModel> {
@AllowNull(false)
@Default(null)

View File

@ -1,5 +1,4 @@
import { UserRegistration, type UserRegistrationStateType } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import {
isRegistrationModerationResponseValid,
isRegistrationReasonValid,
@ -19,13 +18,11 @@ import {
DataType,
ForeignKey,
Is,
IsEmail,
Model,
Table,
IsEmail, Table,
UpdatedAt
} from 'sequelize-typescript'
import { isUserDisplayNameValid, isUserEmailVerifiedValid, isUserPasswordValid } from '../../helpers/custom-validators/users.js'
import { getSort, parseAggregateResult, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, getSort, parseAggregateResult, throwIfNotValid } from '../shared/index.js'
import { UserModel } from './user.js'
import { forceNumber } from '@peertube/peertube-core-utils'
@ -50,7 +47,7 @@ import { forceNumber } from '@peertube/peertube-core-utils'
}
]
})
export class UserRegistrationModel extends Model<Partial<AttributesOnly<UserRegistrationModel>>> {
export class UserRegistrationModel extends SequelizeModel<UserRegistrationModel> {
@AllowNull(false)
@Is('RegistrationState', value => throwIfNotValid(value, isRegistrationStateValid, 'state'))

View File

@ -1,10 +1,10 @@
import { DestroyOptions, Op, Transaction } from 'sequelize'
import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, IsInt, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, IsInt, Table, UpdatedAt } from 'sequelize-typescript'
import { ResultList } from '@peertube/peertube-models'
import { MUserAccountId, MUserId } from '@server/types/models/index.js'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { VideoModel } from '../video/video.js'
import { UserModel } from './user.js'
import { SequelizeModel } from '../shared/sequelize-type.js'
@Table({
tableName: 'userVideoHistory',
@ -21,7 +21,7 @@ import { UserModel } from './user.js'
}
]
})
export class UserVideoHistoryModel extends Model<Partial<AttributesOnly<UserVideoHistoryModel>>> {
export class UserVideoHistoryModel extends SequelizeModel<UserVideoHistoryModel> {
@CreatedAt
createdAt: Date

View File

@ -10,7 +10,6 @@ import {
type UserAdminFlagType,
type UserRoleType
} from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { TokensCache } from '@server/lib/auth/tokens-cache.js'
import { LiveQuotaStore } from '@server/lib/live/index.js'
import {
@ -37,9 +36,7 @@ import {
HasOne,
Is,
IsEmail,
IsUUID,
Model,
Scopes,
IsUUID, Scopes,
Table,
UpdatedAt
} from 'sequelize-typescript'
@ -70,7 +67,7 @@ import { ActorFollowModel } from '../actor/actor-follow.js'
import { ActorImageModel } from '../actor/actor-image.js'
import { ActorModel } from '../actor/actor.js'
import { OAuthTokenModel } from '../oauth/oauth-token.js'
import { getAdminUsersSort, throwIfNotValid } from '../shared/index.js'
import { getAdminUsersSort, SequelizeModel, throwIfNotValid } from '../shared/index.js'
import { VideoChannelModel } from '../video/video-channel.js'
import { VideoImportModel } from '../video/video-import.js'
import { VideoLiveModel } from '../video/video-live.js'
@ -278,7 +275,7 @@ enum ScopeNames {
}
]
})
export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
export class UserModel extends SequelizeModel<UserModel> {
@AllowNull(true)
@Is('UserPassword', value => throwIfNotValid(value, isUserPasswordValid, 'user password', true))

View File

@ -1,9 +1,9 @@
import { Op, Transaction } from 'sequelize'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Table, UpdatedAt } from 'sequelize-typescript'
import { VideoPrivacy } from '@peertube/peertube-models'
import { MScheduleVideoUpdate, MScheduleVideoUpdateFormattable } from '@server/types/models/index.js'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { VideoModel } from './video.js'
import { SequelizeModel } from '../shared/index.js'
@Table({
tableName: 'scheduleVideoUpdate',
@ -17,7 +17,7 @@ import { VideoModel } from './video.js'
}
]
})
export class ScheduleVideoUpdateModel extends Model<Partial<AttributesOnly<ScheduleVideoUpdateModel>>> {
export class ScheduleVideoUpdateModel extends SequelizeModel<ScheduleVideoUpdateModel> {
@AllowNull(false)
@Default(null)

View File

@ -23,7 +23,7 @@ export interface ListVideoCommentsOptions {
isLocal?: boolean
onLocalVideo?: boolean
onPublicVideo?: boolean
videoAccountOwnerId?: boolean
videoAccountOwnerId?: number
search?: string
searchAccount?: string

View File

@ -1,14 +1,14 @@
import { remove } from 'fs-extra/esm'
import { join } from 'path'
import { AfterDestroy, AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AfterDestroy, AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Table, UpdatedAt } from 'sequelize-typescript'
import { CONFIG } from '@server/initializers/config.js'
import { MStoryboard, MStoryboardVideo, MVideo } from '@server/types/models/index.js'
import { Storyboard } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { logger } from '../../helpers/logger.js'
import { CONSTRAINTS_FIELDS, LAZY_STATIC_PATHS, WEBSERVER } from '../../initializers/constants.js'
import { VideoModel } from './video.js'
import { Transaction } from 'sequelize'
import { SequelizeModel } from '../shared/index.js'
@Table({
tableName: 'storyboard',
@ -23,7 +23,7 @@ import { Transaction } from 'sequelize'
}
]
})
export class StoryboardModel extends Model<Partial<AttributesOnly<StoryboardModel>>> {
export class StoryboardModel extends SequelizeModel<StoryboardModel> {
@AllowNull(false)
@Column

View File

@ -1,10 +1,9 @@
import { col, fn, QueryTypes, Transaction } from 'sequelize'
import { AllowNull, BelongsToMany, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsToMany, Column, CreatedAt, Is, Table, UpdatedAt } from 'sequelize-typescript'
import { VideoPrivacy, VideoState } from '@peertube/peertube-models'
import { MTag } from '@server/types/models/index.js'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { isVideoTagValid } from '../../helpers/custom-validators/videos.js'
import { throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, throwIfNotValid } from '../shared/index.js'
import { VideoTagModel } from './video-tag.js'
import { VideoModel } from './video.js'
@ -22,7 +21,7 @@ import { VideoModel } from './video.js'
}
]
})
export class TagModel extends Model<Partial<AttributesOnly<TagModel>>> {
export class TagModel extends SequelizeModel<TagModel> {
@AllowNull(false)
@Is('VideoTag', value => throwIfNotValid(value, isVideoTagValid, 'tag'))

View File

@ -1,5 +1,4 @@
import { ActivityIconObject, ThumbnailType, type ThumbnailType_Type } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { afterCommitIfTransaction } from '@server/helpers/database-utils.js'
import { MThumbnail, MThumbnailVideo, MVideo, MVideoPlaylist } from '@server/types/models/index.js'
import { remove } from 'fs-extra/esm'
@ -14,9 +13,7 @@ import {
CreatedAt,
DataType,
Default,
ForeignKey,
Model,
Table,
ForeignKey, Table,
UpdatedAt
} from 'sequelize-typescript'
import { logger } from '../../helpers/logger.js'
@ -24,6 +21,7 @@ import { CONFIG } from '../../initializers/config.js'
import { CONSTRAINTS_FIELDS, LAZY_STATIC_PATHS, WEBSERVER } from '../../initializers/constants.js'
import { VideoPlaylistModel } from './video-playlist.js'
import { VideoModel } from './video.js'
import { SequelizeModel } from '../shared/sequelize-type.js'
@Table({
tableName: 'thumbnail',
@ -41,7 +39,7 @@ import { VideoModel } from './video.js'
}
]
})
export class ThumbnailModel extends Model<Partial<AttributesOnly<ThumbnailModel>>> {
export class ThumbnailModel extends SequelizeModel<ThumbnailModel> {
@AllowNull(false)
@Column

View File

@ -1,11 +1,10 @@
import { VideoBlacklist, type VideoBlacklistType_Type } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/models/index.js'
import { FindOptions } from 'sequelize'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Table, UpdatedAt } from 'sequelize-typescript'
import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist.js'
import { CONSTRAINTS_FIELDS } from '../../initializers/constants.js'
import { getBlacklistSort, searchAttribute, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, getBlacklistSort, searchAttribute, throwIfNotValid } from '../shared/index.js'
import { ThumbnailModel } from './thumbnail.js'
import { SummaryOptions, VideoChannelModel, ScopeNames as VideoChannelScopeNames } from './video-channel.js'
import { VideoModel } from './video.js'
@ -19,7 +18,7 @@ import { VideoModel } from './video.js'
}
]
})
export class VideoBlacklistModel extends Model<Partial<AttributesOnly<VideoBlacklistModel>>> {
export class VideoBlacklistModel extends SequelizeModel<VideoBlacklistModel> {
@AllowNull(true)
@Is('VideoBlacklistReason', value => throwIfNotValid(value, isVideoBlacklistReasonValid, 'reason', true))

View File

@ -9,9 +9,7 @@ import {
CreatedAt,
DataType,
ForeignKey,
Is,
Model,
Scopes,
Is, Scopes,
Table,
UpdatedAt
} from 'sequelize-typescript'
@ -24,12 +22,11 @@ import {
MVideoCaptionVideo
} from '@server/types/models/index.js'
import { buildUUID } from '@peertube/peertube-node-utils'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions.js'
import { logger } from '../../helpers/logger.js'
import { CONFIG } from '../../initializers/config.js'
import { CONSTRAINTS_FIELDS, LAZY_STATIC_PATHS, VIDEO_LANGUAGES, WEBSERVER } from '../../initializers/constants.js'
import { buildWhereIdOrUUID, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, buildWhereIdOrUUID, throwIfNotValid } from '../shared/index.js'
import { VideoModel } from './video.js'
export enum ScopeNames {
@ -64,7 +61,7 @@ export enum ScopeNames {
}
]
})
export class VideoCaptionModel extends Model<Partial<AttributesOnly<VideoCaptionModel>>> {
export class VideoCaptionModel extends SequelizeModel<VideoCaptionModel> {
@CreatedAt
createdAt: Date

View File

@ -1,9 +1,8 @@
import { VideoChangeOwnership, type VideoChangeOwnershipStatusType } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { MVideoChangeOwnershipFormattable, MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership.js'
import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
import { AccountModel } from '../account/account.js'
import { getSort } from '../shared/index.js'
import { SequelizeModel, getSort } from '../shared/index.js'
import { VideoModel, ScopeNames as VideoScopeNames } from './video.js'
enum ScopeNames {
@ -54,7 +53,7 @@ enum ScopeNames {
]
}
}))
export class VideoChangeOwnershipModel extends Model<Partial<AttributesOnly<VideoChangeOwnershipModel>>> {
export class VideoChangeOwnershipModel extends SequelizeModel<VideoChangeOwnershipModel> {
@CreatedAt
createdAt: Date

View File

@ -1,5 +1,4 @@
import { VideoChannelSync, VideoChannelSyncState, type VideoChannelSyncStateType } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { isUrlValid } from '@server/helpers/custom-validators/activitypub/misc.js'
import { isVideoChannelSyncStateValid } from '@server/helpers/custom-validators/video-channel-syncs.js'
import { CONSTRAINTS_FIELDS, VIDEO_CHANNEL_SYNC_STATE } from '@server/initializers/constants.js'
@ -14,13 +13,11 @@ import {
Default,
DefaultScope,
ForeignKey,
Is,
Model,
Table,
Is, Table,
UpdatedAt
} from 'sequelize-typescript'
import { AccountModel } from '../account/account.js'
import { getChannelSyncSort, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, getChannelSyncSort, throwIfNotValid } from '../shared/index.js'
import { UserModel } from '../user/user.js'
import { VideoChannelModel } from './video-channel.js'
@ -40,7 +37,7 @@ import { VideoChannelModel } from './video-channel.js'
}
]
})
export class VideoChannelSyncModel extends Model<Partial<AttributesOnly<VideoChannelSyncModel>>> {
export class VideoChannelSyncModel extends SequelizeModel<VideoChannelSyncModel> {
@AllowNull(false)
@Default(null)

View File

@ -1,6 +1,5 @@
import { forceNumber, pick } from '@peertube/peertube-core-utils'
import { ActivityPubActor, VideoChannel, VideoChannelSummary } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { CONFIG } from '@server/initializers/config.js'
import { InternalEventEmitter } from '@server/lib/internal-event-emitter.js'
import { MAccountHost } from '@server/types/models/index.js'
@ -19,9 +18,7 @@ import {
DefaultScope,
ForeignKey,
HasMany,
Is,
Model,
Scopes,
Is, Scopes,
Sequelize,
Table,
UpdatedAt
@ -47,6 +44,7 @@ import { ActorImageModel } from '../actor/actor-image.js'
import { ActorModel, unusedActorAttributesForAPI } from '../actor/actor.js'
import { ServerModel } from '../server/server.js'
import {
SequelizeModel,
buildServerIdsFollowedBy,
buildTrigramSearchIndex,
createSimilarityAttribute,
@ -352,7 +350,7 @@ export type SummaryOptions = {
}
]
})
export class VideoChannelModel extends Model<Partial<AttributesOnly<VideoChannelModel>>> {
export class VideoChannelModel extends SequelizeModel<VideoChannelModel> {
@AllowNull(false)
@Is('VideoChannelName', value => throwIfNotValid(value, isVideoChannelDisplayNameValid, 'name'))

View File

@ -1,10 +1,10 @@
import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Table, UpdatedAt } from 'sequelize-typescript'
import { MVideo, MVideoChapter } from '@server/types/models/index.js'
import { VideoChapter, VideoChapterObject } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { VideoModel } from './video.js'
import { Transaction } from 'sequelize'
import { getSort } from '../shared/sort.js'
import { SequelizeModel } from '../shared/sequelize-type.js'
@Table({
tableName: 'videoChapter',
@ -15,7 +15,7 @@ import { getSort } from '../shared/sort.js'
}
]
})
export class VideoChapterModel extends Model<Partial<AttributesOnly<VideoChapterModel>>> {
export class VideoChapterModel extends SequelizeModel<VideoChapterModel> {
@AllowNull(false)
@Column

View File

@ -1,4 +1,4 @@
import { FindOptions, Op, Order, QueryTypes, Sequelize, Transaction } from 'sequelize'
import { Op, Order, QueryTypes, Sequelize, Transaction } from 'sequelize'
import {
AllowNull,
BelongsTo,
@ -7,9 +7,7 @@ import {
DataType,
ForeignKey,
HasMany,
Is,
Model,
Scopes,
Is, Scopes,
Table,
UpdatedAt
} from 'sequelize-typescript'
@ -18,7 +16,6 @@ import { ActivityTagObject, ActivityTombstoneObject, VideoComment, VideoCommentA
import { extractMentions } from '@server/helpers/mentions.js'
import { getServerActor } from '@server/models/application/application.js'
import { MAccount, MAccountId, MUserAccountId } from '@server/types/models/index.js'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc.js'
import { CONSTRAINTS_FIELDS } from '../../initializers/constants.js'
import {
@ -38,7 +35,7 @@ import {
import { VideoCommentAbuseModel } from '../abuse/video-comment-abuse.js'
import { AccountModel } from '../account/account.js'
import { ActorModel } from '../actor/actor.js'
import { buildLocalAccountIdsIn, buildSQLAttributes, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, buildLocalAccountIdsIn, buildSQLAttributes, throwIfNotValid } from '../shared/index.js'
import { ListVideoCommentsOptions, VideoCommentListQueryBuilder } from './sql/comment/video-comment-list-query-builder.js'
import { VideoChannelModel } from './video-channel.js'
import { VideoModel } from './video.js'
@ -123,7 +120,7 @@ export enum ScopeNames {
}
]
})
export class VideoCommentModel extends Model<Partial<AttributesOnly<VideoCommentModel>>> {
export class VideoCommentModel extends SequelizeModel<VideoCommentModel> {
@CreatedAt
createdAt: Date
@ -216,46 +213,43 @@ export class VideoCommentModel extends Model<Partial<AttributesOnly<VideoComment
// ---------------------------------------------------------------------------
static loadById (id: number, t?: Transaction): Promise<MComment> {
const query: FindOptions = {
static loadById (id: number, transaction?: Transaction): Promise<MComment> {
const query = {
where: {
id
}
},
transaction
}
if (t !== undefined) query.transaction = t
return VideoCommentModel.findOne(query)
}
static loadByIdAndPopulateVideoAndAccountAndReply (id: number, t?: Transaction): Promise<MCommentOwnerVideoReply> {
const query: FindOptions = {
static loadByIdAndPopulateVideoAndAccountAndReply (id: number, transaction?: Transaction): Promise<MCommentOwnerVideoReply> {
const query = {
where: {
id
}
},
transaction
}
if (t !== undefined) query.transaction = t
return VideoCommentModel
.scope([ ScopeNames.WITH_VIDEO, ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_IN_REPLY_TO ])
.findOne(query)
}
static loadByUrlAndPopulateAccountAndVideo (url: string, t?: Transaction): Promise<MCommentOwnerVideo> {
const query: FindOptions = {
static loadByUrlAndPopulateAccountAndVideo (url: string, transaction?: Transaction): Promise<MCommentOwnerVideo> {
const query = {
where: {
url
}
},
transaction
}
if (t !== undefined) query.transaction = t
return VideoCommentModel.scope([ ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_VIDEO ]).findOne(query)
}
static loadByUrlAndPopulateReplyAndVideoUrlAndAccount (url: string, t?: Transaction): Promise<MCommentOwnerReplyVideoLight> {
const query: FindOptions = {
static loadByUrlAndPopulateReplyAndVideoUrlAndAccount (url: string, transaction?: Transaction): Promise<MCommentOwnerReplyVideoLight> {
const query = {
where: {
url
},
@ -264,11 +258,10 @@ export class VideoCommentModel extends Model<Partial<AttributesOnly<VideoComment
attributes: [ 'id', 'url' ],
model: VideoModel.unscoped()
}
]
],
transaction
}
if (t !== undefined) query.transaction = t
return VideoCommentModel.scope([ ScopeNames.WITH_IN_REPLY_TO, ScopeNames.WITH_ACCOUNT ]).findOne(query)
}

View File

@ -1,5 +1,4 @@
import { ActivityVideoUrlObject, VideoResolution, FileStorage, type FileStorageType } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { logger } from '@server/helpers/logger.js'
import { extractVideo } from '@server/helpers/video.js'
import { CONFIG } from '@server/initializers/config.js'
@ -27,9 +26,7 @@ import {
DefaultScope,
ForeignKey,
HasMany,
Is,
Model,
Scopes,
Is, Scopes,
Table,
UpdatedAt
} from 'sequelize-typescript'
@ -51,7 +48,7 @@ import {
} from '../../initializers/constants.js'
import { MVideoFile, MVideoFileStreamingPlaylistVideo, MVideoFileVideo } from '../../types/models/video/video-file.js'
import { VideoRedundancyModel } from '../redundancy/video-redundancy.js'
import { doesExist, parseAggregateResult, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, doesExist, parseAggregateResult, throwIfNotValid } from '../shared/index.js'
import { VideoStreamingPlaylistModel } from './video-streaming-playlist.js'
import { VideoModel } from './video.js'
import { getVideoFileMimeType } from '@server/lib/video-file.js'
@ -158,7 +155,7 @@ export enum ScopeNames {
}
]
})
export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>>> {
export class VideoFileModel extends SequelizeModel<VideoFileModel> {
@CreatedAt
createdAt: Date
@ -257,7 +254,7 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
})
RedundancyVideos: Awaited<VideoRedundancyModel>[]
static doesInfohashExistCached = memoizee(VideoFileModel.doesInfohashExist, {
static doesInfohashExistCached = memoizee(VideoFileModel.doesInfohashExist.bind(VideoFileModel), {
promise: true,
max: MEMOIZE_LENGTH.INFO_HASH_EXISTS,
maxAge: MEMOIZE_TTL.INFO_HASH_EXISTS

View File

@ -1,5 +1,4 @@
import { VideoImport, VideoImportState, type VideoImportStateType } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { afterCommitIfTransaction } from '@server/helpers/database-utils.js'
import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/models/video/video-import.js'
import { IncludeOptions, Op, WhereOptions } from 'sequelize'
@ -13,15 +12,13 @@ import {
Default,
DefaultScope,
ForeignKey,
Is,
Model,
Table,
Is, Table,
UpdatedAt
} from 'sequelize-typescript'
import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports.js'
import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos.js'
import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers/constants.js'
import { getSort, searchAttribute, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, getSort, searchAttribute, throwIfNotValid } from '../shared/index.js'
import { UserModel } from '../user/user.js'
import { VideoChannelSyncModel } from './video-channel-sync.js'
import { VideoModel, ScopeNames as VideoModelScopeNames } from './video.js'
@ -63,7 +60,7 @@ const defaultVideoScope = () => {
}
]
})
export class VideoImportModel extends Model<Partial<AttributesOnly<VideoImportModel>>> {
export class VideoImportModel extends SequelizeModel<VideoImportModel> {
@CreatedAt
createdAt: Date

View File

@ -1,8 +1,8 @@
import { Op, QueryTypes, Transaction } from 'sequelize'
import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, IsInt, Model, Table, Unique, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, IsInt, Table, Unique, UpdatedAt } from 'sequelize-typescript'
import { forceNumber } from '@peertube/peertube-core-utils'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { VideoModel } from './video.js'
import { SequelizeModel } from '../shared/sequelize-type.js'
export type VideoJobInfoColumnType = 'pendingMove' | 'pendingTranscode'
@ -20,7 +20,7 @@ export type VideoJobInfoColumnType = 'pendingMove' | 'pendingTranscode'
]
})
export class VideoJobInfoModel extends Model<Partial<AttributesOnly<VideoJobInfoModel>>> {
export class VideoJobInfoModel extends SequelizeModel<VideoJobInfoModel> {
@CreatedAt
createdAt: Date

View File

@ -2,13 +2,14 @@ import { type VideoPrivacyType } from '@peertube/peertube-models'
import { isVideoPrivacyValid } from '@server/helpers/custom-validators/videos.js'
import { MLiveReplaySetting } from '@server/types/models/video/video-live-replay-setting.js'
import { Transaction } from 'sequelize'
import { AllowNull, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, Column, CreatedAt, Is, Table, UpdatedAt } from 'sequelize-typescript'
import { throwIfNotValid } from '../shared/sequelize-helpers.js'
import { SequelizeModel } from '../shared/index.js'
@Table({
tableName: 'videoLiveReplaySetting'
})
export class VideoLiveReplaySettingModel extends Model<VideoLiveReplaySettingModel> {
export class VideoLiveReplaySettingModel extends SequelizeModel<VideoLiveReplaySettingModel> {
@CreatedAt
createdAt: Date

View File

@ -10,14 +10,13 @@ import {
Column,
CreatedAt,
DataType,
ForeignKey,
Model,
Scopes,
ForeignKey, Scopes,
Table,
UpdatedAt
} from 'sequelize-typescript'
import { VideoLiveReplaySettingModel } from './video-live-replay-setting.js'
import { VideoModel } from './video.js'
import { SequelizeModel } from '../shared/index.js'
export enum ScopeNames {
WITH_REPLAY = 'WITH_REPLAY'
@ -54,7 +53,7 @@ export enum ScopeNames {
}
]
})
export class VideoLiveSessionModel extends Model<Partial<AttributesOnly<VideoLiveSessionModel>>> {
export class VideoLiveSessionModel extends SequelizeModel<VideoLiveSessionModel> {
@CreatedAt
createdAt: Date

View File

@ -1,5 +1,4 @@
import { LiveVideo, VideoState, type LiveVideoLatencyModeType } from '@peertube/peertube-models'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { CONFIG } from '@server/initializers/config.js'
import { WEBSERVER } from '@server/initializers/constants.js'
import { MVideoLive, MVideoLiveVideoWithSetting, MVideoLiveWithSetting } from '@server/types/models/index.js'
@ -12,14 +11,13 @@ import {
CreatedAt,
DataType,
DefaultScope,
ForeignKey,
Model,
Table,
ForeignKey, Table,
UpdatedAt
} from 'sequelize-typescript'
import { VideoBlacklistModel } from './video-blacklist.js'
import { VideoLiveReplaySettingModel } from './video-live-replay-setting.js'
import { VideoModel } from './video.js'
import { SequelizeModel } from '../shared/index.js'
@DefaultScope(() => ({
include: [
@ -52,7 +50,7 @@ import { VideoModel } from './video.js'
}
]
})
export class VideoLiveModel extends Model<Partial<AttributesOnly<VideoLiveModel>>> {
export class VideoLiveModel extends SequelizeModel<VideoLiveModel> {
@AllowNull(true)
@Column(DataType.STRING)

View File

@ -1,9 +1,8 @@
import { AllowNull, BelongsTo, Column, CreatedAt, DefaultScope, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, DefaultScope, ForeignKey, Is, Table, UpdatedAt } from 'sequelize-typescript'
import { VideoModel } from './video.js'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { ResultList, VideoPassword } from '@peertube/peertube-models'
import { getSort, throwIfNotValid } from '../shared/index.js'
import { FindOptions, Transaction } from 'sequelize'
import { SequelizeModel, getSort, throwIfNotValid } from '../shared/index.js'
import { Transaction } from 'sequelize'
import { MVideoPassword } from '@server/types/models/index.js'
import { isPasswordValid } from '@server/helpers/custom-validators/videos.js'
import { pick } from '@peertube/peertube-core-utils'
@ -25,7 +24,7 @@ import { pick } from '@peertube/peertube-core-utils'
}
]
})
export class VideoPasswordModel extends Model<Partial<AttributesOnly<VideoPasswordModel>>> {
export class VideoPasswordModel extends SequelizeModel<VideoPasswordModel> {
@AllowNull(false)
@Is('VideoPassword', value => throwIfNotValid(value, isPasswordValid, 'videoPassword'))
@ -51,7 +50,7 @@ export class VideoPasswordModel extends Model<Partial<AttributesOnly<VideoPasswo
Video: Awaited<VideoModel>
static async countByVideoId (videoId: number, t?: Transaction) {
const query: FindOptions = {
const query = {
where: {
videoId
},
@ -63,7 +62,7 @@ export class VideoPasswordModel extends Model<Partial<AttributesOnly<VideoPasswo
static async loadByIdAndVideo (options: { id: number, videoId: number, t?: Transaction }): Promise<MVideoPassword> {
const { id, videoId, t } = options
const query: FindOptions = {
const query = {
where: {
id,
videoId

View File

@ -9,9 +9,7 @@ import {
ForeignKey,
Is,
IsInt,
Min,
Model,
Table,
Min, Table,
UpdatedAt
} from 'sequelize-typescript'
import validator from 'validator'
@ -32,11 +30,10 @@ import {
MVideoPlaylistElementVideoThumbnail,
MVideoPlaylistElementVideoUrl
} from '@server/types/models/video/video-playlist-element.js'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc.js'
import { CONSTRAINTS_FIELDS } from '../../initializers/constants.js'
import { AccountModel } from '../account/account.js'
import { getSort, throwIfNotValid } from '../shared/index.js'
import { SequelizeModel, getSort, throwIfNotValid } from '../shared/index.js'
import { VideoPlaylistModel } from './video-playlist.js'
import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './video.js'
@ -55,7 +52,7 @@ import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './vide
}
]
})
export class VideoPlaylistElementModel extends Model<Partial<AttributesOnly<VideoPlaylistElementModel>>> {
export class VideoPlaylistElementModel extends SequelizeModel<VideoPlaylistElementModel> {
@CreatedAt
createdAt: Date

View File

@ -9,7 +9,6 @@ import {
type VideoPlaylistType_Type
} from '@peertube/peertube-models'
import { buildUUID, uuidToShort } from '@peertube/peertube-node-utils'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { activityPubCollectionPagination } from '@server/lib/activitypub/collection.js'
import { MAccountId, MChannelId } from '@server/types/models/index.js'
import { join } from 'path'
@ -25,9 +24,7 @@ import {
HasMany,
HasOne,
Is,
IsUUID,
Model,
Scopes,
IsUUID, Scopes,
Table,
UpdatedAt
} from 'sequelize-typescript'
@ -58,6 +55,7 @@ import {
import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions } from '../account/account.js'
import { ActorModel } from '../actor/actor.js'
import {
SequelizeModel,
buildServerIdsFollowedBy,
buildTrigramSearchIndex,
buildWhereIdOrUUID,
@ -287,7 +285,7 @@ function getVideoLengthSelect () {
}
]
})
export class VideoPlaylistModel extends Model<Partial<AttributesOnly<VideoPlaylistModel>>> {
export class VideoPlaylistModel extends SequelizeModel<VideoPlaylistModel> {
@CreatedAt
createdAt: Date

View File

@ -1,13 +1,12 @@
import { literal, Op, QueryTypes, Transaction } from 'sequelize'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
import { forceNumber } from '@peertube/peertube-core-utils'
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc.js'
import { CONSTRAINTS_FIELDS } from '../../initializers/constants.js'
import { MActorDefault, MActorFollowersUrl, MActorId } from '../../types/models/index.js'
import { MVideoShareActor, MVideoShareFull } from '../../types/models/video/index.js'
import { ActorModel } from '../actor/actor.js'
import { buildLocalActorIdsIn, throwIfNotValid } from '../shared/index.js'
import { buildLocalActorIdsIn, SequelizeModel, throwIfNotValid } from '../shared/index.js'
import { VideoModel } from './video.js'
enum ScopeNames {
@ -52,7 +51,7 @@ enum ScopeNames {
}
]
})
export class VideoShareModel extends Model<Partial<AttributesOnly<VideoShareModel>>> {
export class VideoShareModel extends SequelizeModel<VideoShareModel> {
@AllowNull(false)
@Is('VideoShareUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url'))

Some files were not shown because too many files have changed in this diff Show More