Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New backend seeds and documentation adjustments #2

Merged
merged 11 commits into from
Oct 26, 2023
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,6 @@ tmtags
*.sql
*.sqlite
*.db
/backend/node-express-js/node-express-starter-js/package-lock.json
/backend/node-express-js/node-express-starter-js/yarn.lock
/backend/node-express-js/node-express-starter-js/package-lock.json
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ implementing your logic.

## Technologies & Frameworks Supported

- **Web Frameworks**: React, Vue.js, Angular, etc.
- **Backend Frameworks**: Express, Django, Flask, etc.
- **Databases**: MongoDB, PostgreSQL, MySQL, Elasticsearch, etc.
- **Frontend Frameworks**: React, Vue.js, Angular, etc.
- **Backend Frameworks**: Node.js, Django, Flask, etc.
- **Data Processing**: Pandas, Apache Spark, Hadoop, Kubernetes Jobs, etc.
- **Artificial Intelligence & Machine Learning**: TensorFlow, PyTorch, SciKit-Learn, Keras, etc.
- ... and many more!

## How to Use a Seed
Expand All @@ -38,9 +39,10 @@ we'd love for you to contribute. Check out our [Contributing Guide](./CONTRIBUTI

When creating a PR, make sure to attach appropriate labels. This helps in categorizing and reviewing PRs efficiently:

- `web-framework`: For seeds related to web frameworks.
- `frontend`: For seeds related to frontend frameworks.
- `backend`: For backend-specific seeds.
- `database`: For seeds with a specific database focus.
- `data-processing`: For seeds focused on data processing techniques and tools.
- `ml/ai`: For seeds related to artificial intelligence and machine learning technologies.
- ... (you can extend this list based on the categories of seeds you anticipate)

## What Makes a Good Seed?
Expand Down
19 changes: 19 additions & 0 deletions backend/node-express-js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Node-Express Seeds (JavaScript Version)

This repository contains multiple seeds (starter templates) for Node.js projects using Express.js with different
configurations and additions.

## Folder Structure

- **node-express-starter-js**: This contains a basic Node-Express seed to get you started with a simple "Hello, World!"
API.
- **node-express-mongoose-js**: This seed incorporates Mongoose, enabling you to quickly start a project with MongoDB
integration.

## Getting Started

To use any of the seeds, navigate to the respective folder and follow the instructions in its README.

## Contributions

Feel free to contribute to these seeds by submitting pull requests or opening issues with suggestions/improvements.
2 changes: 2 additions & 0 deletions backend/node-express-js/node-express-mongoose-js/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PORT=3000
MONGO_URI=mongodb+srv://
36 changes: 36 additions & 0 deletions backend/node-express-js/node-express-mongoose-js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Node Express - Mongoose with Javascript Seed

This seed helps you kickstart your Node.js projects using Express.js and **Javascript** with integrated MongoDB support
through Mongoose.

## Getting Started

