{"id":22239793,"url":"https://github.com/carmelocampos/firestore-db-orm","last_synced_at":"2026-02-04T10:16:07.320Z","repository":{"id":243602827,"uuid":"812874619","full_name":"CarmeloCampos/firestore-db-orm","owner":"CarmeloCampos","description":"ORM for the database in Firestore","archived":false,"fork":false,"pushed_at":"2024-07-12T06:33:16.000Z","size":159,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-14T20:12:12.089Z","etag":null,"topics":["firebase","firebase-db-orm","firestore","firestore-orm"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/firestore-db-orm","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CarmeloCampos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-10T04:20:41.000Z","updated_at":"2024-07-12T06:33:20.000Z","dependencies_parsed_at":"2024-06-10T05:32:53.322Z","dependency_job_id":"c470c811-a400-4129-9fab-52b50c01cdd8","html_url":"https://github.com/CarmeloCampos/firestore-db-orm","commit_stats":null,"previous_names":["carmelocampos/firestore-db-orm"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CarmeloCampos%2Ffirestore-db-orm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CarmeloCampos%2Ffirestore-db-orm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CarmeloCampos%2Ffirestore-db-orm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CarmeloCampos%2Ffirestore-db-orm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CarmeloCampos","download_url":"https://codeload.github.com/CarmeloCampos/firestore-db-orm/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227844511,"owners_count":17828167,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["firebase","firebase-db-orm","firestore","firestore-orm"],"created_at":"2024-12-03T03:21:43.461Z","updated_at":"2026-02-04T10:16:02.275Z","avatar_url":"https://github.com/CarmeloCampos.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Firestore DB ORM\n\n`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.\n\n## Table of Contents\n\n- [Features](#features)\n- [Installation](#installation)\n- [Instantiate the ORM](#instantiate-the-orm)\n- [CRUD Operations](#crud-operations)\n  - [`add(data: T): Promise\u003cT\u003e`](#adddata-t-promiset)\n  - [`get(id: string): Promise\u003cT | undefined\u003e`](#getid-string-promiset--undefined)\n  - [`update(id: string, data: Partial\u003cT\u003e): Promise\u003cvoid\u003e`](#updateid-string-data-partialt-promisevoid)\n  - [`delete(id: string): Promise\u003cvoid\u003e`](#deleteid-string-promisevoid)\n  - [`findOne(searchParams: SearchParams): Promise\u003cT | undefined\u003e`](#findonesearchparams-searchparams-promiset--undefined)\n- [Finding Multiple Documents (`finds` Method)](#finding-multiple-documents-finds-method)\n  - [Examples of `finds` Method](#examples-of-finds-method)\n- [Advanced Usage (Future Enhancements)](#advanced-usage-future-enhancements)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Features\n\n*   **Type-Safe:** Leverages TypeScript for strong typing of your data models.\n*   **Simple API:** Easy-to-understand methods for CRUD operations.\n*   **Flexible Querying:** Supports various query conditions for finding documents.\n*   **Automatic ID Generation:** Automatically handles `id` generation for new documents (using `uuid`).\n*   **Promise-based:** Asynchronous operations using Promises for modern JavaScript.\n\n## Installation\n\nInstall `firestore-db-orm` using your preferred package manager:\n\n**bun**\n```bash\nbun add firestore-db-orm\n```\n\n**npm**\n```bash\nnpm install firestore-db-orm\n```\n\n**yarn**\n```bash\nyarn add firestore-db-orm\n```\n\n## Instantiate the ORM\n\n```typescript\nimport { initializeApp, cert } from 'firebase-admin/app';\nimport { getFirestore } from 'firebase-admin/firestore';\nimport { FirestoreORM } from \"firestore-db-orm\";\nimport type { IUser } from \"./user.interface\"; // Your data model interface\n\n// Initialize Firebase Admin SDK\n// Ensure you have your service account key JSON file\n// (e.g., serviceAccountKey.json) in your project.\n// Replace with your actual service account key path and project details.\nconst serviceAccount = require('./path/to/your/serviceAccountKey.json');\n\ninitializeApp({\n  credential: cert(serviceAccount),\n  // databaseURL: 'https://\u003cYOUR_PROJECT_ID\u003e.firebaseio.com' // Optional: if not using default\n});\n\n// Get Firestore instance\nconst db = getFirestore();\n\n// Instantiate the ORM\n// Parameters:\n// 1. db: The Firestore instance.\n// 2. modelCollection: The name of the Firestore collection (e.g., \"users\").\nconst userORM = new FirestoreORM\u003cIUser\u003e(db, \"users\");\n\nexport default userORM;\n```\n\n**Explanation:**\n\n*   **`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.\n*   **`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.\n*   **`\"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.\n\n## CRUD Operations\n\nThe ORM provides methods for common Create, Read, Update, and Delete (CRUD) operations.\n\n### `add(data: T): Promise\u003cT\u003e`\n\nAdds a new document to the collection. The `id` field is automatically generated (using `uuid`) and added to the data before saving.\n\n```typescript\nimport userORM from \"./user.orm\"; // Assuming user.orm.ts is set up as shown above\nimport { v4 } from \"uuid\"; // Or use any ID generation strategy\n\n(async () =\u003e {\n  try {\n    const newUser = await userORM.add({\n      // id: v4(), // ID is auto-generated, but you can pre-define if needed for your model\n      email: \"test@example.com\",\n      password: \"securepassword123\",\n      // Add other fields as per your IUser interface\n    });\n    console.log(\"New user created:\", newUser);\n  } catch (error) {\n    console.error(\"Error adding user:\", error);\n  }\n})();\n```\n\n### `get(id: string): Promise\u003cT | undefined\u003e`\n\nRetrieves a document by its ID. Returns the document data if found, otherwise `undefined`.\n\n```typescript\nimport userORM from \"./user.orm\";\n\n(async () =\u003e {\n  try {\n    const userId = \"some-user-id\"; // Replace with an actual ID\n    const user = await userORM.get(userId);\n\n    if (user) {\n      console.log(\"User found:\", user);\n    } else {\n      console.log(\"User not found.\");\n    }\n  } catch (error) {\n    console.error(\"Error getting user:\", error);\n  }\n})();\n```\n\n### `update(id: string, data: Partial\u003cT\u003e): Promise\u003cvoid\u003e`\n\nUpdates an existing document with the provided data. `Partial\u003cT\u003e` means you can provide only the fields you want to change.\n\n```typescript\nimport userORM from \"./user.orm\";\n\n(async () =\u003e {\n  try {\n    const userIdToUpdate = \"some-user-id\"; // Replace with an actual ID\n    await userORM.update(userIdToUpdate, { email: \"updated.email@example.com\" });\n    console.log(\"User updated successfully.\");\n\n    // You can verify by getting the user\n    const updatedUser = await userORM.get(userIdToUpdate);\n    if (updatedUser) {\n      console.log(\"Updated user data:\", updatedUser);\n    }\n  } catch (error) {\n    console.error(\"Error updating user:\", error);\n  }\n})();\n```\n\n### `delete(id: string): Promise\u003cvoid\u003e`\n\nDeletes a document by its ID.\n\n```typescript\nimport userORM from \"./user.orm\";\n\n(async () =\u003e {\n  try {\n    const userIdToDelete = \"some-user-id\"; // Replace with an actual ID\n    await userORM.delete(userIdToDelete);\n    console.log(\"User deleted successfully.\");\n\n    // You can verify by trying to get the user\n    const deletedUser = await userORM.get(userIdToDelete);\n    if (!deletedUser) {\n      console.log(\"User confirmed deleted.\");\n    }\n  } catch (error) {\n    console.error(\"Error deleting user:\", error);\n  }\n})();\n```\n\n### `findOne(searchParams: SearchParams): Promise\u003cT | undefined\u003e`\n\nFinds a single document that matches the search criteria. Returns the first matching document or `undefined`.\nThe `searchParams` object allows you to specify field conditions.\n\n```typescript\nimport userORM from \"./user.orm\";\n\n(async () =\u003e {\n  try {\n    const user = await userORM.findOne({\n      email: { where: \"==\", value: \"test@example.com\" },\n    });\n\n    if (user) {\n      console.log(\"User found by email:\", user);\n    } else {\n      console.log(\"User with that email not found.\");\n    }\n  } catch (error) {\n    console.error(\"Error finding one user:\", error);\n  }\n})();\n```\n\n## Finding Multiple Documents (`finds` Method)\n\nThe `finds(searchParams: SearchParams = {}): Promise\u003cT[]\u003e` method allows you to retrieve multiple documents based on complex query conditions.\n\n**`SearchParams` Type:**\n\nThe `searchParams` object is a key-value map where:\n*   **Key**: The field name in your document (e.g., `age`, `name`).\n*   **Value**: Can be one of the following:\n    *   A direct value (e.g., `25`, `\"Juan\"`): This implies an \"equals\" (`==`) condition.\n    *   A `SearchParam` object: `{ value: any; where: WhereFilterOp }` for specifying conditions like greater than (`\u003e`), less than (`\u003c`), etc. `WhereFilterOp` is a string type from Firebase (`\u003c`, `\u003c=`, `==`, `!=`, `\u003e=`, `\u003e`, `array-contains`, `in`, `not-in`, `array-contains-any`).\n    *   An array of `SearchParam` objects: For applying multiple conditions to the same field (e.g., age \u003e 10 AND age \u003c 30).\n\n### Example 1: Simple Search\n\nFind documents where `age` is equal to 25.\n\n```typescript\nconst searchParams1: SearchParams = {\n  age: 25,\n};\n\nconst result1 = await userORM.finds(searchParams1);\nconsole.log(result1);\n```\n\n### Example 2: Search with Simple Condition\n\nFind documents where `age` is greater than 18.\n\n```typescript\nconst searchParams2: SearchParams = {\n  age: {\n    value: 18,\n    where: \"\u003e\",\n  },\n};\n\nconst result2 = await userORM.finds(searchParams2);\nconsole.log(result2);\n```\n\n### Example 3: Search with Multiple Conditions for the Same Field\n\nFind documents where `age` is greater than 10 and less than 30.\n\n```typescript\nconst searchParams3: SearchParams = {\n  age: [\n    {\n      value: 10,\n      where: \"\u003e\",\n    },\n    {\n      value: 30,\n      where: \"\u003c\",\n    },\n  ],\n};\n\nconst result3 = await userORM.finds(searchParams3);\nconsole.log(result3);\n```\n\n### Example 4: Search with Multiple Fields and Conditions\n\nFind documents where `age` is greater than 18 and `name` is equal to \"Juan\".\n\n```typescript\nconst searchParams4: SearchParams = {\n  age: {\n    value: 18,\n    where: \"\u003e\",\n  },\n  name: \"Juan\",\n};\n\nconst result4 = await userORM.finds(searchParams4);\nconsole.log(result4);\n```\n\n### Example 5: Search with Multiple Fields and Multiple Conditions\n\nFind documents where `age` is within certain ranges and `name` is equal to \"Ana\".\n\n```typescript\nconst searchParams5: SearchParams = {\n  age: [\n    {\n      value: 10,\n      where: \"\u003e\",\n    },\n    {\n      value: 30,\n      where: \"\u003c\",\n    },\n  ],\n  name: \"Ana\",\n};\n\nconst result5 = await userORM.finds(searchParams5);\nconsole.log(result5);\n```\n\n### Example 6: Complex Search with Several Fields and Conditions\n\nFind documents where `age` is greater than 10 and less than 30, `name` is \"Pedro\", and `active` is true.\n\n```typescript\nconst searchParams6: SearchParams = {\n  age: [\n    {\n      value: 10,\n      where: \"\u003e\",\n    },\n    {\n      value: 30,\n      where: \"\u003c\",\n    },\n  ],\n  name: \"Pedro\",\n  active: true,\n};\n\nconst result6 = await userORM.finds(searchParams6);\nconsole.log(result6);\n```\n\n## Advanced Usage (Future Enhancements)\n\nCurrently, the ORM focuses on providing straightforward CRUD operations. Future enhancements could include:\n\n*   **Transactions:** Support for Firestore transactions to perform multiple operations atomically.\n*   **Batch Writes:** Enabling batch operations (e.g., multiple `set`, `update`, or `delete` calls in a single request) for efficiency.\n*   **Custom Data Transformers:** Hooks or methods to transform data when reading from or writing to Firestore (e.g., for date conversions, encryption/decryption).\n*   **Real-time Listeners:** Integration with Firestore's real-time data synchronization capabilities.\n\nIf you have specific needs or ideas for advanced features, please feel free to open an issue or contribute to the project!\n\n## Contributing\n\nContributions are welcome! If you'd like to contribute, please follow these steps:\n\n1.  **Fork the repository.**\n2.  **Create a new branch:** `git checkout -b my-feature-branch`\n3.  **Make your changes.**\n4.  **Commit your changes:** `git commit -m 'Add some feature'`\n5.  **Push to the branch:** `git push origin my-feature-branch`\n6.  **Open a pull request.**\n\nPlease make sure to update tests as appropriate and follow the existing code style.\n\n## License\n\nThis project is licensed under the MPL-2.0 License. See the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarmelocampos%2Ffirestore-db-orm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcarmelocampos%2Ffirestore-db-orm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarmelocampos%2Ffirestore-db-orm/lists"}