diff options
54 files changed, 146 insertions, 93 deletions
diff --git a/server/controllers/activitypub/utils.ts b/server/controllers/activitypub/utils.ts index 599cf48ab..19bdd58eb 100644 --- a/server/controllers/activitypub/utils.ts +++ b/server/controllers/activitypub/utils.ts | |||
@@ -3,7 +3,6 @@ import * as express from 'express' | |||
3 | function activityPubResponse (data: any, res: express.Response) { | 3 | function activityPubResponse (data: any, res: express.Response) { |
4 | return res.type('application/activity+json; charset=utf-8') | 4 | return res.type('application/activity+json; charset=utf-8') |
5 | .json(data) | 5 | .json(data) |
6 | .end() | ||
7 | } | 6 | } |
8 | 7 | ||
9 | export { | 8 | export { |
diff --git a/server/controllers/api/users/index.ts b/server/controllers/api/users/index.ts index c655d1648..f384f0f28 100644 --- a/server/controllers/api/users/index.ts +++ b/server/controllers/api/users/index.ts | |||
@@ -323,14 +323,20 @@ async function updateUser (req: express.Request, res: express.Response) { | |||
323 | const oldUserAuditView = new UserAuditView(userToUpdate.toFormattedJSON()) | 323 | const oldUserAuditView = new UserAuditView(userToUpdate.toFormattedJSON()) |
324 | const roleChanged = body.role !== undefined && body.role !== userToUpdate.role | 324 | const roleChanged = body.role !== undefined && body.role !== userToUpdate.role |
325 | 325 | ||
326 | if (body.password !== undefined) userToUpdate.password = body.password | 326 | const keysToUpdate: (keyof UserUpdate)[] = [ |
327 | if (body.email !== undefined) userToUpdate.email = body.email | 327 | 'password', |
328 | if (body.emailVerified !== undefined) userToUpdate.emailVerified = body.emailVerified | 328 | 'email', |
329 | if (body.videoQuota !== undefined) userToUpdate.videoQuota = body.videoQuota | 329 | 'emailVerified', |
330 | if (body.videoQuotaDaily !== undefined) userToUpdate.videoQuotaDaily = body.videoQuotaDaily | 330 | 'videoQuota', |
331 | if (body.role !== undefined) userToUpdate.role = body.role | 331 | 'videoQuotaDaily', |
332 | if (body.adminFlags !== undefined) userToUpdate.adminFlags = body.adminFlags | 332 | 'role', |
333 | if (body.pluginAuth !== undefined) userToUpdate.pluginAuth = body.pluginAuth | 333 | 'adminFlags', |
334 | 'pluginAuth' | ||
335 | ] | ||
336 | |||
337 | for (const key of keysToUpdate) { | ||
338 | if (body[key] !== undefined) userToUpdate.set(key, body[key]) | ||
339 | } | ||
334 | 340 | ||
335 | const user = await userToUpdate.save() | 341 | const user = await userToUpdate.save() |
336 | 342 | ||
diff --git a/server/controllers/api/videos/import.ts b/server/controllers/api/videos/import.ts index 4ed58f978..2c225315c 100644 --- a/server/controllers/api/videos/import.ts +++ b/server/controllers/api/videos/import.ts | |||
@@ -5,6 +5,7 @@ import * as parseTorrent from 'parse-torrent' | |||
5 | import { join } from 'path' | 5 | import { join } from 'path' |
6 | import { getEnabledResolutions } from '@server/lib/config' | 6 | import { getEnabledResolutions } from '@server/lib/config' |
7 | import { setVideoTags } from '@server/lib/video' | 7 | import { setVideoTags } from '@server/lib/video' |
8 | import { FilteredModelAttributes } from '@server/types' | ||
8 | import { | 9 | import { |
9 | MChannelAccountDefault, | 10 | MChannelAccountDefault, |
10 | MThumbnail, | 11 | MThumbnail, |
@@ -15,7 +16,7 @@ import { | |||
15 | MVideoThumbnail, | 16 | MVideoThumbnail, |
16 | MVideoWithBlacklistLight | 17 | MVideoWithBlacklistLight |
17 | } from '@server/types/models' | 18 | } from '@server/types/models' |
18 | import { MVideoImport, MVideoImportFormattable } from '@server/types/models/video/video-import' | 19 | import { MVideoImportFormattable } from '@server/types/models/video/video-import' |
19 | import { ServerErrorCode, VideoImportCreate, VideoImportState, VideoPrivacy, VideoState } from '../../../../shared' | 20 | import { ServerErrorCode, VideoImportCreate, VideoImportState, VideoPrivacy, VideoState } from '../../../../shared' |
20 | import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' | 21 | import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' |
21 | import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type' | 22 | import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type' |
@@ -253,7 +254,9 @@ function buildVideo (channelId: number, body: VideoImportCreate, importData: You | |||
253 | privacy: body.privacy || VideoPrivacy.PRIVATE, | 254 | privacy: body.privacy || VideoPrivacy.PRIVATE, |
254 | duration: 0, // duration will be set by the import job | 255 | duration: 0, // duration will be set by the import job |
255 | channelId: channelId, | 256 | channelId: channelId, |
256 | originallyPublishedAt: body.originallyPublishedAt || importData.originallyPublishedAt | 257 | originallyPublishedAt: body.originallyPublishedAt |
258 | ? new Date(body.originallyPublishedAt) | ||
259 | : importData.originallyPublishedAt | ||
257 | } | 260 | } |
258 | const video = new VideoModel(videoData) | 261 | const video = new VideoModel(videoData) |
259 | video.url = getLocalVideoActivityPubUrl(video) | 262 | video.url = getLocalVideoActivityPubUrl(video) |
@@ -317,7 +320,7 @@ async function insertIntoDB (parameters: { | |||
317 | previewModel: MThumbnail | 320 | previewModel: MThumbnail |
318 | videoChannel: MChannelAccountDefault | 321 | videoChannel: MChannelAccountDefault |
319 | tags: string[] | 322 | tags: string[] |
320 | videoImportAttributes: Partial<MVideoImport> | 323 | videoImportAttributes: FilteredModelAttributes<VideoImportModel> |
321 | user: MUser | 324 | user: MUser |
322 | }): Promise<MVideoImportFormattable> { | 325 | }): Promise<MVideoImportFormattable> { |
323 | const { video, thumbnailModel, previewModel, videoChannel, tags, videoImportAttributes, user } = parameters | 326 | const { video, thumbnailModel, previewModel, videoChannel, tags, videoImportAttributes, user } = parameters |
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index c32626d30..f5ce15074 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -308,7 +308,7 @@ async function addVideo (options: { | |||
308 | if (videoInfo.scheduleUpdate) { | 308 | if (videoInfo.scheduleUpdate) { |
309 | await ScheduleVideoUpdateModel.create({ | 309 | await ScheduleVideoUpdateModel.create({ |
310 | videoId: video.id, | 310 | videoId: video.id, |
311 | updateAt: videoInfo.scheduleUpdate.updateAt, | 311 | updateAt: new Date(videoInfo.scheduleUpdate.updateAt), |
312 | privacy: videoInfo.scheduleUpdate.privacy || null | 312 | privacy: videoInfo.scheduleUpdate.privacy || null |
313 | }, { transaction: t }) | 313 | }, { transaction: t }) |
314 | } | 314 | } |
@@ -435,7 +435,7 @@ async function updateVideo (req: express.Request, res: express.Response) { | |||
435 | if (videoInfoToUpdate.scheduleUpdate) { | 435 | if (videoInfoToUpdate.scheduleUpdate) { |
436 | await ScheduleVideoUpdateModel.upsert({ | 436 | await ScheduleVideoUpdateModel.upsert({ |
437 | videoId: videoInstanceUpdated.id, | 437 | videoId: videoInstanceUpdated.id, |
438 | updateAt: videoInfoToUpdate.scheduleUpdate.updateAt, | 438 | updateAt: new Date(videoInfoToUpdate.scheduleUpdate.updateAt), |
439 | privacy: videoInfoToUpdate.scheduleUpdate.privacy || null | 439 | privacy: videoInfoToUpdate.scheduleUpdate.privacy || null |
440 | }, { transaction: t }) | 440 | }, { transaction: t }) |
441 | } else if (videoInfoToUpdate.scheduleUpdate === null) { | 441 | } else if (videoInfoToUpdate.scheduleUpdate === null) { |
diff --git a/server/helpers/database-utils.ts b/server/helpers/database-utils.ts index f9cb33aca..7befa2c49 100644 --- a/server/helpers/database-utils.ts +++ b/server/helpers/database-utils.ts | |||
@@ -68,7 +68,7 @@ function transactionRetryer <T> (func: (err: any, data: T) => any) { | |||
68 | }) | 68 | }) |
69 | } | 69 | } |
70 | 70 | ||
71 | function updateInstanceWithAnother <T extends Model<T>> (instanceToUpdate: Model<T>, baseInstance: Model<T>) { | 71 | function updateInstanceWithAnother <M, T extends U, U extends Model<M>> (instanceToUpdate: T, baseInstance: U) { |
72 | const obj = baseInstance.toJSON() | 72 | const obj = baseInstance.toJSON() |
73 | 73 | ||
74 | for (const key of Object.keys(obj)) { | 74 | for (const key of Object.keys(obj)) { |
@@ -88,7 +88,7 @@ function afterCommitIfTransaction (t: Transaction, fn: Function) { | |||
88 | return fn() | 88 | return fn() |
89 | } | 89 | } |
90 | 90 | ||
91 | function deleteNonExistingModels <T extends { hasSameUniqueKeysThan (other: T): boolean } & Model<T>> ( | 91 | function deleteNonExistingModels <T extends { hasSameUniqueKeysThan (other: T): boolean } & Pick<Model, 'destroy'>> ( |
92 | fromDatabase: T[], | 92 | fromDatabase: T[], |
93 | newModels: T[], | 93 | newModels: T[], |
94 | t: Transaction | 94 | t: Transaction |
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts index 8865b6277..1bcee7ef9 100644 --- a/server/lib/activitypub/actor.ts +++ b/server/lib/activitypub/actor.ts | |||
@@ -132,12 +132,11 @@ async function getOrCreateActorAndServerAndModel ( | |||
132 | return actorRefreshed | 132 | return actorRefreshed |
133 | } | 133 | } |
134 | 134 | ||
135 | function buildActorInstance (type: ActivityPubActorType, url: string, preferredUsername: string, uuid?: string) { | 135 | function buildActorInstance (type: ActivityPubActorType, url: string, preferredUsername: string) { |
136 | return new ActorModel({ | 136 | return new ActorModel({ |
137 | type, | 137 | type, |
138 | url, | 138 | url, |
139 | preferredUsername, | 139 | preferredUsername, |
140 | uuid, | ||
141 | publicKey: null, | 140 | publicKey: null, |
142 | privateKey: null, | 141 | privateKey: null, |
143 | followersCount: 0, | 142 | followersCount: 0, |
diff --git a/server/lib/job-queue/handlers/video-views.ts b/server/lib/job-queue/handlers/video-views.ts index 897235ec0..86d0a271f 100644 --- a/server/lib/job-queue/handlers/video-views.ts +++ b/server/lib/job-queue/handlers/video-views.ts | |||
@@ -36,8 +36,8 @@ async function processVideosViews () { | |||
36 | } | 36 | } |
37 | 37 | ||
38 | await VideoViewModel.create({ | 38 | await VideoViewModel.create({ |
39 | startDate, | 39 | startDate: new Date(startDate), |
40 | endDate, | 40 | endDate: new Date(endDate), |
41 | views, | 41 | views, |
42 | videoId | 42 | videoId |
43 | }) | 43 | }) |
diff --git a/server/lib/video-channel.ts b/server/lib/video-channel.ts index 0476cb2d5..d57e832fe 100644 --- a/server/lib/video-channel.ts +++ b/server/lib/video-channel.ts | |||
@@ -1,5 +1,4 @@ | |||
1 | import * as Sequelize from 'sequelize' | 1 | import * as Sequelize from 'sequelize' |
2 | import { v4 as uuidv4 } from 'uuid' | ||
3 | import { VideoChannelCreate } from '../../shared/models' | 2 | import { VideoChannelCreate } from '../../shared/models' |
4 | import { VideoModel } from '../models/video/video' | 3 | import { VideoModel } from '../models/video/video' |
5 | import { VideoChannelModel } from '../models/video/video-channel' | 4 | import { VideoChannelModel } from '../models/video/video-channel' |
@@ -9,9 +8,8 @@ import { getLocalVideoChannelActivityPubUrl } from './activitypub/url' | |||
9 | import { federateVideoIfNeeded } from './activitypub/videos' | 8 | import { federateVideoIfNeeded } from './activitypub/videos' |
10 | 9 | ||
11 | async function createLocalVideoChannel (videoChannelInfo: VideoChannelCreate, account: MAccountId, t: Sequelize.Transaction) { | 10 | async function createLocalVideoChannel (videoChannelInfo: VideoChannelCreate, account: MAccountId, t: Sequelize.Transaction) { |
12 | const uuid = uuidv4() | ||
13 | const url = getLocalVideoChannelActivityPubUrl(videoChannelInfo.name) | 11 | const url = getLocalVideoChannelActivityPubUrl(videoChannelInfo.name) |
14 | const actorInstance = buildActorInstance('Group', url, videoChannelInfo.name, uuid) | 12 | const actorInstance = buildActorInstance('Group', url, videoChannelInfo.name) |
15 | 13 | ||
16 | const actorInstanceCreated = await actorInstance.save({ transaction: t }) | 14 | const actorInstanceCreated = await actorInstance.save({ transaction: t }) |
17 | 15 | ||
diff --git a/server/lib/video.ts b/server/lib/video.ts index 21e4b7ff2..d26cf85cd 100644 --- a/server/lib/video.ts +++ b/server/lib/video.ts | |||
@@ -28,6 +28,8 @@ function buildLocalVideoFromReq (videoInfo: VideoCreate, channelId: number): Fil | |||
28 | privacy: videoInfo.privacy || VideoPrivacy.PRIVATE, | 28 | privacy: videoInfo.privacy || VideoPrivacy.PRIVATE, |
29 | channelId: channelId, | 29 | channelId: channelId, |
30 | originallyPublishedAt: videoInfo.originallyPublishedAt | 30 | originallyPublishedAt: videoInfo.originallyPublishedAt |
31 | ? new Date(videoInfo.originallyPublishedAt) | ||
32 | : null | ||
31 | } | 33 | } |
32 | } | 34 | } |
33 | 35 | ||
diff --git a/server/models/abuse/abuse-message.ts b/server/models/abuse/abuse-message.ts index 7e51b3e07..2c5987e96 100644 --- a/server/models/abuse/abuse-message.ts +++ b/server/models/abuse/abuse-message.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { isAbuseMessageValid } from '@server/helpers/custom-validators/abuses' | 2 | import { isAbuseMessageValid } from '@server/helpers/custom-validators/abuses' |
3 | import { MAbuseMessage, MAbuseMessageFormattable } from '@server/types/models' | 3 | import { MAbuseMessage, MAbuseMessageFormattable } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { AbuseMessage } from '@shared/models' | 5 | import { AbuseMessage } from '@shared/models' |
5 | import { AccountModel, ScopeNames as AccountScopeNames } from '../account/account' | 6 | import { AccountModel, ScopeNames as AccountScopeNames } from '../account/account' |
6 | import { getSort, throwIfNotValid } from '../utils' | 7 | import { getSort, throwIfNotValid } from '../utils' |
@@ -17,7 +18,7 @@ import { AbuseModel } from './abuse' | |||
17 | } | 18 | } |
18 | ] | 19 | ] |
19 | }) | 20 | }) |
20 | export class AbuseMessageModel extends Model { | 21 | export class AbuseMessageModel extends Model<Partial<AttributesOnly<AbuseMessageModel>>> { |
21 | 22 | ||
22 | @AllowNull(false) | 23 | @AllowNull(false) |
23 | @Is('AbuseMessage', value => throwIfNotValid(value, isAbuseMessageValid, 'message')) | 24 | @Is('AbuseMessage', value => throwIfNotValid(value, isAbuseMessageValid, 'message')) |
diff --git a/server/models/abuse/abuse.ts b/server/models/abuse/abuse.ts index 262f364f1..ffe109c2f 100644 --- a/server/models/abuse/abuse.ts +++ b/server/models/abuse/abuse.ts | |||
@@ -16,6 +16,7 @@ import { | |||
16 | UpdatedAt | 16 | UpdatedAt |
17 | } from 'sequelize-typescript' | 17 | } from 'sequelize-typescript' |
18 | import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses' | 18 | import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses' |
19 | import { AttributesOnly } from '@shared/core-utils' | ||
19 | import { abusePredefinedReasonsMap } from '@shared/core-utils/abuse' | 20 | import { abusePredefinedReasonsMap } from '@shared/core-utils/abuse' |
20 | import { | 21 | import { |
21 | AbuseFilter, | 22 | AbuseFilter, |
@@ -187,7 +188,7 @@ export enum ScopeNames { | |||
187 | } | 188 | } |
188 | ] | 189 | ] |
189 | }) | 190 | }) |
190 | export class AbuseModel extends Model { | 191 | export class AbuseModel extends Model<Partial<AttributesOnly<AbuseModel>>> { |
191 | 192 | ||
192 | @AllowNull(false) | 193 | @AllowNull(false) |
193 | @Default(null) | 194 | @Default(null) |
diff --git a/server/models/abuse/video-abuse.ts b/server/models/abuse/video-abuse.ts index 90aa0695e..95bff50d0 100644 --- a/server/models/abuse/video-abuse.ts +++ b/server/models/abuse/video-abuse.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { VideoDetails } from '@shared/models' | 3 | import { VideoDetails } from '@shared/models' |
3 | import { VideoModel } from '../video/video' | 4 | import { VideoModel } from '../video/video' |
4 | import { AbuseModel } from './abuse' | 5 | import { AbuseModel } from './abuse' |
@@ -14,7 +15,7 @@ import { AbuseModel } from './abuse' | |||
14 | } | 15 | } |
15 | ] | 16 | ] |
16 | }) | 17 | }) |
17 | export class VideoAbuseModel extends Model { | 18 | export class VideoAbuseModel extends Model<Partial<AttributesOnly<VideoAbuseModel>>> { |
18 | 19 | ||
19 | @CreatedAt | 20 | @CreatedAt |
20 | createdAt: Date | 21 | createdAt: Date |
diff --git a/server/models/abuse/video-comment-abuse.ts b/server/models/abuse/video-comment-abuse.ts index d3fce76a5..32cb2ca64 100644 --- a/server/models/abuse/video-comment-abuse.ts +++ b/server/models/abuse/video-comment-abuse.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { VideoCommentModel } from '../video/video-comment' | 3 | import { VideoCommentModel } from '../video/video-comment' |
3 | import { AbuseModel } from './abuse' | 4 | import { AbuseModel } from './abuse' |
4 | 5 | ||
@@ -13,7 +14,7 @@ import { AbuseModel } from './abuse' | |||
13 | } | 14 | } |
14 | ] | 15 | ] |
15 | }) | 16 | }) |
16 | export class VideoCommentAbuseModel extends Model { | 17 | export class VideoCommentAbuseModel extends Model<Partial<AttributesOnly<VideoCommentAbuseModel>>> { |
17 | 18 | ||
18 | @CreatedAt | 19 | @CreatedAt |
19 | createdAt: Date | 20 | createdAt: Date |
diff --git a/server/models/account/account-blocklist.ts b/server/models/account/account-blocklist.ts index 9f3be22bd..b2375b006 100644 --- a/server/models/account/account-blocklist.ts +++ b/server/models/account/account-blocklist.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { Op } from 'sequelize' | 1 | import { Op } from 'sequelize' |
2 | import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { MAccountBlocklist, MAccountBlocklistAccounts, MAccountBlocklistFormattable } from '@server/types/models' | 3 | import { MAccountBlocklist, MAccountBlocklistAccounts, MAccountBlocklistFormattable } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { AccountBlock } from '../../../shared/models' | 5 | import { AccountBlock } from '../../../shared/models' |
5 | import { ActorModel } from '../actor/actor' | 6 | import { ActorModel } from '../actor/actor' |
6 | import { ServerModel } from '../server/server' | 7 | import { ServerModel } from '../server/server' |
@@ -40,7 +41,7 @@ enum ScopeNames { | |||
40 | } | 41 | } |
41 | ] | 42 | ] |
42 | }) | 43 | }) |
43 | export class AccountBlocklistModel extends Model { | 44 | export class AccountBlocklistModel extends Model<Partial<AttributesOnly<AccountBlocklistModel>>> { |
44 | 45 | ||
45 | @CreatedAt | 46 | @CreatedAt |
46 | createdAt: Date | 47 | createdAt: Date |
diff --git a/server/models/account/account-video-rate.ts b/server/models/account/account-video-rate.ts index 576a44576..ee6dbc6da 100644 --- a/server/models/account/account-video-rate.ts +++ b/server/models/account/account-video-rate.ts | |||
@@ -7,6 +7,7 @@ import { | |||
7 | MAccountVideoRateAccountVideo, | 7 | MAccountVideoRateAccountVideo, |
8 | MAccountVideoRateFormattable | 8 | MAccountVideoRateFormattable |
9 | } from '@server/types/models/video/video-rate' | 9 | } from '@server/types/models/video/video-rate' |
10 | import { AttributesOnly } from '@shared/core-utils' | ||
10 | import { AccountVideoRate } from '../../../shared' | 11 | import { AccountVideoRate } from '../../../shared' |
11 | import { VideoRateType } from '../../../shared/models/videos' | 12 | import { VideoRateType } from '../../../shared/models/videos' |
12 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 13 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
@@ -42,7 +43,7 @@ import { AccountModel } from './account' | |||
42 | } | 43 | } |
43 | ] | 44 | ] |
44 | }) | 45 | }) |
45 | export class AccountVideoRateModel extends Model { | 46 | export class AccountVideoRateModel extends Model<Partial<AttributesOnly<AccountVideoRateModel>>> { |
46 | 47 | ||
47 | @AllowNull(false) | 48 | @AllowNull(false) |
48 | @Column(DataType.ENUM(...values(VIDEO_RATE_TYPES))) | 49 | @Column(DataType.ENUM(...values(VIDEO_RATE_TYPES))) |
diff --git a/server/models/account/account.ts b/server/models/account/account.ts index 7b2af706d..9db109bf8 100644 --- a/server/models/account/account.ts +++ b/server/models/account/account.ts | |||
@@ -17,6 +17,7 @@ import { | |||
17 | UpdatedAt | 17 | UpdatedAt |
18 | } from 'sequelize-typescript' | 18 | } from 'sequelize-typescript' |
19 | import { ModelCache } from '@server/models/model-cache' | 19 | import { ModelCache } from '@server/models/model-cache' |
20 | import { AttributesOnly } from '@shared/core-utils' | ||
20 | import { Account, AccountSummary } from '../../../shared/models/actors' | 21 | import { Account, AccountSummary } from '../../../shared/models/actors' |
21 | import { isAccountDescriptionValid } from '../../helpers/custom-validators/accounts' | 22 | import { isAccountDescriptionValid } from '../../helpers/custom-validators/accounts' |
22 | import { CONSTRAINTS_FIELDS, SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants' | 23 | import { CONSTRAINTS_FIELDS, SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants' |
@@ -141,7 +142,7 @@ export type SummaryOptions = { | |||
141 | } | 142 | } |
142 | ] | 143 | ] |
143 | }) | 144 | }) |
144 | export class AccountModel extends Model { | 145 | export class AccountModel extends Model<Partial<AttributesOnly<AccountModel>>> { |
145 | 146 | ||
146 | @AllowNull(false) | 147 | @AllowNull(false) |
147 | @Column | 148 | @Column |
diff --git a/server/models/actor/actor-follow.ts b/server/models/actor/actor-follow.ts index 4c5f37620..3a09e51d6 100644 --- a/server/models/actor/actor-follow.ts +++ b/server/models/actor/actor-follow.ts | |||
@@ -28,6 +28,7 @@ import { | |||
28 | MActorFollowFormattable, | 28 | MActorFollowFormattable, |
29 | MActorFollowSubscriptions | 29 | MActorFollowSubscriptions |
30 | } from '@server/types/models' | 30 | } from '@server/types/models' |
31 | import { AttributesOnly } from '@shared/core-utils' | ||
31 | import { ActivityPubActorType } from '@shared/models' | 32 | import { ActivityPubActorType } from '@shared/models' |
32 | import { FollowState } from '../../../shared/models/actors' | 33 | import { FollowState } from '../../../shared/models/actors' |
33 | import { ActorFollow } from '../../../shared/models/actors/follow.model' | 34 | import { ActorFollow } from '../../../shared/models/actors/follow.model' |
@@ -61,7 +62,7 @@ import { ActorModel, unusedActorAttributesForAPI } from './actor' | |||
61 | } | 62 | } |
62 | ] | 63 | ] |
63 | }) | 64 | }) |
64 | export class ActorFollowModel extends Model { | 65 | export class ActorFollowModel extends Model<Partial<AttributesOnly<ActorFollowModel>>> { |
65 | 66 | ||
66 | @AllowNull(false) | 67 | @AllowNull(false) |
67 | @Column(DataType.ENUM(...values(FOLLOW_STATES))) | 68 | @Column(DataType.ENUM(...values(FOLLOW_STATES))) |
@@ -619,7 +620,7 @@ export class ActorFollowModel extends Model { | |||
619 | if (serverIds.length === 0) return | 620 | if (serverIds.length === 0) return |
620 | 621 | ||
621 | const me = await getServerActor() | 622 | const me = await getServerActor() |
622 | const serverIdsString = createSafeIn(ActorFollowModel, serverIds) | 623 | const serverIdsString = createSafeIn(ActorFollowModel.sequelize, serverIds) |
623 | 624 | ||
624 | const query = `UPDATE "actorFollow" SET "score" = LEAST("score" + ${value}, ${ACTOR_FOLLOW_SCORE.MAX}) ` + | 625 | const query = `UPDATE "actorFollow" SET "score" = LEAST("score" + ${value}, ${ACTOR_FOLLOW_SCORE.MAX}) ` + |
625 | 'WHERE id IN (' + | 626 | 'WHERE id IN (' + |
diff --git a/server/models/actor/actor-image.ts b/server/models/actor/actor-image.ts index ae05b4969..a35f9edb0 100644 --- a/server/models/actor/actor-image.ts +++ b/server/models/actor/actor-image.ts | |||
@@ -2,6 +2,7 @@ import { remove } from 'fs-extra' | |||
2 | import { join } from 'path' | 2 | import { join } from 'path' |
3 | import { AfterDestroy, AllowNull, Column, CreatedAt, Default, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 3 | import { AfterDestroy, AllowNull, Column, CreatedAt, Default, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
4 | import { MActorImageFormattable } from '@server/types/models' | 4 | import { MActorImageFormattable } from '@server/types/models' |
5 | import { AttributesOnly } from '@shared/core-utils' | ||
5 | import { ActorImageType } from '@shared/models' | 6 | import { ActorImageType } from '@shared/models' |
6 | import { ActorImage } from '../../../shared/models/actors/actor-image.model' | 7 | import { ActorImage } from '../../../shared/models/actors/actor-image.model' |
7 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 8 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
@@ -19,7 +20,7 @@ import { throwIfNotValid } from '../utils' | |||
19 | } | 20 | } |
20 | ] | 21 | ] |
21 | }) | 22 | }) |
22 | export class ActorImageModel extends Model { | 23 | export class ActorImageModel extends Model<Partial<AttributesOnly<ActorImageModel>>> { |
23 | 24 | ||
24 | @AllowNull(false) | 25 | @AllowNull(false) |
25 | @Column | 26 | @Column |
diff --git a/server/models/actor/actor.ts b/server/models/actor/actor.ts index 5cf6fb8f1..65c53f8f8 100644 --- a/server/models/actor/actor.ts +++ b/server/models/actor/actor.ts | |||
@@ -18,6 +18,7 @@ import { | |||
18 | UpdatedAt | 18 | UpdatedAt |
19 | } from 'sequelize-typescript' | 19 | } from 'sequelize-typescript' |
20 | import { ModelCache } from '@server/models/model-cache' | 20 | import { ModelCache } from '@server/models/model-cache' |
21 | import { AttributesOnly } from '@shared/core-utils' | ||
21 | import { ActivityIconObject, ActivityPubActorType } from '../../../shared/models/activitypub' | 22 | import { ActivityIconObject, ActivityPubActorType } from '../../../shared/models/activitypub' |
22 | import { ActorImage } from '../../../shared/models/actors/actor-image.model' | 23 | import { ActorImage } from '../../../shared/models/actors/actor-image.model' |
23 | import { activityPubContextify } from '../../helpers/activitypub' | 24 | import { activityPubContextify } from '../../helpers/activitypub' |
@@ -159,7 +160,7 @@ export const unusedActorAttributesForAPI = [ | |||
159 | } | 160 | } |
160 | ] | 161 | ] |
161 | }) | 162 | }) |
162 | export class ActorModel extends Model { | 163 | export class ActorModel extends Model<Partial<AttributesOnly<ActorModel>>> { |
163 | 164 | ||
164 | @AllowNull(false) | 165 | @AllowNull(false) |
165 | @Column(DataType.ENUM(...values(ACTIVITY_PUB_ACTOR_TYPES))) | 166 | @Column(DataType.ENUM(...values(ACTIVITY_PUB_ACTOR_TYPES))) |
diff --git a/server/models/application/application.ts b/server/models/application/application.ts index 21f8b1cbc..5531d134a 100644 --- a/server/models/application/application.ts +++ b/server/models/application/application.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import * as memoizee from 'memoizee' | ||
1 | import { AllowNull, Column, Default, DefaultScope, HasOne, IsInt, Model, Table } from 'sequelize-typescript' | 2 | import { AllowNull, Column, Default, DefaultScope, HasOne, IsInt, Model, Table } from 'sequelize-typescript' |
3 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { AccountModel } from '../account/account' | 4 | import { AccountModel } from '../account/account' |
3 | import * as memoizee from 'memoizee' | ||
4 | 5 | ||
5 | export const getServerActor = memoizee(async function () { | 6 | export const getServerActor = memoizee(async function () { |
6 | const application = await ApplicationModel.load() | 7 | const application = await ApplicationModel.load() |
@@ -24,7 +25,7 @@ export const getServerActor = memoizee(async function () { | |||
24 | tableName: 'application', | 25 | tableName: 'application', |
25 | timestamps: false | 26 | timestamps: false |
26 | }) | 27 | }) |
27 | export class ApplicationModel extends Model { | 28 | export class ApplicationModel extends Model<Partial<AttributesOnly<ApplicationModel>>> { |
28 | 29 | ||
29 | @AllowNull(false) | 30 | @AllowNull(false) |
30 | @Default(0) | 31 | @Default(0) |
diff --git a/server/models/oauth/oauth-client.ts b/server/models/oauth/oauth-client.ts index 8dbc1c2f5..890954bdb 100644 --- a/server/models/oauth/oauth-client.ts +++ b/server/models/oauth/oauth-client.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { AllowNull, Column, CreatedAt, DataType, HasMany, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, Column, CreatedAt, DataType, HasMany, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { OAuthTokenModel } from './oauth-token' | 3 | import { OAuthTokenModel } from './oauth-token' |
3 | 4 | ||
4 | @Table({ | 5 | @Table({ |
@@ -14,7 +15,7 @@ import { OAuthTokenModel } from './oauth-token' | |||
14 | } | 15 | } |
15 | ] | 16 | ] |
16 | }) | 17 | }) |
17 | export class OAuthClientModel extends Model { | 18 | export class OAuthClientModel extends Model<Partial<AttributesOnly<OAuthClientModel>>> { |
18 | 19 | ||
19 | @AllowNull(false) | 20 | @AllowNull(false) |
20 | @Column | 21 | @Column |
diff --git a/server/models/oauth/oauth-token.ts b/server/models/oauth/oauth-token.ts index aa512a985..af4b0ec42 100644 --- a/server/models/oauth/oauth-token.ts +++ b/server/models/oauth/oauth-token.ts | |||
@@ -15,6 +15,7 @@ import { | |||
15 | import { TokensCache } from '@server/lib/auth/tokens-cache' | 15 | import { TokensCache } from '@server/lib/auth/tokens-cache' |
16 | import { MUserAccountId } from '@server/types/models' | 16 | import { MUserAccountId } from '@server/types/models' |
17 | import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' | 17 | import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' |
18 | import { AttributesOnly } from '@shared/core-utils' | ||
18 | import { logger } from '../../helpers/logger' | 19 | import { logger } from '../../helpers/logger' |
19 | import { AccountModel } from '../account/account' | 20 | import { AccountModel } from '../account/account' |
20 | import { ActorModel } from '../actor/actor' | 21 | import { ActorModel } from '../actor/actor' |
@@ -78,7 +79,7 @@ enum ScopeNames { | |||
78 | } | 79 | } |
79 | ] | 80 | ] |
80 | }) | 81 | }) |
81 | export class OAuthTokenModel extends Model { | 82 | export class OAuthTokenModel extends Model<Partial<AttributesOnly<OAuthTokenModel>>> { |
82 | 83 | ||
83 | @AllowNull(false) | 84 | @AllowNull(false) |
84 | @Column | 85 | @Column |
diff --git a/server/models/redundancy/video-redundancy.ts b/server/models/redundancy/video-redundancy.ts index b6538c8fd..ef780c2a4 100644 --- a/server/models/redundancy/video-redundancy.ts +++ b/server/models/redundancy/video-redundancy.ts | |||
@@ -16,6 +16,7 @@ import { | |||
16 | } from 'sequelize-typescript' | 16 | } from 'sequelize-typescript' |
17 | import { getServerActor } from '@server/models/application/application' | 17 | import { getServerActor } from '@server/models/application/application' |
18 | import { MActor, MVideoForRedundancyAPI, MVideoRedundancy, MVideoRedundancyAP, MVideoRedundancyVideo } from '@server/types/models' | 18 | import { MActor, MVideoForRedundancyAPI, MVideoRedundancy, MVideoRedundancyAP, MVideoRedundancyVideo } from '@server/types/models' |
19 | import { AttributesOnly } from '@shared/core-utils' | ||
19 | import { VideoRedundanciesTarget } from '@shared/models/redundancy/video-redundancies-filters.model' | 20 | import { VideoRedundanciesTarget } from '@shared/models/redundancy/video-redundancies-filters.model' |
20 | import { | 21 | import { |
21 | FileRedundancyInformation, | 22 | FileRedundancyInformation, |
@@ -84,7 +85,7 @@ export enum ScopeNames { | |||
84 | } | 85 | } |
85 | ] | 86 | ] |
86 | }) | 87 | }) |
87 | export class VideoRedundancyModel extends Model { | 88 | export class VideoRedundancyModel extends Model<Partial<AttributesOnly<VideoRedundancyModel>>> { |
88 | 89 | ||
89 | @CreatedAt | 90 | @CreatedAt |
90 | createdAt: Date | 91 | createdAt: Date |
diff --git a/server/models/server/plugin.ts b/server/models/server/plugin.ts index 94c9b04bf..8bb9649da 100644 --- a/server/models/server/plugin.ts +++ b/server/models/server/plugin.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { FindAndCountOptions, json, QueryTypes } from 'sequelize' | 1 | import { FindAndCountOptions, json, QueryTypes } from 'sequelize' |
2 | import { AllowNull, Column, CreatedAt, DataType, DefaultScope, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, Column, CreatedAt, DataType, DefaultScope, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { MPlugin, MPluginFormattable } from '@server/types/models' | 3 | import { MPlugin, MPluginFormattable } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { PeerTubePlugin, PluginType, RegisterServerSettingOptions } from '../../../shared/models' | 5 | import { PeerTubePlugin, PluginType, RegisterServerSettingOptions } from '../../../shared/models' |
5 | import { | 6 | import { |
6 | isPluginDescriptionValid, | 7 | isPluginDescriptionValid, |
@@ -26,7 +27,7 @@ import { getSort, throwIfNotValid } from '../utils' | |||
26 | } | 27 | } |
27 | ] | 28 | ] |
28 | }) | 29 | }) |
29 | export class PluginModel extends Model { | 30 | export class PluginModel extends Model<Partial<AttributesOnly<PluginModel>>> { |
30 | 31 | ||
31 | @AllowNull(false) | 32 | @AllowNull(false) |
32 | @Is('PluginName', value => throwIfNotValid(value, isPluginNameValid, 'name')) | 33 | @Is('PluginName', value => throwIfNotValid(value, isPluginNameValid, 'name')) |
diff --git a/server/models/server/server-blocklist.ts b/server/models/server/server-blocklist.ts index 4dc236537..b3579d589 100644 --- a/server/models/server/server-blocklist.ts +++ b/server/models/server/server-blocklist.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { Op } from 'sequelize' | 1 | import { Op } from 'sequelize' |
2 | import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/types/models' | 3 | import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { ServerBlock } from '@shared/models' | 5 | import { ServerBlock } from '@shared/models' |
5 | import { AccountModel } from '../account/account' | 6 | import { AccountModel } from '../account/account' |
6 | import { getSort, searchAttribute } from '../utils' | 7 | import { getSort, searchAttribute } from '../utils' |
@@ -42,7 +43,7 @@ enum ScopeNames { | |||
42 | } | 43 | } |
43 | ] | 44 | ] |
44 | }) | 45 | }) |
45 | export class ServerBlocklistModel extends Model { | 46 | export class ServerBlocklistModel extends Model<Partial<AttributesOnly<ServerBlocklistModel>>> { |
46 | 47 | ||
47 | @CreatedAt | 48 | @CreatedAt |
48 | createdAt: Date | 49 | createdAt: Date |
diff --git a/server/models/server/server.ts b/server/models/server/server.ts index fb4c15d97..25d9924fb 100644 --- a/server/models/server/server.ts +++ b/server/models/server/server.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { AllowNull, Column, CreatedAt, Default, HasMany, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, Column, CreatedAt, Default, HasMany, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { MServer, MServerFormattable } from '@server/types/models/server' | 2 | import { MServer, MServerFormattable } from '@server/types/models/server' |
3 | import { AttributesOnly } from '@shared/core-utils' | ||
3 | import { isHostValid } from '../../helpers/custom-validators/servers' | 4 | import { isHostValid } from '../../helpers/custom-validators/servers' |
4 | import { ActorModel } from '../actor/actor' | 5 | import { ActorModel } from '../actor/actor' |
5 | import { throwIfNotValid } from '../utils' | 6 | import { throwIfNotValid } from '../utils' |
@@ -14,7 +15,7 @@ import { ServerBlocklistModel } from './server-blocklist' | |||
14 | } | 15 | } |
15 | ] | 16 | ] |
16 | }) | 17 | }) |
17 | export class ServerModel extends Model { | 18 | export class ServerModel extends Model<Partial<AttributesOnly<ServerModel>>> { |
18 | 19 | ||
19 | @AllowNull(false) | 20 | @AllowNull(false) |
20 | @Is('Host', value => throwIfNotValid(value, isHostValid, 'valid host')) | 21 | @Is('Host', value => throwIfNotValid(value, isHostValid, 'valid host')) |
diff --git a/server/models/server/tracker.ts b/server/models/server/tracker.ts index 97520f92d..c09fdd64b 100644 --- a/server/models/server/tracker.ts +++ b/server/models/server/tracker.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { AllowNull, BelongsToMany, Column, CreatedAt, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, BelongsToMany, Column, CreatedAt, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { Transaction } from 'sequelize/types' | 2 | import { Transaction } from 'sequelize/types' |
3 | import { MTracker } from '@server/types/models/server/tracker' | 3 | import { MTracker } from '@server/types/models/server/tracker' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { VideoModel } from '../video/video' | 5 | import { VideoModel } from '../video/video' |
5 | import { VideoTrackerModel } from './video-tracker' | 6 | import { VideoTrackerModel } from './video-tracker' |
6 | 7 | ||
@@ -13,7 +14,7 @@ import { VideoTrackerModel } from './video-tracker' | |||
13 | } | 14 | } |
14 | ] | 15 | ] |
15 | }) | 16 | }) |
16 | export class TrackerModel extends Model { | 17 | export class TrackerModel extends Model<Partial<AttributesOnly<TrackerModel>>> { |
17 | 18 | ||
18 | @AllowNull(false) | 19 | @AllowNull(false) |
19 | @Column | 20 | @Column |
diff --git a/server/models/server/video-tracker.ts b/server/models/server/video-tracker.ts index 367bf0117..c49fbd1c6 100644 --- a/server/models/server/video-tracker.ts +++ b/server/models/server/video-tracker.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { VideoModel } from '../video/video' | 3 | import { VideoModel } from '../video/video' |
3 | import { TrackerModel } from './tracker' | 4 | import { TrackerModel } from './tracker' |
4 | 5 | ||
@@ -13,7 +14,7 @@ import { TrackerModel } from './tracker' | |||
13 | } | 14 | } |
14 | ] | 15 | ] |
15 | }) | 16 | }) |
16 | export class VideoTrackerModel extends Model { | 17 | export class VideoTrackerModel extends Model<Partial<AttributesOnly<VideoTrackerModel>>> { |
17 | @CreatedAt | 18 | @CreatedAt |
18 | createdAt: Date | 19 | createdAt: Date |
19 | 20 | ||
diff --git a/server/models/user/user-notification-setting.ts b/server/models/user/user-notification-setting.ts index 138051528..bee7d7851 100644 --- a/server/models/user/user-notification-setting.ts +++ b/server/models/user/user-notification-setting.ts | |||
@@ -14,6 +14,7 @@ import { | |||
14 | } from 'sequelize-typescript' | 14 | } from 'sequelize-typescript' |
15 | import { TokensCache } from '@server/lib/auth/tokens-cache' | 15 | import { TokensCache } from '@server/lib/auth/tokens-cache' |
16 | import { MNotificationSettingFormattable } from '@server/types/models' | 16 | import { MNotificationSettingFormattable } from '@server/types/models' |
17 | import { AttributesOnly } from '@shared/core-utils' | ||
17 | import { UserNotificationSetting, UserNotificationSettingValue } from '../../../shared/models/users/user-notification-setting.model' | 18 | import { UserNotificationSetting, UserNotificationSettingValue } from '../../../shared/models/users/user-notification-setting.model' |
18 | import { isUserNotificationSettingValid } from '../../helpers/custom-validators/user-notifications' | 19 | import { isUserNotificationSettingValid } from '../../helpers/custom-validators/user-notifications' |
19 | import { throwIfNotValid } from '../utils' | 20 | import { throwIfNotValid } from '../utils' |
@@ -28,7 +29,7 @@ import { UserModel } from './user' | |||
28 | } | 29 | } |
29 | ] | 30 | ] |
30 | }) | 31 | }) |
31 | export class UserNotificationSettingModel extends Model { | 32 | export class UserNotificationSettingModel extends Model<Partial<AttributesOnly<UserNotificationSettingModel>>> { |
32 | 33 | ||
33 | @AllowNull(false) | 34 | @AllowNull(false) |
34 | @Default(null) | 35 | @Default(null) |
diff --git a/server/models/user/user-notification.ts b/server/models/user/user-notification.ts index f7f9ac867..a7f84e9ca 100644 --- a/server/models/user/user-notification.ts +++ b/server/models/user/user-notification.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { FindOptions, ModelIndexesOptions, Op, WhereOptions } from 'sequelize' | 1 | import { FindOptions, ModelIndexesOptions, Op, WhereOptions } from 'sequelize' |
2 | import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user' | 3 | import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { UserNotification, UserNotificationType } from '../../../shared' | 5 | import { UserNotification, UserNotificationType } from '../../../shared' |
5 | import { isBooleanValid } from '../../helpers/custom-validators/misc' | 6 | import { isBooleanValid } from '../../helpers/custom-validators/misc' |
6 | import { isUserNotificationTypeValid } from '../../helpers/custom-validators/user-notifications' | 7 | import { isUserNotificationTypeValid } from '../../helpers/custom-validators/user-notifications' |
@@ -286,7 +287,7 @@ function buildAccountInclude (required: boolean, withActor = false) { | |||
286 | } | 287 | } |
287 | ] as (ModelIndexesOptions & { where?: WhereOptions })[] | 288 | ] as (ModelIndexesOptions & { where?: WhereOptions })[] |
288 | }) | 289 | }) |
289 | export class UserNotificationModel extends Model { | 290 | export class UserNotificationModel extends Model<Partial<AttributesOnly<UserNotificationModel>>> { |
290 | 291 | ||
291 | @AllowNull(false) | 292 | @AllowNull(false) |
292 | @Default(null) | 293 | @Default(null) |
diff --git a/server/models/user/user-video-history.ts b/server/models/user/user-video-history.ts index 6be1d65ea..e3dc4a062 100644 --- a/server/models/user/user-video-history.ts +++ b/server/models/user/user-video-history.ts | |||
@@ -1,8 +1,9 @@ | |||
1 | import { DestroyOptions, Op, Transaction } from 'sequelize' | ||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, IsInt, Model, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, IsInt, Model, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { MUserAccountId, MUserId } from '@server/types/models' | ||
4 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { VideoModel } from '../video/video' | 5 | import { VideoModel } from '../video/video' |
3 | import { UserModel } from './user' | 6 | import { UserModel } from './user' |
4 | import { DestroyOptions, Op, Transaction } from 'sequelize' | ||
5 | import { MUserAccountId, MUserId } from '@server/types/models' | ||
6 | 7 | ||
7 | @Table({ | 8 | @Table({ |
8 | tableName: 'userVideoHistory', | 9 | tableName: 'userVideoHistory', |
@@ -19,7 +20,7 @@ import { MUserAccountId, MUserId } from '@server/types/models' | |||
19 | } | 20 | } |
20 | ] | 21 | ] |
21 | }) | 22 | }) |
22 | export class UserVideoHistoryModel extends Model { | 23 | export class UserVideoHistoryModel extends Model<Partial<AttributesOnly<UserVideoHistoryModel>>> { |
23 | @CreatedAt | 24 | @CreatedAt |
24 | createdAt: Date | 25 | createdAt: Date |
25 | 26 | ||
diff --git a/server/models/user/user.ts b/server/models/user/user.ts index 8d2564e54..20696b1f4 100644 --- a/server/models/user/user.ts +++ b/server/models/user/user.ts | |||
@@ -31,6 +31,7 @@ import { | |||
31 | MUserWithNotificationSetting, | 31 | MUserWithNotificationSetting, |
32 | MVideoWithRights | 32 | MVideoWithRights |
33 | } from '@server/types/models' | 33 | } from '@server/types/models' |
34 | import { AttributesOnly } from '@shared/core-utils' | ||
34 | import { hasUserRight, USER_ROLE_LABELS } from '../../../shared/core-utils/users' | 35 | import { hasUserRight, USER_ROLE_LABELS } from '../../../shared/core-utils/users' |
35 | import { AbuseState, MyUser, UserRight, VideoPlaylistType, VideoPrivacy } from '../../../shared/models' | 36 | import { AbuseState, MyUser, UserRight, VideoPlaylistType, VideoPrivacy } from '../../../shared/models' |
36 | import { User, UserRole } from '../../../shared/models/users' | 37 | import { User, UserRole } from '../../../shared/models/users' |
@@ -233,7 +234,7 @@ enum ScopeNames { | |||
233 | } | 234 | } |
234 | ] | 235 | ] |
235 | }) | 236 | }) |
236 | export class UserModel extends Model { | 237 | export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> { |
237 | 238 | ||
238 | @AllowNull(true) | 239 | @AllowNull(true) |
239 | @Is('UserPassword', value => throwIfNotValid(value, isUserPasswordValid, 'user password', true)) | 240 | @Is('UserPassword', value => throwIfNotValid(value, isUserPasswordValid, 'user password', true)) |
diff --git a/server/models/utils.ts b/server/models/utils.ts index ec51c66bf..e27625bc8 100644 --- a/server/models/utils.ts +++ b/server/models/utils.ts | |||
@@ -1,5 +1,4 @@ | |||
1 | import { literal, Op, OrderItem } from 'sequelize' | 1 | import { literal, Op, OrderItem, Sequelize } from 'sequelize' |
2 | import { Model, Sequelize } from 'sequelize-typescript' | ||
3 | import { Col } from 'sequelize/types/lib/utils' | 2 | import { Col } from 'sequelize/types/lib/utils' |
4 | import validator from 'validator' | 3 | import validator from 'validator' |
5 | 4 | ||
@@ -195,11 +194,11 @@ function parseAggregateResult (result: any) { | |||
195 | return total | 194 | return total |
196 | } | 195 | } |
197 | 196 | ||
198 | const createSafeIn = (model: typeof Model, stringArr: (string | number)[]) => { | 197 | function createSafeIn (sequelize: Sequelize, stringArr: (string | number)[]) { |
199 | return stringArr.map(t => { | 198 | return stringArr.map(t => { |
200 | return t === null | 199 | return t === null |
201 | ? null | 200 | ? null |
202 | : model.sequelize.escape('' + t) | 201 | : sequelize.escape('' + t) |
203 | }).join(', ') | 202 | }).join(', ') |
204 | } | 203 | } |
205 | 204 | ||
diff --git a/server/models/video/schedule-video-update.ts b/server/models/video/schedule-video-update.ts index 22b08e91a..b0952c431 100644 --- a/server/models/video/schedule-video-update.ts +++ b/server/models/video/schedule-video-update.ts | |||
@@ -1,8 +1,9 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | ||
2 | import { ScopeNames as VideoScopeNames, VideoModel } from './video' | ||
3 | import { VideoPrivacy } from '../../../shared/models/videos' | ||
4 | import { Op, Transaction } from 'sequelize' | 1 | import { Op, Transaction } from 'sequelize' |
2 | import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | ||
5 | import { MScheduleVideoUpdateFormattable, MScheduleVideoUpdateVideoAll } from '@server/types/models' | 3 | import { MScheduleVideoUpdateFormattable, MScheduleVideoUpdateVideoAll } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
5 | import { VideoPrivacy } from '../../../shared/models/videos' | ||
6 | import { ScopeNames as VideoScopeNames, VideoModel } from './video' | ||
6 | 7 | ||
7 | @Table({ | 8 | @Table({ |
8 | tableName: 'scheduleVideoUpdate', | 9 | tableName: 'scheduleVideoUpdate', |
@@ -16,7 +17,7 @@ import { MScheduleVideoUpdateFormattable, MScheduleVideoUpdateVideoAll } from '@ | |||
16 | } | 17 | } |
17 | ] | 18 | ] |
18 | }) | 19 | }) |
19 | export class ScheduleVideoUpdateModel extends Model { | 20 | export class ScheduleVideoUpdateModel extends Model<Partial<AttributesOnly<ScheduleVideoUpdateModel>>> { |
20 | 21 | ||
21 | @AllowNull(false) | 22 | @AllowNull(false) |
22 | @Default(null) | 23 | @Default(null) |
diff --git a/server/models/video/tag.ts b/server/models/video/tag.ts index d04205703..c1eebe27f 100644 --- a/server/models/video/tag.ts +++ b/server/models/video/tag.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { col, fn, QueryTypes, Transaction } from 'sequelize' | 1 | import { col, fn, QueryTypes, Transaction } from 'sequelize' |
2 | import { AllowNull, BelongsToMany, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsToMany, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { MTag } from '@server/types/models' | 3 | import { MTag } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { VideoPrivacy, VideoState } from '../../../shared/models/videos' | 5 | import { VideoPrivacy, VideoState } from '../../../shared/models/videos' |
5 | import { isVideoTagValid } from '../../helpers/custom-validators/videos' | 6 | import { isVideoTagValid } from '../../helpers/custom-validators/videos' |
6 | import { throwIfNotValid } from '../utils' | 7 | import { throwIfNotValid } from '../utils' |
@@ -21,7 +22,7 @@ import { VideoTagModel } from './video-tag' | |||
21 | } | 22 | } |
22 | ] | 23 | ] |
23 | }) | 24 | }) |
24 | export class TagModel extends Model { | 25 | export class TagModel extends Model<Partial<AttributesOnly<TagModel>>> { |
25 | 26 | ||
26 | @AllowNull(false) | 27 | @AllowNull(false) |
27 | @Is('VideoTag', value => throwIfNotValid(value, isVideoTagValid, 'tag')) | 28 | @Is('VideoTag', value => throwIfNotValid(value, isVideoTagValid, 'tag')) |
diff --git a/server/models/video/thumbnail.ts b/server/models/video/thumbnail.ts index f1187c8d6..3388478d9 100644 --- a/server/models/video/thumbnail.ts +++ b/server/models/video/thumbnail.ts | |||
@@ -17,6 +17,7 @@ import { | |||
17 | } from 'sequelize-typescript' | 17 | } from 'sequelize-typescript' |
18 | import { afterCommitIfTransaction } from '@server/helpers/database-utils' | 18 | import { afterCommitIfTransaction } from '@server/helpers/database-utils' |
19 | import { MThumbnail, MThumbnailVideo, MVideo } from '@server/types/models' | 19 | import { MThumbnail, MThumbnailVideo, MVideo } from '@server/types/models' |
20 | import { AttributesOnly } from '@shared/core-utils' | ||
20 | import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' | 21 | import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' |
21 | import { logger } from '../../helpers/logger' | 22 | import { logger } from '../../helpers/logger' |
22 | import { CONFIG } from '../../initializers/config' | 23 | import { CONFIG } from '../../initializers/config' |
@@ -40,7 +41,7 @@ import { VideoPlaylistModel } from './video-playlist' | |||
40 | } | 41 | } |
41 | ] | 42 | ] |
42 | }) | 43 | }) |
43 | export class ThumbnailModel extends Model { | 44 | export class ThumbnailModel extends Model<Partial<AttributesOnly<ThumbnailModel>>> { |
44 | 45 | ||
45 | @AllowNull(false) | 46 | @AllowNull(false) |
46 | @Column | 47 | @Column |
diff --git a/server/models/video/video-blacklist.ts b/server/models/video/video-blacklist.ts index aa18896da..98f4ec9c5 100644 --- a/server/models/video/video-blacklist.ts +++ b/server/models/video/video-blacklist.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { FindOptions } from 'sequelize' | 1 | import { FindOptions } from 'sequelize' |
2 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/models' | 3 | import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos' | 5 | import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos' |
5 | import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist' | 6 | import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist' |
6 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' | 7 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' |
@@ -18,7 +19,7 @@ import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel | |||
18 | } | 19 | } |
19 | ] | 20 | ] |
20 | }) | 21 | }) |
21 | export class VideoBlacklistModel extends Model { | 22 | export class VideoBlacklistModel extends Model<Partial<AttributesOnly<VideoBlacklistModel>>> { |
22 | 23 | ||
23 | @AllowNull(true) | 24 | @AllowNull(true) |
24 | @Is('VideoBlacklistReason', value => throwIfNotValid(value, isVideoBlacklistReasonValid, 'reason', true)) | 25 | @Is('VideoBlacklistReason', value => throwIfNotValid(value, isVideoBlacklistReasonValid, 'reason', true)) |
diff --git a/server/models/video/video-caption.ts b/server/models/video/video-caption.ts index bfdec73e9..d2c742b66 100644 --- a/server/models/video/video-caption.ts +++ b/server/models/video/video-caption.ts | |||
@@ -17,6 +17,7 @@ import { | |||
17 | } from 'sequelize-typescript' | 17 | } from 'sequelize-typescript' |
18 | import { v4 as uuidv4 } from 'uuid' | 18 | import { v4 as uuidv4 } from 'uuid' |
19 | import { MVideo, MVideoCaption, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models' | 19 | import { MVideo, MVideoCaption, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models' |
20 | import { AttributesOnly } from '@shared/core-utils' | ||
20 | import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model' | 21 | import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model' |
21 | import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions' | 22 | import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions' |
22 | import { logger } from '../../helpers/logger' | 23 | import { logger } from '../../helpers/logger' |
@@ -57,7 +58,7 @@ export enum ScopeNames { | |||
57 | } | 58 | } |
58 | ] | 59 | ] |
59 | }) | 60 | }) |
60 | export class VideoCaptionModel extends Model { | 61 | export class VideoCaptionModel extends Model<Partial<AttributesOnly<VideoCaptionModel>>> { |
61 | @CreatedAt | 62 | @CreatedAt |
62 | createdAt: Date | 63 | createdAt: Date |
63 | 64 | ||
diff --git a/server/models/video/video-change-ownership.ts b/server/models/video/video-change-ownership.ts index 298e8bfe2..7d20a954d 100644 --- a/server/models/video/video-change-ownership.ts +++ b/server/models/video/video-change-ownership.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { MVideoChangeOwnershipFormattable, MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership' | 2 | import { MVideoChangeOwnershipFormattable, MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership' |
3 | import { AttributesOnly } from '@shared/core-utils' | ||
3 | import { VideoChangeOwnership, VideoChangeOwnershipStatus } from '../../../shared/models/videos' | 4 | import { VideoChangeOwnership, VideoChangeOwnershipStatus } from '../../../shared/models/videos' |
4 | import { AccountModel } from '../account/account' | 5 | import { AccountModel } from '../account/account' |
5 | import { getSort } from '../utils' | 6 | import { getSort } from '../utils' |
@@ -53,7 +54,7 @@ enum ScopeNames { | |||
53 | ] | 54 | ] |
54 | } | 55 | } |
55 | })) | 56 | })) |
56 | export class VideoChangeOwnershipModel extends Model { | 57 | export class VideoChangeOwnershipModel extends Model<Partial<AttributesOnly<VideoChangeOwnershipModel>>> { |
57 | @CreatedAt | 58 | @CreatedAt |
58 | createdAt: Date | 59 | createdAt: Date |
59 | 60 | ||
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index 8e4b78723..8c4357009 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts | |||
@@ -19,6 +19,7 @@ import { | |||
19 | } from 'sequelize-typescript' | 19 | } from 'sequelize-typescript' |
20 | import { setAsUpdated } from '@server/helpers/database-utils' | 20 | import { setAsUpdated } from '@server/helpers/database-utils' |
21 | import { MAccountActor } from '@server/types/models' | 21 | import { MAccountActor } from '@server/types/models' |
22 | import { AttributesOnly } from '@shared/core-utils' | ||
22 | import { ActivityPubActor } from '../../../shared/models/activitypub' | 23 | import { ActivityPubActor } from '../../../shared/models/activitypub' |
23 | import { VideoChannel, VideoChannelSummary } from '../../../shared/models/videos' | 24 | import { VideoChannel, VideoChannelSummary } from '../../../shared/models/videos' |
24 | import { | 25 | import { |
@@ -246,7 +247,7 @@ export type SummaryOptions = { | |||
246 | } | 247 | } |
247 | ] | 248 | ] |
248 | }) | 249 | }) |
249 | export class VideoChannelModel extends Model { | 250 | export class VideoChannelModel extends Model<Partial<AttributesOnly<VideoChannelModel>>> { |
250 | 251 | ||
251 | @AllowNull(false) | 252 | @AllowNull(false) |
252 | @Is('VideoChannelName', value => throwIfNotValid(value, isVideoChannelNameValid, 'name')) | 253 | @Is('VideoChannelName', value => throwIfNotValid(value, isVideoChannelNameValid, 'name')) |
diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts index ffd324526..bdf5d86bc 100644 --- a/server/models/video/video-comment.ts +++ b/server/models/video/video-comment.ts | |||
@@ -16,6 +16,7 @@ import { | |||
16 | } from 'sequelize-typescript' | 16 | } from 'sequelize-typescript' |
17 | import { getServerActor } from '@server/models/application/application' | 17 | import { getServerActor } from '@server/models/application/application' |
18 | import { MAccount, MAccountId, MUserAccountId } from '@server/types/models' | 18 | import { MAccount, MAccountId, MUserAccountId } from '@server/types/models' |
19 | import { AttributesOnly } from '@shared/core-utils' | ||
19 | import { VideoPrivacy } from '@shared/models' | 20 | import { VideoPrivacy } from '@shared/models' |
20 | import { ActivityTagObject, ActivityTombstoneObject } from '../../../shared/models/activitypub/objects/common-objects' | 21 | import { ActivityTagObject, ActivityTombstoneObject } from '../../../shared/models/activitypub/objects/common-objects' |
21 | import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object' | 22 | import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object' |
@@ -173,7 +174,7 @@ export enum ScopeNames { | |||
173 | } | 174 | } |
174 | ] | 175 | ] |
175 | }) | 176 | }) |
176 | export class VideoCommentModel extends Model { | 177 | export class VideoCommentModel extends Model<Partial<AttributesOnly<VideoCommentModel>>> { |
177 | @CreatedAt | 178 | @CreatedAt |
178 | createdAt: Date | 179 | createdAt: Date |
179 | 180 | ||
diff --git a/server/models/video/video-file.ts b/server/models/video/video-file.ts index 1ad796104..e3fa2f3d2 100644 --- a/server/models/video/video-file.ts +++ b/server/models/video/video-file.ts | |||
@@ -25,6 +25,7 @@ import { logger } from '@server/helpers/logger' | |||
25 | import { extractVideo } from '@server/helpers/video' | 25 | import { extractVideo } from '@server/helpers/video' |
26 | import { getTorrentFilePath } from '@server/lib/video-paths' | 26 | import { getTorrentFilePath } from '@server/lib/video-paths' |
27 | import { MStreamingPlaylistVideo, MVideo, MVideoWithHost } from '@server/types/models' | 27 | import { MStreamingPlaylistVideo, MVideo, MVideoWithHost } from '@server/types/models' |
28 | import { AttributesOnly } from '@shared/core-utils' | ||
28 | import { | 29 | import { |
29 | isVideoFileExtnameValid, | 30 | isVideoFileExtnameValid, |
30 | isVideoFileInfoHashValid, | 31 | isVideoFileInfoHashValid, |
@@ -149,7 +150,7 @@ export enum ScopeNames { | |||
149 | } | 150 | } |
150 | ] | 151 | ] |
151 | }) | 152 | }) |
152 | export class VideoFileModel extends Model { | 153 | export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>>> { |
153 | @CreatedAt | 154 | @CreatedAt |
154 | createdAt: Date | 155 | createdAt: Date |
155 | 156 | ||
diff --git a/server/models/video/video-import.ts b/server/models/video/video-import.ts index d8f09e1e5..5c73fb07c 100644 --- a/server/models/video/video-import.ts +++ b/server/models/video/video-import.ts | |||
@@ -15,6 +15,7 @@ import { | |||
15 | } from 'sequelize-typescript' | 15 | } from 'sequelize-typescript' |
16 | import { afterCommitIfTransaction } from '@server/helpers/database-utils' | 16 | import { afterCommitIfTransaction } from '@server/helpers/database-utils' |
17 | import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/models/video/video-import' | 17 | import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/models/video/video-import' |
18 | import { AttributesOnly } from '@shared/core-utils' | ||
18 | import { VideoImport, VideoImportState } from '../../../shared' | 19 | import { VideoImport, VideoImportState } from '../../../shared' |
19 | import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports' | 20 | import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports' |
20 | import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos' | 21 | import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos' |
@@ -52,7 +53,7 @@ import { ScopeNames as VideoModelScopeNames, VideoModel } from './video' | |||
52 | } | 53 | } |
53 | ] | 54 | ] |
54 | }) | 55 | }) |
55 | export class VideoImportModel extends Model { | 56 | export class VideoImportModel extends Model<Partial<AttributesOnly<VideoImportModel>>> { |
56 | @CreatedAt | 57 | @CreatedAt |
57 | createdAt: Date | 58 | createdAt: Date |
58 | 59 | ||
diff --git a/server/models/video/video-live.ts b/server/models/video/video-live.ts index cb4a9b896..014491d50 100644 --- a/server/models/video/video-live.ts +++ b/server/models/video/video-live.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, DefaultScope, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, DefaultScope, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { WEBSERVER } from '@server/initializers/constants' | 2 | import { WEBSERVER } from '@server/initializers/constants' |
3 | import { MVideoLive, MVideoLiveVideo } from '@server/types/models' | 3 | import { MVideoLive, MVideoLiveVideo } from '@server/types/models' |
4 | import { AttributesOnly } from '@shared/core-utils' | ||
4 | import { LiveVideo, VideoState } from '@shared/models' | 5 | import { LiveVideo, VideoState } from '@shared/models' |
5 | import { VideoModel } from './video' | 6 | import { VideoModel } from './video' |
6 | import { VideoBlacklistModel } from './video-blacklist' | 7 | import { VideoBlacklistModel } from './video-blacklist' |
@@ -28,7 +29,7 @@ import { VideoBlacklistModel } from './video-blacklist' | |||
28 | } | 29 | } |
29 | ] | 30 | ] |
30 | }) | 31 | }) |
31 | export class VideoLiveModel extends Model { | 32 | export class VideoLiveModel extends Model<Partial<AttributesOnly<VideoLiveModel>>> { |
32 | 33 | ||
33 | @AllowNull(true) | 34 | @AllowNull(true) |
34 | @Column(DataType.STRING) | 35 | @Column(DataType.STRING) |
diff --git a/server/models/video/video-playlist-element.ts b/server/models/video/video-playlist-element.ts index d2d7e2740..e6906cb19 100644 --- a/server/models/video/video-playlist-element.ts +++ b/server/models/video/video-playlist-element.ts | |||
@@ -32,6 +32,7 @@ import { AccountModel } from '../account/account' | |||
32 | import { getSort, throwIfNotValid } from '../utils' | 32 | import { getSort, throwIfNotValid } from '../utils' |
33 | import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './video' | 33 | import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './video' |
34 | import { VideoPlaylistModel } from './video-playlist' | 34 | import { VideoPlaylistModel } from './video-playlist' |
35 | import { AttributesOnly } from '@shared/core-utils' | ||
35 | 36 | ||
36 | @Table({ | 37 | @Table({ |
37 | tableName: 'videoPlaylistElement', | 38 | tableName: 'videoPlaylistElement', |
@@ -48,7 +49,7 @@ import { VideoPlaylistModel } from './video-playlist' | |||
48 | } | 49 | } |
49 | ] | 50 | ] |
50 | }) | 51 | }) |
51 | export class VideoPlaylistElementModel extends Model { | 52 | export class VideoPlaylistElementModel extends Model<Partial<AttributesOnly<VideoPlaylistElementModel>>> { |
52 | @CreatedAt | 53 | @CreatedAt |
53 | createdAt: Date | 54 | createdAt: Date |
54 | 55 | ||
@@ -274,7 +275,8 @@ export class VideoPlaylistElementModel extends Model { | |||
274 | validate: false // We use a literal to update the position | 275 | validate: false // We use a literal to update the position |
275 | } | 276 | } |
276 | 277 | ||
277 | return VideoPlaylistElementModel.update({ position: Sequelize.literal(`${newPosition} + "position" - ${firstPosition}`) }, query) | 278 | const positionQuery = Sequelize.literal(`${newPosition} + "position" - ${firstPosition}`) |
279 | return VideoPlaylistElementModel.update({ position: positionQuery as any }, query) | ||
278 | } | 280 | } |
279 | 281 | ||
280 | static increasePositionOf ( | 282 | static increasePositionOf ( |
diff --git a/server/models/video/video-playlist.ts b/server/models/video/video-playlist.ts index b48dd2945..c293287d3 100644 --- a/server/models/video/video-playlist.ts +++ b/server/models/video/video-playlist.ts | |||
@@ -19,6 +19,7 @@ import { | |||
19 | } from 'sequelize-typescript' | 19 | } from 'sequelize-typescript' |
20 | import { v4 as uuidv4 } from 'uuid' | 20 | import { v4 as uuidv4 } from 'uuid' |
21 | import { MAccountId, MChannelId } from '@server/types/models' | 21 | import { MAccountId, MChannelId } from '@server/types/models' |
22 | import { AttributesOnly } from '@shared/core-utils' | ||
22 | import { ActivityIconObject } from '../../../shared/models/activitypub/objects' | 23 | import { ActivityIconObject } from '../../../shared/models/activitypub/objects' |
23 | import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object' | 24 | import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object' |
24 | import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model' | 25 | import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model' |
@@ -221,7 +222,7 @@ type AvailableForListOptions = { | |||
221 | } | 222 | } |
222 | ] | 223 | ] |
223 | }) | 224 | }) |
224 | export class VideoPlaylistModel extends Model { | 225 | export class VideoPlaylistModel extends Model<Partial<AttributesOnly<VideoPlaylistModel>>> { |
225 | @CreatedAt | 226 | @CreatedAt |
226 | createdAt: Date | 227 | createdAt: Date |
227 | 228 | ||
diff --git a/server/models/video/video-query-builder.ts b/server/models/video/video-query-builder.ts index 155afe64b..2aa5e65c8 100644 --- a/server/models/video/video-query-builder.ts +++ b/server/models/video/video-query-builder.ts | |||
@@ -1,9 +1,9 @@ | |||
1 | import { VideoFilter, VideoPrivacy, VideoState } from '@shared/models' | 1 | import { Sequelize } from 'sequelize/types' |
2 | import { buildDirectionAndField, createSafeIn } from '@server/models/utils' | ||
3 | import { Model } from 'sequelize-typescript' | ||
4 | import { MUserAccountId, MUserId } from '@server/types/models' | ||
5 | import validator from 'validator' | 2 | import validator from 'validator' |
6 | import { exists } from '@server/helpers/custom-validators/misc' | 3 | import { exists } from '@server/helpers/custom-validators/misc' |
4 | import { buildDirectionAndField, createSafeIn } from '@server/models/utils' | ||
5 | import { MUserAccountId, MUserId } from '@server/types/models' | ||
6 | import { VideoFilter, VideoPrivacy, VideoState } from '@shared/models' | ||
7 | 7 | ||
8 | export type BuildVideosQueryOptions = { | 8 | export type BuildVideosQueryOptions = { |
9 | attributes?: string[] | 9 | attributes?: string[] |
@@ -55,7 +55,7 @@ export type BuildVideosQueryOptions = { | |||
55 | having?: string | 55 | having?: string |
56 | } | 56 | } |
57 | 57 | ||
58 | function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions) { | 58 | function buildListQuery (sequelize: Sequelize, options: BuildVideosQueryOptions) { |
59 | const and: string[] = [] | 59 | const and: string[] = [] |
60 | const joins: string[] = [] | 60 | const joins: string[] = [] |
61 | const replacements: any = {} | 61 | const replacements: any = {} |
@@ -77,7 +77,7 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions) | |||
77 | const blockerIds = [ options.serverAccountId ] | 77 | const blockerIds = [ options.serverAccountId ] |
78 | if (options.user) blockerIds.push(options.user.Account.id) | 78 | if (options.user) blockerIds.push(options.user.Account.id) |
79 | 79 | ||
80 | const inClause = createSafeIn(model, blockerIds) | 80 | const inClause = createSafeIn(sequelize, blockerIds) |
81 | 81 | ||
82 | and.push( | 82 | and.push( |
83 | 'NOT EXISTS (' + | 83 | 'NOT EXISTS (' + |
@@ -179,7 +179,7 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions) | |||
179 | 'EXISTS (' + | 179 | 'EXISTS (' + |
180 | ' SELECT 1 FROM "videoTag" ' + | 180 | ' SELECT 1 FROM "videoTag" ' + |
181 | ' INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + | 181 | ' INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + |
182 | ' WHERE lower("tag"."name") IN (' + createSafeIn(model, tagsOneOfLower) + ') ' + | 182 | ' WHERE lower("tag"."name") IN (' + createSafeIn(sequelize, tagsOneOfLower) + ') ' + |
183 | ' AND "video"."id" = "videoTag"."videoId"' + | 183 | ' AND "video"."id" = "videoTag"."videoId"' + |
184 | ')' | 184 | ')' |
185 | ) | 185 | ) |
@@ -192,7 +192,7 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions) | |||
192 | 'EXISTS (' + | 192 | 'EXISTS (' + |
193 | ' SELECT 1 FROM "videoTag" ' + | 193 | ' SELECT 1 FROM "videoTag" ' + |
194 | ' INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + | 194 | ' INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + |
195 | ' WHERE lower("tag"."name") IN (' + createSafeIn(model, tagsAllOfLower) + ') ' + | 195 | ' WHERE lower("tag"."name") IN (' + createSafeIn(sequelize, tagsAllOfLower) + ') ' + |
196 | ' AND "video"."id" = "videoTag"."videoId" ' + | 196 | ' AND "video"."id" = "videoTag"."videoId" ' + |
197 | ' GROUP BY "videoTag"."videoId" HAVING COUNT(*) = ' + tagsAllOfLower.length + | 197 | ' GROUP BY "videoTag"."videoId" HAVING COUNT(*) = ' + tagsAllOfLower.length + |
198 | ')' | 198 | ')' |
@@ -232,7 +232,7 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions) | |||
232 | languagesQueryParts.push( | 232 | languagesQueryParts.push( |
233 | 'EXISTS (' + | 233 | 'EXISTS (' + |
234 | ' SELECT 1 FROM "videoCaption" WHERE "videoCaption"."language" ' + | 234 | ' SELECT 1 FROM "videoCaption" WHERE "videoCaption"."language" ' + |
235 | ' IN (' + createSafeIn(model, languages) + ') AND ' + | 235 | ' IN (' + createSafeIn(sequelize, languages) + ') AND ' + |
236 | ' "videoCaption"."videoId" = "video"."id"' + | 236 | ' "videoCaption"."videoId" = "video"."id"' + |
237 | ')' | 237 | ')' |
238 | ) | 238 | ) |
@@ -345,8 +345,8 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions) | |||
345 | } | 345 | } |
346 | 346 | ||
347 | if (options.search) { | 347 | if (options.search) { |
348 | const escapedSearch = model.sequelize.escape(options.search) | 348 | const escapedSearch = sequelize.escape(options.search) |
349 | const escapedLikeSearch = model.sequelize.escape('%' + options.search + '%') | 349 | const escapedLikeSearch = sequelize.escape('%' + options.search + '%') |
350 | 350 | ||
351 | cte.push( | 351 | cte.push( |
352 | '"trigramSearch" AS (' + | 352 | '"trigramSearch" AS (' + |
diff --git a/server/models/video/video-share.ts b/server/models/video/video-share.ts index 99a24dbdf..505c305e2 100644 --- a/server/models/video/video-share.ts +++ b/server/models/video/video-share.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { literal, Op, QueryTypes, Transaction } from 'sequelize' | 1 | import { literal, Op, QueryTypes, Transaction } from 'sequelize' |
2 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' |
3 | import { AttributesOnly } from '@shared/core-utils' | ||
3 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 4 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
4 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' | 5 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' |
5 | import { MActorDefault } from '../../types/models' | 6 | import { MActorDefault } from '../../types/models' |
@@ -50,7 +51,7 @@ enum ScopeNames { | |||
50 | } | 51 | } |
51 | ] | 52 | ] |
52 | }) | 53 | }) |
53 | export class VideoShareModel extends Model { | 54 | export class VideoShareModel extends Model<Partial<AttributesOnly<VideoShareModel>>> { |
54 | 55 | ||
55 | @AllowNull(false) | 56 | @AllowNull(false) |
56 | @Is('VideoShareUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url')) | 57 | @Is('VideoShareUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url')) |
diff --git a/server/models/video/video-streaming-playlist.ts b/server/models/video/video-streaming-playlist.ts index c9375b433..d627e8c9d 100644 --- a/server/models/video/video-streaming-playlist.ts +++ b/server/models/video/video-streaming-playlist.ts | |||
@@ -13,6 +13,7 @@ import { CONSTRAINTS_FIELDS, MEMOIZE_LENGTH, MEMOIZE_TTL, P2P_MEDIA_LOADER_PEER_ | |||
13 | import { VideoRedundancyModel } from '../redundancy/video-redundancy' | 13 | import { VideoRedundancyModel } from '../redundancy/video-redundancy' |
14 | import { throwIfNotValid } from '../utils' | 14 | import { throwIfNotValid } from '../utils' |
15 | import { VideoModel } from './video' | 15 | import { VideoModel } from './video' |
16 | import { AttributesOnly } from '@shared/core-utils' | ||
16 | 17 | ||
17 | @Table({ | 18 | @Table({ |
18 | tableName: 'videoStreamingPlaylist', | 19 | tableName: 'videoStreamingPlaylist', |
@@ -30,7 +31,7 @@ import { VideoModel } from './video' | |||
30 | } | 31 | } |
31 | ] | 32 | ] |
32 | }) | 33 | }) |
33 | export class VideoStreamingPlaylistModel extends Model { | 34 | export class VideoStreamingPlaylistModel extends Model<Partial<AttributesOnly<VideoStreamingPlaylistModel>>> { |
34 | @CreatedAt | 35 | @CreatedAt |
35 | createdAt: Date | 36 | createdAt: Date |
36 | 37 | ||
diff --git a/server/models/video/video-tag.ts b/server/models/video/video-tag.ts index 5052b8c4d..1285d375b 100644 --- a/server/models/video/video-tag.ts +++ b/server/models/video/video-tag.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { TagModel } from './tag' | 3 | import { TagModel } from './tag' |
3 | import { VideoModel } from './video' | 4 | import { VideoModel } from './video' |
4 | 5 | ||
@@ -13,7 +14,7 @@ import { VideoModel } from './video' | |||
13 | } | 14 | } |
14 | ] | 15 | ] |
15 | }) | 16 | }) |
16 | export class VideoTagModel extends Model { | 17 | export class VideoTagModel extends Model<Partial<AttributesOnly<VideoTagModel>>> { |
17 | @CreatedAt | 18 | @CreatedAt |
18 | createdAt: Date | 19 | createdAt: Date |
19 | 20 | ||
diff --git a/server/models/video/video-view.ts b/server/models/video/video-view.ts index 992cf258a..dfc6296ce 100644 --- a/server/models/video/video-view.ts +++ b/server/models/video/video-view.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Table } from 'sequelize-typescript' | 2 | import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Table } from 'sequelize-typescript' |
3 | import { AttributesOnly } from '@shared/core-utils' | ||
2 | import { VideoModel } from './video' | 4 | import { VideoModel } from './video' |
3 | import * as Sequelize from 'sequelize' | ||
4 | 5 | ||
5 | @Table({ | 6 | @Table({ |
6 | tableName: 'videoView', | 7 | tableName: 'videoView', |
@@ -14,7 +15,7 @@ import * as Sequelize from 'sequelize' | |||
14 | } | 15 | } |
15 | ] | 16 | ] |
16 | }) | 17 | }) |
17 | export class VideoViewModel extends Model { | 18 | export class VideoViewModel extends Model<Partial<AttributesOnly<VideoViewModel>>> { |
18 | @CreatedAt | 19 | @CreatedAt |
19 | createdAt: Date | 20 | createdAt: Date |
20 | 21 | ||
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index f8a099d9c..749ef7197 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -31,6 +31,7 @@ import { LiveManager } from '@server/lib/live-manager' | |||
31 | import { getHLSDirectory, getVideoFilePath } from '@server/lib/video-paths' | 31 | import { getHLSDirectory, getVideoFilePath } from '@server/lib/video-paths' |
32 | import { getServerActor } from '@server/models/application/application' | 32 | import { getServerActor } from '@server/models/application/application' |
33 | import { ModelCache } from '@server/models/model-cache' | 33 | import { ModelCache } from '@server/models/model-cache' |
34 | import { AttributesOnly } from '@shared/core-utils' | ||
34 | import { VideoFile } from '@shared/models/videos/video-file.model' | 35 | import { VideoFile } from '@shared/models/videos/video-file.model' |
35 | import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared' | 36 | import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared' |
36 | import { VideoObject } from '../../../shared/models/activitypub/objects' | 37 | import { VideoObject } from '../../../shared/models/activitypub/objects' |
@@ -489,7 +490,7 @@ export type AvailableForListIDsOptions = { | |||
489 | } | 490 | } |
490 | ] | 491 | ] |
491 | }) | 492 | }) |
492 | export class VideoModel extends Model { | 493 | export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { |
493 | 494 | ||
494 | @AllowNull(false) | 495 | @AllowNull(false) |
495 | @Default(DataType.UUIDV4) | 496 | @Default(DataType.UUIDV4) |
@@ -1617,7 +1618,7 @@ export class VideoModel extends Model { | |||
1617 | includeLocalVideos: true | 1618 | includeLocalVideos: true |
1618 | } | 1619 | } |
1619 | 1620 | ||
1620 | const { query, replacements } = buildListQuery(VideoModel, queryOptions) | 1621 | const { query, replacements } = buildListQuery(VideoModel.sequelize, queryOptions) |
1621 | 1622 | ||
1622 | return this.sequelize.query<any>(query, { replacements, type: QueryTypes.SELECT }) | 1623 | return this.sequelize.query<any>(query, { replacements, type: QueryTypes.SELECT }) |
1623 | .then(rows => rows.map(r => r[field])) | 1624 | .then(rows => rows.map(r => r[field])) |
@@ -1645,7 +1646,7 @@ export class VideoModel extends Model { | |||
1645 | if (countVideos !== true) return Promise.resolve(undefined) | 1646 | if (countVideos !== true) return Promise.resolve(undefined) |
1646 | 1647 | ||
1647 | const countOptions = Object.assign({}, options, { isCount: true }) | 1648 | const countOptions = Object.assign({}, options, { isCount: true }) |
1648 | const { query: queryCount, replacements: replacementsCount } = buildListQuery(VideoModel, countOptions) | 1649 | const { query: queryCount, replacements: replacementsCount } = buildListQuery(VideoModel.sequelize, countOptions) |
1649 | 1650 | ||
1650 | return VideoModel.sequelize.query<any>(queryCount, { replacements: replacementsCount, type: QueryTypes.SELECT }) | 1651 | return VideoModel.sequelize.query<any>(queryCount, { replacements: replacementsCount, type: QueryTypes.SELECT }) |
1651 | .then(rows => rows.length !== 0 ? rows[0].total : 0) | 1652 | .then(rows => rows.length !== 0 ? rows[0].total : 0) |
@@ -1654,7 +1655,7 @@ export class VideoModel extends Model { | |||
1654 | function getModels () { | 1655 | function getModels () { |
1655 | if (options.count === 0) return Promise.resolve([]) | 1656 | if (options.count === 0) return Promise.resolve([]) |
1656 | 1657 | ||
1657 | const { query, replacements, order } = buildListQuery(VideoModel, options) | 1658 | const { query, replacements, order } = buildListQuery(VideoModel.sequelize, options) |
1658 | const queryModels = wrapForAPIResults(query, replacements, options, order) | 1659 | const queryModels = wrapForAPIResults(query, replacements, options, order) |
1659 | 1660 | ||
1660 | return VideoModel.sequelize.query<any>(queryModels, { replacements, type: QueryTypes.SELECT, nest: true }) | 1661 | return VideoModel.sequelize.query<any>(queryModels, { replacements, type: QueryTypes.SELECT, nest: true }) |
diff --git a/server/types/sequelize.ts b/server/types/sequelize.ts index 9cd83612d..535113d01 100644 --- a/server/types/sequelize.ts +++ b/server/types/sequelize.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { Model } from 'sequelize-typescript' | 1 | import { AttributesOnly } from '@shared/core-utils' |
2 | import { Model } from 'sequelize' | ||
2 | 3 | ||
3 | // Thanks to sequelize-typescript: https://github.com/RobinBuschmann/sequelize-typescript | 4 | // Thanks to sequelize-typescript: https://github.com/RobinBuschmann/sequelize-typescript |
4 | 5 | ||
@@ -9,7 +10,7 @@ export type Omit<T, K extends keyof T> = { [P in Diff<keyof T, K>]: T[P] } | |||
9 | 10 | ||
10 | export type RecursivePartial<T> = { [P in keyof T]?: RecursivePartial<T[P]> } | 11 | export type RecursivePartial<T> = { [P in keyof T]?: RecursivePartial<T[P]> } |
11 | 12 | ||
12 | export type FilteredModelAttributes<T extends Model<T>> = RecursivePartial<Omit<T, keyof Model<any>>> & { | 13 | export type FilteredModelAttributes<T extends Model<any>> = Partial<AttributesOnly<T>> & { |
13 | id?: number | any | 14 | id?: number | any |
14 | createdAt?: Date | any | 15 | createdAt?: Date | any |
15 | updatedAt?: Date | any | 16 | updatedAt?: Date | any |
diff --git a/shared/core-utils/miscs/types.ts b/shared/core-utils/miscs/types.ts index bb64dc830..bd2a97b98 100644 --- a/shared/core-utils/miscs/types.ts +++ b/shared/core-utils/miscs/types.ts | |||
@@ -6,6 +6,10 @@ export type FunctionPropertyNames<T> = { | |||
6 | 6 | ||
7 | export type FunctionProperties<T> = Pick<T, FunctionPropertyNames<T>> | 7 | export type FunctionProperties<T> = Pick<T, FunctionPropertyNames<T>> |
8 | 8 | ||
9 | export type AttributesOnly<T> = { | ||
10 | [K in keyof T]: T[K] extends Function ? never : T[K] | ||
11 | } | ||
12 | |||
9 | export type PickWith<T, KT extends keyof T, V> = { | 13 | export type PickWith<T, KT extends keyof T, V> = { |
10 | [P in KT]: T[P] extends V ? V : never | 14 | [P in KT]: T[P] extends V ? V : never |
11 | } | 15 | } |