Skip to content

Commit

Permalink
Merge pull request #2 from warestack/feature/node-express-base
Browse files Browse the repository at this point in the history
New backend seeds and documentation adjustments
  • Loading branch information
dkargatzis committed Oct 26, 2023
2 parents f089339 + 59bdcdd commit 44ee874
Show file tree
Hide file tree
Showing 46 changed files with 790 additions and 8 deletions.
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-js-express/node-js-express-starter/package-lock.json
/backend/node-js-express/node-js-express-starter/yarn.lock
/backend/node-js-express/node-js-express-starter/package-lock.json
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ changes can be merged. Please check the output of the failed GitHub Action for d
If you have any questions or need help contributing to this repository, please reach out to the maintainers through:

- The issue tracker.
- On our [Discord channel](https://discord.gg/2yXQUTMs).
- On our [Discord channel](https://discord.gg/mDQd2kcX).

## Code of Conduct

Expand Down
16 changes: 9 additions & 7 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 All @@ -56,7 +58,7 @@ When creating a PR, make sure to attach appropriate labels. This helps in catego
## Resources

- [Warestack Official Documentation](https://www.warestack.com/documentation)
- [Warestack Community Discord](https://discord.gg/2yXQUTMs)
- [Warestack Community Discord](https://discord.gg/pqg5sxhx6Y)
- [Warestack Platform](https://www.warestack.com/)

## License
Expand All @@ -65,4 +67,4 @@ This project is licensed under the MIT License. See the [LICENSE](./LICENSE) fil

---

❤️ Made with passion by the Warestack Community. Join us on [Discord](https://discord.gg/2yXQUTMs)!
❤️ Made with passion by the Warestack Community. Join us on [Discord](https://discord.gg/pqg5sxhx6Y)!
19 changes: 19 additions & 0 deletions backend/node-js-express/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-js-express-starter**: This contains a basic Node-Express seed to get you started with a simple "Hello, World!"
API.
- **node-js-express-mongoose**: 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-js-express/node-js-express-mongoose/.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-js-express/node-js-express-mongoose/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. Additionally, it includes a `healthz` endpoint, essential for automated deployments on Warestack.

## Getting Started

- Navigate to the `node-js-express-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-js-express/node-js-express-mongoose/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);
Loading

0 comments on commit 44ee874

Please sign in to comment.