rate-core 0.0.0 → 0.0.3

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,17 +1,4 @@
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
- })();
15
2
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
16
3
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
17
4
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -52,90 +39,106 @@ function __export(m) {
52
39
  for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
53
40
  }
54
41
  Object.defineProperty(exports, "__esModule", { value: true });
55
- var core_1 = require("./core");
56
42
  __export(require("./rate"));
57
- var RateManager = (function (_super) {
58
- __extends(RateManager, _super);
59
- function RateManager(search, repository, infoRepository, rateCommentRepository, rateReactionRepository) {
60
- var _this = _super.call(this, search, repository) || this;
61
- _this.repository = repository;
62
- _this.infoRepository = infoRepository;
63
- _this.rateCommentRepository = rateCommentRepository;
64
- _this.rateReactionRepository = rateReactionRepository;
65
- _this.rate = _this.rate.bind(_this);
66
- _this.update = _this.update.bind(_this);
67
- _this.save = _this.save.bind(_this);
68
- _this.comment = _this.comment.bind(_this);
69
- _this.load = _this.load.bind(_this);
70
- _this.removeComment = _this.removeComment.bind(_this);
71
- _this.updateComment = _this.updateComment.bind(_this);
72
- _this.updateRate = _this.updateRate.bind(_this);
73
- return _this;
43
+ var RateService = (function () {
44
+ function RateService(find, repository, infoRepository, rateCommentRepository, rateReactionRepository, queryURL) {
45
+ this.find = find;
46
+ this.repository = repository;
47
+ this.infoRepository = infoRepository;
48
+ this.rateCommentRepository = rateCommentRepository;
49
+ this.rateReactionRepository = rateReactionRepository;
50
+ this.queryURL = queryURL;
51
+ this.rate = this.rate.bind(this);
52
+ this.comment = this.comment.bind(this);
53
+ this.removeComment = this.removeComment.bind(this);
54
+ this.updateComment = this.updateComment.bind(this);
55
+ this.search = this.search.bind(this);
74
56
  }
75
- RateManager.prototype.rate = function (rate) {
76
- var _a;
57
+ RateService.prototype.rate = function (rate) {
77
58
  return __awaiter(this, void 0, void 0, function () {
78
- var info, exist, r, sumRate, count;
79
- return __generator(this, function (_b) {
80
- switch (_b.label) {
81
- case 0: return [4, this.infoRepository.load(rate.id)];
59
+ var info, r0, exist, r1, sr, history, res;
60
+ return __generator(this, function (_a) {
61
+ switch (_a.label) {
62
+ case 0:
63
+ rate.time = new Date();
64
+ return [4, this.infoRepository.load(rate.id)];
82
65
  case 1:
83
- info = _b.sent();
84
- if (!info) {
85
- info = {
86
- 'id': rate.id,
87
- 'rate': 0,
88
- 'rate1': 0,
89
- 'rate2': 0,
90
- 'rate3': 0,
91
- 'rate4': 0,
92
- 'rate5': 0,
93
- 'viewCount': 0,
94
- };
95
- }
96
- return [4, this.repository.getRate(rate.id, rate.author)];
66
+ info = _a.sent();
67
+ if (!!info) return [3, 3];
68
+ return [4, this.repository.insert(rate, true)];
97
69
  case 2:
98
- exist = _b.sent();
99
- r = (exist ? exist.rate : 0);
100
- info['rate' + ((_a = rate.rate) === null || _a === void 0 ? void 0 : _a.toString())] += 1;
101
- sumRate = info.rate1 +
102
- info.rate2 * 2 +
103
- info.rate3 * 3 +
104
- info.rate4 * 4 +
105
- info.rate5 * 5 - r;
106
- count = info.rate1 +
107
- info.rate2 +
108
- info.rate3 +
109
- info.rate4 +
110
- info.rate5 + (exist ? 0 : 1);
111
- info.rate = sumRate / count;
112
- info.viewCount = count;
113
- rate.usefulCount = 0;
114
- return [4, this.infoRepository.save(info)];
115
- case 3:
116
- _b.sent();
117
- return [4, this.repository.save(rate)];
70
+ r0 = _a.sent();
71
+ return [2, r0];
72
+ case 3: return [4, this.repository.getRate(rate.id, rate.author)];
118
73
  case 4:
119
- _b.sent();
120
- return [2, true];
74
+ exist = _a.sent();
75
+ if (!!exist) return [3, 6];
76
+ return [4, this.repository.insert(rate)];
77
+ case 5:
78
+ r1 = _a.sent();
79
+ return [2, r1];
80
+ case 6:
81
+ sr = { review: exist.review, rate: exist.rate, time: exist.time };
82
+ if (exist.histories && exist.histories.length > 0) {
83
+ history = exist.histories;
84
+ history.push(sr);
85
+ rate.histories = history;
86
+ }
87
+ else {
88
+ rate.histories = [sr];
89
+ }
90
+ return [4, this.repository.update(rate, exist.rate)];
91
+ case 7:
92
+ res = _a.sent();
93
+ return [2, res];
121
94
  }
122
95
  });
123
96
  });
124
97
  };
125
- RateManager.prototype.getRate = function (id, author) {
98
+ RateService.prototype.search = function (s, limit, offset, fields) {
99
+ var _this = this;
100
+ return this.find(s, limit, offset, fields).then(function (res) {
101
+ if (!_this.queryURL) {
102
+ return res;
103
+ }
104
+ else {
105
+ if (res.list && res.list.length > 0) {
106
+ var ids = [];
107
+ for (var _i = 0, _a = res.list; _i < _a.length; _i++) {
108
+ var rate = _a[_i];
109
+ ids.push(rate.author);
110
+ }
111
+ return _this.queryURL(ids).then(function (urls) {
112
+ for (var _i = 0, _a = res.list; _i < _a.length; _i++) {
113
+ var rate = _a[_i];
114
+ var i = binarySearch(urls, rate.author);
115
+ if (i >= 0) {
116
+ rate.authorURL = urls[i].url;
117
+ }
118
+ }
119
+ return res;
120
+ });
121
+ }
122
+ else {
123
+ return res;
124
+ }
125
+ }
126
+ });
127
+ };
128
+ RateService.prototype.getRate = function (id, author) {
126
129
  return this.repository.getRate(id, author);
127
130
  };
128
- RateManager.prototype.setUseful = function (id, author, userId) {
131
+ RateService.prototype.setUseful = function (id, author, userId) {
129
132
  return this.rateReactionRepository.save(id, author, userId, 1);
130
133
  };
131
- RateManager.prototype.removeUseful = function (id, author, userId) {
134
+ RateService.prototype.removeUseful = function (id, author, userId) {
132
135
  return this.rateReactionRepository.remove(id, author, userId);
133
136
  };
134
- RateManager.prototype.comment = function (comment) {
137
+ RateService.prototype.comment = function (comment) {
135
138
  var _this = this;
136
139
  return this.repository.getRate(comment.id, comment.author).then(function (checkRate) {
137
140
  if (!checkRate) {
138
- return 0;
141
+ return -1;
139
142
  }
140
143
  else {
141
144
  comment.time ? comment.time = comment.time : comment.time = new Date();
@@ -143,7 +146,7 @@ var RateManager = (function (_super) {
143
146
  }
144
147
  });
145
148
  };
146
- RateManager.prototype.removeComment = function (commentId, userId) {
149
+ RateService.prototype.removeComment = function (commentId, userId) {
147
150
  var _this = this;
148
151
  return this.rateCommentRepository.load(commentId).then(function (comment) {
149
152
  if (comment) {
@@ -159,40 +162,153 @@ var RateManager = (function (_super) {
159
162
  }
160
163
  });
161
164
  };
162
- RateManager.prototype.updateComment = function (comment) {
165
+ RateService.prototype.updateComment = function (comment) {
163
166
  var _this = this;
164
167
  return this.rateCommentRepository.load(comment.commentId).then(function (exist) {
165
168
  if (!exist) {
166
- return 0;
169
+ return -1;
167
170
  }
168
171
  else {
169
- comment.updatedAt = new Date();
170
- return _this.rateCommentRepository.update(comment);
172
+ if (exist.userId !== comment.userId) {
173
+ return -2;
174
+ }
175
+ exist.updatedAt = new Date();
176
+ var c = { comment: exist.comment, time: exist.time };
177
+ if (exist.histories && exist.histories.length > 0) {
178
+ exist.histories.push(c);
179
+ }
180
+ else {
181
+ exist.histories = [c];
182
+ }
183
+ exist.comment = comment.comment;
184
+ var res = _this.rateCommentRepository.update(exist);
185
+ return res;
171
186
  }
172
187
  });
173
188
  };
174
- RateManager.prototype.updateRate = function (rate) {
189
+ return RateService;
190
+ }());
191
+ exports.RateService = RateService;
192
+ var CommentQuery = (function () {
193
+ function CommentQuery(find, repository, queryURL) {
194
+ this.find = find;
195
+ this.repository = repository;
196
+ this.queryURL = queryURL;
197
+ this.load = this.load.bind(this);
198
+ this.search = this.search.bind(this);
199
+ this.getComments = this.getComments.bind(this);
200
+ }
201
+ CommentQuery.prototype.load = function (id, ctx) {
202
+ return this.repository.load(id, ctx);
203
+ };
204
+ CommentQuery.prototype.getComments = function (id, author, limit) {
205
+ if (this.repository.getComments) {
206
+ return this.repository.getComments(id, author, limit);
207
+ }
208
+ else {
209
+ return Promise.resolve([]);
210
+ }
211
+ };
212
+ CommentQuery.prototype.search = function (s, limit, offset, fields) {
175
213
  var _this = this;
176
- return this.repository.getRate(rate.id, rate.author).then(function (exist) {
177
- if (exist) {
178
- rate.time ? rate.time = rate.time : rate.time = new Date();
179
- return _this.repository.update(rate);
214
+ return this.find(s, limit, offset, fields).then(function (res) {
215
+ if (!_this.queryURL) {
216
+ return res;
180
217
  }
181
218
  else {
182
- return 0;
219
+ if (res.list && res.list.length > 0) {
220
+ var ids = [];
221
+ for (var _i = 0, _a = res.list; _i < _a.length; _i++) {
222
+ var rate = _a[_i];
223
+ ids.push(rate.userId);
224
+ }
225
+ return _this.queryURL(ids).then(function (urls) {
226
+ for (var _i = 0, _a = res.list; _i < _a.length; _i++) {
227
+ var rate = _a[_i];
228
+ var i = binarySearch(urls, rate.userId);
229
+ if (i >= 0) {
230
+ rate.userURL = urls[i].url;
231
+ }
232
+ }
233
+ return res;
234
+ });
235
+ }
236
+ else {
237
+ return res;
238
+ }
183
239
  }
184
240
  });
185
241
  };
186
- return RateManager;
187
- }(core_1.Manager));
188
- exports.RateManager = RateManager;
189
- var RateCommentManager = (function (_super) {
190
- __extends(RateCommentManager, _super);
191
- function RateCommentManager(search, replyRepository) {
192
- var _this = _super.call(this, search, replyRepository) || this;
193
- _this.replyRepository = replyRepository;
194
- return _this;
242
+ return CommentQuery;
243
+ }());
244
+ exports.CommentQuery = CommentQuery;
245
+ function binarySearch(ar, el) {
246
+ var m = 0;
247
+ var n = ar.length - 1;
248
+ while (m <= n) {
249
+ var k = (n + m) >> 1;
250
+ var cmp = compare(el, ar[k].id);
251
+ if (cmp > 0) {
252
+ m = k + 1;
253
+ }
254
+ else if (cmp < 0) {
255
+ n = k - 1;
256
+ }
257
+ else {
258
+ return k;
259
+ }
260
+ }
261
+ return -m - 1;
262
+ }
263
+ function compare(s1, s2) {
264
+ return s1.localeCompare(s2);
265
+ }
266
+ var CommentValidator = (function () {
267
+ function CommentValidator(attributes, check) {
268
+ this.attributes = attributes;
269
+ this.check = check;
270
+ this.validate = this.validate.bind(this);
271
+ }
272
+ CommentValidator.prototype.validate = function (comment) {
273
+ var errs = this.check(comment, this.attributes);
274
+ return Promise.resolve(errs);
275
+ };
276
+ return CommentValidator;
277
+ }());
278
+ exports.CommentValidator = CommentValidator;
279
+ var RateValidator = (function () {
280
+ function RateValidator(attributes, check, max) {
281
+ this.attributes = attributes;
282
+ this.check = check;
283
+ this.max = max;
284
+ this.validate = this.validate.bind(this);
285
+ }
286
+ RateValidator.prototype.validate = function (rate) {
287
+ var errs = this.check(rate, this.attributes);
288
+ if (rate.rate > this.max) {
289
+ var err = createError('rate', 'max', this.max);
290
+ if (errs) {
291
+ errs.push(err);
292
+ return Promise.resolve(errs);
293
+ }
294
+ else {
295
+ return Promise.resolve([err]);
296
+ }
297
+ }
298
+ else {
299
+ return Promise.resolve(errs);
300
+ }
301
+ };
302
+ return RateValidator;
303
+ }());
304
+ exports.RateValidator = RateValidator;
305
+ function createError(field, code, param) {
306
+ if (!code) {
307
+ code = 'string';
195
308
  }
196
- return RateCommentManager;
197
- }(core_1.Manager));
198
- exports.RateCommentManager = RateCommentManager;
309
+ var error = { field: field, code: code };
310
+ if (param) {
311
+ error.param = param;
312
+ }
313
+ return error;
314
+ }
package/lib/rate.js CHANGED
@@ -1,5 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.rateHistoryModel = {
4
+ rate: {
5
+ type: 'integer'
6
+ },
7
+ time: {
8
+ type: 'datetime',
9
+ },
10
+ review: {},
11
+ };
3
12
  exports.rateModel = {
4
13
  id: {
5
14
  key: true,
@@ -14,7 +23,6 @@ exports.rateModel = {
14
23
  rate: {
15
24
  type: 'integer',
16
25
  min: 1,
17
- max: 5
18
26
  },
19
27
  time: {
20
28
  type: 'datetime',
@@ -29,15 +37,45 @@ exports.rateModel = {
29
37
  replyCount: {
30
38
  type: 'integer',
31
39
  min: 0
40
+ },
41
+ histories: {
42
+ type: 'array',
43
+ typeof: exports.rateHistoryModel
32
44
  }
33
45
  };
34
46
  exports.infoModel = {
35
47
  id: {
36
48
  key: true,
37
49
  },
38
- viewCount: {
50
+ rate: {
39
51
  type: 'number'
40
52
  },
53
+ rate1: {
54
+ type: 'number',
55
+ },
56
+ rate2: {
57
+ type: 'number',
58
+ },
59
+ rate3: {
60
+ type: 'number',
61
+ },
62
+ rate4: {
63
+ type: 'number',
64
+ },
65
+ rate5: {
66
+ type: 'number',
67
+ },
68
+ count: {
69
+ type: 'number',
70
+ },
71
+ score: {
72
+ type: 'number',
73
+ }
74
+ };
75
+ exports.info10Model = {
76
+ id: {
77
+ key: true,
78
+ },
41
79
  rate: {
42
80
  type: 'number'
43
81
  },
@@ -56,6 +94,35 @@ exports.infoModel = {
56
94
  rate5: {
57
95
  type: 'number',
58
96
  },
97
+ rate6: {
98
+ type: 'number',
99
+ },
100
+ rate7: {
101
+ type: 'number',
102
+ },
103
+ rate8: {
104
+ type: 'number',
105
+ },
106
+ rate9: {
107
+ type: 'number',
108
+ },
109
+ rate10: {
110
+ type: 'number',
111
+ },
112
+ count: {
113
+ type: 'number',
114
+ },
115
+ score: {
116
+ type: 'number',
117
+ }
118
+ };
119
+ exports.commentModel = {
120
+ comment: {
121
+ length: 500
122
+ },
123
+ time: {
124
+ type: 'datetime'
125
+ }
59
126
  };
60
127
  exports.rateCommentModel = {
61
128
  commentId: {
@@ -63,20 +130,31 @@ exports.rateCommentModel = {
63
130
  },
64
131
  id: {
65
132
  required: true,
133
+ noupdate: true,
66
134
  match: 'equal'
67
135
  },
68
136
  author: {
69
137
  required: true,
138
+ noupdate: true,
70
139
  match: 'equal'
71
140
  },
72
141
  userId: {
73
142
  required: true,
143
+ noupdate: true,
74
144
  match: 'equal'
75
145
  },
76
146
  comment: {
77
147
  length: 500
78
148
  },
79
149
  time: {
150
+ type: 'datetime',
151
+ noupdate: true,
152
+ },
153
+ updatedAt: {
80
154
  type: 'datetime'
155
+ },
156
+ histories: {
157
+ type: 'array',
158
+ typeof: exports.commentModel
81
159
  }
82
160
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rate-core",
3
- "version": "0.0.0",
3
+ "version": "0.0.3",
4
4
  "description": "rate",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./src/index.ts",
package/src/core.ts CHANGED
@@ -131,65 +131,5 @@ export interface GenericSearchService<T, ID, R, F extends Filter>
131
131
  }
132
132
  export interface Service<T, ID, F extends Filter> extends GenericSearchService<T, ID, Result<T>, F> {
133
133
 
134
- }
135
- export class ViewManager<T, ID> implements ViewService<T, ID> {
136
- constructor(private r: ViewRepository<T, ID>) {
137
- this.metadata = this.metadata.bind(this);
138
- this.keys = this.keys.bind(this);
139
- this.all = this.all.bind(this);
140
- this.load = this.load.bind(this);
141
- this.exist = this.exist.bind(this);
142
- }
143
- metadata(): Attributes|undefined {
144
- return (this.r.metadata ? this.r.metadata() : undefined);
145
- }
146
- keys(): string[] {
147
- return (this.r.keys ? this.r.keys() : []);
148
- }
149
- all(ctx?: any): Promise<T[]> {
150
- return (this.r.all ? this.r.all() : Promise.resolve([]));
151
- }
152
- load(id: ID, ctx?: any): Promise<T | null> {
153
- return this.r.load(id, ctx);
154
- }
155
- exist(id: ID, ctx?: any): Promise<boolean> {
156
- return (this.r.exist ? this.r.exist(id, ctx) : Promise.resolve(false));
157
- }
158
- }
159
- // tslint:disable-next-line:max-classes-per-file
160
- export class GenericManager<T, ID> extends ViewManager<T, ID> implements GenericService<T, ID, number> {
161
- constructor(protected repository: Repository<T, ID>) {
162
- super(repository);
163
- this.insert = this.insert.bind(this);
164
- this.update = this.update.bind(this);
165
- this.patch = this.patch.bind(this);
166
- this.save = this.save.bind(this);
167
- this.delete = this.delete.bind(this);
168
- }
169
- insert(obj: T, ctx?: any): Promise<number> {
170
- return this.repository.insert(obj, ctx);
171
- }
172
- update(obj: T, ctx?: any): Promise<number> {
173
- return this.repository.update(obj, ctx);
174
- }
175
- patch(obj: T, ctx?: any): Promise<number> {
176
- return (this.repository.patch ? this.repository.patch(obj, ctx) : Promise.resolve(-1));
177
- }
178
- save(obj: T, ctx?: any): Promise<number> {
179
- return (this.repository.save ? this.repository.save(obj, ctx) : Promise.resolve(-1));
180
- }
181
- delete(id: ID, ctx?: any): Promise<number> {
182
- return (this.repository.delete ? this.repository.delete(id, ctx) : Promise.resolve(-1));
183
- }
184
134
  }
185
135
  export type Search<T, F> = (s: F, limit?: number, offset?: number | string, fields?: string[]) => Promise<SearchResult<T>>;
186
- // tslint:disable-next-line:max-classes-per-file
187
- export class Manager<T, ID, F extends Filter> extends GenericManager<T, ID> implements GenericSearchService<T, ID, number, F> {
188
- constructor(public find: Search<T, F>, repo: Repository<T, ID>) {
189
- super(repo);
190
- this.search = this.search.bind(this);
191
- }
192
- search(s: F, limit?: number, offset?: number|string, fields?: string[]): Promise<SearchResult<T>> {
193
- return this.find(s, limit, offset, fields);
194
- }
195
- }
package/src/index.ts CHANGED
@@ -1,66 +1,79 @@
1
- import { Manager, Search } from './core';
1
+ import { Attributes, Search, SearchResult } from './core';
2
2
  import {
3
- InfoRepository, Rate, RateComment, RateCommentFilter, RateCommentRepository, RateCommentService, RateFilter, RateId,
4
- RateReactionRepository, RateRepository, RateService
3
+ InfoRepository, Rate, RateComment, RateCommentFilter, RateCommentRepository, RateCommentQuery, RateFilter, RateReactionRepository,
4
+ RateRepository, Rater, ShortComment, ShortRate
5
5
  } from './rate';
6
+
6
7
  export * from './rate';
7
8
 
8
- export class RateManager extends Manager<Rate, RateId, RateFilter> implements RateService {
9
- constructor(search: Search<Rate, RateFilter>,
9
+ export interface URL {
10
+ id: string;
11
+ url: string;
12
+ }
13
+ export class RateService<O> implements Rater {
14
+ constructor(protected find: Search<Rate, RateFilter>,
10
15
  public repository: RateRepository,
11
- private infoRepository: InfoRepository,
16
+ private infoRepository: InfoRepository<O>,
12
17
  private rateCommentRepository: RateCommentRepository,
13
- private rateReactionRepository: RateReactionRepository) {
14
- super(search, repository);
18
+ private rateReactionRepository: RateReactionRepository,
19
+ private queryURL?: (ids: string[]) => Promise<URL[]>) {
15
20
  this.rate = this.rate.bind(this);
16
- this.update = this.update.bind(this);
17
- this.save = this.save.bind(this);
18
21
  this.comment = this.comment.bind(this);
19
- this.load = this.load.bind(this);
20
22
  this.removeComment = this.removeComment.bind(this);
21
23
  this.updateComment = this.updateComment.bind(this);
22
- this.updateRate = this.updateRate.bind(this);
24
+ this.search = this.search.bind(this);
23
25
  }
24
- async rate(rate: Rate): Promise<boolean> {
25
- let info = await this.infoRepository.load(rate.id);
26
+ async rate(rate: Rate): Promise<number> {
27
+ rate.time = new Date();
28
+ const info = await this.infoRepository.load(rate.id);
26
29
  if (!info) {
27
- info = {
28
- 'id': rate.id,
29
- 'rate': 0,
30
- 'rate1': 0,
31
- 'rate2': 0,
32
- 'rate3': 0,
33
- 'rate4': 0,
34
- 'rate5': 0,
35
- 'viewCount': 0,
36
- };
30
+ const r0 = await this.repository.insert(rate, true);
31
+ return r0;
37
32
  }
38
33
  const exist = await this.repository.getRate(rate.id, rate.author);
39
- const r = (exist ? exist.rate : 0);
40
- (info as any)['rate' + rate.rate?.toString()] += 1;
41
- const sumRate = info.rate1 +
42
- info.rate2 * 2 +
43
- info.rate3 * 3 +
44
- info.rate4 * 4 +
45
- info.rate5 * 5 - r;
46
-
47
- const count = info.rate1 +
48
- info.rate2 +
49
- info.rate3 +
50
- info.rate4 +
51
- info.rate5 + (exist ? 0 : 1);
52
-
53
- info.rate = sumRate / count;
54
- info.viewCount = count;
55
- rate.usefulCount = 0;
56
- await this.infoRepository.save(info);
57
- await this.repository.save(rate);
58
- return true;
34
+ if (!exist) {
35
+ const r1 = await this.repository.insert(rate);
36
+ return r1;
37
+ }
38
+ const sr: ShortRate = { review: exist.review, rate: exist.rate, time: exist.time };
39
+ if (exist.histories && exist.histories.length > 0) {
40
+ const history = exist.histories;
41
+ history.push(sr);
42
+ rate.histories = history;
43
+ } else {
44
+ rate.histories = [sr];
45
+ }
46
+ const res = await this.repository.update(rate, exist.rate);
47
+ return res;
48
+ }
49
+ search(s: RateFilter, limit?: number, offset?: number | string, fields?: string[]): Promise<SearchResult<Rate>> {
50
+ return this.find(s, limit, offset, fields).then(res => {
51
+ if (!this.queryURL) {
52
+ return res;
53
+ } else {
54
+ if (res.list && res.list.length > 0) {
55
+ const ids: string[] = [];
56
+ for (const rate of res.list) {
57
+ ids.push(rate.author);
58
+ }
59
+ return this.queryURL(ids).then(urls => {
60
+ for (const rate of res.list) {
61
+ const i = binarySearch(urls, rate.author);
62
+ if (i >= 0) {
63
+ rate.authorURL = urls[i].url;
64
+ }
65
+ }
66
+ return res;
67
+ });
68
+ } else {
69
+ return res;
70
+ }
71
+ }
72
+ });
59
73
  }
60
74
  getRate(id: string, author: string): Promise<Rate | null> {
61
75
  return this.repository.getRate(id, author);
62
76
  }
63
-
64
77
  setUseful(id: string, author: string, userId: string): Promise<number> {
65
78
  return this.rateReactionRepository.save(id, author, userId, 1);
66
79
  }
@@ -70,7 +83,7 @@ export class RateManager extends Manager<Rate, RateId, RateFilter> implements Ra
70
83
  comment(comment: RateComment): Promise<number> {
71
84
  return this.repository.getRate(comment.id, comment.author).then(checkRate => {
72
85
  if (!checkRate) {
73
- return 0;
86
+ return -1;
74
87
  } else {
75
88
  comment.time ? comment.time = comment.time : comment.time = new Date();
76
89
  return this.rateCommentRepository.insert(comment);
@@ -93,28 +106,135 @@ export class RateManager extends Manager<Rate, RateId, RateFilter> implements Ra
93
106
  updateComment(comment: RateComment): Promise<number> {
94
107
  return this.rateCommentRepository.load(comment.commentId).then(exist => {
95
108
  if (!exist) {
96
- return 0;
109
+ return -1;
97
110
  } else {
98
- comment.updatedAt = new Date();
99
- return this.rateCommentRepository.update(comment);
111
+ if (exist.userId !== comment.userId) {
112
+ return -2;
113
+ }
114
+ exist.updatedAt = new Date();
115
+ const c: ShortComment = { comment: exist.comment, time: exist.time };
116
+ if (exist.histories && exist.histories.length > 0) {
117
+ exist.histories.push(c);
118
+ } else {
119
+ exist.histories = [c];
120
+ }
121
+ exist.comment = comment.comment;
122
+ const res = this.rateCommentRepository.update(exist);
123
+ return res;
100
124
  }
101
125
  });
102
126
  }
103
- updateRate(rate: Rate): Promise<number> {
104
- return this.repository.getRate(rate.id, rate.author).then(exist => {
105
- if (exist) {
106
- rate.time ? rate.time = rate.time : rate.time = new Date();
107
- return this.repository.update(rate);
127
+ }
128
+ export interface CommentRepository {
129
+ load(commentId: string, ctx?: any): Promise<RateComment|null>;
130
+ getComments?(id: string, author: string, limit?: number): Promise<RateComment[]>;
131
+ }
132
+ // tslint:disable-next-line:max-classes-per-file
133
+ export class CommentQuery implements RateCommentQuery {
134
+ constructor(protected find: Search<RateComment, RateCommentFilter>, protected repository: CommentRepository, private queryURL?: (ids: string[]) => Promise<URL[]>) {
135
+ this.load = this.load.bind(this);
136
+ this.search = this.search.bind(this);
137
+ this.getComments = this.getComments.bind(this)
138
+ }
139
+ load(id: string, ctx?: any): Promise<RateComment|null> {
140
+ return this.repository.load(id, ctx);
141
+ }
142
+ getComments(id: string, author: string, limit?: number): Promise<RateComment[]> {
143
+ if (this.repository.getComments) {
144
+ return this.repository.getComments(id, author, limit);
145
+ } else {
146
+ return Promise.resolve([]);
147
+ }
148
+ }
149
+ search(s: RateCommentFilter, limit?: number, offset?: number | string, fields?: string[]): Promise<SearchResult<RateComment>> {
150
+ return this.find(s, limit, offset, fields).then(res => {
151
+ if (!this.queryURL) {
152
+ return res;
108
153
  } else {
109
- return 0;
154
+ if (res.list && res.list.length > 0) {
155
+ const ids: string[] = [];
156
+ for (const rate of res.list) {
157
+ ids.push(rate.userId);
158
+ }
159
+ return this.queryURL(ids).then(urls => {
160
+ for (const rate of res.list) {
161
+ const i = binarySearch(urls, rate.userId);
162
+ if (i >= 0) {
163
+ rate.userURL = urls[i].url;
164
+ }
165
+ }
166
+ return res;
167
+ });
168
+ } else {
169
+ return res;
170
+ }
110
171
  }
111
172
  });
112
173
  }
113
174
  }
175
+ function binarySearch(ar: URL[], el: string): number {
176
+ let m = 0;
177
+ let n = ar.length - 1;
178
+ while (m <= n) {
179
+ // tslint:disable-next-line:no-bitwise
180
+ const k = (n + m) >> 1;
181
+ const cmp = compare(el, ar[k].id);
182
+ if (cmp > 0) {
183
+ m = k + 1;
184
+ } else if (cmp < 0) {
185
+ n = k - 1;
186
+ } else {
187
+ return k;
188
+ }
189
+ }
190
+ return -m - 1;
191
+ }
192
+ function compare(s1: string, s2: string): number {
193
+ return s1.localeCompare(s2);
194
+ }
195
+ interface ErrorMessage {
196
+ field: string;
197
+ code: string;
198
+ param?: string|number|Date;
199
+ message?: string;
200
+ }
114
201
  // tslint:disable-next-line:max-classes-per-file
115
- export class RateCommentManager extends Manager<RateComment, string, RateCommentFilter> implements RateCommentService {
116
- constructor(search: Search<RateComment, RateCommentFilter>,
117
- protected replyRepository: RateCommentRepository) {
118
- super(search, replyRepository);
202
+ export class CommentValidator {
203
+ constructor(protected attributes: Attributes, protected check: (obj: any, attributes: Attributes) => ErrorMessage[]) {
204
+ this.validate = this.validate.bind(this);
205
+ }
206
+ validate(comment: RateComment): Promise<ErrorMessage[]> {
207
+ const errs = this.check(comment, this.attributes);
208
+ return Promise.resolve(errs);
209
+ }
210
+ }
211
+ // tslint:disable-next-line:max-classes-per-file
212
+ export class RateValidator {
213
+ constructor(protected attributes: Attributes, protected check: (obj: any, attributes: Attributes) => ErrorMessage[], protected max: number) {
214
+ this.validate = this.validate.bind(this);
215
+ }
216
+ validate(rate: Rate): Promise<ErrorMessage[]> {
217
+ const errs = this.check(rate, this.attributes);
218
+ if (rate.rate > this.max) {
219
+ const err = createError('rate', 'max', this.max);
220
+ if (errs) {
221
+ errs.push(err);
222
+ return Promise.resolve(errs);
223
+ } else {
224
+ return Promise.resolve([err]);
225
+ }
226
+ } else {
227
+ return Promise.resolve(errs);
228
+ }
229
+ }
230
+ }
231
+ function createError(field: string, code?: string, param?: string | number | Date): ErrorMessage {
232
+ if (!code) {
233
+ code = 'string';
234
+ }
235
+ const error: ErrorMessage = { field, code };
236
+ if (param) {
237
+ error.param = param;
119
238
  }
239
+ return error;
120
240
  }
package/src/rate.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Attributes, Filter, Repository, Service, ViewRepository } from './core';
1
+ import { Attributes, Filter, Repository, SearchResult, ViewRepository } from './core';
2
2
 
3
3
  export interface RateId {
4
4
  id: string;
@@ -8,13 +8,19 @@ export interface RateId {
8
8
  export interface Rate {
9
9
  id: string;
10
10
  author: string;
11
+ authorURL?: string;
11
12
  rate: number;
12
13
  time: Date;
13
14
  review: string;
14
15
  usefulCount: number;
15
16
  replyCount: number;
17
+ histories?: ShortRate[];
18
+ }
19
+ export interface ShortRate {
20
+ rate: number;
21
+ time: Date;
22
+ review: string;
16
23
  }
17
-
18
24
  export interface RateFilter extends Filter {
19
25
  id?: string;
20
26
  author?: string;
@@ -25,15 +31,16 @@ export interface RateFilter extends Filter {
25
31
  replyCount?: number;
26
32
  }
27
33
 
28
- export interface RateRepository extends Repository<Rate, RateId> {
29
- save(obj: Rate, ctx?: any): Promise<number>;
34
+ export interface RateRepository {
35
+ // 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>;
30
38
  getRate(id: string, author: string): Promise<Rate | null>;
31
39
  }
32
-
33
- export interface RateService extends Service<Rate, RateId, RateFilter> {
40
+ export interface Rater {
41
+ search(s: RateFilter, limit?: number, offset?: number | string, fields?: string[], ctx?: any): Promise<SearchResult<Rate>>;
34
42
  getRate(id: string, author: string): Promise<Rate | null>;
35
- updateRate(rate: Rate): Promise<number>;
36
- rate(rate: Rate): Promise<boolean>;
43
+ rate(rate: Rate): Promise<number>;
37
44
  setUseful(id: string, author: string, userId: string, ctx?: any): Promise<number>;
38
45
  removeUseful(id: string, author: string, userId: string, ctx?: any): Promise<number>;
39
46
  comment(comment: RateComment): Promise<number>;
@@ -50,9 +57,24 @@ export interface RateCommentRepository extends Repository<RateComment, string> {
50
57
  remove(commentId: string, id: string, author: string): Promise<number>;
51
58
  }
52
59
 
53
- export interface RateCommentService extends Service<RateComment, string, RateCommentFilter> {
60
+ export interface Query<T, ID, S> {
61
+ search: (s: S, limit?: number, skip?: number|string, fields?: string[]) => Promise<SearchResult<T>>;
62
+ metadata?(): Attributes|undefined;
63
+ load(id: ID, ctx?: any): Promise<T|null>;
54
64
  }
55
-
65
+ export interface RateCommentQuery extends Query<RateComment, string, RateCommentFilter> {
66
+ getComments(id: string, author: string, limit?: number): Promise<RateComment[]>;
67
+ }
68
+ export const rateHistoryModel: Attributes = {
69
+ rate: {
70
+ type: 'integer'
71
+ },
72
+ time: {
73
+ type: 'datetime',
74
+ },
75
+ review: {
76
+ },
77
+ };
56
78
  export const rateModel: Attributes = {
57
79
  id: {
58
80
  key: true,
@@ -67,7 +89,6 @@ export const rateModel: Attributes = {
67
89
  rate: {
68
90
  type: 'integer',
69
91
  min: 1,
70
- max: 5
71
92
  },
72
93
  time: {
73
94
  type: 'datetime',
@@ -82,6 +103,10 @@ export const rateModel: Attributes = {
82
103
  replyCount: {
83
104
  type: 'integer',
84
105
  min: 0
106
+ },
107
+ histories: {
108
+ type: 'array',
109
+ typeof: rateHistoryModel
85
110
  }
86
111
  };
87
112
 
@@ -89,9 +114,35 @@ export const infoModel: Attributes = {
89
114
  id: {
90
115
  key: true,
91
116
  },
92
- viewCount: {
117
+ rate: {
93
118
  type: 'number'
94
119
  },
120
+ rate1: {
121
+ type: 'number',
122
+ },
123
+ rate2: {
124
+ type: 'number',
125
+ },
126
+ rate3: {
127
+ type: 'number',
128
+ },
129
+ rate4: {
130
+ type: 'number',
131
+ },
132
+ rate5: {
133
+ type: 'number',
134
+ },
135
+ count: {
136
+ type: 'number',
137
+ },
138
+ score: {
139
+ type: 'number',
140
+ }
141
+ };
142
+ export const info10Model: Attributes = {
143
+ id: {
144
+ key: true,
145
+ },
95
146
  rate: {
96
147
  type: 'number'
97
148
  },
@@ -110,8 +161,28 @@ export const infoModel: Attributes = {
110
161
  rate5: {
111
162
  type: 'number',
112
163
  },
164
+ rate6: {
165
+ type: 'number',
166
+ },
167
+ rate7: {
168
+ type: 'number',
169
+ },
170
+ rate8: {
171
+ type: 'number',
172
+ },
173
+ rate9: {
174
+ type: 'number',
175
+ },
176
+ rate10: {
177
+ type: 'number',
178
+ },
179
+ count: {
180
+ type: 'number',
181
+ },
182
+ score: {
183
+ type: 'number',
184
+ }
113
185
  };
114
-
115
186
  export interface Info {
116
187
  id: string;
117
188
  rate: number;
@@ -120,11 +191,26 @@ export interface Info {
120
191
  rate3: number;
121
192
  rate4: number;
122
193
  rate5: number;
123
- viewCount: number;
194
+ count: number;
195
+ score: number;
124
196
  }
125
-
126
- export interface InfoRepository extends ViewRepository<Info, string> {
127
- save(obj: Info, ctx?: any): Promise<number>;
197
+ export interface Info10 {
198
+ id: string;
199
+ rate: number;
200
+ rate1: number;
201
+ rate2: number;
202
+ rate3: number;
203
+ rate4: number;
204
+ rate5: number;
205
+ rate6: number;
206
+ rate7: number;
207
+ rate8: number;
208
+ rate9: number;
209
+ rate10: number;
210
+ count: number;
211
+ score: number;
212
+ }
213
+ export interface InfoRepository<T> extends ViewRepository<T, string> {
128
214
  }
129
215
 
130
216
  export interface RateCommentId {
@@ -141,7 +227,9 @@ export interface RateComment {
141
227
  comment: string;
142
228
  time: Date;
143
229
  updatedAt?: Date;
144
- history?: ShortComment;
230
+ histories?: ShortComment[];
231
+ userURL?: string;
232
+ authorURL?: string;
145
233
  }
146
234
  export interface ShortComment {
147
235
  comment: string;
@@ -155,27 +243,47 @@ export interface RateCommentFilter extends Filter {
155
243
  userId?: string;
156
244
  comment?: string;
157
245
  time?: Date;
246
+ updatedAt?: Date;
158
247
  }
248
+ export const commentModel: Attributes = {
249
+ comment: {
250
+ length: 500
251
+ },
252
+ time: {
253
+ type: 'datetime'
254
+ }
255
+ };
159
256
  export const rateCommentModel: Attributes = {
160
257
  commentId: {
161
258
  key: true
162
259
  },
163
260
  id: {
164
261
  required: true,
262
+ noupdate: true,
165
263
  match: 'equal'
166
264
  },
167
265
  author: {
168
266
  required: true,
267
+ noupdate: true,
169
268
  match: 'equal'
170
269
  },
171
270
  userId: {
172
271
  required: true,
272
+ noupdate: true,
173
273
  match: 'equal'
174
274
  },
175
275
  comment: {
176
276
  length: 500
177
277
  },
178
278
  time: {
279
+ type: 'datetime',
280
+ noupdate: true,
281
+ },
282
+ updatedAt: {
179
283
  type: 'datetime'
284
+ },
285
+ histories: {
286
+ type: 'array',
287
+ typeof: commentModel
180
288
  }
181
289
  };
package/lib/core.js DELETED
@@ -1,86 +0,0 @@
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
- })();
15
- Object.defineProperty(exports, "__esModule", { value: true });
16
- var ViewManager = (function () {
17
- function ViewManager(r) {
18
- this.r = r;
19
- this.metadata = this.metadata.bind(this);
20
- this.keys = this.keys.bind(this);
21
- this.all = this.all.bind(this);
22
- this.load = this.load.bind(this);
23
- this.exist = this.exist.bind(this);
24
- }
25
- ViewManager.prototype.metadata = function () {
26
- return (this.r.metadata ? this.r.metadata() : undefined);
27
- };
28
- ViewManager.prototype.keys = function () {
29
- return (this.r.keys ? this.r.keys() : []);
30
- };
31
- ViewManager.prototype.all = function (ctx) {
32
- return (this.r.all ? this.r.all() : Promise.resolve([]));
33
- };
34
- ViewManager.prototype.load = function (id, ctx) {
35
- return this.r.load(id, ctx);
36
- };
37
- ViewManager.prototype.exist = function (id, ctx) {
38
- return (this.r.exist ? this.r.exist(id, ctx) : Promise.resolve(false));
39
- };
40
- return ViewManager;
41
- }());
42
- exports.ViewManager = ViewManager;
43
- var GenericManager = (function (_super) {
44
- __extends(GenericManager, _super);
45
- function GenericManager(repository) {
46
- var _this = _super.call(this, repository) || this;
47
- _this.repository = repository;
48
- _this.insert = _this.insert.bind(_this);
49
- _this.update = _this.update.bind(_this);
50
- _this.patch = _this.patch.bind(_this);
51
- _this.save = _this.save.bind(_this);
52
- _this.delete = _this.delete.bind(_this);
53
- return _this;
54
- }
55
- GenericManager.prototype.insert = function (obj, ctx) {
56
- return this.repository.insert(obj, ctx);
57
- };
58
- GenericManager.prototype.update = function (obj, ctx) {
59
- return this.repository.update(obj, ctx);
60
- };
61
- GenericManager.prototype.patch = function (obj, ctx) {
62
- return (this.repository.patch ? this.repository.patch(obj, ctx) : Promise.resolve(-1));
63
- };
64
- GenericManager.prototype.save = function (obj, ctx) {
65
- return (this.repository.save ? this.repository.save(obj, ctx) : Promise.resolve(-1));
66
- };
67
- GenericManager.prototype.delete = function (id, ctx) {
68
- return (this.repository.delete ? this.repository.delete(id, ctx) : Promise.resolve(-1));
69
- };
70
- return GenericManager;
71
- }(ViewManager));
72
- exports.GenericManager = GenericManager;
73
- var Manager = (function (_super) {
74
- __extends(Manager, _super);
75
- function Manager(find, repo) {
76
- var _this = _super.call(this, repo) || this;
77
- _this.find = find;
78
- _this.search = _this.search.bind(_this);
79
- return _this;
80
- }
81
- Manager.prototype.search = function (s, limit, offset, fields) {
82
- return this.find(s, limit, offset, fields);
83
- };
84
- return Manager;
85
- }(GenericManager));
86
- exports.Manager = Manager;