rate-core 0.5.0 → 0.5.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/README.md CHANGED
@@ -1 +1 @@
1
- # rate
1
+ # rate-core
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) {
@@ -53,170 +40,11 @@ function __export(m) {
53
40
  }
54
41
  Object.defineProperty(exports, "__esModule", { value: true });
55
42
  __export(require("./rate"));
56
- var BaseRateService = (function () {
57
- function BaseRateService(find, repository, infoRepository, commentRepository, reactionRepository, queryURL) {
58
- this.find = find;
43
+ var RateService = (function () {
44
+ function RateService(repository, infoRepository) {
59
45
  this.repository = repository;
60
46
  this.infoRepository = infoRepository;
61
- this.commentRepository = commentRepository;
62
- this.reactionRepository = reactionRepository;
63
- this.queryURL = queryURL;
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);
69
- this.comment = this.comment.bind(this);
70
- this.removeComment = this.removeComment.bind(this);
71
- this.updateComment = this.updateComment.bind(this);
72
- this.getComments = this.getComments.bind(this);
73
- this.getComment = this.getComment.bind(this);
74
- }
75
- BaseRateService.prototype.search = function (s, limit, offset, fields) {
76
- var _this = this;
77
- return this.find(s, limit, offset, fields).then(function (res) {
78
- if (!_this.queryURL) {
79
- return res;
80
- }
81
- else {
82
- if (res.list && res.list.length > 0) {
83
- var ids = [];
84
- for (var _i = 0, _a = res.list; _i < _a.length; _i++) {
85
- var rate = _a[_i];
86
- ids.push(rate.author);
87
- }
88
- return _this.queryURL(ids).then(function (urls) {
89
- for (var _i = 0, _a = res.list; _i < _a.length; _i++) {
90
- var rate = _a[_i];
91
- var i = binarySearch(urls, rate.author);
92
- if (i >= 0) {
93
- rate.authorURL = urls[i].url;
94
- }
95
- }
96
- return res;
97
- });
98
- }
99
- else {
100
- return res;
101
- }
102
- }
103
- });
104
- };
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);
110
- };
111
- BaseRateService.prototype.setUseful = function (id, author, userId) {
112
- return this.reactionRepository.save(id, author, userId, 1);
113
- };
114
- BaseRateService.prototype.removeUseful = function (id, author, userId) {
115
- return this.reactionRepository.remove(id, author, userId);
116
- };
117
- BaseRateService.prototype.comment = function (comment) {
118
- var _this = this;
119
- return this.repository.load(comment.id, comment.author).then(function (checkRate) {
120
- if (!checkRate) {
121
- return -1;
122
- }
123
- else {
124
- comment.time ? comment.time = comment.time : comment.time = new Date();
125
- return _this.commentRepository.insert(comment);
126
- }
127
- });
128
- };
129
- BaseRateService.prototype.removeComment = function (commentId, userId) {
130
- var _this = this;
131
- return this.commentRepository.load(commentId).then(function (comment) {
132
- if (comment) {
133
- if (userId === comment.author || userId === comment.userId) {
134
- return _this.commentRepository.remove(commentId, comment.id, comment.author);
135
- }
136
- else {
137
- return -2;
138
- }
139
- }
140
- else {
141
- return -1;
142
- }
143
- });
144
- };
145
- BaseRateService.prototype.updateComment = function (comment) {
146
- var _this = this;
147
- return this.commentRepository.load(comment.commentId).then(function (exist) {
148
- if (!exist) {
149
- return -1;
150
- }
151
- else {
152
- if (exist.userId !== comment.userId) {
153
- return -2;
154
- }
155
- exist.updatedAt = new Date();
156
- var c = { comment: exist.comment, time: exist.time };
157
- if (exist.histories && exist.histories.length > 0) {
158
- exist.histories.push(c);
159
- }
160
- else {
161
- exist.histories = [c];
162
- }
163
- exist.comment = comment.comment;
164
- var res = _this.commentRepository.update(exist);
165
- return res;
166
- }
167
- });
168
- };
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
- };
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
- });
210
- };
211
- return BaseRateService;
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;
47
+ this.rate = this.rate.bind(this);
220
48
  }
