{"id":15516679,"url":"https://github.com/alexvcasillas/graphdb","last_synced_at":"2025-04-23T04:16:34.583Z","repository":{"id":44972346,"uuid":"242221196","full_name":"alexvcasillas/graphdb","owner":"alexvcasillas","description":"An in memory database with sync capabilities","archived":false,"fork":false,"pushed_at":"2024-07-11T09:26:17.000Z","size":519,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-17T19:17:57.176Z","etag":null,"topics":["database","in-memory","in-memory-database","in-memory-storage","javascript","synchronization","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@alexvcasillas/graphdb","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/alexvcasillas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"alexvcasillas","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2020-02-21T20:05:20.000Z","updated_at":"2024-07-11T09:26:15.000Z","dependencies_parsed_at":"2025-04-17T08:04:26.485Z","dependency_job_id":"7f69ccf4-3129-4ad0-99a6-4b2feea35f6e","html_url":"https://github.com/alexvcasillas/graphdb","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexvcasillas%2Fgraphdb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexvcasillas%2Fgraphdb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexvcasillas%2Fgraphdb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexvcasillas%2Fgraphdb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexvcasillas","download_url":"https://codeload.github.com/alexvcasillas/graphdb/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249981648,"owners_count":21355546,"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":["database","in-memory","in-memory-database","in-memory-storage","javascript","synchronization","typescript"],"created_at":"2024-10-02T10:09:28.677Z","updated_at":"2025-04-23T04:16:34.557Z","avatar_url":"https://github.com/alexvcasillas.png","language":"TypeScript","funding_links":["https://github.com/sponsors/alexvcasillas"],"categories":[],"sub_categories":[],"readme":"# 📦 GraphDB – An in memory database with sync capabilities\n\nGraphDB is an in memory database with sync capabilities that lets you handle data the way you want with a bare minimum setup.\n\n[![CircleCI](https://circleci.com/gh/alexvcasillas/graphdb.svg?style=svg)](https://circleci.com/gh/alexvcasillas/graphdb)\n[![Codecoverage](https://img.shields.io/badge/coverage-98.87%25-green)](https://img.shields.io/badge/coverage-98.87%25-green)\n\n[![BundleSize](https://img.shields.io/bundlephobia/minzip/@alexvcasillas/graphdb)](https://img.shields.io/bundlephobia/minzip/@alexvcasillas/graphdb)\n[![Downloads](https://img.shields.io/npm/dw/@alexvcasillas/graphdb)](https://img.shields.io/npm/dw/@alexvcasillas/graphdb)\n\n[![Version](https://img.shields.io/npm/v/@alexvcasillas/graphdb)](https://img.shields.io/npm/v/@alexvcasillas/graphdb)[![License](https://img.shields.io/npm/l/@alexvcasillas/graphdb)](https://img.shields.io/npm/l/@alexvcasillas/graphdb)\n\n- [Quick start](#quick-start)\n- [Initialization](#initialization)\n- [API and Types](#api-and-types)\n- [Create a collection](#create-a-collection)\n- [Get a collection](#get-a-collection)\n- [Populate a collection](#populate-a-collection)\n- [Listen to collection on](#listen-to-collection-on)\n- [Create a document](#create-a-document)\n- [Read a document](#read-a-document)\n- [Query documents](#query-documents)\n- [Query documents with complex where clause](#query-documents-with-complex-where-clause)\n- [Query documents with additional options](#query-documents-with-additional-options)\n- [Update a document](#update-a-document)\n- [Remove a document](#remove-a-document)\n- [Listen to changes](#listen-to-changes)\n- [Syncers](#syncers)\n\n# Quick start\n\n```\nyarn add @alexvcasillas/graphdb\n```\n\n```\nnpm i -s @alexvcasillas/graphdb\n```\n\n# Initialization\n\n```typescript\nimport { GraphDB } from '@alexvcasillas/graphdb';\n\nconst graphdb = GraphDB();\n```\n\n# API and Types\n\n```typescript\nexport type GraphDBType = {\n  createCollection: \u003cT\u003e(\n    collectionId: string,\n    syncers?: GraphDocumentSyncers\u003cT\u003e\n  ) =\u003e void;\n  getCollection: \u003cT\u003e(collectionId: string) =\u003e Collection\u003cT\u003e | null;\n};\n\nexport type Where = {\n  [property: string]: any;\n};\n\nexport type QueryOptions = {\n  skip?: number;\n  limit?: number;\n  orderBy?: {\n    [key: string]: 'ASC' | 'DESC';\n  };\n};\n\nexport type Collection\u003cT\u003e = {\n  read: (documentId: string) =\u003e GraphDocument\u003cT\u003e;\n  query: (\n    where: Where,\n    options?: QueryOptions\n  ) =\u003e GraphDocument\u003cT\u003e | GraphDocument\u003cT\u003e[] | null;\n  create: (document: T) =\u003e Promise\u003cstring\u003e;\n  update: (documentId: string, patch: Partial\u003cT\u003e) =\u003e Promise\u003cGraphDocument\u003cT\u003e\u003e;\n  remove: (documentId: string) =\u003e Promise\u003cRemoveOperationFeedback\u003e;\n  populate: (population: GraphDocument\u003cT\u003e[]) =\u003e void;\n  listen: (\n    documentId: string,\n    listener: ListenerFn\u003cGraphDocument\u003cT\u003e\u003e\n  ) =\u003e CancelListenerFn;\n  on: (\n    type: 'create' | 'update' | 'remove' | 'populate',\n    listener: ListenerFn\u003cGraphDocument\u003cT\u003e\u003e\n  ) =\u003e CancelListenerFn;\n};\n\nexport type GraphDocument\u003cT\u003e = {\n  _id: string;\n  createdAt: Date;\n  updateAt: Date;\n} \u0026 T;\n\nexport type ListenerFn\u003cT\u003e = (document: GraphDocument\u003cT\u003e) =\u003e void;\nexport type ListenerOnFn = () =\u003e void;\n\nexport type GraphDocumentListener\u003cT\u003e = {\n  id: string;\n  document: string;\n  fn: ListenerFn\u003cGraphDocument\u003cT\u003e\u003e;\n};\n\nexport type GraphDocumentListenerOn = {\n  id: string;\n  type: 'create' | 'update' | 'remove' | 'populate';\n  fn: ListenerOnFn;\n};\n\nexport type GraphDocumentListeners\u003cT\u003e = GraphDocumentListener\u003cT\u003e[];\nexport type GraphDocumentListenersOn = GraphDocumentListenerOn[];\n\nexport type CancelListenerFn = () =\u003e void;\n\nexport type GraphDocumentSyncers\u003cT\u003e = {\n  create?: (document: GraphDocument\u003cT\u003e) =\u003e Promise\u003cboolean\u003e;\n  update?: (document: GraphDocument\u003cT\u003e) =\u003e Promise\u003cboolean\u003e;\n  remove?: (documentId: string) =\u003e Promise\u003cboolean\u003e;\n};\n\nexport type RemoveOperationFeedback = {\n  removedId: string;\n  acknowledge: true;\n};\n```\n\n# Create a collection\n\n```typescript\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n}\n\ngraphdb.createCollection\u003cUserModel\u003e('user');\n```\n\n# Get a collection\n\n```typescript\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n}\n\nconst userCollection = graphdb.getCollection\u003cUserModel\u003e('user');\n```\n\n# Populate a collection\n\n```typescript\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n}\n\nconst userCollection = graphdb.getCollection\u003cUserModel\u003e('user');\n\nuserCollection.populate([\n  {\n    _id: '1',\n    name: 'Alex',\n    lastName: 'Casillas',\n    age: 29,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '2',\n    name: 'Alex',\n    lastName: 'Casillas',\n    age: 29,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '3',\n    name: 'Alex',\n    lastName: 'Casillas',\n    age: 29,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '4',\n    name: 'Alex',\n    lastName: 'Casillas',\n    age: 29,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '5',\n    name: 'Alex',\n    lastName: 'Casillas',\n    age: 29,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '6',\n    name: 'Alex',\n    lastName: 'Casillas',\n    age: 29,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n]);\n```\n\n# Listen to collection on\n\n```typescript\nimport { GraphDocument } from '@alexvcasillas/graphdb';\n\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n}\n\nconst userCollection = graphdb.getCollection\u003cUserModel\u003e('user');\n\nconst stopOnCreateListen = userCollection.on('create', function onCreate() {});\nconst stopOnPopulateListen = userCollection.on(\n  'populate',\n  function onPopulate() {}\n);\nconst stopOnUpdateListen = userCollection.on('update', function onUpdate() {});\nconst stopOnRemoveListen = userCollection.on('remove', function onRemove() {});\n\nstopOnCreateListen();\nstopOnPopulateListen();\nstopOnUpdateListen();\nstopOnRemoveListen();\n```\n\n# Create a document\n\n```typescript\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n}\n\nconst userCollection = graphdb.getCollection\u003cUserModel\u003e('user');\n\nconst insertedId = await userCollection.create({\n  name: 'Alex',\n  lastName: 'Casillas',\n  age: 29,\n});\n```\n\n# Read a document\n\n```typescript\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n}\n\nconst userCollection = graphdb.getCollection\u003cUserModel\u003e('user');\n\nconst insertedId = await userCollection.create({\n  name: 'Alex',\n  lastName: 'Casillas',\n  age: 29,\n});\n\nconst userDocument = userCollection.read(insertedId as string);\n```\n\n# Query documents\n\n```typescript\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n}\n\nconst userCollection = graphdb.getCollection\u003cUserModel\u003e('user');\n\nawait userCollection.create({\n  name: 'Alex',\n  lastName: 'Casillas',\n  age: 29,\n});\n\n// Empty where clause returns all documents on the collection\nuserCollection.query({});\nuserCollection.query({ name: 'Alex', age: 29 });\n```\n\nRegExp can be used as value to check for a matching property without the need of a complex query object.\n\n```typescript\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n  email: string;\n}\n\nconst userCollection = graphdb.getCollection\u003cUserModel\u003e('user');\n\nuserCollection?.populate([\n  {\n    _id: '1',\n    name: 'Alex',\n    lastName: 'Casillas',\n    email: 'alex@gmail.com',\n    age: 29,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '2',\n    name: 'Daniel',\n    lastName: 'Casillas',\n    email: 'dani@hotmail.com',\n    age: 22,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '3',\n    name: 'Antonio',\n    lastName: 'Cobos',\n    email: 'antonio@gmail.com',\n    age: 35,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '4',\n    name: 'John',\n    lastName: 'Snow',\n    email: 'john@thewall.com'\n    age: 19,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '5',\n    name: 'John',\n    lastName: 'Doe',\n    email: 'john@gmail.com',\n    age: 40,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '6',\n    name: 'Jane',\n    lastName: 'Doe',\n    email: 'jane@msn.com',\n    age: 50,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n]);\n\nconst queryResult = userCollection?.query({\n  'name', new RegExp(/Al{1,1}/ig)\n});\n\n// queryResult.length === 1\n\n// queryResult[0]\n// { _id: '1', name: 'Alex', lastName: 'Casillas', email: 'alex@gmail.com' }\n```\n\n# Query documents with complex where clause\n\nComplex operators for `number` types include for now:\n\n- `gt`: greater than\n- `gte`: greater than or equals\n- `lt`: lower than\n- `lte`: lower than or equals\n\n```\n{ age: { gt: 20, lt: 40 } }\n```\n\n```typescript\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n}\n\nconst userCollection = graphdb.getCollection\u003cUserModel\u003e('user');\n\nuserCollection?.populate([\n  {\n    _id: '1',\n    name: 'Alex',\n    lastName: 'Casillas',\n    age: 29,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '2',\n    name: 'Daniel',\n    lastName: 'Casillas',\n    age: 22,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '3',\n    name: 'Antonio',\n    lastName: 'Cobos',\n    age: 35,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '4',\n    name: 'John',\n    lastName: 'Snow',\n    age: 19,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '5',\n    name: 'John',\n    lastName: 'Doe',\n    age: 40,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '6',\n    name: 'Jane',\n    lastName: 'Doe',\n    age: 50,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n]);\n\nconst queryResult = userCollection?.query({\n  age: { gt: 30 },\n});\n\n// queryResult.length === 3\n\n// queryResult[0]\n// { _id: '3', name: 'Antonio', lastName: 'Cobos', age: 35 }\n\n// queryResult[1]\n// { _id: '5', name: 'John', lastName: 'Doe', age: 40 }\n\n// queryResult[2]\n// { _id: '6', name: 'Jane', lastName: 'Doe', age: 50 }\n```\n\nComplex operators for `string` types include for now:\n\n- `eq`: equals\n- `notEq`: not equals\n- `includes`: includes the given substring\n- `startsWith`: starts with the given substring\n- `endsWith`: ends with the given substring\n\nThis operators can be used to form complex where clauses like the following:\n\n```\n{ email: { endsWith: '@gmail.com' } }\n```\n\n```typescript\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n  email: string;\n}\n\nconst userCollection = graphdb.getCollection\u003cUserModel\u003e('user');\n\nuserCollection?.populate([\n  {\n    _id: '1',\n    name: 'Alex',\n    lastName: 'Casillas',\n    email: 'alex@gmail.com',\n    age: 29,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '2',\n    name: 'Daniel',\n    lastName: 'Casillas',\n    email: 'dani@hotmail.com',\n    age: 22,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '3',\n    name: 'Antonio',\n    lastName: 'Cobos',\n    email: 'antonio@gmail.com',\n    age: 35,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '4',\n    name: 'John',\n    lastName: 'Snow',\n    email: 'john@thewall.com'\n    age: 19,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '5',\n    name: 'John',\n    lastName: 'Doe',\n    email: 'john@gmail.com',\n    age: 40,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '6',\n    name: 'Jane',\n    lastName: 'Doe',\n    email: 'jane@msn.com',\n    age: 50,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n]);\n\nconst queryResult = userCollection?.query({\n  email: { endsWith: '@gmail.com' },\n});\n\n// queryResult.length === 3\n\n// queryResult[0]\n// { _id: '1', name: 'Alex', lastName: 'Casillas', email: 'alex@gmail.com' }\n\n// queryResult[1]\n// { _id: '3', name: 'Antonio', lastName: 'Cobos', email: 'antonio@gmail.com' }\n\n// queryResult[2]\n// { _id: '5', name: 'John', lastName: 'Doe', email: 'john@gmail.com' }\n```\n\nComplex operators can include a `RegExp` to match, this will give you a boost of flexibility, the `match` property \nin the complex where clause will allow you to perform this operation.\n\n```typescript\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n  email: string;\n}\n\nconst userCollection = graphdb.getCollection\u003cUserModel\u003e('user');\n\nuserCollection?.populate([\n  {\n    _id: '1',\n    name: 'Alex',\n    lastName: 'Casillas',\n    email: 'alex@gmail.com',\n    age: 29,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '2',\n    name: 'Daniel',\n    lastName: 'Casillas',\n    email: 'dani@hotmail.com',\n    age: 22,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '3',\n    name: 'Antonio',\n    lastName: 'Cobos',\n    email: 'antonio@gmail.com',\n    age: 35,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '4',\n    name: 'John',\n    lastName: 'Snow',\n    email: 'john@thewall.com'\n    age: 19,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '5',\n    name: 'John',\n    lastName: 'Doe',\n    email: 'john@gmail.com',\n    age: 40,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '6',\n    name: 'Jane',\n    lastName: 'Doe',\n    email: 'jane@msn.com',\n    age: 50,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n]);\n\nconst queryResult = userCollection?.query({\n  'name', { match: new RegExp(/Al{1,1}/ig) }\n});\n\n// queryResult.length === 1\n\n// queryResult[0]\n// { _id: '1', name: 'Alex', lastName: 'Casillas', email: 'alex@gmail.com' }\n```\n\n# Query documents with additional options\n\nAdditional options for the query are the following:\n\n- `skip`: skips the given amount of documents from the beginning of the collection\n- `limit`: by the given amount limits the resulted documents from the query\n- `orderBy`: sorts the resulted query documents by the given fields in the given order (ASC or DESC)\n\nThis operators can be combined to form complex option clauses like the following:\n\n```\n{\n  skip: 2,\n  limit: 4,\n  orderBy: {\n    age: 'DESC',\n  },\n}\n```\n\n```typescript\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n}\n\nconst userCollection = graphdb.getCollection\u003cUserModel\u003e('user');\n\nuserCollection?.populate([\n  {\n    _id: '1',\n    name: 'Alex',\n    lastName: 'Casillas',\n    age: 29,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '2',\n    name: 'Daniel',\n    lastName: 'Casillas',\n    age: 22,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '3',\n    name: 'Antonio',\n    lastName: 'Cobos',\n    age: 35,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '4',\n    name: 'John',\n    lastName: 'Snow',\n    age: 19,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '5',\n    name: 'John',\n    lastName: 'Doe',\n    age: 40,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n  {\n    _id: '6',\n    name: 'Jane',\n    lastName: 'Doe',\n    age: 50,\n    createdAt: new Date(),\n    updateAt: new Date(),\n  },\n]);\n\nconst queryResult = userCollection?.query(\n  {},\n  {\n    orderBy: {\n      age: 'ASC',\n    },\n  }\n);\n\n// queryResult[0]._id = '4'\n// queryResult[1]._id = '2'\n// queryResult[2]._id = '1'\n// queryResult[3]._id = '3'\n// queryResult[4]._id = '5'\n// queryResult[5]._id = '6'\n```\n\n# Update a document\n\n```typescript\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n}\n\nconst userCollection = graphdb.getCollection\u003cUserModel\u003e('user');\n\nconst insertedId = await userCollection.create({\n  name: 'Alex',\n  lastName: 'Casillas',\n  age: 29,\n});\n\nconst updatedDocument = await userCollection.update(insertedId as string, {\n  name: 'John',\n  lastName: 'Snow',\n});\n```\n\n# Remove a document\n\n```typescript\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n}\n\nconst userCollection = graphdb.getCollection\u003cUserModel\u003e('user');\n\nconst insertedId = await userCollection.create({\n  name: 'Alex',\n  lastName: 'Casillas',\n  age: 29,\n});\n\nconst removeFeedback = await userCollection.remove(insertedId as string);\n```\n\n# Listen to changes\n\n```typescript\nimport { GraphDocument } from '@alexvcasillas/graphdb';\n\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n}\n\nconst userCollection = graphdb.getCollection\u003cUserModel\u003e('user');\n\nconst insertedId = await userCollection.create({\n  name: 'Alex',\n  lastName: 'Casillas',\n  age: 29,\n});\n\nconst stopListen = userCollection.listen(\n  insertedId as string,\n  (document: GraphDocument\u003cUserModel\u003e) =\u003e {\n    // Handle document updates here\n  }\n);\n\n// Call this whenever you want to stop lintening to changes\nstopListen();\n```\n\n# Syncers\n\nSyncers are a cool feature that will let you sync data to your backend. You can add up to three syncers: to `create`, to `update` and to `remove`.\n\n```typescript\nimport { GraphDB } from '@alexvcasillas/graphdb'\n\nconst graphdb = GraphDB();\n\ninterface UserModel {\n  name: string;\n  lastName: string;\n  age: string;\n}\n\ngraphdb.createCollection\u003cUserModel\u003e('user', {\n  create(document: GraphDocument\u003cT\u003e) {\n    return new Promise((resolve, reject) =\u003e {\n      // Send data to your backend!\n      const backendResponse = await backend.create(document);\n      // Resolve with true if backend process was ok\n      if (backendResponse.status === 200) return resolve(true);\n      // Reject with false if backend process was ok\n      if (backendResponse.status === 500) return reject(false);\n    });\n  };\n  update(document: GraphDocument\u003cT\u003e) {\n    return new Promise((resolve, reject) =\u003e {\n      // Send data to your backend!\n      const backendResponse = await backend.update(document);\n      // Resolve with true if backend process was ok\n      if (backendResponse.status === 200) return resolve(true);\n      // Reject with false if backend process was ok\n      if (backendResponse.status === 500) return reject(false);\n    });\n  };\n  remove(documentId: string) {\n    return new Promise((resolve, reject) =\u003e {\n      // Send data to your backend!\n      const backendResponse = await backend.remove(document);\n      // Resolve with true if backend process was ok\n      if (backendResponse.status === 200) return resolve(true);\n      // Reject with false if backend process was ok\n      if (backendResponse.status === 500) return reject(false);\n    });\n  };\n});\n```\n\nThe cool thing about data-syncing is that if the sync promise returns false, it will revert changes locally at the state it was previously, meaning that changes wont be applied localy and you'll always be in-sync with your backend.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexvcasillas%2Fgraphdb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexvcasillas%2Fgraphdb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexvcasillas%2Fgraphdb/lists"}