rate-core 0.0.4 → 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 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,64 +53,26 @@ function __export(m) {
40
53
  }
41
54
  Object.defineProperty(exports, "__esModule", { value: true });
42
55
  __export(require("./rate"));
43
- var RateService = (function () {
44
- function RateService(find, repository, infoRepository, commentRepository, rateReactionRepository, queryURL) {
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.rateReactionRepository = rateReactionRepository;
62
+ this.reactionRepository = reactionRepository;
50
63
  this.queryURL = queryURL;
51
- this.rate = this.rate.bind(this);
64
+ this.search = this.search.bind(this);
65
+ this.load = this.load.bind(this);
66
+ this.getRate = this.getRate.bind(this);
67
+ this.setUseful = this.setUseful.bind(this);
68
+ this.removeUseful = this.removeUseful.bind(this);
52
69
  this.comment = this.comment.bind(this);
53
70
  this.removeComment = this.removeComment.bind(this);
54
71
  this.updateComment = this.updateComment.bind(this);
55
- this.search = this.search.bind(this);
56
- this.getComment = this.getComment.bind(this);
57
72
  this.getComments = this.getComments.bind(this);
73
+ this.getComment = this.getComment.bind(this);
58
74
  }
59
- RateService.prototype.rate = function (rate) {
60
- return __awaiter(this, void 0, void 0, function () {
61
- var info, r0, exist, r1, sr, history, res;
62
- return __generator(this, function (_a) {
63
- switch (_a.label) {
64
- case 0:
65
- rate.time = new Date();
66
- return [4, this.infoRepository.load(rate.id)];
67
- case 1:
68
- info = _a.sent();
69
- if (!!info) return [3, 3];
70
- return [4, this.repository.insert(rate, true)];
71
- case 2:
72
- r0 = _a.sent();
73
- return [2, r0];
74
- case 3: return [4, this.repository.getRate(rate.id, rate.author)];
75
- case 4:
76
- exist = _a.sent();
77
- if (!!exist) return [3, 6];
78
- return [4, this.repository.insert(rate)];
79
- case 5:
80
- r1 = _a.sent();
81
- return [2, r1];
82
- case 6:
83
- sr = { review: exist.review, rate: exist.rate, time: exist.time };
84
- if (exist.histories && exist.histories.length > 0) {
85
- history = exist.histories;
86
- history.push(sr);
87
- rate.histories = history;
88
- }
89
- else {
90
- rate.histories = [sr];
91
- }
92
- return [4, this.repository.update(rate, exist.rate)];
93
- case 7:
94
- res = _a.sent();
95
- return [2, res];
96
- }
97
- });
98
- });
99
- };
100
- RateService.prototype.search = function (s, limit, offset, fields) {
75
+ BaseRateService.prototype.search = function (s, limit, offset, fields) {
101
76
  var _this = this;
102
77
  return this.find(s, limit, offset, fields).then(function (res) {
103
78
  if (!_this.queryURL) {
@@ -127,18 +102,21 @@ var RateService = (function () {
127
102
  }
128
103
  });
129
104
  };
130
- RateService.prototype.getRate = function (id, author) {
131
- return this.repository.getRate(id, author);
105
+ BaseRateService.prototype.load = function (id, author) {
106
+ return this.repository.load(id, author);
107
+ };
108
+ BaseRateService.prototype.getRate = function (id, author) {
109
+ return this.repository.load(id, author);
132
110
  };
133
- RateService.prototype.setUseful = function (id, author, userId) {
134
- return this.rateReactionRepository.save(id, author, userId, 1);
111
+ BaseRateService.prototype.setUseful = function (id, author, userId) {
112
+ return this.reactionRepository.save(id, author, userId, 1);
135
113
  };
136
- RateService.prototype.removeUseful = function (id, author, userId) {
137
- return this.rateReactionRepository.remove(id, author, userId);
114
+ BaseRateService.prototype.removeUseful = function (id, author, userId) {
115
+ return this.reactionRepository.remove(id, author, userId);
138
116
  };
139
- RateService.prototype.comment = function (comment) {
117
+ BaseRateService.prototype.comment = function (comment) {
140
118
  var _this = this;
141
- return this.repository.getRate(comment.id, comment.author).then(function (checkRate) {
119
+ return this.repository.load(comment.id, comment.author).then(function (checkRate) {
142
120
  if (!checkRate) {
143
121
  return -1;
144
122
  }
@@ -148,7 +126,7 @@ var RateService = (function () {
148
126
  }
149
127
  });
150
128
  };
151
- RateService.prototype.removeComment = function (commentId, userId) {
129
+ BaseRateService.prototype.removeComment = function (commentId, userId) {
152
130
  var _this = this;
153
131
  return this.commentRepository.load(commentId).then(function (comment) {
154
132
  if (comment) {
@@ -164,7 +142,7 @@ var RateService = (function () {
164
142
  }
165
143
  });
166
144
  };
167
- RateService.prototype.updateComment = function (comment) {
145
+ BaseRateService.prototype.updateComment = function (comment) {
168
146
  var _this = this;
169
147
  return this.commentRepository.load(comment.commentId).then(function (exist) {
170
148
  if (!exist) {
@@ -188,15 +166,164 @@ var RateService = (function () {
188
166
  }
189
167
  });
190
168
  };
191
- RateService.prototype.getComments = function (id, author, limit) {
192
- return this.commentRepository.getComments(id, author, limit);
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
+ });
193
193
  };
194
- RateService.prototype.getComment = function (id) {
195
- return this.commentRepository.load(id);
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
+ });
196
210
  };
197
- return RateService;
211
+ return BaseRateService;
198
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));
199
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;
200
327
  var CommentQuery = (function () {
201
328
  function CommentQuery(find, repository, queryURL) {
202
329
  this.find = find;
@@ -207,10 +334,46 @@ var CommentQuery = (function () {
207
334
  this.getComments = this.getComments.bind(this);
208
335
  }
209
336
  CommentQuery.prototype.load = function (id, ctx) {
210
- return this.repository.load(id, ctx);
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
+ });
211
352
  };
212
353
  CommentQuery.prototype.getComments = function (id, author, limit) {
213
- return this.repository.getComments(id, author, limit);
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
+ });
214
377
  };
215
378
  CommentQuery.prototype.search = function (s, limit, offset, fields) {
216
379
  var _this = this;
package/lib/rate.js CHANGED
@@ -116,45 +116,37 @@ exports.info10Model = {
116
116
  type: 'number',
117
117
  }
118
118
  };
119
- exports.commentModel = {
120
- comment: {
121
- length: 500
119
+ exports.rateInfoModel = {
120
+ id: {
121
+ key: true
122
122
  },
123
- time: {
124
- type: 'datetime'
123
+ rate: {
124
+ type: 'number',
125
+ },
126
+ count: {
127
+ type: 'integer',
128
+ },
129
+ score: {
130
+ type: 'number',
125
131
  }
126
132
  };
127
- exports.rateCommentModel = {
128
- commentId: {
129
- key: true
130
- },
133
+ exports.ratesModel = {
131
134
  id: {
132
- required: true,
133
- noupdate: true,
135
+ key: true,
134
136
  match: 'equal'
135
137
  },
136
138
  author: {
137
- required: true,
138
- noupdate: true,
139
+ key: true,
139
140
  match: 'equal'
140
141
  },
141
- userId: {
142
- required: true,
143
- noupdate: true,
144
- match: 'equal'
142
+ rate: {
143
+ type: 'number'
145
144
  },
146
- comment: {
147
- length: 500
145
+ rates: {
146
+ type: 'integers'
148
147
  },
149
148
  time: {
150
- type: 'datetime',
151
- noupdate: true,
152
- },
153
- updatedAt: {
154
149
  type: 'datetime'
155
150
  },
156
- histories: {
157
- type: 'array',
158
- typeof: exports.commentModel
159
- }
151
+ review: {},
160
152
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rate-core",
3
- "version": "0.0.4",
3
+ "version": "0.5.0",
4
4
  "description": "rate",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./src/index.ts",
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, RateCommentRepository, RateCommentQuery, RateFilter, RateReactionRepository,
4
- RateRepository, Rater, ShortComment, ShortRate
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,45 +10,25 @@ export interface URL {
10
10
  id: string;
11
11
  url: string;
12
12
  }
13
- export class RateService<O> implements Rater {
14
- constructor(protected find: Search<Rate, RateFilter>,
15
- public repository: RateRepository,
16
- private infoRepository: InfoRepository<O>,
17
- private commentRepository: RateCommentRepository,
18
- private rateReactionRepository: RateReactionRepository,
19
- private queryURL?: (ids: string[]) => Promise<URL[]>) {
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[]>) {
20
+ this.search = this.search.bind(this);
21
+ this.load = this.load.bind(this);
22
+ this.getRate = this.getRate.bind(this);
23
+ this.setUseful = this.setUseful.bind(this);
24
+ this.removeUseful = this.removeUseful.bind(this);
21
25
  this.comment = this.comment.bind(this);
22
26
  this.removeComment = this.removeComment.bind(this);
23
27
  this.updateComment = this.updateComment.bind(this);
24
- this.search = this.search.bind(this);
25
- this.getComment = this.getComment.bind(this);
26
28
  this.getComments = this.getComments.bind(this);
29
+ this.getComment = this.getComment.bind(this);
27
30
  }
28
- async rate(rate: Rate): Promise<number> {
29
- rate.time = new Date();
30
- const info = await this.infoRepository.load(rate.id);
31
- if (!info) {
32
- const r0 = await this.repository.insert(rate, true);
33
- return r0;
34
- }
35
- const exist = await this.repository.getRate(rate.id, rate.author);
36
- if (!exist) {
37
- const r1 = await this.repository.insert(rate);
38
- return r1;
39
- }
40
- const sr: ShortRate = { review: exist.review, rate: exist.rate, time: exist.time };
41
- if (exist.histories && exist.histories.length > 0) {
42
- const history = exist.histories;
43
- history.push(sr);
44
- rate.histories = history;
45
- } else {
46
- rate.histories = [sr];
47
- }
48
- const res = await this.repository.update(rate, exist.rate);
49
- return res;
50
- }
51
- 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>> {
52
32
  return this.find(s, limit, offset, fields).then(res => {
53
33
  if (!this.queryURL) {
54
34
  return res;
@@ -73,17 +53,20 @@ export class RateService<O> implements Rater {
73
53
  }
74
54
  });
75
55
  }
76
- getRate(id: string, author: string): Promise<Rate | null> {
77
- return this.repository.getRate(id, author);
56
+ load(id: string, author: string): Promise<R | null> {
57
+ return this.repository.load(id, author);
58
+ }
59
+ getRate(id: string, author: string): Promise<R | null> {
60
+ return this.repository.load(id, author);
78
61
  }
79
62
  setUseful(id: string, author: string, userId: string): Promise<number> {
80
- return this.rateReactionRepository.save(id, author, userId, 1);
63
+ return this.reactionRepository.save(id, author, userId, 1);
81
64
  }
82
65
  removeUseful(id: string, author: string, userId: string): Promise<number> {
83
- return this.rateReactionRepository.remove(id, author, userId);
66
+ return this.reactionRepository.remove(id, author, userId);
84
67
  }
85
68
  comment(comment: Comment): Promise<number> {
86
- return this.repository.getRate(comment.id, comment.author).then(checkRate => {
69
+ return this.repository.load(comment.id, comment.author).then(checkRate => {
87
70
  if (!checkRate) {
88
71
  return -1;
89
72
  } else {
@@ -121,34 +104,174 @@ export class RateService<O> implements Rater {
121
104
  exist.histories = [c];
122
105
  }
123
106
  exist.comment = comment.comment;
124
- const res = this.commentRepository.update(exist);
107
+ const res = this.commentRepository.update(exist);
125
108
  return res;
126
109
  }
127
110
  });
128
111
  }
129
112
  getComments(id: string, author: string, limit?: number): Promise<Comment[]> {
130
- 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
+ });
131
132
  }
132
- getComment(id: string): Promise<Comment|null> {
133
- 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
+ });
134
147
  }
135
148
  }
136
149
  export interface CommentRepository {
137
- load(commentId: string, ctx?: any): Promise<Comment|null>;
150
+ load(commentId: string, ctx?: any): Promise<Comment | null>;
138
151
  getComments(id: string, author: string, limit?: number): Promise<Comment[]>;
139
152
  }
140
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
141
234
  export class CommentQuery implements RateCommentQuery {
142
235
  constructor(protected find: Search<Comment, CommentFilter>, protected repository: CommentRepository, private queryURL?: (ids: string[]) => Promise<URL[]>) {
143
236
  this.load = this.load.bind(this);
144
237
  this.search = this.search.bind(this);
145
- this.getComments = this.getComments.bind(this)
238
+ this.getComments = this.getComments.bind(this);
146
239
  }
147
- load(id: string, ctx?: any): Promise<Comment|null> {
148
- 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
+ });
149
254
  }
150
255
  getComments(id: string, author: string, limit?: number): Promise<Comment[]> {
151
- 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
+ });
152
275
  }
153
276
  search(s: CommentFilter, limit?: number, offset?: number | string, fields?: string[]): Promise<SearchResult<Comment>> {
154
277
  return this.find(s, limit, offset, fields).then(res => {
@@ -180,16 +303,16 @@ function binarySearch(ar: URL[], el: string): number {
180
303
  let m = 0;
181
304
  let n = ar.length - 1;
182
305
  while (m <= n) {
183
- // tslint:disable-next-line:no-bitwise
184
- const k = (n + m) >> 1;
185
- const cmp = compare(el, ar[k].id);
186
- if (cmp > 0) {
187
- m = k + 1;
188
- } else if (cmp < 0) {
189
- n = k - 1;
190
- } else {
191
- return k;
192
- }
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
+ }
193
316
  }
194
317
  return -m - 1;
195
318
  }
@@ -199,7 +322,7 @@ function compare(s1: string, s2: string): number {
199
322
  interface ErrorMessage {
200
323
  field: string;
201
324
  code: string;
202
- param?: string|number|Date;
325
+ param?: string | number | Date;
203
326
  message?: string;
204
327
  }
205
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,57 @@ export interface RateFilter extends Filter {
30
31
  usefulCount?: number;
31
32
  replyCount?: number;
32
33
  }
33
-
34
- export interface RateRepository {
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: Rate, newInfo?: boolean): Promise<number>;
37
- update(rate: Rate, oldRate: number): Promise<number>;
38
- getRate(id: string, author: string): Promise<Rate | null>;
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>;
39
72
  }
40
- export interface Rater {
41
- search(s: RateFilter, limit?: number, offset?: number | string, fields?: string[], ctx?: any): Promise<SearchResult<Rate>>;
42
- getRate(id: string, author: string): Promise<Rate | null>;
43
- rate(rate: Rate): Promise<number>;
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>;
82
+ getComments(id: string, author: string, limit?: number): Promise<Comment[]>;
83
+ getComment(id: string): Promise<Comment | null>;
49
84
  }
50
-
51
85
  export interface RateReactionRepository {
52
86
  remove(id: string, author: string, userId: string, ctx?: any): Promise<number>;
53
87
  save(id: string, author: string, userId: string, type: number): Promise<number>;
@@ -59,9 +93,9 @@ export interface RateCommentRepository extends Repository<Comment, string> {
59
93
  }
60
94
 
61
95
  export interface Query<T, ID, S> {
62
- search: (s: S, limit?: number, skip?: number|string, fields?: string[]) => Promise<SearchResult<T>>;
63
- metadata?(): Attributes|undefined;
64
- 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>;
65
99
  }
66
100
  export interface RateCommentQuery extends Query<Comment, string, CommentFilter> {
67
101
  getComments(id: string, author: string, limit?: number): Promise<Comment[]>;
@@ -246,45 +280,39 @@ export interface CommentFilter extends Filter {
246
280
  time?: Date;
247
281
  updatedAt?: Date;
248
282
  }
249
- export const commentModel: Attributes = {
250
- comment: {
251
- length: 500
283
+
284
+ export const rateInfoModel: Attributes = {
285
+ id: {
286
+ key: true
252
287
  },
253
- time: {
254
- type: 'datetime'
288
+ rate: {
289
+ type: 'number',
290
+ },
291
+ count: {
292
+ type: 'integer',
293
+ },
294
+ score: {
295
+ type: 'number',
255
296
  }
256
297
  };
257
- export const rateCommentModel: Attributes = {
258
- commentId: {
259
- key: true
260
- },
298
+
299
+ export const ratesModel: Attributes = {
261
300
  id: {
262
- required: true,
263
- noupdate: true,
301
+ key: true,
264
302
  match: 'equal'
265
303
  },
266
304
  author: {
267
- required: true,
268
- noupdate: true,
305
+ key: true,
269
306
  match: 'equal'
270
307
  },
271
- userId: {
272
- required: true,
273
- noupdate: true,
274
- match: 'equal'
308
+ rate: {
309
+ type: 'number'
275
310
  },
276
- comment: {
277
- length: 500
311
+ rates: {
312
+ type: 'integers'
278
313
  },
279
314
  time: {
280
- type: 'datetime',
281
- noupdate: true,
282
- },
283
- updatedAt: {
284
315
  type: 'datetime'
285
316
  },
286
- histories: {
287
- type: 'array',
288
- typeof: commentModel
289
- }
317
+ review: {},
290
318
  };