├── .gitignore ├── tsconfig.json ├── nuxt.config.ts ├── app.vue ├── assets └── css │ └── main.css ├── server └── api │ ├── posts.get.js │ └── posts.post.js ├── layouts └── default.vue ├── package.json ├── config └── config.json ├── models ├── posts.js └── index.js ├── .github └── ISSUE_TEMPLATE │ └── bug_report.md ├── migrations └── 20220804091844-create-posts.js ├── LICENSE ├── README.md ├── components ├── TheHeader.vue └── TheFooter.vue └── pages └── index.vue /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log* 3 | .nuxt 4 | .nitro 5 | .cache 6 | .output 7 | .env 8 | dist 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://v3.nuxtjs.org/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /nuxt.config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | css: [ 3 | // CSS file in the project 4 | '@/assets/css/main.css', 5 | ] 6 | } -------------------------------------------------------------------------------- /app.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /assets/css/main.css: -------------------------------------------------------------------------------- 1 | @import url("https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"); 2 | .container { 3 | margin: 0 auto; 4 | } 5 | -------------------------------------------------------------------------------- /server/api/posts.get.js: -------------------------------------------------------------------------------- 1 | import db from '../../models/index.js'; 2 | 3 | export default defineEventHandler((event) => { 4 | return db.Posts.findAll(); 5 | }) -------------------------------------------------------------------------------- /layouts/default.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "nuxt build", 5 | "dev": "nuxt dev", 6 | "generate": "nuxt generate", 7 | "preview": "nuxt preview" 8 | }, 9 | "devDependencies": { 10 | "nuxt": "^3.16.2", 11 | "sequelize-cli": "^6.6.2" 12 | }, 13 | "dependencies": { 14 | "mysql2": "^3.14.0", 15 | "sequelize": "^6.37.7" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /config/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "development": { 3 | "username": "root", 4 | "password": null, 5 | "database": "database_development", 6 | "host": "127.0.0.1", 7 | "dialect": "mysql" 8 | }, 9 | "test": { 10 | "username": "root", 11 | "password": null, 12 | "database": "database_test", 13 | "host": "127.0.0.1", 14 | "dialect": "mysql" 15 | }, 16 | "production": { 17 | "username": "root", 18 | "password": null, 19 | "database": "database_production", 20 | "host": "127.0.0.1", 21 | "dialect": "mysql" 22 | } 23 | } -------------------------------------------------------------------------------- /models/posts.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import { Model } from 'sequelize'; 3 | export default (sequelize, DataTypes) => { 4 | class Posts extends Model { 5 | /** 6 | * Helper method for defining associations. 7 | * This method is not a part of Sequelize lifecycle. 8 | * The `models/index` file will call this method automatically. 9 | */ 10 | static associate(models) { 11 | // define association here 12 | } 13 | } 14 | Posts.init({ 15 | title: DataTypes.STRING, 16 | content: DataTypes.TEXT 17 | }, { 18 | sequelize, 19 | modelName: 'Posts', 20 | }); 21 | return Posts; 22 | }; -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /migrations/20220804091844-create-posts.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = { 3 | async up(queryInterface, Sequelize) { 4 | await queryInterface.createTable('Posts', { 5 | id: { 6 | allowNull: false, 7 | autoIncrement: true, 8 | primaryKey: true, 9 | type: Sequelize.INTEGER 10 | }, 11 | title: { 12 | type: Sequelize.STRING 13 | }, 14 | content: { 15 | type: Sequelize.TEXT 16 | }, 17 | createdAt: { 18 | allowNull: false, 19 | type: Sequelize.DATE 20 | }, 21 | updatedAt: { 22 | allowNull: false, 23 | type: Sequelize.DATE 24 | } 25 | }); 26 | }, 27 | async down(queryInterface, Sequelize) { 28 | await queryInterface.dropTable('Posts'); 29 | } 30 | }; -------------------------------------------------------------------------------- /models/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import Sequelize, { DataTypes } from 'sequelize'; 4 | import allConfig from '~~/config/config.json'; 5 | 6 | 7 | // import all models 8 | import Post from './posts.js'; 9 | 10 | const env = process.env.NODE_ENV || 'development'; 11 | const config = allConfig[env]; 12 | 13 | 14 | 15 | const db = {}; 16 | 17 | let sequelize; 18 | if (config.use_env_variable) { 19 | sequelize = new Sequelize(process.env[config.use_env_variable], config); 20 | } else { 21 | sequelize = new Sequelize(config.database, config.username, config.password, config); 22 | } 23 | 24 | db['Posts'] = Post(sequelize, DataTypes); 25 | 26 | Object.keys(db).forEach(modelName => { 27 | if (db[modelName].associate) { 28 | db[modelName].associate(db); 29 | } 30 | }); 31 | 32 | db.sequelize = sequelize; 33 | db.Sequelize = Sequelize; 34 | 35 | export default db; 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Anik Ghosh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nuxt-mysql-sequelize 2 | CRUD application example using Nuxt JS 3, Sequelize, and MySQL. 3 | 4 | 5 | ## I'm using bootstrap 5 cdn for basic styling 6 | So you have to remove the bootstrap cdn link from main.css file and add your own css file or install library. 7 | 8 | ## Update Database connection 9 | 10 | You will find the connection details in config/config.json file. Then you have to run migration command. 11 | ``` 12 | npx sequelize-cli db:migrate 13 | ``` 14 | 15 | 16 | 17 | ## Setup 18 | 19 | Make sure to install the dependencies: 20 | 21 | ```bash 22 | # yarn 23 | yarn install 24 | 25 | # npm 26 | npm install 27 | 28 | # pnpm 29 | pnpm install --shamefully-hoist 30 | ``` 31 | 32 | ## Development Server 33 | 34 | Start the development server on http://localhost:3000 35 | 36 | ```bash 37 | npm run dev 38 | ``` 39 | 40 | ## Production 41 | 42 | Build the application for production: 43 | 44 | ```bash 45 | npm run build 46 | ``` 47 | 48 | Locally preview production build: 49 | 50 | ```bash 51 | npm run preview 52 | ``` 53 | 54 | Checkout the [deployment documentation](https://v3.nuxtjs.org/guide/deploy/presets) for more information. 55 | -------------------------------------------------------------------------------- /server/api/posts.post.js: -------------------------------------------------------------------------------- 1 | import db from '../../models/index.js'; 2 | 3 | export default defineEventHandler(async (event) => { 4 | const form = await readBody(event); 5 | const { title, content } = extractTitleAndBody(form.content); 6 | 7 | if (form.id && form.id != '') { 8 | return updatePost(form.id, title, content); 9 | } 10 | return createPost(title, content); 11 | }) 12 | 13 | 14 | /** 15 | * Extract title and body from content. 16 | * 17 | * @param {String} content - The content of the post. 18 | * @returns {Object} - The title and body of the post. 19 | */ 20 | function extractTitleAndBody(bodyData) { 21 | const dataArr = bodyData.split('||'); 22 | const title = dataArr[0].trim(); 23 | const content = (dataArr[1] || '').trim(); 24 | return { title, content }; 25 | } 26 | 27 | /** 28 | * Create a new post. 29 | * 30 | */ 31 | async function createPost(title, content) { 32 | const post = await db.Posts.create({ 33 | title, 34 | content, 35 | }); 36 | return post; 37 | } 38 | 39 | /** 40 | * Update a post. 41 | */ 42 | async function updatePost(id, title, content) { 43 | const post = await db.Posts.update({ 44 | title, 45 | content, 46 | }, { 47 | where: { id }, 48 | }); 49 | return post; 50 | } -------------------------------------------------------------------------------- /components/TheHeader.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 55 | -------------------------------------------------------------------------------- /pages/index.vue: -------------------------------------------------------------------------------- 1 | 77 | 78 | -------------------------------------------------------------------------------- /components/TheFooter.vue: -------------------------------------------------------------------------------- 1 | 79 | 80 | --------------------------------------------------------------------------------