pg-mvc-service 1.0.0
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 +1 -0
- package/dist/PoolManager.js +57 -0
- package/dist/Service.js +257 -0
- package/dist/clients/AwsS3Client.js +249 -0
- package/dist/clients/Base64Client.js +153 -0
- package/dist/clients/EncryptClient.js +85 -0
- package/dist/clients/StringClient.js +13 -0
- package/dist/documents/Swagger.js +94 -0
- package/dist/exceptions/Exception.js +53 -0
- package/dist/index.js +16 -0
- package/dist/models/MigrateDatabase.js +138 -0
- package/dist/models/MigrateRollback.js +146 -0
- package/dist/models/MigrateTable.js +51 -0
- package/dist/models/SqlUtils/SelectExpression.js +92 -0
- package/dist/models/SqlUtils/ValidateValueUtil.js +250 -0
- package/dist/models/SqlUtils/WhereExpression.js +256 -0
- package/dist/models/TableDoc.js +353 -0
- package/dist/models/TableModel.js +636 -0
- package/dist/models/Type.js +2 -0
- package/dist/models/Utils/DateTimeUtil.js +134 -0
- package/dist/models/Utils/NumberUtil.js +28 -0
- package/dist/models/Utils/StringUtil.js +31 -0
- package/dist/models/ValidateClient.js +164 -0
- package/dist/models/index.js +14 -0
- package/dist/reqestResponse/ReqResType.js +196 -0
- package/dist/reqestResponse/RequestType.js +742 -0
- package/dist/reqestResponse/ResponseType.js +380 -0
- package/index.d.ts +306 -0
- package/package.json +36 -0
- package/src/PoolManager.ts +48 -0
- package/src/Service.ts +251 -0
- package/src/clients/AwsS3Client.ts +229 -0
- package/src/clients/Base64Client.ts +155 -0
- package/src/clients/EncryptClient.ts +100 -0
- package/src/clients/StringClient.ts +14 -0
- package/src/documents/Swagger.ts +111 -0
- package/src/exceptions/Exception.ts +54 -0
- package/src/index.ts +7 -0
- package/src/models/MigrateDatabase.ts +135 -0
- package/src/models/MigrateRollback.ts +151 -0
- package/src/models/MigrateTable.ts +56 -0
- package/src/models/SqlUtils/SelectExpression.ts +97 -0
- package/src/models/SqlUtils/ValidateValueUtil.ts +270 -0
- package/src/models/SqlUtils/WhereExpression.ts +286 -0
- package/src/models/TableDoc.ts +360 -0
- package/src/models/TableModel.ts +713 -0
- package/src/models/Type.ts +59 -0
- package/src/models/Utils/DateTimeUtil.ts +146 -0
- package/src/models/Utils/NumberUtil.ts +23 -0
- package/src/models/Utils/StringUtil.ts +33 -0
- package/src/models/ValidateClient.ts +182 -0
- package/src/models/index.ts +7 -0
- package/src/reqestResponse/ReqResType.ts +242 -0
- package/src/reqestResponse/RequestType.ts +851 -0
- package/src/reqestResponse/ResponseType.ts +418 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const ValidateValueUtil_1 = __importDefault(require("./ValidateValueUtil"));
|
|
7
|
+
class WhereExpression {
|
|
8
|
+
/**
|
|
9
|
+
* Helper method to create OR conditions
|
|
10
|
+
* @param conditions Array of conditions that make up the OR condition
|
|
11
|
+
* @returns SQL query string representing the OR condition
|
|
12
|
+
*/
|
|
13
|
+
static createCondition(conditions, model, varLength) {
|
|
14
|
+
if (conditions.length === 0) {
|
|
15
|
+
return { sql: '' };
|
|
16
|
+
}
|
|
17
|
+
let logicalOperator = 'AND';
|
|
18
|
+
if (conditions[0] === 'AND' || conditions[0] === 'OR') {
|
|
19
|
+
if (conditions.length === 1) {
|
|
20
|
+
return { sql: '' };
|
|
21
|
+
}
|
|
22
|
+
logicalOperator = conditions[0];
|
|
23
|
+
conditions.shift();
|
|
24
|
+
}
|
|
25
|
+
const expression = [];
|
|
26
|
+
let vars = [];
|
|
27
|
+
for (let condition of conditions) {
|
|
28
|
+
if (Array.isArray(condition)) {
|
|
29
|
+
// If it's an array, it's a nested condition, so call this function recursively
|
|
30
|
+
const query = this.createCondition(condition, model, varLength + vars.length);
|
|
31
|
+
expression.push(query.sql);
|
|
32
|
+
if (query.vars !== undefined) {
|
|
33
|
+
vars = [...vars, ...query.vars];
|
|
34
|
+
}
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (typeof condition === 'string') {
|
|
38
|
+
// If specified directly as a string, it becomes a query, so insert as is
|
|
39
|
+
expression.push(condition);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (typeof condition.l === 'string') {
|
|
43
|
+
const query = this.create({ model: model, name: condition.l }, condition.o, condition.r, varLength + vars.length);
|
|
44
|
+
expression.push(query.sql);
|
|
45
|
+
if (query.vars !== undefined) {
|
|
46
|
+
vars = [...vars, ...query.vars];
|
|
47
|
+
}
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const query = this.create(condition.l, condition.o, condition.r, varLength + vars.length);
|
|
51
|
+
expression.push(query.sql);
|
|
52
|
+
if (query.vars !== undefined) {
|
|
53
|
+
vars = [...vars, ...query.vars];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
sql: `(${expression.filter(condition => condition !== null && condition !== void 0 ? condition : '' !== '').join(` ${logicalOperator} `)})`,
|
|
58
|
+
vars: vars
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
static create(left, operator, right, varLength) {
|
|
62
|
+
// Check if the specified ColumnInfo exists
|
|
63
|
+
const leftColumn = left.model.getColumn(left.name);
|
|
64
|
+
// Are the operators correct?
|
|
65
|
+
const useableOperator = {
|
|
66
|
+
number: ["=", "!=", ">", ">=", "<", "<=", "in", "not in"],
|
|
67
|
+
'number[]': [],
|
|
68
|
+
string: ["=", "!=", "like", "ilike", "h2f_like", "h2f_ilike", "in", "not in"],
|
|
69
|
+
'string[]': [],
|
|
70
|
+
uuid: ["=", "!=", "in", "not in"],
|
|
71
|
+
'uuid[]': [],
|
|
72
|
+
bool: ["=", "!=", "in", "not in"],
|
|
73
|
+
'bool[]': [],
|
|
74
|
+
date: ["=", "!=", ">", ">=", "<", "<="],
|
|
75
|
+
'date[]': [],
|
|
76
|
+
time: ["=", "!=", ">", ">=", "<", "<="],
|
|
77
|
+
'time[]': [],
|
|
78
|
+
timestamp: ["=", "!=", ">", ">=", "<", "<="],
|
|
79
|
+
'timestamp[]': []
|
|
80
|
+
};
|
|
81
|
+
if (useableOperator[leftColumn.type].includes(operator) == false) {
|
|
82
|
+
throw new Error(`The ${operator} operator cannot be used for ${leftColumn.tableName}.${leftColumn.columnName}. (${leftColumn.type})`);
|
|
83
|
+
}
|
|
84
|
+
if (right === null) {
|
|
85
|
+
if (leftColumn.attribute !== "nullable") {
|
|
86
|
+
throw new Error(`You cannot use conditions with null values unless the attribute is nullable.`);
|
|
87
|
+
}
|
|
88
|
+
if (operator == "=") {
|
|
89
|
+
return {
|
|
90
|
+
sql: `${leftColumn.expression} is null`
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
else if (operator == "!=") {
|
|
94
|
+
return {
|
|
95
|
+
sql: `${leftColumn.expression} is not null`
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
throw new Error(`When comparing with null, operators other than =, != cannot be used. (${operator})`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (leftColumn.type.endsWith("[]")) {
|
|
103
|
+
return this.createExpression(leftColumn, operator, right, varLength);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
return this.createExpression(leftColumn, operator, right, varLength);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
static createExpression(leftColumn, operator, right, varLength) {
|
|
110
|
+
// IN NOT IN clause
|
|
111
|
+
if (["in", "not in"].includes(operator)) {
|
|
112
|
+
if (Array.isArray(right) == false) {
|
|
113
|
+
throw new Error(`For the 'in' operator, you cannot input anything other than an array on the right side.`);
|
|
114
|
+
}
|
|
115
|
+
if (right.length == 0) {
|
|
116
|
+
// Creating in, not in with 0 elements will cause an error, but since the data to be passed is correct and the expected return value does not change, do not search if there are 0 elements
|
|
117
|
+
return { sql: '' };
|
|
118
|
+
}
|
|
119
|
+
// Validate values
|
|
120
|
+
for (const value of right) {
|
|
121
|
+
ValidateValueUtil_1.default.validateValue(leftColumn, value);
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
sql: `${leftColumn.expression} ${operator === 'in' ? '=' : '!='} ANY($${varLength})`,
|
|
125
|
+
vars: [right]
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
else if (Array.isArray(right)) {
|
|
129
|
+
throw new Error(`For operators other than 'in', you cannot input an array on the right side.`);
|
|
130
|
+
}
|
|
131
|
+
// If the right side value is a column specification
|
|
132
|
+
if (right !== null && typeof right === 'object' && 'model' in right && 'name' in right) {
|
|
133
|
+
const rightColumn = right.model.getColumn(right.name);
|
|
134
|
+
if (leftColumn.type !== rightColumn.type) {
|
|
135
|
+
throw new Error(`The types of [${leftColumn.tableName}].[${leftColumn.columnName}] and [${rightColumn.tableName}].[${rightColumn.columnName}] are different.`);
|
|
136
|
+
}
|
|
137
|
+
// LIKE operators are different, so handle separately
|
|
138
|
+
switch (operator) {
|
|
139
|
+
case 'like':
|
|
140
|
+
case 'ilike':
|
|
141
|
+
return {
|
|
142
|
+
sql: `${leftColumn.expression} ${operator} '%' || ${rightColumn.expression} || '%'`
|
|
143
|
+
};
|
|
144
|
+
case 'h2f_like': // half to full like
|
|
145
|
+
case 'h2f_ilike': // half to full ilike
|
|
146
|
+
return {
|
|
147
|
+
sql: `${this.makeSqlReplaceHalfToFull(leftColumn.expression)} ${operator.replace("h2f_", "")} ${this.makeSqlReplaceHalfToFull(`'%' || ${rightColumn.expression} || '%'`)}`
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
sql: `${leftColumn.expression} ${operator} ${rightColumn.expression}`
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
ValidateValueUtil_1.default.validateValue(leftColumn, right);
|
|
155
|
+
// LIKE operators are different, so handle separately
|
|
156
|
+
switch (operator) {
|
|
157
|
+
case 'like':
|
|
158
|
+
case 'ilike':
|
|
159
|
+
return {
|
|
160
|
+
sql: `${leftColumn.expression} ${operator} $${varLength}`,
|
|
161
|
+
vars: [`%${right}%`]
|
|
162
|
+
};
|
|
163
|
+
case 'h2f_like': // half to full like
|
|
164
|
+
case 'h2f_ilike': // half to full ilike
|
|
165
|
+
return {
|
|
166
|
+
sql: `${this.makeSqlReplaceHalfToFull(leftColumn.expression)} ${operator.replace("h2f_", "")} ${this.makeSqlReplaceHalfToFull(`$${varLength}`)}`,
|
|
167
|
+
vars: [`%${right}%`]
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
sql: `${leftColumn.expression} ${operator} $${varLength}`,
|
|
172
|
+
vars: [right]
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
static createExpressionArrayValue(leftColumn, operator, right, varLength) {
|
|
176
|
+
// ValidateValueUtil.validateValue(leftColumn, right);
|
|
177
|
+
// LIKE operators are different, so handle separately
|
|
178
|
+
// switch (operator) {
|
|
179
|
+
// case 'like':
|
|
180
|
+
// case 'ilike':
|
|
181
|
+
// return {
|
|
182
|
+
// sql: `${leftColumn.expression} ${operator} $${varLength}`,
|
|
183
|
+
// vars: [`%${right}%`]
|
|
184
|
+
// }
|
|
185
|
+
// case 'h2f_like': // half to full like
|
|
186
|
+
// case 'h2f_ilike': // half to full ilike
|
|
187
|
+
// return {
|
|
188
|
+
// sql: `${this.makeSqlReplaceHalfToFull(leftColumn.expression)} ${operator.replace("h2f_", "")} ${this.makeSqlReplaceHalfToFull(`$${varLength}`)}`,
|
|
189
|
+
// vars: [`%${right}%`]
|
|
190
|
+
// }
|
|
191
|
+
// }
|
|
192
|
+
switch (operator) {
|
|
193
|
+
case '=':
|
|
194
|
+
// バリデーションチェックをする
|
|
195
|
+
return {
|
|
196
|
+
sql: `${leftColumn.expression} ${operator} $${varLength}`,
|
|
197
|
+
vars: [right]
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
sql: `${leftColumn.expression} ${operator} $${varLength}`,
|
|
202
|
+
vars: [right]
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* SQL statement to convert half-width characters to full-width
|
|
207
|
+
* @param {string} columnName Column name
|
|
208
|
+
* @returns SQL statement
|
|
209
|
+
*/
|
|
210
|
+
static makeSqlReplaceHalfToFull(columnNameOrValue) {
|
|
211
|
+
const num = {
|
|
212
|
+
'0': '0', '1': '1', '2': '2', '3': '3', '4': '4',
|
|
213
|
+
'5': '5', '6': '6', '7': '7', '8': '8', '9': '9'
|
|
214
|
+
};
|
|
215
|
+
const kana = {
|
|
216
|
+
'ア': 'ア', 'イ': 'イ', 'ウ': 'ウ', 'エ': 'エ', 'オ': 'オ',
|
|
217
|
+
'カ': 'カ', 'キ': 'キ', 'ク': 'ク', 'ケ': 'ケ', 'コ': 'コ',
|
|
218
|
+
'サ': 'サ', 'シ': 'シ', 'ス': 'ス', 'セ': 'セ', 'ソ': 'ソ',
|
|
219
|
+
'タ': 'タ', 'チ': 'チ', 'ツ': 'ツ', 'テ': 'テ', 'ト': 'ト',
|
|
220
|
+
'ナ': 'ナ', 'ニ': 'ニ', 'ヌ': 'ヌ', 'ネ': 'ネ', 'ノ': 'ノ',
|
|
221
|
+
'ハ': 'ハ', 'ヒ': 'ヒ', 'フ': 'フ', 'ヘ': 'ヘ', 'ホ': 'ホ',
|
|
222
|
+
'マ': 'マ', 'ミ': 'ミ', 'ム': 'ム', 'メ': 'メ', 'モ': 'モ',
|
|
223
|
+
'ヤ': 'ヤ', 'ユ': 'ユ', 'ヨ': 'ヨ',
|
|
224
|
+
'ラ': 'ラ', 'リ': 'リ', 'ル': 'ル', 'レ': 'レ', 'ロ': 'ロ',
|
|
225
|
+
'ワ': 'ワ', 'ヲ': 'ヲ', 'ン': 'ン',
|
|
226
|
+
'ヴ': 'ヴ',
|
|
227
|
+
'ガ': 'ガ', 'ギ': 'ギ', 'グ': 'グ', 'ゲ': 'ゲ', 'ゴ': 'ゴ',
|
|
228
|
+
'ザ': 'ザ', 'ジ': 'ジ', 'ズ': 'ズ', 'ゼ': 'ゼ', 'ゾ': 'ゾ',
|
|
229
|
+
'ダ': 'ダ', 'ヂ': 'ヂ', 'ヅ': 'ヅ', 'デ': 'デ', 'ド': 'ド',
|
|
230
|
+
'バ': 'ハ', 'ビ': 'ビ', 'ブ': 'ブ', 'ベ': 'ベ', 'ボ': 'ボ',
|
|
231
|
+
'パ': 'パ', 'ピ': 'ピ', 'プ': 'プ', 'ペ': 'ペ', 'ポ': 'ポ',
|
|
232
|
+
'ァ': 'ァ', 'ィ': 'ィ', 'ゥ': 'ゥ', 'ェ': 'ェ', 'ォ': 'ォ',
|
|
233
|
+
'ャ': 'ャ', 'ュ': 'ュ', 'ョ': 'ョ',
|
|
234
|
+
'ッ': 'ッ',
|
|
235
|
+
'ー': 'ー', '、': '、', '。': '。', '・': '・', '「': '「', '」': '」', '゛': ' ゙', '゜': ' ゚'
|
|
236
|
+
};
|
|
237
|
+
const alpha = {
|
|
238
|
+
'A': 'A', 'B': 'B', 'C': 'C', 'D': 'D', 'E': 'E', 'F': 'F', 'G': 'G',
|
|
239
|
+
'H': 'H', 'I': 'I', 'J': 'J', 'K': 'K', 'L': 'L', 'M': 'M', 'N': 'N',
|
|
240
|
+
'O': 'O', 'P': 'P', 'Q': 'Q', 'R': 'R', 'S': 'S', 'T': 'T', 'U': 'U',
|
|
241
|
+
'V': 'V', 'W': 'W', 'X': 'X', 'Y': 'Y', 'Z': 'Z',
|
|
242
|
+
'a': 'a', 'b': 'b', 'c': 'c', 'd': 'd', 'e': 'e', 'f': 'f', 'g': 'g',
|
|
243
|
+
'h': 'h', 'i': 'i', 'j': 'j', 'k': 'k', 'l': 'l', 'm': 'm', 'n': 'n',
|
|
244
|
+
'o': 'o', 'p': 'p', 'q': 'q', 'r': 'r', 's': 's', 't': 't', 'u': 'u',
|
|
245
|
+
'v': 'v', 'w': 'w', 'x': 'x', 'y': 'y', 'z': 'z',
|
|
246
|
+
};
|
|
247
|
+
let objs = {};
|
|
248
|
+
Object.assign(objs, num);
|
|
249
|
+
Object.assign(objs, kana);
|
|
250
|
+
Object.assign(objs, alpha);
|
|
251
|
+
let sql = columnNameOrValue;
|
|
252
|
+
Object.keys(objs).forEach(key => sql = `TRANSLATE(${sql} ,'${key}','${objs[key]}')`);
|
|
253
|
+
return sql;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
exports.default = WhereExpression;
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createTableDoc = void 0;
|
|
4
|
+
const createTableDoc = (models, serviceName) => {
|
|
5
|
+
var _a, _b, _c, _d;
|
|
6
|
+
let html = `
|
|
7
|
+
<!DOCTYPE html>
|
|
8
|
+
<html lang="ja">
|
|
9
|
+
<head>
|
|
10
|
+
<meta charset="UTF-8">
|
|
11
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
12
|
+
<title>table document</title>
|
|
13
|
+
</head>
|
|
14
|
+
<style>
|
|
15
|
+
:root {
|
|
16
|
+
--primary: rgb(73, 204, 144);
|
|
17
|
+
--primary-dark: rgb(64, 169, 121);
|
|
18
|
+
--bg-primary: rgba(73, 204, 144, 0.15);
|
|
19
|
+
--border-primary: rgba(73, 204, 144, 0.3);
|
|
20
|
+
--border-gray: rgb(200, 200, 200);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
body {
|
|
24
|
+
padding: 0px;
|
|
25
|
+
padding-left: 12px;
|
|
26
|
+
padding-right: 12px;
|
|
27
|
+
margin: 0px;
|
|
28
|
+
color: rgb(30, 35, 40);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
button {
|
|
33
|
+
padding-left: 8px;
|
|
34
|
+
padding-right: 8px;
|
|
35
|
+
padding-top: 2px;
|
|
36
|
+
padding-bottom: 2px;
|
|
37
|
+
background-color: var(--primary);
|
|
38
|
+
border: 0px;
|
|
39
|
+
color: #ffffff;
|
|
40
|
+
border-radius: 999px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
button:hover {
|
|
44
|
+
background-color: var(--primary-dark);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* title*/
|
|
48
|
+
h1 {
|
|
49
|
+
font-size: 28px;
|
|
50
|
+
font-weight: bold;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* db-title*/
|
|
54
|
+
h2 {
|
|
55
|
+
background-color: var(--primary);
|
|
56
|
+
border-top-left-radius: 8px;
|
|
57
|
+
border-top-right-radius: 8px;
|
|
58
|
+
color: #ffffff;
|
|
59
|
+
padding-left: 4px;
|
|
60
|
+
margin: 0;
|
|
61
|
+
font-size: 24px;
|
|
62
|
+
font-weight: bold;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.db-wrapper {
|
|
66
|
+
border-radius: 8px;
|
|
67
|
+
border: var(--primary) solid 1px;
|
|
68
|
+
margin-bottom: 24px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* table-title*/
|
|
72
|
+
h3 {
|
|
73
|
+
font-size: 18px;
|
|
74
|
+
font-weight: bold;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.table-wrapper {
|
|
78
|
+
padding: 0px;
|
|
79
|
+
margin-bottom: 16px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.table-title-wrapper {
|
|
83
|
+
background-color: var(--bg-primary);
|
|
84
|
+
border-top: var(--border-primary) solid 1px;
|
|
85
|
+
margin: 0;
|
|
86
|
+
padding: 2px 4px;
|
|
87
|
+
align-items: center;
|
|
88
|
+
display: flex;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.table-title-left {
|
|
92
|
+
font-size: 18px;
|
|
93
|
+
font-weight: bold;
|
|
94
|
+
text-align: left;
|
|
95
|
+
font-size: 18px;
|
|
96
|
+
font-weight: bold;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.table-title-right {
|
|
100
|
+
margin-left: auto;
|
|
101
|
+
padding: 2px;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.comment-wrapper {
|
|
105
|
+
padding-left: 4px;
|
|
106
|
+
padding-top: 4px;
|
|
107
|
+
padding-bottom: 8px;
|
|
108
|
+
font-size: 14px;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
table {
|
|
112
|
+
border-collapse: collapse;
|
|
113
|
+
margin-top: 0px;
|
|
114
|
+
margin-left: 8px;
|
|
115
|
+
margin-right: 8px;
|
|
116
|
+
margin-bottom: 12px;
|
|
117
|
+
font-size: 14px;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
tr:nth-child(odd) {
|
|
121
|
+
background-color: var(--bg-primary); /* 奇数行の背景色を変更 */
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
tr:nth-child(even) {
|
|
125
|
+
background-color: #ffffff; /* 偶数行の背景色を変更 */
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
th {
|
|
129
|
+
padding-left: 4px;
|
|
130
|
+
padding-right: 4px;
|
|
131
|
+
background-color: var(--primary);
|
|
132
|
+
color: #ffffff;
|
|
133
|
+
border: 1px solid var(--border-gray); /* 線の色と太さを指定 */
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
td {
|
|
137
|
+
border: 1px solid var(--border-primary); /* 線の色と太さを指定 */
|
|
138
|
+
padding-left: 4px;
|
|
139
|
+
padding-right: 4px;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* No */
|
|
143
|
+
td:nth-child(1) {
|
|
144
|
+
width: 16px;
|
|
145
|
+
text-align: center;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* PK */
|
|
149
|
+
td:nth-child(2) {
|
|
150
|
+
width: 24px;
|
|
151
|
+
text-align: center;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* name */
|
|
155
|
+
td:nth-child(3) {
|
|
156
|
+
width: 140px;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* alias */
|
|
160
|
+
td:nth-child(4) {
|
|
161
|
+
width: 180px;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* type */
|
|
165
|
+
td:nth-child(5) {
|
|
166
|
+
width: 60px;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* length */
|
|
170
|
+
td:nth-child(6) {
|
|
171
|
+
width: 40px;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* nullable */
|
|
175
|
+
td:nth-child(7) {
|
|
176
|
+
width: 40px;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/* default */
|
|
180
|
+
td:nth-child(8) {
|
|
181
|
+
width: 120px;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* Foreign Key */
|
|
185
|
+
td:nth-child(9) {
|
|
186
|
+
width: 300px;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* comment */
|
|
190
|
+
td:nth-child(10) {
|
|
191
|
+
width: auto;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* function */
|
|
195
|
+
td:nth-child(11) {
|
|
196
|
+
width: auto;
|
|
197
|
+
}
|
|
198
|
+
</style>
|
|
199
|
+
|
|
200
|
+
<body>
|
|
201
|
+
<h1>${serviceName === undefined ? '' : serviceName + ' :'}Your Table Definition Document</h1>
|
|
202
|
+
`;
|
|
203
|
+
const dbObj = {};
|
|
204
|
+
for (const model of models) {
|
|
205
|
+
if (model.DbName in dbObj === false) {
|
|
206
|
+
dbObj[model.DbName] = [];
|
|
207
|
+
}
|
|
208
|
+
dbObj[model.DbName].push(model);
|
|
209
|
+
}
|
|
210
|
+
const jsCripFuncs = {};
|
|
211
|
+
for (const [keyDbName, models] of Object.entries(dbObj)) {
|
|
212
|
+
html += `
|
|
213
|
+
<div class="db-wrapper">
|
|
214
|
+
<h2>${keyDbName} Database</h2>`;
|
|
215
|
+
for (const model of models) {
|
|
216
|
+
const createFuncName = `clipboard_createTable_${model.DbName}_${model.TableName}`;
|
|
217
|
+
html += `
|
|
218
|
+
<div class="table-wrapper">
|
|
219
|
+
<div class="table-title-wrapper">
|
|
220
|
+
<div class="table-title-left">${model.TableName} ${model.TableDescription !== '' ? ` : ${model.TableDescription}` : ''}</div>
|
|
221
|
+
<button class="table-title-right" onclick="${createFuncName}()">Copy Create Query</button>
|
|
222
|
+
</div>
|
|
223
|
+
<div class="comment-wrapper">${model.Comment.replace('\n', '<br>')}</div>
|
|
224
|
+
|
|
225
|
+
<table>
|
|
226
|
+
<tr>
|
|
227
|
+
<th>No</th>
|
|
228
|
+
<th>PK</th>
|
|
229
|
+
<th>name</th>
|
|
230
|
+
<th>alias</th>
|
|
231
|
+
<th>type</th>
|
|
232
|
+
<th>length</th>
|
|
233
|
+
<th>nullable</th>
|
|
234
|
+
<th>default</th>
|
|
235
|
+
<th>foreign key</th>
|
|
236
|
+
<th>comment</th>
|
|
237
|
+
<th>function</th>
|
|
238
|
+
</tr>`;
|
|
239
|
+
const createColExpressions = [];
|
|
240
|
+
const pkColNames = [];
|
|
241
|
+
let index = 0;
|
|
242
|
+
for (const [keyColName, column] of Object.entries(model.Columns)) {
|
|
243
|
+
index++;
|
|
244
|
+
const addFuncName = `clipboard_addColumn_${model.DbName}_${model.TableName}_${keyColName}`;
|
|
245
|
+
const dropFuncName = `clipboard_dropColumn_${model.DbName}_${model.TableName}_${keyColName}`;
|
|
246
|
+
// 外部キー用
|
|
247
|
+
let references = [];
|
|
248
|
+
for (const ref of model.GetReferences(keyColName)) {
|
|
249
|
+
const targetRef = ref.columns.filter(col => col.target === keyColName);
|
|
250
|
+
if (targetRef.length > 0) {
|
|
251
|
+
references.push(`[${ref.table}].[${targetRef[0].ref}]`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
references = Array.from(new Set(references)); // 重複を除く
|
|
255
|
+
html += `
|
|
256
|
+
<tr>
|
|
257
|
+
<td>${index}</td>
|
|
258
|
+
<td>${column.attribute === 'primary' ? 'PK' : ''}</td>
|
|
259
|
+
<td>${keyColName}</td>
|
|
260
|
+
<td>${(_a = column.alias) !== null && _a !== void 0 ? _a : keyColName}</td>
|
|
261
|
+
<td>${column.type}</td>
|
|
262
|
+
<td>${(_b = column.length) !== null && _b !== void 0 ? _b : ''}</td>
|
|
263
|
+
<td>${column.attribute === 'nullable' ? 'nullable' : ''}</td>
|
|
264
|
+
<td>${column.attribute === 'hasDefault' ? (_c = column.default) !== null && _c !== void 0 ? _c : '???' : ''}</td>
|
|
265
|
+
<td>${references.length === 0 ? '' : references.join('<br>')}</td>
|
|
266
|
+
<td>${((_d = column.comment) !== null && _d !== void 0 ? _d : '').replace('\n', '<br>')}</td>
|
|
267
|
+
<td>
|
|
268
|
+
${column.attribute === "primary" ? `` : `
|
|
269
|
+
<button onclick="${addFuncName}()">Copy add column</button>
|
|
270
|
+
<button onclick="${dropFuncName}()">Copy drop column</button>
|
|
271
|
+
`}
|
|
272
|
+
</td>
|
|
273
|
+
</tr>`;
|
|
274
|
+
jsCripFuncs[addFuncName] = `ALTER TABLE ${model.TableName} ADD COLUMN ${keyColName} ${toColumnType(column)} ${toColumnAttibute(column)};`;
|
|
275
|
+
jsCripFuncs[dropFuncName] = `ALTER TABLE ${model.TableName} DROP COLUMN ${keyColName};`;
|
|
276
|
+
// CreateTable作成用
|
|
277
|
+
createColExpressions.push(`${keyColName} ${toColumnType(column)} ${toColumnAttibute(column)}`);
|
|
278
|
+
if (column.attribute === 'primary') {
|
|
279
|
+
pkColNames.push(keyColName);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
// CreateTable作成文
|
|
283
|
+
const expressions = [...createColExpressions];
|
|
284
|
+
if (pkColNames.length > 0) {
|
|
285
|
+
expressions.push(`PRIMARY KEY (${pkColNames.join(', ')})`);
|
|
286
|
+
}
|
|
287
|
+
for (const ref of model.References) {
|
|
288
|
+
expressions.push(`FOREIGN KEY (${ref.columns.map(col => col.target).join(', ')}) REFERENCES ${ref.table}(${ref.columns.map(col => col.ref).join(', ')})`);
|
|
289
|
+
}
|
|
290
|
+
jsCripFuncs[createFuncName] = `CREATE TABLE ${model.TableName} (\n ${expressions.join(',\n ')}\n);`;
|
|
291
|
+
html += `
|
|
292
|
+
</table>
|
|
293
|
+
</div>`;
|
|
294
|
+
}
|
|
295
|
+
html += `
|
|
296
|
+
</div>`;
|
|
297
|
+
}
|
|
298
|
+
html += `\n <script>\n`;
|
|
299
|
+
for (const [keyFunName, value] of Object.entries(jsCripFuncs)) {
|
|
300
|
+
html += `
|
|
301
|
+
function ${keyFunName}() {
|
|
302
|
+
const el = document.createElement('textarea');
|
|
303
|
+
el.value = \`${value}\`;
|
|
304
|
+
document.body.appendChild(el);
|
|
305
|
+
el.select();
|
|
306
|
+
document.execCommand('copy');
|
|
307
|
+
document.body.removeChild(el);
|
|
308
|
+
alert('コピーしました');
|
|
309
|
+
}\n`;
|
|
310
|
+
}
|
|
311
|
+
html += ` </script>
|
|
312
|
+
</body>
|
|
313
|
+
</html>
|
|
314
|
+
`;
|
|
315
|
+
return html;
|
|
316
|
+
};
|
|
317
|
+
exports.createTableDoc = createTableDoc;
|
|
318
|
+
function toColumnType(column) {
|
|
319
|
+
if (column.type.startsWith('uuid')) {
|
|
320
|
+
return column.type.replace('uuid', 'UUID');
|
|
321
|
+
}
|
|
322
|
+
else if (column.type.startsWith('bool')) {
|
|
323
|
+
return column.type.replace('bool', 'BOOLEAN');
|
|
324
|
+
}
|
|
325
|
+
else if (column.type.startsWith('date')) {
|
|
326
|
+
return column.type.replace('date', 'DATE');
|
|
327
|
+
}
|
|
328
|
+
else if (column.type.startsWith('number')) {
|
|
329
|
+
return column.type.replace('number', 'INTEGER');
|
|
330
|
+
}
|
|
331
|
+
else if (column.type.startsWith('string')) {
|
|
332
|
+
return column.type.replace('string', `VARCHAR(${column.length})`);
|
|
333
|
+
}
|
|
334
|
+
else if (column.type.startsWith('time')) {
|
|
335
|
+
return column.type.replace('time', 'TIME');
|
|
336
|
+
}
|
|
337
|
+
else if (column.type.startsWith('timestamp')) {
|
|
338
|
+
return column.type.replace('timestamp', 'TIMESTAMP');
|
|
339
|
+
}
|
|
340
|
+
return '';
|
|
341
|
+
}
|
|
342
|
+
function toColumnAttibute(column) {
|
|
343
|
+
switch (column.attribute) {
|
|
344
|
+
case 'hasDefault':
|
|
345
|
+
return 'NOT NULL DEFAULT ' + column.default;
|
|
346
|
+
case 'noDefault':
|
|
347
|
+
return 'NOT NULL';
|
|
348
|
+
case 'nullable':
|
|
349
|
+
return 'NULL';
|
|
350
|
+
case 'primary':
|
|
351
|
+
return ''; // 主キーは後で設定するので
|
|
352
|
+
}
|
|
353
|
+
}
|