gg-mysql-connector 1.0.35 → 1.0.37

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.
@@ -0,0 +1,72 @@
1
+ import mysql, { QueryResult, RowDataPacket } from "mysql2";
2
+ import { DatabaseConfigInterface } from "../ModelGenerator/ModelGenerator";
3
+ export interface ClassDBInterface<Main> {
4
+ connection: mysql.Connection;
5
+ query<T>(statement: string, parameter?: object, isPrint?: boolean): Promise<T | QueryResult>;
6
+ getColumnList(tableName: string): Promise<string[]>;
7
+ select<T extends keyof Main>(tableName: T extends string ? T : string): Promise<Main[T][]>;
8
+ selectByID<T extends keyof Main>(tableName: T extends string ? T : string, id: number): Promise<Main[T][]>;
9
+ selectByMatchParams<T extends keyof Main>(tableName: T extends string ? T : string, params: object): Promise<Main[T][]>;
10
+ selectBySearchTextInRow(tableName: string, textToSearch: string): Promise<RowDataPacket[]>;
11
+ insert<T extends keyof Main>(tableName: T, params: any): Promise<mysql.OkPacket>;
12
+ update(tableName: string, parameter: object | object[]): Promise<mysql.OkPacket>;
13
+ updateOnlyID<T extends keyof Main extends string ? keyof Main : string>(tableName: T, params: {
14
+ oldID: number;
15
+ newID: number;
16
+ }): Promise<mysql.OkPacket | null>;
17
+ deleteByID(tableName: string, id: number): Promise<mysql.OkPacket>;
18
+ deleteByMatchParams(tableName: string, parameter: any): Promise<mysql.OkPacket | null>;
19
+ getTableNameList(): Promise<string[]>;
20
+ getViewNameList(): Promise<string[]>;
21
+ getViewNameIfExist(tableName: string): Promise<string>;
22
+ loadTableAndViewNameList(): Promise<string[]>;
23
+ createDatabaseIfNotExist(tempConnection: mysql.Connection): Promise<void>;
24
+ }
25
+ export type Unarray<T> = T extends Array<infer U> ? U : T;
26
+ export default class GGMySQLConnector<Main> implements ClassDBInterface<Main> {
27
+ DBInfo: DatabaseConfigInterface;
28
+ connection: mysql.Connection;
29
+ isPrintStatement: boolean;
30
+ tableAndViewNameList: string[];
31
+ columnAndTableListCache: {
32
+ COLUMN_NAME: string;
33
+ TABLE_NAME: string;
34
+ DATA_TYPE: string;
35
+ }[] | null;
36
+ isConnected: boolean;
37
+ constructor(DBInfo: DatabaseConfigInterface);
38
+ createDatabaseIfNotExist(tempConnection: mysql.Connection): Promise<void>;
39
+ selectBySearchTextInRow(tableName: string, textToSearch: string): Promise<mysql.RowDataPacket[]>;
40
+ loadTableAndViewNameList(): Promise<string[]>;
41
+ getViewNameIfExist(tableName: string): Promise<string>;
42
+ selectByMatchParams<T extends keyof Main>(tableName: T extends string ? T : string, params: Partial<{
43
+ [K in keyof Main[T]]: string | number | undefined | null;
44
+ }>): Promise<Main[T][]>;
45
+ selectByID<T extends keyof Main>(tableName: T extends string ? T : string, id: number): Promise<Main[T][]>;
46
+ select<T extends keyof Main>(tableName: T extends string ? T : string): Promise<Main[T][]>;
47
+ getTableNameList(): Promise<string[]>;
48
+ getViewNameList(): Promise<string[]>;
49
+ deleteByMatchParams<T extends keyof Main>(tableName: T extends string ? T : string, params: Partial<{
50
+ [K in keyof Main[T]]: T | string | number | undefined | null;
51
+ }>): Promise<mysql.OkPacket | null>;
52
+ deleteByID<T extends keyof Main>(tableName: T extends string ? T : string, id: number): Promise<mysql.OkPacket>;
53
+ insert<T extends keyof Main>(tableName: T, parameter: Partial<{
54
+ [R in keyof Unarray<Main[T]>]: any;
55
+ }> | Partial<{
56
+ [R in keyof Unarray<Main[T]>]: any;
57
+ }>[]): Promise<mysql.OkPacket>;
58
+ updateOnlyID<T extends keyof Main extends string ? keyof Main : string>(tableName: T, params: {
59
+ oldID: number;
60
+ newID: number;
61
+ }): Promise<mysql.OkPacket | null>;
62
+ update<T extends keyof Main>(tableName: T extends string ? T : string, parameter: Partial<{
63
+ [K in keyof Main[T]]: Main[T][K];
64
+ }>): Promise<mysql.OkPacket>;
65
+ init(): Promise<void>;
66
+ loadColumnListToCache(): Promise<void>;
67
+ getColumnList(tableName: string): Promise<string[]>;
68
+ getColumnFullList(tableName: string): Promise<mysql.RowDataPacket[]>;
69
+ waitUntilInitSuccess(interval: number): true | Promise<unknown>;
70
+ query<T>(statment: string, parameter?: any[], isPrint?: boolean): Promise<T | QueryResult>;
71
+ private printResultLength;
72
+ }
@@ -0,0 +1,296 @@
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 chalk_1 = __importDefault(require("chalk"));
7
+ const crypto_1 = require("crypto");
8
+ const mysql2_1 = __importDefault(require("mysql2"));
9
+ class GGMySQLConnector {
10
+ constructor(DBInfo) {
11
+ this.printResultLength = (results, executionTime, queryResult) => {
12
+ if (results.length) {
13
+ const executionTimeMessage = executionTime > 1000
14
+ ? chalk_1.default.bgRed(`${executionTime} ` + " ms")
15
+ : chalk_1.default.yellow(`${executionTime} ` + " ms");
16
+ console.log(`${this.DBInfo.database} > ${chalk_1.default.green(queryResult.sql)} ${chalk_1.default.cyan(`found ${results.length} rows.`)} ${executionTimeMessage}`);
17
+ }
18
+ };
19
+ this.isPrintStatement = false;
20
+ this.tableAndViewNameList = [];
21
+ this.columnAndTableListCache = null;
22
+ this.DBInfo = DBInfo;
23
+ this.isConnected = false;
24
+ }
25
+ async createDatabaseIfNotExist(tempConnection) {
26
+ const currentDatabaseName = this.DBInfo.database;
27
+ console.log("currentDatabaseName", currentDatabaseName);
28
+ return new Promise((resolve, reject) => {
29
+ tempConnection.query(`CREATE DATABASE IF NOT EXISTS ${currentDatabaseName}`, () => {
30
+ resolve();
31
+ });
32
+ });
33
+ }
34
+ async selectBySearchTextInRow(tableName, textToSearch) {
35
+ const result = (await this.query(`SELECT * FROM ${tableName}`));
36
+ const wordList = textToSearch.split(" ");
37
+ const temp = result.filter((row) => {
38
+ const rawText = Object.values(row).flat().join(" ");
39
+ const wordFilterResult = wordList.filter((wRow) => rawText.search(wRow) >= 0);
40
+ if (wordFilterResult.length === wordList.length)
41
+ return true;
42
+ return false;
43
+ });
44
+ return temp;
45
+ }
46
+ async loadTableAndViewNameList() {
47
+ let result = (await this.query("SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = ?", [this.DBInfo.database], false));
48
+ this.tableAndViewNameList = result.map((row) => row.TABLE_NAME);
49
+ return this.tableAndViewNameList;
50
+ }
51
+ async getViewNameIfExist(tableName) {
52
+ const tableList = this.tableAndViewNameList;
53
+ const viewPostFixArray = ["_view", "__view", "__view_list"];
54
+ for (let i = 0; i < viewPostFixArray.length; i++) {
55
+ const expectViewName = tableName + viewPostFixArray[i];
56
+ for (let j = 0; j < tableList.length; j++) {
57
+ const row = tableList[j];
58
+ if (row === expectViewName) {
59
+ return expectViewName;
60
+ }
61
+ else if (i == viewPostFixArray.length - 1 &&
62
+ j == tableList.length - 1) {
63
+ return tableName;
64
+ }
65
+ }
66
+ }
67
+ return tableName;
68
+ }
69
+ async selectByMatchParams(tableName, params) {
70
+ const columnList = await this.getColumnList(tableName);
71
+ const keyList = Object.keys(params);
72
+ const keyToSearchList = [];
73
+ const valueToSearchList = [];
74
+ for (const key of keyList) {
75
+ const temp = columnList.find((fkey) => key === fkey);
76
+ if (temp) {
77
+ keyToSearchList.push(` ${key} = ? `);
78
+ valueToSearchList.push(params[key]);
79
+ }
80
+ }
81
+ if (keyToSearchList.length === 0) {
82
+ return [];
83
+ }
84
+ let result = (await this.query(`SELECT * FROM ${tableName} WHERE ${keyToSearchList.join(" AND ")}`, valueToSearchList));
85
+ return result;
86
+ }
87
+ async selectByID(tableName, id) {
88
+ let result = (await this.query(`SELECT * FROM ${tableName} WHERE id = ? LIMIT 1`, [id]));
89
+ return result;
90
+ }
91
+ async select(tableName) {
92
+ let result = (await this.query(`SELECT * FROM ${tableName}`));
93
+ return result;
94
+ }
95
+ async getTableNameList() {
96
+ let data = [];
97
+ let result = (await this.query("SELECT * FROM information_schema.tables WHERE table_schema = ? AND TABLE_TYPE = 'BASE TABLE'", [this.DBInfo.database], false));
98
+ for (let row of result)
99
+ data.push(row.TABLE_NAME || row.row.table_name);
100
+ return data;
101
+ }
102
+ async getViewNameList() {
103
+ let data = [];
104
+ let result = (await this.query("SELECT * FROM information_schema.tables WHERE table_schema = ? AND TABLE_TYPE = 'VIEW'", [this.DBInfo.database], false));
105
+ for (let row of result)
106
+ data.push(row.TABLE_NAME || row.row.table_name);
107
+ return data;
108
+ }
109
+ async deleteByMatchParams(tableName, params) {
110
+ const columnList = await this.getColumnList(tableName);
111
+ const keyList = Object.keys(params);
112
+ const keyToSearchList = [];
113
+ const valueToSearchList = [];
114
+ for (const key of keyList) {
115
+ const temp = columnList.find((fkey) => key === fkey);
116
+ if (temp) {
117
+ keyToSearchList.push(` ${key} = ? `);
118
+ valueToSearchList.push(params[key]);
119
+ }
120
+ }
121
+ if (keyToSearchList.length === 0)
122
+ return null;
123
+ let result = (await this.query(`DELETE FROM ${tableName} WHERE ${keyToSearchList.join(" AND ")}`, valueToSearchList));
124
+ // this.webSocket.sendByURL("/websocket/watchTableChange", tableName)
125
+ return result;
126
+ }
127
+ async deleteByID(tableName, id) {
128
+ let result = (await this.query(`DELETE FROM ${tableName} WHERE id = ?`, [
129
+ id,
130
+ ]));
131
+ console.log("Delete Success");
132
+ // this.webSocket.sendByURL("/websocket/watchTableChange", tableName)
133
+ return result;
134
+ }
135
+ async insert(tableName, parameter) {
136
+ let params = [];
137
+ if (Array.isArray(parameter) === true) {
138
+ params = parameter;
139
+ }
140
+ else
141
+ params = [parameter];
142
+ const columnList = await this.getColumnList(tableName);
143
+ const exampleParams = params[0];
144
+ const keyList = Object.keys(exampleParams);
145
+ const keyListToInsert = [];
146
+ for (const row of keyList) {
147
+ const temp = columnList.find((fRow) => row === fRow);
148
+ if (temp)
149
+ keyListToInsert.push(row);
150
+ }
151
+ const valueArrayToInsertInQuery = [];
152
+ for (let i = 0; i < params.length; i++) {
153
+ const valueListToInsert = [];
154
+ for (const row of keyList) {
155
+ const temp = columnList.find((fRow) => row === fRow);
156
+ if (temp) {
157
+ valueListToInsert.push(params[i][row]);
158
+ }
159
+ }
160
+ valueArrayToInsertInQuery.push(valueListToInsert);
161
+ }
162
+ console.log(valueArrayToInsertInQuery.slice(0, 5));
163
+ const result = (await this.query(`INSERT INTO ${tableName} (${keyListToInsert.join(",")}) VALUES ?`, [valueArrayToInsertInQuery]));
164
+ console.log("Insert Success");
165
+ // this.webSocket.sendByURL("/websocket/watchTableChange", String(tableName))
166
+ return result;
167
+ }
168
+ async updateOnlyID(tableName, params) {
169
+ const isNewIdExist = await this.query(`SELECT * FROM ${tableName} WHERE id = ? `, [params.newID]);
170
+ if (isNewIdExist.length >= 1) {
171
+ console.log(`error : newID (${params.newID}) is already exist`);
172
+ return null;
173
+ }
174
+ let result = (await this.query(`UPDATE ${tableName} SET id = ? WHERE id = ?`, [params.newID, params.oldID], false));
175
+ console.log("UpdateOnlyID Success");
176
+ // this.webSocket.sendByURL("/websocket/watchTableChange", String(tableName))
177
+ return result;
178
+ }
179
+ async update(tableName, parameter) {
180
+ const columnList = await this.getColumnList(tableName);
181
+ console.log(parameter);
182
+ const keyList = Object.keys(parameter);
183
+ const keyListToInsert = [];
184
+ const valueListToInsert = [];
185
+ for (const row of keyList) {
186
+ const temp = columnList.find((fRow) => row === fRow);
187
+ if (temp) {
188
+ keyListToInsert.push(row);
189
+ valueListToInsert.push(parameter[row]);
190
+ }
191
+ }
192
+ // build set sql
193
+ const temp = [];
194
+ let index = 0;
195
+ for (const row of keyListToInsert) {
196
+ if (valueListToInsert[index] === null) {
197
+ temp.push(`${row} = NULL`);
198
+ }
199
+ else {
200
+ let value = valueListToInsert[index];
201
+ if (typeof value === "string") {
202
+ value = value.replace(/'/g, "");
203
+ }
204
+ temp.push(`${row} = '${value}'`);
205
+ }
206
+ index++;
207
+ }
208
+ let result = (await this.query(`UPDATE ${tableName} SET ${temp.join(",")} WHERE id = ${parameter.id}`, [], false));
209
+ console.log("Update Success");
210
+ // this.webSocket.sendByURL("/websocket/watchTableChange", String(tableName))
211
+ return result;
212
+ }
213
+ async init() {
214
+ const currentConnection = mysql2_1.default.createConnection({
215
+ host: this.DBInfo.host,
216
+ user: this.DBInfo.user,
217
+ password: this.DBInfo.password,
218
+ });
219
+ this.isConnected = true;
220
+ await this.createDatabaseIfNotExist(currentConnection);
221
+ // await currentConnection.end()
222
+ this.connection = mysql2_1.default.createConnection(Object.assign({}, this.DBInfo));
223
+ // await this.query("SET global sql_mode=''")
224
+ // await this.query("SET global query_cache_type='ON'")
225
+ // await this.query("SET global query_cache_size=16777216")
226
+ // await this.query("SET global query_cache_limit=16777216")
227
+ await this.loadTableAndViewNameList();
228
+ await this.loadColumnListToCache();
229
+ }
230
+ async loadColumnListToCache() {
231
+ const result = (await this.query(`SELECT COLUMN_NAME,TABLE_NAME,DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '${this.DBInfo.database}'`, undefined, false));
232
+ this.columnAndTableListCache = result;
233
+ }
234
+ async getColumnList(tableName) {
235
+ if (this.columnAndTableListCache !== null) {
236
+ return this.columnAndTableListCache
237
+ .filter((row) => row.TABLE_NAME === tableName)
238
+ .map((row) => row.COLUMN_NAME);
239
+ }
240
+ const result = await this.query(`SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '${this.DBInfo.database}' AND TABLE_NAME = '${tableName}'`, undefined, false);
241
+ return result.map((row) => row.COLUMN_NAME);
242
+ }
243
+ async getColumnFullList(tableName) {
244
+ const result = (await this.query(`SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '${this.DBInfo.database}' AND TABLE_NAME = '${tableName}'`, undefined, false));
245
+ return result;
246
+ }
247
+ waitUntilInitSuccess(interval) {
248
+ if (this.isConnected === true)
249
+ return true;
250
+ return new Promise((resolve, reject) => {
251
+ setTimeout(() => {
252
+ if (this.isConnected === false) {
253
+ console.log(`${this.DBInfo.database} > wait for database connection . . .`);
254
+ this.waitUntilInitSuccess(interval);
255
+ }
256
+ else {
257
+ return resolve(true);
258
+ }
259
+ }, interval);
260
+ });
261
+ }
262
+ async query(statment, parameter, isPrint) {
263
+ await this.waitUntilInitSuccess(1000);
264
+ return new Promise((resolve, reject) => {
265
+ const uniqueTime = `${(0, crypto_1.randomUUID)()} ${statment}`;
266
+ console.time(uniqueTime);
267
+ const startTime = new Date();
268
+ const queryResult = this.connection.query(statment, parameter, (error, results, fields) => {
269
+ if (error) {
270
+ // _getCallerFile()
271
+ console.log(chalk_1.default.bgRed("Query Error"));
272
+ console.log(chalk_1.default.bgRed(error));
273
+ console.log(chalk_1.default.bgRed("Statement : "));
274
+ console.log(statment);
275
+ console.log(chalk_1.default.bgRed("Parameter : "));
276
+ console.log(parameter);
277
+ console.log("------------------------------------------------");
278
+ console.log(chalk_1.default.bgRed(queryResult.sql));
279
+ reject(error);
280
+ }
281
+ else {
282
+ const endTime = new Date();
283
+ const executionTime = endTime.getTime() - startTime.getTime();
284
+ if (isPrint === true) {
285
+ this.printResultLength(results, executionTime, queryResult);
286
+ }
287
+ else if (this.isPrintStatement) {
288
+ this.printResultLength(results, executionTime, queryResult);
289
+ }
290
+ resolve(results);
291
+ }
292
+ });
293
+ });
294
+ }
295
+ }
296
+ exports.default = GGMySQLConnector;
@@ -0,0 +1,38 @@
1
+ import mysql from "mysql2/promise";
2
+ import { MyModel } from "../myModel";
3
+ export interface DatabaseConfigInterface {
4
+ host: string;
5
+ user: string;
6
+ password: string;
7
+ database: string;
8
+ }
9
+ export default class ModelGenerator {
10
+ model: MyModel[];
11
+ dbInfo: DatabaseConfigInterface;
12
+ connection: mysql.Connection;
13
+ isConnected: boolean;
14
+ constructor(dbInfo: DatabaseConfigInterface, model: MyModel[]);
15
+ init(): Promise<void>;
16
+ private createDatabaseIfNotExist;
17
+ pushModelToDB(): Promise<void>;
18
+ pushViewToDB(viewDirectory: string): Promise<void>;
19
+ waitUntilInitSuccess(interval: number): true | Promise<unknown>;
20
+ query<T>(statment: string, parameter?: any[], isPrint?: boolean): Promise<T>;
21
+ private printResultLength;
22
+ getTableNameList(): Promise<string[]>;
23
+ getViewNameList(): Promise<string[]>;
24
+ getColumnFullList(tableName: string): Promise<mysql.RowDataPacket[]>;
25
+ private isTableNameExistInModel;
26
+ private isColumnExistInModel;
27
+ getPossibleColumnValue(model: MyModel[], tableName: string, columnName: string): false | any[] | undefined;
28
+ generateModelInterface(params: {
29
+ appName: string;
30
+ model: MyModel[];
31
+ outputDirectory: string[];
32
+ }): Promise<string>;
33
+ generateModelConstStructure(params: {
34
+ appName: string;
35
+ model: MyModel[];
36
+ outputDirectory: string[];
37
+ }): Promise<string>;
38
+ }
@@ -0,0 +1,299 @@
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 chalk_1 = __importDefault(require("chalk"));
7
+ const crypto_1 = require("crypto");
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const promise_1 = __importDefault(require("mysql2/promise"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const MyDBMigrator_1 = __importDefault(require("../MyDBMigrator/MyDBMigrator"));
12
+ class ModelGenerator {
13
+ constructor(dbInfo, model) {
14
+ this.printResultLength = (results, executionTime, queryResult) => {
15
+ if (results.length) {
16
+ const executionTimeMessage = executionTime > 1000
17
+ ? chalk_1.default.bgRed(`${executionTime} ` + " ms")
18
+ : chalk_1.default.yellow(`${executionTime} ` + " ms");
19
+ console.log(`${chalk_1.default.green(queryResult.sql)} ${chalk_1.default.cyan(`found ${results.length} rows.`)} ${executionTimeMessage}`);
20
+ }
21
+ };
22
+ this.model = model;
23
+ this.dbInfo = dbInfo;
24
+ this.isConnected = false;
25
+ }
26
+ async init() {
27
+ console.log("init");
28
+ this.connection = await promise_1.default.createConnection({
29
+ host: this.dbInfo.host,
30
+ user: this.dbInfo.user,
31
+ password: this.dbInfo.password,
32
+ });
33
+ this.isConnected = true;
34
+ await this.createDatabaseIfNotExist();
35
+ }
36
+ async createDatabaseIfNotExist() {
37
+ const databaseName = this.dbInfo.database;
38
+ await this.connection.query(`CREATE DATABASE IF NOT EXISTS ${databaseName}`);
39
+ await this.connection.query(`USE ${databaseName}`);
40
+ }
41
+ async pushModelToDB() {
42
+ const migrator = new MyDBMigrator_1.default(this);
43
+ await migrator.migrateTable(this.model);
44
+ }
45
+ async pushViewToDB(viewDirectory) {
46
+ const migrator = new MyDBMigrator_1.default(this);
47
+ await migrator.migrateView(viewDirectory);
48
+ }
49
+ waitUntilInitSuccess(interval) {
50
+ if (this.isConnected === true)
51
+ return true;
52
+ return new Promise((resolve, reject) => {
53
+ setTimeout(() => {
54
+ if (this.isConnected === false) {
55
+ console.log(`${this.dbInfo.database} > wait for database connection . . .`);
56
+ this.waitUntilInitSuccess(interval);
57
+ }
58
+ else {
59
+ return resolve(true);
60
+ }
61
+ }, interval);
62
+ });
63
+ }
64
+ async query(statment, parameter, isPrint) {
65
+ await this.waitUntilInitSuccess(1000);
66
+ return new Promise((resolve, reject) => {
67
+ const uniqueTime = `${(0, crypto_1.randomUUID)()} ${statment}`;
68
+ console.time(uniqueTime);
69
+ const startTime = new Date();
70
+ const queryResult = this.connection
71
+ .query(statment, parameter)
72
+ .then((result) => {
73
+ const endTime = new Date();
74
+ const executionTime = endTime.getTime() - startTime.getTime();
75
+ if (isPrint === true)
76
+ this.printResultLength(result, executionTime, queryResult);
77
+ resolve(result[0]);
78
+ })
79
+ .catch((error) => {
80
+ // _getCallerFile()
81
+ console.log(chalk_1.default.bgRed("Query Error"));
82
+ console.log(chalk_1.default.bgRed(error));
83
+ console.log(chalk_1.default.bgRed("Statement : "));
84
+ console.log(statment);
85
+ console.log(chalk_1.default.bgRed("Parameter : "));
86
+ console.log(parameter);
87
+ console.log("------------------------------------------------");
88
+ console.log(chalk_1.default.bgRed(queryResult.sql));
89
+ reject(error);
90
+ });
91
+ });
92
+ }
93
+ async getTableNameList() {
94
+ let data = [];
95
+ let result = (await this.query("SELECT * FROM information_schema.tables WHERE table_schema = ? AND TABLE_TYPE = 'BASE TABLE'", [this.dbInfo.database], false));
96
+ for (let row of result)
97
+ data.push(row.TABLE_NAME || row.row.table_name);
98
+ return data;
99
+ }
100
+ async getViewNameList() {
101
+ let data = [];
102
+ let result = (await this.query("SELECT * FROM information_schema.tables WHERE table_schema = ? AND TABLE_TYPE = 'VIEW'", [this.dbInfo.database], false));
103
+ for (let row of result)
104
+ data.push(row.TABLE_NAME || row.row.table_name);
105
+ return data;
106
+ }
107
+ async getColumnFullList(tableName) {
108
+ const result = (await this.query(`SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '${this.dbInfo.database}' AND TABLE_NAME = '${tableName}'`, undefined, false));
109
+ return result;
110
+ }
111
+ isTableNameExistInModel(model, tableName) {
112
+ if (tableName === "sessions")
113
+ return true;
114
+ const table = model.find((row) => row.tableName === tableName);
115
+ return table ? true : false;
116
+ }
117
+ isColumnExistInModel(model, tableName, columnName) {
118
+ if (tableName === "sessions")
119
+ return true;
120
+ const table = model.find((row) => row.tableName === tableName);
121
+ if (table) {
122
+ const column = table.columns.find((row) => row.COLUMN_NAME === columnName);
123
+ if (column)
124
+ return true;
125
+ }
126
+ return false;
127
+ }
128
+ getPossibleColumnValue(model, tableName, columnName) {
129
+ const foundTable = model.find((row) => row.tableName === tableName);
130
+ if (foundTable) {
131
+ const foundColumn = foundTable["columns"].find((row) => row.COLUMN_NAME === columnName);
132
+ if (foundColumn) {
133
+ if (foundColumn.POSSIBLE_VALUE)
134
+ return foundColumn.POSSIBLE_VALUE;
135
+ }
136
+ else
137
+ return false;
138
+ }
139
+ }
140
+ async generateModelInterface(params) {
141
+ const tableList = [
142
+ ...(await this.getTableNameList()),
143
+ ...(await this.getViewNameList()),
144
+ ];
145
+ const arrayOfColumnKeyValue = [];
146
+ const arrayOfSeedColumnKeyValue = [];
147
+ for (let i = 0; i < tableList.length; i++) {
148
+ const tableName = tableList[i];
149
+ if (this.isTableNameExistInModel(params.model, tableName) ||
150
+ tableName.search("_view") >= 0) {
151
+ const columnList = await this.getColumnFullList(tableName);
152
+ let stringOfRawColumnKeyAndValue = "";
153
+ for (const cRow of columnList) {
154
+ const isColumnExistInModel = this.isColumnExistInModel(params.model, tableName, cRow.COLUMN_NAME);
155
+ if (isColumnExistInModel || tableName.search("_view") >= 0) {
156
+ const possibleValue = this.getPossibleColumnValue(params.model, cRow.TABLE_NAME, cRow.COLUMN_NAME);
157
+ if (possibleValue) {
158
+ stringOfRawColumnKeyAndValue = `${stringOfRawColumnKeyAndValue} \n ${cRow.COLUMN_NAME}: ${possibleValue.map((row) => `"${row}"`).join(" | ")};`;
159
+ }
160
+ else {
161
+ stringOfRawColumnKeyAndValue = `${stringOfRawColumnKeyAndValue} \n ${cRow.COLUMN_NAME}: ${convertDataType(cRow.DATA_TYPE)};`;
162
+ }
163
+ }
164
+ else {
165
+ console.log(`${tableName}-${cRow.COLUMN_NAME} not exist in model `);
166
+ }
167
+ }
168
+ // normal app model code
169
+ const str = ` ${tableName} : { ${stringOfRawColumnKeyAndValue} }`;
170
+ arrayOfColumnKeyValue.push(str);
171
+ // only seed model code
172
+ const tempSeedModel = params.model.find((row) => row.tableName === tableName && row.isSeed);
173
+ if (tempSeedModel)
174
+ arrayOfSeedColumnKeyValue.push(str);
175
+ }
176
+ }
177
+ // normal app model code
178
+ const fileName = `${params.appName}_INF.ts`;
179
+ const seedFileName = `seed_INF.ts`;
180
+ const code = `export default interface ${params.appName}_INF { ${arrayOfColumnKeyValue.join("\n")} }`;
181
+ const seedCode = `export default interface seed_INF { ${arrayOfSeedColumnKeyValue.join("\n")} }`;
182
+ for (let row of params.outputDirectory) {
183
+ // normal app model code
184
+ const serverFilePath = path_1.default.join(row, fileName);
185
+ await fs_1.default.writeFileSync(serverFilePath, code);
186
+ console.log("save app model to ", serverFilePath);
187
+ // only seed model code
188
+ const seedServerFilePath = path_1.default.join(row, seedFileName);
189
+ await fs_1.default.writeFileSync(seedServerFilePath, seedCode);
190
+ console.log("save seed model to ", seedServerFilePath);
191
+ }
192
+ console.log(`generate interface ${params.appName} ${chalk_1.default.bgGreen(" SUCCESS ")}`);
193
+ return code;
194
+ }
195
+ async generateModelConstStructure(params) {
196
+ const isTableNameExistInModel = (tableName) => {
197
+ if (tableName === "sessions")
198
+ return true;
199
+ const table = params.model.find((row) => row.tableName === tableName);
200
+ if (table)
201
+ return true;
202
+ return false;
203
+ };
204
+ const isColumnExistInModel = (tableName, columnName) => {
205
+ if (tableName === "sessions")
206
+ return true;
207
+ const table = params.model.find((row) => row.tableName === tableName);
208
+ if (table) {
209
+ const column = table.columns.find((row) => row.COLUMN_NAME === columnName);
210
+ if (column)
211
+ return true;
212
+ }
213
+ return false;
214
+ };
215
+ const getPossibleColumnValue = (tableName, columnName) => {
216
+ const foundTable = params.model.find((row) => row.tableName === tableName);
217
+ if (foundTable) {
218
+ const foundColumn = foundTable["columns"].find((row) => row.COLUMN_NAME === columnName);
219
+ if (foundColumn) {
220
+ if (foundColumn.POSSIBLE_VALUE)
221
+ return foundColumn.POSSIBLE_VALUE;
222
+ }
223
+ else
224
+ return false;
225
+ }
226
+ };
227
+ const tableList = [
228
+ ...(await this.getTableNameList()),
229
+ ...(await this.getViewNameList()),
230
+ ];
231
+ const array = [];
232
+ for (let i = 0; i < tableList.length; i++) {
233
+ const tableName = tableList[i];
234
+ if (isTableNameExistInModel(tableName) ||
235
+ tableName.search("_view") >= 0) {
236
+ const columnList = await this.getColumnFullList(tableName);
237
+ let value = "";
238
+ for (const cRow of columnList) {
239
+ const columnChecker = isColumnExistInModel(tableName, cRow.COLUMN_NAME);
240
+ if (columnChecker || tableName.search("_view") >= 0) {
241
+ const possibleValue = getPossibleColumnValue(cRow.TABLE_NAME, cRow.COLUMN_NAME);
242
+ if (possibleValue) {
243
+ value = `${value} \n ${cRow.COLUMN_NAME}: [${possibleValue
244
+ .map((row) => {
245
+ if (typeof row === "string")
246
+ return `"${row}"`;
247
+ else if (typeof row === "number")
248
+ return `${row}`;
249
+ })
250
+ .join(" , ")}] as ${typeof possibleValue[0]}[],`;
251
+ }
252
+ else {
253
+ value = `${value} \n ${cRow.COLUMN_NAME}: "${convertDataType(cRow.DATA_TYPE)}",`;
254
+ }
255
+ }
256
+ else {
257
+ console.log(`${tableName}-${cRow.COLUMN_NAME} not exist in model `);
258
+ }
259
+ }
260
+ const str = ` ${tableName} : { ${value} }`;
261
+ array.push(str);
262
+ // console.log(`generate interface from ${tableName}`)
263
+ }
264
+ }
265
+ const fileName = `${params.appName}_model_const.ts`;
266
+ const code = `
267
+ export const ${params.appName}_model_const = { ${array.join(",")} } as const`;
268
+ for (let row of params.outputDirectory) {
269
+ const serverFilePath = path_1.default.join(row, fileName);
270
+ await fs_1.default.writeFileSync(serverFilePath, code);
271
+ console.log("save to ", serverFilePath);
272
+ }
273
+ console.log(`generate interface ${params.appName} ${chalk_1.default.bgGreen(" SUCCESS ")}`);
274
+ return code;
275
+ }
276
+ }
277
+ exports.default = ModelGenerator;
278
+ function convertDataType(inputDataType) {
279
+ let result = "string";
280
+ if (inputDataType === "int") {
281
+ result = "number";
282
+ }
283
+ else if (inputDataType === "tinyint") {
284
+ result = "number";
285
+ }
286
+ else if (inputDataType === "bigint") {
287
+ result = "number";
288
+ }
289
+ else if (inputDataType === "date") {
290
+ result = "string";
291
+ }
292
+ else if (inputDataType === "float") {
293
+ result = "number";
294
+ }
295
+ else if (inputDataType === "double") {
296
+ result = "number";
297
+ }
298
+ return result;
299
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function generateSeedInterface(model) { }
@@ -253,15 +253,7 @@ class ModelGenerator {
253
253
  }
254
254
  const fileName = `${params.appName}_model_const.ts`;
255
255
  const code = `
256
- type paramType = "number" | "string" | "any" | string[] | number[]
257
- interface constInterface {
258
- [keytable: string]: {
259
- [key: string]: paramType
260
- }
261
- }
262
-
263
-
264
- export const ${params.appName}_model_const : constInterface = { ${array.join(",")} } as const`;
256
+ export const ${params.appName}_model_const = { ${array.join(",")} } as const`;
265
257
  for (let row of params.outputDirectory) {
266
258
  const serverFilePath = path_1.default.join(row, fileName);
267
259
  await fs_1.default.writeFileSync(serverFilePath, code);
@@ -0,0 +1,22 @@
1
+ import ModelGenerator from "../ModelGenerator/ModelGenerator";
2
+ import { columnType, MyModel } from "../myModel";
3
+ export default class MyDBMigrator {
4
+ MyDB: ModelGenerator;
5
+ onetimeLoadColumnContent: {
6
+ COLUMN_NAME: string;
7
+ DATA_TYPE: columnType;
8
+ TABLE_NAME: string;
9
+ COLUMN_DEFAULT: string;
10
+ COLUMN_KEY: string;
11
+ }[];
12
+ constructor(connection: ModelGenerator);
13
+ migrateTable(model: MyModel[]): Promise<void>;
14
+ private createTableIfNotExist;
15
+ private columnInTableExist;
16
+ private loadColumnContentIfEmpty;
17
+ private checkIsColumnDataTypeChange;
18
+ alterUniqueKey(tableName: string, columnName: string, IS_UNIQUE: boolean | undefined): Promise<void>;
19
+ alterIndex(tableName: string, columnName: string, IS_INDEX: boolean | undefined): Promise<void>;
20
+ migrateView(viewDirectory: string): Promise<0 | undefined>;
21
+ checkIsPrimaryKey(databaseName: string, tableName: string, columnName: string): Promise<boolean>;
22
+ }
@@ -0,0 +1,157 @@
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 chalk_1 = __importDefault(require("chalk"));
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ class MyDBMigrator {
10
+ constructor(connection) {
11
+ this.MyDB = connection;
12
+ this.onetimeLoadColumnContent = [];
13
+ }
14
+ async migrateTable(model) {
15
+ let data = model.filter((row) => row.tableName !== "sessions" && row.tableName.search("prisma") < 0);
16
+ let index = 1;
17
+ for (let row of data) {
18
+ console.log(chalk_1.default.bgBlue(`${index}/${data.length} ${row.tableName}`));
19
+ await this.createTableIfNotExist(row.tableName);
20
+ this.onetimeLoadColumnContent = [];
21
+ await this.loadColumnContentIfEmpty();
22
+ index++;
23
+ for (let col of row.columns) {
24
+ console.log(`${row.tableName} (${col.DATA_TYPE}) - ${col.COLUMN_NAME} `);
25
+ if (col.COLUMN_NAME === "id" && col.AUTO_INCREMENT === true) {
26
+ if ((await this.checkIsPrimaryKey(this.MyDB.dbInfo.database, row.tableName, col.COLUMN_NAME)) === false)
27
+ await this.MyDB.query(`ALTER TABLE ${row.tableName} ADD PRIMARY KEY(id);`);
28
+ }
29
+ const AutoIncrement = col.AUTO_INCREMENT ? "AUTO_INCREMENT" : "";
30
+ const columnDefault = col.COLUMN_DEFAULT
31
+ ? `DEFAULT ${col.COLUMN_DEFAULT}`
32
+ : "";
33
+ const isColumnChange = await this.checkIsColumnDataTypeChange(row.tableName, col.COLUMN_NAME, col.DATA_TYPE, col.COLUMN_DEFAULT);
34
+ if (isColumnChange) {
35
+ const isColumnExist = await this.columnInTableExist(row.tableName, col.COLUMN_NAME);
36
+ if (!isColumnExist) {
37
+ await this.MyDB.query(`ALTER TABLE ${row.tableName} ADD COLUMN ${col.COLUMN_NAME} ${col.DATA_TYPE} ${AutoIncrement} ${columnDefault}`);
38
+ }
39
+ else {
40
+ await this.MyDB.query(`ALTER TABLE ${row.tableName} MODIFY COLUMN ${col.COLUMN_NAME} ${col.DATA_TYPE} ${AutoIncrement} ${columnDefault}`);
41
+ }
42
+ }
43
+ await this.alterUniqueKey(row.tableName, col.COLUMN_NAME, col.IS_UNIQUE);
44
+ await this.alterIndex(row.tableName, col.COLUMN_NAME, col.IS_INDEX);
45
+ }
46
+ }
47
+ console.log("migrate table done");
48
+ }
49
+ async createTableIfNotExist(tableName) {
50
+ await this.MyDB.query(`CREATE TABLE IF NOT EXISTS ${tableName} (id INT(11) AUTO_INCREMENT PRIMARY KEY)`);
51
+ }
52
+ async columnInTableExist(tableName, columnName) {
53
+ await this.loadColumnContentIfEmpty();
54
+ let result = this.onetimeLoadColumnContent.filter((row) => row.COLUMN_NAME === columnName && row.TABLE_NAME === tableName);
55
+ if (result.length)
56
+ return true;
57
+ else
58
+ return false;
59
+ }
60
+ async loadColumnContentIfEmpty() {
61
+ if (this.onetimeLoadColumnContent.length === 0) {
62
+ this.onetimeLoadColumnContent = (await this.MyDB.query(`SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '${this.MyDB.dbInfo.database}'`, undefined, false));
63
+ }
64
+ }
65
+ async checkIsColumnDataTypeChange(tableName, columnName, dataType, columnDefault) {
66
+ await this.loadColumnContentIfEmpty();
67
+ let temp = this.onetimeLoadColumnContent.filter((row) => row.TABLE_NAME === tableName && row.COLUMN_NAME === columnName);
68
+ if (columnDefault === undefined)
69
+ columnDefault = "NULL";
70
+ if (columnDefault === null)
71
+ columnDefault = "NULL";
72
+ if (temp.length > 0) {
73
+ if (temp[0].DATA_TYPE !== dataType) {
74
+ console.log(chalk_1.default.green `${temp[0].DATA_TYPE} change to ${dataType}`);
75
+ return true;
76
+ }
77
+ if (temp[0].COLUMN_DEFAULT !== columnDefault) {
78
+ console.log(chalk_1.default.green `${temp[0].COLUMN_DEFAULT} change to ${columnDefault}`);
79
+ return true;
80
+ }
81
+ return false;
82
+ }
83
+ else {
84
+ console.log(chalk_1.default.red `${columnName} not found`);
85
+ return true;
86
+ }
87
+ }
88
+ async alterUniqueKey(tableName, columnName, IS_UNIQUE) {
89
+ const data = this.onetimeLoadColumnContent.find((row) => row.COLUMN_NAME === columnName && row.TABLE_NAME === tableName);
90
+ if (data) {
91
+ if ((data.COLUMN_KEY === "UNI" && !IS_UNIQUE) ||
92
+ (data.COLUMN_KEY !== "UNI" && IS_UNIQUE === true))
93
+ if (IS_UNIQUE === true) {
94
+ await this.MyDB.query(`ALTER TABLE ${tableName} ADD UNIQUE (${columnName});`);
95
+ }
96
+ else {
97
+ await this.MyDB.query(`ALTER TABLE ${tableName} DROP INDEX ${columnName};`);
98
+ }
99
+ }
100
+ }
101
+ async alterIndex(tableName, columnName, IS_INDEX) {
102
+ const data = this.onetimeLoadColumnContent.find((row) => row.COLUMN_NAME === columnName && row.TABLE_NAME === tableName);
103
+ if (data) {
104
+ if ((data.COLUMN_KEY === "MUL" && !IS_INDEX) ||
105
+ (data.COLUMN_KEY !== "MUL" && IS_INDEX === true))
106
+ if (IS_INDEX === true) {
107
+ await this.MyDB.query(`ALTER TABLE ${tableName} ADD INDEX (${columnName});`);
108
+ }
109
+ else {
110
+ await this.MyDB.query(`DROP INDEX ${columnName} ON ${tableName};`);
111
+ }
112
+ }
113
+ }
114
+ async migrateView(viewDirectory) {
115
+ if (!fs_1.default.existsSync(viewDirectory)) {
116
+ return 0;
117
+ }
118
+ let fileList = (await fs_1.default.readdirSync(path_1.default.join(viewDirectory)));
119
+ let unSuccessUpdateViewList = fileList;
120
+ let loopCount = 0;
121
+ while (unSuccessUpdateViewList.length > 0) {
122
+ for (const viewFileName of unSuccessUpdateViewList) {
123
+ const filePath = path_1.default.join(viewDirectory, viewFileName);
124
+ const content = fs_1.default.readFileSync(filePath, "utf8");
125
+ process.stdout.write(`loop : ${loopCount} unUpdate : ${unSuccessUpdateViewList.length} update view ${viewFileName}`);
126
+ await this.MyDB.query(content)
127
+ .then((result) => {
128
+ process.stdout.write(" " + chalk_1.default.bgGreen(`success`));
129
+ unSuccessUpdateViewList = unSuccessUpdateViewList.filter((row) => row !== viewFileName);
130
+ })
131
+ .catch((_error) => {
132
+ process.stdout.write(" " + chalk_1.default.bgRed(`fail`));
133
+ })
134
+ .finally(() => {
135
+ console.log("");
136
+ });
137
+ }
138
+ }
139
+ }
140
+ async checkIsPrimaryKey(databaseName, tableName, columnName) {
141
+ let result = await this.MyDB.query(`SELECT *
142
+ FROM INFORMATION_SCHEMA.COLUMNS
143
+ WHERE TABLE_SCHEMA='${databaseName}'
144
+ AND TABLE_NAME='${tableName}'
145
+ AND COLUMN_NAME='${columnName}'`);
146
+ console.log("result", result);
147
+ if (result.length) {
148
+ if (result[0].COLUMN_KEY === "PRI")
149
+ return true;
150
+ else
151
+ return false;
152
+ }
153
+ else
154
+ return false;
155
+ }
156
+ }
157
+ exports.default = MyDBMigrator;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { MyModel, columnContent, columnType } from "./myModel";
2
- export { DatabaseConfigInterface } from "./ModelGenerator";
3
- export { default as ModelGenerator } from "./ModelGenerator";
4
- export { default as GGMySQLConnector } from "./GGMySQLConnector";
2
+ export { DatabaseConfigInterface } from "./ModelGenerator/ModelGenerator";
3
+ export { default as ModelGenerator } from "./ModelGenerator/ModelGenerator";
4
+ export { default as GGMySQLConnector } from "./GGMySQLConnector/GGMySQLConnector";
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.GGMySQLConnector = exports.ModelGenerator = void 0;
7
- var ModelGenerator_1 = require("./ModelGenerator");
7
+ var ModelGenerator_1 = require("./ModelGenerator/ModelGenerator");
8
8
  Object.defineProperty(exports, "ModelGenerator", { enumerable: true, get: function () { return __importDefault(ModelGenerator_1).default; } });
9
- var GGMySQLConnector_1 = require("./GGMySQLConnector");
9
+ var GGMySQLConnector_1 = require("./GGMySQLConnector/GGMySQLConnector");
10
10
  Object.defineProperty(exports, "GGMySQLConnector", { enumerable: true, get: function () { return __importDefault(GGMySQLConnector_1).default; } });
package/dist/myModel.d.ts CHANGED
@@ -9,9 +9,8 @@ export interface columnContent {
9
9
  IS_INDEX?: boolean;
10
10
  }
11
11
  export interface MyModel {
12
+ isSeed: boolean;
12
13
  tableName: string;
13
- columns: [
14
- ...columnContent[]
15
- ];
14
+ columns: [...columnContent[]];
16
15
  meaning?: string;
17
16
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gg-mysql-connector",
3
- "version": "1.0.35",
3
+ "version": "1.0.37",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -1,7 +1,7 @@
1
1
  import chalk from "chalk"
2
2
  import { randomUUID } from "crypto"
3
3
  import mysql, { QueryResult, RowDataPacket } from "mysql2"
4
- import { DatabaseConfigInterface } from "./ModelGenerator"
4
+ import { DatabaseConfigInterface } from "../ModelGenerator/ModelGenerator"
5
5
 
6
6
  export interface ClassDBInterface<Main> {
7
7
  connection: mysql.Connection
@@ -3,8 +3,8 @@ import { randomUUID } from "crypto"
3
3
  import fs from "fs"
4
4
  import mysql from "mysql2/promise"
5
5
  import path from "path"
6
- import MyDBMigration from "./MyDBMigration"
7
- import { MyModel } from "./myModel"
6
+ import MyDBMigrator from "../MyDBMigrator/MyDBMigrator"
7
+ import { MyModel } from "../myModel"
8
8
  export interface DatabaseConfigInterface {
9
9
  host: string
10
10
  user: string
@@ -39,11 +39,11 @@ export default class ModelGenerator {
39
39
  }
40
40
 
41
41
  async pushModelToDB() {
42
- const migrator = new MyDBMigration(this)
42
+ const migrator = new MyDBMigrator(this)
43
43
  await migrator.migrateTable(this.model)
44
44
  }
45
45
  async pushViewToDB(viewDirectory: string) {
46
- const migrator = new MyDBMigration(this)
46
+ const migrator = new MyDBMigrator(this)
47
47
  await migrator.migrateView(viewDirectory)
48
48
  }
49
49
  waitUntilInitSuccess(interval: number) {
@@ -142,70 +142,79 @@ export default class ModelGenerator {
142
142
  )) as mysql.RowDataPacket[]
143
143
  return result
144
144
  }
145
+
146
+ private isTableNameExistInModel(model: MyModel[], tableName: string) {
147
+ if (tableName === "sessions") return true
148
+ const table = model.find((row) => row.tableName === tableName)
149
+ return table ? true : false
150
+ }
151
+ private isColumnExistInModel(
152
+ model: MyModel[],
153
+ tableName: string,
154
+ columnName: string
155
+ ) {
156
+ if (tableName === "sessions") return true
157
+ const table = model.find((row) => row.tableName === tableName)
158
+ if (table) {
159
+ const column = table.columns.find((row) => row.COLUMN_NAME === columnName)
160
+ if (column) return true
161
+ }
162
+ return false
163
+ }
164
+ getPossibleColumnValue(
165
+ model: MyModel[],
166
+ tableName: string,
167
+ columnName: string
168
+ ) {
169
+ const foundTable = model.find((row) => row.tableName === tableName)
170
+ if (foundTable) {
171
+ const foundColumn = foundTable["columns"].find(
172
+ (row) => row.COLUMN_NAME === columnName
173
+ )
174
+ if (foundColumn) {
175
+ if (foundColumn.POSSIBLE_VALUE) return foundColumn.POSSIBLE_VALUE
176
+ } else return false
177
+ }
178
+ }
145
179
  async generateModelInterface(params: {
146
180
  appName: string
147
181
  model: MyModel[]
148
182
  outputDirectory: string[]
149
183
  }) {
150
- const isTableNameExistInModel = (tableName: string) => {
151
- if (tableName === "sessions") return true
152
- const table = params.model.find((row) => row.tableName === tableName)
153
- if (table) return true
154
- return false
155
- }
156
- const isColumnExistInModel = (tableName: string, columnName: string) => {
157
- if (tableName === "sessions") return true
158
- const table = params.model.find((row) => row.tableName === tableName)
159
- if (table) {
160
- const column = table.columns.find(
161
- (row) => row.COLUMN_NAME === columnName
162
- )
163
- if (column) return true
164
- }
165
- return false
166
- }
167
- const getPossibleColumnValue = (tableName: string, columnName: string) => {
168
- const foundTable = params.model.find((row) => row.tableName === tableName)
169
- if (foundTable) {
170
- const foundColumn = foundTable["columns"].find(
171
- (row) => row.COLUMN_NAME === columnName
172
- )
173
- if (foundColumn) {
174
- if (foundColumn.POSSIBLE_VALUE) return foundColumn.POSSIBLE_VALUE
175
- } else return false
176
- }
177
- }
178
184
  const tableList = [
179
185
  ...(await this.getTableNameList()),
180
186
  ...(await this.getViewNameList()),
181
187
  ]
182
188
 
183
- const array = []
189
+ const arrayOfColumnKeyValue = []
190
+ const arrayOfSeedColumnKeyValue = []
184
191
  for (let i = 0; i < tableList.length; i++) {
185
192
  const tableName = tableList[i]
186
193
  if (
187
- isTableNameExistInModel(tableName) ||
194
+ this.isTableNameExistInModel(params.model, tableName) ||
188
195
  tableName.search("_view") >= 0
189
196
  ) {
190
197
  const columnList = await this.getColumnFullList(tableName)
191
198
 
192
- let singleInterfaceContent = ""
199
+ let stringOfRawColumnKeyAndValue = ""
193
200
  for (const cRow of columnList) {
194
- const columnChecker = isColumnExistInModel(
201
+ const isColumnExistInModel = this.isColumnExistInModel(
202
+ params.model,
195
203
  tableName,
196
204
  cRow.COLUMN_NAME
197
205
  )
198
- if (columnChecker || tableName.search("_view") >= 0) {
199
- const possibleValue = getPossibleColumnValue(
206
+ if (isColumnExistInModel || tableName.search("_view") >= 0) {
207
+ const possibleValue = this.getPossibleColumnValue(
208
+ params.model,
200
209
  cRow.TABLE_NAME,
201
210
  cRow.COLUMN_NAME
202
211
  )
203
212
  if (possibleValue) {
204
- singleInterfaceContent = `${singleInterfaceContent} \n ${
213
+ stringOfRawColumnKeyAndValue = `${stringOfRawColumnKeyAndValue} \n ${
205
214
  cRow.COLUMN_NAME
206
215
  }: ${possibleValue.map((row) => `"${row}"`).join(" | ")};`
207
216
  } else {
208
- singleInterfaceContent = `${singleInterfaceContent} \n ${
217
+ stringOfRawColumnKeyAndValue = `${stringOfRawColumnKeyAndValue} \n ${
209
218
  cRow.COLUMN_NAME
210
219
  }: ${convertDataType(cRow.DATA_TYPE)};`
211
220
  }
@@ -214,20 +223,35 @@ export default class ModelGenerator {
214
223
  }
215
224
  }
216
225
 
217
- const str = ` ${tableName} : { ${singleInterfaceContent} }`
218
- array.push(str)
219
- // console.log(`generate interface from ${tableName}`)
226
+ // normal app model code
227
+ const str = ` ${tableName} : { ${stringOfRawColumnKeyAndValue} }`
228
+ arrayOfColumnKeyValue.push(str)
229
+ // only seed model code
230
+ const tempSeedModel = params.model.find(
231
+ (row) => row.tableName === tableName && row.isSeed
232
+ )
233
+ if (tempSeedModel) arrayOfSeedColumnKeyValue.push(str)
220
234
  }
221
235
  }
236
+ // normal app model code
222
237
  const fileName = `${params.appName}_INF.ts`
238
+ const seedFileName = `seed_INF.ts`
223
239
  const code = `export default interface ${
224
240
  params.appName
225
- }_INF { ${array.join("\n")} }`
241
+ }_INF { ${arrayOfColumnKeyValue.join("\n")} }`
242
+ const seedCode = `export default interface seed_INF { ${arrayOfSeedColumnKeyValue.join(
243
+ "\n"
244
+ )} }`
226
245
 
227
246
  for (let row of params.outputDirectory) {
247
+ // normal app model code
228
248
  const serverFilePath = path.join(row, fileName)
229
249
  await fs.writeFileSync(serverFilePath, code)
230
- console.log("save to ", serverFilePath)
250
+ console.log("save app model to ", serverFilePath)
251
+ // only seed model code
252
+ const seedServerFilePath = path.join(row, seedFileName)
253
+ await fs.writeFileSync(seedServerFilePath, seedCode)
254
+ console.log("save seed model to ", seedServerFilePath)
231
255
  }
232
256
 
233
257
  console.log(
@@ -319,17 +343,9 @@ export default class ModelGenerator {
319
343
  }
320
344
  const fileName = `${params.appName}_model_const.ts`
321
345
  const code = `
322
- type paramType = "number" | "string" | "any" | string[] | number[]
323
- interface constInterface {
324
- [keytable: string]: {
325
- [key: string]: paramType
326
- }
327
- }
328
-
329
-
330
- export const ${
331
- params.appName
332
- }_model_const : constInterface = { ${array.join(",")} } as const`
346
+ export const ${params.appName}_model_const = { ${array.join(
347
+ ","
348
+ )} } as const`
333
349
 
334
350
  for (let row of params.outputDirectory) {
335
351
  const serverFilePath = path.join(row, fileName)
@@ -0,0 +1,3 @@
1
+ import { MyModel } from "../myModel"
2
+
3
+ function generateSeedInterface(model: MyModel[]) {}
@@ -1,10 +1,10 @@
1
1
  import chalk from "chalk"
2
2
  import fs from "fs"
3
3
  import path from "path"
4
- import ModelGenerator from "./ModelGenerator"
5
- import { columnType, MyModel } from "./myModel"
4
+ import ModelGenerator from "../ModelGenerator/ModelGenerator"
5
+ import { columnType, MyModel } from "../myModel"
6
6
 
7
- export default class MyDBMigration<Main> {
7
+ export default class MyDBMigrator {
8
8
  MyDB: ModelGenerator
9
9
  onetimeLoadColumnContent: {
10
10
  COLUMN_NAME: string
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { MyModel, columnContent, columnType } from "./myModel"
2
- export { DatabaseConfigInterface } from "./ModelGenerator"
3
- export { default as ModelGenerator } from "./ModelGenerator"
4
- export { default as GGMySQLConnector } from "./GGMySQLConnector"
2
+ export { DatabaseConfigInterface } from "./ModelGenerator/ModelGenerator"
3
+ export { default as ModelGenerator } from "./ModelGenerator/ModelGenerator"
4
+ export { default as GGMySQLConnector } from "./GGMySQLConnector/GGMySQLConnector"
package/src/myModel.ts CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  export type columnType =
3
2
  | "int"
4
3
  | "tinyint"
@@ -26,10 +25,9 @@ export interface columnContent {
26
25
  IS_INDEX?: boolean
27
26
  }
28
27
  export interface MyModel {
28
+ isSeed: boolean
29
29
  tableName: string
30
- columns: [
31
- ...columnContent[]
32
- ]
30
+ columns: [...columnContent[]]
33
31
  meaning?: string
34
32
  }
35
33
  // export interface MyModelView {