Cette fois, nous utiliserons Sequelize, qui est l'ORM de Node.js, pour accéder à MySQL depuis le serveur Express, acquérir des données et répondre.
Puisque la création du serveur Express et de l'API simple a été complétée par l'article précédent, cette fois je me concentrerai sur l'introduction de Sequelize et la création de Model.
Comment créer un environnement pour [TypeScript + Vue + Express + MySQL] avec Docker ~ Vue Edition ~ Comment créer un environnement de [TypeScript + Vue + Express + MySQL] avec Docker ~ MySQL edition ~ Comment créer un environnement de [TypeScript + Vue + Express + MySQL] avec Docker ~ Express ~
docker-compose.yml
version: "3"
services:
app:
container_name: app_container
build: ./docker/app
ports:
- 8080:8080
volumes:
- ./app:/app
stdin_open: true
tty: true
environment:
TZ: Asia/Tokyo
command: yarn serve
networks: #Ajouter un réseau
- default
api:
container_name: api_container
build: ./docker/api
ports:
- 3000:3000
volumes:
- ./api:/api
tty: true
environment:
CHOKIDAR_USEPOLLING: 1
TZ: Asia/Tokyo
depends_on:
- db
command: yarn nodemon
networks: #Ajouter un réseau
- default
db:
container_name: db_container
build: ./docker/db
image: mysql:5.7
ports:
- 3306:3306
volumes:
- ./db/conf/my.cnf:/etc/mysql/conf.d/mysql.cnf
- ./db/init_db:/docker-entrypoint-initdb.d
- test_data:/var/lib/mysql
environment:
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- TZ="Asia/Tokyo"
networks: #Ajouter un réseau
- default
networks: #Ajouter un réseau
default:
volumes:
test_data:
En se connectant à un réseau commun, il est possible de communiquer entre chaque composant.
$ docker-compose up -d
De là, nous allons introduire Sequelize, qui est un ORM pour Node.js (qui acquiert et manipule les données d'une base de données relationnelle), et acquiert des données de la base de données.
$ docker exec -it api_container sh
$ yarn add [email protected] sequelize-typescript reflect-metadata mysql2 log4js cors
$ yarn add --dev dotenv @types/validator @types/bluebird @types/cors @types/dotenv
* Une erreur peut survenir selon la version de sequelize, vous devez donc vérifier la version au moment de l'installation! </ font>
api/index.ts
import cors from 'cors' //ajouter à
import express from 'express'
import router from './routes/index'
const app = express()
const port = 3000
app.use(cors()) //ajouter à
app.use('/api', router)
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
api/models/settings/.env
MYSQL_DATABASE=test_db
MYSQL_USER={Ce qui a été défini lors de la création du conteneur MySQL}
MYSQL_PASSWORD={Ce qui a été défini lors de la création du conteneur MySQL}
MYSQL_ROOT_PASSWORD={Ce qui a été défini lors de la création du conteneur MySQL}
Il s'agit du même paramètre que .env dans le répertoire racine.
api/models/settings/db_setting.ts
import dotenv from 'dotenv'
dotenv.config({ path: __dirname + '/.env' })
interface DatabaseTypes {
database: string | undefined
user: string | undefined
password: string | undefined
}
export const dbSetting: DatabaseTypes = {
database: process.env.MYSQL_DATABASE,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
}
Définissez le mot de passe et la table pour Sequelize.
api/models/test.ts
import {
Table,
Model,
Column,
DataType,
PrimaryKey,
AutoIncrement,
} from 'sequelize-typescript'
@Table({
modelName: 'test',
tableName: 'test',
})
export class Test extends Model<Test> {
@PrimaryKey
@AutoIncrement
@Column(DataType.INTEGER)
readonly id!: number
@Column(DataType.STRING)
name!: string
@Column(DataType.STRING)
description!: string
}
Créez un modèle pour la table de test. Décrit sur une base de décorateur.
J'obtiens une erreur TypeScript, j'ai donc ajouté une règle.
api/tsconfig.json
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": ["./**/*"]
}
Modifier les paramètres tsconfig ci-dessus
api/models/index.ts
import log4js from 'log4js'
import { Sequelize } from 'sequelize-typescript'
import { dbSetting } from './settings/db_setting'
import { Test } from './test'
const logger = log4js.getLogger('mysql')
export default new Sequelize({
dialect: 'mysql',
timezone: '+09:00',
port: 3306,
host: 'db',
username: dbSetting['user'],
password: dbSetting['password'],
database: dbSetting['database'],
logging: (sql: string) => {
logger.info(sql)
},
define: { timestamps: false, underscored: true },
pool: { max: 5, min: 0, idle: 10000, acquire: 30000 },
models: [Test],
})
export { Test }
C'est le cœur de cette époque. Si vous obtenez une erreur, elle devrait être ici. Si la version de la bibliothèque est différente ou si les paramètres tsconfig ne sont pas corrects, une erreur se produira ici.
api/routes/tests/get_tests.ts
import { Request, Response } from 'express'
import { Handler } from '../../core/handler'
import { NO_DATA_EXISTS } from '../../constants/error'
import { Test } from '../../models/index'
export class GetTests {
handler: Handler
constructor(req: Request, res: Response) {
this.handler = new Handler(req, res)
}
/**
*Traitement principal
*/
async main() {
const data = await this.getTests()
if (!data) {
return this.handler.error(NO_DATA_EXISTS)
}
return this.handler.json(data)
}
/**
*Obtenez toutes les données de test
*/
getTests() {
return Test.findAll({
attributes: ['id', 'name', 'description'],
})
}
}
En tant que flux de traitement
Accédez à localhost: 3000 / api / tests! Ce n'est pas grave si les données réelles sont renvoyées en JSON!
api/routes/tests/get_test_by_id.ts
import { Request, Response } from 'express'
import { Handler } from '../../core/handler'
import { PARAMETER_INVALID, NO_DATA_EXISTS } from '../../constants/error'
import { Test } from '../../models/index'
type Params = {
test_id: number
}
export class GetTestById {
handler: Handler
params: Params
constructor(req: Request, res: Response) {
this.handler = new Handler(req, res)
this.params = {
test_id: Number(req.params.test_id),
}
}
/**
*Traitement principal
*/
async main() {
if (!this.params.test_id) {
return this.handler.error(PARAMETER_INVALID)
}
const data = await this.getTest()
if (!data) {
return this.handler.error(NO_DATA_EXISTS)
}
return this.handler.json(data)
}
/**
*Obtenez toutes les données de test
*/
getTest() {
return Test.findOne({
attributes: ['id', 'name', 'description'],
where: {
id: this.params.test_id,
},
})
}
}
Cette fois, dans la fonction findOne (obtenir une donnée correspondante), recherchez par la clause where pour obtenir les données avec l'ID correspondant.
testsController.ts
import { Router } from 'express'
import { GetTests } from '../tests/get_tests'
import { GetTestById } from '../tests/get_test_by_id' //ajouter à
const router = Router()
router.get('/', (req, res, next) => {
new GetTests(req, res).main().catch(next)
})
router.get('/:test_id', (req, res, next) => { //ajouter à
new GetTestById(req, res).main().catch(next) //ajouter à
}) //ajouter à
export default router
L'ID à rechercher est passé à la classe GetTestById en tant que requête de l'URL.
Accédez à localhost: 3000 / api / tests / 1
Si les données de / tests / ** {ID spécifié ici} ** sont renvoyées, c'est réussi! Veuillez vérifier avec d'autres identifiants à titre d'essai.
À ce stade, le côté serveur est terminé. À partir de là, nous allons définir les paramètres pour appeler l'API créée depuis l'avant.
$ exit
$ docker exec -it app_container sh
$ yarn add axios
app/src/utils/axios.ts
import axios from 'axios'
export const api = axios.create({
baseURL: 'http://localhost:3000/api',
})
Définissez un module pour les contre-mesures cors et la conversion d'URL par défaut. Lors d'un appel, il est possible d'appeler avec api.get ou api.post.
app/src/store/modules/test.ts
import {
getModule,
Module,
VuexModule,
Mutation,
Action,
} from 'vuex-module-decorators'
import store from '../index'
import { api } from '../../utils/axios'
type TestType = {
id: number
name: string
description: string
}
type TestState = {
apiTests: TestType[]
}
@Module({ store, dynamic: true, namespaced: true, name: 'Test' })
class TestModule extends VuexModule implements TestState {
apiTests: TestType[] = []
@Mutation
SET_API_TESTS(payload: TestType[]) {
this.apiTests = payload
}
@Action
async getTests() {
const response = await api.get('/tests')
if (response.data.data) {
this.SET_API_TESTS(response.data.data)
}
}
}
export const testModule = getModule(TestModule)
Créez un magasin de test Vuex et stockez les données obtenues en appelant l'API créée dans GetTests of Action dans l'état apiTests.
app/src/pages/Test.vue
<template>
<div class="test">
<v-data-table :headers="headers" :items="tests"> </v-data-table>
</div>
</template>
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
import { testModule } from '../store/modules/test'
@Component
export default class Test extends Vue {
tests = []
headers = [
{ text: 'ID', align: 'center', value: 'id' },
{ text: 'Nom', align: 'center', value: 'name' },
{ text: 'Détails', align: 'center', value: 'description' },
]
async created() {
await testModule.getTests()
this.tests = testModule.apiTests
}
}
</script>
Lorsque Vue est créée, exécutez l'action getTests dans le magasin de test pour obtenir les données et liez les données apiTests pour référencer les données dans Vue. Passez les données à la v-table-table de Vuetify et vous avez terminé.
localhost:8080
Jusqu'à présent, j'ai pu appeler l'API sur la face avant, obtenir les données de la base de données, stocker les données renvoyées dans Vuex et les rendre. Maintenant que vous avez une base, vous pouvez l'étendre en ajoutant des API et des pages de la même manière.
Maintenant que le modèle est terminé, je vais créer une application qui vous permettra d'effectuer des opérations CLUD simples la prochaine fois!
Comment créer un environnement pour [TypeScript + Vue + Express + MySQL] avec Docker ~ Vue Edition ~ Comment créer un environnement de [TypeScript + Vue + Express + MySQL] avec Docker ~ MySQL edition ~ Comment créer un environnement de [TypeScript + Vue + Express + MySQL] avec Docker ~ Express ~
Recommended Posts