Skip to content

Commit d8cb5ec

Browse files
Merge pull request #2 from CarmeloCampos/improve-readme
docs: enhance README with comprehensive usage guide
2 parents 56d87e7 + 0a1b7af commit d8cb5ec

1 file changed

Lines changed: 216 additions & 25 deletions

File tree

README.md

Lines changed: 216 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,223 @@
11
# Firestore DB ORM
22

3-
`firestore-db-orm` is a simple ORM library for Firestore, designed to provide easy-to-use, TypeScript-typed CRUD
4-
operations.
3+
`firestore-db-orm` is a lightweight, TypeScript-first Object-Relational Mapper (ORM) for Google Firestore. It simplifies interactions with your Firestore database by providing an intuitive, promise-based API for common CRUD (Create, Read, Update, Delete) operations and flexible querying.
4+
5+
## Table of Contents
6+
7+
- [Features](#features)
8+
- [Installation](#installation)
9+
- [Instantiate the ORM](#instantiate-the-orm)
10+
- [CRUD Operations](#crud-operations)
11+
- [`add(data: T): Promise<T>`](#adddata-t-promiset)
12+
- [`get(id: string): Promise<T | undefined>`](#getid-string-promiset--undefined)
13+
- [`update(id: string, data: Partial<T>): Promise<void>`](#updateid-string-data-partialt-promisevoid)
14+
- [`delete(id: string): Promise<void>`](#deleteid-string-promisevoid)
15+
- [`findOne(searchParams: SearchParams): Promise<T | undefined>`](#findonesearchparams-searchparams-promiset--undefined)
16+
- [Finding Multiple Documents (`finds` Method)](#finding-multiple-documents-finds-method)
17+
- [Examples of `finds` Method](#examples-of-finds-method)
18+
- [Advanced Usage (Future Enhancements)](#advanced-usage-future-enhancements)
19+
- [Contributing](#contributing)
20+
- [License](#license)
21+
22+
## Features
23+
24+
* **Type-Safe:** Leverages TypeScript for strong typing of your data models.
25+
* **Simple API:** Easy-to-understand methods for CRUD operations.
26+
* **Flexible Querying:** Supports various query conditions for finding documents.
27+
* **Automatic ID Generation:** Automatically handles `id` generation for new documents (using `uuid`).
28+
* **Promise-based:** Asynchronous operations using Promises for modern JavaScript.
529

630
## Installation
731

8-
Install firebase-db-orm with bun
32+
Install `firestore-db-orm` using your preferred package manager:
933

34+
**bun**
1035
```bash
1136
bun add firestore-db-orm
1237
```
1338

39+
**npm**
40+
```bash
41+
npm install firestore-db-orm
42+
```
43+
44+
**yarn**
45+
```bash
46+
yarn add firestore-db-orm
47+
```
48+
1449
## Instantiate the ORM
1550

1651
```typescript
52+
import { initializeApp, cert } from 'firebase-admin/app';
53+
import { getFirestore } from 'firebase-admin/firestore';
1754
import { FirestoreORM } from "firestore-db-orm";
18-
import { db } from "./firestore";
19-
import type { IUser } from "./user.interface";
20-
55+
import type { IUser } from "./user.interface"; // Your data model interface
56+
57+
// Initialize Firebase Admin SDK
58+
// Ensure you have your service account key JSON file
59+
// (e.g., serviceAccountKey.json) in your project.
60+
// Replace with your actual service account key path and project details.
61+
const serviceAccount = require('./path/to/your/serviceAccountKey.json');
62+
63+
initializeApp({
64+
credential: cert(serviceAccount),
65+
// databaseURL: 'https://<YOUR_PROJECT_ID>.firebaseio.com' // Optional: if not using default
66+
});
67+
68+
// Get Firestore instance
69+
const db = getFirestore();
70+
71+
// Instantiate the ORM
72+
// Parameters:
73+
// 1. db: The Firestore instance.
74+
// 2. modelCollection: The name of the Firestore collection (e.g., "users").
2175
const userORM = new FirestoreORM<IUser>(db, "users");
76+
2277
export default userORM;
2378
```
2479

25-
## Complete Example
80+
**Explanation:**
81+
82+
* **`IUser`**: This is a TypeScript interface defining the structure of your data (e.g., for a "users" collection). You should replace this with your actual data model.
83+
* **`db`**: This is your initialized Firestore database instance. The example shows how to initialize it using `firebase-admin`. Make sure you have the `firebase-admin` package installed and configured with your Firebase project credentials.
84+
* **`"users"`**: This string is the name of the Firestore collection where your data will be stored. Replace `"users"` with the actual name of your collection.
85+
86+
## CRUD Operations
87+
88+
The ORM provides methods for common Create, Read, Update, and Delete (CRUD) operations.
89+
90+
### `add(data: T): Promise<T>`
91+
92+
Adds a new document to the collection. The `id` field is automatically generated (using `uuid`) and added to the data before saving.
93+
94+
```typescript
95+
import userORM from "./user.orm"; // Assuming user.orm.ts is set up as shown above
96+
import { v4 } from "uuid"; // Or use any ID generation strategy
97+
98+
(async () => {
99+
try {
100+
const newUser = await userORM.add({
101+
// id: v4(), // ID is auto-generated, but you can pre-define if needed for your model
102+
email: "test@example.com",
103+
password: "securepassword123",
104+
// Add other fields as per your IUser interface
105+
});
106+
console.log("New user created:", newUser);
107+
} catch (error) {
108+
console.error("Error adding user:", error);
109+
}
110+
})();
111+
```
112+
113+
### `get(id: string): Promise<T | undefined>`
114+
115+
Retrieves a document by its ID. Returns the document data if found, otherwise `undefined`.
26116

27117
```typescript
28118
import userORM from "./user.orm";
29-
import { v4 } from "uuid";
30119

31120
(async () => {
32-
const newUser = await userORM.add({
33-
id: v4(),
34-
email: "test@example.com",
35-
password: "securepassword",
36-
});
37-
console.log("New user created:", newUser);
38-
39-
const user = await userORM.get(newUser.id);
40-
if (user) {
41-
console.log("User found:", user);
121+
try {
122+
const userId = "some-user-id"; // Replace with an actual ID
123+
const user = await userORM.get(userId);
124+
125+
if (user) {
126+
console.log("User found:", user);
127+
} else {
128+
console.log("User not found.");
129+
}
130+
} catch (error) {
131+
console.error("Error getting user:", error);
42132
}
133+
})();
134+
```
43135

44-
await userORM.update(newUser.id, { email: "newemail@example.com" });
45-
await userORM.delete(newUser.id);
136+
### `update(id: string, data: Partial<T>): Promise<void>`
46137

47-
const otherUser = await userORM.findOne({
48-
email: { where: "==", value: "email@asd.com" },
49-
});
138+
Updates an existing document with the provided data. `Partial<T>` means you can provide only the fields you want to change.
139+
140+
```typescript
141+
import userORM from "./user.orm";
142+
143+
(async () => {
144+
try {
145+
const userIdToUpdate = "some-user-id"; // Replace with an actual ID
146+
await userORM.update(userIdToUpdate, { email: "updated.email@example.com" });
147+
console.log("User updated successfully.");
148+
149+
// You can verify by getting the user
150+
const updatedUser = await userORM.get(userIdToUpdate);
151+
if (updatedUser) {
152+
console.log("Updated user data:", updatedUser);
153+
}
154+
} catch (error) {
155+
console.error("Error updating user:", error);
156+
}
50157
})();
51158
```
52159

53-
## Examples of `finds` Method
160+
### `delete(id: string): Promise<void>`
161+
162+
Deletes a document by its ID.
163+
164+
```typescript
165+
import userORM from "./user.orm";
166+
167+
(async () => {
168+
try {
169+
const userIdToDelete = "some-user-id"; // Replace with an actual ID
170+
await userORM.delete(userIdToDelete);
171+
console.log("User deleted successfully.");
172+
173+
// You can verify by trying to get the user
174+
const deletedUser = await userORM.get(userIdToDelete);
175+
if (!deletedUser) {
176+
console.log("User confirmed deleted.");
177+
}
178+
} catch (error) {
179+
console.error("Error deleting user:", error);
180+
}
181+
})();
182+
```
183+
184+
### `findOne(searchParams: SearchParams): Promise<T | undefined>`
185+
186+
Finds a single document that matches the search criteria. Returns the first matching document or `undefined`.
187+
The `searchParams` object allows you to specify field conditions.
188+
189+
```typescript
190+
import userORM from "./user.orm";
191+
192+
(async () => {
193+
try {
194+
const user = await userORM.findOne({
195+
email: { where: "==", value: "test@example.com" },
196+
});
197+
198+
if (user) {
199+
console.log("User found by email:", user);
200+
} else {
201+
console.log("User with that email not found.");
202+
}
203+
} catch (error) {
204+
console.error("Error finding one user:", error);
205+
}
206+
})();
207+
```
208+
209+
## Finding Multiple Documents (`finds` Method)
210+
211+
The `finds(searchParams: SearchParams = {}): Promise<T[]>` method allows you to retrieve multiple documents based on complex query conditions.
212+
213+
**`SearchParams` Type:**
214+
215+
The `searchParams` object is a key-value map where:
216+
* **Key**: The field name in your document (e.g., `age`, `name`).
217+
* **Value**: Can be one of the following:
218+
* A direct value (e.g., `25`, `"Juan"`): This implies an "equals" (`==`) condition.
219+
* A `SearchParam` object: `{ value: any; where: WhereFilterOp }` for specifying conditions like greater than (`>`), less than (`<`), etc. `WhereFilterOp` is a string type from Firebase (`<`, `<=`, `==`, `!=`, `>=`, `>`, `array-contains`, `in`, `not-in`, `array-contains-any`).
220+
* An array of `SearchParam` objects: For applying multiple conditions to the same field (e.g., age > 10 AND age < 30).
54221

55222
### Example 1: Simple Search
56223

@@ -167,6 +334,30 @@ const result6 = await userORM.finds(searchParams6);
167334
console.log(result6);
168335
```
169336

337+
## Advanced Usage (Future Enhancements)
338+
339+
Currently, the ORM focuses on providing straightforward CRUD operations. Future enhancements could include:
340+
341+
* **Transactions:** Support for Firestore transactions to perform multiple operations atomically.
342+
* **Batch Writes:** Enabling batch operations (e.g., multiple `set`, `update`, or `delete` calls in a single request) for efficiency.
343+
* **Custom Data Transformers:** Hooks or methods to transform data when reading from or writing to Firestore (e.g., for date conversions, encryption/decryption).
344+
* **Real-time Listeners:** Integration with Firestore's real-time data synchronization capabilities.
345+
346+
If you have specific needs or ideas for advanced features, please feel free to open an issue or contribute to the project!
347+
348+
## Contributing
349+
350+
Contributions are welcome! If you'd like to contribute, please follow these steps:
351+
352+
1. **Fork the repository.**
353+
2. **Create a new branch:** `git checkout -b my-feature-branch`
354+
3. **Make your changes.**
355+
4. **Commit your changes:** `git commit -m 'Add some feature'`
356+
5. **Push to the branch:** `git push origin my-feature-branch`
357+
6. **Open a pull request.**
358+
359+
Please make sure to update tests as appropriate and follow the existing code style.
360+
170361
## License
171362

172-
[MPL-2.0](https://www.mozilla.org/en-US/MPL/2.0/)
363+
This project is licensed under the MPL-2.0 License. See the [LICENSE](LICENSE) file for details.

0 commit comments

Comments
 (0)