revision.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import type {
  2. HasObjectId,
  3. IRevision,
  4. Origin,
  5. } from '@growi/core';
  6. import { allOrigin } from '@growi/core';
  7. import type { Types } from 'mongoose';
  8. import {
  9. Schema, type Document, type Model,
  10. } from 'mongoose';
  11. import mongoosePaginate from 'mongoose-paginate-v2';
  12. import loggerFactory from '~/utils/logger';
  13. import { getOrCreateModel } from '../util/mongoose-utils';
  14. import type { PageDocument } from './page';
  15. const logger = loggerFactory('growi:models:revision');
  16. export interface IRevisionDocument extends IRevision, Document {
  17. }
  18. type UpdateRevisionListByPageId = (pageId: Types.ObjectId, updateData: Partial<IRevision>) => Promise<void>;
  19. type PrepareRevision = (
  20. pageData: PageDocument, body: string, previousBody: string | null, user: HasObjectId, origin?: Origin, options?: { format: string }
  21. ) => IRevisionDocument;
  22. export interface IRevisionModel extends Model<IRevisionDocument> {
  23. updateRevisionListByPageId: UpdateRevisionListByPageId,
  24. prepareRevision: PrepareRevision,
  25. }
  26. // Use this to allow empty strings to pass the `required` validator
  27. Schema.Types.String.checkRequired(v => typeof v === 'string');
  28. const revisionSchema = new Schema<IRevisionDocument, IRevisionModel>({
  29. // The type of pageId is always converted to String at server startup
  30. // Refer to this method (/src/server/service/normalize-data/convert-revision-page-id-to-string.ts) to change the pageId type
  31. pageId: {
  32. type: Schema.Types.ObjectId, ref: 'Page', required: true, index: true,
  33. },
  34. body: {
  35. type: String,
  36. required: true,
  37. get: (data) => {
  38. // replace CR/CRLF to LF above v3.1.5
  39. // see https://github.com/weseek/growi/issues/463
  40. return data ? data.replace(/\r\n?/g, '\n') : '';
  41. },
  42. },
  43. format: { type: String, default: 'markdown' },
  44. author: { type: Schema.Types.ObjectId, ref: 'User' },
  45. hasDiffToPrev: { type: Boolean },
  46. origin: { type: String, enum: allOrigin },
  47. }, {
  48. timestamps: { createdAt: true, updatedAt: false },
  49. });
  50. revisionSchema.plugin(mongoosePaginate);
  51. const updateRevisionListByPageId: UpdateRevisionListByPageId = async function(this: IRevisionModel, pageId, updateData) {
  52. // Check pageId for safety
  53. if (pageId == null) {
  54. throw new Error('Error: pageId is required');
  55. }
  56. await this.updateMany({ pageId }, { $set: updateData });
  57. };
  58. revisionSchema.statics.updateRevisionListByPageId = updateRevisionListByPageId;
  59. const prepareRevision: PrepareRevision = function(this: IRevisionModel, pageData, body, previousBody, user, origin, options = { format: 'markdown' }) {
  60. if (user._id == null) {
  61. throw new Error('user should have _id');
  62. }
  63. if (pageData._id == null) {
  64. throw new Error('pageData should have _id');
  65. }
  66. const newRevision = new this();
  67. newRevision.pageId = pageData._id;
  68. newRevision.body = body;
  69. newRevision.format = options.format;
  70. newRevision.author = user._id;
  71. newRevision.origin = origin;
  72. if (pageData.revision != null) {
  73. newRevision.hasDiffToPrev = body !== previousBody;
  74. }
  75. return newRevision;
  76. };
  77. revisionSchema.statics.prepareRevision = prepareRevision;
  78. export const Revision = getOrCreateModel<IRevisionDocument, IRevisionModel>('Revision', revisionSchema);