Skip to content

Commit 2ba707c

Browse files
borodayevValeriy Borodayev
and
Valeriy Borodayev
committed
perf: add an ability to merge specific versions (#46)
* refactor: remove updatedAt field from diff doc * feat: add startVersion & endVersion args to mergeDiffs method * test: cover mergeDiffs methods with additional cases Co-authored-by: Valeriy Borodayev <[email protected]>
1 parent a015b75 commit 2ba707c

File tree

4 files changed

+378
-41
lines changed

4 files changed

+378
-41
lines changed

__fixtures__/Post.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable no-await-in-loop */
12
// @flow
23
/* eslint-disable no-param-reassign, func-names */
34

@@ -7,6 +8,16 @@ import DB from './db';
78

89
DB.init();
910

11+
export interface IPostDoc extends Document {
12+
title: string;
13+
subjects: Array<{ name: string }>;
14+
}
15+
16+
interface IPostModel extends Model<IPostDoc> {
17+
diffModel(): IDiffModel;
18+
createDifferentSubjects(findObj: string, count: number): Promise<void>;
19+
}
20+
1021
export const PostSchema: Schema<IPostDoc> = new mongoose.Schema(
1122
{
1223
title: {
@@ -34,14 +45,19 @@ export const PostSchema: Schema<IPostDoc> = new mongoose.Schema(
3445
}
3546
);
3647

37-
export interface IPostDoc extends Document {
38-
title: string;
39-
subjects: Array<{ name: string }>;
40-
}
41-
42-
interface IPostModel extends Model<IPostDoc> {
43-
diffModel(): IDiffModel;
44-
}
48+
// for test purposes
49+
PostSchema.statics.createDifferentSubjects = async function (
50+
title: string,
51+
count: number
52+
): Promise<void> {
53+
for (let i = 1; i <= count; i += 1) {
54+
const post: IPostDoc = await this.findOne({ title }).exec();
55+
if (post) {
56+
post.subjects.push({ name: `name_${i}` });
57+
await post.save();
58+
}
59+
}
60+
};
4561

4662
PostSchema.plugin(DiffPlugin);
4763

src/DiffModel.ts

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
/* eslint-disable func-names */
22
import { Schema, Connection } from 'mongoose';
3-
import { IDiffModel, ObjectId, RawChangeT, ChangeDoc, IDiffDoc } from './types';
3+
import {
4+
IDiffModel,
5+
ObjectId,
6+
RawChangeT,
7+
ChangeDoc,
8+
IDiffDoc,
9+
MergedDiffsOptsT,
10+
} from './types';
411
import MHD, { revertChanges } from './diff';
512

613
export default function (
714
mongooseConnection: Connection,
815
collectionName: string
916
): IDiffModel {
10-
if (!mongooseConnection) throw new Error(`'mongooseConection' is required`);
17+
if (!mongooseConnection) throw new Error(`'mongooseConnection' is required`);
1118
if (!collectionName) throw new Error(`'collectionName' is required`);
1219

1320
const ItemSchema = new Schema(
@@ -49,7 +56,11 @@ export default function (
4956
c: [ChangeSchema],
5057
v: Number,
5158
},
52-
{ versionKey: false, timestamps: true, collection: collectionName }
59+
{
60+
versionKey: false,
61+
timestamps: { createdAt: true, updatedAt: false },
62+
collection: collectionName,
63+
}
5364
);
5465
DiffSchema.index({ docId: 1, path: 1 });
5566

@@ -103,12 +114,40 @@ export default function (
103114
return revertChanges(doc, changes);
104115
};
105116

106-
DiffSchema.statics.mergeDiffs = async function (doc: {
107-
toObject: Function;
108-
}): Promise<Array<RawChangeT>> {
109-
const currentDoc = { ...doc.toObject() };
110-
const initialDoc = await this.revertToVersion(currentDoc, 1);
111-
if (!initialDoc) return [];
117+
DiffSchema.statics.mergeDiffs = async function (
118+
doc: {
119+
toObject: Function;
120+
},
121+
opts?: MergedDiffsOptsT
122+
): Promise<Array<RawChangeT>> {
123+
const { startVersion, endVersion } = opts || {};
124+
125+
if (typeof startVersion === 'number' && startVersion < 1)
126+
throw new Error(
127+
`"startVersion" argument should be >= 1, but got: ${startVersion}`
128+
);
129+
130+
if (typeof endVersion === 'number' && endVersion < 1)
131+
throw new Error(
132+
`"endVersion" argument should be >= 1, but got: ${endVersion}`
133+
);
134+
135+
let initialDoc = null;
136+
let currentDoc = { ...doc.toObject() };
137+
138+
if (startVersion && endVersion) {
139+
initialDoc = await this.revertToVersion(currentDoc, startVersion);
140+
currentDoc = await this.revertToVersion(currentDoc, endVersion);
141+
} else if (startVersion) {
142+
initialDoc = await this.revertToVersion(currentDoc, startVersion);
143+
} else if (endVersion) {
144+
initialDoc = await this.revertToVersion(currentDoc, 1);
145+
currentDoc = await this.revertToVersion(currentDoc, endVersion);
146+
} else {
147+
initialDoc = await this.revertToVersion(currentDoc, 1);
148+
}
149+
150+
if (!initialDoc || !currentDoc) return [];
112151
return MHD.findDiff(initialDoc, currentDoc);
113152
};
114153

0 commit comments

Comments
 (0)