5htp-core 0.1.2 → 0.2.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/changelog.md +5 -0
- package/doc/TODO.md +71 -0
- package/package.json +5 -4
- package/src/client/{App.tsx → app/component.tsx} +15 -11
- package/src/client/app/index.ts +128 -0
- package/src/client/app/service.ts +34 -0
- package/src/client/app.tsconfig.json +0 -4
- package/src/client/assets/css/components.less +52 -0
- package/src/client/assets/css/core.less +7 -28
- package/src/client/assets/css/theme.less +1 -1
- package/src/client/assets/css/{borders.less → utils/borders.less} +0 -0
- package/src/client/assets/css/{layouts.less → utils/layouts.less} +0 -0
- package/src/client/assets/css/{medias.less → utils/medias.less} +14 -1
- package/src/client/assets/css/{sizing.less → utils/sizing.less} +0 -0
- package/src/client/assets/css/{spacing.less → utils/spacing.less} +0 -0
- package/src/client/components/Card/index.tsx +13 -7
- package/src/client/components/Dialog/Manager.tsx +41 -14
- package/src/client/components/Dialog/index.less +2 -4
- package/src/client/components/Form/index.tsx +1 -1
- package/src/client/components/Row/index.less +0 -2
- package/src/client/components/Table/index.tsx +3 -2
- package/src/client/components/button.tsx +2 -2
- package/src/client/components/containers/Popover/index.tsx +1 -1
- package/src/client/components/containers/champs.less +0 -2
- package/src/client/components/data/spintext/index.tsx +1 -1
- package/src/client/components/dropdown/index.tsx +1 -1
- package/src/client/components/index.ts +23 -0
- package/src/client/components/input/BaseV2/index.less +0 -2
- package/src/client/components/input/BaseV2/index.tsx +1 -1
- package/src/client/components/input/Date/index.less +0 -2
- package/src/client/components/input/Periode/index.less +0 -2
- package/src/client/components/input/Radio/index.less +0 -2
- package/src/client/components/input/UploadImage/index.less +0 -2
- package/src/client/components/input/UploadImage/index.tsx +1 -1
- package/src/client/hooks/index.ts +5 -0
- package/src/client/hooks/useState/index.tsx +2 -2
- package/src/client/hooks.ts +22 -0
- package/src/client/index.ts +5 -0
- package/src/client/pages/_layout/landing/index.tsx +0 -2
- package/src/client/pages/_messages/400.tsx +2 -2
- package/src/client/pages/_messages/401.tsx +2 -2
- package/src/client/pages/_messages/403.tsx +2 -2
- package/src/client/pages/_messages/404.tsx +2 -2
- package/src/client/pages/_messages/500.tsx +2 -2
- package/src/client/pages/bug.tsx +1 -1
- package/src/client/pages/useHeader.tsx +1 -1
- package/src/client/{context/captcha.ts → services/captcha/index.ts} +0 -0
- package/src/client/services/metrics/index.ts +37 -0
- package/src/client/{router → services/router/components}/Link.tsx +1 -1
- package/src/client/services/router/components/Page.tsx +59 -0
- package/src/client/{router/component.tsx → services/router/components/router.tsx} +52 -74
- package/src/client/services/router/index.tsx +453 -0
- package/src/client/services/router/request/api.ts +227 -0
- package/src/client/{router → services/router}/request/history.ts +0 -0
- package/src/client/services/router/request/index.ts +52 -0
- package/src/client/services/router/response/index.tsx +107 -0
- package/src/client/services/router/response/page.ts +90 -0
- package/src/client/{context/socket.ts → services/socket/index.ts} +2 -2
- package/src/client/utils/dom.ts +1 -1
- package/src/common/app/index.ts +9 -0
- package/src/common/data/chaines/index.ts +9 -6
- package/src/common/data/input/validate.ts +3 -166
- package/src/common/data/objets.ts +25 -0
- package/src/common/data/tableaux.ts +8 -0
- package/src/common/errors/index.ts +3 -1
- package/src/common/router/index.ts +67 -88
- package/src/common/router/layouts.ts +50 -0
- package/src/common/router/register.ts +62 -0
- package/src/common/router/request/api.ts +72 -0
- package/src/common/router/request/index.ts +31 -0
- package/src/common/router/{response.ts → response/index.ts} +9 -13
- package/src/common/router/response/page.ts +46 -54
- package/src/common/validation/index.ts +3 -0
- package/src/common/validation/schema.ts +185 -0
- package/src/common/validation/validator.ts +95 -0
- package/src/common/validation/validators.ts +313 -0
- package/src/server/app/config.ts +9 -27
- package/src/server/app/index.ts +81 -124
- package/src/server/app/service.ts +98 -0
- package/src/server/app.tsconfig.json +0 -8
- package/src/server/index.ts +5 -0
- package/src/server/patch.ts +0 -6
- package/src/server/{data/Cache.ts → services/cache/index.ts} +79 -47
- package/src/server/services/console/bugReporter.ts +26 -16
- package/src/server/services/console/index.ts +59 -51
- package/src/server/services/cron/index.ts +12 -26
- package/src/server/services/database/bucket.ts +40 -0
- package/src/server/services/database/connection.ts +213 -80
- package/src/server/services/database/datatypes.ts +63 -40
- package/src/server/services/database/debug.ts +20 -0
- package/src/server/services/database/index.ts +295 -272
- package/src/server/services/database/metas.ts +246 -135
- package/src/server/services/database/stats.ts +151 -126
- package/src/server/services/email/index.ts +30 -62
- package/src/server/services/email/transporter.ts +38 -0
- package/src/server/services/{router/request/services → metrics}/detect.ts +8 -10
- package/src/server/services/{router/request/services/tracking.ts → metrics/index.ts} +68 -45
- package/src/server/services/{http → router/http}/index.ts +28 -70
- package/src/server/services/{http → router/http}/multipart.ts +0 -0
- package/src/server/services/{http → router/http}/session.ts.old +0 -0
- package/src/server/services/router/index.ts +273 -202
- package/src/server/services/router/request/api.ts +76 -0
- package/src/server/services/router/request/index.ts +16 -97
- package/src/server/services/router/request/service.ts +21 -0
- package/src/server/services/router/response/index.ts +131 -65
- package/src/server/services/router/response/{filter → mask}/Filter.ts +0 -0
- package/src/server/services/router/response/{filter → mask}/index.ts +0 -2
- package/src/server/services/router/response/{filter → mask}/selecteurs.ts +0 -0
- package/src/server/services/router/response/page/document.tsx +194 -0
- package/src/server/services/router/response/page/index.tsx +157 -0
- package/src/server/{libs/pages → services/router/response/page}/schemaGenerator.ts +0 -0
- package/src/server/services/router/service.ts +48 -0
- package/src/server/services/schema/index.ts +47 -0
- package/src/server/services/schema/request.ts +55 -0
- package/src/server/services/schema/router.ts +33 -0
- package/src/server/services/socket/index.ts +38 -43
- package/src/server/services/socket/scope.ts +6 -4
- package/src/server/services/users/index.ts +203 -0
- package/src/server/services/{auth/base.ts → users/old.ts} +28 -112
- package/src/server/services/users/router/index.ts +72 -0
- package/src/server/services/users/router/request.ts +49 -0
- package/src/server/{data → services_old}/SocketClient.ts +0 -0
- package/src/server/{data/Token.olg.ts → services_old/Token.old.ts} +0 -0
- package/src/server/{data → services_old}/aes.ts +0 -0
- package/src/types/aliases.d.ts +43 -2
- package/templates/composant.tsx +1 -1
- package/templates/modal.tsx +1 -1
- package/templates/page.tsx +1 -1
- package/tsconfig.common.json +0 -4
- package/src/client/assets/css/components/components.less +0 -31
- package/src/client/context/api.ts +0 -92
- package/src/client/context/index.ts +0 -246
- package/src/client/index.tsx +0 -129
- package/src/client/router/index.ts +0 -286
- package/src/client/router/request/index.ts +0 -106
- package/src/client/router/response/index.ts +0 -38
- package/src/client/router/route.ts +0 -75
- package/src/common/data/input/validators/basic.ts +0 -299
- package/src/common/data/input/validators/build.ts +0 -63
- package/src/common/router/request.ts +0 -83
- package/src/server/data/ApiClient.ts +0 -119
- package/src/server/data/input.ts +0 -41
- package/src/server/libs/pages/document.static.tsx +0 -41
- package/src/server/libs/pages/document.tsx +0 -203
- package/src/server/libs/pages/render.tsx +0 -90
- package/src/server/routes/auth.ts +0 -151
- package/src/server/services/redis/index.ts +0 -71
- package/src/server/services/router/request/services/auth.ts +0 -177
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
----------------------------------*/
|
|
4
4
|
|
|
5
5
|
// Core
|
|
6
|
+
import Application, { Service } from '@server/app';
|
|
6
7
|
import { NotFound } from '@common/errors';
|
|
7
|
-
import app from '@server/app';
|
|
8
8
|
import context from '@server/context';
|
|
9
9
|
|
|
10
10
|
/*----------------------------------
|
|
@@ -19,25 +19,19 @@ export { default as CronTask } from './CronTask';
|
|
|
19
19
|
- SERVICE CONFIG
|
|
20
20
|
----------------------------------*/
|
|
21
21
|
|
|
22
|
-
export type
|
|
22
|
+
export type Config = {
|
|
23
23
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
namespace Config {
|
|
29
|
-
interface Services {
|
|
30
|
-
cron: CronServiceConfig
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
26
|
+
export type Hooks = {
|
|
27
|
+
|
|
34
28
|
}
|
|
35
29
|
|
|
36
30
|
/*----------------------------------
|
|
37
31
|
- CLASSE
|
|
38
32
|
----------------------------------*/
|
|
39
33
|
|
|
40
|
-
export class CronManager {
|
|
34
|
+
export default class CronManager extends Service<Config, Hooks, Application> {
|
|
41
35
|
|
|
42
36
|
public static taches: { [nom: string]: CronTask } = {}
|
|
43
37
|
public static timer: NodeJS.Timeout;
|
|
@@ -45,11 +39,15 @@ export class CronManager {
|
|
|
45
39
|
/*----------------------------------
|
|
46
40
|
- HOOKS
|
|
47
41
|
----------------------------------*/
|
|
48
|
-
|
|
49
|
-
|
|
42
|
+
|
|
43
|
+
public async register() {
|
|
44
|
+
|
|
50
45
|
}
|
|
51
46
|
|
|
52
|
-
public async
|
|
47
|
+
public async start() {
|
|
48
|
+
|
|
49
|
+
this.app.on('cleanup', () => this.cleanup());
|
|
50
|
+
|
|
53
51
|
clearInterval(CronManager.timer);
|
|
54
52
|
CronManager.timer = setInterval(() => {
|
|
55
53
|
|
|
@@ -116,16 +114,4 @@ export class CronManager {
|
|
|
116
114
|
throw new Error(`L'instance de la tâche cron ${name} n'a pas été trouvée`);
|
|
117
115
|
return cron;
|
|
118
116
|
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/*----------------------------------
|
|
122
|
-
- REGISTER SERVICE
|
|
123
|
-
----------------------------------*/
|
|
124
|
-
app.register('cron', CronManager);
|
|
125
|
-
declare global {
|
|
126
|
-
namespace Core {
|
|
127
|
-
interface Services {
|
|
128
|
-
cron: CronManager;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
117
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPENDANCES
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
// Core
|
|
6
|
+
import { TQueryOptions } from './connection';
|
|
7
|
+
|
|
8
|
+
/*----------------------------------
|
|
9
|
+
- TYPES
|
|
10
|
+
----------------------------------*/
|
|
11
|
+
|
|
12
|
+
const LogPrefix = '[database][bucket]';
|
|
13
|
+
|
|
14
|
+
/*----------------------------------
|
|
15
|
+
- CLASS
|
|
16
|
+
----------------------------------*/
|
|
17
|
+
export default class Queriesbucket {
|
|
18
|
+
|
|
19
|
+
public queries: Set<string>;
|
|
20
|
+
|
|
21
|
+
public constructor(
|
|
22
|
+
private queryOptions: TQueryOptions<'bucket'> = {},
|
|
23
|
+
queriesList: string[] = [],
|
|
24
|
+
) {
|
|
25
|
+
this.queries = new Set<string>(queriesList);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public add( query: string ) {
|
|
29
|
+
this.queries.add(query);
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public delete( query: string ) {
|
|
34
|
+
this.queries.delete(query);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public run() {
|
|
38
|
+
this.queryOptions.log && console.log(LogPrefix, `Run queries bucket`, ...this.queries);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -6,46 +6,97 @@
|
|
|
6
6
|
import mysql from 'mysql2/promise';
|
|
7
7
|
|
|
8
8
|
// Core: general
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
|
|
9
|
+
import Application from '@server/app';
|
|
10
|
+
import Service from '@server/app/service';
|
|
11
|
+
|
|
12
|
+
// Core: specific
|
|
13
|
+
import { SqlError } from './debug';
|
|
14
|
+
import type Console from '../console';
|
|
15
|
+
import MetadataParser, { TDatabasesList, TMetasTable, TColumnTypes, TMetasColonne } from './metas';
|
|
16
|
+
import { TMySQLTypeName, mysqlToJs, js as jsTypes } from './datatypes';
|
|
17
|
+
import Bucket from './bucket';
|
|
18
|
+
|
|
19
|
+
/*----------------------------------
|
|
20
|
+
- CONFIG
|
|
21
|
+
----------------------------------*/
|
|
22
|
+
|
|
23
|
+
const LogPrefix = '[database][connection]';
|
|
24
|
+
|
|
25
|
+
/*----------------------------------
|
|
26
|
+
- SERVICE CONFIG
|
|
27
|
+
----------------------------------*/
|
|
28
|
+
|
|
29
|
+
export type DatabaseServiceConfig = {
|
|
30
|
+
list: string[],
|
|
31
|
+
dev: {
|
|
32
|
+
host: string,
|
|
33
|
+
port: number,
|
|
34
|
+
login: string,
|
|
35
|
+
password: string,
|
|
36
|
+
},
|
|
37
|
+
prod: {
|
|
38
|
+
host: string,
|
|
39
|
+
port: number,
|
|
40
|
+
login: string,
|
|
41
|
+
password: string,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type THooks = {
|
|
46
|
+
|
|
47
|
+
}
|
|
12
48
|
|
|
13
49
|
/*----------------------------------
|
|
14
|
-
-
|
|
50
|
+
- TYPES
|
|
15
51
|
----------------------------------*/
|
|
16
52
|
|
|
53
|
+
type TBasicQueryOptions = {
|
|
54
|
+
bucket?: Bucket,
|
|
55
|
+
simulate?: boolean,
|
|
56
|
+
log?: boolean,
|
|
57
|
+
returnQuery?: boolean,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type TQueryOptions<TOmitValues extends keyof TBasicQueryOptions = never, TRequireValues extends keyof TBasicQueryOptions = never> = (
|
|
61
|
+
Omit<TBasicQueryOptions, TOmitValues>
|
|
62
|
+
&
|
|
63
|
+
Required<Pick<TBasicQueryOptions, TRequireValues>>
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
export type TQueryResult = TSelectQueryResult;
|
|
67
|
+
|
|
68
|
+
// TODO: specifiy return type of every mysql query type
|
|
69
|
+
type TSelectQueryResult = any;
|
|
17
70
|
|
|
18
71
|
/*----------------------------------
|
|
19
72
|
- SERVICES
|
|
20
73
|
----------------------------------*/
|
|
21
|
-
export default class
|
|
74
|
+
export default class DatabaseConnection extends Service<DatabaseServiceConfig, THooks, Application> {
|
|
22
75
|
|
|
23
76
|
private initialized = false;
|
|
24
77
|
public connection!: mysql.Pool;
|
|
25
|
-
public tables: TDatabasesList = {};
|
|
26
78
|
|
|
27
|
-
public
|
|
79
|
+
public tables: TDatabasesList = {};
|
|
80
|
+
public metas = new MetadataParser(this);
|
|
28
81
|
|
|
29
82
|
/*----------------------------------
|
|
30
83
|
- HOOKS
|
|
31
84
|
----------------------------------*/
|
|
32
|
-
public constructor() {
|
|
33
85
|
|
|
34
|
-
|
|
86
|
+
public async register() {
|
|
35
87
|
|
|
36
88
|
}
|
|
37
|
-
|
|
89
|
+
|
|
38
90
|
public loading: Promise<void> | undefined = undefined;
|
|
39
|
-
public async
|
|
40
|
-
|
|
41
|
-
// Wait for database service to be ready
|
|
42
|
-
//await seconds(5);
|
|
91
|
+
public async start() {
|
|
43
92
|
|
|
44
93
|
this.initialized = false;
|
|
45
94
|
|
|
95
|
+
this.app.on('cleanup', () => this.cleanup());
|
|
96
|
+
|
|
46
97
|
this.connection = await this.connect();
|
|
47
98
|
|
|
48
|
-
this.tables = await
|
|
99
|
+
this.tables = await this.metas.load( this.config.list );
|
|
49
100
|
|
|
50
101
|
this.initialized = true;
|
|
51
102
|
|
|
@@ -60,9 +111,9 @@ export default class FastDatabase {
|
|
|
60
111
|
----------------------------------*/
|
|
61
112
|
public async connect() {
|
|
62
113
|
|
|
63
|
-
console.info(`Connecting to databases ...`);
|
|
114
|
+
console.info(LogPrefix, `Connecting to databases ...`);
|
|
64
115
|
|
|
65
|
-
const creds = this.config[ app.env.profile ];
|
|
116
|
+
const creds = this.config[ this.app.env.profile ];
|
|
66
117
|
|
|
67
118
|
return await mysql.createPool({
|
|
68
119
|
|
|
@@ -93,102 +144,184 @@ export default class FastDatabase {
|
|
|
93
144
|
multipleStatements: true,
|
|
94
145
|
|
|
95
146
|
queryFormat: function (query, values) {
|
|
96
|
-
//console.info('queryFormat', query);
|
|
147
|
+
//console.info(LogPrefix, 'queryFormat', query);
|
|
97
148
|
return query;
|
|
98
149
|
}
|
|
99
150
|
});
|
|
100
151
|
}
|
|
101
152
|
|
|
102
|
-
private typeCast(field, next) {
|
|
153
|
+
private typeCast( field: mysql.Field, next: Function ) {
|
|
103
154
|
|
|
104
|
-
//
|
|
155
|
+
// Wait for the connection to be initialized
|
|
105
156
|
if (!this.initialized)
|
|
106
157
|
return next();
|
|
107
158
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
// TODO: A revoir, car les infos passées peuvent être des alias
|
|
159
|
+
// Normal column
|
|
160
|
+
let databaseColumn: TMetasColonne | undefined;
|
|
161
|
+
if (field.db && field.table && field.name) {
|
|
112
162
|
|
|
113
163
|
const db = this.tables[ field.db ];
|
|
114
164
|
if (db === undefined) {
|
|
115
|
-
return next();
|
|
116
165
|
console.error("Field infos:", field);
|
|
117
166
|
throw new Error(`Database metadatas for ${field.db} were not loaded.`);
|
|
118
167
|
}
|
|
119
168
|
|
|
120
169
|
const table = db[field.table];
|
|
121
170
|
if (table === undefined) {
|
|
122
|
-
return next();
|
|
123
171
|
console.error("Field infos:", field);
|
|
124
172
|
throw new Error(`Table metadatas for ${field.db}.${field.table} were not loaded.`);
|
|
125
173
|
}
|
|
126
174
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
175
|
+
databaseColumn = table.colonnes[field.name];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
let type: TColumnTypes;
|
|
180
|
+
if (databaseColumn !== undefined) {
|
|
181
|
+
|
|
182
|
+
type = databaseColumn.type;
|
|
183
|
+
|
|
184
|
+
// If the column name has not been found in the concerned table,
|
|
185
|
+
// We assume it's a computed column
|
|
186
|
+
} else {
|
|
187
|
+
|
|
188
|
+
const mysqlType = {
|
|
189
|
+
name: field.type as TMySQLTypeName,
|
|
190
|
+
params: []
|
|
132
191
|
}
|
|
133
192
|
|
|
134
|
-
|
|
193
|
+
let jsTypeName = mysqlToJs[ mysqlType.name ];
|
|
194
|
+
if (jsTypeName === undefined) {
|
|
195
|
+
console.warn(`The mySQL data type « ${mysqlType.name} » has not been associated with a JS equivalent in mysqlToJs. Using any instead.`);
|
|
196
|
+
jsTypeName = mysqlToJs['UNKNOWN'];
|
|
197
|
+
}
|
|
135
198
|
|
|
136
|
-
|
|
199
|
+
type = {
|
|
200
|
+
sql: mysqlType,
|
|
201
|
+
js: {
|
|
202
|
+
name: jsTypeName,
|
|
203
|
+
params: []
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
137
207
|
|
|
138
|
-
|
|
208
|
+
// Retrieve value
|
|
209
|
+
let val = field.string();
|
|
139
210
|
if (val === null)
|
|
140
211
|
return undefined;
|
|
141
212
|
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
return new Date(val);
|
|
165
|
-
|
|
166
|
-
case 'VARCHAR':
|
|
167
|
-
case 'CHAR':
|
|
168
|
-
case 'VAR_STRING':
|
|
169
|
-
case 'LONGTEXT':
|
|
170
|
-
case 'TEXT':
|
|
171
|
-
case 'ENUM':
|
|
172
|
-
return val;
|
|
173
|
-
|
|
174
|
-
case 'JSON':
|
|
175
|
-
return JSON.parse(val);
|
|
176
|
-
|
|
213
|
+
// Cast value
|
|
214
|
+
const jsTypeParser = jsTypes[ type.js.name ];
|
|
215
|
+
const castedVal = jsTypeParser.parse(val);
|
|
216
|
+
//console.log(LogPrefix, `type cast`, val, `(${type.sql.name}) =>`, castedVal, `(${type.js.name})`);
|
|
217
|
+
|
|
218
|
+
return castedVal;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/*----------------------------------
|
|
222
|
+
- METADATA
|
|
223
|
+
----------------------------------*/
|
|
224
|
+
|
|
225
|
+
public getTable( path: string ): TMetasTable {
|
|
226
|
+
|
|
227
|
+
// Parse path
|
|
228
|
+
let db: string, table: string;
|
|
229
|
+
if (path.includes('.'))
|
|
230
|
+
([db, table] = path.split('.'));
|
|
231
|
+
else {
|
|
232
|
+
// Only the table = use the main database (first of the list in the config)
|
|
233
|
+
db = this.config.list[0];
|
|
234
|
+
table = path;
|
|
177
235
|
}
|
|
236
|
+
|
|
237
|
+
// Retrieve table info
|
|
238
|
+
if (this.tables[db] === undefined)
|
|
239
|
+
throw new Error(`Database "${db}" not loaded. Did you add it in the database config ?`);
|
|
240
|
+
if (this.tables[db][table] === undefined)
|
|
241
|
+
throw new Error(`Table "${db}.${table}" not loaded.`);
|
|
242
|
+
|
|
243
|
+
return this.tables[db][table];
|
|
178
244
|
|
|
179
|
-
console.warn("/!\\ UNHANDLED TYPE " + type + " for field " + field.name);
|
|
180
|
-
return val;
|
|
181
245
|
}
|
|
182
|
-
}
|
|
183
246
|
|
|
184
|
-
/*----------------------------------
|
|
185
|
-
-
|
|
186
|
-
----------------------------------*/
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
247
|
+
/*----------------------------------
|
|
248
|
+
- QUERY
|
|
249
|
+
----------------------------------*/
|
|
250
|
+
public bucket(
|
|
251
|
+
queryOptions: TQueryOptions<'bucket'> = {},
|
|
252
|
+
queriesList: string[] = [],
|
|
253
|
+
) {
|
|
254
|
+
return new Bucket(queryOptions, queriesList);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
public async query<TResult extends TQueryResult>(
|
|
258
|
+
query: string,
|
|
259
|
+
opts: TQueryOptions<'bucket', 'bucket'>
|
|
260
|
+
): Promise<Bucket>;
|
|
261
|
+
|
|
262
|
+
public async query<TResult extends TQueryResult>(
|
|
263
|
+
query: string,
|
|
264
|
+
opts: TQueryOptions<'returnQuery', 'returnQuery'>
|
|
265
|
+
): Promise<string>;
|
|
266
|
+
|
|
267
|
+
public async query<TResult extends TQueryResult>(
|
|
268
|
+
query: string,
|
|
269
|
+
opts: TQueryOptions<'simulate', 'simulate'>
|
|
270
|
+
): Promise<void>;
|
|
271
|
+
|
|
272
|
+
public async query<TResult extends TQueryResult>(
|
|
273
|
+
query: string,
|
|
274
|
+
opts?: TQueryOptions
|
|
275
|
+
): Promise<TResult>;
|
|
276
|
+
|
|
277
|
+
public async query<TResult extends TQueryResult>(
|
|
278
|
+
query: string,
|
|
279
|
+
opts: TQueryOptions = {}
|
|
280
|
+
): Promise<TResult | Bucket | string | void> {
|
|
281
|
+
|
|
282
|
+
if (opts.bucket)
|
|
283
|
+
return opts.bucket.add(query);
|
|
284
|
+
|
|
285
|
+
if (opts.returnQuery === true)
|
|
286
|
+
return query;
|
|
287
|
+
|
|
288
|
+
if (opts.log === true)
|
|
289
|
+
console.log(`[database][query]`, query);
|
|
290
|
+
|
|
291
|
+
if (opts.simulate === true)
|
|
292
|
+
return;
|
|
293
|
+
|
|
294
|
+
try {
|
|
295
|
+
|
|
296
|
+
const startTime = Date.now();
|
|
297
|
+
|
|
298
|
+
// Lancement de la requête
|
|
299
|
+
const [rows, fields] = await this.connection.query(query);
|
|
300
|
+
|
|
301
|
+
if (opts.log !== false)
|
|
302
|
+
this.log(query, startTime);
|
|
303
|
+
|
|
304
|
+
return rows as unknown as TResult;
|
|
305
|
+
|
|
306
|
+
} catch (error) {
|
|
307
|
+
|
|
308
|
+
throw new SqlError(error, query);
|
|
192
309
|
}
|
|
193
310
|
}
|
|
311
|
+
|
|
312
|
+
private log( query: string, startTime: number ) {
|
|
313
|
+
|
|
314
|
+
const console = this.app.use<Console>('console');
|
|
315
|
+
if (!console) return;
|
|
316
|
+
|
|
317
|
+
const { channelType, channelId } = console.getChannel();
|
|
318
|
+
if (channelId !== 'admin')
|
|
319
|
+
console.sqlQueries.push({
|
|
320
|
+
channelType,
|
|
321
|
+
channelId,
|
|
322
|
+
date: new Date(),
|
|
323
|
+
query: query.trim(),
|
|
324
|
+
time: Date.now() - startTime,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
194
327
|
}
|
|
@@ -1,74 +1,97 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPENDANCES
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
import type { TMetasColonne } from './metas';
|
|
5
|
+
|
|
6
|
+
/*----------------------------------
|
|
7
|
+
- TYPES
|
|
8
|
+
----------------------------------*/
|
|
9
|
+
|
|
1
10
|
type JsType = {
|
|
2
11
|
parse: (value: string) => any,
|
|
3
|
-
|
|
12
|
+
print: (col: TMetasColonne) => string
|
|
4
13
|
}
|
|
5
14
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
15
|
+
export type TJsTypeName = keyof typeof js;
|
|
16
|
+
export type TMySQLTypeName = keyof typeof mysqlToJs;
|
|
17
|
+
|
|
18
|
+
/*----------------------------------
|
|
19
|
+
- LISTS
|
|
20
|
+
----------------------------------*/
|
|
21
|
+
export const js = {
|
|
9
22
|
array: {
|
|
10
23
|
parse: (val: string) => val.split(','),
|
|
11
|
-
|
|
24
|
+
print: (col) => (col.type.sql.params.length
|
|
25
|
+
? '(' + col.type.sql.params.map( param => "'" + param + "'").join(' | ') + ')'
|
|
26
|
+
: 'string'
|
|
27
|
+
) + '[]'
|
|
28
|
+
},
|
|
29
|
+
enum: {
|
|
30
|
+
parse: (val: string) => val,
|
|
31
|
+
print: (col) => col.type.sql.params.map( param => "'" + param + "'").join(' | ')
|
|
12
32
|
},
|
|
13
33
|
float: {
|
|
14
34
|
parse: (val: string) => parseFloat(val),
|
|
15
|
-
|
|
35
|
+
print: (col) => 'number'
|
|
16
36
|
},
|
|
17
37
|
int: {
|
|
18
38
|
parse: (val: string) => parseFloat(val),
|
|
19
|
-
|
|
39
|
+
print: (col) => 'number'
|
|
20
40
|
},
|
|
21
41
|
date: {
|
|
22
42
|
parse: (val: string) => new Date(val),
|
|
23
|
-
|
|
43
|
+
print: (col) => 'Date'
|
|
24
44
|
},
|
|
25
45
|
string: {
|
|
26
46
|
parse: (val: string) => val,
|
|
27
|
-
|
|
47
|
+
print: (col) => 'string'
|
|
28
48
|
},
|
|
29
49
|
object: {
|
|
30
50
|
parse: (val: string) => JSON.parse(val),
|
|
31
|
-
|
|
51
|
+
print: (col) => 'object'
|
|
32
52
|
},
|
|
33
53
|
|
|
34
54
|
// When we were not able to find an equivalent
|
|
35
55
|
unknown: {
|
|
36
56
|
parse: (val: any) => val,
|
|
37
|
-
|
|
57
|
+
print: (col) => 'any'
|
|
38
58
|
},
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export const mysqlToJs: {
|
|
42
|
-
[type: string]: JsType
|
|
43
|
-
} = {
|
|
44
|
-
|
|
45
|
-
'SET': js.array,
|
|
59
|
+
} as const
|
|
46
60
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
'
|
|
61
|
+
// https://www.w3schools.com/sql/sql_datatypes.asp
|
|
62
|
+
export const mysqlToJs = {
|
|
63
|
+
// Float
|
|
64
|
+
'DECIMAL': 'float',
|
|
65
|
+
'FLOAT': 'float',
|
|
66
|
+
'NEWDECIMAL': 'float',
|
|
67
|
+
'DOUBLE': 'float',
|
|
68
|
+
'POINT': 'float',
|
|
51
69
|
|
|
52
|
-
|
|
53
|
-
'
|
|
54
|
-
'
|
|
55
|
-
'
|
|
56
|
-
'
|
|
57
|
-
'
|
|
58
|
-
'
|
|
70
|
+
// Integres
|
|
71
|
+
'INT': 'int',
|
|
72
|
+
'BIGINT': 'int',
|
|
73
|
+
'LONG': 'int',
|
|
74
|
+
'LONGLONG': 'int',
|
|
75
|
+
'TINYINT': 'int',
|
|
76
|
+
'SMALLINT': 'int',
|
|
77
|
+
'MEDIUMINT': 'int',
|
|
59
78
|
|
|
60
|
-
|
|
61
|
-
'
|
|
79
|
+
// Dates
|
|
80
|
+
'DATE': 'date',
|
|
81
|
+
'DATETIME': 'date',
|
|
62
82
|
|
|
63
|
-
|
|
64
|
-
'
|
|
65
|
-
'
|
|
66
|
-
'
|
|
67
|
-
'
|
|
68
|
-
'
|
|
83
|
+
// Strings
|
|
84
|
+
'VARCHAR': 'string',
|
|
85
|
+
'CHAR': 'string',
|
|
86
|
+
'VAR_STRING': 'string',
|
|
87
|
+
'LONGTEXT': 'string',
|
|
88
|
+
'TEXT': 'string',
|
|
89
|
+
'ENUM': 'enum',
|
|
69
90
|
|
|
70
|
-
|
|
91
|
+
// Objects
|
|
92
|
+
'SET': 'array',
|
|
93
|
+
'JSON': 'object',
|
|
71
94
|
|
|
72
95
|
// When we were not able to find an equivalent
|
|
73
|
-
'UNKNOWN':
|
|
74
|
-
}
|
|
96
|
+
'UNKNOWN': 'unknown',
|
|
97
|
+
} as const
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPENDANCES
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
/*----------------------------------
|
|
6
|
+
- CLASS
|
|
7
|
+
----------------------------------*/
|
|
8
|
+
export class SqlError extends Error {
|
|
9
|
+
|
|
10
|
+
public constructor(
|
|
11
|
+
public original: Error,
|
|
12
|
+
public query: string
|
|
13
|
+
) {
|
|
14
|
+
super(original.message);
|
|
15
|
+
|
|
16
|
+
this.name = original.name;
|
|
17
|
+
this.message = original.message;
|
|
18
|
+
this.stack = original.stack;
|
|
19
|
+
}
|
|
20
|
+
}
|