pg-mvc-service 1.0.28 → 2.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/dist/models/TableModel.js +70 -160
- package/dist/models/Utils/MessageUtil.js +58 -0
- package/package.json +1 -1
- package/src/models/TableModel.ts +82 -168
- package/src/models/Utils/MessageUtil.ts +60 -0
|
@@ -20,6 +20,7 @@ const ValidateClient_1 = __importDefault(require("./ValidateClient"));
|
|
|
20
20
|
const Exception_1 = require("../exceptions/Exception");
|
|
21
21
|
const ExpressionClient_1 = __importDefault(require("./ExpressionClient"));
|
|
22
22
|
const UpdateExpression_1 = __importDefault(require("./SqlUtils/UpdateExpression"));
|
|
23
|
+
const MessageUtil_1 = __importDefault(require("./Utils/MessageUtil"));
|
|
23
24
|
class TableModel {
|
|
24
25
|
get DbName() { return this.dbName; }
|
|
25
26
|
get TableName() {
|
|
@@ -59,7 +60,12 @@ class TableModel {
|
|
|
59
60
|
get createSqlFromJoinWhere() {
|
|
60
61
|
let sql = ` FROM ${this.TableName} as "${this.TableAlias}"`;
|
|
61
62
|
for (const join of this.joinConditions) {
|
|
62
|
-
|
|
63
|
+
const joins = {
|
|
64
|
+
inner: ' INNER JOIN',
|
|
65
|
+
left: ' LEFT OUTER JOIN',
|
|
66
|
+
full: ' FULL OUTER JOIN',
|
|
67
|
+
};
|
|
68
|
+
sql += joins[join.type];
|
|
63
69
|
sql += ` ${join.model.TableName} as "${join.model.TableAlias}" ON `;
|
|
64
70
|
const query = WhereExpression_1.default.createCondition(join.conditions, this, this.vars.length + 1);
|
|
65
71
|
sql += query.expression;
|
|
@@ -113,71 +119,14 @@ class TableModel {
|
|
|
113
119
|
this.groupExpression = [];
|
|
114
120
|
this.sortExpression = [];
|
|
115
121
|
this.vars = [];
|
|
116
|
-
this.
|
|
117
|
-
'string': '{name} should be entered as a string or number type.',
|
|
118
|
-
'string[]': '{name} should be entered as an array of string or number types.',
|
|
119
|
-
'uuid': '{name} should be entered as a UUID.',
|
|
120
|
-
'uuid[]': '{name} should be entered as an array of UUIDs.',
|
|
121
|
-
'integer': '{name} should be entered as a number.',
|
|
122
|
-
'integer[]': '{name} should be entered as an array of numbers.',
|
|
123
|
-
'real': '{name} should be entered as a number.',
|
|
124
|
-
'real[]': '{name} should be entered as an array of numbers.',
|
|
125
|
-
'bool': '{name} should be entered as a bool type, "true", "false", 0, or 1.',
|
|
126
|
-
'bool[]': '{name} should be entered as an array of bool types, "true", "false", 0, or 1.',
|
|
127
|
-
'date': '{name} should be entered in "YYYY-MM-DD" or "YYYY-MM-DD hh:mi:ss" format or as a Date type.',
|
|
128
|
-
'date[]': '{name} should be entered as an array of dates in "YYYY-MM-DD" or "YYYY-MM-DD hh:mi:ss" format or as Date types.',
|
|
129
|
-
'time': '{name} should be entered in "hh:mi" format or "hh:mi:ss" format.',
|
|
130
|
-
'time[]': '{name} should be entered as an array of times in "hh:mi" format or "hh:mi:ss" format.',
|
|
131
|
-
'timestamp': '{name} should be entered in "YYYY-MM-DD" format, "YYYY-MM-DD hh:mi:ss" format, "YYYY-MM-DDThh:mi:ss" format, or as a Date type.',
|
|
132
|
-
'timestamp[]': '{name} should be entered as an array of timestamps in "YYYY-MM-DD" format, "YYYY-MM-DD hh:mi:ss" format, "YYYY-MM-DDThh:mi:ss" format, or as Date types.',
|
|
133
|
-
'json': '{name} should be entered as an Object or JSON string.',
|
|
134
|
-
'json[]': '{name} should be entered as an array of Objects or JSON strings.',
|
|
135
|
-
'jsonb': '{name} should be entered as an Object or JSON string.',
|
|
136
|
-
'jsonb[]': '{name} should be entered as an array of Objects or JSON strings.',
|
|
137
|
-
'length': '{name} should be entered within {length} characters.',
|
|
138
|
-
'null': '{name} is not allowed to be null.',
|
|
139
|
-
'notInput': 'Please enter {name}.',
|
|
140
|
-
'fk': 'The value of {name} does not exist in the table.',
|
|
141
|
-
'idNotExist': 'The specified ID({id}) does not exist in the table.',
|
|
142
|
-
'find': 'The specified data does not exist in the table. ({pks})'
|
|
143
|
-
};
|
|
144
|
-
this.errorMessageJapan = {
|
|
145
|
-
'string': '{name}はstringかnumberで入力してください。',
|
|
146
|
-
'string[]': '{name}はstringかnumberの配列で入力してください。',
|
|
147
|
-
'uuid': '{name}はuuidで入力してください。',
|
|
148
|
-
'uuid[]': '{name}はuuidの配列で入力してください。',
|
|
149
|
-
'integer': '{name}はnumberか半角数字のstring型で入力してください。',
|
|
150
|
-
'integer[]': '{name}はnumberか半角数字のstring型の配列で入力してください。',
|
|
151
|
-
'real': '{name}はnumberか半角数字のstring型で入力してください。',
|
|
152
|
-
'real[]': '{name}はnumberか半角数字のstring型の配列で入力してください。',
|
|
153
|
-
'bool': '{name}はbool型、"true"、"false"、0、または1で入力してください。',
|
|
154
|
-
'bool[]': '{name}はbool型、"true"、"false"、0、または1の配列で入力してください。',
|
|
155
|
-
'date': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、またはDate型で入力してください。',
|
|
156
|
-
'date[]': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、またはDate型の配列で入力してください。',
|
|
157
|
-
'time': '{name}は"hh:mi"形式または"hh:mi:ss"形式で入力してください。',
|
|
158
|
-
'time[]': '{name}は"hh:mi"形式または"hh:mi:ss"形式の配列で入力してください。',
|
|
159
|
-
'timestamp': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、"YYYY-MM-DDThh:mi:ss"形式、またはDate型で入力してください。',
|
|
160
|
-
'timestamp[]': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、"YYYY-MM-DDThh:mi:ss"形式、またはDate型の配列で入力してください。',
|
|
161
|
-
'json': '{name}はObject形またはJSON文字列で入力してください。',
|
|
162
|
-
'json[]': '{name}はObject形またはJSON文字列の配列で入力してください。',
|
|
163
|
-
'jsonb': '{name}はObject形またはJSON文字列で入力してください。',
|
|
164
|
-
'jsonb[]': '{name}はObject形またはJSON文字列の配列で入力してください。',
|
|
165
|
-
'length': '{name}は{length}文字以内で入力してください。',
|
|
166
|
-
'null': '{name}はnullを許可されていません。',
|
|
167
|
-
'notInput': '{name}を入力してください。',
|
|
168
|
-
'fk': '{name}の値がテーブルに存在しません。',
|
|
169
|
-
'idNotExist': '指定されたID({id})はテーブルに存在しません。',
|
|
170
|
-
'find': '指定されたデータはテーブルに存在しません。({pks})'
|
|
171
|
-
};
|
|
172
|
-
this.errorMessages = process.env.TZ === 'Asia/Tokyo' ? this.errorMessageJapan : this.errorMessageEnglish;
|
|
122
|
+
this.errorMessages = process.env.TZ === 'Asia/Tokyo' ? MessageUtil_1.default.optionErrorMessageJapan : MessageUtil_1.default.optionErrorMessageEnglish;
|
|
173
123
|
this.client = client;
|
|
174
124
|
if (tableAlias !== undefined && tableAlias.trim() !== '') {
|
|
175
125
|
this.tableAlias = tableAlias;
|
|
176
126
|
}
|
|
177
127
|
}
|
|
178
|
-
|
|
179
|
-
return __awaiter(this, arguments, void 0, function* (
|
|
180
|
-
ValidateValueUtil_1.default.validateId(this.Columns, id);
|
|
128
|
+
find(pkOrId_1) {
|
|
129
|
+
return __awaiter(this, arguments, void 0, function* (pkOrId, selectColumns = "*", selectExpressions = null, keyFormat = 'snake') {
|
|
181
130
|
let selects = [];
|
|
182
131
|
if (selectColumns == "*") {
|
|
183
132
|
for (const key of Object.keys(this.Columns)) {
|
|
@@ -194,32 +143,16 @@ class TableModel {
|
|
|
194
143
|
selects.push(`${expression.expression} as "${expression.alias}"`);
|
|
195
144
|
}
|
|
196
145
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
find(pk_1) {
|
|
203
|
-
return __awaiter(this, arguments, void 0, function* (pk, selectColumns = "*", selectExpressions = null, keyFormat = 'snake') {
|
|
204
|
-
let selects = [];
|
|
205
|
-
if (selectColumns == "*") {
|
|
206
|
-
for (const key of Object.keys(this.Columns)) {
|
|
207
|
-
selects.push(SelectExpression_1.default.create({ model: this, name: key }, null, null, keyFormat));
|
|
208
|
-
}
|
|
146
|
+
let query;
|
|
147
|
+
if (typeof pkOrId === 'string' || typeof pkOrId === 'number' || typeof pkOrId === 'boolean') {
|
|
148
|
+
ValidateValueUtil_1.default.validateId(this.Columns, pkOrId);
|
|
149
|
+
query = WhereExpression_1.default.createConditionPk(this, { id: pkOrId });
|
|
209
150
|
}
|
|
210
|
-
else
|
|
211
|
-
|
|
212
|
-
selects.push(SelectExpression_1.default.create({ model: this, name: key }, null, null, keyFormat));
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
if (selectExpressions != null) {
|
|
216
|
-
for (const expression of selectExpressions) {
|
|
217
|
-
selects.push(`${expression.expression} as "${expression.alias}"`);
|
|
218
|
-
}
|
|
151
|
+
else {
|
|
152
|
+
query = WhereExpression_1.default.createConditionPk(this, pkOrId);
|
|
219
153
|
}
|
|
220
|
-
const {
|
|
221
|
-
|
|
222
|
-
let datas = yield this.executeQuery(sql, vars);
|
|
154
|
+
const sql = `SELECT ${selects.join(',')} FROM ${this.TableName} WHERE ${query.expression}`;
|
|
155
|
+
let datas = yield this.executeQuery(sql, query.vars);
|
|
223
156
|
return datas.rowCount == 0 ? null : datas.rows[0];
|
|
224
157
|
});
|
|
225
158
|
}
|
|
@@ -395,7 +328,7 @@ class TableModel {
|
|
|
395
328
|
return { datas: data.rows, count: Number(countData.rows[0].count), lastPage: Math.ceil(Number(countData.rows[0].count) / this.PageCount) };
|
|
396
329
|
});
|
|
397
330
|
}
|
|
398
|
-
throwException(code, type, columnName,
|
|
331
|
+
throwException(code, type, columnName, value) {
|
|
399
332
|
var _a;
|
|
400
333
|
const column = this.getColumn(columnName);
|
|
401
334
|
let message = this.errorMessages[type];
|
|
@@ -447,6 +380,16 @@ class TableModel {
|
|
|
447
380
|
}
|
|
448
381
|
// 外部キー制約チェック
|
|
449
382
|
if (isInsert) {
|
|
383
|
+
for (const key in this.Columns) {
|
|
384
|
+
const column = this.getColumn(key);
|
|
385
|
+
const name = (column.alias === undefined || column.alias === '') ? key : column.alias;
|
|
386
|
+
if (options[key] === undefined || options[key] === null) {
|
|
387
|
+
// Null許容されていないカラムにNULLを入れようとしているか?
|
|
388
|
+
if (column.attribute === "primary" || column.attribute === "noDefault") {
|
|
389
|
+
this.throwException("005", "notInput", key, options[key]);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
450
393
|
for (const ref of this.References) {
|
|
451
394
|
const refValues = ref.columns.map(col => options[col.target]);
|
|
452
395
|
// 全ての値がnullの場合はスキップ
|
|
@@ -456,49 +399,22 @@ class TableModel {
|
|
|
456
399
|
// 一部の値がnullの場合はエラー
|
|
457
400
|
if (refValues.some(value => value === null || value === undefined)) {
|
|
458
401
|
const name = ref.columns.map(col => { var _a; return (_a = this.getColumn(col.target).alias) !== null && _a !== void 0 ? _a : this.getColumn(col.target).columnName; }).join(',');
|
|
459
|
-
throw new Exception_1.UnprocessableException("
|
|
402
|
+
throw new Exception_1.UnprocessableException("006", this.errorMessages.null.replace('{name}', name));
|
|
460
403
|
}
|
|
461
404
|
let refIndex = 1;
|
|
462
405
|
const sql = `SELECT COUNT(*) as count FROM ${ref.table} WHERE ${ref.columns.map(col => `${col.ref} = $${refIndex++}`).join(" AND ")}`;
|
|
463
406
|
const datas = yield this.clientQuery(sql, refValues);
|
|
464
407
|
if (datas.rows[0].count == "0") {
|
|
465
408
|
const name = ref.columns.map(col => { var _a; return (_a = this.getColumn(col.target).alias) !== null && _a !== void 0 ? _a : this.getColumn(col.target).columnName; }).join(',');
|
|
466
|
-
throw new Exception_1.DbConflictException("
|
|
409
|
+
throw new Exception_1.DbConflictException("007", this.errorMessages.fk.replace('{name}', name));
|
|
467
410
|
}
|
|
468
411
|
}
|
|
469
412
|
}
|
|
470
413
|
});
|
|
471
414
|
}
|
|
472
|
-
|
|
473
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
474
|
-
for (const key in this.Columns) {
|
|
475
|
-
const column = this.getColumn(key);
|
|
476
|
-
const name = (column.alias === undefined || column.alias === '') ? key : column.alias;
|
|
477
|
-
if (options[key] === undefined || options[key] === null) {
|
|
478
|
-
// Null許容されていないカラムにNULLを入れようとしているか?
|
|
479
|
-
if (column.attribute === "primary" || column.attribute === "noDefault") {
|
|
480
|
-
this.throwException("101", "notInput", key, options[key]);
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
validateUpdate(options) {
|
|
487
|
-
return __awaiter(this, void 0, void 0, function* () { });
|
|
488
|
-
}
|
|
489
|
-
validateUpdateId(id, options) {
|
|
490
|
-
return __awaiter(this, void 0, void 0, function* () { });
|
|
491
|
-
}
|
|
492
|
-
validateDelete() {
|
|
493
|
-
return __awaiter(this, void 0, void 0, function* () { });
|
|
494
|
-
}
|
|
495
|
-
validateDeleteId(id) {
|
|
496
|
-
return __awaiter(this, void 0, void 0, function* () { });
|
|
497
|
-
}
|
|
498
|
-
executeInsert(options) {
|
|
415
|
+
insert(options) {
|
|
499
416
|
return __awaiter(this, void 0, void 0, function* () {
|
|
500
417
|
yield this.validateOptions(options, true);
|
|
501
|
-
yield this.validateInsert(options);
|
|
502
418
|
const columns = [];
|
|
503
419
|
const vars = [];
|
|
504
420
|
for (const [key, value] of Object.entries(options)) {
|
|
@@ -513,10 +429,47 @@ class TableModel {
|
|
|
513
429
|
yield this.executeQuery(sql, vars);
|
|
514
430
|
});
|
|
515
431
|
}
|
|
432
|
+
update(pkOrId, options) {
|
|
433
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
434
|
+
var _a;
|
|
435
|
+
yield this.validateOptions(options, false);
|
|
436
|
+
const updateSetQuery = UpdateExpression_1.default.createUpdateSet(this, options);
|
|
437
|
+
let whereQuery;
|
|
438
|
+
if (typeof pkOrId === 'string' || typeof pkOrId === 'number' || typeof pkOrId === 'boolean') {
|
|
439
|
+
ValidateValueUtil_1.default.validateId(this.Columns, pkOrId);
|
|
440
|
+
whereQuery = WhereExpression_1.default.createConditionPk(this, { id: pkOrId }, updateSetQuery.vars);
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
whereQuery = WhereExpression_1.default.createConditionPk(this, pkOrId, updateSetQuery.vars);
|
|
444
|
+
}
|
|
445
|
+
const sql = updateSetQuery.expression + ' WHERE ' + whereQuery.expression;
|
|
446
|
+
const data = yield this.executeQuery(sql, whereQuery.vars);
|
|
447
|
+
if (data.rowCount !== 1) {
|
|
448
|
+
throw new Exception_1.UnprocessableException("201", this.errorMessages.find.replace('{pks}', ((_a = whereQuery.vars) !== null && _a !== void 0 ? _a : []).join(',')));
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
delete(pkOrId) {
|
|
453
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
454
|
+
var _a;
|
|
455
|
+
let whereQuery;
|
|
456
|
+
if (typeof pkOrId === 'string' || typeof pkOrId === 'number' || typeof pkOrId === 'boolean') {
|
|
457
|
+
ValidateValueUtil_1.default.validateId(this.Columns, pkOrId);
|
|
458
|
+
whereQuery = WhereExpression_1.default.createConditionPk(this, { id: pkOrId });
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
whereQuery = WhereExpression_1.default.createConditionPk(this, pkOrId);
|
|
462
|
+
}
|
|
463
|
+
const sql = `DELETE FROM ${this.TableName} WHERE ${whereQuery.expression}`;
|
|
464
|
+
const data = yield this.executeQuery(sql, whereQuery.vars);
|
|
465
|
+
if (data.rowCount !== 1) {
|
|
466
|
+
throw new Exception_1.UnprocessableException("301", this.errorMessages.find.replace('{pks}', ((_a = whereQuery.vars) !== null && _a !== void 0 ? _a : []).join(',')));
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
}
|
|
516
470
|
executeUpdate(options) {
|
|
517
471
|
return __awaiter(this, void 0, void 0, function* () {
|
|
518
472
|
yield this.validateOptions(options, false);
|
|
519
|
-
yield this.validateUpdate(options);
|
|
520
473
|
const updateExpressions = [];
|
|
521
474
|
for (const [key, value] of Object.entries(options)) {
|
|
522
475
|
const column = this.getColumn(key);
|
|
@@ -544,40 +497,8 @@ class TableModel {
|
|
|
544
497
|
return data.rowCount;
|
|
545
498
|
});
|
|
546
499
|
}
|
|
547
|
-
executeUpdateId(id, options) {
|
|
548
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
549
|
-
var _a;
|
|
550
|
-
ValidateValueUtil_1.default.validateId(this.Columns, id);
|
|
551
|
-
yield this.validateOptions(options, false);
|
|
552
|
-
yield this.validateUpdateId(id, options);
|
|
553
|
-
yield this.validateUpdate(options);
|
|
554
|
-
const updateSetQuery = UpdateExpression_1.default.createUpdateSet(this, options);
|
|
555
|
-
const whereQuery = WhereExpression_1.default.createConditionPk(this, { id: id }, updateSetQuery.vars);
|
|
556
|
-
const sql = updateSetQuery.expression + ' WHERE ' + whereQuery.expression;
|
|
557
|
-
const data = yield this.executeQuery(sql, whereQuery.vars);
|
|
558
|
-
if (data.rowCount !== 1) {
|
|
559
|
-
throw new Exception_1.UnprocessableException("201", this.errorMessages.find.replace('{pks}', ((_a = whereQuery.vars) !== null && _a !== void 0 ? _a : []).join(',')));
|
|
560
|
-
}
|
|
561
|
-
});
|
|
562
|
-
}
|
|
563
|
-
executeUpdateByPk(pk, options) {
|
|
564
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
565
|
-
var _a;
|
|
566
|
-
yield this.validateOptions(options, false);
|
|
567
|
-
// await this.validateUpdateId(id, options);
|
|
568
|
-
yield this.validateUpdate(options);
|
|
569
|
-
const updateSetQuery = UpdateExpression_1.default.createUpdateSet(this, options);
|
|
570
|
-
const whereQuery = WhereExpression_1.default.createConditionPk(this, pk, updateSetQuery.vars);
|
|
571
|
-
const sql = updateSetQuery.expression + ' WHERE ' + whereQuery.expression;
|
|
572
|
-
const data = yield this.executeQuery(sql, whereQuery.vars);
|
|
573
|
-
if (data.rowCount !== 1) {
|
|
574
|
-
throw new Exception_1.UnprocessableException("401", this.errorMessages.find.replace('{pks}', ((_a = whereQuery.vars) !== null && _a !== void 0 ? _a : []).join(',')));
|
|
575
|
-
}
|
|
576
|
-
});
|
|
577
|
-
}
|
|
578
500
|
executeDelete() {
|
|
579
501
|
return __awaiter(this, void 0, void 0, function* () {
|
|
580
|
-
this.validateDelete();
|
|
581
502
|
let sql = `DELETE FROM ${this.TableName} "${this.TableAlias}" `;
|
|
582
503
|
if (this.joinConditions.length > 0) {
|
|
583
504
|
const tables = [];
|
|
@@ -598,17 +519,6 @@ class TableModel {
|
|
|
598
519
|
return datas.rowCount;
|
|
599
520
|
});
|
|
600
521
|
}
|
|
601
|
-
executeDeleteId(id) {
|
|
602
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
603
|
-
ValidateValueUtil_1.default.validateId(this.Columns, id);
|
|
604
|
-
yield this.validateDeleteId(id);
|
|
605
|
-
let sql = `DELETE FROM ${this.TableName} WHERE id = $1`;
|
|
606
|
-
const datas = yield this.executeQuery(sql, [id]);
|
|
607
|
-
if (datas.rowCount !== 1) {
|
|
608
|
-
throw new Exception_1.UnprocessableException("301", this.errorMessages.idNotExist.replace('{id}', id));
|
|
609
|
-
}
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
522
|
executeQuery(param1, vars) {
|
|
613
523
|
return __awaiter(this, void 0, void 0, function* () {
|
|
614
524
|
// 初期化項目
|
|
@@ -1 +1,59 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class MessageUtil {
|
|
4
|
+
}
|
|
5
|
+
MessageUtil.optionErrorMessageEnglish = {
|
|
6
|
+
'string': '{name} should be entered as a string or number type.',
|
|
7
|
+
'string[]': '{name} should be entered as an array of string or number types.',
|
|
8
|
+
'uuid': '{name} should be entered as a UUID.',
|
|
9
|
+
'uuid[]': '{name} should be entered as an array of UUIDs.',
|
|
10
|
+
'integer': '{name} should be entered as a number.',
|
|
11
|
+
'integer[]': '{name} should be entered as an array of numbers.',
|
|
12
|
+
'real': '{name} should be entered as a number.',
|
|
13
|
+
'real[]': '{name} should be entered as an array of numbers.',
|
|
14
|
+
'bool': '{name} should be entered as a bool type, "true", "false", 0, or 1.',
|
|
15
|
+
'bool[]': '{name} should be entered as an array of bool types, "true", "false", 0, or 1.',
|
|
16
|
+
'date': '{name} should be entered in "YYYY-MM-DD" or "YYYY-MM-DD hh:mi:ss" format or as a Date type.',
|
|
17
|
+
'date[]': '{name} should be entered as an array of dates in "YYYY-MM-DD" or "YYYY-MM-DD hh:mi:ss" format or as Date types.',
|
|
18
|
+
'time': '{name} should be entered in "hh:mi" format or "hh:mi:ss" format.',
|
|
19
|
+
'time[]': '{name} should be entered as an array of times in "hh:mi" format or "hh:mi:ss" format.',
|
|
20
|
+
'timestamp': '{name} should be entered in "YYYY-MM-DD" format, "YYYY-MM-DD hh:mi:ss" format, "YYYY-MM-DDThh:mi:ss" format, or as a Date type.',
|
|
21
|
+
'timestamp[]': '{name} should be entered as an array of timestamps in "YYYY-MM-DD" format, "YYYY-MM-DD hh:mi:ss" format, "YYYY-MM-DDThh:mi:ss" format, or as Date types.',
|
|
22
|
+
'json': '{name} should be entered as an Object or JSON string.',
|
|
23
|
+
'json[]': '{name} should be entered as an array of Objects or JSON strings.',
|
|
24
|
+
'jsonb': '{name} should be entered as an Object or JSON string.',
|
|
25
|
+
'jsonb[]': '{name} should be entered as an array of Objects or JSON strings.',
|
|
26
|
+
'length': '{name} should be entered within {length} characters.',
|
|
27
|
+
'null': '{name} is not allowed to be null.',
|
|
28
|
+
'notInput': 'Please enter {name}.',
|
|
29
|
+
'fk': 'The value of {name} does not exist in the table.',
|
|
30
|
+
'find': 'The specified data does not exist in the table. ({pks})'
|
|
31
|
+
};
|
|
32
|
+
MessageUtil.optionErrorMessageJapan = {
|
|
33
|
+
'string': '{name}はstringかnumberで入力してください。',
|
|
34
|
+
'string[]': '{name}はstringかnumberの配列で入力してください。',
|
|
35
|
+
'uuid': '{name}はuuidで入力してください。',
|
|
36
|
+
'uuid[]': '{name}はuuidの配列で入力してください。',
|
|
37
|
+
'integer': '{name}はnumberか半角数字のstring型で入力してください。',
|
|
38
|
+
'integer[]': '{name}はnumberか半角数字のstring型の配列で入力してください。',
|
|
39
|
+
'real': '{name}はnumberか半角数字のstring型で入力してください。',
|
|
40
|
+
'real[]': '{name}はnumberか半角数字のstring型の配列で入力してください。',
|
|
41
|
+
'bool': '{name}はbool型、"true"、"false"、0、または1で入力してください。',
|
|
42
|
+
'bool[]': '{name}はbool型、"true"、"false"、0、または1の配列で入力してください。',
|
|
43
|
+
'date': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、またはDate型で入力してください。',
|
|
44
|
+
'date[]': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、またはDate型の配列で入力してください。',
|
|
45
|
+
'time': '{name}は"hh:mi"形式または"hh:mi:ss"形式で入力してください。',
|
|
46
|
+
'time[]': '{name}は"hh:mi"形式または"hh:mi:ss"形式の配列で入力してください。',
|
|
47
|
+
'timestamp': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、"YYYY-MM-DDThh:mi:ss"形式、またはDate型で入力してください。',
|
|
48
|
+
'timestamp[]': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、"YYYY-MM-DDThh:mi:ss"形式、またはDate型の配列で入力してください。',
|
|
49
|
+
'json': '{name}はObject形またはJSON文字列で入力してください。',
|
|
50
|
+
'json[]': '{name}はObject形またはJSON文字列の配列で入力してください。',
|
|
51
|
+
'jsonb': '{name}はObject形またはJSON文字列で入力してください。',
|
|
52
|
+
'jsonb[]': '{name}はObject形またはJSON文字列の配列で入力してください。',
|
|
53
|
+
'length': '{name}は{length}文字以内で入力してください。',
|
|
54
|
+
'null': '{name}はnullを許可されていません。',
|
|
55
|
+
'notInput': '{name}を入力してください。',
|
|
56
|
+
'fk': '{name}の値がテーブルに存在しません。',
|
|
57
|
+
'find': '指定されたデータはテーブルに存在しません。({pks})'
|
|
58
|
+
};
|
|
59
|
+
exports.default = MessageUtil;
|
package/package.json
CHANGED
package/src/models/TableModel.ts
CHANGED
|
@@ -7,6 +7,7 @@ import ValidateClient from './ValidateClient';
|
|
|
7
7
|
import { DbConflictException, UnprocessableException } from '../exceptions/Exception';
|
|
8
8
|
import ExpressionClient from './ExpressionClient';
|
|
9
9
|
import UpdateExpression from './SqlUtils/UpdateExpression';
|
|
10
|
+
import MessageUtil, { TOptionErrorMessage } from './Utils/MessageUtil';
|
|
10
11
|
|
|
11
12
|
export class TableModel {
|
|
12
13
|
|
|
@@ -69,7 +70,7 @@ export class TableModel {
|
|
|
69
70
|
|
|
70
71
|
private selectExpressions: Array<string> = [];
|
|
71
72
|
private joinConditions: Array<{
|
|
72
|
-
type: 'inner' | 'left',
|
|
73
|
+
type: 'inner' | 'left' | 'full',
|
|
73
74
|
model: TableModel,
|
|
74
75
|
conditions: Array<TNestedCondition>
|
|
75
76
|
}> = [];
|
|
@@ -82,7 +83,12 @@ export class TableModel {
|
|
|
82
83
|
let sql = ` FROM ${this.TableName} as "${this.TableAlias}"`;
|
|
83
84
|
|
|
84
85
|
for (const join of this.joinConditions) {
|
|
85
|
-
|
|
86
|
+
const joins = {
|
|
87
|
+
inner: ' INNER JOIN',
|
|
88
|
+
left: ' LEFT OUTER JOIN',
|
|
89
|
+
full: ' FULL OUTER JOIN',
|
|
90
|
+
}
|
|
91
|
+
sql += joins[join.type];
|
|
86
92
|
sql += ` ${join.model.TableName} as "${join.model.TableAlias}" ON `;
|
|
87
93
|
const query = WhereExpression.createCondition(join.conditions, this, this.vars.length + 1);
|
|
88
94
|
sql += query.expression;
|
|
@@ -138,41 +144,19 @@ export class TableModel {
|
|
|
138
144
|
}
|
|
139
145
|
}
|
|
140
146
|
|
|
141
|
-
public findId<T = {[key: string]: any}>(id: any, selectColumns: Array<string> | "*" | null, selectExpressions: Array<TSelectExpression> | null, keyFormat: TKeyFormat): Promise<T | null>;
|
|
142
|
-
public findId<T = {[key: string]: any}>(id: any, selectColumns: Array<string> | "*" | null, selectExpressions: Array<TSelectExpression> | null): Promise<T | null>;
|
|
143
|
-
public findId<T = {[key: string]: any}>(id: any, selectColumns: Array<string> | "*" | null): Promise<T | null>;
|
|
144
|
-
public findId<T = {[key: string]: any}>(id: any): Promise<T | null>;
|
|
145
|
-
public async findId<T = {[key: string]: any}>(id: any, selectColumns: Array<string> | "*" | null = "*", selectExpressions: Array<TSelectExpression> | null = null, keyFormat: TKeyFormat = 'snake'): Promise<T | null> {
|
|
146
|
-
ValidateValueUtil.validateId(this.Columns, id);
|
|
147
|
-
|
|
148
|
-
let selects: Array<string> = [];
|
|
149
|
-
if (selectColumns == "*") {
|
|
150
|
-
for (const key of Object.keys(this.Columns)) {
|
|
151
|
-
selects.push(SelectExpression.create({model: this, name: key}, null, null, keyFormat));
|
|
152
|
-
}
|
|
153
|
-
} else if (selectColumns != null) {
|
|
154
|
-
for (const key of selectColumns) {
|
|
155
|
-
selects.push(SelectExpression.create({model: this, name: key}, null, null, keyFormat));
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (selectExpressions != null) {
|
|
160
|
-
for (const expression of selectExpressions) {
|
|
161
|
-
selects.push(`${expression.expression} as "${expression.alias}"`);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const sql = `SELECT ${selects.join(',')} FROM ${this.TableName} WHERE id = $1`;
|
|
166
|
-
let datas = await this.executeQuery(sql, [id]);
|
|
167
|
-
|
|
168
|
-
return datas.rowCount == 0 ? null : datas.rows[0] as T;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
public find<T = {[key: string]: any}>(pk: {[key: string]: any}, selectColumns: Array<string> | "*" | null, selectExpressions: Array<TSelectExpression> | null, keyFormat: TKeyFormat): Promise<T | null>;
|
|
172
|
-
public find<T = {[key: string]: any}>(pk: {[key: string]: any}, selectColumns: Array<string> | "*" | null, selectExpressions: Array<TSelectExpression> | null): Promise<T | null>;
|
|
173
|
-
public find<T = {[key: string]: any}>(pk: {[key: string]: any}, selectColumns: Array<string> | "*" | null): Promise<T | null>;
|
|
174
147
|
public find<T = {[key: string]: any}>(pk: {[key: string]: any}): Promise<T | null>;
|
|
175
|
-
public
|
|
148
|
+
public find<T = {[key: string]: any}>(id: string | number | boolean): Promise<T | null>;
|
|
149
|
+
public find<T = {[key: string]: any}>(pk: {[key: string]: any}, selectColumns: Array<string> | "*" | null): Promise<T | null>;
|
|
150
|
+
public find<T = {[key: string]: any}>(id: string | number | boolean, selectColumns: Array<string> | "*" | null): Promise<T | null>;
|
|
151
|
+
public find<T = {[key: string]: any}>(pk: {[key: string]: any}, selectColumns: Array<string> | "*" | null, selectExpressions: Array<TSelectExpression> | null): Promise<T | null>;
|
|
152
|
+
public find<T = {[key: string]: any}>(id: string | number | boolean, selectColumns: Array<string> | "*" | null, selectExpressions: Array<TSelectExpression> | null): Promise<T | null>;
|
|
153
|
+
public find<T = {[key: string]: any}>(pk: {[key: string]: any}, selectColumns: Array<string> | "*" | null, selectExpressions: Array<TSelectExpression> | null, keyFormat: TKeyFormat): Promise<T | null>;
|
|
154
|
+
public find<T = {[key: string]: any}>(id: string | number | boolean, selectColumns: Array<string> | "*" | null, selectExpressions: Array<TSelectExpression> | null, keyFormat: TKeyFormat): Promise<T | null>;
|
|
155
|
+
public async find<T = {[key: string]: any}>(
|
|
156
|
+
pkOrId: string | number | boolean | {[key: string]: any},
|
|
157
|
+
selectColumns: Array<string> | "*" | null = "*",
|
|
158
|
+
selectExpressions: Array<TSelectExpression> | null = null,
|
|
159
|
+
keyFormat: TKeyFormat = 'snake'): Promise<T | null> {
|
|
176
160
|
|
|
177
161
|
let selects: Array<string> = [];
|
|
178
162
|
if (selectColumns == "*") {
|
|
@@ -191,10 +175,16 @@ export class TableModel {
|
|
|
191
175
|
}
|
|
192
176
|
}
|
|
193
177
|
|
|
194
|
-
|
|
178
|
+
let query: TQuery;
|
|
179
|
+
if (typeof pkOrId === 'string' || typeof pkOrId === 'number' || typeof pkOrId === 'boolean') {
|
|
180
|
+
ValidateValueUtil.validateId(this.Columns, pkOrId);
|
|
181
|
+
query = WhereExpression.createConditionPk(this, {id: pkOrId});
|
|
182
|
+
} else {
|
|
183
|
+
query = WhereExpression.createConditionPk(this, pkOrId);
|
|
184
|
+
}
|
|
195
185
|
|
|
196
|
-
const sql = `SELECT ${selects.join(',')} FROM ${this.TableName} WHERE ${expression}`;
|
|
197
|
-
let datas = await this.executeQuery(sql, vars);
|
|
186
|
+
const sql = `SELECT ${selects.join(',')} FROM ${this.TableName} WHERE ${query.expression}`;
|
|
187
|
+
let datas = await this.executeQuery(sql, query.vars);
|
|
198
188
|
|
|
199
189
|
return datas.rowCount == 0 ? null : datas.rows[0] as T;
|
|
200
190
|
}
|
|
@@ -263,7 +253,7 @@ export class TableModel {
|
|
|
263
253
|
* @param joinBaseModel 結合する対象のBaseModelインスタンスを指定します。
|
|
264
254
|
* @param conditions 結合条件を指定します。条件はオブジェクトまたは文字列で指定できます。
|
|
265
255
|
*/
|
|
266
|
-
public join(joinType: 'left' | 'inner', joinModel: TableModel, conditions: Array<TNestedCondition>): void {
|
|
256
|
+
public join(joinType: 'left' | 'inner' | 'full', joinModel: TableModel, conditions: Array<TNestedCondition>): void {
|
|
267
257
|
this.joinConditions.push({type: joinType, model: joinModel, conditions: conditions});
|
|
268
258
|
}
|
|
269
259
|
|
|
@@ -393,64 +383,10 @@ export class TableModel {
|
|
|
393
383
|
return { datas: data.rows as Array<T>, count: Number(countData.rows[0].count), lastPage: Math.ceil(Number(countData.rows[0].count) / this.PageCount)};
|
|
394
384
|
}
|
|
395
385
|
|
|
396
|
-
|
|
397
|
-
'
|
|
398
|
-
'string[]': '{name} should be entered as an array of string or number types.',
|
|
399
|
-
'uuid': '{name} should be entered as a UUID.',
|
|
400
|
-
'uuid[]': '{name} should be entered as an array of UUIDs.',
|
|
401
|
-
'integer': '{name} should be entered as a number.',
|
|
402
|
-
'integer[]': '{name} should be entered as an array of numbers.',
|
|
403
|
-
'real': '{name} should be entered as a number.',
|
|
404
|
-
'real[]': '{name} should be entered as an array of numbers.',
|
|
405
|
-
'bool': '{name} should be entered as a bool type, "true", "false", 0, or 1.',
|
|
406
|
-
'bool[]': '{name} should be entered as an array of bool types, "true", "false", 0, or 1.',
|
|
407
|
-
'date': '{name} should be entered in "YYYY-MM-DD" or "YYYY-MM-DD hh:mi:ss" format or as a Date type.',
|
|
408
|
-
'date[]': '{name} should be entered as an array of dates in "YYYY-MM-DD" or "YYYY-MM-DD hh:mi:ss" format or as Date types.',
|
|
409
|
-
'time': '{name} should be entered in "hh:mi" format or "hh:mi:ss" format.',
|
|
410
|
-
'time[]': '{name} should be entered as an array of times in "hh:mi" format or "hh:mi:ss" format.',
|
|
411
|
-
'timestamp': '{name} should be entered in "YYYY-MM-DD" format, "YYYY-MM-DD hh:mi:ss" format, "YYYY-MM-DDThh:mi:ss" format, or as a Date type.',
|
|
412
|
-
'timestamp[]': '{name} should be entered as an array of timestamps in "YYYY-MM-DD" format, "YYYY-MM-DD hh:mi:ss" format, "YYYY-MM-DDThh:mi:ss" format, or as Date types.',
|
|
413
|
-
'json': '{name} should be entered as an Object or JSON string.',
|
|
414
|
-
'json[]': '{name} should be entered as an array of Objects or JSON strings.',
|
|
415
|
-
'jsonb': '{name} should be entered as an Object or JSON string.',
|
|
416
|
-
'jsonb[]': '{name} should be entered as an array of Objects or JSON strings.',
|
|
417
|
-
'length': '{name} should be entered within {length} characters.',
|
|
418
|
-
'null': '{name} is not allowed to be null.',
|
|
419
|
-
'notInput': 'Please enter {name}.',
|
|
420
|
-
'fk': 'The value of {name} does not exist in the table.',
|
|
421
|
-
'idNotExist': 'The specified ID({id}) does not exist in the table.',
|
|
422
|
-
'find': 'The specified data does not exist in the table. ({pks})'
|
|
423
|
-
}
|
|
424
|
-
private readonly errorMessageJapan: Record<TColumnType | TColumnArrayType | 'length' | 'null' | 'notInput' | 'fk' | 'idNotExist' | 'find', string> = {
|
|
425
|
-
'string': '{name}はstringかnumberで入力してください。',
|
|
426
|
-
'string[]': '{name}はstringかnumberの配列で入力してください。',
|
|
427
|
-
'uuid': '{name}はuuidで入力してください。',
|
|
428
|
-
'uuid[]': '{name}はuuidの配列で入力してください。',
|
|
429
|
-
'integer': '{name}はnumberか半角数字のstring型で入力してください。',
|
|
430
|
-
'integer[]': '{name}はnumberか半角数字のstring型の配列で入力してください。',
|
|
431
|
-
'real': '{name}はnumberか半角数字のstring型で入力してください。',
|
|
432
|
-
'real[]': '{name}はnumberか半角数字のstring型の配列で入力してください。',
|
|
433
|
-
'bool': '{name}はbool型、"true"、"false"、0、または1で入力してください。',
|
|
434
|
-
'bool[]': '{name}はbool型、"true"、"false"、0、または1の配列で入力してください。',
|
|
435
|
-
'date': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、またはDate型で入力してください。',
|
|
436
|
-
'date[]': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、またはDate型の配列で入力してください。',
|
|
437
|
-
'time': '{name}は"hh:mi"形式または"hh:mi:ss"形式で入力してください。',
|
|
438
|
-
'time[]': '{name}は"hh:mi"形式または"hh:mi:ss"形式の配列で入力してください。',
|
|
439
|
-
'timestamp': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、"YYYY-MM-DDThh:mi:ss"形式、またはDate型で入力してください。',
|
|
440
|
-
'timestamp[]': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、"YYYY-MM-DDThh:mi:ss"形式、またはDate型の配列で入力してください。',
|
|
441
|
-
'json': '{name}はObject形またはJSON文字列で入力してください。',
|
|
442
|
-
'json[]': '{name}はObject形またはJSON文字列の配列で入力してください。',
|
|
443
|
-
'jsonb': '{name}はObject形またはJSON文字列で入力してください。',
|
|
444
|
-
'jsonb[]': '{name}はObject形またはJSON文字列の配列で入力してください。',
|
|
445
|
-
'length': '{name}は{length}文字以内で入力してください。',
|
|
446
|
-
'null': '{name}はnullを許可されていません。',
|
|
447
|
-
'notInput': '{name}を入力してください。',
|
|
448
|
-
'fk': '{name}の値がテーブルに存在しません。',
|
|
449
|
-
'idNotExist': '指定されたID({id})はテーブルに存在しません。',
|
|
450
|
-
'find': '指定されたデータはテーブルに存在しません。({pks})'
|
|
451
|
-
}
|
|
386
|
+
protected readonly errorMessages: TOptionErrorMessage =
|
|
387
|
+
process.env.TZ === 'Asia/Tokyo' ? MessageUtil.optionErrorMessageJapan : MessageUtil.optionErrorMessageEnglish;
|
|
452
388
|
|
|
453
|
-
private throwException(code: string, type: TColumnType | TColumnArrayType | 'length' | 'null' | 'notInput' | 'fk'
|
|
389
|
+
private throwException(code: string, type: TColumnType | TColumnArrayType | 'length' | 'null' | 'notInput' | 'fk', columnName: string, value: any): never {
|
|
454
390
|
const column = this.getColumn(columnName);
|
|
455
391
|
|
|
456
392
|
let message = this.errorMessages[type];
|
|
@@ -464,9 +400,6 @@ export class TableModel {
|
|
|
464
400
|
throw new UnprocessableException(code, message);
|
|
465
401
|
}
|
|
466
402
|
|
|
467
|
-
protected readonly errorMessages: Record<TColumnType | TColumnArrayType | 'length' | 'null' | 'notInput' | 'fk' | 'idNotExist' | 'find', string> =
|
|
468
|
-
process.env.TZ === 'Asia/Tokyo' ? this.errorMessageJapan : this.errorMessageEnglish;
|
|
469
|
-
|
|
470
403
|
protected async validateOptions(options: {[key: string]: any}, isInsert: boolean): Promise<void> {
|
|
471
404
|
if (Object.keys(options).length === 0) {
|
|
472
405
|
throw new Error('At least one key-value pair is required in options.');
|
|
@@ -513,6 +446,17 @@ export class TableModel {
|
|
|
513
446
|
|
|
514
447
|
// 外部キー制約チェック
|
|
515
448
|
if (isInsert) {
|
|
449
|
+
for (const key in this.Columns) {
|
|
450
|
+
const column = this.getColumn(key);
|
|
451
|
+
const name = (column.alias === undefined || column.alias === '') ? key : column.alias;
|
|
452
|
+
if (options[key] === undefined || options[key] === null) {
|
|
453
|
+
// Null許容されていないカラムにNULLを入れようとしているか?
|
|
454
|
+
if (column.attribute === "primary" || column.attribute === "noDefault") {
|
|
455
|
+
this.throwException("005", "notInput", key, options[key]);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
516
460
|
for (const ref of this.References) {
|
|
517
461
|
const refValues = ref.columns.map(col => options[col.target]);
|
|
518
462
|
// 全ての値がnullの場合はスキップ
|
|
@@ -523,7 +467,7 @@ export class TableModel {
|
|
|
523
467
|
// 一部の値がnullの場合はエラー
|
|
524
468
|
if (refValues.some(value => value === null || value === undefined)) {
|
|
525
469
|
const name = ref.columns.map(col => this.getColumn(col.target).alias ?? this.getColumn(col.target).columnName).join(',');
|
|
526
|
-
throw new UnprocessableException("
|
|
470
|
+
throw new UnprocessableException("006", this.errorMessages.null.replace('{name}', name));
|
|
527
471
|
}
|
|
528
472
|
|
|
529
473
|
let refIndex = 1;
|
|
@@ -531,33 +475,14 @@ export class TableModel {
|
|
|
531
475
|
const datas = await this.clientQuery(sql, refValues);
|
|
532
476
|
if (datas.rows[0].count == "0") {
|
|
533
477
|
const name = ref.columns.map(col => this.getColumn(col.target).alias ?? this.getColumn(col.target).columnName).join(',');
|
|
534
|
-
throw new DbConflictException("
|
|
478
|
+
throw new DbConflictException("007", this.errorMessages.fk.replace('{name}', name));
|
|
535
479
|
}
|
|
536
480
|
}
|
|
537
481
|
}
|
|
538
482
|
}
|
|
539
483
|
|
|
540
|
-
|
|
541
|
-
for (const key in this.Columns) {
|
|
542
|
-
const column = this.getColumn(key);
|
|
543
|
-
const name = (column.alias === undefined || column.alias === '') ? key : column.alias;
|
|
544
|
-
if (options[key] === undefined || options[key] === null) {
|
|
545
|
-
// Null許容されていないカラムにNULLを入れようとしているか?
|
|
546
|
-
if (column.attribute === "primary" || column.attribute === "noDefault") {
|
|
547
|
-
this.throwException("101", "notInput", key, options[key]);
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
protected async validateUpdate(options: {[key: string]: any}) : Promise<void> { }
|
|
554
|
-
protected async validateUpdateId(id: any, options: {[key: string]: any}) : Promise<void> { }
|
|
555
|
-
protected async validateDelete() : Promise<void> { }
|
|
556
|
-
protected async validateDeleteId(id: any) : Promise<void> { }
|
|
557
|
-
|
|
558
|
-
public async executeInsert(options: {[key: string]: any}) : Promise<void> {
|
|
484
|
+
public async insert(options: {[key: string]: any}) : Promise<void> {
|
|
559
485
|
await this.validateOptions(options, true);
|
|
560
|
-
await this.validateInsert(options);
|
|
561
486
|
|
|
562
487
|
const columns: Array<string> = [];
|
|
563
488
|
const vars: Array<any> = [];
|
|
@@ -576,9 +501,43 @@ export class TableModel {
|
|
|
576
501
|
await this.executeQuery(sql, vars);
|
|
577
502
|
}
|
|
578
503
|
|
|
504
|
+
public async update(pkOrId: string | number | boolean | {[key: string]: any}, options: {[key: string]: any}) : Promise<void> {
|
|
505
|
+
await this.validateOptions(options, false);
|
|
506
|
+
|
|
507
|
+
const updateSetQuery = UpdateExpression.createUpdateSet(this, options);
|
|
508
|
+
let whereQuery: TQuery;
|
|
509
|
+
if (typeof pkOrId === 'string' || typeof pkOrId === 'number' || typeof pkOrId === 'boolean') {
|
|
510
|
+
ValidateValueUtil.validateId(this.Columns, pkOrId);
|
|
511
|
+
whereQuery = WhereExpression.createConditionPk(this, {id: pkOrId}, updateSetQuery.vars);
|
|
512
|
+
} else {
|
|
513
|
+
whereQuery = WhereExpression.createConditionPk(this, pkOrId, updateSetQuery.vars);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
const sql = updateSetQuery.expression + ' WHERE ' + whereQuery.expression;
|
|
517
|
+
const data = await this.executeQuery(sql, whereQuery.vars);
|
|
518
|
+
if (data.rowCount !== 1) {
|
|
519
|
+
throw new UnprocessableException("201", this.errorMessages.find.replace('{pks}', (whereQuery.vars ?? []).join(',')));
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
public async delete(pkOrId: string | number | boolean | {[key: string]: any}) : Promise<void> {
|
|
524
|
+
let whereQuery: TQuery;
|
|
525
|
+
if (typeof pkOrId === 'string' || typeof pkOrId === 'number' || typeof pkOrId === 'boolean') {
|
|
526
|
+
ValidateValueUtil.validateId(this.Columns, pkOrId);
|
|
527
|
+
whereQuery = WhereExpression.createConditionPk(this, {id: pkOrId});
|
|
528
|
+
} else {
|
|
529
|
+
whereQuery = WhereExpression.createConditionPk(this, pkOrId);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
const sql = `DELETE FROM ${this.TableName} WHERE ${whereQuery.expression}`;
|
|
533
|
+
const data = await this.executeQuery(sql, whereQuery.vars);
|
|
534
|
+
if (data.rowCount !== 1) {
|
|
535
|
+
throw new UnprocessableException("301", this.errorMessages.find.replace('{pks}', (whereQuery.vars ?? []).join(',')));
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
579
539
|
public async executeUpdate(options: {[key: string]: any}) : Promise<number> {
|
|
580
540
|
await this.validateOptions(options, false);
|
|
581
|
-
await this.validateUpdate(options);
|
|
582
541
|
|
|
583
542
|
const updateExpressions: Array<string> = [];
|
|
584
543
|
for (const [key, value] of Object.entries(options)) {
|
|
@@ -612,41 +571,7 @@ export class TableModel {
|
|
|
612
571
|
return data.rowCount;
|
|
613
572
|
}
|
|
614
573
|
|
|
615
|
-
public async executeUpdateId(id: any, options: {[key: string]: any}) : Promise<void> {
|
|
616
|
-
ValidateValueUtil.validateId(this.Columns, id);
|
|
617
|
-
await this.validateOptions(options, false);
|
|
618
|
-
await this.validateUpdateId(id, options);
|
|
619
|
-
await this.validateUpdate(options);
|
|
620
|
-
|
|
621
|
-
const updateSetQuery = UpdateExpression.createUpdateSet(this, options);
|
|
622
|
-
const whereQuery = WhereExpression.createConditionPk(this, {id: id}, updateSetQuery.vars);
|
|
623
|
-
|
|
624
|
-
const sql = updateSetQuery.expression + ' WHERE ' + whereQuery.expression;
|
|
625
|
-
|
|
626
|
-
const data = await this.executeQuery(sql, whereQuery.vars);
|
|
627
|
-
if (data.rowCount !== 1) {
|
|
628
|
-
throw new UnprocessableException("201", this.errorMessages.find.replace('{pks}', (whereQuery.vars ?? []).join(',')));
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
public async executeUpdateByPk(pk: {[key: string]: any}, options: {[key: string]: any}) : Promise<void> {
|
|
633
|
-
await this.validateOptions(options, false);
|
|
634
|
-
// await this.validateUpdateId(id, options);
|
|
635
|
-
await this.validateUpdate(options);
|
|
636
|
-
|
|
637
|
-
const updateSetQuery = UpdateExpression.createUpdateSet(this, options);
|
|
638
|
-
const whereQuery = WhereExpression.createConditionPk(this, pk, updateSetQuery.vars);
|
|
639
|
-
|
|
640
|
-
const sql = updateSetQuery.expression + ' WHERE ' + whereQuery.expression;
|
|
641
|
-
|
|
642
|
-
const data = await this.executeQuery(sql, whereQuery.vars);
|
|
643
|
-
if (data.rowCount !== 1) {
|
|
644
|
-
throw new UnprocessableException("401", this.errorMessages.find.replace('{pks}', (whereQuery.vars ?? []).join(',')));
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
|
|
648
574
|
public async executeDelete() : Promise<number> {
|
|
649
|
-
this.validateDelete();
|
|
650
575
|
let sql = `DELETE FROM ${this.TableName} "${this.TableAlias}" `;
|
|
651
576
|
|
|
652
577
|
if (this.joinConditions.length > 0) {
|
|
@@ -671,17 +596,6 @@ export class TableModel {
|
|
|
671
596
|
return datas.rowCount;
|
|
672
597
|
}
|
|
673
598
|
|
|
674
|
-
public async executeDeleteId(id: any) : Promise<void> {
|
|
675
|
-
ValidateValueUtil.validateId(this.Columns, id);
|
|
676
|
-
await this.validateDeleteId(id);
|
|
677
|
-
let sql = `DELETE FROM ${this.TableName} WHERE id = $1`;
|
|
678
|
-
|
|
679
|
-
const datas = await this.executeQuery(sql, [id]);
|
|
680
|
-
if (datas.rowCount !== 1) {
|
|
681
|
-
throw new UnprocessableException("301", this.errorMessages.idNotExist.replace('{id}', id));
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
|
|
685
599
|
protected executeQuery(param1: string, vars?: Array<any>) : Promise<any>;
|
|
686
600
|
protected executeQuery(param1: TQuery) : Promise<any>;
|
|
687
601
|
protected async executeQuery(param1: string | TQuery, vars?: Array<any>) : Promise<any> {
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { TColumnArrayType, TColumnType } from "../Type"
|
|
2
|
+
|
|
3
|
+
export type TOptionErrorMessage = Record<TColumnType | TColumnArrayType | 'length' | 'null' | 'notInput' | 'fk' | 'find', string>;
|
|
4
|
+
|
|
5
|
+
export default class MessageUtil {
|
|
6
|
+
public static readonly optionErrorMessageEnglish: TOptionErrorMessage = {
|
|
7
|
+
'string': '{name} should be entered as a string or number type.',
|
|
8
|
+
'string[]': '{name} should be entered as an array of string or number types.',
|
|
9
|
+
'uuid': '{name} should be entered as a UUID.',
|
|
10
|
+
'uuid[]': '{name} should be entered as an array of UUIDs.',
|
|
11
|
+
'integer': '{name} should be entered as a number.',
|
|
12
|
+
'integer[]': '{name} should be entered as an array of numbers.',
|
|
13
|
+
'real': '{name} should be entered as a number.',
|
|
14
|
+
'real[]': '{name} should be entered as an array of numbers.',
|
|
15
|
+
'bool': '{name} should be entered as a bool type, "true", "false", 0, or 1.',
|
|
16
|
+
'bool[]': '{name} should be entered as an array of bool types, "true", "false", 0, or 1.',
|
|
17
|
+
'date': '{name} should be entered in "YYYY-MM-DD" or "YYYY-MM-DD hh:mi:ss" format or as a Date type.',
|
|
18
|
+
'date[]': '{name} should be entered as an array of dates in "YYYY-MM-DD" or "YYYY-MM-DD hh:mi:ss" format or as Date types.',
|
|
19
|
+
'time': '{name} should be entered in "hh:mi" format or "hh:mi:ss" format.',
|
|
20
|
+
'time[]': '{name} should be entered as an array of times in "hh:mi" format or "hh:mi:ss" format.',
|
|
21
|
+
'timestamp': '{name} should be entered in "YYYY-MM-DD" format, "YYYY-MM-DD hh:mi:ss" format, "YYYY-MM-DDThh:mi:ss" format, or as a Date type.',
|
|
22
|
+
'timestamp[]': '{name} should be entered as an array of timestamps in "YYYY-MM-DD" format, "YYYY-MM-DD hh:mi:ss" format, "YYYY-MM-DDThh:mi:ss" format, or as Date types.',
|
|
23
|
+
'json': '{name} should be entered as an Object or JSON string.',
|
|
24
|
+
'json[]': '{name} should be entered as an array of Objects or JSON strings.',
|
|
25
|
+
'jsonb': '{name} should be entered as an Object or JSON string.',
|
|
26
|
+
'jsonb[]': '{name} should be entered as an array of Objects or JSON strings.',
|
|
27
|
+
'length': '{name} should be entered within {length} characters.',
|
|
28
|
+
'null': '{name} is not allowed to be null.',
|
|
29
|
+
'notInput': 'Please enter {name}.',
|
|
30
|
+
'fk': 'The value of {name} does not exist in the table.',
|
|
31
|
+
'find': 'The specified data does not exist in the table. ({pks})'
|
|
32
|
+
}
|
|
33
|
+
public static readonly optionErrorMessageJapan: TOptionErrorMessage = {
|
|
34
|
+
'string': '{name}はstringかnumberで入力してください。',
|
|
35
|
+
'string[]': '{name}はstringかnumberの配列で入力してください。',
|
|
36
|
+
'uuid': '{name}はuuidで入力してください。',
|
|
37
|
+
'uuid[]': '{name}はuuidの配列で入力してください。',
|
|
38
|
+
'integer': '{name}はnumberか半角数字のstring型で入力してください。',
|
|
39
|
+
'integer[]': '{name}はnumberか半角数字のstring型の配列で入力してください。',
|
|
40
|
+
'real': '{name}はnumberか半角数字のstring型で入力してください。',
|
|
41
|
+
'real[]': '{name}はnumberか半角数字のstring型の配列で入力してください。',
|
|
42
|
+
'bool': '{name}はbool型、"true"、"false"、0、または1で入力してください。',
|
|
43
|
+
'bool[]': '{name}はbool型、"true"、"false"、0、または1の配列で入力してください。',
|
|
44
|
+
'date': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、またはDate型で入力してください。',
|
|
45
|
+
'date[]': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、またはDate型の配列で入力してください。',
|
|
46
|
+
'time': '{name}は"hh:mi"形式または"hh:mi:ss"形式で入力してください。',
|
|
47
|
+
'time[]': '{name}は"hh:mi"形式または"hh:mi:ss"形式の配列で入力してください。',
|
|
48
|
+
'timestamp': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、"YYYY-MM-DDThh:mi:ss"形式、またはDate型で入力してください。',
|
|
49
|
+
'timestamp[]': '{name}は"YYYY-MM-DD"形式、"YYYY-MM-DD hh:mi:ss"形式、"YYYY-MM-DDThh:mi:ss"形式、またはDate型の配列で入力してください。',
|
|
50
|
+
'json': '{name}はObject形またはJSON文字列で入力してください。',
|
|
51
|
+
'json[]': '{name}はObject形またはJSON文字列の配列で入力してください。',
|
|
52
|
+
'jsonb': '{name}はObject形またはJSON文字列で入力してください。',
|
|
53
|
+
'jsonb[]': '{name}はObject形またはJSON文字列の配列で入力してください。',
|
|
54
|
+
'length': '{name}は{length}文字以内で入力してください。',
|
|
55
|
+
'null': '{name}はnullを許可されていません。',
|
|
56
|
+
'notInput': '{name}を入力してください。',
|
|
57
|
+
'fk': '{name}の値がテーブルに存在しません。',
|
|
58
|
+
'find': '指定されたデータはテーブルに存在しません。({pks})'
|
|
59
|
+
}
|
|
60
|
+
}
|