diff --git a/.gitignore b/.gitignore index 889ab41..7209816 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,11 @@ node_modules # testing coverage +*.sqlite3 # production build/ +config.json # misc .DS_Store diff --git a/package.json b/package.json index 5e2796c..01c4c6c 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,11 @@ "scripts": { "build": "cd client && npm run build", "dev": "nodemon --exec npm start", + "migrate": "npm run migrate:up", + "migrate:up": "cd server && npx sequelize-cli db:migrate", + "migrate:undo": "cd server && npx sequelize-cli db:migrate:undo", "start": "node server/index.js", - "start:client": "cd client && node server/index.js" + "start:client": "cd client && npm run start" }, "keywords": [ "train" @@ -17,10 +20,11 @@ "dependencies": { "express": "^4.18.2", "pg": "^8.8.0", - "sequelize": "^6.32.1" + "sequelize": "^6.32.1", + "sequelize-cli": "^6.6.1" }, "devDependencies": { "nodemon": "^2.0.22", - "sqlite3": "^5.1.5" + "sqlite3": "^5.1.6" } } diff --git a/server/config/config.json.example b/server/config/config.json.example new file mode 100644 index 0000000..0e1ad80 --- /dev/null +++ b/server/config/config.json.example @@ -0,0 +1,17 @@ +{ + "development": { + "dialect": "sqlite", + "storage": "db.sqlite3" + }, + "test": { + "dialect": "sqlite", + "storage": "db-test.sqlite3" + }, + "production": { + "username": "prenezletrain", + "password": "PASSWORD", + "database": "prenezletrain", + "host": "127.0.0.1", + "dialect": "postgres" + } +} diff --git a/server/migrations/20230623122607-create-airport.js b/server/migrations/20230623122607-create-airport.js new file mode 100644 index 0000000..2d1cd44 --- /dev/null +++ b/server/migrations/20230623122607-create-airport.js @@ -0,0 +1,43 @@ +'use strict'; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable('Airports', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + name: { + type: Sequelize.STRING + }, + iata_code: { + type: Sequelize.STRING + }, + icao_code: { + type: Sequelize.STRING + }, + lat: { + type: Sequelize.FLOAT + }, + lng: { + type: Sequelize.FLOAT + }, + country_code: { + type: Sequelize.STRING + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable('Airports'); + } +}; \ No newline at end of file diff --git a/server/migrations/20230623122947-create-flight.js b/server/migrations/20230623122947-create-flight.js new file mode 100644 index 0000000..ad9ea21 --- /dev/null +++ b/server/migrations/20230623122947-create-flight.js @@ -0,0 +1,88 @@ +'use strict'; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable('Flights', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + airline_iata: { + type: Sequelize.STRING + }, + airline_icao: { + type: Sequelize.STRING + }, + flight_number: { + type: Sequelize.STRING + }, + flight_iata: { + type: Sequelize.STRING + }, + flight_icao: { + type: Sequelize.STRING + }, + cs_airline_data: { + type: Sequelize.STRING + }, + cs_flight_iata: { + type: Sequelize.STRING + }, + cs_flight_number: { + type: Sequelize.STRING + }, + dep_iata: { + type: Sequelize.STRING + }, + dep_icao: { + type: Sequelize.STRING + }, + dep_terminals: { + type: Sequelize.JSON + }, + dep_time: { + type: Sequelize.TIME + }, + dep_time_utc: { + type: Sequelize.TIME + }, + arr_iata: { + type: Sequelize.STRING + }, + arr_icao: { + type: Sequelize.STRING + }, + arr_terminals: { + type: Sequelize.JSON + }, + arr_time: { + type: Sequelize.TIME + }, + arr_time_utc: { + type: Sequelize.TIME + }, + duration: { + type: Sequelize.INTEGER + }, + updated: { + type: Sequelize.DATE + }, + days: { + type: Sequelize.JSON + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable('Flights'); + } +}; diff --git a/server/models/airport.js b/server/models/airport.js new file mode 100644 index 0000000..68d8a8e --- /dev/null +++ b/server/models/airport.js @@ -0,0 +1,28 @@ +'use strict'; +const { + Model +} = require('sequelize'); +module.exports = (sequelize, DataTypes) => { + class Airport extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + } + } + Airport.init({ + name: DataTypes.STRING, + iata_code: DataTypes.STRING, + icao_code: DataTypes.STRING, + lat: DataTypes.FLOAT, + lng: DataTypes.FLOAT, + country_code: DataTypes.STRING + }, { + sequelize, + modelName: 'Airport', + }); + return Airport; +}; \ No newline at end of file diff --git a/server/models/flight.js b/server/models/flight.js new file mode 100644 index 0000000..d748f42 --- /dev/null +++ b/server/models/flight.js @@ -0,0 +1,43 @@ +'use strict'; +const { + Model +} = require('sequelize'); +module.exports = (sequelize, DataTypes) => { + class Flight extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + } + } + Flight.init({ + airline_iata: DataTypes.STRING, + airline_icao: DataTypes.STRING, + flight_number: DataTypes.STRING, + flight_iata: DataTypes.STRING, + flight_icao: DataTypes.STRING, + cs_airline_data: DataTypes.STRING, + cs_flight_iata: DataTypes.STRING, + cs_flight_number: DataTypes.STRING, + dep_iata: DataTypes.STRING, + dep_icao: DataTypes.STRING, + dep_terminals: DataTypes.JSON, + dep_time: DataTypes.TIME, + dep_time_utc: DataTypes.TIME, + arr_iata: DataTypes.STRING, + arr_icao: DataTypes.STRING, + arr_terminals: DataTypes.JSON, + arr_time: DataTypes.TIME, + arr_time_utc: DataTypes.TIME, + duration: DataTypes.INTEGER, + updated: DataTypes.DATE, + days: DataTypes.JSON + }, { + sequelize, + modelName: 'Flight', + }); + return Flight; +}; \ No newline at end of file diff --git a/server/models/index.js b/server/models/index.js new file mode 100644 index 0000000..024200e --- /dev/null +++ b/server/models/index.js @@ -0,0 +1,43 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const Sequelize = require('sequelize'); +const process = require('process'); +const basename = path.basename(__filename); +const env = process.env.NODE_ENV || 'development'; +const config = require(__dirname + '/../config/config.json')[env]; +const db = {}; + +let sequelize; +if (config.use_env_variable) { + sequelize = new Sequelize(process.env[config.use_env_variable], config); +} else { + sequelize = new Sequelize(config.database, config.username, config.password, config); +} + +fs + .readdirSync(__dirname) + .filter(file => { + return ( + file.indexOf('.') !== 0 && + file !== basename && + file.slice(-3) === '.js' && + file.indexOf('.test.js') === -1 + ); + }) + .forEach(file => { + const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes); + db[model.name] = model; + }); + +Object.keys(db).forEach(modelName => { + if (db[modelName].associate) { + db[modelName].associate(db); + } +}); + +db.sequelize = sequelize; +db.Sequelize = Sequelize; + +module.exports = db;