rates-service 0.0.1

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 ADDED
@@ -0,0 +1 @@
1
+ # rates
package/lib/index.js ADDED
@@ -0,0 +1,268 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (_) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ function buildMap(attrs) {
40
+ var mp = {};
41
+ var ks = Object.keys(attrs);
42
+ for (var _i = 0, ks_1 = ks; _i < ks_1.length; _i++) {
43
+ var k = ks_1[_i];
44
+ var attr = attrs[k];
45
+ attr.name = k;
46
+ var field = attr.column ? attr.column : k;
47
+ var s = field.toLowerCase();
48
+ if (s !== k) {
49
+ mp[s] = k;
50
+ }
51
+ }
52
+ return mp;
53
+ }
54
+ exports.buildMap = buildMap;
55
+ var SqlRateRepository = (function () {
56
+ function SqlRateRepository(db, table, attributes, max, infoTable, buildToInsert, buildToUpdate, generateId, rateIdField, rateField, count, score, authorCol, id, idField, idCol, rateCol) {
57
+ this.db = db;
58
+ this.table = table;
59
+ this.attributes = attributes;
60
+ this.max = max;
61
+ this.infoTable = infoTable;
62
+ this.buildToInsert = buildToInsert;
63
+ this.buildToUpdate = buildToUpdate;
64
+ this.generateId = generateId;
65
+ this.rateIdField = rateIdField;
66
+ this.map = buildMap(attributes);
67
+ this.id = (id && id.length > 0 ? id : 'id');
68
+ this.rate = (rateCol && rateCol.length > 0 ? rateCol : 'rate');
69
+ this.count = (count && count.length > 0 ? count : 'count');
70
+ this.score = (score && score.length > 0 ? score : 'score');
71
+ this.idField = (idField && idField.length > 0 ? idField : 'id');
72
+ this.rateField = (rateField && rateField.length > 0 ? rateField : 'rate');
73
+ this.authorCol = (authorCol && authorCol.length > 0 ? authorCol : 'author');
74
+ if (idCol && idCol.length > 0) {
75
+ this.idCol = idCol;
76
+ }
77
+ else {
78
+ var c = attributes[this.idField];
79
+ if (c) {
80
+ this.idCol = (c.column && c.column.length > 0 ? c.column : this.idField);
81
+ }
82
+ else {
83
+ this.idCol = this.idField;
84
+ }
85
+ }
86
+ if (rateCol && rateCol.length > 0) {
87
+ this.rate = rateCol;
88
+ }
89
+ else {
90
+ var c = attributes[this.rateField];
91
+ if (c) {
92
+ this.rate = (c.column && c.column.length > 0 ? c.column : this.rateField);
93
+ }
94
+ else {
95
+ this.rate = this.rateField;
96
+ }
97
+ }
98
+ this.load = this.load.bind(this);
99
+ this.create = this.create.bind(this);
100
+ this.update = this.update.bind(this);
101
+ this.insertInfo = this.insertInfo.bind(this);
102
+ this.updateNewInfo = this.updateNewInfo.bind(this);
103
+ this.updateOldInfo = this.updateOldInfo.bind(this);
104
+ }
105
+ SqlRateRepository.prototype.load = function (id, author, tx) {
106
+ var db = tx ? tx : this.db;
107
+ return db.query("select * from " + this.table + " where " + this.idCol + " = " + this.db.param(1) + " and " + this.authorCol + " = " + this.db.param(2), [id, author], this.map).then(function (rates) {
108
+ return rates && rates.length > 0 ? rates[0] : null;
109
+ });
110
+ };
111
+ SqlRateRepository.prototype.create = function (rate, newInfo, tx) {
112
+ rate[this.rateIdField] = this.generateId();
113
+ var stmt = this.buildToInsert(rate, this.table, this.attributes, this.db.param);
114
+ if (stmt.query) {
115
+ var obj = rate;
116
+ var rateNum = obj[this.rateField];
117
+ var id = obj[this.idField];
118
+ var db = tx ? tx : this.db;
119
+ if (newInfo) {
120
+ var query = this.insertInfo(rateNum);
121
+ var s2 = { query: query, params: [id] };
122
+ return db.executeBatch([s2, stmt], true);
123
+ }
124
+ else {
125
+ var query = this.updateNewInfo(rateNum);
126
+ var s2 = { query: query, params: [id] };
127
+ return db.executeBatch([s2, stmt], true);
128
+ }
129
+ }
130
+ else {
131
+ return Promise.resolve(-1);
132
+ }
133
+ };
134
+ SqlRateRepository.prototype.insertInfo = function (r) {
135
+ var rateCols = [];
136
+ var ps = [];
137
+ for (var i = 1; i <= this.max; i++) {
138
+ rateCols.push("" + this.rate + i);
139
+ if (i === r) {
140
+ ps.push('' + 1);
141
+ }
142
+ else {
143
+ ps.push('0');
144
+ }
145
+ }
146
+ var query = "\n insert into " + this.infoTable + " (" + this.id + ", " + this.rate + ", " + this.count + ", " + this.score + ", " + rateCols.join(',') + ")\n values (" + this.db.param(1) + ", " + r + ", 1, " + r + ", " + ps.join(',') + ")";
147
+ return query;
148
+ };
149
+ SqlRateRepository.prototype.update = function (rate, oldRate, tx) {
150
+ var stmt = this.buildToUpdate(rate, this.table, this.attributes, this.db.param);
151
+ if (stmt.query) {
152
+ var obj = rate;
153
+ var rateNum = obj[this.rateField];
154
+ var id = obj[this.idField];
155
+ var query = this.updateOldInfo(rateNum, oldRate);
156
+ var s2 = { query: query, params: [id] };
157
+ var db = tx ? tx : this.db;
158
+ return db.executeBatch([s2, stmt], true);
159
+ }
160
+ else {
161
+ return Promise.resolve(-1);
162
+ }
163
+ };
164
+ SqlRateRepository.prototype.updateNewInfo = function (r) {
165
+ var query = "\n update " + this.infoTable + " set " + this.rate + " = (" + this.score + " + " + r + ")/(" + this.count + " + 1), " + this.count + " = " + this.count + " + 1, " + this.score + " = " + this.score + " + " + r + ", " + this.rate + r + " = " + this.rate + r + " + 1\n where " + this.id + " = " + this.db.param(1);
166
+ return query;
167
+ };
168
+ SqlRateRepository.prototype.updateOldInfo = function (newRate, oldRate) {
169
+ if (newRate === oldRate) {
170
+ return '';
171
+ }
172
+ var delta = newRate - oldRate;
173
+ var query = "\n update " + this.infoTable + " set " + this.rate + " = (" + this.score + " + (" + delta + "))/" + this.count + ", " + this.score + " = " + this.score + " + (" + delta + "), " + this.rate + newRate + " = " + this.rate + newRate + " + 1, " + this.rate + oldRate + " = " + this.rate + oldRate + " - 1\n where " + this.id + " = " + this.db.param(1);
174
+ return query;
175
+ };
176
+ return SqlRateRepository;
177
+ }());
178
+ exports.SqlRateRepository = SqlRateRepository;
179
+ var Rater = (function () {
180
+ function Rater(db, rateRepository, rateSummaryRepository, usefulRepository) {
181
+ this.db = db;
182
+ this.rateRepository = rateRepository;
183
+ this.rateSummaryRepository = rateSummaryRepository;
184
+ this.usefulRepository = usefulRepository;
185
+ this.getRate = this.getRate.bind(this);
186
+ this.setUseful = this.setUseful.bind(this);
187
+ this.removeUseful = this.removeUseful.bind(this);
188
+ this.rate = this.rate.bind(this);
189
+ }
190
+ Rater.prototype.getRate = function (id, author) {
191
+ return this.rateRepository.load(id, author);
192
+ };
193
+ Rater.prototype.setUseful = function (rateId, userId) {
194
+ return this.usefulRepository.setUseful(rateId, userId);
195
+ };
196
+ Rater.prototype.removeUseful = function (rateId, userId) {
197
+ return this.usefulRepository.removeUseful(rateId, userId);
198
+ };
199
+ Rater.prototype.rate = function (rateReq) {
200
+ return __awaiter(this, void 0, void 0, function () {
201
+ var rate, tx, summary, res, exist, res, history, histories, oldRate, count, err_1;
202
+ return __generator(this, function (_a) {
203
+ switch (_a.label) {
204
+ case 0:
205
+ rate = { id: rateReq.id, author: rateReq.author, rate: rateReq.rate, time: new Date(), review: rateReq.review };
206
+ return [4, this.db.beginTransaction()];
207
+ case 1:
208
+ tx = _a.sent();
209
+ _a.label = 2;
210
+ case 2:
211
+ _a.trys.push([2, 13, , 15]);
212
+ return [4, this.rateSummaryRepository.exist(rateReq.id, tx)];
213
+ case 3:
214
+ summary = _a.sent();
215
+ if (!!summary) return [3, 6];
216
+ return [4, this.rateRepository.create(rate, true, tx)];
217
+ case 4:
218
+ res = _a.sent();
219
+ return [4, tx.commit()];
220
+ case 5:
221
+ _a.sent();
222
+ return [2, res];
223
+ case 6: return [4, this.rateRepository.load(rateReq.id, rateReq.author, tx)];
224
+ case 7:
225
+ exist = _a.sent();
226
+ if (!!exist) return [3, 10];
227
+ return [4, this.rateRepository.create(rate, false, tx)];
228
+ case 8:
229
+ res = _a.sent();
230
+ return [4, tx.commit()];
231
+ case 9:
232
+ _a.sent();
233
+ return [2, res];
234
+ case 10:
235
+ history = { review: exist.review, rate: exist.rate, time: exist.time };
236
+ if (exist.histories && exist.histories.length > 0) {
237
+ histories = exist.histories;
238
+ histories.push(history);
239
+ exist.histories = histories;
240
+ }
241
+ else {
242
+ exist.histories = [history];
243
+ }
244
+ oldRate = exist.rate;
245
+ exist.rate = rateReq.rate;
246
+ exist.review = rateReq.review;
247
+ exist.time = new Date();
248
+ return [4, this.rateRepository.update(exist, oldRate, tx)];
249
+ case 11:
250
+ count = _a.sent();
251
+ return [4, tx.commit()];
252
+ case 12:
253
+ _a.sent();
254
+ return [2, count];
255
+ case 13:
256
+ err_1 = _a.sent();
257
+ return [4, tx.rollback()];
258
+ case 14:
259
+ _a.sent();
260
+ throw err_1;
261
+ case 15: return [2];
262
+ }
263
+ });
264
+ });
265
+ };
266
+ return Rater;
267
+ }());
268
+ exports.Rater = Rater;
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "rates-service",
3
+ "version": "0.0.1",
4
+ "description": "rate",
5
+ "main": "./lib/index.js",
6
+ "types": "./src/index.ts",
7
+ "scripts": {
8
+ "build:lib": "tsc",
9
+ "clean:lib": "rimraf lib"
10
+ },
11
+ "devDependencies": {
12
+ "tslint": "5.10.0",
13
+ "typescript": "^3.3.3333"
14
+ },
15
+ "publishConfig": {
16
+ "registry": "https://registry.npmjs.org/"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git@github.com/core-ts/rates"
21
+ },
22
+ "keywords": [
23
+ "rates",
24
+ "rates service",
25
+ "rates-core"
26
+ ]
27
+ }
package/src/index.ts ADDED
@@ -0,0 +1,297 @@
1
+ export type DataType =
2
+ | "ObjectId"
3
+ | "date"
4
+ | "datetime"
5
+ | "time"
6
+ | "boolean"
7
+ | "number"
8
+ | "integer"
9
+ | "string"
10
+ | "text"
11
+ | "object"
12
+ | "array"
13
+ | "binary"
14
+ | "primitives"
15
+ | "booleans"
16
+ | "numbers"
17
+ | "integers"
18
+ | "strings"
19
+ | "dates"
20
+ | "datetimes"
21
+ | "times"
22
+ export type Operator = "=" | "like" | "!=" | "<>" | ">" | ">=" | "<" | "<="
23
+
24
+ export interface Attribute {
25
+ name?: string
26
+ column?: string
27
+ type?: DataType
28
+ default?: string | number | Date | boolean
29
+ key?: boolean
30
+ q?: boolean
31
+ noinsert?: boolean
32
+ noupdate?: boolean
33
+ nopatch?: boolean
34
+ version?: boolean
35
+ ignored?: boolean
36
+ true?: string | number
37
+ false?: string | number
38
+ createdAt?: boolean
39
+ updatedAt?: boolean
40
+ }
41
+ export interface Attributes {
42
+ [key: string]: Attribute
43
+ }
44
+
45
+ export interface Executor {
46
+ driver: string
47
+ param(i: number): string
48
+ execute(sql: string, args?: any[], ctx?: any): Promise<number>
49
+ executeBatch(statements: Statement[], firstSuccess?: boolean, ctx?: any): Promise<number>
50
+ query<T>(sql: string, args?: any[], m?: StringMap, bools?: Attribute[], ctx?: any): Promise<T[]>
51
+ }
52
+ export interface Transaction extends Executor {
53
+ commit(): Promise<void>
54
+ rollback(): Promise<void>
55
+ }
56
+ export interface DB extends Executor {
57
+ beginTransaction(): Promise<Transaction>
58
+ }
59
+ export interface StringMap {
60
+ [key: string]: string
61
+ }
62
+ export interface Statement {
63
+ query: string
64
+ params?: any[]
65
+ }
66
+
67
+ export function buildMap(attrs: Attributes): StringMap {
68
+ const mp: StringMap = {}
69
+ const ks = Object.keys(attrs)
70
+ for (const k of ks) {
71
+ const attr = attrs[k]
72
+ attr.name = k
73
+ const field = attr.column ? attr.column : k
74
+ const s = field.toLowerCase()
75
+ if (s !== k) {
76
+ mp[s] = k
77
+ }
78
+ }
79
+ return mp
80
+ }
81
+ export class SqlRateRepository<R> {
82
+ constructor(protected db: DB, protected table: string, protected attributes: Attributes, protected max: number, protected infoTable: string,
83
+ protected buildToInsert: (obj: R, table: string, attrs: Attributes, buildParam: (i: number) => string) => Statement,
84
+ protected buildToUpdate: (obj: R, table: string, attrs: Attributes, buildParam: (i: number) => string) => Statement,
85
+ protected generateId: () => string, protected rateIdField: string, rateField?: string, count?: string, score?: string, authorCol?: string, id?: string, idField?: string, idCol?: string, rateCol?: string) {
86
+ this.map = buildMap(attributes);
87
+ this.id = (id && id.length > 0 ? id : 'id');
88
+ this.rate = (rateCol && rateCol.length > 0 ? rateCol : 'rate');
89
+ this.count = (count && count.length > 0 ? count : 'count');
90
+ this.score = (score && score.length > 0 ? score : 'score');
91
+ this.idField = (idField && idField.length > 0 ? idField : 'id');
92
+ this.rateField = (rateField && rateField.length > 0 ? rateField : 'rate');
93
+ this.authorCol = (authorCol && authorCol.length > 0 ? authorCol : 'author');
94
+ if (idCol && idCol.length > 0) {
95
+ this.idCol = idCol;
96
+ } else {
97
+ const c = attributes[this.idField];
98
+ if (c) {
99
+ this.idCol = (c.column && c.column.length > 0 ? c.column : this.idField);
100
+ } else {
101
+ this.idCol = this.idField;
102
+ }
103
+ }
104
+ if (rateCol && rateCol.length > 0) {
105
+ this.rate = rateCol;
106
+ } else {
107
+ const c = attributes[this.rateField];
108
+ if (c) {
109
+ this.rate = (c.column && c.column.length > 0 ? c.column : this.rateField);
110
+ } else {
111
+ this.rate = this.rateField;
112
+ }
113
+ }
114
+ this.load = this.load.bind(this);
115
+ this.create = this.create.bind(this);
116
+ this.update = this.update.bind(this);
117
+ this.insertInfo = this.insertInfo.bind(this);
118
+ this.updateNewInfo = this.updateNewInfo.bind(this);
119
+ this.updateOldInfo = this.updateOldInfo.bind(this);
120
+ }
121
+ map?: StringMap;
122
+ count: string;
123
+ score: string;
124
+ id: string;
125
+ rate: string;
126
+ idField: string;
127
+ rateField: string;
128
+ idCol: string;
129
+ authorCol: string;
130
+ load(id: string, author: string, tx?: Transaction): Promise<R | null> {
131
+ const db = tx ? tx : this.db
132
+ return db.query<R>(`select * from ${this.table} where ${this.idCol} = ${this.db.param(1)} and ${this.authorCol} = ${this.db.param(2)}`, [id, author], this.map).then(rates => {
133
+ return rates && rates.length > 0 ? rates[0] : null;
134
+ });
135
+ }
136
+ create(rate: R, newInfo?: boolean, tx?: Transaction): Promise<number> {
137
+ (rate as any)[this.rateIdField] = this.generateId()
138
+ const stmt = this.buildToInsert(rate, this.table, this.attributes, this.db.param);
139
+ if (stmt.query) {
140
+ const obj: any = rate;
141
+ const rateNum: number = obj[this.rateField];
142
+ const id: string = obj[this.idField];
143
+ const db = tx ? tx : this.db
144
+ if (newInfo) {
145
+ const query = this.insertInfo(rateNum);
146
+ const s2: Statement = { query, params: [id] };
147
+ return db.executeBatch([s2, stmt], true);
148
+ } else {
149
+ const query = this.updateNewInfo(rateNum);
150
+ const s2: Statement = { query, params: [id] };
151
+ return db.executeBatch([s2, stmt], true);
152
+ }
153
+ } else {
154
+ return Promise.resolve(-1);
155
+ }
156
+ }
157
+ protected insertInfo(r: number): string {
158
+ const rateCols: string[] = [];
159
+ const ps: string[] = [];
160
+ for (let i = 1; i <= this.max; i++) {
161
+ rateCols.push(`${this.rate}${i}`);
162
+ if (i === r) {
163
+ ps.push('' + 1);
164
+ } else {
165
+ ps.push('0');
166
+ }
167
+ }
168
+ const query = `
169
+ insert into ${this.infoTable} (${this.id}, ${this.rate}, ${this.count}, ${this.score}, ${rateCols.join(',')})
170
+ values (${this.db.param(1)}, ${r}, 1, ${r}, ${ps.join(',')})`;
171
+ return query;
172
+ }
173
+ update(rate: R, oldRate: number, tx?: Transaction): Promise<number> {
174
+ const stmt = this.buildToUpdate(rate, this.table, this.attributes, this.db.param);
175
+ if (stmt.query) {
176
+ const obj: any = rate;
177
+ const rateNum: number = obj[this.rateField];
178
+ const id: string = obj[this.idField];
179
+ const query = this.updateOldInfo(rateNum, oldRate);
180
+ const s2: Statement = { query, params: [id] };
181
+ const db = tx ? tx : this.db
182
+ return db.executeBatch([s2, stmt], true);
183
+ } else {
184
+ return Promise.resolve(-1);
185
+ }
186
+ }
187
+ protected updateNewInfo(r: number): string {
188
+ const query = `
189
+ update ${this.infoTable} set ${this.rate} = (${this.score} + ${r})/(${this.count} + 1), ${this.count} = ${this.count} + 1, ${this.score} = ${this.score} + ${r}, ${this.rate}${r} = ${this.rate}${r} + 1
190
+ where ${this.id} = ${this.db.param(1)}`;
191
+ return query;
192
+ }
193
+ protected updateOldInfo(newRate: number, oldRate: number): string {
194
+ if (newRate === oldRate) {
195
+ return '';
196
+ }
197
+ const delta = newRate - oldRate;
198
+ const query = `
199
+ update ${this.infoTable} set ${this.rate} = (${this.score} + (${delta}))/${this.count}, ${this.score} = ${this.score} + (${delta}), ${this.rate}${newRate} = ${this.rate}${newRate} + 1, ${this.rate}${oldRate} = ${this.rate}${oldRate} - 1
200
+ where ${this.id} = ${this.db.param(1)}`;
201
+ return query;
202
+ }
203
+ }
204
+
205
+ export interface SubmittedRate {
206
+ id: string;
207
+ author: string;
208
+ rate: number;
209
+ review: string;
210
+ }
211
+ export interface Rate {
212
+ id: string;
213
+ author: string;
214
+ rate: number;
215
+ time: Date;
216
+ review: string;
217
+ histories?: History[];
218
+ }
219
+
220
+ export interface History {
221
+ rate: number;
222
+ time: Date;
223
+ review: string;
224
+ }
225
+
226
+ export interface RateRepository {
227
+ create(rate: Rate, newInfo?: boolean, tx?: Transaction): Promise<number>
228
+ update(rate: Rate, oldRate: number, tx?: Transaction): Promise<number>
229
+ load(id: string, author: string, tx?: Transaction): Promise<Rate | null>
230
+ }
231
+ export interface RateSummaryRepository {
232
+ exist(id: string, tx?: Transaction): Promise<boolean>
233
+ }
234
+ export interface RateService {
235
+ getRate(id: string, author: string): Promise<Rate | null>
236
+ setUseful(rateId: string, userId: string): Promise<number>
237
+ removeUseful(rateId: string, userId: string): Promise<number>
238
+ rate(rateReq: SubmittedRate): Promise<number>
239
+ }
240
+ export interface UsefulRepository {
241
+ setUseful(rateId: string, userId: string): Promise<number>
242
+ removeUseful(rateId: string, userId: string): Promise<number>
243
+ }
244
+ // tslint:disable-next-line:max-classes-per-file
245
+ export class Rater implements RateService {
246
+ constructor(protected db: DB, protected rateRepository: RateRepository, protected rateSummaryRepository: RateSummaryRepository, protected usefulRepository: UsefulRepository) {
247
+ this.getRate = this.getRate.bind(this)
248
+ this.setUseful = this.setUseful.bind(this)
249
+ this.removeUseful = this.removeUseful.bind(this)
250
+ this.rate = this.rate.bind(this)
251
+ }
252
+ getRate(id: string, author: string): Promise<Rate | null> {
253
+ return this.rateRepository.load(id, author)
254
+ }
255
+ setUseful(rateId: string, userId: string): Promise<number> {
256
+ return this.usefulRepository.setUseful(rateId, userId)
257
+ }
258
+ removeUseful(rateId: string, userId: string): Promise<number> {
259
+ return this.usefulRepository.removeUseful(rateId, userId)
260
+ }
261
+ async rate(rateReq: SubmittedRate): Promise<number> {
262
+ const rate: Rate = {id: rateReq.id, author: rateReq.author, rate: rateReq.rate, time: new Date(), review: rateReq.review}
263
+ const tx = await this.db.beginTransaction()
264
+ try {
265
+ const summary = await this.rateSummaryRepository.exist(rateReq.id, tx)
266
+ if (!summary) {
267
+ const res = await this.rateRepository.create(rate, true, tx)
268
+ await tx.commit()
269
+ return res;
270
+ }
271
+ const exist = await this.rateRepository.load(rateReq.id, rateReq.author, tx)
272
+ if (!exist) {
273
+ const res = await this.rateRepository.create(rate, false, tx)
274
+ await tx.commit()
275
+ return res;
276
+ }
277
+ const history: History = { review: exist.review, rate: exist.rate, time: exist.time }
278
+ if (exist.histories && exist.histories.length > 0) {
279
+ const histories = exist.histories;
280
+ histories.push(history);
281
+ exist.histories = histories;
282
+ } else {
283
+ exist.histories = [history];
284
+ }
285
+ const oldRate = exist.rate
286
+ exist.rate = rateReq.rate
287
+ exist.review = rateReq.review
288
+ exist.time = new Date()
289
+ const count = await this.rateRepository.update(exist, oldRate, tx)
290
+ await tx.commit()
291
+ return count
292
+ } catch (err) {
293
+ await tx.rollback()
294
+ throw err
295
+ }
296
+ }
297
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "compileOnSave": true,
3
+ "compilerOptions": {
4
+ "target": "es5",
5
+ "baseUrl": "./src",
6
+ "outDir": "./lib",
7
+ "module": "commonjs",
8
+ "moduleResolution": "node",
9
+ "strict": true,
10
+ "pretty": true,
11
+ "sourceMap": false,
12
+ "declaration": false,
13
+ "experimentalDecorators": false,
14
+ "removeComments": true,
15
+ "lib": [
16
+ "es6"
17
+ ]
18
+ },
19
+ "include": [
20
+ "src/**/*.ts"
21
+ ],
22
+ "exclude": [
23
+ "node_modules"
24
+ ]
25
+ }