221
49
  RateService.prototype.rate = function (rate) {
222
50
  return __awaiter(this, void 0, void 0, function () {
@@ -225,7 +53,7 @@ var RateService = (function (_super) {
225
53
  switch (_a.label) {
226
54
  case 0:
227
55
  rate.time = new Date();
228
- return [4, this.infoRepository.load(rate.id)];
56
+ return [4, this.infoRepository.exist(rate.id)];
229
57
  case 1:
230
58
  info = _a.sent();
231
59
  if (!!info) return [3, 3];
@@ -260,7 +88,7 @@ var RateService = (function (_super) {
260
88
  });
261
89
  };
262
90
  return RateService;
263
- }(BaseRateService));
91
+ }());
264
92
  exports.RateService = RateService;
265
93
  function avg(n) {
266
94
  var sum = 0;
@@ -271,19 +99,18 @@ function avg(n) {
271
99
  return sum / n.length;
272
100
  }
273
101
  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;
102
+ var RatesService = (function () {
103
+ function RatesService(repository, infoRepository) {
104
+ this.repository = repository;
105
+ this.infoRepository = infoRepository;
106
+ this.rate = this.rate.bind(this);
280
107
  }
281
108
  RatesService.prototype.rate = function (rate) {
282
109
  return __awaiter(this, void 0, void 0, function () {
283
110
  var info, r0, exist, r1, sr, history, res;
284
111
  return __generator(this, function (_a) {
285
112
  switch (_a.label) {
286
- case 0: return [4, this.infoRepository.load(rate.id)];
113
+ case 0: return [4, this.infoRepository.exist(rate.id)];
287
114
  case 1:
288
115
  info = _a.sent();
289
116
  if (rate.rates && rate.rates.length > 0) {
@@ -322,126 +149,8 @@ var RatesService = (function (_super) {
322
149
  });
323
150
  };
324
151
  return RatesService;
325
- }(BaseRateService));
326
- exports.RatesService = RatesService;
327
- var CommentQuery = (function () {
328
- function CommentQuery(find, repository, queryURL) {
329
- this.find = find;
330
- this.repository = repository;
331
- this.queryURL = queryURL;
332
- this.load = this.load.bind(this);
333
- this.search = this.search.bind(this);
334
- this.getComments = this.getComments.bind(this);
335
- }
336
- CommentQuery.prototype.load = function (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
- });
352
- };
353
- CommentQuery.prototype.getComments = function (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
- });
377
- };
378
- CommentQuery.prototype.search = function (s, limit, offset, fields) {
379
- var _this = this;
380
- return this.find(s, limit, offset, fields).then(function (res) {
381
- if (!_this.queryURL) {
382
- return res;
383
- }
384
- else {
385
- if (res.list && res.list.length > 0) {
386
- var ids = [];
387
- for (var _i = 0, _a = res.list; _i < _a.length; _i++) {
388
- var rate = _a[_i];
389
- ids.push(rate.userId);
390
- }
391
- return _this.queryURL(ids).then(function (urls) {
392
- for (var _i = 0, _a = res.list; _i < _a.length; _i++) {
393
- var rate = _a[_i];
394
- var i = binarySearch(urls, rate.userId);
395
- if (i >= 0) {
396
- rate.userURL = urls[i].url;
397
- }
398
- }
399
- return res;
400
- });
401
- }
402
- else {
403
- return res;
404
- }
405
- }
406
- });
407
- };
408
- return CommentQuery;
409
- }());
410
- exports.CommentQuery = CommentQuery;
411
- function binarySearch(ar, el) {
412
- var m = 0;
413
- var n = ar.length - 1;
414
- while (m <= n) {
415
- var k = (n + m) >> 1;
416
- var cmp = compare(el, ar[k].id);
417
- if (cmp > 0) {
418
- m = k + 1;
419
- }
420
- else if (cmp < 0) {
421
- n = k - 1;
422
- }
423
- else {
424
- return k;
425
- }
426
- }
427
- return -m - 1;
428
- }
429
- function compare(s1, s2) {
430
- return s1.localeCompare(s2);
431
- }
432
- var CommentValidator = (function () {
433
- function CommentValidator(attributes, check) {
434
- this.attributes = attributes;
435
- this.check = check;
436
- this.validate = this.validate.bind(this);
437
- }
438
- CommentValidator.prototype.validate = function (comment) {
439
- var errs = this.check(comment, this.attributes);
440
- return Promise.resolve(errs);
441
- };
442
- return CommentValidator;
443
152
  }());
444
- exports.CommentValidator = CommentValidator;
153
+ exports.RatesService = RatesService;
445
154
  var RateValidator = (function () {
446
155
  function RateValidator(attributes, check, max) {
447
156
  this.attributes = attributes;
@@ -468,6 +177,38 @@ var RateValidator = (function () {
468
177
  return RateValidator;
469
178
  }());
470
179
  exports.RateValidator = RateValidator;
180
+ var RatesValidator = (function () {
181
+ function RatesValidator(attributes, check, max, length) {
182
+ this.attributes = attributes;
183
+ this.check = check;
184
+ this.max = max;
185
+ this.length = length;
186
+ this.validate = this.validate.bind(this);
187
+ }
188
+ RatesValidator.prototype.validate = function (rate) {
189
+ var errs = this.check(rate, this.attributes);
190
+ if (!rate.rates || rate.rates.length === 0) {
191
+ var err = createError('rates', 'required');
192
+ errs.push(err);
193
+ return Promise.resolve(errs);
194
+ }
195
+ if (rate.rates.length !== this.length) {
196
+ var err = createError('rates', 'length', this.length);
197
+ errs.push(err);
198
+ return Promise.resolve(errs);
199
+ }
200
+ for (var _i = 0, _a = rate.rates; _i < _a.length; _i++) {
201
+ var r = _a[_i];
202
+ if (r > this.max) {
203
+ var err = createError('rates', 'max', this.max);
204
+ errs.push(err);
205
+ }
206
+ }
207
+ return Promise.resolve(errs);
208
+ };
209
+ return RatesValidator;
210
+ }());
211
+ exports.RatesValidator = RatesValidator;
471
212
  function createError(field, code, param) {
472
213
  if (!code) {
473
214
  code = 'string';
package/lib/rate.js CHANGED
@@ -143,6 +143,7 @@ exports.ratesModel = {
143
143
  type: 'number'
144
144
  },
145
145
  rates: {
146
+ required: true,
146
147
  type: 'integers'
147
148
  },
148
149
  time: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rate-core",
3
- "version": "0.5.0",
3
+ "version": "0.5.3",
4
4
  "description": "rate",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./src/index.ts",
package/src/core.ts CHANGED
@@ -1,17 +1,3 @@
1
- export interface StringMap {
2
- [key: string]: string;
3
- }
4
- export interface Statement {
5
- query: string;
6
- params?: any[];
7
- }
8
- export interface DB {
9
- driver: string;
10
- param(i: number): string;
11
- exec(sql: string, args?: any[], ctx?: any): Promise<number>;
12
- execBatch(statements: Statement[], firstSuccess?: boolean, ctx?: any): Promise<number>;
13
- query<T>(sql: string, args?: any[], m?: StringMap, bools?: Attribute[], ctx?: any): Promise<T[]>;
14
- }
15
1
  export type DataType = 'ObjectId' | 'date' | 'datetime' | 'time'
16
2
  | 'boolean' | 'number' | 'integer' | 'string' | 'text'
17
3
  | 'object' | 'array' | 'binary'
@@ -73,63 +59,3 @@ export interface Filter {
73
59
  pageIndex?: number;
74
60
  pageSize?: number;
75
61
  }
76
- export interface ViewRepository<T, ID> {
77
- metadata?(): Attributes|undefined;
78
- keys?(): string[];
79
- all?(ctx?: any): Promise<T[]>;
80
- load(id: ID, ctx?: any): Promise<T|null>;
81
- exist?(id: ID, ctx?: any): Promise<boolean>;
82
- }
83
- export interface Repository<T, ID> extends ViewRepository<T, ID> {
84
- insert(obj: T, ctx?: any): Promise<number>;
85
- update(obj: T, ctx?: any): Promise<number>;
86
- patch?(obj: T, ctx?: any): Promise<number>;
87
- save?(obj: T, ctx?: any): Promise<number>;
88
- delete(id: ID, ctx?: any): Promise<number>;
89
- }
90
-
91
- export interface ViewService<T, ID> {
92
- metadata?(): Attributes|undefined;
93
- keys?(): string[];
94
- all?(ctx?: any): Promise<T[]>;
95
- load(id: ID, ctx?: any): Promise<T|null>;
96
- exist?(id: ID, ctx?: any): Promise<boolean>;
97
- }
98
- export interface GenericService<T, ID, R> extends ViewService<T, ID> {
99
- insert(obj: T, ctx?: any): Promise<R>;
100
- update(obj: T, ctx?: any): Promise<R>;
101
- patch?(obj: T, ctx?: any): Promise<R>;
102
- save?(obj: T, ctx?: any): Promise<R>;
103
- delete?(id: ID, ctx?: any): Promise<number>;
104
- }
105
- export interface SearchResult<T> {
106
- list: T[];
107
- total?: number;
108
- last?: boolean;
109
- nextPageToken?: string;
110
- }
111
-
112
- export interface ErrorMessage {
113
- field: string;
114
- code: string;
115
- param?: string|number|Date;
116
- message?: string;
117
- }
118
- export interface ResultInfo<T> {
119
- status: number|string;
120
- errors?: ErrorMessage[];
121
- value?: T;
122
- message?: string;
123
- }
124
- export type Result<T> = number | ResultInfo<T>;
125
- export interface SearchService<T, F extends Filter> {
126
- keys?(): string[];
127
- search(s: F, limit?: number, offset?: number|string, fields?: string[], ctx?: any): Promise<SearchResult<T>>;
128
- }
129
- export interface GenericSearchService<T, ID, R, F extends Filter>
130
- extends GenericService<T, ID, R>, SearchService<T, F> {
131
- }
132
- export interface Service<T, ID, F extends Filter> extends GenericSearchService<T, ID, Result<T>, F> {
133
-
134
- }
135
- export type Search<T, F> = (s: F, limit?: number, offset?: number | string, fields?: string[]) => Promise<SearchResult<T>>;
package/src/index.ts CHANGED
@@ -1,169 +1,18 @@
1
- import { Attributes, Search, SearchResult } from './core';
2
- import {
3
- BaseRate, Comment, CommentFilter, InfoRepository, Rate, RateCommentQuery, RateCommentRepository, RateFilter, Rater, RateReactionRepository, RateRepository,
4
- Rates, RatesFilter, ShortComment, ShortRate, ShortRates
5
- } from './rate';
1
+ import { Attributes } from './core';
2
+ import { BaseRepository, InfoRepository, Rate, Rater, Rates, ShortRate, ShortRates } from './rate';
6
3
 
7
4
  export * from './rate';
8
5
 
9
- export interface URL {
10
- id: string;
11
- url: string;
12
- }
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);
25
- this.comment = this.comment.bind(this);
26
- this.removeComment = this.removeComment.bind(this);
27
- this.updateComment = this.updateComment.bind(this);
28
- this.getComments = this.getComments.bind(this);
29
- this.getComment = this.getComment.bind(this);
30
- }
31
- search(s: F, limit?: number, offset?: number | string, fields?: string[]): Promise<SearchResult<R>> {
32
- return this.find(s, limit, offset, fields).then(res => {
33
- if (!this.queryURL) {
34
- return res;
35
- } else {
36
- if (res.list && res.list.length > 0) {
37
- const ids: string[] = [];
38
- for (const rate of res.list) {
39
- ids.push(rate.author);
40
- }
41
- return this.queryURL(ids).then(urls => {
42
- for (const rate of res.list) {
43
- const i = binarySearch(urls, rate.author);
44
- if (i >= 0) {
45
- rate.authorURL = urls[i].url;
46
- }
47
- }
48
- return res;
49
- });
50
- } else {
51
- return res;
52
- }
53
- }
54
- });
55
- }
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);
61
- }
62
- setUseful(id: string, author: string, userId: string): Promise<number> {
63
- return this.reactionRepository.save(id, author, userId, 1);
64
- }
65
- removeUseful(id: string, author: string, userId: string): Promise<number> {
66
- return this.reactionRepository.remove(id, author, userId);
67
- }
68
- comment(comment: Comment): Promise<number> {
69
- return this.repository.load(comment.id, comment.author).then(checkRate => {
70
- if (!checkRate) {
71
- return -1;
72
- } else {
73
- comment.time ? comment.time = comment.time : comment.time = new Date();
74
- return this.commentRepository.insert(comment);
75
- }
76
- });
77
- }
78
- removeComment(commentId: string, userId: string): Promise<number> {
79
- return this.commentRepository.load(commentId).then(comment => {
80
- if (comment) {
81
- if (userId === comment.author || userId === comment.userId) {
82
- return this.commentRepository.remove(commentId, comment.id, comment.author);
83
- } else {
84
- return -2;
85
- }
86
- } else {
87
- return -1;
88
- }
89
- });
90
- }
91
- updateComment(comment: Comment): Promise<number> {
92
- return this.commentRepository.load(comment.commentId).then(exist => {
93
- if (!exist) {
94
- return -1;
95
- } else {
96
- if (exist.userId !== comment.userId) {
97
- return -2;
98
- }
99
- exist.updatedAt = new Date();
100
- const c: ShortComment = { comment: exist.comment, time: exist.time };
101
- if (exist.histories && exist.histories.length > 0) {
102
- exist.histories.push(c);
103
- } else {
104
- exist.histories = [c];
105
- }
106
- exist.comment = comment.comment;
107
- const res = this.commentRepository.update(exist);
108
- return res;
109
- }
110
- });
111
- }
112
- getComments(id: string, author: string, limit?: number): Promise<Comment[]> {
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
- });
132
- }
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
- });
147
- }
148
- }
149
- export interface CommentRepository {
150
- load(commentId: string, ctx?: any): Promise<Comment | null>;
151
- getComments(id: string, author: string, limit?: number): Promise<Comment[]>;
152
- }
153
6
  // 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);
