Skip to content

Commit

Permalink
Merge pull request #13 from austenstone/further
Browse files Browse the repository at this point in the history
further
  • Loading branch information
austenstone authored Oct 26, 2024
2 parents cf2a526 + ce1cc46 commit 0299559
Show file tree
Hide file tree
Showing 29 changed files with 553 additions and 212 deletions.
47 changes: 22 additions & 25 deletions backend/README.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,30 @@
# Backend Documentation
# Backend

## Overview
This is the backend part of the fullstack application built with Node.js, TypeScript, and SQLite. The backend serves as the API for the frontend Angular application.

## Project Structure
- **src/**: Contains the source code for the backend.
- **controllers/**: Handles incoming requests and responses.
- **models/**: Defines data models for interacting with the SQLite database.
- **routes/**: Sets up API routes and links them to controllers.
- **services/**: Contains business logic and data access methods.
- **app.ts**: Entry point for the Node.js backend, setting up the Express app.

## Getting Started
1. Clone the repository.
2. Navigate to the backend directory.
3. Install dependencies:
```
npm install
```
4. Start the server:
```
npm start
```
## Development
```bash
npm run dev
```

## Database
The backend uses SQLite for data storage. The database file is located in the `database/` directory.
The backend uses a MySQL database to store data.

## API Endpoints
Refer to the routes defined in the `src/routes/index.ts` file for available API endpoints.
You can run the docker compose file to start the database. Just shutdown the backend server so you can free up the port.

You can also run it manually:
```bash
docker run -d \
--name db \
--restart always \
-e MYSQL_PASSWORD=octocat \
-e MYSQL_DATABASE=value \
-p 3306:3306 \
-v db:/var/lib/mysql \
-v ./db/init.sql:/docker-entrypoint-initdb.d/init.sql \
mysql
```

## License
This project is licensed under the MIT License.
## API Endpoints
Refer to the routes defined in the [`src/routes/index.ts`](./src/routes/index.ts) file for available API endpoints.
39 changes: 38 additions & 1 deletion backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@
"dependencies": {
"bunyan": "^1.8.15",
"cors": "^2.8.5",
"cron": "^3.1.7",
"dotenv": "^16.4.5",
"eventsource": "^2.0.2",
"express": "^4.21.1",
"express-rate-limit": "^7.4.1",
"mysql2": "^3.11.3",
"node-cron": "^3.0.3",
"octokit": "^4.0.2",
"sequelize": "^6.37.5",
"smee-client": "^2.0.4"
"smee-client": "^2.0.4",
"update-dotenv": "^1.1.1"
},
"devDependencies": {
"@types/bunyan": "^1.8.11",
"@types/cors": "^2.8.17",
"@types/eventsource": "^1.1.15",
"@types/express": "^4.17.21",
"@types/node": "^22.8.0",
"@types/node-cron": "^3.0.11",
"nodemon": "^3.1.7",
"typescript": "^5.6.3"
},
Expand Down
10 changes: 8 additions & 2 deletions backend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { dbConnect } from './database';
import setup from './services/setup';
import SmeeService from './services/smee';
import logger, { expressLoggerMiddleware } from './services/logger';
import dotenv from 'dotenv'

const PORT = Number(process.env.PORT) || 80;

Expand All @@ -27,8 +28,13 @@ app.use(expressLoggerMiddleware);
logger.info('Failed to create app from environment. This is expected if the app is not yet installed.');
}

// API Routes
app.use('/api', bodyParser.json(), bodyParser.urlencoded({ extended: true }), apiRoutes);
app.use((req, res, next) => {
if (req.path === '/api/github/webhooks') {
return next();
}
bodyParser.json()(req, res, next);
}, bodyParser.urlencoded({ extended: true }));
app.use('/api', apiRoutes);

// Angular Frontend
const frontendPath = path.join(__dirname, '../../frontend/dist/github-value/browser');
Expand Down
7 changes: 1 addition & 6 deletions backend/src/controllers/settings.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Request, Response } from 'express';
import SettingsService from '../services/settings.service';

class SettingsController {
// Get all settings ⚙️
async getAllSettings(req: Request, res: Response) {
try {
const settings = await SettingsService.getAllSettings();
Expand All @@ -13,7 +12,6 @@ class SettingsController {
}
}

// Get settings by name 🆔
async getSettingsByName(req: Request, res: Response) {
try {
const { name } = req.params;
Expand All @@ -28,17 +26,15 @@ class SettingsController {
}
}

// Create new settings 🆕
async createSettings(req: Request, res: Response) {
try {
const newSettings = await SettingsService.updateOrCreateSettings(req.body);
const newSettings = await SettingsService.updateSettings(req.body);
res.status(201).json(newSettings);
} catch (error) {
res.status(500).json(error);
}
}

// Update settings ✏️
async updateSettings(req: Request, res: Response) {
try {
const updatedSettings = await SettingsService.updateSettings(req.body);
Expand All @@ -48,7 +44,6 @@ class SettingsController {
}
}

// Delete settings 🗑️
async deleteSettings(req: Request, res: Response) {
try {
const { name } = req.params;
Expand Down
20 changes: 19 additions & 1 deletion backend/src/controllers/setup.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class SetupController {
throw new Error('installation_id must be a number');
}
const app = await setup.createAppFromInstallationId(Number(installation_id));

res.redirect(process.env.WEB_URL || '/');
} catch (error) {
res.status(500).json(error);
Expand All @@ -38,6 +38,24 @@ class SetupController {
}
}

async addExistingApp(req: Request, res: Response) {
try {
const { appId, privateKey, webhookSecret } = req.body;

if (!appId || !privateKey || !webhookSecret) {
return res.status(400).json({ error: 'All fields are required' });
}

const installUrl = await setup.createAppFromExisting(appId, privateKey, webhookSecret);

console.log('installUrl', installUrl );

res.json({ installUrl });
} catch (error) {
res.status(500).json(error);
}
}

isSetup(req: Request, res: Response) {
try {
res.json({ isSetup: setup.isSetup() });
Expand Down
3 changes: 2 additions & 1 deletion backend/src/controllers/webhook.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Webhooks } from '@octokit/webhooks';
import { App } from 'octokit';
import logger from '../services/logger';
import settingsService from '../services/settings.service';

const webhooks = new Webhooks({
secret: process.env.GITHUB_WEBHOOK_SECRET || 'your-secret',
Expand All @@ -14,7 +15,7 @@ const webhooks = new Webhooks({

export const setupWebhookListeners = (github: App) => {
github.webhooks.on("pull_request.opened", ({ octokit, payload }) => {
const surveyUrl = new URL(`/surveys/new`, octokit.request.endpoint.DEFAULTS.baseUrl);
const surveyUrl = new URL(`/surveys/new`, settingsService.baseUrl);

surveyUrl.searchParams.append('url', payload.pull_request.html_url);
surveyUrl.searchParams.append('author', payload.pull_request.user.login);
Expand Down
2 changes: 1 addition & 1 deletion backend/src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const sequelize = new Sequelize({
host: process.env.MYSQL_HOST,
port: parseInt(process.env.MYSQL_PORT || '3306'),
logging: (sql: string, timing?: number) => {
logger.info(sql, timing && `(${timing}ms)`);
logger.info(sql);
}
});
const dbConnect = async () => {
Expand Down
1 change: 1 addition & 0 deletions backend/src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ router.get('/setup/redirect', setupController.setup);
router.get('/setup/install', setupController.install);
router.get('/setup/status', setupController.isSetup);
router.get('/setup/manifest', setupController.getManifest);
router.post('/setup/existing-app', setupController.addExistingApp);

router.get

Expand Down
Loading

0 comments on commit 0299559

Please sign in to comment.