Type server models (#6326)
* fix: type server models * fix: make ParanoidModel generic * fix: ApiKey * fix: Attachment * fix: AuthenticationProvider * fix: Backlink * fix: Collection * fix: Comment * fix: Document * fix: FileOperation * fix: Group * fix: GroupPermission * fix: GroupUser * fix: Integration * fix: IntegrationAuthentication * fix: Notification * fix: Pin * fix: Revision * fix: SearchQuery * fix: Share * fix: Star * fix: Subscription * fix: TypeError * fix: Imports * fix: Team * fix: TeamDomain * fix: User * fix: UserAuthentication * fix: UserPermission * fix: View * fix: WebhookDelivery * fix: WebhookSubscription * Remove type duplication --------- Co-authored-by: Tom Moor <tom.moor@gmail.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import randomstring from "randomstring";
|
||||
import { InferAttributes, InferCreationAttributes } from "sequelize";
|
||||
import {
|
||||
Column,
|
||||
Table,
|
||||
@@ -14,7 +15,10 @@ import Length from "./validators/Length";
|
||||
|
||||
@Table({ tableName: "apiKeys", modelName: "apiKey" })
|
||||
@Fix
|
||||
class ApiKey extends ParanoidModel {
|
||||
class ApiKey extends ParanoidModel<
|
||||
InferAttributes<ApiKey>,
|
||||
Partial<InferCreationAttributes<ApiKey>>
|
||||
> {
|
||||
static prefix = "ol_api_";
|
||||
|
||||
@Length({
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { createReadStream } from "fs";
|
||||
import path from "path";
|
||||
import { File } from "formidable";
|
||||
import { QueryTypes } from "sequelize";
|
||||
import {
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
QueryTypes,
|
||||
} from "sequelize";
|
||||
import {
|
||||
BeforeDestroy,
|
||||
BelongsTo,
|
||||
@@ -25,7 +29,10 @@ import Length from "./validators/Length";
|
||||
|
||||
@Table({ tableName: "attachments", modelName: "attachment" })
|
||||
@Fix
|
||||
class Attachment extends IdModel {
|
||||
class Attachment extends IdModel<
|
||||
InferAttributes<Attachment>,
|
||||
Partial<InferCreationAttributes<Attachment>>
|
||||
> {
|
||||
@Length({
|
||||
max: 4096,
|
||||
msg: "key must be 4096 characters or less",
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { Op, SaveOptions } from "sequelize";
|
||||
import {
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
InstanceUpdateOptions,
|
||||
Op,
|
||||
} from "sequelize";
|
||||
import {
|
||||
BelongsTo,
|
||||
Column,
|
||||
@@ -8,11 +13,11 @@ import {
|
||||
ForeignKey,
|
||||
HasMany,
|
||||
Table,
|
||||
Model,
|
||||
IsUUID,
|
||||
PrimaryKey,
|
||||
} from "sequelize-typescript";
|
||||
import env from "@server/env";
|
||||
import Model from "@server/models/base/Model";
|
||||
import AzureClient from "@server/utils/azure";
|
||||
import GoogleClient from "@server/utils/google";
|
||||
import OIDCClient from "@server/utils/oidc";
|
||||
@@ -28,7 +33,10 @@ import Length from "./validators/Length";
|
||||
updatedAt: false,
|
||||
})
|
||||
@Fix
|
||||
class AuthenticationProvider extends Model {
|
||||
class AuthenticationProvider extends Model<
|
||||
InferAttributes<AuthenticationProvider>,
|
||||
Partial<InferCreationAttributes<AuthenticationProvider>>
|
||||
> {
|
||||
@IsUUID(4)
|
||||
@PrimaryKey
|
||||
@Default(DataType.UUIDV4)
|
||||
@@ -97,7 +105,9 @@ class AuthenticationProvider extends Model {
|
||||
}
|
||||
}
|
||||
|
||||
disable = async (options?: SaveOptions<AuthenticationProvider>) => {
|
||||
disable: (
|
||||
options?: InstanceUpdateOptions<InferAttributes<AuthenticationProvider>>
|
||||
) => Promise<AuthenticationProvider> = async (options) => {
|
||||
const res = await (
|
||||
this.constructor as typeof AuthenticationProvider
|
||||
).findAndCountAll({
|
||||
@@ -124,7 +134,9 @@ class AuthenticationProvider extends Model {
|
||||
}
|
||||
};
|
||||
|
||||
enable = (options?: SaveOptions<AuthenticationProvider>) =>
|
||||
enable: (
|
||||
options?: InstanceUpdateOptions<InferAttributes<AuthenticationProvider>>
|
||||
) => Promise<AuthenticationProvider> = (options) =>
|
||||
this.update(
|
||||
{
|
||||
enabled: true,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { InferAttributes, InferCreationAttributes } from "sequelize";
|
||||
import {
|
||||
DataType,
|
||||
BelongsTo,
|
||||
@@ -12,7 +13,10 @@ import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "backlinks", modelName: "backlink" })
|
||||
@Fix
|
||||
class Backlink extends IdModel {
|
||||
class Backlink extends IdModel<
|
||||
InferAttributes<Backlink>,
|
||||
Partial<InferCreationAttributes<Backlink>>
|
||||
> {
|
||||
@BelongsTo(() => User, "userId")
|
||||
user: User;
|
||||
|
||||
|
||||
@@ -223,11 +223,10 @@ describe("#updateDocument", () => {
|
||||
const document = await buildDocument({ collectionId: collection.id });
|
||||
await collection.reload();
|
||||
|
||||
const newDocument = await Document.create({
|
||||
const newDocument = await buildDocument({
|
||||
parentDocumentId: document.id,
|
||||
collectionId: collection.id,
|
||||
teamId: collection.teamId,
|
||||
userId: collection.createdById,
|
||||
lastModifiedById: collection.createdById,
|
||||
createdById: collection.createdById,
|
||||
title: "Child document",
|
||||
@@ -277,11 +276,10 @@ describe("#removeDocument", () => {
|
||||
await collection.reload();
|
||||
|
||||
// Add a child for testing
|
||||
const newDocument = await Document.create({
|
||||
const newDocument = await buildDocument({
|
||||
parentDocumentId: document.id,
|
||||
collectionId: collection.id,
|
||||
teamId: collection.teamId,
|
||||
userId: collection.createdById,
|
||||
lastModifiedById: collection.createdById,
|
||||
createdById: collection.createdById,
|
||||
title: "Child document",
|
||||
@@ -306,11 +304,10 @@ describe("#removeDocument", () => {
|
||||
await collection.reload();
|
||||
|
||||
// Add a child for testing
|
||||
const newDocument = await Document.create({
|
||||
const newDocument = await buildDocument({
|
||||
parentDocumentId: document.id,
|
||||
collectionId: collection.id,
|
||||
teamId: collection.teamId,
|
||||
userId: collection.createdById,
|
||||
lastModifiedById: collection.createdById,
|
||||
createdById: collection.createdById,
|
||||
publishedAt: new Date(),
|
||||
|
||||
@@ -10,6 +10,8 @@ import {
|
||||
Op,
|
||||
FindOptions,
|
||||
NonNullFindOptions,
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
} from "sequelize";
|
||||
import {
|
||||
Sequelize,
|
||||
@@ -159,7 +161,10 @@ import NotContainsUrl from "./validators/NotContainsUrl";
|
||||
}))
|
||||
@Table({ tableName: "collections", modelName: "collection" })
|
||||
@Fix
|
||||
class Collection extends ParanoidModel {
|
||||
class Collection extends ParanoidModel<
|
||||
InferAttributes<Collection>,
|
||||
Partial<InferCreationAttributes<Collection>>
|
||||
> {
|
||||
@SimpleLength({
|
||||
min: 10,
|
||||
max: 10,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { InferAttributes, InferCreationAttributes } from "sequelize";
|
||||
import {
|
||||
DataType,
|
||||
BelongsTo,
|
||||
@@ -38,7 +39,10 @@ import TextLength from "./validators/TextLength";
|
||||
}))
|
||||
@Table({ tableName: "comments", modelName: "comment" })
|
||||
@Fix
|
||||
class Comment extends ParanoidModel {
|
||||
class Comment extends ParanoidModel<
|
||||
InferAttributes<Comment>,
|
||||
Partial<InferCreationAttributes<Comment>>
|
||||
> {
|
||||
@TextLength({
|
||||
max: CommentValidation.maxLength,
|
||||
msg: `Comment must be less than ${CommentValidation.maxLength} characters`,
|
||||
|
||||
@@ -3,7 +3,13 @@ import compact from "lodash/compact";
|
||||
import isNil from "lodash/isNil";
|
||||
import uniq from "lodash/uniq";
|
||||
import randomstring from "randomstring";
|
||||
import type { Identifier, NonNullFindOptions, SaveOptions } from "sequelize";
|
||||
import type {
|
||||
Identifier,
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
NonNullFindOptions,
|
||||
SaveOptions,
|
||||
} from "sequelize";
|
||||
import {
|
||||
Sequelize,
|
||||
Transaction,
|
||||
@@ -186,7 +192,10 @@ type AdditionalFindOptions = {
|
||||
}))
|
||||
@Table({ tableName: "documents", modelName: "document" })
|
||||
@Fix
|
||||
class Document extends ParanoidModel {
|
||||
class Document extends ParanoidModel<
|
||||
InferAttributes<Document>,
|
||||
Partial<InferCreationAttributes<Document>>
|
||||
> {
|
||||
@SimpleLength({
|
||||
min: 10,
|
||||
max: 10,
|
||||
@@ -208,7 +217,7 @@ class Document extends ParanoidModel {
|
||||
|
||||
@IsNumeric
|
||||
@Column(DataType.SMALLINT)
|
||||
version: number;
|
||||
version?: number | null;
|
||||
|
||||
@Default(false)
|
||||
@Column
|
||||
@@ -261,7 +270,7 @@ class Document extends ParanoidModel {
|
||||
msg: `Document collaborative state is too large, you must create a new document`,
|
||||
})
|
||||
@Column(DataType.BLOB)
|
||||
state: Uint8Array;
|
||||
state?: Uint8Array | null;
|
||||
|
||||
/** Whether this document is part of onboarding. */
|
||||
@Default(false)
|
||||
@@ -387,14 +396,13 @@ class Document extends ParanoidModel {
|
||||
// ensure documents have a title
|
||||
model.title = model.title || "";
|
||||
|
||||
if (model.previous("title") && model.previous("title") !== model.title) {
|
||||
const previousTitle = model.previous("title");
|
||||
if (previousTitle && previousTitle !== model.title) {
|
||||
if (!model.previousTitles) {
|
||||
model.previousTitles = [];
|
||||
}
|
||||
|
||||
model.previousTitles = uniq(
|
||||
model.previousTitles.concat(model.previous("title"))
|
||||
);
|
||||
model.previousTitles = uniq(model.previousTitles.concat(previousTitle));
|
||||
}
|
||||
|
||||
// add the current user as a collaborator on this doc
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import type { SaveOptions, WhereOptions } from "sequelize";
|
||||
import type {
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
SaveOptions,
|
||||
WhereOptions,
|
||||
} from "sequelize";
|
||||
import {
|
||||
ForeignKey,
|
||||
AfterSave,
|
||||
@@ -22,7 +27,10 @@ import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "events", modelName: "event", updatedAt: false })
|
||||
@Fix
|
||||
class Event extends IdModel {
|
||||
class Event extends IdModel<
|
||||
InferAttributes<Event>,
|
||||
Partial<InferCreationAttributes<Event>>
|
||||
> {
|
||||
@IsUUID(4)
|
||||
@Column(DataType.UUID)
|
||||
modelId: string | null;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { Op, WhereOptions } from "sequelize";
|
||||
import {
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
Op,
|
||||
WhereOptions,
|
||||
} from "sequelize";
|
||||
import {
|
||||
ForeignKey,
|
||||
DefaultScope,
|
||||
@@ -36,7 +41,10 @@ import Fix from "./decorators/Fix";
|
||||
}))
|
||||
@Table({ tableName: "file_operations", modelName: "file_operation" })
|
||||
@Fix
|
||||
class FileOperation extends ParanoidModel {
|
||||
class FileOperation extends ParanoidModel<
|
||||
InferAttributes<FileOperation>,
|
||||
Partial<InferCreationAttributes<FileOperation>>
|
||||
> {
|
||||
@Column(DataType.ENUM(...Object.values(FileOperationType)))
|
||||
type: FileOperationType;
|
||||
|
||||
@@ -50,7 +58,7 @@ class FileOperation extends ParanoidModel {
|
||||
key: string;
|
||||
|
||||
@Column
|
||||
url: string;
|
||||
url?: string | null;
|
||||
|
||||
@Column
|
||||
error: string | null;
|
||||
@@ -118,7 +126,7 @@ class FileOperation extends ParanoidModel {
|
||||
|
||||
@ForeignKey(() => Collection)
|
||||
@Column(DataType.UUID)
|
||||
collectionId: string;
|
||||
collectionId?: string | null;
|
||||
|
||||
/**
|
||||
* Count the number of export file operations for a given team after a point
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Op } from "sequelize";
|
||||
import { InferAttributes, InferCreationAttributes, Op } from "sequelize";
|
||||
import {
|
||||
AfterDestroy,
|
||||
BelongsTo,
|
||||
@@ -69,7 +69,10 @@ import NotContainsUrl from "./validators/NotContainsUrl";
|
||||
},
|
||||
})
|
||||
@Fix
|
||||
class Group extends ParanoidModel {
|
||||
class Group extends ParanoidModel<
|
||||
InferAttributes<Group>,
|
||||
Partial<InferCreationAttributes<Group>>
|
||||
> {
|
||||
@Length({ min: 0, max: 255, msg: "name must be be 255 characters or less" })
|
||||
@NotContainsUrl
|
||||
@Column
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Op } from "sequelize";
|
||||
import { InferAttributes, InferCreationAttributes, Op } from "sequelize";
|
||||
import {
|
||||
BelongsTo,
|
||||
Column,
|
||||
@@ -40,7 +40,10 @@ import Fix from "./decorators/Fix";
|
||||
}))
|
||||
@Table({ tableName: "group_permissions", modelName: "group_permission" })
|
||||
@Fix
|
||||
class GroupPermission extends ParanoidModel {
|
||||
class GroupPermission extends ParanoidModel<
|
||||
InferAttributes<GroupPermission>,
|
||||
Partial<InferCreationAttributes<GroupPermission>>
|
||||
> {
|
||||
@Default(CollectionPermission.ReadWrite)
|
||||
@IsIn([Object.values(CollectionPermission)])
|
||||
@Column(DataType.STRING)
|
||||
@@ -71,6 +74,10 @@ class GroupPermission extends ParanoidModel {
|
||||
|
||||
@BelongsTo(() => User, "createdById")
|
||||
createdBy: User;
|
||||
|
||||
@ForeignKey(() => User)
|
||||
@Column(DataType.UUID)
|
||||
createdById: string;
|
||||
}
|
||||
|
||||
export default GroupPermission;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { InferAttributes, InferCreationAttributes } from "sequelize";
|
||||
import {
|
||||
DefaultScope,
|
||||
BelongsTo,
|
||||
@@ -37,7 +38,10 @@ import Fix from "./decorators/Fix";
|
||||
}))
|
||||
@Table({ tableName: "group_users", modelName: "group_user", paranoid: true })
|
||||
@Fix
|
||||
class GroupUser extends Model {
|
||||
class GroupUser extends Model<
|
||||
InferAttributes<GroupUser>,
|
||||
Partial<InferCreationAttributes<GroupUser>>
|
||||
> {
|
||||
@BelongsTo(() => User, "userId")
|
||||
user: User;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { InferAttributes, InferCreationAttributes } from "sequelize";
|
||||
import {
|
||||
ForeignKey,
|
||||
BelongsTo,
|
||||
@@ -8,7 +9,10 @@ import {
|
||||
IsIn,
|
||||
} from "sequelize-typescript";
|
||||
import { IntegrationType, IntegrationService } from "@shared/types";
|
||||
import type { IntegrationSettings } from "@shared/types";
|
||||
import type {
|
||||
IntegrationSettings,
|
||||
UserCreatableIntegrationService,
|
||||
} from "@shared/types";
|
||||
import Collection from "./Collection";
|
||||
import IntegrationAuthentication from "./IntegrationAuthentication";
|
||||
import Team from "./Team";
|
||||
@@ -16,12 +20,6 @@ import User from "./User";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
export enum UserCreatableIntegrationService {
|
||||
Diagrams = "diagrams",
|
||||
Grist = "grist",
|
||||
GoogleAnalytics = "google-analytics",
|
||||
}
|
||||
|
||||
@Scopes(() => ({
|
||||
withAuthentication: {
|
||||
include: [
|
||||
@@ -35,14 +33,17 @@ export enum UserCreatableIntegrationService {
|
||||
}))
|
||||
@Table({ tableName: "integrations", modelName: "integration" })
|
||||
@Fix
|
||||
class Integration<T = unknown> extends IdModel {
|
||||
class Integration<T = unknown> extends IdModel<
|
||||
InferAttributes<Integration<T>>,
|
||||
Partial<InferCreationAttributes<Integration<T>>>
|
||||
> {
|
||||
@IsIn([Object.values(IntegrationType)])
|
||||
@Column(DataType.STRING)
|
||||
type: IntegrationType;
|
||||
|
||||
@IsIn([Object.values(IntegrationService)])
|
||||
@Column(DataType.STRING)
|
||||
service: IntegrationService;
|
||||
service: IntegrationService | UserCreatableIntegrationService;
|
||||
|
||||
@Column(DataType.JSONB)
|
||||
settings: IntegrationSettings<T>;
|
||||
@@ -67,11 +68,11 @@ class Integration<T = unknown> extends IdModel {
|
||||
teamId: string;
|
||||
|
||||
@BelongsTo(() => Collection, "collectionId")
|
||||
collection: Collection;
|
||||
collection?: Collection | null;
|
||||
|
||||
@ForeignKey(() => Collection)
|
||||
@Column(DataType.UUID)
|
||||
collectionId: string;
|
||||
collectionId?: string | null;
|
||||
|
||||
@BelongsTo(() => IntegrationAuthentication, "authenticationId")
|
||||
authentication: IntegrationAuthentication;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { InferAttributes, InferCreationAttributes } from "sequelize";
|
||||
import {
|
||||
DataType,
|
||||
Table,
|
||||
@@ -17,7 +18,10 @@ import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "authentications", modelName: "authentication" })
|
||||
@Fix
|
||||
class IntegrationAuthentication extends IdModel {
|
||||
class IntegrationAuthentication extends IdModel<
|
||||
InferAttributes<IntegrationAuthentication>,
|
||||
Partial<InferCreationAttributes<IntegrationAuthentication>>
|
||||
> {
|
||||
@Column(DataType.STRING)
|
||||
service: IntegrationService;
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import crypto from "crypto";
|
||||
import type { SaveOptions } from "sequelize";
|
||||
import type {
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
SaveOptions,
|
||||
} from "sequelize";
|
||||
import {
|
||||
Table,
|
||||
ForeignKey,
|
||||
Model,
|
||||
Column,
|
||||
PrimaryKey,
|
||||
IsUUID,
|
||||
@@ -18,6 +21,7 @@ import {
|
||||
} from "sequelize-typescript";
|
||||
import { NotificationEventType } from "@shared/types";
|
||||
import env from "@server/env";
|
||||
import Model from "@server/models/base/Model";
|
||||
import Collection from "./Collection";
|
||||
import Comment from "./Comment";
|
||||
import Document from "./Document";
|
||||
@@ -83,7 +87,10 @@ import Fix from "./decorators/Fix";
|
||||
updatedAt: false,
|
||||
})
|
||||
@Fix
|
||||
class Notification extends Model {
|
||||
class Notification extends Model<
|
||||
InferAttributes<Notification>,
|
||||
Partial<InferCreationAttributes<Notification>>
|
||||
> {
|
||||
@IsUUID(4)
|
||||
@PrimaryKey
|
||||
@Default(DataType.UUIDV4)
|
||||
@@ -92,7 +99,7 @@ class Notification extends Model {
|
||||
|
||||
@AllowNull
|
||||
@Column
|
||||
emailedAt: Date;
|
||||
emailedAt?: Date | null;
|
||||
|
||||
@AllowNull
|
||||
@Column
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { InferAttributes, InferCreationAttributes } from "sequelize";
|
||||
import {
|
||||
DataType,
|
||||
Column,
|
||||
@@ -14,7 +15,10 @@ import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "pins", modelName: "pin" })
|
||||
@Fix
|
||||
class Pin extends IdModel {
|
||||
class Pin extends IdModel<
|
||||
InferAttributes<Pin>,
|
||||
Partial<InferCreationAttributes<Pin>>
|
||||
> {
|
||||
@Column
|
||||
index: string | null;
|
||||
|
||||
@@ -28,11 +32,11 @@ class Pin extends IdModel {
|
||||
createdById: string;
|
||||
|
||||
@BelongsTo(() => Collection, "collectionId")
|
||||
collection: Collection;
|
||||
collection?: Collection | null;
|
||||
|
||||
@ForeignKey(() => Collection)
|
||||
@Column(DataType.UUID)
|
||||
collectionId: string;
|
||||
collectionId?: string | null;
|
||||
|
||||
@BelongsTo(() => Document, "documentId")
|
||||
document: Document;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { Op, SaveOptions } from "sequelize";
|
||||
import {
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
Op,
|
||||
SaveOptions,
|
||||
} from "sequelize";
|
||||
import {
|
||||
DataType,
|
||||
BelongsTo,
|
||||
@@ -28,10 +33,13 @@ import Length from "./validators/Length";
|
||||
}))
|
||||
@Table({ tableName: "revisions", modelName: "revision" })
|
||||
@Fix
|
||||
class Revision extends IdModel {
|
||||
class Revision extends IdModel<
|
||||
InferAttributes<Revision>,
|
||||
Partial<InferCreationAttributes<Revision>>
|
||||
> {
|
||||
@IsNumeric
|
||||
@Column(DataType.SMALLINT)
|
||||
version: number;
|
||||
version?: number | null;
|
||||
|
||||
@SimpleLength({
|
||||
max: 255,
|
||||
@@ -133,7 +141,7 @@ class Revision extends IdModel {
|
||||
*/
|
||||
static createFromDocument(
|
||||
document: Document,
|
||||
options?: SaveOptions<Revision>
|
||||
options?: SaveOptions<InferAttributes<Revision>>
|
||||
) {
|
||||
const revision = this.buildFromDocument(document);
|
||||
return revision.save(options);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { InferAttributes, InferCreationAttributes } from "sequelize";
|
||||
import {
|
||||
Table,
|
||||
ForeignKey,
|
||||
Model,
|
||||
Column,
|
||||
PrimaryKey,
|
||||
IsUUID,
|
||||
@@ -10,8 +10,10 @@ import {
|
||||
DataType,
|
||||
Default,
|
||||
} from "sequelize-typescript";
|
||||
import Team from "./Team";
|
||||
import User from "./User";
|
||||
import Share from "@server/models/Share";
|
||||
import Team from "@server/models/Team";
|
||||
import User from "@server/models/User";
|
||||
import Model from "@server/models/base/Model";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({
|
||||
@@ -20,7 +22,10 @@ import Fix from "./decorators/Fix";
|
||||
updatedAt: false,
|
||||
})
|
||||
@Fix
|
||||
class SearchQuery extends Model {
|
||||
class SearchQuery extends Model<
|
||||
InferAttributes<SearchQuery>,
|
||||
Partial<InferCreationAttributes<SearchQuery>>
|
||||
> {
|
||||
@IsUUID(4)
|
||||
@PrimaryKey
|
||||
@Default(DataType.UUIDV4)
|
||||
@@ -69,11 +74,18 @@ class SearchQuery extends Model {
|
||||
// associations
|
||||
|
||||
@BelongsTo(() => User, "userId")
|
||||
user: User;
|
||||
user?: User | null;
|
||||
|
||||
@ForeignKey(() => User)
|
||||
@Column(DataType.UUID)
|
||||
userId: string;
|
||||
userId?: string | null;
|
||||
|
||||
@BelongsTo(() => Share, "shareId")
|
||||
share?: Share | null;
|
||||
|
||||
@ForeignKey(() => Share)
|
||||
@Column(DataType.UUID)
|
||||
shareId?: string | null;
|
||||
|
||||
@BelongsTo(() => Team, "teamId")
|
||||
team: Team;
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { type SaveOptions } from "sequelize";
|
||||
import {
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
type SaveOptions,
|
||||
} from "sequelize";
|
||||
import {
|
||||
ForeignKey,
|
||||
BelongsTo,
|
||||
@@ -69,7 +73,10 @@ import Length from "./validators/Length";
|
||||
}))
|
||||
@Table({ tableName: "shares", modelName: "share" })
|
||||
@Fix
|
||||
class Share extends IdModel {
|
||||
class Share extends IdModel<
|
||||
InferAttributes<Share>,
|
||||
Partial<InferCreationAttributes<Share>>
|
||||
> {
|
||||
@Column
|
||||
published: boolean;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { InferAttributes, InferCreationAttributes } from "sequelize";
|
||||
import {
|
||||
Column,
|
||||
DataType,
|
||||
@@ -13,7 +14,10 @@ import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "stars", modelName: "star" })
|
||||
@Fix
|
||||
class Star extends IdModel {
|
||||
class Star extends IdModel<
|
||||
InferAttributes<Star>,
|
||||
Partial<InferCreationAttributes<Star>>
|
||||
> {
|
||||
@Column
|
||||
index: string | null;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { InferAttributes, InferCreationAttributes } from "sequelize";
|
||||
import {
|
||||
Column,
|
||||
DataType,
|
||||
@@ -23,7 +24,10 @@ import Fix from "./decorators/Fix";
|
||||
}))
|
||||
@Table({ tableName: "subscriptions", modelName: "subscription" })
|
||||
@Fix
|
||||
class Subscription extends ParanoidModel {
|
||||
class Subscription extends ParanoidModel<
|
||||
InferAttributes<Subscription>,
|
||||
Partial<InferCreationAttributes<Subscription>>
|
||||
> {
|
||||
@BelongsTo(() => User, "userId")
|
||||
user: User;
|
||||
|
||||
|
||||
@@ -3,7 +3,11 @@ import fs from "fs";
|
||||
import path from "path";
|
||||
import { URL } from "url";
|
||||
import util from "util";
|
||||
import { type SaveOptions } from "sequelize";
|
||||
import {
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
type SaveOptions,
|
||||
} from "sequelize";
|
||||
import { Op } from "sequelize";
|
||||
import {
|
||||
Column,
|
||||
@@ -65,7 +69,10 @@ const readFile = util.promisify(fs.readFile);
|
||||
}))
|
||||
@Table({ tableName: "teams", modelName: "team" })
|
||||
@Fix
|
||||
class Team extends ParanoidModel {
|
||||
class Team extends ParanoidModel<
|
||||
InferAttributes<Team>,
|
||||
Partial<InferCreationAttributes<Team>>
|
||||
> {
|
||||
@NotContainsUrl
|
||||
@Length({ min: 2, max: 255, msg: "name must be between 2 to 255 characters" })
|
||||
@Column
|
||||
@@ -275,7 +282,6 @@ class Team extends ParanoidModel {
|
||||
parentDocumentId: null,
|
||||
collectionId: collection.id,
|
||||
teamId: collection.teamId,
|
||||
userId: collection.createdById,
|
||||
lastModifiedById: collection.createdById,
|
||||
createdById: collection.createdById,
|
||||
title,
|
||||
@@ -366,14 +372,9 @@ class Team extends ParanoidModel {
|
||||
|
||||
@AfterUpdate
|
||||
static deletePreviousAvatar = async (model: Team) => {
|
||||
if (
|
||||
model.previous("avatarUrl") &&
|
||||
model.previous("avatarUrl") !== model.avatarUrl
|
||||
) {
|
||||
const attachmentIds = parseAttachmentIds(
|
||||
model.previous("avatarUrl"),
|
||||
true
|
||||
);
|
||||
const previousAvatarUrl = model.previous("avatarUrl");
|
||||
if (previousAvatarUrl && previousAvatarUrl !== model.avatarUrl) {
|
||||
const attachmentIds = parseAttachmentIds(previousAvatarUrl, true);
|
||||
if (!attachmentIds.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import emailProviders from "email-providers";
|
||||
import { InferAttributes, InferCreationAttributes } from "sequelize";
|
||||
import {
|
||||
Column,
|
||||
Table,
|
||||
@@ -21,7 +22,10 @@ import Length from "./validators/Length";
|
||||
|
||||
@Table({ tableName: "team_domains", modelName: "team_domain" })
|
||||
@Fix
|
||||
class TeamDomain extends IdModel {
|
||||
class TeamDomain extends IdModel<
|
||||
InferAttributes<TeamDomain>,
|
||||
Partial<InferCreationAttributes<TeamDomain>>
|
||||
> {
|
||||
@NotIn({
|
||||
args: env.isCloudHosted ? [emailProviders] : [],
|
||||
msg: "You chose a restricted domain, please try another.",
|
||||
|
||||
@@ -8,6 +8,9 @@ import {
|
||||
SaveOptions,
|
||||
Op,
|
||||
FindOptions,
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
InstanceUpdateOptions,
|
||||
} from "sequelize";
|
||||
import {
|
||||
Table,
|
||||
@@ -40,6 +43,7 @@ import {
|
||||
} from "@shared/types";
|
||||
import { stringToColor } from "@shared/utils/color";
|
||||
import env from "@server/env";
|
||||
import Model from "@server/models/base/Model";
|
||||
import DeleteAttachmentTask from "@server/queues/tasks/DeleteAttachmentTask";
|
||||
import parseAttachmentIds from "@server/utils/parseAttachmentIds";
|
||||
import { ValidationError } from "../errors";
|
||||
@@ -117,7 +121,10 @@ export enum UserFlag {
|
||||
}))
|
||||
@Table({ tableName: "users", modelName: "user" })
|
||||
@Fix
|
||||
class User extends ParanoidModel {
|
||||
class User extends ParanoidModel<
|
||||
InferAttributes<User>,
|
||||
Partial<InferCreationAttributes<User>>
|
||||
> {
|
||||
@IsEmail
|
||||
@Length({ max: 255, msg: "User email must be 255 characters or less" })
|
||||
@Column
|
||||
@@ -519,7 +526,10 @@ class User extends ParanoidModel {
|
||||
],
|
||||
});
|
||||
|
||||
demote = async (to: UserRole, options?: SaveOptions<User>) => {
|
||||
demote: (
|
||||
to: UserRole,
|
||||
options?: InstanceUpdateOptions<InferAttributes<Model>>
|
||||
) => Promise<void> = async (to, options) => {
|
||||
const res = await (this.constructor as typeof User).findAndCountAll({
|
||||
where: {
|
||||
teamId: this.teamId,
|
||||
@@ -568,7 +578,9 @@ class User extends ParanoidModel {
|
||||
}
|
||||
};
|
||||
|
||||
promote = (options?: SaveOptions<User>) =>
|
||||
promote: (
|
||||
options?: InstanceUpdateOptions<InferAttributes<User>>
|
||||
) => Promise<User> = (options) =>
|
||||
this.update(
|
||||
{
|
||||
isAdmin: true,
|
||||
@@ -605,14 +617,9 @@ class User extends ParanoidModel {
|
||||
|
||||
@AfterUpdate
|
||||
static deletePreviousAvatar = async (model: User) => {
|
||||
if (
|
||||
model.previous("avatarUrl") &&
|
||||
model.previous("avatarUrl") !== model.avatarUrl
|
||||
) {
|
||||
const attachmentIds = parseAttachmentIds(
|
||||
model.previous("avatarUrl"),
|
||||
true
|
||||
);
|
||||
const previousAvatarUrl = model.previous("avatarUrl");
|
||||
if (previousAvatarUrl && previousAvatarUrl !== model.avatarUrl) {
|
||||
const attachmentIds = parseAttachmentIds(previousAvatarUrl, true);
|
||||
if (!attachmentIds.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { addMinutes, subMinutes } from "date-fns";
|
||||
import invariant from "invariant";
|
||||
import { SaveOptions } from "sequelize";
|
||||
import {
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
SaveOptions,
|
||||
} from "sequelize";
|
||||
import {
|
||||
BeforeCreate,
|
||||
BelongsTo,
|
||||
@@ -22,7 +26,10 @@ import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "user_authentications", modelName: "user_authentication" })
|
||||
@Fix
|
||||
class UserAuthentication extends IdModel {
|
||||
class UserAuthentication extends IdModel<
|
||||
InferAttributes<UserAuthentication>,
|
||||
Partial<InferCreationAttributes<UserAuthentication>>
|
||||
> {
|
||||
@Column(DataType.ARRAY(DataType.STRING))
|
||||
scopes: string[];
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Op } from "sequelize";
|
||||
import { InferAttributes, InferCreationAttributes, Op } from "sequelize";
|
||||
import {
|
||||
Column,
|
||||
ForeignKey,
|
||||
@@ -39,7 +39,10 @@ import Fix from "./decorators/Fix";
|
||||
}))
|
||||
@Table({ tableName: "user_permissions", modelName: "user_permission" })
|
||||
@Fix
|
||||
class UserPermission extends IdModel {
|
||||
class UserPermission extends IdModel<
|
||||
InferAttributes<UserPermission>,
|
||||
Partial<InferCreationAttributes<UserPermission>>
|
||||
> {
|
||||
@Default(CollectionPermission.ReadWrite)
|
||||
@IsIn([Object.values(CollectionPermission)])
|
||||
@Column(DataType.STRING)
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { FindOrCreateOptions, Op } from "sequelize";
|
||||
import {
|
||||
FindOrCreateOptions,
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
Op,
|
||||
} from "sequelize";
|
||||
import {
|
||||
BelongsTo,
|
||||
Column,
|
||||
@@ -26,7 +31,10 @@ import Fix from "./decorators/Fix";
|
||||
}))
|
||||
@Table({ tableName: "views", modelName: "view" })
|
||||
@Fix
|
||||
class View extends IdModel {
|
||||
class View extends IdModel<
|
||||
InferAttributes<View>,
|
||||
Partial<InferCreationAttributes<View>>
|
||||
> {
|
||||
@Column
|
||||
lastEditingAt: Date | null;
|
||||
|
||||
@@ -55,7 +63,7 @@ class View extends IdModel {
|
||||
userId: string;
|
||||
documentId: string;
|
||||
},
|
||||
options?: FindOrCreateOptions
|
||||
options?: FindOrCreateOptions<InferAttributes<View>>
|
||||
) {
|
||||
const [model, created] = await this.findOrCreate({
|
||||
...options,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { InferAttributes, InferCreationAttributes } from "sequelize";
|
||||
import {
|
||||
Column,
|
||||
Table,
|
||||
@@ -7,6 +8,7 @@ import {
|
||||
DataType,
|
||||
IsIn,
|
||||
} from "sequelize-typescript";
|
||||
import { type WebhookDeliveryStatus } from "@server/types";
|
||||
import WebhookSubscription from "./WebhookSubscription";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
@@ -16,14 +18,17 @@ import Fix from "./decorators/Fix";
|
||||
modelName: "webhook_delivery",
|
||||
})
|
||||
@Fix
|
||||
class WebhookDelivery extends IdModel {
|
||||
class WebhookDelivery extends IdModel<
|
||||
InferAttributes<WebhookDelivery>,
|
||||
Partial<InferCreationAttributes<WebhookDelivery>>
|
||||
> {
|
||||
@NotEmpty
|
||||
@IsIn([["pending", "success", "failed"]])
|
||||
@Column(DataType.STRING)
|
||||
status: "pending" | "success" | "failed";
|
||||
status: WebhookDeliveryStatus;
|
||||
|
||||
@Column(DataType.INTEGER)
|
||||
statusCode: number;
|
||||
statusCode?: number | null;
|
||||
|
||||
@Column(DataType.JSONB)
|
||||
requestBody: unknown;
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import crypto from "crypto";
|
||||
import isEmpty from "lodash/isEmpty";
|
||||
import { SaveOptions } from "sequelize";
|
||||
import {
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
InstanceUpdateOptions,
|
||||
} from "sequelize";
|
||||
import {
|
||||
Column,
|
||||
Table,
|
||||
@@ -39,7 +43,10 @@ import Length from "./validators/Length";
|
||||
modelName: "webhook_subscription",
|
||||
})
|
||||
@Fix
|
||||
class WebhookSubscription extends ParanoidModel {
|
||||
class WebhookSubscription extends ParanoidModel<
|
||||
InferAttributes<WebhookSubscription>,
|
||||
Partial<InferCreationAttributes<WebhookSubscription>>
|
||||
> {
|
||||
@NotEmpty
|
||||
@Length({ max: 255, msg: "Webhook name be less than 255 characters" })
|
||||
@Column
|
||||
@@ -110,7 +117,9 @@ class WebhookSubscription extends ParanoidModel {
|
||||
* @param options Save options
|
||||
* @returns Promise<WebhookSubscription>
|
||||
*/
|
||||
public async disable(options?: SaveOptions<WebhookSubscription>) {
|
||||
public async disable(
|
||||
options?: InstanceUpdateOptions<InferAttributes<WebhookSubscription>>
|
||||
) {
|
||||
return this.update({ enabled: false }, options);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/ban-types */
|
||||
import {
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
@@ -9,7 +10,10 @@ import {
|
||||
} from "sequelize-typescript";
|
||||
import Model from "./Model";
|
||||
|
||||
class IdModel extends Model {
|
||||
class IdModel<
|
||||
TModelAttributes extends {} = any,
|
||||
TCreationAttributes extends {} = TModelAttributes
|
||||
> extends Model<TModelAttributes, TCreationAttributes> {
|
||||
@IsUUID(4)
|
||||
@PrimaryKey
|
||||
@Default(DataType.UUIDV4)
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
/* eslint-disable @typescript-eslint/ban-types */
|
||||
import { FindOptions } from "sequelize";
|
||||
import { Model as SequelizeModel } from "sequelize-typescript";
|
||||
|
||||
class Model extends SequelizeModel {
|
||||
class Model<
|
||||
TModelAttributes extends {} = any,
|
||||
TCreationAttributes extends {} = TModelAttributes
|
||||
> extends SequelizeModel<TModelAttributes, TCreationAttributes> {
|
||||
/**
|
||||
* Find all models in batches, calling the callback function for each batch.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
/* eslint-disable @typescript-eslint/ban-types */
|
||||
import { DeletedAt } from "sequelize-typescript";
|
||||
import IdModel from "./IdModel";
|
||||
|
||||
class ParanoidModel extends IdModel {
|
||||
class ParanoidModel<
|
||||
TModelAttributes extends {} = any,
|
||||
TCreationAttributes extends {} = TModelAttributes
|
||||
> extends IdModel<TModelAttributes, TCreationAttributes> {
|
||||
@DeletedAt
|
||||
deletedAt: Date | null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user