Files
outline/server/models/Revision.ts
Apoorv Mishra 7e61a519f1 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>
2024-01-12 22:33:05 +05:30

171 lines
3.9 KiB
TypeScript

import {
InferAttributes,
InferCreationAttributes,
Op,
SaveOptions,
} from "sequelize";
import {
DataType,
BelongsTo,
Column,
DefaultScope,
ForeignKey,
Table,
IsNumeric,
Length as SimpleLength,
} from "sequelize-typescript";
import type { ProsemirrorData } from "@shared/types";
import { DocumentValidation } from "@shared/validations";
import Document from "./Document";
import User from "./User";
import IdModel from "./base/IdModel";
import Fix from "./decorators/Fix";
import Length from "./validators/Length";
@DefaultScope(() => ({
include: [
{
model: User,
as: "user",
paranoid: false,
},
],
}))
@Table({ tableName: "revisions", modelName: "revision" })
@Fix
class Revision extends IdModel<
InferAttributes<Revision>,
Partial<InferCreationAttributes<Revision>>
> {
@IsNumeric
@Column(DataType.SMALLINT)
version?: number | null;
@SimpleLength({
max: 255,
msg: `editorVersion must be 255 characters or less`,
})
@Column
editorVersion: string;
@Length({
max: DocumentValidation.maxTitleLength,
msg: `Revision title must be ${DocumentValidation.maxTitleLength} characters or less`,
})
@Column
title: string;
/**
* The content of the revision as Markdown.
*
* @deprecated Use `content` instead, or `DocumentHelper.toMarkdown` if exporting lossy markdown.
* This column will be removed in a future migration.
*/
@Column(DataType.TEXT)
text: string;
/**
* The content of the revision as JSON.
*/
@Column(DataType.JSONB)
content: ProsemirrorData;
@Length({
max: 1,
msg: `Emoji must be a single character`,
})
@Column
emoji: string | null;
// associations
@BelongsTo(() => Document, "documentId")
document: Document;
@ForeignKey(() => Document)
@Column(DataType.UUID)
documentId: string;
@BelongsTo(() => User, "userId")
user: User;
@ForeignKey(() => User)
@Column(DataType.UUID)
userId: string;
// static methods
/**
* Find the latest revision for a given document
*
* @param documentId The document id to find the latest revision for
* @returns A Promise that resolves to a Revision model
*/
static findLatest(documentId: string) {
return this.findOne({
where: {
documentId,
},
order: [["createdAt", "DESC"]],
});
}
/**
* Build a Revision model from a Document model
*
* @param document The document to build from
* @returns A Revision model
*/
static buildFromDocument(document: Document) {
return this.build({
title: document.title,
text: document.text,
emoji: document.emoji,
content: document.content,
userId: document.lastModifiedById,
editorVersion: document.editorVersion,
version: document.version,
documentId: document.id,
// revision time is set to the last time document was touched as this
// handler can be debounced in the case of an update
createdAt: document.updatedAt,
});
}
/**
* Create a Revision model from a Document model and save it to the database
*
* @param document The document to create from
* @param options Options passed to the save method
* @returns A Promise that resolves when saved
*/
static createFromDocument(
document: Document,
options?: SaveOptions<InferAttributes<Revision>>
) {
const revision = this.buildFromDocument(document);
return revision.save(options);
}
// instance methods
/**
* Find the revision for the document before this one.
*
* @returns A Promise that resolves to a Revision, or null if this is the first revision.
*/
before(): Promise<Revision | null> {
return (this.constructor as typeof Revision).findOne({
where: {
documentId: this.documentId,
createdAt: {
[Op.lt]: this.createdAt,
},
},
order: [["createdAt", "DESC"]],
});
}
}
export default Revision;