- Navigate to the `mongoose` directory.
- Configure environment variables as described in the [local development](#local-development) section.
- Ensure you have a MongoDB instance running or use your connection string in the `.env` for an external database.
- Run `yarn install` to install the necessary dependencies.
- Use `yarn start` to start the server.
- Your API is now connected to a MongoDB instance, and you can begin creating models, routes, etc.

## Dependencies

This seed uses:

- [Express.js](https://expressjs.com/): A fast, minimalist web framework for Node.js.
- [Mongoose](https://mongoosejs.com/): Elegant MongoDB object modeling for Node.js.

## Local Development

This seed uses environment variables for configuration:

- Make sure to set up your `.env` file by using `.env.example` as a reference.
- Adjust the values in `.env` as necessary to match your setup.

## Warestack Deployments

For this Flask API to be compatible with automated deployments on Warestack, the inclusion of the `healthz` endpoint is
mandatory. Warestack uses this endpoint to ensure that the service is running correctly.

## Questions & Contributions

If you have any questions or wish to contribute, please open an issue or submit a pull request.
42 changes: 42 additions & 0 deletions backend/node-express-js/node-express-mongoose-js/app/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const express = require('express');

// Load environment variables from .env file
require('dotenv').config();

const dbConfig = require('./config/database');

const RootController = require('./root/root.controller');
const HealthController = require('./health/health.controller');
const UsersController = require('./user/user.controller');

class App {
static bootstrap() {
return new App();
}

constructor() {
// create express js application
this.app = express();

// Connect to MongoDB
dbConfig.connect();

// add routes
this.routes();
}

dbConnect(){
dbConfig.connect();
}
routes() {
this.app.use('/', new RootController().getRouter());
this.app.use('/healthz', new HealthController().getRouter());
this.app.use(`/users`, new UsersController().getRouter());
}
}

function expressApp() {
return new App().app;
}

module.exports = expressApp;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const mongoose = require('mongoose');

const dbConfig = {
connect: function() {
const MONGO_URI = process.env.MONGO_URI || 'mongodb://localhost:27017/test'; // Default URI

mongoose.connect(MONGO_URI, {
useUnifiedTopology: true,
useNewUrlParser: true,
})
.then(() => {
console.log('Successfully connected to MongoDB.');
})
.catch(error => {
console.error('Error connecting to MongoDB:', error);
process.exit(1);
});

// Setting up mongoose event handlers
mongoose.connection.on('error', err => {
console.error('MongoDB connection error:', err);
});

mongoose.connection.on('disconnected', () => {
console.log('MongoDB disconnected.');
});

process.on('SIGINT', async () => {
try {
await mongoose.connection.close();
console.log('MongoDB connection closed due to app termination.');
process.exit(0);
} catch (err) {
console.error('Error during database disconnection:', err);
process.exit(1);
}
});
}
};

module.exports = dbConfig;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const express = require('express');

const HealthService = require('./health.service');

class HealthController {
constructor() {
this.router = express.Router();

// Setting the routes for the greeting endpoint group
this.router.get('/', this.health.bind(this)); // Binding is necessary for 'this' to refer to the class instance
}

getRouter() {
return this.router;
}

async health(request, response, next) {
const message = HealthService.health();
response.status(200).send(message);
}
}

module.exports = HealthController;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class HealthService {
health() {
return "I am healthy!";
}
}

module.exports = new HealthService(); // Exporting an instance of the service
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const express = require('express');
const RootService = require('./root.service');

class RootController {
constructor() {
this.router = express.Router();

// Setting the routes for the root endpoint group
this.router.get('/', this.info.bind(this)); // Binding is necessary for 'this' to refer to the class instance
}

getRouter() {
return this.router;
}

async info(request, response, next) {
const message = RootService.info();
response.status(200).send(message);
}
}

module.exports = RootController;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class RootService {
info() {
return "Hello, World!";
}
}

module.exports = new RootService(); // Exporting an instance of the service
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
const express = require('express');

const UserService = require('./user.service');

class UsersController {
constructor() {
this.router = express.Router();
this.router.get('/', this.getUsers.bind(this));
this.router.get('/:email', this.getUserByEmail.bind(this));
this.router.post('/', this.createUser.bind(this));
this.router.put('/:email', this.updateUser.bind(this));
this.router.delete('/:email', this.deleteUser.bind(this));
}

getRouter() {
return this.router;
}

async getUsers(request, response, next) {
try {
const users = await UserService.getUsers();
response.status(200).send(users);
} catch (e) {
next(e);
}
}

async getUserByEmail(request, response, next) {
try {
const user = await UserService.getUserByEmail(request.params.email);
if (!user) {
response.status(404).send({ message: 'User not found.' });
return;
}
response.status(200).send(user);
} catch (e) {
next(e);
}
}

async createUser(request, response, next) {
try {
const user = await UserService.createUser(request.body);
response.status(201).send(user);
} catch (e) {
next(e);
}
}

async updateUser(request, response, next) {
try {
const updatedUser = await UserService.updateUser(request.params.email, request.body);
if (!updatedUser) {
response.status(404).send({ message: 'User not found.' });
return;
}
response.status(200).send(updatedUser);
} catch (e) {
next(e);
}
}

async deleteUser(request, response, next) {
try {
const deletedUser = await UserService.deleteUser(request.params.email);
if (!deletedUser) {
response.status(404).send({ message: 'User not found.' });
return;
}
response.status(200).send(deletedUser);
} catch (e) {
next(e);
}
}
}

module.exports = UsersController;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
}
});

module.exports = mongoose.model('User', userSchema);
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const User = require('./user.model');

class UserService {
async getUsers() {
try {
return await User.find();
} catch (err) {
throw new Error('Error fetching users from the database.');
}
}

async getUserByEmail(email) {
try {
return await User.findOne({ email: email });
} catch (err) {
throw new Error('Error fetching user by email.');
}
}

async createUser(user) {
try {
return await User.create(user);
} catch (err) {
throw new Error('Error creating user.');
}
}

async updateUser(email, user) {
try {
return await User.findOneAndUpdate({ email: email }, user, { new: true });
} catch (err) {
throw new Error('Error updating user.');
}
}

async deleteUser(email) {
try {
return await User.findOneAndDelete({ email: email });
} catch (err) {
throw new Error('Error deleting user.');
}
}
}

module.exports = new UserService(); // Exporting an instance of the service
14 changes: 14 additions & 0 deletions backend/node-express-js/node-express-mongoose-js/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "node-express-mongoose-js",
"version": "1.0.0",
"description": "A foundational seed for Node-Express and Javascript with Mongoose projects.",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"dotenv": "^16.3.1",
"express": "^4.18.2",
"mongoose": "^7.5.4"
}
}
Loading