7
+ export class RateService implements Rater<Rate> {
8
+ constructor(
9
+ public repository: BaseRepository<Rate>,
10
+ public infoRepository: InfoRepository) {
162
11
  this.rate = this.rate.bind(this);
163
12
  }
164
13
  async rate(rate: Rate): Promise<number> {
165
14
  rate.time = new Date();
166
- const info = await this.infoRepository.load(rate.id);
15
+ const info = await this.infoRepository.exist(rate.id);
167
16
  if (!info) {
168
17
  const r0 = await this.repository.insert(rate, true);
169
18
  return r0;
@@ -193,18 +42,14 @@ export function avg(n: number[]): number {
193
42
  return sum / n.length;
194
43
  }
195
44
  // 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);
45
+ export class RatesService implements Rater<Rates> {
46
+ constructor(
47
+ public repository: BaseRepository<Rates>,
48
+ public infoRepository: InfoRepository) {
204
49
  this.rate = this.rate.bind(this);
205
50
  }
206
51
  async rate(rate: Rates): Promise<number> {
207
- const info = await this.infoRepository.load(rate.id);
52
+ const info = await this.infoRepository.exist(rate.id);
208
53
  if (rate.rates && rate.rates.length > 0) {
209
54
  rate.rate = avg(rate.rates);
210
55
  }
@@ -230,95 +75,6 @@ export class RatesService<O> extends BaseRateService<Rates, RatesFilter, O> impl
230
75
  return res;
231
76
  }
232
77
  }
233
- // tslint:disable-next-line:max-classes-per-file
234
- export class CommentQuery implements RateCommentQuery {
235
- constructor(protected find: Search<Comment, CommentFilter>, protected repository: CommentRepository, private queryURL?: (ids: string[]) => Promise<URL[]>) {
236
- this.load = this.load.bind(this);
237
- this.search = this.search.bind(this);
238
- this.getComments = this.getComments.bind(this);
239
- }
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
- });
254
- }
255
- getComments(id: string, author: string, limit?: number): Promise<Comment[]> {
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
- });
275
- }
276
- search(s: CommentFilter, limit?: number, offset?: number | string, fields?: string[]): Promise<SearchResult<Comment>> {
277
- return this.find(s, limit, offset, fields).then(res => {
278
- if (!this.queryURL) {
279
- return res;
280
- } else {
281
- if (res.list && res.list.length > 0) {
282
- const ids: string[] = [];
283
- for (const rate of res.list) {
284
- ids.push(rate.userId);
285
- }
286
- return this.queryURL(ids).then(urls => {
287
- for (const rate of res.list) {
288
- const i = binarySearch(urls, rate.userId);
289
- if (i >= 0) {
290
- rate.userURL = urls[i].url;
291
- }
292
- }
293
- return res;
294
- });
295
- } else {
296
- return res;
297
- }
298
- }
299
- });
300
- }
301
- }
302
- function binarySearch(ar: URL[], el: string): number {
303
- let m = 0;
304
- let n = ar.length - 1;
305
- while (m <= n) {
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
- }
316
- }
317
- return -m - 1;
318
- }
319
- function compare(s1: string, s2: string): number {
320
- return s1.localeCompare(s2);
321
- }
322
78
  interface ErrorMessage {
323
79
  field: string;
324
80
  code: string;
@@ -326,16 +82,6 @@ interface ErrorMessage {
326
82
  message?: string;
327
83
  }
328
84
  // tslint:disable-next-line:max-classes-per-file
329
- export class CommentValidator {
330
- constructor(protected attributes: Attributes, protected check: (obj: any, attributes: Attributes) => ErrorMessage[]) {
331
- this.validate = this.validate.bind(this);
332
- }
333
- validate(comment: Comment): Promise<ErrorMessage[]> {
334
- const errs = this.check(comment, this.attributes);
335
- return Promise.resolve(errs);
336
- }
337
- }
338
- // tslint:disable-next-line:max-classes-per-file
339
85
  export class RateValidator {
340
86
  constructor(protected attributes: Attributes, protected check: (obj: any, attributes: Attributes) => ErrorMessage[], protected max: number) {
341
87
  this.validate = this.validate.bind(this);
@@ -355,6 +101,32 @@ export class RateValidator {
355
101
  }
356
102
  }
357
103
  }
104
+ // tslint:disable-next-line:max-classes-per-file
105
+ export class RatesValidator {
106
+ constructor(protected attributes: Attributes, protected check: (obj: any, attributes: Attributes) => ErrorMessage[], protected max: number, protected length: number) {
107
+ this.validate = this.validate.bind(this);
108
+ }
109
+ validate(rate: Rates): Promise<ErrorMessage[]> {
110
+ const errs = this.check(rate, this.attributes);
111
+ if (!rate.rates || rate.rates.length === 0) {
112
+ const err = createError('rates', 'required');
113
+ errs.push(err);
114
+ return Promise.resolve(errs);
115
+ }
116
+ if (rate.rates.length !== this.length) {
117
+ const err = createError('rates', 'length', this.length);
118
+ errs.push(err);
119
+ return Promise.resolve(errs);
120
+ }
121
+ for (const r of rate.rates) {
122
+ if (r > this.max) {
123
+ const err = createError('rates', 'max', this.max);
124
+ errs.push(err);
125
+ }
126
+ }
127
+ return Promise.resolve(errs);
128
+ }
129
+ }
358
130
  function createError(field: string, code?: string, param?: string | number | Date): ErrorMessage {
359
131
  if (!code) {
360
132
  code = 'string';
package/src/rate.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Attributes, Filter, Repository, SearchResult, ViewRepository } from './core';
1
+ import { Attributes, Filter } from './core';
2
2
 
3
3
  export interface RateId {
4
4
  id: string;
@@ -64,41 +64,14 @@ export interface RatesFilter extends RateFilter {
64
64
  rate9: number;
65
65
  rate10: number;
66
66
  }
67
- export interface RateRepository<R> {
68
- // save(obj: Rate, info?: T, ctx?: any): Promise<number>;
67
+ export interface BaseRepository<R> {
69
68
  insert(rate: R, newInfo?: boolean): Promise<number>;
70
69
  update(rate: R, oldRate: number): Promise<number>;
71
70
  load(id: string, author: string): Promise<R | null>;
72
71
  }
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>;
77
- setUseful(id: string, author: string, userId: string, ctx?: any): Promise<number>;
78
- removeUseful(id: string, author: string, userId: string, ctx?: any): Promise<number>;
79
- comment(comment: Comment): Promise<number>;
80
- removeComment(id: string, author: string, ctx?: any): Promise<number>;
81
- updateComment(comment: Comment): Promise<number>;
82
- getComments(id: string, author: string, limit?: number): Promise<Comment[]>;
83
- getComment(id: string): Promise<Comment | null>;
84
- }
85
- export interface RateReactionRepository {
86
- remove(id: string, author: string, userId: string, ctx?: any): Promise<number>;
87
- save(id: string, author: string, userId: string, type: number): Promise<number>;
88
- }
89
72
 
90
- export interface RateCommentRepository extends Repository<Comment, string> {
91
- remove(commentId: string, id: string, author: string): Promise<number>;
92
- getComments(id: string, author: string, limit?: number): Promise<Comment[]>;
93
- }
94
-
95
- export interface Query<T, ID, S> {
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>;
99
- }
100
- export interface RateCommentQuery extends Query<Comment, string, CommentFilter> {
101
- getComments(id: string, author: string, limit?: number): Promise<Comment[]>;
73
+ export interface Rater<R> {
74
+ rate(rate: R): Promise<number>;
102
75
  }
103
76
  export const rateHistoryModel: Attributes = {
104
77
  rate: {
@@ -245,40 +218,8 @@ export interface Info10 {
245
218
  count: number;
246
219
  score: number;
247
220
  }
248
- export interface InfoRepository<T> extends ViewRepository<T, string> {
249
- }
250
-
251
- export interface CommentId {
252
- id: string;
253
- author: string;
254
- userId: string;
255
- }
256
-
257
- export interface Comment {
258
- commentId: string;
259
- id: string;
260
- author: string;
261
- userId: string;
262
- comment: string;
263
- time: Date;
264
- updatedAt?: Date;
265
- histories?: ShortComment[];
266
- userURL?: string;
267
- authorURL?: string;
268
- }
269
- export interface ShortComment {
270
- comment: string;
271
- time: Date;
272
- }
273
-
274
- export interface CommentFilter extends Filter {
275
- commentId?: string;
276
- id?: string;
277
- author?: string;
278
- userId?: string;
279
- comment?: string;
280
- time?: Date;
281
- updatedAt?: Date;
221
+ export interface InfoRepository {
222
+ exist(id: string, ctx?: any): Promise<boolean>;
282
223
  }
283
224
 
284
225
  export const rateInfoModel: Attributes = {
@@ -295,7 +236,6 @@ export const rateInfoModel: Attributes = {
295
236
  type: 'number',
296
237
  }
297
238
  };
298
-
299
239
  export const ratesModel: Attributes = {
300
240
  id: {
301
241
  key: true,
@@ -309,6 +249,7 @@ export const ratesModel: Attributes = {
309
249
  type: 'number'
310
250
  },
311
251
  rates: {
252
+ required: true,
312
253
  type: 'integers'
313
254
  },
314
255
  time: {