{"id":28066789,"url":"https://github.com/leoafarias/burnkit","last_synced_at":"2026-04-24T16:04:38.494Z","repository":{"id":282634260,"uuid":"949123886","full_name":"leoafarias/burnkit","owner":"leoafarias","description":"A decorator-based TypeScript ORM for Firebase, providing type-safe data management for Firestore and Realtime Database.","archived":false,"fork":false,"pushed_at":"2025-05-01T15:18:42.000Z","size":572,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-12T16:02:53.808Z","etag":null,"topics":["firebase","firestore","orm","realtime-database","rtdb"],"latest_commit_sha":null,"homepage":"","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/leoafarias.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-03-15T18:22:34.000Z","updated_at":"2025-03-16T18:06:10.000Z","dependencies_parsed_at":"2025-05-01T16:25:52.033Z","dependency_job_id":"865ecb50-d23e-4851-a0b7-f96af3b1b90f","html_url":"https://github.com/leoafarias/burnkit","commit_stats":null,"previous_names":["leoafarias/firekit","leoafarias/burnkit"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/leoafarias/burnkit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leoafarias%2Fburnkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leoafarias%2Fburnkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leoafarias%2Fburnkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leoafarias%2Fburnkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leoafarias","download_url":"https://codeload.github.com/leoafarias/burnkit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leoafarias%2Fburnkit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32230422,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-24T13:21:15.438Z","status":"ssl_error","status_checked_at":"2026-04-24T13:21:15.005Z","response_time":64,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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","orm","realtime-database","rtdb"],"created_at":"2025-05-12T15:54:47.937Z","updated_at":"2026-04-24T16:04:38.476Z","avatar_url":"https://github.com/leoafarias.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BurnKit\n\n[![npm version](https://badge.fury.io/js/burnkit.svg)](https://badge.fury.io/js/burnkit)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nBurnKit is a powerful, decorator-based TypeScript SDK for Firebase that provides a clean, type-safe API for working with both Firestore and the Realtime Database. Designed with a forward-thinking approach, BurnKit simplifies data modeling, validation, and querying while embracing modern best practices.\n\n## Features\n\n- **TypeScript Decorators** for intuitive entity and field mapping\n- **Type-Safe Queries** with a robust, chainable query builder\n- **Automatic Data Validation \u0026 Transformation** using class-transformer-validator\n- **Repository Pattern** for clean, maintainable data access\n- **Batch Operations** for efficient bulk updates\n- **Enhanced Subcollection Support** with dedicated decorators and metadata utilities\n- **Nested Entity Support** for managing complex relationships\n- **Realtime Database Integration** with comprehensive CRUD and query capabilities\n\n## Installation\n\n```bash\nnpm install burnkit firebase-admin reflect-metadata\n# or\nyarn add burnkit firebase-admin reflect-metadata\n```\n\nNote: BurnKit requires reflect-metadata for decorators to function properly. Ensure it is imported once in your application's entry point.\n\n## Quick Start\n\n### Initialize Firebase\n\n```typescript\nimport * as admin from \"firebase-admin\";\nimport \"reflect-metadata\"; // Ensure this is imported once\n\nadmin.initializeApp({\n  credential: admin.credential.cert(require(\"./serviceAccountKey.json\")),\n});\n```\n\n### Define Entity Models\n\nBurnKit leverages decorators to define your Firestore and Realtime Database entities effortlessly. For example:\n\n```typescript\nimport {\n  Collection,\n  Field,\n  ID,\n  CreatedAt,\n  UpdatedAt,\n  Subcollection,\n} from \"burnkit\";\n\n@Collection(\"users\")\nclass User {\n  @ID()\n  id: string;\n\n  @Field()\n  name: string;\n\n  @Field({ index: true })\n  email: string;\n\n  @Field()\n  age: number;\n\n  @Field({\n    transformer: {\n      toFirestore: (roles: string[]) =\u003e roles.join(\",\"),\n      fromFirestore: (value: string) =\u003e (value ? value.split(\",\") : []),\n    },\n  })\n  roles: string[];\n\n  @CreatedAt()\n  createdAt: Date;\n\n  @UpdatedAt()\n  updatedAt: Date;\n\n  // Optional nested entity\n  profile?: UserProfile;\n}\n\n@Collection(\"posts\")\nclass Post {\n  @ID()\n  id: string;\n\n  @Field()\n  title: string;\n\n  @Field()\n  content: string;\n\n  @Field()\n  authorId: string;\n\n  @CreatedAt()\n  createdAt: Date;\n\n  @UpdatedAt()\n  updatedAt: Date;\n\n  // Non-persisted field to hold comments\n  comments?: Comment[];\n}\n\n// Define a subcollection for comments using the new Subcollection decorator\n@Subcollection(Post)\nclass Comment {\n  @ID()\n  id: string;\n\n  @Field()\n  content: string;\n\n  @Field()\n  authorId: string;\n\n  @CreatedAt()\n  createdAt: Date;\n\n  @UpdatedAt()\n  updatedAt: Date;\n}\n\n// Customize the subcollection name if desired\n@Subcollection(Post, \"post-comments\")\nclass CustomComment {\n  // Define fields as needed\n}\n```\n\n### Use the Repository\n\nBurnKit's repository pattern simplifies CRUD operations and query building:\n\n```typescript\nimport { BurnKit } from \"burnkit\";\n\n// Obtain a repository for the User entity\nconst userRepo = BurnKit.getRepository(User);\n\n// Create a new user\nasync function createUser() {\n  const newUser = await userRepo.create({\n    name: \"John Doe\",\n    email: \"john@example.com\",\n    age: 30,\n    roles: [\"user\"],\n  });\n  console.log(`Created user with ID: ${newUser.id}`);\n  return newUser;\n}\n\n// Retrieve a user by ID\nasync function findUser(id: string) {\n  const user = await userRepo.findById(id);\n  if (user) {\n    console.log(`Found user: ${user.name}`);\n  }\n  return user;\n}\n\n// Query users with type-safe queries\nasync function findActiveUsers() {\n  const users = await userRepo\n    .query()\n    .where(\"age\", \"\u003e\", 18)\n    .where(\"roles\", \"array-contains\", \"active\")\n    .orderBy(\"name\")\n    .limit(10)\n    .get();\n\n  console.log(`Found ${users.length} active users`);\n  return users;\n}\n\n// Update a user's details\nasync function updateUser(id: string) {\n  await userRepo.update(id, {\n    name: \"John Smith\",\n    age: 31,\n  });\n  console.log(\"User updated\");\n}\n\n// Delete a user\nasync function deleteUser(id: string) {\n  await userRepo.delete(id);\n  console.log(\"User deleted\");\n}\n```\n\n### Working with Subcollections\n\nBurnKit streamlines working with subcollections using dedicated decorators and helper functions. In addition to using the subcollection decorator, you can generate Firestore paths using metadata utilities:\n\n```typescript\nimport { BurnKit } from \"burnkit\";\n\n// Get the repository for posts\nconst postRepo = BurnKit.getRepository(Post);\n\n// Create a post\nconst post = await postRepo.create({\n  title: \"Getting Started with BurnKit\",\n  content: \"BurnKit is an innovative TypeScript SDK for Firebase...\",\n  authorId: \"user123\",\n});\n\n// Retrieve a repository for the comments subcollection of a specific post\nconst commentsRepo = BurnKit.getSubcollectionRepository(Comment, post.id);\n\n// Add a comment to the post\nconst comment = await commentsRepo.create({\n  content: \"Great article!\",\n  authorId: \"user456\",\n});\n\n// Retrieve all comments for the post\nconst comments = await commentsRepo.findAll();\n```\n\nFor cases where you need to generate a subcollection path manually, use:\n\n```typescript\nimport { buildSubcollectionPath } from \"burnkit\";\n\nconst path = buildSubcollectionPath(Comment, \"postId123\");\nconsole.log(\"Subcollection path:\", path);\n```\n\n### Working with Nested Entities\n\nBurnKit also supports managing nested entities, making it easy to model and interact with related data:\n\n```typescript\nimport { NestedEntityRepository, BurnKit } from \"burnkit\";\n\nconst userProfileRepo = new NestedEntityRepository(\n  User, // Parent entity class\n  UserProfile, // Child entity class\n  \"profile\", // Field name in User to store the profile\n  (userId) =\u003e `users/${userId}/profile` // Path builder for the nested collection\n);\n\nasync function createUserWithProfile() {\n  const userData = {\n    name: \"Jane Doe\",\n    email: \"jane@example.com\",\n    age: 28,\n    roles: [\"user\"],\n  };\n\n  const profileData = {\n    bio: \"Software engineer and avid hiker\",\n    avatarUrl: \"https://example.com/avatar.jpg\",\n    phoneNumber: \"+1234567890\",\n  };\n\n  const user = await userProfileRepo.createWithNested(userData, profileData);\n  console.log(`Created user with profile: ${user.id}`);\n  return user;\n}\n\nasync function loadUserWithProfile(userId: string) {\n  const user = await userProfileRepo.loadWithNested(userId);\n  if (user \u0026\u0026 user.profile) {\n    console.log(`User: ${user.name}`);\n    console.log(`Profile Bio: ${user.profile.bio}`);\n  }\n  return user;\n}\n```\n\n### Using the Realtime Database\n\nBurnKit's Realtime Database integration provides comprehensive CRUD operations and advanced query capabilities:\n\n```typescript\nimport { RealtimeRepository } from \"burnkit\";\n\ninterface ChatMessage {\n  message: string;\n  sender: string;\n  timestamp: number;\n  isRead?: boolean;\n}\n\nconst chatRepo = new RealtimeRepository\u003cChatMessage\u003e(\"chats\");\n\n// Add a new chat message\nasync function sendMessage(sender: string, message: string) {\n  const newMessage = await chatRepo.push({\n    message,\n    sender,\n    timestamp: Date.now(),\n  });\n  console.log(`Message sent with ID: ${newMessage.id}`);\n  return newMessage;\n}\n\n// Listen for real-time updates\nfunction listenForMessages(callback: (messages: ChatMessage[]) =\u003e void) {\n  const unsubscribe = chatRepo\n    .query()\n    .orderByChild(\"timestamp\")\n    .onValue(callback);\n  return unsubscribe;\n}\n```\n\n## API Documentation\n\n### Decorators\n\n#### @Collection(name: string)\n\nMarks a class as a Firestore collection.\n\n```typescript\n@Collection(\"users\")\nclass User {}\n```\n\n#### @Subcollection(parentEntity, collectionName?)\n\nMarks a class as a Firestore subcollection. The subcollection name defaults to the lowercase class name if not specified.\n\n```typescript\n// Basic usage\n@Subcollection(Post)\nclass Comment {}\n\n// With custom collection name\n@Subcollection(Post, \"post-comments\")\nclass CustomComment {}\n```\n\n#### @Field(options?: FieldOptions)\n\nMarks a property as a Firestore document field.\n\n```typescript\n@Field({ index: true })\nemail: string;\n```\n\nOptions include:\n\n- name?: string — Custom field name in Firestore\n- index?: boolean — Enable indexing for this field\n- transformer?: { toFirestore?, fromFirestore? } — Custom transformers\n\n#### @ID()\n\nMarks a property as the document ID.\n\n```typescript\n@ID()\nid: string;\n```\n\n#### @CreatedAt()\n\nAutomatically sets the creation timestamp.\n\n```typescript\n@CreatedAt()\ncreatedAt: Date;\n```\n\n#### @UpdatedAt()\n\nAutomatically updates the timestamp on modifications.\n\n```typescript\n@UpdatedAt()\nupdatedAt: Date;\n```\n\n### Utility Functions\n\n#### getSubcollectionMetadata(target: any): SubcollectionMetadata | undefined\n\nRetrieves metadata for a subcollection from a class.\n\n#### buildSubcollectionPath(childEntity: any, parentId: string): string\n\nGenerates a Firestore path to a subcollection for a given parent document.\n\n```typescript\nimport { buildSubcollectionPath } from \"burnkit\";\nconst path = buildSubcollectionPath(Comment, \"parentDocId\");\n```\n\n### BurnKit Functions\n\n#### BurnKit.getRepository\u003cT\u003e(entityClass: new () =\u003e T): EntityRepository\u003cT\u003e\n\nRetrieves a repository for a specified entity.\n\n```typescript\nconst userRepo = BurnKit.getRepository(User);\n```\n\n#### BurnKit.getSubcollectionRepository\u003cT\u003e(entityClass: new () =\u003e T, parentId: string): EntityRepository\u003cT\u003e\n\nRetrieves a repository for a subcollection belonging to a specific parent document.\n\n```typescript\nconst commentsRepo = BurnKit.getSubcollectionRepository(Comment, postId);\n```\n\n#### BurnKit.clearCache(): void\n\nClears the internal repository cache.\n\n```typescript\nBurnKit.clearCache();\n```\n\n### EntityRepository Methods\n\n- create(data: Partial\u003cT\u003e, id?: string): Promise\u003cT\u003e — Create a new entity.\n- findById(id: string): Promise\u003cT | null\u003e — Retrieve an entity by ID.\n- getById(id: string): Promise\u003cT\u003e — Retrieve an entity by ID (throws if not found).\n- update(id: string, data: Partial\u003cT\u003e): Promise\u003cvoid\u003e — Update an entity.\n- delete(id: string): Promise\u003cvoid\u003e — Delete an entity.\n- findAll(): Promise\u003cT[]\u003e — Retrieve all entities in a collection.\n- query(): QueryBuilder\u003cT\u003e — Create a query builder for advanced queries.\n- batch(operations: (batch: FirestoreBatchHelper\u003cT\u003e) =\u003e void): Promise\u003cvoid\u003e — Execute batch operations.\n\n### QueryBuilder Methods\n\n- where(field: string, operator: FirestoreOperator, value: any): QueryBuilder\u003cT\u003e — Add filtering criteria.\n- orderBy(field: string, direction?: \"asc\" | \"desc\"): QueryBuilder\u003cT\u003e — Sort query results.\n- limit(limit: number): QueryBuilder\u003cT\u003e — Limit the number of documents.\n- offset(offset: number): QueryBuilder\u003cT\u003e — Skip a number of documents.\n- get(): Promise\u003cT[]\u003e — Execute the query.\n- getFirst(): Promise\u003cT | null\u003e — Retrieve the first matching document.\n- count(): Promise\u003cnumber\u003e — Count matching documents.\n\n### RealtimeRepository Methods\n\n- push(data: Partial\u003cT\u003e): Promise\u003cT \u0026 { id: string }\u003e — Create a new entry with an auto-generated ID.\n- set(id: string, data: Partial\u003cT\u003e): Promise\u003cvoid\u003e — Create or update an entry.\n- update(id: string, data: Partial\u003cT\u003e): Promise\u003cvoid\u003e — Update an existing entry.\n- get(id: string): Promise\u003c(T \u0026 { id: string }) | null\u003e — Retrieve an entry by ID.\n- getAll(): Promise\u003c(T \u0026 { id: string })[]\u003e — Retrieve all entries.\n- remove(id: string): Promise\u003cvoid\u003e — Delete an entry.\n- query(): RealtimeQueryBuilder\u003cT\u003e — Create a query builder for the Realtime Database.\n\n### RealtimeQueryBuilder Methods\n\n- orderByChild(child: string): RealtimeQueryBuilder\u003cT\u003e — Order results by a specific child key.\n- equalTo(child: string, value: string | number | boolean | null): RealtimeQueryBuilder\u003cT\u003e — Filter results by equality.\n- between(child: string, startValue: any, endValue: any): RealtimeQueryBuilder\u003cT\u003e — Filter results within a range.\n- limitToFirst(limit: number): RealtimeQueryBuilder\u003cT\u003e — Limit to the first N results.\n- limitToLast(limit: number): RealtimeQueryBuilder\u003cT\u003e — Limit to the last N results.\n- startAt(value: any): RealtimeQueryBuilder\u003cT\u003e — Start results at a specific value.\n- endAt(value: any): RealtimeQueryBuilder\u003cT\u003e — End results at a specific value.\n- get(): Promise\u003c(T \u0026 { id: string })[]\u003e — Execute the query.\n- onValue(callback: (data: (T \u0026 { id: string })[]) =\u003e void): () =\u003e void — Listen for real-time updates.\n\n## Firebase Setup\n\n1. Create a Firebase Project: Visit the Firebase Console.\n2. Generate a Service Account Key:\n   - Navigate to Project Settings \u003e Service Accounts.\n   - Click \"Generate New Private Key\" and download the JSON file.\n3. Configure Firebase:\n\n```bash\nnpm run setup-firebase\n```\n\n4. Test Firebase Connection:\n\n```bash\nnpm run test-firebase\n```\n\n5. Run Example Files:\n\n```bash\nts-node examples/main-collection-example.ts\n```\n\nSecurity Note: The serviceAccountKey.json file contains sensitive information and should not be committed to version control. It is excluded via .gitignore.\n\n## CI/CD Pipeline\n\nBurnKit utilizes GitHub Actions for continuous integration and deployment.\n\n### Automated Workflow\n\n1. Testing \u0026 Linting: On each push or pull request to the main branch:\n   - Unit tests and Firebase connectivity tests are run.\n   - Code linting and TypeScript checks are executed.\n2. Deployment: When a new version tag (e.g., v1.0.0) is pushed:\n   - All tests and linting are performed.\n   - If successful, the package is published to npm.\n\n### Setting Up Secrets\n\nConfigure the following GitHub secrets:\n\n- FIREBASE_SERVICE_ACCOUNT_KEY: Base64 encoded Firebase service account key JSON.\n- NPM_TOKEN: Your npm access token.\n\n### Manual Release Process\n\n1. Update the version in package.json.\n2. Commit changes: git commit -am \"Release v1.0.0\".\n3. Tag the release: git tag v1.0.0.\n4. Push commits and tags: git push \u0026\u0026 git push --tags.\n5. GitHub Actions will automatically publish the package to npm.\n\n---\n\nThis section is automatically maintained by BurnKit documentation.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleoafarias%2Fburnkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleoafarias%2Fburnkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleoafarias%2Fburnkit/lists"}