ไม่มีชื่อบทความ
⚙️ ออกแบบ “Firestore Service Layer” – แยก Logic อ่าน/เขียนให้ทดสอบง่าย
โฟลเดอร์ที่แนะนำ
สร้างไฟล์ใน /services/firestore/:
services/
└── firestore/
├── addMessage.js
├── getMessages.js
└── updateMessage.js
🔹 ตัวอย่าง addMessage.js
import { collection, addDoc } from 'firebase/firestore';
import { db } from '@/lib/firebaseClient';
export async function addMessage(data) {
try {
const docRef = await addDoc(collection(db, 'messages'), data);
return { id: docRef.id };
} catch (err) {
console.error('[addMessage] ❌', err);
throw new Error('ไม่สามารถเพิ่มข้อความได้');
}
}
🔹 ตัวอย่าง getMessages.js
import { collection, getDocs } from 'firebase/firestore';
import { db } from '@/lib/firebaseClient';
export async function getMessages() {
try {
const snap = await getDocs(collection(db, 'messages'));
return snap.docs.map(doc => ({ id: doc.id, ...doc.data() }));
} catch (err) {
console.error('[getMessages] ❌', err);
return [];
}
}
🔹 ตัวอย่าง updateMessage.js
import { doc, updateDoc } from 'firebase/firestore';
import { db } from '@/lib/firebaseClient';
export async function updateMessage(id, newData) {
try {
const docRef = doc(db, 'messages', id);
await updateDoc(docRef, newData);
return true;
} catch (err) {
console.error('[updateMessage] ❌', err);
return false;
}
}
✅ จุดเด่นของการแยก Service Layer
- Separation of Concerns: หน้า UI ไม่ต้องมี logic Firebase โดยตรง
- Reusability: เรียกซ้ำได้จากหลาย component หรือ API
- Testability: นำไปเขียน Unit Test ได้ง่ายขึ้น
🧪 ตัวอย่างการทดสอบด้วย Vitest (ข้ามได้หากยังไม่ใช้)
// tests/services/firestore/addMessage.test.js
import { describe, it, expect, vi } from 'vitest';
import { addMessage } from '@/services/firestore/addMessage';
vi.mock('@/lib/firebaseClient', () => ({
db: {},
}));
vi.mock('firebase/firestore', () => ({
collection: vi.fn(),
addDoc: vi.fn(() => Promise.resolve({ id: 'mock-id' })),
}));
describe('addMessage()', () => {
it('should return doc id', async () => {
const result = await addMessage({ text: 'Hello' });
expect(result.id).toBe('mock-id');
});
});
สามารถใช้แนวทางนี้กับ Collection อื่น ๆ ได้เช่นกัน เช่น users, comments, logs ฯลฯ
หากต้องการเวอร์ชัน TypeScript ก็สามารถใช้ generics T เพิ่มเข้าไปใน type ของ data ที่รับเข้า/ส่งออก