5htp-core 0.2.1 → 0.2.2
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/package.json +10 -3
- package/src/client/app/index.ts +2 -2
- package/src/client/assets/css/components/card.less +0 -3
- package/src/client/assets/css/components/other.less +2 -4
- package/src/client/assets/css/components/table.less +1 -2
- package/src/client/assets/css/components.less +4 -0
- package/src/client/assets/css/core.less +0 -1
- package/src/client/assets/css/theme.less +2 -2
- package/src/client/assets/css/utils/medias.less +21 -0
- package/src/client/components/Card/index.tsx +8 -5
- package/src/client/components/Dialog/index.less +3 -3
- package/src/client/components/Row/index.less +2 -0
- package/src/client/components/Row/index.tsx +44 -10
- package/src/client/components/Video/index.less +39 -0
- package/src/client/components/Video/index.tsx +69 -0
- package/src/client/components/containers/Popover/index.tsx +2 -2
- package/src/client/components/data/Time.tsx +1 -1
- package/src/client/components/data/progressbar/circular/index.tsx +1 -1
- package/src/client/components/index.ts +24 -8
- package/src/client/components/input/BaseV2/index.tsx +0 -1
- package/src/client/components/{input/BaseV2/index.less → inputv3/base.less} +1 -1
- package/src/client/components/inputv3/base.tsx +73 -0
- package/src/client/components/{input/UploadImage → inputv3/file}/Bouton.tsx +0 -0
- package/src/client/components/inputv3/file/FileToUpload.ts +34 -0
- package/src/client/components/inputv3/file/index.less +59 -0
- package/src/client/components/inputv3/file/index.tsx +157 -0
- package/src/client/components/{input → inputv3/string}/index.tsx +41 -27
- package/src/client/pages/bug.tsx +3 -4
- package/src/client/services/router/index.tsx +0 -1
- package/src/client/services/router/request/api.ts +20 -12
- package/src/client/services/router/request/multipart.ts +27 -0
- package/src/common/data/chaines/greetings.ts +1 -1
- package/src/common/data/dates.ts +1 -1
- package/src/common/data/input/validate.ts +0 -9
- package/src/common/data/markdown.ts +1 -1
- package/src/common/errors/index.ts +16 -12
- package/src/common/router/request/api.ts +11 -3
- package/src/common/validation/schema.ts +21 -20
- package/src/common/validation/validators.ts +3 -6
- package/src/server/app/commands.ts +149 -0
- package/src/server/app/index.ts +23 -4
- package/src/server/app/service.ts +4 -0
- package/src/server/services/cache/commands.ts +41 -0
- package/src/server/services/cache/index.ts +102 -34
- package/src/server/services/console/index.ts +1 -1
- package/src/server/services/database/connection.ts +38 -22
- package/src/server/services/database/datatypes.ts +51 -12
- package/src/server/services/database/index.ts +133 -40
- package/src/server/services/database/metas.ts +63 -37
- package/src/server/services/database/repository.ts +26 -0
- package/src/server/services/email/index.ts +102 -42
- package/src/server/services/fetch/index.ts +110 -0
- package/src/server/services/router/http/multipart.ts +70 -41
- package/src/server/services/router/index.ts +35 -4
- package/src/server/services/router/request/index.ts +8 -6
- package/src/server/services/schema/index.ts +4 -11
- package/src/server/services/schema/request.ts +16 -7
- package/src/server/services/schema/router.ts +6 -2
- package/src/server/{services_old → services/security/encrypt}/aes.ts +33 -14
- package/src/server/services/users/index.ts +3 -3
- package/src/server/services/users/router/index.ts +0 -2
- package/src/types/global/utils.d.ts +11 -1
- package/tsconfig.common.json +3 -0
- package/src/client/components/input/Textarea.tsx +0 -57
- package/src/client/components/input/Upload.tsx +0 -5
- package/src/client/components/input/UploadImage/index.less +0 -93
- package/src/client/components/input/UploadImage/index.tsx +0 -220
- package/src/common/data/file.ts +0 -25
|
@@ -187,7 +187,8 @@ export default class DatabaseConnection extends Service<DatabaseServiceConfig, T
|
|
|
187
187
|
|
|
188
188
|
const mysqlType = {
|
|
189
189
|
name: field.type as TMySQLTypeName,
|
|
190
|
-
params: []
|
|
190
|
+
params: [],
|
|
191
|
+
raw: 'undefined', // Not needed here
|
|
191
192
|
}
|
|
192
193
|
|
|
193
194
|
let jsTypeName = mysqlToJs[ mysqlType.name ];
|
|
@@ -200,7 +201,8 @@ export default class DatabaseConnection extends Service<DatabaseServiceConfig, T
|
|
|
200
201
|
sql: mysqlType,
|
|
201
202
|
js: {
|
|
202
203
|
name: jsTypeName,
|
|
203
|
-
params: []
|
|
204
|
+
params: [],
|
|
205
|
+
raw: 'undefined', // Not needed here
|
|
204
206
|
}
|
|
205
207
|
}
|
|
206
208
|
}
|
|
@@ -244,6 +246,23 @@ export default class DatabaseConnection extends Service<DatabaseServiceConfig, T
|
|
|
244
246
|
|
|
245
247
|
}
|
|
246
248
|
|
|
249
|
+
public checkValue( value: unknown, column: TMetasColonne ): string | false {
|
|
250
|
+
|
|
251
|
+
const jsType = jsTypes[ column.type.js.name ];
|
|
252
|
+
|
|
253
|
+
const isValid = (value === undefined || value === null)
|
|
254
|
+
? column.optional
|
|
255
|
+
: jsType.check( value, column );
|
|
256
|
+
|
|
257
|
+
if (isValid)
|
|
258
|
+
return false;
|
|
259
|
+
|
|
260
|
+
console.log(column.type.sql.params)
|
|
261
|
+
|
|
262
|
+
return `Data expected to match: ${column.type.js.raw} (MySQL: ${column.type.sql.raw}) ||. Got: ` + JSON.stringify(value);;
|
|
263
|
+
|
|
264
|
+
}
|
|
265
|
+
|
|
247
266
|
/*----------------------------------
|
|
248
267
|
- QUERY
|
|
249
268
|
----------------------------------*/
|
|
@@ -254,30 +273,30 @@ export default class DatabaseConnection extends Service<DatabaseServiceConfig, T
|
|
|
254
273
|
return new Bucket(queryOptions, queriesList);
|
|
255
274
|
}
|
|
256
275
|
|
|
257
|
-
public
|
|
276
|
+
public query<TResult extends TQueryResult>(
|
|
258
277
|
query: string,
|
|
259
278
|
opts: TQueryOptions<'bucket', 'bucket'>
|
|
260
|
-
):
|
|
279
|
+
): Bucket;
|
|
261
280
|
|
|
262
|
-
public
|
|
281
|
+
public query<TResult extends TQueryResult>(
|
|
263
282
|
query: string,
|
|
264
283
|
opts: TQueryOptions<'returnQuery', 'returnQuery'>
|
|
265
|
-
):
|
|
284
|
+
): string;
|
|
266
285
|
|
|
267
|
-
public
|
|
286
|
+
public query<TResult extends TQueryResult>(
|
|
268
287
|
query: string,
|
|
269
288
|
opts: TQueryOptions<'simulate', 'simulate'>
|
|
270
|
-
):
|
|
289
|
+
): void;
|
|
271
290
|
|
|
272
|
-
public
|
|
291
|
+
public query<TResult extends TQueryResult>(
|
|
273
292
|
query: string,
|
|
274
293
|
opts?: TQueryOptions
|
|
275
294
|
): Promise<TResult>;
|
|
276
295
|
|
|
277
|
-
public
|
|
296
|
+
public query<TResult extends TQueryResult>(
|
|
278
297
|
query: string,
|
|
279
298
|
opts: TQueryOptions = {}
|
|
280
|
-
): Promise<TResult | Bucket | string | void
|
|
299
|
+
): Promise<TResult> | Bucket | string | void {
|
|
281
300
|
|
|
282
301
|
if (opts.bucket)
|
|
283
302
|
return opts.bucket.add(query);
|
|
@@ -285,28 +304,25 @@ export default class DatabaseConnection extends Service<DatabaseServiceConfig, T
|
|
|
285
304
|
if (opts.returnQuery === true)
|
|
286
305
|
return query;
|
|
287
306
|
|
|
288
|
-
if (opts.log === true)
|
|
307
|
+
if (opts.log === true || opts.simulate === true)
|
|
289
308
|
console.log(`[database][query]`, query);
|
|
290
309
|
|
|
291
310
|
if (opts.simulate === true)
|
|
292
311
|
return;
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
const startTime = Date.now();
|
|
297
|
-
|
|
298
|
-
// Lancement de la requête
|
|
299
|
-
const [rows, fields] = await this.connection.query(query);
|
|
312
|
+
|
|
313
|
+
const startTime = Date.now();
|
|
314
|
+
return this.connection.query(query).then(([rows, fields]) => {
|
|
300
315
|
|
|
301
316
|
if (opts.log !== false)
|
|
302
317
|
this.log(query, startTime);
|
|
303
318
|
|
|
304
319
|
return rows as unknown as TResult;
|
|
305
|
-
|
|
306
|
-
}
|
|
320
|
+
|
|
321
|
+
}).catch((error) => {
|
|
307
322
|
|
|
308
323
|
throw new SqlError(error, query);
|
|
309
|
-
|
|
324
|
+
|
|
325
|
+
})
|
|
310
326
|
}
|
|
311
327
|
|
|
312
328
|
private log( query: string, startTime: number ) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*----------------------------------
|
|
2
2
|
- DEPENDANCES
|
|
3
3
|
----------------------------------*/
|
|
4
|
-
import type { TMetasColonne } from './metas';
|
|
4
|
+
import type { TMetasColonne, TMySQLType } from './metas';
|
|
5
5
|
|
|
6
6
|
/*----------------------------------
|
|
7
7
|
- TYPES
|
|
@@ -9,7 +9,8 @@ import type { TMetasColonne } from './metas';
|
|
|
9
9
|
|
|
10
10
|
type JsType = {
|
|
11
11
|
parse: (value: string) => any,
|
|
12
|
-
|
|
12
|
+
check: (value: unknown, col: TMetasColonne) => boolean,
|
|
13
|
+
print: (mysqlTypeParams: TMySQLType["params"]) => string,
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export type TJsTypeName = keyof typeof js;
|
|
@@ -18,43 +19,81 @@ export type TMySQLTypeName = keyof typeof mysqlToJs;
|
|
|
18
19
|
/*----------------------------------
|
|
19
20
|
- LISTS
|
|
20
21
|
----------------------------------*/
|
|
22
|
+
/*
|
|
23
|
+
TODO: to merge avec the schema library
|
|
24
|
+
*/
|
|
21
25
|
export const js = {
|
|
22
26
|
array: {
|
|
23
27
|
parse: (val: string) => val.split(','),
|
|
24
|
-
print: (
|
|
25
|
-
? '(' +
|
|
28
|
+
print: (mysqlTypeParams: TMySQLType["params"]) => (mysqlTypeParams !== undefined
|
|
29
|
+
? '(' + mysqlTypeParams.map( param => "'" + param + "'").join(' | ') + ')'
|
|
26
30
|
: 'string'
|
|
27
|
-
) + '[]'
|
|
31
|
+
) + '[]',
|
|
32
|
+
// Check before using into a mysql query
|
|
33
|
+
check: (val: unknown, col: TMetasColonne) => Array.isArray(val) && (
|
|
34
|
+
col.type.sql.params === undefined
|
|
35
|
+
||
|
|
36
|
+
val.every( item => col.type.sql.params?.includes( item ))
|
|
37
|
+
)
|
|
28
38
|
},
|
|
29
39
|
enum: {
|
|
30
40
|
parse: (val: string) => val,
|
|
31
|
-
print: (
|
|
41
|
+
print: (mysqlTypeParams: TMySQLType["params"]) => mysqlTypeParams !== undefined
|
|
42
|
+
? mysqlTypeParams.map( param => "'" + param + "'").join(' | ')
|
|
43
|
+
: 'string',
|
|
44
|
+
// Check before using into a mysql query
|
|
45
|
+
check: (val: unknown, col: TMetasColonne) => typeof val === 'string' && (
|
|
46
|
+
col.type.sql.params === undefined
|
|
47
|
+
||
|
|
48
|
+
col.type.sql.params.includes( val )
|
|
49
|
+
)
|
|
32
50
|
},
|
|
33
51
|
float: {
|
|
34
52
|
parse: (val: string) => parseFloat(val),
|
|
35
|
-
print: (
|
|
53
|
+
print: () => 'number',
|
|
54
|
+
// Check before using into a mysql query
|
|
55
|
+
check: (val: unknown) => typeof val === 'number'
|
|
36
56
|
},
|
|
37
57
|
int: {
|
|
38
58
|
parse: (val: string) => parseFloat(val),
|
|
39
|
-
print: (
|
|
59
|
+
print: () => 'number',
|
|
60
|
+
// Check before using into a mysql query
|
|
61
|
+
check: (val: unknown, col: TMetasColonne) => (
|
|
62
|
+
typeof val === 'number'
|
|
63
|
+
||
|
|
64
|
+
// We assume that a int(1) is possibly a boolean
|
|
65
|
+
(
|
|
66
|
+
typeof val === 'boolean'
|
|
67
|
+
/*&&
|
|
68
|
+
col.type.sql.params[]*/
|
|
69
|
+
)
|
|
70
|
+
)
|
|
40
71
|
},
|
|
41
72
|
date: {
|
|
42
73
|
parse: (val: string) => new Date(val),
|
|
43
|
-
print: (
|
|
74
|
+
print: () => 'Date',
|
|
75
|
+
// Check before using into a mysql query
|
|
76
|
+
check: (val: unknown) => typeof val === 'number' || typeof val === 'string' || (typeof val === 'object' && val instanceof Date)
|
|
44
77
|
},
|
|
45
78
|
string: {
|
|
46
79
|
parse: (val: string) => val,
|
|
47
|
-
print: (
|
|
80
|
+
print: () => 'string',
|
|
81
|
+
// Check before using into a mysql query
|
|
82
|
+
check: (val: unknown) => typeof val === 'string'
|
|
48
83
|
},
|
|
49
84
|
object: {
|
|
50
85
|
parse: (val: string) => JSON.parse(val),
|
|
51
|
-
print: (
|
|
86
|
+
print: () => 'object',
|
|
87
|
+
// Check before using into a mysql query
|
|
88
|
+
check: (val: unknown) => typeof val === 'object'
|
|
52
89
|
},
|
|
53
90
|
|
|
54
91
|
// When we were not able to find an equivalent
|
|
55
92
|
unknown: {
|
|
56
93
|
parse: (val: any) => val,
|
|
57
|
-
print: (
|
|
94
|
+
print: (mysqlTypeParams: TMySQLType["params"]) => 'any',
|
|
95
|
+
// Check before using into a mysql query
|
|
96
|
+
check: (val: unknown) => true
|
|
58
97
|
},
|
|
59
98
|
} as const
|
|
60
99
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
// Npm
|
|
6
6
|
import mysql from 'mysql2/promise';
|
|
7
|
+
import type { ResultSetHeader } from 'mysql2';
|
|
7
8
|
import dottie from 'dottie';
|
|
8
9
|
const safeStringify = require('fast-safe-stringify'); // remplace les références circulairs par un [Circular]
|
|
9
10
|
|
|
@@ -21,6 +22,8 @@ import type { TMetasTable } from './metas';
|
|
|
21
22
|
- SERVICE TYPES
|
|
22
23
|
----------------------------------*/
|
|
23
24
|
|
|
25
|
+
export { default as Repository } from './repository';
|
|
26
|
+
|
|
24
27
|
export type Config = {
|
|
25
28
|
|
|
26
29
|
}
|
|
@@ -33,28 +36,32 @@ export type Hooks = {
|
|
|
33
36
|
- DEFINITIONS TYPES
|
|
34
37
|
----------------------------------*/
|
|
35
38
|
|
|
36
|
-
export type SqlQuery = SQL
|
|
39
|
+
export type SqlQuery = ReturnType<SQL["sql"]>
|
|
37
40
|
|
|
38
41
|
export type TSelectQueryOptions = TQueryOptions & {
|
|
39
42
|
|
|
40
43
|
}
|
|
41
44
|
|
|
45
|
+
export type TUpdateQueryOptions<TData extends TObjetDonnees = TObjetDonnees> = TQueryOptions;
|
|
46
|
+
|
|
42
47
|
export type TInsertQueryOptions<TData extends TObjetDonnees = TObjetDonnees> = TQueryOptions & {
|
|
43
|
-
upsert?:
|
|
48
|
+
upsert?: TColsToUpsert<TData>, // When "*", we use table.upsertableColumns
|
|
44
49
|
upsertMode?: 'increment'
|
|
45
50
|
try?: boolean
|
|
46
51
|
}
|
|
47
52
|
|
|
48
|
-
type
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
type TColsToUpsert<TData extends TObjetDonnees> = (
|
|
54
|
+
// Update all updatable columns (default)
|
|
55
|
+
'*'
|
|
56
|
+
|
|
|
57
|
+
// Specify which values exactly we have to update
|
|
58
|
+
// If '*', provided, we update all the updatable values and override with specific values
|
|
59
|
+
// { '*': true } is equivalent to '*'
|
|
60
|
+
({ '*'?: true } & Partial<TData>)
|
|
61
|
+
|
|
|
62
|
+
// A list of columns to update
|
|
63
|
+
(keyof TData)[]
|
|
64
|
+
)
|
|
58
65
|
|
|
59
66
|
/*----------------------------------
|
|
60
67
|
- HELPERS
|
|
@@ -63,7 +70,7 @@ type TInsertResult = {
|
|
|
63
70
|
const LogPrefix = '[database]'
|
|
64
71
|
|
|
65
72
|
const equalities = (data: TObjetDonnees, keys = Object.keys(data)) =>
|
|
66
|
-
keys.map(k => '
|
|
73
|
+
keys.map(k => '' + k + ' = ' + mysql.escape( data[k] ))
|
|
67
74
|
|
|
68
75
|
/*----------------------------------
|
|
69
76
|
- CORE
|
|
@@ -164,15 +171,16 @@ export default class SQL extends Service<Config, Hooks, Application> {
|
|
|
164
171
|
stringBefore = stringBefore.trim();
|
|
165
172
|
const prefix = stringBefore[stringBefore.length - 1];
|
|
166
173
|
|
|
174
|
+
// Null
|
|
167
175
|
if (value === undefined || value === null) {
|
|
168
176
|
|
|
169
177
|
value = 'NULL';
|
|
170
178
|
|
|
171
179
|
// Replace ""= NULL" by "IS NULL"
|
|
172
|
-
console.log("signBeforesignBefore", prefix, stringBefore);
|
|
173
180
|
if (prefix === '=')
|
|
174
181
|
stringBefore = stringBefore.substring(0, stringBefore.length - 1) + 'IS ';
|
|
175
182
|
|
|
183
|
+
// Prefix = special parse
|
|
176
184
|
} else if (prefix === ':' || prefix === '&') {
|
|
177
185
|
|
|
178
186
|
// Remove the prefix
|
|
@@ -191,6 +199,7 @@ export default class SQL extends Service<Config, Hooks, Application> {
|
|
|
191
199
|
|
|
192
200
|
}
|
|
193
201
|
|
|
202
|
+
// SQL query
|
|
194
203
|
} else if (typeof value === 'function' && value.string !== undefined)
|
|
195
204
|
value = value.string;
|
|
196
205
|
else
|
|
@@ -266,18 +275,61 @@ export default class SQL extends Service<Config, Hooks, Application> {
|
|
|
266
275
|
- OPERATIONS: UPDATE
|
|
267
276
|
----------------------------------*/
|
|
268
277
|
|
|
269
|
-
|
|
270
|
-
|
|
278
|
+
// Update multiple records
|
|
279
|
+
public update<TData extends TObjetDonnees>(
|
|
280
|
+
tableName: string,
|
|
281
|
+
data: TData[],
|
|
282
|
+
where: (keyof TData)[],
|
|
283
|
+
opts?: TUpdateQueryOptions<TData>
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
// Update one record
|
|
287
|
+
public update<TData extends TObjetDonnees>(
|
|
288
|
+
tableName: string,
|
|
271
289
|
data: TData,
|
|
272
|
-
where: TObjetDonnees,
|
|
273
|
-
opts?:
|
|
274
|
-
)
|
|
290
|
+
where: (keyof TData)[] | TObjetDonnees,
|
|
291
|
+
opts?: TUpdateQueryOptions<TData>
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
public update<TData extends TObjetDonnees>(...args: [
|
|
295
|
+
tableName: string,
|
|
296
|
+
data: TData[],
|
|
297
|
+
where: (keyof TData)[],
|
|
298
|
+
opts?: TUpdateQueryOptions<TData>
|
|
299
|
+
] | [
|
|
300
|
+
tableName: string,
|
|
301
|
+
data: TData,
|
|
302
|
+
where: (keyof TData)[] | TObjetDonnees,
|
|
303
|
+
opts?: TUpdateQueryOptions<TData>
|
|
304
|
+
]) {
|
|
305
|
+
|
|
306
|
+
let [tableName, data, where, opts] = args;
|
|
307
|
+
|
|
308
|
+
// Multiple updates in one
|
|
309
|
+
if (Array.isArray( data ))
|
|
310
|
+
return this.database.query(
|
|
311
|
+
data.map(record => this.update(tableName, record, where, opts)).join(';\n')
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
// No condition specified = use the pks
|
|
315
|
+
if (Array.isArray(where)) {
|
|
316
|
+
const whereColNames = where;
|
|
317
|
+
where = {}
|
|
318
|
+
for (const whereCol of whereColNames) {
|
|
319
|
+
const whereValue = data[whereCol];
|
|
320
|
+
if (whereValue === undefined)
|
|
321
|
+
throw new Error(`The column "${whereCol}" is used as a where value, but no value has been provided in the data to update.`);
|
|
322
|
+
where[ whereCol ] = whereValue;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
275
325
|
|
|
326
|
+
// Create equalities
|
|
276
327
|
const egalitesData = equalities(data).join(', ')
|
|
277
328
|
const egalitesWhere = equalities(where).join(' AND ')
|
|
278
329
|
|
|
330
|
+
// Build query
|
|
279
331
|
return this.database.query(`
|
|
280
|
-
UPDATE ${
|
|
332
|
+
UPDATE ${tableName} SET ${egalitesData} WHERE ${egalitesWhere};
|
|
281
333
|
`, opts);
|
|
282
334
|
|
|
283
335
|
}
|
|
@@ -285,12 +337,12 @@ export default class SQL extends Service<Config, Hooks, Application> {
|
|
|
285
337
|
public upsert<TData extends TObjetDonnees>(
|
|
286
338
|
path: string,
|
|
287
339
|
data: TData[] | TData,
|
|
288
|
-
colsToUpdate
|
|
340
|
+
colsToUpdate: TColsToUpsert<TData> = '*',
|
|
289
341
|
opts: TInsertQueryOptions<TData> = {}
|
|
290
342
|
) {
|
|
291
343
|
return this.insert(path, data, {
|
|
292
344
|
...opts,
|
|
293
|
-
upsert: colsToUpdate
|
|
345
|
+
upsert: colsToUpdate
|
|
294
346
|
});
|
|
295
347
|
}
|
|
296
348
|
|
|
@@ -305,7 +357,7 @@ export default class SQL extends Service<Config, Hooks, Application> {
|
|
|
305
357
|
path: string,
|
|
306
358
|
data: TData | TData[],
|
|
307
359
|
opts: TInsertQueryOptions<TData> = {}
|
|
308
|
-
): Promise<
|
|
360
|
+
): Promise<ResultSetHeader> {
|
|
309
361
|
|
|
310
362
|
const table = this.database.getTable(path);
|
|
311
363
|
|
|
@@ -320,9 +372,8 @@ export default class SQL extends Service<Config, Hooks, Application> {
|
|
|
320
372
|
changedRows: 0,
|
|
321
373
|
insertId: 0,
|
|
322
374
|
serverStatus: 0,
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
procotol41: false,
|
|
375
|
+
warningStatus: 0,
|
|
376
|
+
info: undefined
|
|
326
377
|
};
|
|
327
378
|
}
|
|
328
379
|
|
|
@@ -387,29 +438,71 @@ export default class SQL extends Service<Config, Hooks, Application> {
|
|
|
387
438
|
opts: With<TInsertQueryOptions<TData>, 'upsert'>
|
|
388
439
|
): string | null {
|
|
389
440
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
// Auto
|
|
393
|
-
if (upsert === true) {
|
|
394
|
-
console.log(LogPrefix, `Automatic upsert into ${table.chemin} using ${table.pk.join(', ')} as pk`);
|
|
395
|
-
upsert = table.columnNamesButPk;
|
|
396
|
-
}
|
|
441
|
+
const valuesToUpdate = this.getValuesToUpdate(table, opts.upsert);
|
|
397
442
|
|
|
398
443
|
// All columns are ps
|
|
399
|
-
|
|
444
|
+
const valuesToUpdatesEntries = Object.entries(valuesToUpdate);
|
|
445
|
+
if (valuesToUpdatesEntries.length === 0)
|
|
400
446
|
// Replace by insert ignore
|
|
401
447
|
return null;
|
|
402
448
|
|
|
403
|
-
return 'ON DUPLICATE KEY UPDATE ' +
|
|
404
|
-
'`' +
|
|
449
|
+
return 'ON DUPLICATE KEY UPDATE ' + valuesToUpdatesEntries.map(([ colName, value ]) =>
|
|
450
|
+
'`' + colName + '` = ' + value
|
|
405
451
|
)
|
|
406
452
|
}
|
|
407
453
|
|
|
454
|
+
// TODO: Fix typings
|
|
455
|
+
private getValuesToUpdate<TData extends TObjetDonnees>(
|
|
456
|
+
table: TMetasTable,
|
|
457
|
+
colsToUpdate: TColsToUpsert<TData>
|
|
458
|
+
) {
|
|
459
|
+
|
|
460
|
+
// Column name => SQL
|
|
461
|
+
let valuesToUpdate: Partial<TData> = {};
|
|
462
|
+
|
|
463
|
+
// Define which columns to update when the record already exists
|
|
464
|
+
let valuesNamesToUpdate: (keyof TData)[] = [];
|
|
465
|
+
if (colsToUpdate === '*') {
|
|
466
|
+
|
|
467
|
+
console.log(LogPrefix, `Automatic upsert into ${table.chemin} using ${table.pk.join(', ')} as pk`);
|
|
468
|
+
valuesNamesToUpdate = table.columnNamesButPk;
|
|
469
|
+
|
|
470
|
+
} else if (Array.isArray( colsToUpdate )) {
|
|
471
|
+
|
|
472
|
+
valuesNamesToUpdate = colsToUpdate;
|
|
473
|
+
|
|
474
|
+
} else {
|
|
475
|
+
|
|
476
|
+
const { '*': updateAll, ...customValuesToUpdate } = colsToUpdate;
|
|
477
|
+
|
|
478
|
+
for (const colKey in customValuesToUpdate)
|
|
479
|
+
valuesToUpdate[ colKey ] = this.esc(customValuesToUpdate[ colKey ]);
|
|
480
|
+
|
|
481
|
+
if (updateAll)
|
|
482
|
+
valuesNamesToUpdate = table.columnNamesButPk;
|
|
483
|
+
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
for (const colToUpdate of valuesNamesToUpdate)
|
|
487
|
+
if (!( colToUpdate in valuesToUpdate ))
|
|
488
|
+
valuesToUpdate[ colToUpdate ] = "VALUES(`" + colToUpdate + "`)";
|
|
489
|
+
|
|
490
|
+
return valuesToUpdate;
|
|
491
|
+
}
|
|
492
|
+
|
|
408
493
|
/*----------------------------------
|
|
409
494
|
- OTHER
|
|
410
495
|
----------------------------------*/
|
|
411
|
-
public delete
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
496
|
+
public delete(
|
|
497
|
+
table: string,
|
|
498
|
+
where: TObjetDonnees | SQL = {},
|
|
499
|
+
opts?: TQueryOptions
|
|
500
|
+
): Promise<ResultSetHeader> {
|
|
501
|
+
|
|
502
|
+
const whereSql = typeof where === 'function' && where['string'] !== undefined
|
|
503
|
+
? where['string']
|
|
504
|
+
: equalities(where).join(' AND ');
|
|
505
|
+
|
|
506
|
+
return this.database.query(`DELETE FROM ${table} WHERE ${whereSql};`, opts);
|
|
507
|
+
}
|
|
415
508
|
}
|