{"id":50758812,"url":"https://github.com/phamngocduy98/npm-flashstore-admin","last_synced_at":"2026-06-11T08:00:54.127Z","repository":{"id":38764898,"uuid":"284965276","full_name":"phamngocduy98/npm-flashstore-admin","owner":"phamngocduy98","description":"Firebase Cloud Firestore Library | For NodeJS server with FirebaseAdminSdk","archived":false,"fork":false,"pushed_at":"2023-01-07T04:57:29.000Z","size":304,"stargazers_count":2,"open_issues_count":7,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-14T13:23:32.275Z","etag":null,"topics":["firebase","firebase-admin","firebase-admin-sdk","firebase-database","firebase-firestore","firebase-nodejs","nodejs","nodejs-framework"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phamngocduy98.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}},"created_at":"2020-08-04T11:57:11.000Z","updated_at":"2021-03-06T09:34:26.000Z","dependencies_parsed_at":"2023-02-06T12:30:40.924Z","dependency_job_id":null,"html_url":"https://github.com/phamngocduy98/npm-flashstore-admin","commit_stats":null,"previous_names":["phamngocduy98/node_flashstore_library"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/phamngocduy98/npm-flashstore-admin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phamngocduy98%2Fnpm-flashstore-admin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phamngocduy98%2Fnpm-flashstore-admin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phamngocduy98%2Fnpm-flashstore-admin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phamngocduy98%2Fnpm-flashstore-admin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phamngocduy98","download_url":"https://codeload.github.com/phamngocduy98/npm-flashstore-admin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phamngocduy98%2Fnpm-flashstore-admin/sbom","scorecard":{"id":730489,"data":{"date":"2025-08-11","repo":{"name":"github.com/phamngocduy98/npm-flashstore-admin","commit":"c61ebf38591e12008fa8204bc34eafa72e71c0e2"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.2,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/22 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/cd_buid_publish.yml:1","Warn: no topLevel permission defined: .github/workflows/ci_merge_master.yml:1","Warn: no topLevel permission defined: .github/workflows/ci_pull_request.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/cd_buid_publish.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/phamngocduy98/npm-flashstore-admin/cd_buid_publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/cd_buid_publish.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/phamngocduy98/npm-flashstore-admin/cd_buid_publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_merge_master.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/phamngocduy98/npm-flashstore-admin/ci_merge_master.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_merge_master.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/phamngocduy98/npm-flashstore-admin/ci_merge_master.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_pull_request.yml:8: update your workflow using https://app.stepsecurity.io/secureworkflow/phamngocduy98/npm-flashstore-admin/ci_pull_request.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_pull_request.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/phamngocduy98/npm-flashstore-admin/ci_pull_request.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_pull_request.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/phamngocduy98/npm-flashstore-admin/ci_pull_request.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_pull_request.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/phamngocduy98/npm-flashstore-admin/ci_pull_request.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_pull_request.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/phamngocduy98/npm-flashstore-admin/ci_pull_request.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_pull_request.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/phamngocduy98/npm-flashstore-admin/ci_pull_request.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_pull_request.yml:68: update your workflow using https://app.stepsecurity.io/secureworkflow/phamngocduy98/npm-flashstore-admin/ci_pull_request.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_pull_request.yml:73: update your workflow using https://app.stepsecurity.io/secureworkflow/phamngocduy98/npm-flashstore-admin/ci_pull_request.yml/master?enable=pin","Info:   0 out of  12 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 15 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"31 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-4g6q-77j7-vvjc","Warn: Project is vulnerable to: GHSA-7v5v-9h63-cj86","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-w8qv-6jwh-64r5","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-wm7h-9275-46v2","Warn: Project is vulnerable to: GHSA-4q6p-r6v2-jvc5","Warn: Project is vulnerable to: GHSA-ww39-953v-wcq6","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-8cf7-32gw-wr33","Warn: Project is vulnerable to: GHSA-hjrf-2m68-5959","Warn: Project is vulnerable to: GHSA-qwph-4952-7xr6","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-qrpm-p2h7-hrv2","Warn: Project is vulnerable to: GHSA-mwcw-c2x4-8c55","Warn: Project is vulnerable to: GHSA-r683-j2x4-v87g","Warn: Project is vulnerable to: GHSA-5rrq-pxf6-6jx5","Warn: Project is vulnerable to: GHSA-8fr3-hfg3-gpgp","Warn: Project is vulnerable to: GHSA-gf8q-jrpm-jvxq","Warn: Project is vulnerable to: GHSA-2r2c-g63r-vccr","Warn: Project is vulnerable to: GHSA-cfm4-qjh2-4765","Warn: Project is vulnerable to: GHSA-x4jg-mjrx-434g","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-g954-5hwp-pp24","Warn: Project is vulnerable to: GHSA-h755-8qp9-cq85","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T14:16:04.268Z","repository_id":38764898,"created_at":"2025-08-22T14:16:04.268Z","updated_at":"2025-08-22T14:16:04.268Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34188272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-11T02:00:06.485Z","response_time":57,"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","firebase-admin","firebase-admin-sdk","firebase-database","firebase-firestore","firebase-nodejs","nodejs","nodejs-framework"],"created_at":"2026-06-11T08:00:48.592Z","updated_at":"2026-06-11T08:00:54.117Z","avatar_url":"https://github.com/phamngocduy98.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Flashstore admin\n**WARNING: Flashstore is currently in early beta version which is under development, may cause unexpected behaviors and should only be used in personal project.**  \n  \n![npm](https://img.shields.io/npm/v/@phamngocduy98/flashstore-admin)\n![GitHub Workflow Status](https://img.shields.io/github/workflow/status/phamngocduy98/npm-flashstore-admin/Coverage%20check)\n[![codecov](https://codecov.io/gh/phamngocduy98/npm-flashstore-admin/branch/master/graph/badge.svg?token=IJ7YKI7PVJ)](https://codecov.io/gh/phamngocduy98/npm-flashstore-admin)\n![npm](https://img.shields.io/npm/dt/@phamngocduy98/flashstore)\n![npm](https://img.shields.io/npm/dt/@phamngocduy98/flashstore-admin)  \n![npm peer dependency version](https://img.shields.io/npm/dependency-version/@phamngocduy98/flashstore-admin/peer/firebase-admin)\n![npm peer dependency version (scoped)](https://img.shields.io/npm/dependency-version/@phamngocduy98/flashstore-admin/dev/typescript)\n![node-lts (scoped)](https://img.shields.io/node/v-lts/@phamngocduy98/flashstore-admin)\n\nA firebase firestore library that making it easier to CRUD data with typescript\n\n```\nnpm i @phamngocduy98/flashstore-admin\n```\n\n## How to use\n\n### 1. Define document data type\n\nDefine properties of your document by extending `DocumentData` class\n\n```typescript\nimport {DocumentData} from \"@phamngocduy98/flashstore-admin\";\n\nexport class User extends DocumentData {\n    constructor(public name: string, public avatarUrl: string) {\n        super();\n    }\n}\n```\n\n### 2. Define collections:\n\nDefine your database by extending `Database` class. There you can define your collections using `@Collection` decorator:  \n`@Collection(DocDataType: D extends DocumentData, collectionName?: string)`  \nFor example, you have a root collection whose name is `users`\n\n```typescript\nimport {Database, Collection, FirestoreCollection} from \"@phamngocduy98/flashstore-admin\";\nimport {User} from \".\";\n\nexport class MyDatabase extends Database {\n    @Collection(User, \"users\")\n    public users!: FirestoreCollection\u003cUser\u003e;\n}\n```\nIf you don't define collection's name parameter like `@Collection(User)`, the library will use property's name by default.  \nYou can define sub-collection of a document too. If you have a subcollection `wells` inside a `Village` document, then your Village class should look like this:\n\n```typescript\nimport {DocumentData, Collection, FirestoreCollection} from \"@phamngocduy98/flashstore-admin\";\nimport {Well} from \"./sample_db/Well\";\n\nexport class Village extends DocumentData {\n    @Collection(Well, \"wells\")\n    public wells!: FirestoreCollection\u003cWell\u003e;\n}\n```\n\n### 3. CRUD:\n\nYour need initialize your firebase app before using firestore:\n```typescript\nimport * as admin from \"firebase-admin\";\nimport {FirestoreDocument, FirestoreCollection} from \"@phamngocduy98/flashstore-admin\";\nimport {User, MyDatabase} from \".\";\n\nadmin.initializeApp();\nconst db = new MyDatabase(admin.firestore());\n```\n\n#### 3.1 CRUD a collection:\n##### QUERY:\n```typescript\nconst userCollection: FirestoreCollection\u003cUser\u003e = db.users;\nconst users: User[] = await db.users.query((ref) =\u003e ref.where(\"name\", \"==\", \"Duy\"));\n````\n##### CREATE:\n```typescript\n// return FirebaseDocument instance of newly create document\nconst newDocWithAutoCreatedId: FirestoreDocument\u003cUser\u003e = await db.users.create(undefined, new User());\nconst newDocWithSpecificId: FirestoreDocument\u003cUser\u003e = await db.users.create(\"new_user_id\", new User());\n\n// create in batch:\nconst batch = db.batch();\ndb.users.createInBatch(batch, \"new_user_id\", new User());\n```\n##### DELETE:\n```typescript\nawait db.users.delete(\"new_user_id\");\n// delete in batch:\nconst batch = db.batch();\ndb.users.deleteInBatch(batch, \"new_user_id\");\n```\n\n#### 3.2 CRUD a document:\nYou need FirestoreDocument instance to read data or make changes to the document.\nGet a document instance by ID: `Collection.document(docId)`\n```typescript\nconst userCollection: FirestoreCollection\u003cUser\u003e = db.users;\nconst userDoc: FirestoreDocument\u003cUser\u003e = db.users.document(\"my_user_id\");\n```\n\nThen you can read or modify to document as you want:\n##### READ: \n```typescript\n// (return null if document not exists)\nconst userData: User = await userDoc.get();\nconsole.log(userData?.name, userData?.avatarUrl);\n```\n##### UPDATE:\n```typescript\nawait userDoc.update({avatarUrl: \"new avatar\"});\n```\n##### DETELE:\n```typescript\nawait userDoc.delete();\n```\n##### SET:\n```typescript\n// (set will overwrite current value or create a new document if the document not exist)\nuserDoc.set({name: \"new name\", avatarUrl: \"new avatar\"});\n```\n##### Access sub-collection:\n```typescript\nconst villageDoc = await db.villages.document(\"test_village\");\nconst wellSubCollection: FirestoreCollection\u003cWell\u003e = villageDoc.collection(\"wells\");\n// Then you can use all methods that is available for collection\nawait wellSubCollection.create(undefined, new Well(\"well 1\"));\n```\n---\n\n### 4. Using references.\n\n#### 4.1 Define a document property reference to other Document\nFor example, you have a Village entity then your village have an owner which is a user. You need create an `owner` property with `@RefFDocument(collectionName: string)` decorator.  \n```\n@RefFDocument(\"users\")\nowner: FirestoreDocument\u003cUser\u003e;\n```\nThen the `owner` property will be stored as `DocumentReference` in firestore, while you can access it as a true FirestoreDocument in Village instance.  \nMake sure your collection name (eg. \"users\") should be root collection (not a sub-collection).\n\n\n\n```typescript\nexport class Village extends DocumentData {\n    @RefFDocument(\"users\")\n    owner: FirestoreDocument\u003cUser\u003e;\n\n    constructor(public name: string, public description: string, owner: FirestoreDocument\u003cUser\u003e) {\n        super();\n        this.owner = owner;\n    }\n}\n```\n\n##### Read data of referenced document:\nRead Village.owner document data:\n```typescript\nconst villageDoc: FirestoreDocument\u003cVillage\u003e = db.villages.document(\"village_id\");\nconst villageData: Village = await villageDoc.get();\n\nconst ownerDoc: FirestoreDocument\u003cUser\u003e = village!.owner;\nconst ownerData: User = await village!.owner.get();\nconsole.log(ownerData?.name, ownerData?.avatarUrl);\n```\n##### Modify the referenced property\n###### Change it to another document.\n```typescript\nconst userDoc: FirestoreDocument\u003cUser\u003e = db.users.document(\"user_id\");\nvillageDoc.update({owner: userDoc});\n```\n###### Set it to null\nMake sure you define it nullable in Village DocumentData like this `owner: FirestoreDocument\u003cUser\u003e | null;`before set it to null:\n```typescript\nexport class Village extends DocumentData {\n    @RefFDocument(\"users\")\n    owner: FirestoreDocument\u003cUser\u003e | null;\n}\n```\n```typescript\nvillageDoc.update({owner: null});\n```\n---\n#### 4.2 Define a document property reference to array of other Documents\n\nContinue our story: a village entity cannot only have owner :) It needs members which is an array of `User`.\nYou can use `@RefFDUnionArray` decorator the same as `@RefFDocument`. The only difference is `members` is an array of `FirestoreDocument\u003cUser\u003e` and is stored as an array of `DocumentReference` in firestore.\n```\n@RefFDUnionArray(\"users\")\nmembers: FDUnionArray\u003cFirestoreDocument\u003cUser\u003e\u003e;\n```\nSo, the completed Village class is:\n\n```typescript\nexport class Village extends DocumentData {\n    @RefFDocument(\"users\")\n    owner: FirestoreDocument\u003cUser\u003e;\n    @RefFDUnionArray(\"users\")\n    members: FDUnionArray\u003cFirestoreDocument\u003cUser\u003e\u003e;\n\n    constructor(public name: string, public description: string, owner: FirestoreDocument\u003cUser\u003e) {\n        super();\n        this.owner = owner;\n        this.members = new FDUnionArray(owner);\n    }\n}\n```\n\n##### CRUD referenced document array:\n\n```typescript\nconst villageDoc: FirestoreDocument\u003cVillage\u003e = db.villages.document(\"village_id\");\nconst village: Village = await villageDoc.get(); // you must get() parent document before reading referenced document array\nconst members: FDUnionArray\u003cFirestoreDocument\u003cUser\u003e\u003e = village!.members;\n```\n###### Get a document from array:\n```typescript\nconst village: Village = await villageDoc.get(); // you must get() parent document before reading referenced document array\nconst member0: FirestoreDocument\u003cUser\u003e = await village!.members[0];\nconst member0Data: Village = await member0.get();\nconsole.log(member0Data.name, member0Data.avatarUrl);\n```\n###### Get all array\n```typescript\nconst village: Village = await villageDoc.get(); // you must get() parent document before reading referenced document array\nconst villages: Village[] = await village.members.getAll();\n```\n###### push a element\n```typescript\nconst userDoc: FirestoreDocument\u003cUser\u003e = db.users.document(\"user_id\");\nawait village.members.pushDB(userDoc);\n```\n###### pop the array\n```typescript\nconst popDoc = await village.members.popDB();\n```\n###### Splice the array\n```typescript\nawait village.members.spliceDB(0, 1);\n```\n###### Update the whole array\n```typescript\nconst village1Doc: FirestoreDocument\u003cVillage\u003e = db.villages.document(\"village_1_id\");\nconst village2Doc: FirestoreDocument\u003cVillage\u003e = db.villages.document(\"village_2_id\");\nawait village.update({members: [village1Doc, village2Doc]});\n```\n\nYou may want to explore (or not) `FDArrayTracker` that can be get via `FirestoreDocument.linkedArray(propertyName)`.\n\n### 5. Realtime support\n\n**WARNING: This is experiment feature.**  \nWhile realtime features of firestore costs your firestore read/write quota a lot, it's recommend to avoid using it. Realtime Database is a good choice too.\n\n#### 5.1 Realtime Collection\n\nUse `@RealtimeCollection` decorator instead of `@Collection` decorator to define a realtime collection. Realtime Collection document's data is kept in sync with firestore in realtime.  \nYou can add listeners to listen these changes too.\n\n```typescript\nimport {OnCollectionChangedListener, RealtimeFirestoreDocument} from \"@phamngocduy98/flashstore-admin\";\n\nconst listener = new OnCollectionChangedListener();\nlistener.onDocumentAdded = (doc: RealtimeFirestoreDocument\u003cD\u003e) =\u003e {\n    console.log(doc.value());\n};\nlistener.onDocumentModified = (doc: RealtimeFirestoreDocument\u003cD\u003e) =\u003e {\n    console.log(doc.value());\n};\nlistener.onDocumentRemoved = (doc: RealtimeFirestoreDocument\u003cD\u003e) =\u003e {\n    console.log(doc.value());\n};\ndb.anyRealtimeCollection.addOnCollectionChangedListener(listener);\n```\n\n#### 5.2 Realtime Document\n\n`RealtimeFirestoreDocument` is created be `RealtimeFirestoreCollection`. Its data is always up to date with the server in realtime. It support listener too.`\n\n```typescript\nimport {OnValueChangedListener, RealtimeFirestoreDocument} from \"@phamngocduy98/flashstore-admin\";\n\nconst anyRealtimeDocument: RealtimeFirestoreDocument\u003cD\u003e = db.anyRealtimeCollection.document(\"document_id\");\n\nconst listener = new OnValueChangedListener\u003cD\u003e();\nlistener.onValueChanged = (doc: RealtimeFirestoreDocument\u003cD\u003e) =\u003e {\n    console.log(doc.value());\n};\nlistener.onDocumentRemoved = (doc: RealtimeFirestoreDocument\u003cD\u003e) =\u003e {\n    console.log(doc.value());\n};\nanyRealtimeDocument.addOnValueChangedListener(listener);\n```\n\n##### Realtime Document with Referenced Document Array:\n###### Listen for changes\nYou can attach listener to listen when a item is being added to or removed from array\n```typescript\nconst listener = OnArrayChangedListener\u003cUser\u003e();\nlistener.onItemsInserted = (docs: FirestoreDocument\u003cUser\u003e[]) =\u003e {\n    console.log(docs);\n};\nlistener.onItemsRemoved = (docs: FirestoreDocument\u003cUser\u003e[]) =\u003e {\n    console.log(docs);\n};\nvillageDoc.linkedArray(\"member\").addOnArrayChangedListener(listener);\n```\n\n### 6. Batch support\n\n```typescript\nlet batch = db.batch(); // or batch = anyDocument.root.batch();\nuserDoc.updateInBatch(batch, {name: \"new name\"});\nuserDoc.updateInBatch(batch, {avatarUrl: \"new avatar\"});\nawait batch.commit();\n```\n\n### 7. Access parent and root:\n\nIn each document or collection, you can get its parent or root but I do not recommend you do so.\n\n```typescript\nlet root: MyDatabase = userDoc.root;\nlet userCollection: FirestoreCollection\u003cUser\u003e = userDoc.parentCollection;\n```\n\n### 8. A subcollection pattern:\n\n**Reference to a sub-collection is NOT SUPPORTED in the current version of flashstore.  \nPlease wait for updates!**  \n\nPattern introduction:\n- You want to allow clients to directly connect to firestore database.  \n- For example, you allow clients to create their own document to a sub-collection. Then you want reset the sub-collection for new writes, so you need to delete each document in the sub-collection.  \n- These delete operations cost a lot while after deletions, your sub-collection will be soon full of new documents.  \n  \n=\u003e So there is a solution, you can create a referenced document array to take care of which document is new. Now you can access all new documents without reset the sub-collection.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphamngocduy98%2Fnpm-flashstore-admin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphamngocduy98%2Fnpm-flashstore-admin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphamngocduy98%2Fnpm-flashstore-admin/lists"}