{"id":31130273,"url":"https://github.com/mwelwankuta/fairydm","last_synced_at":"2025-09-18T02:17:59.651Z","repository":{"id":298942522,"uuid":"1001406141","full_name":"mwelwankuta/fairydm","owner":"mwelwankuta","description":"A TypeScript ODM for Firebase Firestore built with Node.js","archived":false,"fork":false,"pushed_at":"2025-06-14T09:52:16.000Z","size":163,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-17T06:28:06.554Z","etag":null,"topics":["firebase","firestore","odm","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/fairydm","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mwelwankuta.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null}},"created_at":"2025-06-13T10:21:46.000Z","updated_at":"2025-07-26T02:47:29.000Z","dependencies_parsed_at":"2025-06-13T18:49:03.936Z","dependency_job_id":"2a3bab35-fb49-4904-8c7f-2e68d1c92640","html_url":"https://github.com/mwelwankuta/fairydm","commit_stats":null,"previous_names":["mwelwankuta/fairydm"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mwelwankuta/fairydm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwelwankuta%2Ffairydm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwelwankuta%2Ffairydm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwelwankuta%2Ffairydm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwelwankuta%2Ffairydm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mwelwankuta","download_url":"https://codeload.github.com/mwelwankuta/fairydm/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwelwankuta%2Ffairydm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275696239,"owners_count":25511354,"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","status":"online","status_checked_at":"2025-09-18T02:00:09.552Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","firestore","odm","typescript"],"created_at":"2025-09-18T02:17:57.163Z","updated_at":"2025-09-18T02:17:59.639Z","avatar_url":"https://github.com/mwelwankuta.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fairydm\n\nA simple, Mongoose-like ODM (Object Document Mapper) for Google Firestore, designed to bring structure and type safety to your Firestore data models in TypeScript projects.\n\n[![npm version](https://badge.fury.io/js/fairydm.svg)](https://badge.fury.io/js/fairydm)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n`fairydm` provides a familiar, Mongoose-inspired API for defining schemas, creating models, and performing CRUD operations, all while leveraging the power of TypeScript for a better developer experience.\n\n## Core Features\n\n- **Schema Definition**: Structure your data with clear and simple schema definitions.\n- **Type-Safe Models**: Full TypeScript support with inferred types from your model interfaces.\n- **Mongoose-like API**: A familiar and intuitive API for developers coming from a Mongoose background.\n- **Promise-based**: All asynchronous operations return Promises for easy integration with modern async/await syntax.\n- **Secure Connection**: Connect to your live Firestore database using service account credentials.\n\n## Installation\n\n```bash\nnpm install fairydm firebase-admin\n```\n\n## Quick Start\n\nHere's a quick guide to get you started with `fairydm`.\n\n### 1. Connect to Firestore\n\nTo connect to your Firestore database, you will need a service account key from your Google Cloud/Firebase project.\n\n**Generating a Service Account Key:**\n\n1.  Go to your project settings in the [Firebase Console](https://console.firebase.google.com/).\n2.  Navigate to the **Service accounts** tab.\n3.  Click on **Generate new private key**. A JSON file containing your service account credentials will be downloaded.\n4.  Save this file securely in your project (e.g., in a `config` directory) and **ensure it is added to your `.gitignore`** to prevent it from being committed to version control.\n\nNow, use the service account key to connect `fairydm` to your Firestore instance.\n\n```typescript\nimport { connect, disconnect } from 'fairydm'\nimport admin from 'firebase-admin'\nimport serviceAccount from './config/serviceAccountKey.json' // Adjust path as needed\n\nasync function initialize() {\n  await connect({\n    credential: serviceAccount,\n    projectId: 'testing-fairydm',\n  })\n  console.log('Connected to Firestore!')\n\n  // Your application logic here...\n\n  // Disconnect when done\n  await disconnect()\n}\n\ninitialize()\n```\n\n### 2. Define a Schema and Model\n\nDefine an interface for your data and then create a `Schema` and a `Model`.\n\n```typescript\nimport { model, Schema } from 'fairydm'\n\n// Define a TypeScript interface for your document\ninterface IUser {\n  name: string\n  email: string\n  age?: number\n  role: 'admin' | 'user'\n}\n\n// Create a schema that corresponds to the interface\nconst userSchema = new Schema({\n  name: { type: String, required: true },\n  email: { type: String, required: true },\n  age: { type: Number },\n  role: { type: String, default: 'user' },\n})\n\n// Create the model\nconst User = model\u003cIUser\u003e('User', userSchema)\n```\n\nThe `model\u003cT\u003e()` function is generic, and the type `T` you pass to it will be used to provide type safety and autocompletion for all model methods.\n\n### 3. Create Documents\n\nYou can create new documents using the `.create()` static method or by instantiating the model and calling `.save()`.\n\n```typescript\n// Using .create()\nconst user1 = await User.create({\n  name: 'Alice',\n  email: 'alice@example.com',\n  age: 30,\n})\nconsole.log('Created user:', user1.data)\n\n// Using new and .save()\nconst user2 = new User({\n  name: 'Bob',\n  email: 'bob@example.com',\n})\nawait user2.save() // Bob's role will default to 'user'\nconsole.log('Saved user:', user2.data)\n```\n\n### 4. Find Documents\n\n`fairydm` provides `find` and `findOne` methods with type-safe query objects.\n\n```typescript\n// Find a single document\nconst alice = await User.findOne({ email: 'alice@example.com' })\nif (alice) {\n  console.log('Found Alice:', alice.data.name)\n}\n\n// Find multiple documents\nconst allUsers = await User.find({ role: 'user' })\nconsole.log(`Found ${allUsers.length} users.`)\n```\n\n### 5. Update Documents\n\nUpdate documents using `updateOne` or `updateMany`. You can also update a document instance directly and then call `.save()`.\n\n```typescript\n// Update a single document's age\nawait User.updateOne({ email: 'alice@example.com' }, { $set: { age: 31 } })\n\n// Update an instance and save\nif (alice) {\n  alice.data.role = 'admin'\n  await alice.save()\n  console.log('Promoted Alice to admin.')\n}\n```\n\n### 6. Delete Documents\n\nDelete documents using `deleteMany` or `findByIdAndDelete`.\n\n```typescript\n// Delete Bob by his email\nawait User.deleteMany({ email: 'bob@example.com' })\n\n// Delete Alice by her ID\nif (alice \u0026\u0026 alice.id) {\n  await User.findByIdAndDelete(alice.id)\n}\n```\n\n## Standalone Example Application\n\nThis repository includes a standalone example of a social media API located in the `/example` directory. It demonstrates how to structure a more complex application with multiple models, routes, and authentication.\n\nTo run the example:\n\n1.  Navigate to the example directory: `cd example`\n2.  Create a `serviceAccountKey.json` file inside `example/src/config/`. Follow the instructions in the \"Connect to Firestore\" section to generate your key.\n3.  Install the dependencies: `npm install`\n4.  Start the application: `npm start`\n\n## API Reference\n\n### Model Static Methods\n\n- `model\u003cT\u003e(name, schema)`: Creates a new model.\n- `connect(options)`: Connects to Firestore.\n- `disconnect()`: Disconnects from Firestore.\n- `create(data)`: Creates and saves a new document.\n- `find(query)`: Finds multiple documents matching the query.\n- `findOne(query)`: Finds a single document matching the query.\n- `updateOne(filter, update)`: Updates a single document.\n- `updateMany(filter, update)`: Updates multiple documents.\n- `deleteMany(query)`: Deletes documents matching the query.\n- `findByIdAndDelete(id)`: Deletes a single document by its ID.\n\n### Model Instance Methods\n\n- `save()`: Saves or updates the document instance.\n\n## Future Work \u0026 Todos\n\n`fairydm` is an evolving project. Here are some of the features and improvements planned for the future:\n\n- **Migration System**: Integration with a migration tool or a built-in system to manage schema changes over time.\n- **Advanced Query Operators**: Support for more complex Firestore queries, such as `array-contains`, `in`, and `array-contains-any`.\n- **Enhanced Schema Validation**: More built-in validation rules for schema fields.\n- **Transaction Support**: Helpers for running complex operations within a Firestore transaction.\n\n## License\n\nThis project is licensed under the MIT License.\n\n## Firebase Emulator Suite Setup\n\nThe Firebase Emulator Suite allows you to run a local version of Firebase services, which is ideal for development and testing without incurring costs or affecting production data.\n\n### 1. Installation\n\nIf you haven't already, install the Firebase CLI globally:\n\n```bash\nnpm install -g firebase-tools\n```\n\n### 2. Initialization\n\nFrom your project root, initialize the emulators you want to use (e.g., Firestore, Auth):\n\n```bash\nfirebase init emulators\n```\n\nThe CLI will guide you through the setup process, asking which emulators you want to install and on which ports they should run. This will create a `firebase.json` file in your project.\n\n### 3. Starting the Emulators\n\nTo start the emulators, run the following command from your project root:\n\n```bash\n# Start only the Firestore\nfirebase emulators:start --only firestore\n```\n\n### 4. Running Tests\n\nThe emulators are great for running automated tests. You can use the `emulators:exec` command to run a test script against the emulators. The emulators will start, run your script, and then shut down automatically.\n\n```bash\nfirebase emulators:exec \"npm test\"\n```\n\nWhen using `fairydm` with the Firestore emulator, you don't need to provide service account credentials. `fairydm` will automatically detect that you're connecting to an emulator if you set the `FIRESTORE_EMULATOR_HOST` environment variable, which the `emulators:start` and `emulators:exec` commands do for you.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmwelwankuta%2Ffairydm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmwelwankuta%2Ffairydm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmwelwankuta%2Ffairydm/lists"}