Skip to content

Commit 7fd2982

Browse files
Add CI/CD workflows
1 parent 9d0cabb commit 7fd2982

21 files changed

Lines changed: 712 additions & 0 deletions

.github/workflows/backend_ci.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Backend CI
2+
3+
on:
4+
push:
5+
paths:
6+
- 'src/**'
7+
pull_request:
8+
paths:
9+
- 'src/**'
10+
11+
jobs:
12+
backend:
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- name: Setup Node
19+
uses: actions/setup-node@v4
20+
with:
21+
node-version: '20'
22+
23+
- name: Install dependencies
24+
run: |
25+
cd src
26+
npm install
27+
28+
- name: Run lint
29+
run: |
30+
cd src
31+
npm run lint --if-present
32+
33+
- name: Run tests
34+
run: |
35+
cd src
36+
npm test --if-present

.github/workflows/flutter_ci.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Flutter CI
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
flutter:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@v4
16+
17+
- name: Setup Flutter
18+
uses: subosito/flutter-action@v2
19+
with:
20+
flutter-version: 'stable'
21+
22+
- name: Install dependencies
23+
run: flutter pub get
24+
25+
- name: Analyze code
26+
run: flutter analyze
27+
28+
- name: Run tests
29+
run: flutter test
30+
31+
- name: Build APK
32+
run: flutter build apk --release

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ api_keys.dart
135135
.firebase/
136136
firebase-debug.log
137137
firebase-debug.*.log
138+
*-firebase-adminsdk-*.json
138139

139140
############################################################
140141
# Documentation
50 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

app/google-services.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"project_info": {
3+
"project_number": "846121806536",
4+
"project_id": "maid-5bf4c",
5+
"storage_bucket": "maid-5bf4c.firebasestorage.app"
6+
},
7+
"client": [
8+
{
9+
"client_info": {
10+
"mobilesdk_app_id": "1:846121806536:android:26684438225349d93e53fd",
11+
"android_client_info": {
12+
"package_name": "com.example.maid_ai_reader"
13+
}
14+
},
15+
"oauth_client": [],
16+
"api_key": [
17+
{
18+
"current_key": "AIzaSyBiOnLDiWFF2JYuKSbnbJEhnCZUisDv7AI"
19+
}
20+
],
21+
"services": {
22+
"appinvite_service": {
23+
"other_platform_oauth_client": []
24+
}
25+
}
26+
}
27+
],
28+
"configuration_version": "1"
29+
}

src/app.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import express from 'express';
2+
import cors from 'cors';
3+
import routes from './routes';
4+
5+
const app = express();
6+
7+
app.use(cors());
8+
app.use(express.json());
9+
app.use('/api', routes);
10+
11+
const PORT = process.env.PORT || 3000;
12+
13+
app.listen(PORT, () => {
14+
console.log(`Server running on port ${PORT}`);
15+
});
16+
17+
export default app;

src/config/firebase.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import * as admin from 'firebase-admin';
2+
import * as path from 'path';
3+
4+
const serviceAccountPath = path.join(
5+
__dirname,
6+
'../../maid1-37922-firebase-adminsdk-fbsvc-01dbb7ae1e.json'
7+
);
8+
9+
if (!admin.apps.length) {
10+
admin.initializeApp({
11+
credential: admin.credential.cert(serviceAccountPath),
12+
storageBucket: 'maid1-37922.appspot.com',
13+
});
14+
}
15+
16+
// Firestore Database
17+
export const db = admin.firestore();
18+
19+
// Authentication
20+
export const auth = admin.auth();
21+
22+
// Cloud Storage
23+
export const storage = admin.storage().bucket();
24+
25+
// Cloud Messaging
26+
export const messaging = admin.messaging();
27+
28+
export default admin;

src/controllers/authController.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { Request, Response } from 'express';
2+
import { AuthService, FirestoreService } from '../services/firebaseService';
3+
import { User } from '../types/collections';
4+
5+
export const AuthController = {
6+
async register(req: Request, res: Response) {
7+
try {
8+
const { email, password, displayName, phone, role } = req.body;
9+
10+
const firebaseUser = await AuthService.createUser(email, password, displayName);
11+
await AuthService.setRole(firebaseUser.uid, role);
12+
13+
const user: Omit<User, 'id'> = {
14+
email,
15+
phone,
16+
displayName,
17+
role,
18+
createdAt: new Date(),
19+
updatedAt: new Date(),
20+
};
21+
22+
await FirestoreService.create('users', user, firebaseUser.uid);
23+
24+
res.status(201).json({ uid: firebaseUser.uid, message: 'User created' });
25+
} catch (error: any) {
26+
res.status(400).json({ error: error.message });
27+
}
28+
},
29+
30+
async verifyToken(req: Request, res: Response) {
31+
try {
32+
const token = req.headers.authorization?.split('Bearer ')[1];
33+
if (!token) return res.status(401).json({ error: 'No token provided' });
34+
35+
const decoded = await AuthService.verifyToken(token);
36+
res.json({ uid: decoded.uid, role: decoded.role });
37+
} catch (error: any) {
38+
res.status(401).json({ error: 'Invalid token' });
39+
}
40+
},
41+
};
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { Request, Response } from 'express';
2+
import { BookingService } from '../services/bookingService';
3+
4+
export const BookingController = {
5+
async create(req: Request, res: Response) {
6+
try {
7+
const bookingId = await BookingService.create(req.body);
8+
res.status(201).json({ id: bookingId, message: 'Booking created' });
9+
} catch (error: any) {
10+
res.status(400).json({ error: error.message });
11+
}
12+
},
13+
14+
async getByCustomer(req: Request, res: Response) {
15+
try {
16+
const bookings = await BookingService.getByCustomer(req.params.customerId);
17+
res.json(bookings);
18+
} catch (error: any) {
19+
res.status(400).json({ error: error.message });
20+
}
21+
},
22+
23+
async getByMaid(req: Request, res: Response) {
24+
try {
25+
const bookings = await BookingService.getByMaid(req.params.maidId);
26+
res.json(bookings);
27+
} catch (error: any) {
28+
res.status(400).json({ error: error.message });
29+
}
30+
},
31+
32+
async updateStatus(req: Request, res: Response) {
33+
try {
34+
await BookingService.updateStatus(req.params.id, req.body.status);
35+
res.json({ message: 'Status updated' });
36+
} catch (error: any) {
37+
res.status(400).json({ error: error.message });
38+
}
39+
},
40+
};

0 commit comments

Comments
 (0)