anote-server-libs 0.2.2 → 0.2.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/models/ApiCall.js +37 -37
- package/models/ApiCall.ts +40 -40
- package/models/Migration.js +35 -35
- package/models/Migration.ts +40 -40
- package/models/repository/BaseModelRepository.js +156 -156
- package/models/repository/BaseModelRepository.ts +152 -152
- package/models/repository/MemoryCache.js +92 -92
- package/models/repository/MemoryCache.ts +87 -87
- package/models/repository/ModelDao.js +238 -238
- package/models/repository/ModelDao.ts +259 -259
- package/package.json +38 -38
- package/services/WithBody.js +60 -60
- package/services/WithBody.ts +56 -56
- package/services/WithTransaction.js +137 -137
- package/services/WithTransaction.ts +134 -134
- package/services/utils.js +197 -197
- package/services/utils.ts +180 -180
- package/tsconfig.json +30 -30
|
@@ -1,238 +1,238 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ModelDao = exports.promiseAllStepN = void 0;
|
|
4
|
-
function promiseAllStepN(n, list) {
|
|
5
|
-
if (!list || !list.length)
|
|
6
|
-
return Promise.resolve([]);
|
|
7
|
-
const tail = list.splice(n);
|
|
8
|
-
const head = list;
|
|
9
|
-
const resolved = [];
|
|
10
|
-
let processed = 0;
|
|
11
|
-
return new Promise(resolve => {
|
|
12
|
-
head.forEach(x => {
|
|
13
|
-
const res = x();
|
|
14
|
-
resolved.push(res);
|
|
15
|
-
res.then((y) => {
|
|
16
|
-
runNext();
|
|
17
|
-
return y;
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
function runNext() {
|
|
21
|
-
if (processed === tail.length) {
|
|
22
|
-
resolve(Promise.all(resolved));
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
resolved.push(tail[processed]().then((x) => {
|
|
26
|
-
runNext();
|
|
27
|
-
return x;
|
|
28
|
-
}));
|
|
29
|
-
processed++;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
exports.promiseAllStepN = promiseAllStepN;
|
|
35
|
-
Promise.allConcurrent = (n) => (list) => promiseAllStepN(n, list);
|
|
36
|
-
class Dao {
|
|
37
|
-
constructor(pool, poolMssql, logger, table, nFields, updateDefinition) {
|
|
38
|
-
this.pool = pool;
|
|
39
|
-
this.poolMssql = poolMssql;
|
|
40
|
-
this.logger = logger;
|
|
41
|
-
this.table = table;
|
|
42
|
-
this.nFields = nFields;
|
|
43
|
-
this.updateDefinition = updateDefinition;
|
|
44
|
-
}
|
|
45
|
-
groupResultSet(q, key) {
|
|
46
|
-
const storage = {};
|
|
47
|
-
for (let i = 0; i < q.length; i++) {
|
|
48
|
-
storage[q[i][key]] = storage[q[i][key]] || [];
|
|
49
|
-
storage[q[i][key]].push(q[i]);
|
|
50
|
-
}
|
|
51
|
-
return Object.getOwnPropertyNames(storage).map(k => storage[k]);
|
|
52
|
-
}
|
|
53
|
-
groupResultSetBy(q, key) {
|
|
54
|
-
const storage = {};
|
|
55
|
-
for (let i = 0; i < q.length; i++) {
|
|
56
|
-
storage[key(q[i])] = storage[key(q[i])] || [];
|
|
57
|
-
storage[key(q[i])].push(q[i]);
|
|
58
|
-
}
|
|
59
|
-
return Object.getOwnPropertyNames(storage).map(k => storage[k]);
|
|
60
|
-
}
|
|
61
|
-
update(instance, client) {
|
|
62
|
-
if (instance.archivedOn)
|
|
63
|
-
return Promise.reject('Record archived!');
|
|
64
|
-
instance.updatedOn = new Date();
|
|
65
|
-
if (this.pool) {
|
|
66
|
-
const props = this.serialize(instance);
|
|
67
|
-
props.push(instance.id);
|
|
68
|
-
return client.query('UPDATE ' + this.table + ' SET ' + this.updateDefinition + ' WHERE id=$' + (this.nFields + 1), props).then(() => instance.id);
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
const request = client.request();
|
|
72
|
-
this.serialize(instance, request);
|
|
73
|
-
request.input(String(this.nFields + 1), instance.id);
|
|
74
|
-
return request.query('UPDATE ' + this.table + ' SET ' + this.updateDefinition + ' WHERE id=@' + (this.nFields + 1)).then(() => instance.id);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
replace(instance, client) {
|
|
78
|
-
if (instance.archivedOn)
|
|
79
|
-
return Promise.reject('Record archived!');
|
|
80
|
-
return this.create({ ...instance, replaced_id: instance.id }, client).then(id => {
|
|
81
|
-
return this.archive(instance.id, id, client).then(() => id);
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
create(instance, client) {
|
|
85
|
-
instance.createdOn = instance.updatedOn = new Date();
|
|
86
|
-
if (this.pool) {
|
|
87
|
-
const props = this.serialize(instance);
|
|
88
|
-
return (client || this.pool).query('INSERT INTO ' + this.table + '(' + this.updateDefinition.replace(/=\$\d+/g, '') + ')'
|
|
89
|
-
+ ' VALUES(' + new Array(this.nFields).fill(undefined).map((_, i) => '$' + (i + 1)).join(',') + ') RETURNING id', props).then(q => {
|
|
90
|
-
const idNum = parseInt(q.rows[0].id, 10);
|
|
91
|
-
if (String(idNum) !== q.rows[0].id)
|
|
92
|
-
return q.rows[0].id;
|
|
93
|
-
return idNum;
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
const request = (client || this.poolMssql).request();
|
|
98
|
-
this.serialize(instance, request);
|
|
99
|
-
return request.query('INSERT INTO ' + this.table + '(' + this.updateDefinition.replace(/=@\d+/g, '').replace(/=[^)]+\)/g, '') + ')'
|
|
100
|
-
+ ' VALUES(' + new Array(this.nFields).fill(undefined).map((_, i) => '@' + (i + 1)).join(',') + '); SELECT SCOPE_IDENTITY() AS id').then(q => {
|
|
101
|
-
return q.recordsets[0][0].id || instance.id;
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
createSeveral(instances, client) {
|
|
106
|
-
if (!instances.length)
|
|
107
|
-
return Promise.resolve([]);
|
|
108
|
-
const now = new Date();
|
|
109
|
-
instances.forEach(instance => instance.updatedOn = now);
|
|
110
|
-
const props = [].concat.apply([], instances.map(instance => this.serialize(instance)));
|
|
111
|
-
return (client || this.pool).query('INSERT INTO ' + this.table + '(' + this.updateDefinition.replace(/=\$\d+/g, '') + ')'
|
|
112
|
-
+ ' VALUES' + instances.map((_, j) => ('(' + new Array(this.nFields).fill(undefined).map((__, i) => '$' + (j * this.nFields + i + 1)).join(', ') + ')')).join(',') + ' RETURNING id', props).then(q => q.rows.map(r => {
|
|
113
|
-
const idNum = parseInt(r.id, 10);
|
|
114
|
-
if (String(idNum) !== q.rows[0].id)
|
|
115
|
-
return r.id;
|
|
116
|
-
return idNum;
|
|
117
|
-
}));
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
class ModelDao extends Dao {
|
|
121
|
-
get(id, client, lock = true) {
|
|
122
|
-
if (this.pool) {
|
|
123
|
-
return (client || this.pool).query('SELECT * FROM ' + this.table + ' WHERE id=$1' + ((client && lock) ? ' FOR UPDATE' : ''), [id]).then(q => this.buildObject(q.rows[0]));
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
const request = (client || this.poolMssql).request();
|
|
127
|
-
request.input('1', id);
|
|
128
|
-
return request.query('SELECT * FROM ' + this.table + ((client && lock) ? ' WITH (ROWLOCK)' : '') + ' WHERE id=@1').then(q => this.buildObject(q.recordsets[0][0]));
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
count(where, inputs = [], client) {
|
|
132
|
-
if (this.pool) {
|
|
133
|
-
return (client || this.pool).query('SELECT count(*) AS cnt FROM ' + this.table + (where ? (' WHERE ' + where) : ''), inputs).then(q => parseInt(q.rows[0].cnt, 10));
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
const request = (client || this.poolMssql).request();
|
|
137
|
-
if (where)
|
|
138
|
-
where.match(/(@\d+)/g).forEach((match, i) => request.input(match.substr(1), inputs[i]));
|
|
139
|
-
return request.query('SELECT count(*) AS cnt FROM ' + this.table + (where ? (' WHERE ' + where) : '')).then(q => q.recordsets[0][0].cnt);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
getList(ids, client, lock = true) {
|
|
143
|
-
if (this.pool) {
|
|
144
|
-
return (client || this.pool).query('SELECT * FROM ' + this.table + ' WHERE id=ANY($1)' + ((client && lock) ? ' FOR UPDATE' : ''), [ids])
|
|
145
|
-
.then(q => q.rows.map(r => this.buildObject(r)));
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
const request = (client || this.poolMssql).request();
|
|
149
|
-
return request.query('SELECT * FROM ' + this.table + ((client && lock) ? ' WITH (ROWLOCK)' : '') + ' WHERE id IN ('
|
|
150
|
-
+ (ids.length > 0 ? (typeof ids[0] === 'string' ? '\'' + ids.join('\',\'') + '\'' : ids.join(',')) : '') + ')')
|
|
151
|
-
.then(q => q.recordsets[0].map(r => this.buildObject(r)));
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
getAllBy(order, offset, limit, where, inputs = [], client, lock = true) {
|
|
155
|
-
if (this.pool) {
|
|
156
|
-
return (client || this.pool).query('SELECT * FROM ' + this.table + (where ? (' WHERE ' + where) : '') + (order ? (' ORDER BY ' + order) : '')
|
|
157
|
-
+ (offset ? (' OFFSET ' + offset) : '') + (limit !== undefined ? (' LIMIT ' + limit) : '') + ((client && lock) ? ' FOR UPDATE' : ''), inputs)
|
|
158
|
-
.then(q => q.rows.map(r => this.buildObject(r)));
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
const request = (client || this.poolMssql).request();
|
|
162
|
-
if (where)
|
|
163
|
-
where.match(/(@\d+)/g).forEach((match, i) => request.input(match.substr(1), inputs[i]));
|
|
164
|
-
return request.query('SELECT * FROM ' + this.table + ((client && lock) ? ' WITH (ROWLOCK)' : '') + (where ? (' WHERE ' + where) : '')
|
|
165
|
-
+ (order ? (' ORDER BY ' + order) : '') + (offset !== undefined ? (' OFFSET ' + offset + ' ROWS') : '') + (limit !== undefined ? (' FETCH NEXT ' + limit + ' ROWS ONLY') : ''))
|
|
166
|
-
.then(q => q.recordsets[0].map(r => this.buildObject(r)));
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
getViewCountBy(order, offset, limit, where, inputs = [], client, lock = true) {
|
|
170
|
-
if (this.pool) {
|
|
171
|
-
return (client || this.pool).query('SELECT *, COUNT(*) OVER() AS cnt FROM ' + this.table + (where ? (' WHERE ' + where) : '') + (order ? (' ORDER BY ' + order) : '')
|
|
172
|
-
+ (offset ? (' OFFSET ' + offset) : '') + (limit !== undefined ? (' LIMIT ' + limit) : '') + ((client && lock) ? ' FOR UPDATE' : ''), inputs)
|
|
173
|
-
.then(q => ({
|
|
174
|
-
views: q.rows.map(r => this.buildObject(r)),
|
|
175
|
-
count: q.rows.length ? parseInt(q.rows[0].cnt, 10) : 0
|
|
176
|
-
}));
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
const request = (client || this.poolMssql).request();
|
|
180
|
-
if (where)
|
|
181
|
-
where.match(/(@\d+)/g).forEach((match, i) => request.input(match.substr(1), inputs[i]));
|
|
182
|
-
return Promise.allConcurrent(1)([
|
|
183
|
-
() => request.query('SELECT * FROM ' + this.table + ((client && lock) ? ' WITH (ROWLOCK)' : '') + (where ? (' WHERE ' + where) : '')
|
|
184
|
-
+ (order ? (' ORDER BY ' + order) : '') + (offset !== undefined ? (' OFFSET ' + offset + ' ROWS') : '') + (limit !== undefined ? (' FETCH NEXT ' + limit + ' ROWS ONLY') : '')),
|
|
185
|
-
() => request.query('SELECT COUNT(DISTINCT id) AS cnt FROM ' + this.table + (where ? (' WHERE ' + where) : ''))
|
|
186
|
-
]).then(([q1, q2]) => ({
|
|
187
|
-
views: q1.recordsets[0].map((r) => this.buildObject(r)),
|
|
188
|
-
count: q2.recordsets.length ? q2.recordsets[0].reduce((p, n) => p + n.cnt, 0) : 0
|
|
189
|
-
}));
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
getRowsViewCountBy(rows, order, offset, limit, where, inputs = [], client, lock = true) {
|
|
193
|
-
if (this.pool) {
|
|
194
|
-
return (client || this.pool).query('SELECT ' + rows.map(r => '"' + r + '"').join(',') + ', COUNT(*) OVER() AS cnt FROM ' + this.table + (where ? (' WHERE ' + where) : '') + (order ? (' ORDER BY ' + order) : '')
|
|
195
|
-
+ (offset ? (' OFFSET ' + offset) : '') + (limit !== undefined ? (' LIMIT ' + limit) : '') + ((client && lock) ? ' FOR UPDATE' : ''), inputs)
|
|
196
|
-
.then(q => ({
|
|
197
|
-
views: q.rows.map(r => this.buildObject(r)),
|
|
198
|
-
count: q.rows.length ? parseInt(q.rows[0].cnt, 10) : 0
|
|
199
|
-
}));
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
const request = (client || this.poolMssql).request();
|
|
203
|
-
if (where)
|
|
204
|
-
where.match(/(@\d+)/g).forEach((match, i) => request.input(match.substr(1), inputs[i]));
|
|
205
|
-
return Promise.allConcurrent(1)([
|
|
206
|
-
() => request.query('SELECT ' + rows.map(r => '"' + r + '"').join(',') + ' FROM ' + this.table
|
|
207
|
-
+ ((client && lock) ? ' WITH (ROWLOCK)' : '') + (where ? (' WHERE ' + where) : '') + (order ? (' ORDER BY ' + order) : '')
|
|
208
|
-
+ (offset !== undefined ? (' OFFSET ' + offset + ' ROWS') : '') + (limit !== undefined ? (' FETCH NEXT ' + limit + ' ROWS ONLY') : '')),
|
|
209
|
-
() => request.query('SELECT COUNT(DISTINCT id) AS cnt FROM ' + this.table + (where ? (' WHERE ' + where) : ''))
|
|
210
|
-
]).then(([q1, q2]) => ({
|
|
211
|
-
views: q1.recordsets[0].map((r) => this.buildObject(r)),
|
|
212
|
-
count: q2.recordsets.length ? q2.recordsets[0].reduce((p, n) => p + n.cnt, 0) : 0
|
|
213
|
-
}));
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
archive(id, replacedById, client) {
|
|
217
|
-
if (this.pool) {
|
|
218
|
-
return client.query('UPDATE ' + this.table + ' SET "archivedOn"=now(),replaced_by_id=$1 WHERE id=$2', [replacedById, id]);
|
|
219
|
-
}
|
|
220
|
-
else {
|
|
221
|
-
const request = client.request();
|
|
222
|
-
request.input('1', replacedById);
|
|
223
|
-
request.input('2', id);
|
|
224
|
-
return request.query('UPDATE ' + this.table + ' SET "archivedOn"=now(),replaced_by_id=@1 WHERE id=@2');
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
delete(id, client) {
|
|
228
|
-
if (this.pool) {
|
|
229
|
-
return client.query('DELETE FROM ' + this.table + ' WHERE id=$1', [id]);
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
const request = client.request();
|
|
233
|
-
request.input('1', id);
|
|
234
|
-
return request.query('DELETE FROM ' + this.table + ' WHERE id=@1');
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
exports.ModelDao = ModelDao;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ModelDao = exports.promiseAllStepN = void 0;
|
|
4
|
+
function promiseAllStepN(n, list) {
|
|
5
|
+
if (!list || !list.length)
|
|
6
|
+
return Promise.resolve([]);
|
|
7
|
+
const tail = list.splice(n);
|
|
8
|
+
const head = list;
|
|
9
|
+
const resolved = [];
|
|
10
|
+
let processed = 0;
|
|
11
|
+
return new Promise(resolve => {
|
|
12
|
+
head.forEach(x => {
|
|
13
|
+
const res = x();
|
|
14
|
+
resolved.push(res);
|
|
15
|
+
res.then((y) => {
|
|
16
|
+
runNext();
|
|
17
|
+
return y;
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
function runNext() {
|
|
21
|
+
if (processed === tail.length) {
|
|
22
|
+
resolve(Promise.all(resolved));
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
resolved.push(tail[processed]().then((x) => {
|
|
26
|
+
runNext();
|
|
27
|
+
return x;
|
|
28
|
+
}));
|
|
29
|
+
processed++;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
exports.promiseAllStepN = promiseAllStepN;
|
|
35
|
+
Promise.allConcurrent = (n) => (list) => promiseAllStepN(n, list);
|
|
36
|
+
class Dao {
|
|
37
|
+
constructor(pool, poolMssql, logger, table, nFields, updateDefinition) {
|
|
38
|
+
this.pool = pool;
|
|
39
|
+
this.poolMssql = poolMssql;
|
|
40
|
+
this.logger = logger;
|
|
41
|
+
this.table = table;
|
|
42
|
+
this.nFields = nFields;
|
|
43
|
+
this.updateDefinition = updateDefinition;
|
|
44
|
+
}
|
|
45
|
+
groupResultSet(q, key) {
|
|
46
|
+
const storage = {};
|
|
47
|
+
for (let i = 0; i < q.length; i++) {
|
|
48
|
+
storage[q[i][key]] = storage[q[i][key]] || [];
|
|
49
|
+
storage[q[i][key]].push(q[i]);
|
|
50
|
+
}
|
|
51
|
+
return Object.getOwnPropertyNames(storage).map(k => storage[k]);
|
|
52
|
+
}
|
|
53
|
+
groupResultSetBy(q, key) {
|
|
54
|
+
const storage = {};
|
|
55
|
+
for (let i = 0; i < q.length; i++) {
|
|
56
|
+
storage[key(q[i])] = storage[key(q[i])] || [];
|
|
57
|
+
storage[key(q[i])].push(q[i]);
|
|
58
|
+
}
|
|
59
|
+
return Object.getOwnPropertyNames(storage).map(k => storage[k]);
|
|
60
|
+
}
|
|
61
|
+
update(instance, client) {
|
|
62
|
+
if (instance.archivedOn)
|
|
63
|
+
return Promise.reject('Record archived!');
|
|
64
|
+
instance.updatedOn = new Date();
|
|
65
|
+
if (this.pool) {
|
|
66
|
+
const props = this.serialize(instance);
|
|
67
|
+
props.push(instance.id);
|
|
68
|
+
return client.query('UPDATE ' + this.table + ' SET ' + this.updateDefinition + ' WHERE id=$' + (this.nFields + 1), props).then(() => instance.id);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
const request = client.request();
|
|
72
|
+
this.serialize(instance, request);
|
|
73
|
+
request.input(String(this.nFields + 1), instance.id);
|
|
74
|
+
return request.query('UPDATE ' + this.table + ' SET ' + this.updateDefinition + ' WHERE id=@' + (this.nFields + 1)).then(() => instance.id);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
replace(instance, client) {
|
|
78
|
+
if (instance.archivedOn)
|
|
79
|
+
return Promise.reject('Record archived!');
|
|
80
|
+
return this.create({ ...instance, replaced_id: instance.id }, client).then(id => {
|
|
81
|
+
return this.archive(instance.id, id, client).then(() => id);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
create(instance, client) {
|
|
85
|
+
instance.createdOn = instance.updatedOn = new Date();
|
|
86
|
+
if (this.pool) {
|
|
87
|
+
const props = this.serialize(instance);
|
|
88
|
+
return (client || this.pool).query('INSERT INTO ' + this.table + '(' + this.updateDefinition.replace(/=\$\d+/g, '').replace(/=[^)]+\)/g, '') + ')'
|
|
89
|
+
+ ' VALUES(' + new Array(this.nFields).fill(undefined).map((_, i) => '$' + (i + 1)).join(',') + ') RETURNING id', props).then(q => {
|
|
90
|
+
const idNum = parseInt(q.rows[0].id, 10);
|
|
91
|
+
if (String(idNum) !== q.rows[0].id)
|
|
92
|
+
return q.rows[0].id;
|
|
93
|
+
return idNum;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const request = (client || this.poolMssql).request();
|
|
98
|
+
this.serialize(instance, request);
|
|
99
|
+
return request.query('INSERT INTO ' + this.table + '(' + this.updateDefinition.replace(/=@\d+/g, '').replace(/=[^)]+\)/g, '') + ')'
|
|
100
|
+
+ ' VALUES(' + new Array(this.nFields).fill(undefined).map((_, i) => '@' + (i + 1)).join(',') + '); SELECT SCOPE_IDENTITY() AS id').then(q => {
|
|
101
|
+
return q.recordsets[0][0].id || instance.id;
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
createSeveral(instances, client) {
|
|
106
|
+
if (!instances.length)
|
|
107
|
+
return Promise.resolve([]);
|
|
108
|
+
const now = new Date();
|
|
109
|
+
instances.forEach(instance => instance.updatedOn = now);
|
|
110
|
+
const props = [].concat.apply([], instances.map(instance => this.serialize(instance)));
|
|
111
|
+
return (client || this.pool).query('INSERT INTO ' + this.table + '(' + this.updateDefinition.replace(/=\$\d+/g, '').replace(/=[^)]+\)/g, '') + ')'
|
|
112
|
+
+ ' VALUES' + instances.map((_, j) => ('(' + new Array(this.nFields).fill(undefined).map((__, i) => '$' + (j * this.nFields + i + 1)).join(', ') + ')')).join(',') + ' RETURNING id', props).then(q => q.rows.map(r => {
|
|
113
|
+
const idNum = parseInt(r.id, 10);
|
|
114
|
+
if (String(idNum) !== q.rows[0].id)
|
|
115
|
+
return r.id;
|
|
116
|
+
return idNum;
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
class ModelDao extends Dao {
|
|
121
|
+
get(id, client, lock = true) {
|
|
122
|
+
if (this.pool) {
|
|
123
|
+
return (client || this.pool).query('SELECT * FROM ' + this.table + ' WHERE id=$1' + ((client && lock) ? ' FOR UPDATE' : ''), [id]).then(q => this.buildObject(q.rows[0]));
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
const request = (client || this.poolMssql).request();
|
|
127
|
+
request.input('1', id);
|
|
128
|
+
return request.query('SELECT * FROM ' + this.table + ((client && lock) ? ' WITH (ROWLOCK)' : '') + ' WHERE id=@1').then(q => this.buildObject(q.recordsets[0][0]));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
count(where, inputs = [], client) {
|
|
132
|
+
if (this.pool) {
|
|
133
|
+
return (client || this.pool).query('SELECT count(*) AS cnt FROM ' + this.table + (where ? (' WHERE ' + where) : ''), inputs).then(q => parseInt(q.rows[0].cnt, 10));
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
const request = (client || this.poolMssql).request();
|
|
137
|
+
if (where)
|
|
138
|
+
where.match(/(@\d+)/g).forEach((match, i) => request.input(match.substr(1), inputs[i]));
|
|
139
|
+
return request.query('SELECT count(*) AS cnt FROM ' + this.table + (where ? (' WHERE ' + where) : '')).then(q => q.recordsets[0][0].cnt);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
getList(ids, client, lock = true) {
|
|
143
|
+
if (this.pool) {
|
|
144
|
+
return (client || this.pool).query('SELECT * FROM ' + this.table + ' WHERE id=ANY($1)' + ((client && lock) ? ' FOR UPDATE' : ''), [ids])
|
|
145
|
+
.then(q => q.rows.map(r => this.buildObject(r)));
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
const request = (client || this.poolMssql).request();
|
|
149
|
+
return request.query('SELECT * FROM ' + this.table + ((client && lock) ? ' WITH (ROWLOCK)' : '') + ' WHERE id IN ('
|
|
150
|
+
+ (ids.length > 0 ? (typeof ids[0] === 'string' ? '\'' + ids.join('\',\'') + '\'' : ids.join(',')) : '') + ')')
|
|
151
|
+
.then(q => q.recordsets[0].map(r => this.buildObject(r)));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
getAllBy(order, offset, limit, where, inputs = [], client, lock = true) {
|
|
155
|
+
if (this.pool) {
|
|
156
|
+
return (client || this.pool).query('SELECT * FROM ' + this.table + (where ? (' WHERE ' + where) : '') + (order ? (' ORDER BY ' + order) : '')
|
|
157
|
+
+ (offset ? (' OFFSET ' + offset) : '') + (limit !== undefined ? (' LIMIT ' + limit) : '') + ((client && lock) ? ' FOR UPDATE' : ''), inputs)
|
|
158
|
+
.then(q => q.rows.map(r => this.buildObject(r)));
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
const request = (client || this.poolMssql).request();
|
|
162
|
+
if (where)
|
|
163
|
+
where.match(/(@\d+)/g).forEach((match, i) => request.input(match.substr(1), inputs[i]));
|
|
164
|
+
return request.query('SELECT * FROM ' + this.table + ((client && lock) ? ' WITH (ROWLOCK)' : '') + (where ? (' WHERE ' + where) : '')
|
|
165
|
+
+ (order ? (' ORDER BY ' + order) : '') + (offset !== undefined ? (' OFFSET ' + offset + ' ROWS') : '') + (limit !== undefined ? (' FETCH NEXT ' + limit + ' ROWS ONLY') : ''))
|
|
166
|
+
.then(q => q.recordsets[0].map(r => this.buildObject(r)));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
getViewCountBy(order, offset, limit, where, inputs = [], client, lock = true) {
|
|
170
|
+
if (this.pool) {
|
|
171
|
+
return (client || this.pool).query('SELECT *, COUNT(*) OVER() AS cnt FROM ' + this.table + (where ? (' WHERE ' + where) : '') + (order ? (' ORDER BY ' + order) : '')
|
|
172
|
+
+ (offset ? (' OFFSET ' + offset) : '') + (limit !== undefined ? (' LIMIT ' + limit) : '') + ((client && lock) ? ' FOR UPDATE' : ''), inputs)
|
|
173
|
+
.then(q => ({
|
|
174
|
+
views: q.rows.map(r => this.buildObject(r)),
|
|
175
|
+
count: q.rows.length ? parseInt(q.rows[0].cnt, 10) : 0
|
|
176
|
+
}));
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
const request = (client || this.poolMssql).request();
|
|
180
|
+
if (where)
|
|
181
|
+
where.match(/(@\d+)/g).forEach((match, i) => request.input(match.substr(1), inputs[i]));
|
|
182
|
+
return Promise.allConcurrent(1)([
|
|
183
|
+
() => request.query('SELECT * FROM ' + this.table + ((client && lock) ? ' WITH (ROWLOCK)' : '') + (where ? (' WHERE ' + where) : '')
|
|
184
|
+
+ (order ? (' ORDER BY ' + order) : '') + (offset !== undefined ? (' OFFSET ' + offset + ' ROWS') : '') + (limit !== undefined ? (' FETCH NEXT ' + limit + ' ROWS ONLY') : '')),
|
|
185
|
+
() => request.query('SELECT COUNT(DISTINCT id) AS cnt FROM ' + this.table + (where ? (' WHERE ' + where) : ''))
|
|
186
|
+
]).then(([q1, q2]) => ({
|
|
187
|
+
views: q1.recordsets[0].map((r) => this.buildObject(r)),
|
|
188
|
+
count: q2.recordsets.length ? q2.recordsets[0].reduce((p, n) => p + n.cnt, 0) : 0
|
|
189
|
+
}));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
getRowsViewCountBy(rows, order, offset, limit, where, inputs = [], client, lock = true) {
|
|
193
|
+
if (this.pool) {
|
|
194
|
+
return (client || this.pool).query('SELECT ' + rows.map(r => '"' + r + '"').join(',') + ', COUNT(*) OVER() AS cnt FROM ' + this.table + (where ? (' WHERE ' + where) : '') + (order ? (' ORDER BY ' + order) : '')
|
|
195
|
+
+ (offset ? (' OFFSET ' + offset) : '') + (limit !== undefined ? (' LIMIT ' + limit) : '') + ((client && lock) ? ' FOR UPDATE' : ''), inputs)
|
|
196
|
+
.then(q => ({
|
|
197
|
+
views: q.rows.map(r => this.buildObject(r)),
|
|
198
|
+
count: q.rows.length ? parseInt(q.rows[0].cnt, 10) : 0
|
|
199
|
+
}));
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
const request = (client || this.poolMssql).request();
|
|
203
|
+
if (where)
|
|
204
|
+
where.match(/(@\d+)/g).forEach((match, i) => request.input(match.substr(1), inputs[i]));
|
|
205
|
+
return Promise.allConcurrent(1)([
|
|
206
|
+
() => request.query('SELECT ' + rows.map(r => '"' + r + '"').join(',') + ' FROM ' + this.table
|
|
207
|
+
+ ((client && lock) ? ' WITH (ROWLOCK)' : '') + (where ? (' WHERE ' + where) : '') + (order ? (' ORDER BY ' + order) : '')
|
|
208
|
+
+ (offset !== undefined ? (' OFFSET ' + offset + ' ROWS') : '') + (limit !== undefined ? (' FETCH NEXT ' + limit + ' ROWS ONLY') : '')),
|
|
209
|
+
() => request.query('SELECT COUNT(DISTINCT id) AS cnt FROM ' + this.table + (where ? (' WHERE ' + where) : ''))
|
|
210
|
+
]).then(([q1, q2]) => ({
|
|
211
|
+
views: q1.recordsets[0].map((r) => this.buildObject(r)),
|
|
212
|
+
count: q2.recordsets.length ? q2.recordsets[0].reduce((p, n) => p + n.cnt, 0) : 0
|
|
213
|
+
}));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
archive(id, replacedById, client) {
|
|
217
|
+
if (this.pool) {
|
|
218
|
+
return client.query('UPDATE ' + this.table + ' SET "archivedOn"=now(),replaced_by_id=$1 WHERE id=$2', [replacedById, id]);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
const request = client.request();
|
|
222
|
+
request.input('1', replacedById);
|
|
223
|
+
request.input('2', id);
|
|
224
|
+
return request.query('UPDATE ' + this.table + ' SET "archivedOn"=now(),replaced_by_id=@1 WHERE id=@2');
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
delete(id, client) {
|
|
228
|
+
if (this.pool) {
|
|
229
|
+
return client.query('DELETE FROM ' + this.table + ' WHERE id=$1', [id]);
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
const request = client.request();
|
|
233
|
+
request.input('1', id);
|
|
234
|
+
return request.query('DELETE FROM ' + this.table + ' WHERE id=@1');
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
exports.ModelDao = ModelDao;
|