Compare commits
11 Commits
d6cfef2a62
...
72d310ccfa
Author | SHA1 | Date | |
---|---|---|---|
72d310ccfa | |||
cf548890fc | |||
580a4a4320 | |||
2cb9c142c4 | |||
92e0fd2a68 | |||
17cccc0c9f | |||
9f8582c412 | |||
ad0f30876e | |||
db40b772f1 | |||
ddd9a2fef4 | |||
c12439d1ed |
9
.env.example
Normal file
9
.env.example
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
HASH_SECRET=''
|
||||||
|
JWT_SECRET=''
|
||||||
|
PROJECT_NAME=''
|
||||||
|
|
||||||
|
MYSQL_HOST=''
|
||||||
|
MYSQL_PORT=''
|
||||||
|
MYSQL_USERNAME=''
|
||||||
|
MYSQL_PASS=''
|
||||||
|
MYSQL_DATABASE=''
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
pnpm-lock.yaml
|
5
.idea/.gitignore
generated
vendored
Normal file
5
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||||
|
</state>
|
||||||
|
</component>
|
10
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
10
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||||
|
<Languages>
|
||||||
|
<language minSize="82" name="TypeScript" />
|
||||||
|
</Languages>
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
6
.idea/jsLibraryMappings.xml
generated
Normal file
6
.idea/jsLibraryMappings.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JavaScriptLibraryMappings">
|
||||||
|
<includedPredefinedLibrary name="Node.js Core" />
|
||||||
|
</component>
|
||||||
|
</project>
|
25
.idea/jsonSchemas.xml
generated
Normal file
25
.idea/jsonSchemas.xml
generated
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JsonSchemaMappingsProjectConfiguration">
|
||||||
|
<state>
|
||||||
|
<map>
|
||||||
|
<entry key="TSConfig">
|
||||||
|
<value>
|
||||||
|
<SchemaInfo>
|
||||||
|
<option name="name" value="TSConfig" />
|
||||||
|
<option name="relativePathToSchema" value="http://json.schemastore.org/tsconfig" />
|
||||||
|
<option name="applicationDefined" value="true" />
|
||||||
|
<option name="patterns">
|
||||||
|
<list>
|
||||||
|
<Item>
|
||||||
|
<option name="path" value="tsconfig.json" />
|
||||||
|
</Item>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</SchemaInfo>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
|
</project>
|
7
.idea/misc.xml
generated
Normal file
7
.idea/misc.xml
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DiscordProjectSettings">
|
||||||
|
<option name="show" value="ASK" />
|
||||||
|
<option name="description" value="" />
|
||||||
|
</component>
|
||||||
|
</project>
|
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/template-express.iml" filepath="$PROJECT_DIR$/.idea/template-express.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
12
.idea/template-express.iml
generated
Normal file
12
.idea/template-express.iml
generated
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
24
biome.json
Normal file
24
biome.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://biomejs.dev/schemas/1.6.4/schema.json",
|
||||||
|
"organizeImports": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"linter": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"recommended": true,
|
||||||
|
"performance": {
|
||||||
|
"recommended": true,
|
||||||
|
"noDelete": "off"
|
||||||
|
},
|
||||||
|
"complexity": {
|
||||||
|
"useLiteralKeys": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"formatter": {
|
||||||
|
"indentStyle": "space",
|
||||||
|
"indentWidth": 2,
|
||||||
|
"lineWidth": 15
|
||||||
|
}
|
||||||
|
}
|
28
package.json
Normal file
28
package.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "brief-05-back",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "dist/app.js",
|
||||||
|
"keywords": [],
|
||||||
|
"author": "Mathis HERRIOT",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@node-rs/argon2": "^1.8.3",
|
||||||
|
"compression": "^1.7.4",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"express": "^4.19.2",
|
||||||
|
"express-validator": "^7.0.1",
|
||||||
|
"express-xss-sanitizer": "^1.2.0",
|
||||||
|
"jose": "^5.2.4",
|
||||||
|
"morgan": "^1.10.0",
|
||||||
|
"mysql2": "^3.9.7",
|
||||||
|
"tslog": "^4.9.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@biomejs/biome": "^1.7.0",
|
||||||
|
"@types/compression": "^1.7.5",
|
||||||
|
"@types/cors": "^2.8.17",
|
||||||
|
"@types/express": "^4.17.21",
|
||||||
|
"@types/node": "^20.12.7"
|
||||||
|
}
|
||||||
|
}
|
27
src/app.ts
Normal file
27
src/app.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import express, { type Express } from 'express';
|
||||||
|
import cors from 'cors';
|
||||||
|
import compression from 'compression';
|
||||||
|
import {Logger} from "tslog";
|
||||||
|
|
||||||
|
|
||||||
|
const logger = new Logger({ name: "App" });
|
||||||
|
|
||||||
|
const app: Express = express();
|
||||||
|
|
||||||
|
// enable cors
|
||||||
|
app.use(cors());
|
||||||
|
app.options('*', cors());
|
||||||
|
|
||||||
|
// parse json request body
|
||||||
|
app.use(express.json());
|
||||||
|
|
||||||
|
// parse urlencoded request body
|
||||||
|
app.use(express.urlencoded({ extended: true }));
|
||||||
|
|
||||||
|
// gzip compression
|
||||||
|
app.use(compression())
|
||||||
|
|
||||||
|
//app.use('/auth', AuthRoutes)
|
||||||
|
|
||||||
|
//app.listen(3333)
|
||||||
|
logger.info('Server is running !')
|
23
src/interfaces/UserData.ts
Normal file
23
src/interfaces/UserData.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
interface DbUserData {
|
||||||
|
id?: string;
|
||||||
|
username: string;
|
||||||
|
displayName: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
email: string;
|
||||||
|
|
||||||
|
passwordHash: string;
|
||||||
|
|
||||||
|
isAdmin: boolean;
|
||||||
|
isDisabled: boolean;
|
||||||
|
|
||||||
|
resetPasswordToken?: string;
|
||||||
|
resetPasswordExpires?: Date;
|
||||||
|
|
||||||
|
dob: Date;
|
||||||
|
gdpr: Date;
|
||||||
|
iat: Date;
|
||||||
|
uat: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DbUserData
|
1
src/interfaces/index.ts
Normal file
1
src/interfaces/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './UserData'
|
2
src/services/index.ts
Normal file
2
src/services/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './jwt.service';
|
||||||
|
export * from './mysql.service'
|
60
src/services/jwt.service.ts
Normal file
60
src/services/jwt.service.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import Jose, {type JWTHeaderParameters, type JWTPayload} from "jose";
|
||||||
|
import {Logger} from "tslog";
|
||||||
|
|
||||||
|
const logger = new Logger({ name: "JwtService" });
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify a JWT token.
|
||||||
|
*
|
||||||
|
* @param {string | Uint8Array} jwt
|
||||||
|
* - The JWT token to verify.
|
||||||
|
* @returns {Promise<null | object>}
|
||||||
|
* - The payload of the verified JWT token or null if verification fails.
|
||||||
|
*/
|
||||||
|
async function JwtVerifyService(jwt: string | Uint8Array): Promise<null | object> {
|
||||||
|
try {
|
||||||
|
const result = await Jose.jwtVerify(
|
||||||
|
jwt,
|
||||||
|
new TextEncoder()
|
||||||
|
.encode(`${process.env["JWT_SECRET"]}`),
|
||||||
|
{
|
||||||
|
})
|
||||||
|
return result.payload;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronously signs a JWT token using the provided payload, header, expiration time, and audience.
|
||||||
|
*
|
||||||
|
* @param {JWTPayload} payload
|
||||||
|
* - The payload data to include in the JWT token.
|
||||||
|
* @param {JWTHeaderParameters} pHeader
|
||||||
|
* - The protected header parameters for the JWT token.
|
||||||
|
* @param {string | number | Date} expTime
|
||||||
|
* - The expiration time for the JWT token. (Can be expressed with '1d', '1mo'...)
|
||||||
|
* @param {string | string[]} audience
|
||||||
|
* - The intended audience for the JWT token.
|
||||||
|
*
|
||||||
|
* @returns {Promise<string>}
|
||||||
|
* - A promise that resolves with the signed JWT token.
|
||||||
|
*/
|
||||||
|
async function JwtSignService(payload: JWTPayload, pHeader: JWTHeaderParameters, expTime: string | number | Date, audience: string | string[]): Promise<string> {
|
||||||
|
return await new Jose.SignJWT(payload)
|
||||||
|
.setProtectedHeader(pHeader)
|
||||||
|
.setIssuedAt(new Date())
|
||||||
|
.setIssuer(`${process.env["JWT_SECRET"]} - Mathis HERRIOT`)
|
||||||
|
.setAudience(audience)
|
||||||
|
.setExpirationTime(expTime)
|
||||||
|
.sign(new TextEncoder().encode(`${process.env["JWT_SECRET"]}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
const JwtService = {
|
||||||
|
verify: JwtVerifyService,
|
||||||
|
sign: JwtSignService
|
||||||
|
}
|
||||||
|
|
||||||
|
export default JwtService
|
234
src/services/mysql.service.ts
Normal file
234
src/services/mysql.service.ts
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
import mysql, {type Connection, type ConnectionOptions} from 'mysql2';
|
||||||
|
import {Logger} from "tslog";
|
||||||
|
// biome-ignore lint/style/useImportType: <explanation>
|
||||||
|
import DbUserData from "@interfaces/UserData";
|
||||||
|
|
||||||
|
|
||||||
|
const access: ConnectionOptions = {
|
||||||
|
host: `${process.env["MYSQL_HOST"]}`,
|
||||||
|
port: Number.parseInt(`${process.env["MYSQL_PORT"]}`),
|
||||||
|
user: `${process.env["MYSQL_USER"]}`,
|
||||||
|
database: `${process.env["MYSQL_USER"]}`,
|
||||||
|
password: `${process.env["MYSQL_PASS"]}`
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MySqlHandler {
|
||||||
|
private readonly handlerName: string;
|
||||||
|
private Logger: Logger<unknown>
|
||||||
|
private Connection: Connection;
|
||||||
|
|
||||||
|
constructor(handlerName?: string) {
|
||||||
|
this.handlerName = handlerName || 'Unknown';
|
||||||
|
this.Logger = new Logger({ name: `DB>> ${this.handlerName}` });
|
||||||
|
this.Connection = mysql.createConnection(access);
|
||||||
|
this.Connection.connect((err) => {
|
||||||
|
if (err) {
|
||||||
|
this.Logger.error(`Error connecting to MySQL: ${err}`);
|
||||||
|
throw new Error()
|
||||||
|
}
|
||||||
|
this.Logger.info(`Connected to MySQL database (${access.database})`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
closeConnection() {
|
||||||
|
this.Connection.end();
|
||||||
|
};
|
||||||
|
|
||||||
|
query(queryString: string) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.Connection.query(queryString, (err, results) => {
|
||||||
|
if (err) {
|
||||||
|
this.Logger.error(`Error executing query: ${err}`);
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve(results);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
execute(queryString: string, values: Array<string | boolean | Date | number>): Promise<unknown> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.Connection.execute(queryString, values, (err: mysql.QueryError | null, results: mysql.QueryResult) => {
|
||||||
|
if (err) {
|
||||||
|
this.Logger.error(`Error executing query: ${err}`);
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve(results);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unprepare a previously prepared SQL query.
|
||||||
|
*
|
||||||
|
* @param {string} queryString
|
||||||
|
* - The SQL query string to unprepare.
|
||||||
|
* @return {Promise}
|
||||||
|
* - A promise that resolves if the unprepare operation is successful,
|
||||||
|
* or rejects with an error if there was an error unpreparing the query.
|
||||||
|
*/
|
||||||
|
unprepare(queryString: string): Promise<unknown> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
resolve(this.Connection.unprepare(queryString));
|
||||||
|
} catch (err) {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const MySqlService = {
|
||||||
|
Handler : MySqlHandler,
|
||||||
|
User: {
|
||||||
|
insert(handler: MySqlHandler, userData: DbUserData) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const _now = new Date()
|
||||||
|
const _sql = "INSERT INTO `users`(`username`, `displayName`, `firstName`, `lastName`, `email`, `passwordHash`, `isAdmin`, `isDisabled`, `dob`, `gdpr`, `iat`, `uat`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||||
|
const _values = [
|
||||||
|
userData.username,
|
||||||
|
userData.displayName,
|
||||||
|
userData.firstName,
|
||||||
|
userData.lastName,
|
||||||
|
userData.email,
|
||||||
|
userData.passwordHash,
|
||||||
|
userData.isAdmin,
|
||||||
|
userData.isDisabled,
|
||||||
|
userData.dob,
|
||||||
|
userData.gdpr,
|
||||||
|
_now,
|
||||||
|
_now
|
||||||
|
]
|
||||||
|
try {
|
||||||
|
resolve(handler.execute(_sql, _values))
|
||||||
|
} catch (err: unknown) {
|
||||||
|
reject(err as Error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
update(handler: MySqlHandler, userData: DbUserData) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
const _t = `
|
||||||
|
${userData.username ? "`username` = ?," : null}
|
||||||
|
${userData.displayName ? "`displayName` = ?," : null}
|
||||||
|
${userData.firstName ? "`firstName` = ?," : null}`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const __sql = "UPDATE `users` SET `lastName` = ?, `email` = ?, `passwordHash` = ?, `isAdmin` = ?, `isDisabled` = ?, `dob` = ?, `gdpr` = ? WHERE `id` = ?";
|
||||||
|
const __values = [
|
||||||
|
userData.username,
|
||||||
|
userData.displayName,
|
||||||
|
userData.firstName,
|
||||||
|
userData.lastName,
|
||||||
|
userData.email,
|
||||||
|
userData.passwordHash,
|
||||||
|
userData.isAdmin,
|
||||||
|
userData.isDisabled,
|
||||||
|
userData.dob,
|
||||||
|
userData.gdpr
|
||||||
|
];
|
||||||
|
try {
|
||||||
|
resolve(handler.execute(__sql, __values));
|
||||||
|
} catch (err: unknown) {
|
||||||
|
reject(err as Error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getById(handler: MySqlHandler, userId: string): Promise<DbUserData> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const _sql = "SELECT * FROM `users` WHERE `id` = ?";
|
||||||
|
const _values = [userId];
|
||||||
|
try {
|
||||||
|
resolve(handler.execute(_sql, _values) as unknown as DbUserData);
|
||||||
|
} catch (err: unknown) {
|
||||||
|
reject(err as Error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getAll(handler: MySqlHandler): Promise<Array<DbUserData>> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const _sql = "SELECT * FROM `users`";
|
||||||
|
try {
|
||||||
|
return resolve(handler.query(_sql) as unknown as Array<DbUserData>);
|
||||||
|
} catch (err: unknown) {
|
||||||
|
return reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getByUsername(handler: MySqlHandler, username: string) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const _sql = "SELECT * FROM `users` WHERE `username` = ?";
|
||||||
|
const _values = [username];
|
||||||
|
try {
|
||||||
|
resolve(handler.execute(_sql, _values));
|
||||||
|
} catch (err: unknown) {
|
||||||
|
reject(err as Error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getByEmail(handler: MySqlHandler, email: string) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const _sql = "SELECT * FROM `users` WHERE `email` = ?";
|
||||||
|
const _values = [email];
|
||||||
|
try {
|
||||||
|
resolve(handler.execute(_sql, _values));
|
||||||
|
} catch (err: unknown) {
|
||||||
|
reject(err as Error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getByDisplayName(handler: MySqlHandler, displayName: string) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const _sql = "SELECT * FROM `users` WHERE `displayName` = ?";
|
||||||
|
const _values = [displayName];
|
||||||
|
try {
|
||||||
|
resolve(handler.execute(_sql, _values));
|
||||||
|
} catch (err: unknown) {
|
||||||
|
reject(err as Error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getAdminStateForId(handler: MySqlHandler, userId: string) : Promise<boolean> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const _sql = "SELECT `isAdmin` FROM `users` WHERE `id` = ?";
|
||||||
|
const _values = [userId];
|
||||||
|
try {
|
||||||
|
const isAdmin = handler.execute(_sql, _values)
|
||||||
|
isAdmin.then((result) => {
|
||||||
|
if (result !== true) return resolve(false);
|
||||||
|
return resolve(true)
|
||||||
|
});
|
||||||
|
} catch (err: unknown) {
|
||||||
|
reject(err as Error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
delete(handler: MySqlHandler, userId: string) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const _sql = "DELETE FROM `users` WHERE `id` = ?";
|
||||||
|
const _values = [userId];
|
||||||
|
try {
|
||||||
|
resolve(handler.execute(_sql, _values));
|
||||||
|
} catch (err: unknown) {
|
||||||
|
reject(err as Error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MySqlService
|
58
tsconfig.json
Normal file
58
tsconfig.json
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2017",
|
||||||
|
"module": "es6",
|
||||||
|
"rootDir": "./src",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"@services/*": [
|
||||||
|
"src/services/*"
|
||||||
|
],
|
||||||
|
"@controllers/*": [
|
||||||
|
"src/controllers/*"
|
||||||
|
],
|
||||||
|
"@routes/*": [
|
||||||
|
"src/routes/*"
|
||||||
|
],
|
||||||
|
"@utils/*": [
|
||||||
|
"src/utils/*"
|
||||||
|
],
|
||||||
|
"@interfaces/*": [
|
||||||
|
"src/interfaces/*"
|
||||||
|
],
|
||||||
|
"@validators/*": [
|
||||||
|
"src/validators/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"removeComments": false,
|
||||||
|
"noEmitOnError": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"strict": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"strictFunctionTypes": true,
|
||||||
|
"strictBindCallApply": true,
|
||||||
|
"strictPropertyInitialization": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"useUnknownInCatchVariables": true,
|
||||||
|
"alwaysStrict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"exactOptionalPropertyTypes": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
|
"allowUnusedLabels": true,
|
||||||
|
"allowUnreachableCode": true,
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user