rate-core 0.0.6 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +218 -62
- package/lib/rate.js +34 -0
- package/package.json +1 -1
- package/src/index.ts +173 -57
- package/src/rate.ts +86 -17
package/lib/index.js
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __extends = (this && this.__extends) || (function () {
|
|
3
|
+
var extendStatics = function (d, b) {
|
|
4
|
+
extendStatics = Object.setPrototypeOf ||
|
|
5
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
+
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
|
7
|
+
return extendStatics(d, b);
|
|
8
|
+
};
|
|
9
|
+
return function (d, b) {
|
|
10
|
+
extendStatics(d, b);
|
|
11
|
+
function __() { this.constructor = d; }
|
|
12
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
13
|
+
};
|
|
14
|
+
})();
|
|
2
15
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
16
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
17
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -40,15 +53,14 @@ function __export(m) {
|
|
|
40
53
|
}
|
|
41
54
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
55
|
__export(require("./rate"));
|
|
43
|
-
var
|
|
44
|
-
function
|
|
56
|
+
var BaseRateService = (function () {
|
|
57
|
+
function BaseRateService(find, repository, infoRepository, commentRepository, reactionRepository, queryURL) {
|
|
45
58
|
this.find = find;
|
|
46
59
|
this.repository = repository;
|
|
47
60
|
this.infoRepository = infoRepository;
|
|
48
61
|
this.commentRepository = commentRepository;
|
|
49
|
-
this.
|
|
62
|
+
this.reactionRepository = reactionRepository;
|
|
50
63
|
this.queryURL = queryURL;
|
|
51
|
-
this.rate = this.rate.bind(this);
|
|
52
64
|
this.search = this.search.bind(this);
|
|
53
65
|
this.load = this.load.bind(this);
|
|
54
66
|
this.getRate = this.getRate.bind(this);
|
|
@@ -60,48 +72,7 @@ var RateService = (function () {
|
|
|
60
72
|
this.getComments = this.getComments.bind(this);
|
|
61
73
|
this.getComment = this.getComment.bind(this);
|
|
62
74
|
}
|
|
63
|
-
|
|
64
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
65
|
-
var info, r0, exist, r1, sr, history, res;
|
|
66
|
-
return __generator(this, function (_a) {
|
|
67
|
-
switch (_a.label) {
|
|
68
|
-
case 0:
|
|
69
|
-
rate.time = new Date();
|
|
70
|
-
return [4, this.infoRepository.load(rate.id)];
|
|
71
|
-
case 1:
|
|
72
|
-
info = _a.sent();
|
|
73
|
-
if (!!info) return [3, 3];
|
|
74
|
-
return [4, this.repository.insert(rate, true)];
|
|
75
|
-
case 2:
|
|
76
|
-
r0 = _a.sent();
|
|
77
|
-
return [2, r0];
|
|
78
|
-
case 3: return [4, this.repository.load(rate.id, rate.author)];
|
|
79
|
-
case 4:
|
|
80
|
-
exist = _a.sent();
|
|
81
|
-
if (!!exist) return [3, 6];
|
|
82
|
-
return [4, this.repository.insert(rate)];
|
|
83
|
-
case 5:
|
|
84
|
-
r1 = _a.sent();
|
|
85
|
-
return [2, r1];
|
|
86
|
-
case 6:
|
|
87
|
-
sr = { review: exist.review, rate: exist.rate, time: exist.time };
|
|
88
|
-
if (exist.histories && exist.histories.length > 0) {
|
|
89
|
-
history = exist.histories;
|
|
90
|
-
history.push(sr);
|
|
91
|
-
rate.histories = history;
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
rate.histories = [sr];
|
|
95
|
-
}
|
|
96
|
-
return [4, this.repository.update(rate, exist.rate)];
|
|
97
|
-
case 7:
|
|
98
|
-
res = _a.sent();
|
|
99
|
-
return [2, res];
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
};
|
|
104
|
-
RateService.prototype.search = function (s, limit, offset, fields) {
|
|
75
|
+
BaseRateService.prototype.search = function (s, limit, offset, fields) {
|
|
105
76
|
var _this = this;
|
|
106
77
|
return this.find(s, limit, offset, fields).then(function (res) {
|
|
107
78
|
if (!_this.queryURL) {
|
|
@@ -131,19 +102,19 @@ var RateService = (function () {
|
|
|
131
102
|
}
|
|
132
103
|
});
|
|
133
104
|
};
|
|
134
|
-
|
|
105
|
+
BaseRateService.prototype.load = function (id, author) {
|
|
135
106
|
return this.repository.load(id, author);
|
|
136
107
|
};
|
|
137
|
-
|
|
108
|
+
BaseRateService.prototype.getRate = function (id, author) {
|
|
138
109
|
return this.repository.load(id, author);
|
|
139
110
|
};
|
|
140
|
-
|
|
141
|
-
return this.
|
|
111
|
+
BaseRateService.prototype.setUseful = function (id, author, userId) {
|
|
112
|
+
return this.reactionRepository.save(id, author, userId, 1);
|
|
142
113
|
};
|
|
143
|
-
|
|
144
|
-
return this.
|
|
114
|
+
BaseRateService.prototype.removeUseful = function (id, author, userId) {
|
|
115
|
+
return this.reactionRepository.remove(id, author, userId);
|
|
145
116
|
};
|
|
146
|
-
|
|
117
|
+
BaseRateService.prototype.comment = function (comment) {
|
|
147
118
|
var _this = this;
|
|
148
119
|
return this.repository.load(comment.id, comment.author).then(function (checkRate) {
|
|
149
120
|
if (!checkRate) {
|
|
@@ -155,7 +126,7 @@ var RateService = (function () {
|
|
|
155
126
|
}
|
|
156
127
|
});
|
|
157
128
|
};
|
|
158
|
-
|
|
129
|
+
BaseRateService.prototype.removeComment = function (commentId, userId) {
|
|
159
130
|
var _this = this;
|
|
160
131
|
return this.commentRepository.load(commentId).then(function (comment) {
|
|
161
132
|
if (comment) {
|
|
@@ -171,7 +142,7 @@ var RateService = (function () {
|
|
|
171
142
|
}
|
|
172
143
|
});
|
|
173
144
|
};
|
|
174
|
-
|
|
145
|
+
BaseRateService.prototype.updateComment = function (comment) {
|
|
175
146
|
var _this = this;
|
|
176
147
|
return this.commentRepository.load(comment.commentId).then(function (exist) {
|
|
177
148
|
if (!exist) {
|
|
@@ -195,15 +166,164 @@ var RateService = (function () {
|
|
|
195
166
|
}
|
|
196
167
|
});
|
|
197
168
|
};
|
|
198
|
-
|
|
199
|
-
|
|
169
|
+
BaseRateService.prototype.getComments = function (id, author, limit) {
|
|
170
|
+
var _this = this;
|
|
171
|
+
return this.commentRepository.getComments(id, author, limit).then(function (comments) {
|
|
172
|
+
if (_this.queryURL) {
|
|
173
|
+
var ids = [];
|
|
174
|
+
for (var _i = 0, comments_1 = comments; _i < comments_1.length; _i++) {
|
|
175
|
+
var comment = comments_1[_i];
|
|
176
|
+
ids.push(comment.userId);
|
|
177
|
+
}
|
|
178
|
+
return _this.queryURL(ids).then(function (urls) {
|
|
179
|
+
for (var _i = 0, comments_2 = comments; _i < comments_2.length; _i++) {
|
|
180
|
+
var comment = comments_2[_i];
|
|
181
|
+
var i = binarySearch(urls, comment.userId);
|
|
182
|
+
if (i >= 0) {
|
|
183
|
+
comment.userURL = urls[i].url;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return comments;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
return comments;
|
|
191
|
+
}
|
|
192
|
+
});
|
|
200
193
|
};
|
|
201
|
-
|
|
202
|
-
|
|
194
|
+
BaseRateService.prototype.getComment = function (id) {
|
|
195
|
+
var _this = this;
|
|
196
|
+
return this.commentRepository.load(id).then(function (comment) {
|
|
197
|
+
if (comment && _this.queryURL) {
|
|
198
|
+
return _this.queryURL([id]).then(function (urls) {
|
|
199
|
+
var i = binarySearch(urls, comment.userId);
|
|
200
|
+
if (i >= 0) {
|
|
201
|
+
comment.userURL = urls[i].url;
|
|
202
|
+
}
|
|
203
|
+
return comment;
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
return comment;
|
|
208
|
+
}
|
|
209
|
+
});
|
|
203
210
|
};
|
|
204
|
-
return
|
|
211
|
+
return BaseRateService;
|
|
205
212
|
}());
|
|
213
|
+
exports.BaseRateService = BaseRateService;
|
|
214
|
+
var RateService = (function (_super) {
|
|
215
|
+
__extends(RateService, _super);
|
|
216
|
+
function RateService(find, repository, infoRepository, commentRepository, reactionRepository, queryURL) {
|
|
217
|
+
var _this = _super.call(this, find, repository, infoRepository, commentRepository, reactionRepository, queryURL) || this;
|
|
218
|
+
_this.rate = _this.rate.bind(_this);
|
|
219
|
+
return _this;
|
|
220
|
+
}
|
|
221
|
+
RateService.prototype.rate = function (rate) {
|
|
222
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
223
|
+
var info, r0, exist, r1, sr, history, res;
|
|
224
|
+
return __generator(this, function (_a) {
|
|
225
|
+
switch (_a.label) {
|
|
226
|
+
case 0:
|
|
227
|
+
rate.time = new Date();
|
|
228
|
+
return [4, this.infoRepository.load(rate.id)];
|
|
229
|
+
case 1:
|
|
230
|
+
info = _a.sent();
|
|
231
|
+
if (!!info) return [3, 3];
|
|
232
|
+
return [4, this.repository.insert(rate, true)];
|
|
233
|
+
case 2:
|
|
234
|
+
r0 = _a.sent();
|
|
235
|
+
return [2, r0];
|
|
236
|
+
case 3: return [4, this.repository.load(rate.id, rate.author)];
|
|
237
|
+
case 4:
|
|
238
|
+
exist = _a.sent();
|
|
239
|
+
if (!!exist) return [3, 6];
|
|
240
|
+
return [4, this.repository.insert(rate)];
|
|
241
|
+
case 5:
|
|
242
|
+
r1 = _a.sent();
|
|
243
|
+
return [2, r1];
|
|
244
|
+
case 6:
|
|
245
|
+
sr = { review: exist.review, rate: exist.rate, time: exist.time };
|
|
246
|
+
if (exist.histories && exist.histories.length > 0) {
|
|
247
|
+
history = exist.histories;
|
|
248
|
+
history.push(sr);
|
|
249
|
+
rate.histories = history;
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
rate.histories = [sr];
|
|
253
|
+
}
|
|
254
|
+
return [4, this.repository.update(rate, exist.rate)];
|
|
255
|
+
case 7:
|
|
256
|
+
res = _a.sent();
|
|
257
|
+
return [2, res];
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
return RateService;
|
|
263
|
+
}(BaseRateService));
|
|
206
264
|
exports.RateService = RateService;
|
|
265
|
+
function avg(n) {
|
|
266
|
+
var sum = 0;
|
|
267
|
+
for (var _i = 0, n_1 = n; _i < n_1.length; _i++) {
|
|
268
|
+
var s = n_1[_i];
|
|
269
|
+
sum = sum + s;
|
|
270
|
+
}
|
|
271
|
+
return sum / n.length;
|
|
272
|
+
}
|
|
273
|
+
exports.avg = avg;
|
|
274
|
+
var RatesService = (function (_super) {
|
|
275
|
+
__extends(RatesService, _super);
|
|
276
|
+
function RatesService(find, repository, infoRepository, commentRepository, reactionRepository, queryURL) {
|
|
277
|
+
var _this = _super.call(this, find, repository, infoRepository, commentRepository, reactionRepository, queryURL) || this;
|
|
278
|
+
_this.rate = _this.rate.bind(_this);
|
|
279
|
+
return _this;
|
|
280
|
+
}
|
|
281
|
+
RatesService.prototype.rate = function (rate) {
|
|
282
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
283
|
+
var info, r0, exist, r1, sr, history, res;
|
|
284
|
+
return __generator(this, function (_a) {
|
|
285
|
+
switch (_a.label) {
|
|
286
|
+
case 0: return [4, this.infoRepository.load(rate.id)];
|
|
287
|
+
case 1:
|
|
288
|
+
info = _a.sent();
|
|
289
|
+
if (rate.rates && rate.rates.length > 0) {
|
|
290
|
+
rate.rate = avg(rate.rates);
|
|
291
|
+
}
|
|
292
|
+
rate.time = new Date();
|
|
293
|
+
if (!!info) return [3, 3];
|
|
294
|
+
return [4, this.repository.insert(rate, true)];
|
|
295
|
+
case 2:
|
|
296
|
+
r0 = _a.sent();
|
|
297
|
+
return [2, r0];
|
|
298
|
+
case 3: return [4, this.repository.load(rate.id, rate.author)];
|
|
299
|
+
case 4:
|
|
300
|
+
exist = _a.sent();
|
|
301
|
+
if (!!exist) return [3, 6];
|
|
302
|
+
return [4, this.repository.insert(rate)];
|
|
303
|
+
case 5:
|
|
304
|
+
r1 = _a.sent();
|
|
305
|
+
return [2, r1];
|
|
306
|
+
case 6:
|
|
307
|
+
sr = { review: exist.review, rates: exist.rates, time: exist.time };
|
|
308
|
+
if (exist.histories && exist.histories.length > 0) {
|
|
309
|
+
history = exist.histories;
|
|
310
|
+
history.push(sr);
|
|
311
|
+
rate.histories = history;
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
rate.histories = [sr];
|
|
315
|
+
}
|
|
316
|
+
return [4, this.repository.update(rate, exist.rate)];
|
|
317
|
+
case 7:
|
|
318
|
+
res = _a.sent();
|
|
319
|
+
return [2, res];
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
};
|
|
324
|
+
return RatesService;
|
|
325
|
+
}(BaseRateService));
|
|
326
|
+
exports.RatesService = RatesService;
|
|
207
327
|
var CommentQuery = (function () {
|
|
208
328
|
function CommentQuery(find, repository, queryURL) {
|
|
209
329
|
this.find = find;
|
|
@@ -214,10 +334,46 @@ var CommentQuery = (function () {
|
|
|
214
334
|
this.getComments = this.getComments.bind(this);
|
|
215
335
|
}
|
|
216
336
|
CommentQuery.prototype.load = function (id, ctx) {
|
|
217
|
-
|
|
337
|
+
var _this = this;
|
|
338
|
+
return this.repository.load(id, ctx).then(function (comment) {
|
|
339
|
+
if (comment && _this.queryURL) {
|
|
340
|
+
return _this.queryURL([id]).then(function (urls) {
|
|
341
|
+
var i = binarySearch(urls, comment.userId);
|
|
342
|
+
if (i >= 0) {
|
|
343
|
+
comment.userURL = urls[i].url;
|
|
344
|
+
}
|
|
345
|
+
return comment;
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
return comment;
|
|
350
|
+
}
|
|
351
|
+
});
|
|
218
352
|
};
|
|
219
353
|
CommentQuery.prototype.getComments = function (id, author, limit) {
|
|
220
|
-
|
|
354
|
+
var _this = this;
|
|
355
|
+
return this.repository.getComments(id, author, limit).then(function (comments) {
|
|
356
|
+
if (_this.queryURL) {
|
|
357
|
+
var ids = [];
|
|
358
|
+
for (var _i = 0, comments_3 = comments; _i < comments_3.length; _i++) {
|
|
359
|
+
var comment = comments_3[_i];
|
|
360
|
+
ids.push(comment.userId);
|
|
361
|
+
}
|
|
362
|
+
return _this.queryURL(ids).then(function (urls) {
|
|
363
|
+
for (var _i = 0, comments_4 = comments; _i < comments_4.length; _i++) {
|
|
364
|
+
var comment = comments_4[_i];
|
|
365
|
+
var i = binarySearch(urls, comment.userId);
|
|
366
|
+
if (i >= 0) {
|
|
367
|
+
comment.userURL = urls[i].url;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return comments;
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
return comments;
|
|
375
|
+
}
|
|
376
|
+
});
|
|
221
377
|
};
|
|
222
378
|
CommentQuery.prototype.search = function (s, limit, offset, fields) {
|
|
223
379
|
var _this = this;
|
package/lib/rate.js
CHANGED
|
@@ -116,3 +116,37 @@ exports.info10Model = {
|
|
|
116
116
|
type: 'number',
|
|
117
117
|
}
|
|
118
118
|
};
|
|
119
|
+
exports.rateInfoModel = {
|
|
120
|
+
id: {
|
|
121
|
+
key: true
|
|
122
|
+
},
|
|
123
|
+
rate: {
|
|
124
|
+
type: 'number',
|
|
125
|
+
},
|
|
126
|
+
count: {
|
|
127
|
+
type: 'integer',
|
|
128
|
+
},
|
|
129
|
+
score: {
|
|
130
|
+
type: 'number',
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
exports.ratesModel = {
|
|
134
|
+
id: {
|
|
135
|
+
key: true,
|
|
136
|
+
match: 'equal'
|
|
137
|
+
},
|
|
138
|
+
author: {
|
|
139
|
+
key: true,
|
|
140
|
+
match: 'equal'
|
|
141
|
+
},
|
|
142
|
+
rate: {
|
|
143
|
+
type: 'number'
|
|
144
|
+
},
|
|
145
|
+
rates: {
|
|
146
|
+
type: 'integers'
|
|
147
|
+
},
|
|
148
|
+
time: {
|
|
149
|
+
type: 'datetime'
|
|
150
|
+
},
|
|
151
|
+
review: {},
|
|
152
|
+
};
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Attributes, Search, SearchResult } from './core';
|
|
2
2
|
import {
|
|
3
|
-
Comment, CommentFilter, InfoRepository, Rate, RateCommentQuery, RateCommentRepository, RateFilter, Rater,
|
|
4
|
-
|
|
3
|
+
BaseRate, Comment, CommentFilter, InfoRepository, Rate, RateCommentQuery, RateCommentRepository, RateFilter, Rater, RateReactionRepository, RateRepository,
|
|
4
|
+
Rates, RatesFilter, ShortComment, ShortRate, ShortRates
|
|
5
5
|
} from './rate';
|
|
6
6
|
|
|
7
7
|
export * from './rate';
|
|
@@ -10,14 +10,13 @@ export interface URL {
|
|
|
10
10
|
id: string;
|
|
11
11
|
url: string;
|
|
12
12
|
}
|
|
13
|
-
export class
|
|
14
|
-
constructor(protected find: Search<
|
|
15
|
-
public repository: RateRepository
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
this.rate = this.rate.bind(this);
|
|
13
|
+
export class BaseRateService<R extends BaseRate, F, O> {
|
|
14
|
+
constructor(protected find: Search<R, F>,
|
|
15
|
+
public repository: RateRepository<R>,
|
|
16
|
+
protected infoRepository: InfoRepository<O>,
|
|
17
|
+
protected commentRepository: RateCommentRepository,
|
|
18
|
+
protected reactionRepository: RateReactionRepository,
|
|
19
|
+
protected queryURL?: (ids: string[]) => Promise<URL[]>) {
|
|
21
20
|
this.search = this.search.bind(this);
|
|
22
21
|
this.load = this.load.bind(this);
|
|
23
22
|
this.getRate = this.getRate.bind(this);
|
|
@@ -29,30 +28,7 @@ export class RateService<O> implements Rater {
|
|
|
29
28
|
this.getComments = this.getComments.bind(this);
|
|
30
29
|
this.getComment = this.getComment.bind(this);
|
|
31
30
|
}
|
|
32
|
-
|
|
33
|
-
rate.time = new Date();
|
|
34
|
-
const info = await this.infoRepository.load(rate.id);
|
|
35
|
-
if (!info) {
|
|
36
|
-
const r0 = await this.repository.insert(rate, true);
|
|
37
|
-
return r0;
|
|
38
|
-
}
|
|
39
|
-
const exist = await this.repository.load(rate.id, rate.author);
|
|
40
|
-
if (!exist) {
|
|
41
|
-
const r1 = await this.repository.insert(rate);
|
|
42
|
-
return r1;
|
|
43
|
-
}
|
|
44
|
-
const sr: ShortRate = { review: exist.review, rate: exist.rate, time: exist.time };
|
|
45
|
-
if (exist.histories && exist.histories.length > 0) {
|
|
46
|
-
const history = exist.histories;
|
|
47
|
-
history.push(sr);
|
|
48
|
-
rate.histories = history;
|
|
49
|
-
} else {
|
|
50
|
-
rate.histories = [sr];
|
|
51
|
-
}
|
|
52
|
-
const res = await this.repository.update(rate, exist.rate);
|
|
53
|
-
return res;
|
|
54
|
-
}
|
|
55
|
-
search(s: RateFilter, limit?: number, offset?: number | string, fields?: string[]): Promise<SearchResult<Rate>> {
|
|
31
|
+
search(s: F, limit?: number, offset?: number | string, fields?: string[]): Promise<SearchResult<R>> {
|
|
56
32
|
return this.find(s, limit, offset, fields).then(res => {
|
|
57
33
|
if (!this.queryURL) {
|
|
58
34
|
return res;
|
|
@@ -77,17 +53,17 @@ export class RateService<O> implements Rater {
|
|
|
77
53
|
}
|
|
78
54
|
});
|
|
79
55
|
}
|
|
80
|
-
load(id: string, author: string): Promise<
|
|
56
|
+
load(id: string, author: string): Promise<R | null> {
|
|
81
57
|
return this.repository.load(id, author);
|
|
82
58
|
}
|
|
83
|
-
getRate(id: string, author: string): Promise<
|
|
59
|
+
getRate(id: string, author: string): Promise<R | null> {
|
|
84
60
|
return this.repository.load(id, author);
|
|
85
61
|
}
|
|
86
62
|
setUseful(id: string, author: string, userId: string): Promise<number> {
|
|
87
|
-
return this.
|
|
63
|
+
return this.reactionRepository.save(id, author, userId, 1);
|
|
88
64
|
}
|
|
89
65
|
removeUseful(id: string, author: string, userId: string): Promise<number> {
|
|
90
|
-
return this.
|
|
66
|
+
return this.reactionRepository.remove(id, author, userId);
|
|
91
67
|
}
|
|
92
68
|
comment(comment: Comment): Promise<number> {
|
|
93
69
|
return this.repository.load(comment.id, comment.author).then(checkRate => {
|
|
@@ -128,34 +104,174 @@ export class RateService<O> implements Rater {
|
|
|
128
104
|
exist.histories = [c];
|
|
129
105
|
}
|
|
130
106
|
exist.comment = comment.comment;
|
|
131
|
-
const res =
|
|
107
|
+
const res = this.commentRepository.update(exist);
|
|
132
108
|
return res;
|
|
133
109
|
}
|
|
134
110
|
});
|
|
135
111
|
}
|
|
136
112
|
getComments(id: string, author: string, limit?: number): Promise<Comment[]> {
|
|
137
|
-
return this.commentRepository.getComments(id, author, limit)
|
|
113
|
+
return this.commentRepository.getComments(id, author, limit).then(comments => {
|
|
114
|
+
if (this.queryURL) {
|
|
115
|
+
const ids: string[] = [];
|
|
116
|
+
for (const comment of comments) {
|
|
117
|
+
ids.push(comment.userId);
|
|
118
|
+
}
|
|
119
|
+
return this.queryURL(ids).then(urls => {
|
|
120
|
+
for (const comment of comments) {
|
|
121
|
+
const i = binarySearch(urls, comment.userId);
|
|
122
|
+
if (i >= 0) {
|
|
123
|
+
comment.userURL = urls[i].url;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return comments;
|
|
127
|
+
});
|
|
128
|
+
} else {
|
|
129
|
+
return comments;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
138
132
|
}
|
|
139
|
-
getComment(id: string): Promise<Comment|null> {
|
|
140
|
-
return this.commentRepository.load(id)
|
|
133
|
+
getComment(id: string): Promise<Comment | null> {
|
|
134
|
+
return this.commentRepository.load(id).then(comment => {
|
|
135
|
+
if (comment && this.queryURL) {
|
|
136
|
+
return this.queryURL([id]).then(urls => {
|
|
137
|
+
const i = binarySearch(urls, comment.userId);
|
|
138
|
+
if (i >= 0) {
|
|
139
|
+
comment.userURL = urls[i].url;
|
|
140
|
+
}
|
|
141
|
+
return comment;
|
|
142
|
+
});
|
|
143
|
+
} else {
|
|
144
|
+
return comment;
|
|
145
|
+
}
|
|
146
|
+
});
|
|
141
147
|
}
|
|
142
148
|
}
|
|
143
149
|
export interface CommentRepository {
|
|
144
|
-
load(commentId: string, ctx?: any): Promise<Comment|null>;
|
|
150
|
+
load(commentId: string, ctx?: any): Promise<Comment | null>;
|
|
145
151
|
getComments(id: string, author: string, limit?: number): Promise<Comment[]>;
|
|
146
152
|
}
|
|
147
153
|
// tslint:disable-next-line:max-classes-per-file
|
|
154
|
+
export class RateService<O> extends BaseRateService<Rate, RateFilter, O> implements Rater<Rate, RateFilter> {
|
|
155
|
+
constructor(find: Search<Rate, RateFilter>,
|
|
156
|
+
repository: RateRepository<Rate>,
|
|
157
|
+
infoRepository: InfoRepository<O>,
|
|
158
|
+
commentRepository: RateCommentRepository,
|
|
159
|
+
reactionRepository: RateReactionRepository,
|
|
160
|
+
queryURL?: (ids: string[]) => Promise<URL[]>) {
|
|
161
|
+
super(find, repository, infoRepository, commentRepository, reactionRepository, queryURL);
|
|
162
|
+
this.rate = this.rate.bind(this);
|
|
163
|
+
}
|
|
164
|
+
async rate(rate: Rate): Promise<number> {
|
|
165
|
+
rate.time = new Date();
|
|
166
|
+
const info = await this.infoRepository.load(rate.id);
|
|
167
|
+
if (!info) {
|
|
168
|
+
const r0 = await this.repository.insert(rate, true);
|
|
169
|
+
return r0;
|
|
170
|
+
}
|
|
171
|
+
const exist = await this.repository.load(rate.id, rate.author);
|
|
172
|
+
if (!exist) {
|
|
173
|
+
const r1 = await this.repository.insert(rate);
|
|
174
|
+
return r1;
|
|
175
|
+
}
|
|
176
|
+
const sr: ShortRate = { review: exist.review, rate: exist.rate, time: exist.time };
|
|
177
|
+
if (exist.histories && exist.histories.length > 0) {
|
|
178
|
+
const history = exist.histories;
|
|
179
|
+
history.push(sr);
|
|
180
|
+
rate.histories = history;
|
|
181
|
+
} else {
|
|
182
|
+
rate.histories = [sr];
|
|
183
|
+
}
|
|
184
|
+
const res = await this.repository.update(rate, exist.rate);
|
|
185
|
+
return res;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
export function avg(n: number[]): number {
|
|
189
|
+
let sum = 0;
|
|
190
|
+
for (const s of n) {
|
|
191
|
+
sum = sum + s;
|
|
192
|
+
}
|
|
193
|
+
return sum / n.length;
|
|
194
|
+
}
|
|
195
|
+
// tslint:disable-next-line:max-classes-per-file
|
|
196
|
+
export class RatesService<O> extends BaseRateService<Rates, RatesFilter, O> implements Rater<Rates, RatesFilter> {
|
|
197
|
+
constructor(find: Search<Rates, RatesFilter>,
|
|
198
|
+
repository: RateRepository<Rates>,
|
|
199
|
+
infoRepository: InfoRepository<O>,
|
|
200
|
+
commentRepository: RateCommentRepository,
|
|
201
|
+
reactionRepository: RateReactionRepository,
|
|
202
|
+
queryURL?: (ids: string[]) => Promise<URL[]>) {
|
|
203
|
+
super(find, repository, infoRepository, commentRepository, reactionRepository, queryURL);
|
|
204
|
+
this.rate = this.rate.bind(this);
|
|
205
|
+
}
|
|
206
|
+
async rate(rate: Rates): Promise<number> {
|
|
207
|
+
const info = await this.infoRepository.load(rate.id);
|
|
208
|
+
if (rate.rates && rate.rates.length > 0) {
|
|
209
|
+
rate.rate = avg(rate.rates);
|
|
210
|
+
}
|
|
211
|
+
rate.time = new Date();
|
|
212
|
+
if (!info) {
|
|
213
|
+
const r0 = await this.repository.insert(rate, true);
|
|
214
|
+
return r0;
|
|
215
|
+
}
|
|
216
|
+
const exist = await this.repository.load(rate.id, rate.author);
|
|
217
|
+
if (!exist) {
|
|
218
|
+
const r1 = await this.repository.insert(rate);
|
|
219
|
+
return r1;
|
|
220
|
+
}
|
|
221
|
+
const sr: ShortRates = { review: exist.review, rates: exist.rates, time: exist.time };
|
|
222
|
+
if (exist.histories && exist.histories.length > 0) {
|
|
223
|
+
const history = exist.histories;
|
|
224
|
+
history.push(sr);
|
|
225
|
+
rate.histories = history;
|
|
226
|
+
} else {
|
|
227
|
+
rate.histories = [sr];
|
|
228
|
+
}
|
|
229
|
+
const res = await this.repository.update(rate, exist.rate);
|
|
230
|
+
return res;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
// tslint:disable-next-line:max-classes-per-file
|
|
148
234
|
export class CommentQuery implements RateCommentQuery {
|
|
149
235
|
constructor(protected find: Search<Comment, CommentFilter>, protected repository: CommentRepository, private queryURL?: (ids: string[]) => Promise<URL[]>) {
|
|
150
236
|
this.load = this.load.bind(this);
|
|
151
237
|
this.search = this.search.bind(this);
|
|
152
238
|
this.getComments = this.getComments.bind(this);
|
|
153
239
|
}
|
|
154
|
-
load(id: string, ctx?: any): Promise<Comment|null> {
|
|
155
|
-
return this.repository.load(id, ctx)
|
|
240
|
+
load(id: string, ctx?: any): Promise<Comment | null> {
|
|
241
|
+
return this.repository.load(id, ctx).then(comment => {
|
|
242
|
+
if (comment && this.queryURL) {
|
|
243
|
+
return this.queryURL([id]).then(urls => {
|
|
244
|
+
const i = binarySearch(urls, comment.userId);
|
|
245
|
+
if (i >= 0) {
|
|
246
|
+
comment.userURL = urls[i].url;
|
|
247
|
+
}
|
|
248
|
+
return comment;
|
|
249
|
+
});
|
|
250
|
+
} else {
|
|
251
|
+
return comment;
|
|
252
|
+
}
|
|
253
|
+
});
|
|
156
254
|
}
|
|
157
255
|
getComments(id: string, author: string, limit?: number): Promise<Comment[]> {
|
|
158
|
-
return this.repository.getComments(id, author, limit)
|
|
256
|
+
return this.repository.getComments(id, author, limit).then(comments => {
|
|
257
|
+
if (this.queryURL) {
|
|
258
|
+
const ids: string[] = [];
|
|
259
|
+
for (const comment of comments) {
|
|
260
|
+
ids.push(comment.userId);
|
|
261
|
+
}
|
|
262
|
+
return this.queryURL(ids).then(urls => {
|
|
263
|
+
for (const comment of comments) {
|
|
264
|
+
const i = binarySearch(urls, comment.userId);
|
|
265
|
+
if (i >= 0) {
|
|
266
|
+
comment.userURL = urls[i].url;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return comments;
|
|
270
|
+
});
|
|
271
|
+
} else {
|
|
272
|
+
return comments;
|
|
273
|
+
}
|
|
274
|
+
});
|
|
159
275
|
}
|
|
160
276
|
search(s: CommentFilter, limit?: number, offset?: number | string, fields?: string[]): Promise<SearchResult<Comment>> {
|
|
161
277
|
return this.find(s, limit, offset, fields).then(res => {
|
|
@@ -187,16 +303,16 @@ function binarySearch(ar: URL[], el: string): number {
|
|
|
187
303
|
let m = 0;
|
|
188
304
|
let n = ar.length - 1;
|
|
189
305
|
while (m <= n) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
306
|
+
// tslint:disable-next-line:no-bitwise
|
|
307
|
+
const k = (n + m) >> 1;
|
|
308
|
+
const cmp = compare(el, ar[k].id);
|
|
309
|
+
if (cmp > 0) {
|
|
310
|
+
m = k + 1;
|
|
311
|
+
} else if (cmp < 0) {
|
|
312
|
+
n = k - 1;
|
|
313
|
+
} else {
|
|
314
|
+
return k;
|
|
315
|
+
}
|
|
200
316
|
}
|
|
201
317
|
return -m - 1;
|
|
202
318
|
}
|
|
@@ -206,7 +322,7 @@ function compare(s1: string, s2: string): number {
|
|
|
206
322
|
interface ErrorMessage {
|
|
207
323
|
field: string;
|
|
208
324
|
code: string;
|
|
209
|
-
param?: string|number|Date;
|
|
325
|
+
param?: string | number | Date;
|
|
210
326
|
message?: string;
|
|
211
327
|
}
|
|
212
328
|
// tslint:disable-next-line:max-classes-per-file
|
package/src/rate.ts
CHANGED
|
@@ -4,12 +4,13 @@ export interface RateId {
|
|
|
4
4
|
id: string;
|
|
5
5
|
author: string;
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
export interface Rate {
|
|
9
|
-
id: string;
|
|
7
|
+
export interface BaseRate {
|
|
10
8
|
author: string;
|
|
11
9
|
authorURL?: string;
|
|
12
10
|
rate: number;
|
|
11
|
+
}
|
|
12
|
+
export interface Rate extends BaseRate {
|
|
13
|
+
id: string;
|
|
13
14
|
time: Date;
|
|
14
15
|
review: string;
|
|
15
16
|
usefulCount: number;
|
|
@@ -30,24 +31,56 @@ export interface RateFilter extends Filter {
|
|
|
30
31
|
usefulCount?: number;
|
|
31
32
|
replyCount?: number;
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
export interface RateInfo {
|
|
35
|
+
id: string;
|
|
36
|
+
rate: number;
|
|
37
|
+
count: number;
|
|
38
|
+
score: number;
|
|
39
|
+
}
|
|
40
|
+
export interface ShortRates {
|
|
41
|
+
rates: number[];
|
|
42
|
+
time: Date;
|
|
43
|
+
review: string;
|
|
44
|
+
}
|
|
45
|
+
export interface Rates extends BaseRate {
|
|
46
|
+
id: string;
|
|
47
|
+
rates: number[];
|
|
48
|
+
time: Date;
|
|
49
|
+
review: string;
|
|
50
|
+
usefulCount: number;
|
|
51
|
+
replyCount: number;
|
|
52
|
+
histories?: ShortRates[];
|
|
53
|
+
}
|
|
54
|
+
export interface RatesFilter extends RateFilter {
|
|
55
|
+
rates?: number[];
|
|
56
|
+
rate1: number;
|
|
57
|
+
rate2: number;
|
|
58
|
+
rate3: number;
|
|
59
|
+
rate4: number;
|
|
60
|
+
rate5: number;
|
|
61
|
+
rate6: number;
|
|
62
|
+
rate7: number;
|
|
63
|
+
rate8: number;
|
|
64
|
+
rate9: number;
|
|
65
|
+
rate10: number;
|
|
66
|
+
}
|
|
67
|
+
export interface RateRepository<R> {
|
|
35
68
|
// save(obj: Rate, info?: T, ctx?: any): Promise<number>;
|
|
36
|
-
insert(rate:
|
|
37
|
-
update(rate:
|
|
38
|
-
load(id: string, author: string): Promise<
|
|
39
|
-
}
|
|
40
|
-
export interface Rater {
|
|
41
|
-
search(s:
|
|
42
|
-
load(id: string, author: string): Promise<
|
|
43
|
-
rate(rate:
|
|
69
|
+
insert(rate: R, newInfo?: boolean): Promise<number>;
|
|
70
|
+
update(rate: R, oldRate: number): Promise<number>;
|
|
71
|
+
load(id: string, author: string): Promise<R | null>;
|
|
72
|
+
}
|
|
73
|
+
export interface Rater<R, F extends Filter> {
|
|
74
|
+
search(s: F, limit?: number, offset?: number | string, fields?: string[], ctx?: any): Promise<SearchResult<R>>;
|
|
75
|
+
load(id: string, author: string): Promise<R | null>;
|
|
76
|
+
rate(rate: R): Promise<number>;
|
|
44
77
|
setUseful(id: string, author: string, userId: string, ctx?: any): Promise<number>;
|
|
45
78
|
removeUseful(id: string, author: string, userId: string, ctx?: any): Promise<number>;
|
|
46
79
|
comment(comment: Comment): Promise<number>;
|
|
47
80
|
removeComment(id: string, author: string, ctx?: any): Promise<number>;
|
|
48
81
|
updateComment(comment: Comment): Promise<number>;
|
|
49
82
|
getComments(id: string, author: string, limit?: number): Promise<Comment[]>;
|
|
50
|
-
getComment(id: string): Promise<Comment|null>;
|
|
83
|
+
getComment(id: string): Promise<Comment | null>;
|
|
51
84
|
}
|
|
52
85
|
export interface RateReactionRepository {
|
|
53
86
|
remove(id: string, author: string, userId: string, ctx?: any): Promise<number>;
|
|
@@ -60,9 +93,9 @@ export interface RateCommentRepository extends Repository<Comment, string> {
|
|
|
60
93
|
}
|
|
61
94
|
|
|
62
95
|
export interface Query<T, ID, S> {
|
|
63
|
-
search: (s: S, limit?: number, skip?: number|string, fields?: string[]) => Promise<SearchResult<T>>;
|
|
64
|
-
metadata?(): Attributes|undefined;
|
|
65
|
-
load(id: ID, ctx?: any): Promise<T|null>;
|
|
96
|
+
search: (s: S, limit?: number, skip?: number | string, fields?: string[]) => Promise<SearchResult<T>>;
|
|
97
|
+
metadata?(): Attributes | undefined;
|
|
98
|
+
load(id: ID, ctx?: any): Promise<T | null>;
|
|
66
99
|
}
|
|
67
100
|
export interface RateCommentQuery extends Query<Comment, string, CommentFilter> {
|
|
68
101
|
getComments(id: string, author: string, limit?: number): Promise<Comment[]>;
|
|
@@ -247,3 +280,39 @@ export interface CommentFilter extends Filter {
|
|
|
247
280
|
time?: Date;
|
|
248
281
|
updatedAt?: Date;
|
|
249
282
|
}
|
|
283
|
+
|
|
284
|
+
export const rateInfoModel: Attributes = {
|
|
285
|
+
id: {
|
|
286
|
+
key: true
|
|
287
|
+
},
|
|
288
|
+
rate: {
|
|
289
|
+
type: 'number',
|
|
290
|
+
},
|
|
291
|
+
count: {
|
|
292
|
+
type: 'integer',
|
|
293
|
+
},
|
|
294
|
+
score: {
|
|
295
|
+
type: 'number',
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
export const ratesModel: Attributes = {
|
|
300
|
+
id: {
|
|
301
|
+
key: true,
|
|
302
|
+
match: 'equal'
|
|
303
|
+
},
|
|
304
|
+
author: {
|
|
305
|
+
key: true,
|
|
306
|
+
match: 'equal'
|
|
307
|
+
},
|
|
308
|
+
rate: {
|
|
309
|
+
type: 'number'
|
|
310
|
+
},
|
|
311
|
+
rates: {
|
|
312
|
+
type: 'integers'
|
|
313
|
+
},
|
|
314
|
+
time: {
|
|
315
|
+
type: 'datetime'
|
|
316
|
+
},
|
|
317
|
+
review: {},
|
|
318
|
+
};
|