{"id":19804061,"url":"https://github.com/svenvdam/htypes","last_synced_at":"2026-06-11T00:31:48.407Z","repository":{"id":57727377,"uuid":"206748834","full_name":"SvenvDam/HTypes","owner":"SvenvDam","description":"A type-safe, asynchronous, composable Scala extension to the HBase Client API","archived":false,"fork":false,"pushed_at":"2019-11-24T10:10:32.000Z","size":155,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-11T05:48:24.091Z","etag":null,"topics":["hbase","hbase-client","scala"],"latest_commit_sha":null,"homepage":"","language":"Scala","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/SvenvDam.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}},"created_at":"2019-09-06T08:26:11.000Z","updated_at":"2021-02-16T16:55:17.000Z","dependencies_parsed_at":"2022-09-26T21:51:22.362Z","dependency_job_id":null,"html_url":"https://github.com/SvenvDam/HTypes","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SvenvDam%2FHTypes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SvenvDam%2FHTypes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SvenvDam%2FHTypes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SvenvDam%2FHTypes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SvenvDam","download_url":"https://codeload.github.com/SvenvDam/HTypes/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241144862,"owners_count":19917363,"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":["hbase","hbase-client","scala"],"created_at":"2024-11-12T08:02:45.668Z","updated_at":"2026-06-11T00:31:48.350Z","avatar_url":"https://github.com/SvenvDam.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/SvenvDam/HTypes.svg?branch=master)](https://travis-ci.org/SvenvDam/HTypes)\n\n# HTypes\n\u003e A type-safe, asynchronous, composable Scala extension to the HBase Client API \n\nHTypes is a simple Scala extension to the Apache HBase API with no dependencies.\nIt assumes you have have the HBase client API available as a dependency in your project.\nIt adds the following improvements to the Java API:\n\n* Asynchronous execution of queries.\n* Automatic conversion between objects and an encoded form.\n* Automatic conversion between common primitive types and byte arrays (and the option to add more yourself).\n\n## Installation\n\n```sbtshell\nlibraryDependencies += \"com.svenvandam\" %% \"htypes-core\" % \"0.5\"\n```\n\n## Example\n\n### Basic usage\n\n```scala\nimport com.svenvandam.htypes.Implicits._\nimport com.svenvandam.htypes.model._\nimport com.svenvandam.htypes.hbase._\nimport com.svenvandam.htypes.hbase.query.{PutUtils, GetUtils}\nimport org.apache.hadoop.hbase.client.{Connection, Put, Scan}\nimport org.apache.hadoop.hbase._\n\n\n// an example type we'll be encoding and decoding\n\ncase class User(id: String, name: String, age: Int)\n\n// typeclass instances for User to en/decode it to an HBase compatible format\n\nimplicit val userCodec = new RowCodec[User] {\n  private val ageColumn = Column(\"profile\", \"age\")\n  private val nameColumn = Column(\"profile\", \"name\")\n\n  def getColumns = Set(\n    ageColumn,\n    nameColumn\n  )\n  \n  def encode(user: User): Row = Row(\n    user.id,\n    Map(\n      ageColumn -\u003e CellValue(user.age, None),\n      nameColumn -\u003e CellValue(user.name, None)\n    )\n  )\n  \n  def decode(row: Row): Option[User] = for {\n    id                      \u003c- row.key.as[String]\n    CellValue(ageBytes, _)  \u003c- row.values.get(ageColumn)\n    age                     \u003c- ageBytes.as[Int]\n    CellValue(nameBytes, _) \u003c- row.values.get(nameColumn)\n    name                    \u003c- nameBytes.as[String]\n  } yield User(id, name, age)\n}\n\n// you'll have to do this yourself\n\nval conn: Connection = getConnection()\n\nval table = conn.getTable(TableName.valueOf(\"MyTable\"))\n\n// a user gets automatically encoded to an HBase compatible form and stored in a Put query\n\nval put = PutUtils.createFrom(User(\"id123\", \"Alice\", 30))\n\ntable.put(put)\n\n// Automatically scan all columns associated with User\n\nval scan = new Scan().addColumnsFrom[User]\n\n// Automatically convert scan result to a series of time-versioned User's\n\nval scanResult = table.getScanner(scan).as[User]\n\nfor {\n  usersInScan       \u003c- scanResult\n  userValues        \u003c- usersInScan\n  (user, timestamp) \u003c- userValues\n} println(s\"Found user $user at timestamp $timestamp\")\n\n```\n\n### Wrapping side-effects\n\n```scala\n// HTypes lets you execute queries in an effect wrapper\n// You have to define a backend to execute your query in (Future, Task, IO, etc)\n// An EffectBackend instance for Future is provided by HTypes\n\nimport com.svenvandam.htypes.effect.FutureEffectBackend\nimport scala.concurrent.ExecutionContext.Implicits.global\n\nimplicit val asyncBackend = FutureEffectBackend()\n\nval f: Future[Unit] = table.putEffect(put)\n\nf.foreach(_ =\u003e println(\"Put result!\"))\n```\n\n### Composing encoders and decoders\n\n```scala\nimport com.svenvandam.htypes.Implicits._\nimport com.svenvandam.htypes.model._\nimport com.svenvandam.htypes.hbase._\n\ncase class UserWithSession(id: String, name: String, age: Int, SessionId: Long)\n\ncase class User(id: String, name: String, age: Int)\n\nval userCodec = new RowCodec[User] {\n  private val ageColumn = Column(\"profile\", \"age\")\n  private val nameColumn = Column(\"profile\", \"name\")\n\n  def getColumns = Set(\n    ageColumn,\n    nameColumn\n  )\n  \n  def encode(user: User): Row = Row(\n    user.id,\n    Map(\n      ageColumn -\u003e CellValue(user.age, None),\n      nameColumn -\u003e CellValue(user.name, None)\n    )\n  )\n  \n  def decode(row: Row): Option[User] = for {\n    id                      \u003c- row.key.as[String]\n    CellValue(ageBytes, _)  \u003c- row.values.get(ageColumn)\n    age                     \u003c- ageBytes.as[Int]\n    CellValue(nameBytes, _) \u003c- row.values.get(nameColumn)\n    name                    \u003c- nameBytes.as[String]\n  } yield User(id, name, age)\n}\n\n\n// mapping an existing RowDecoder\ndef getNewSessionId(): Long = ???\n\nval userSessionDecoder: RowDecoder[UserWithSession] = \n  userCodec.map { case user =\u003e\n    UserWithSession(user.id, user.name, user.age, getNewSessionId())\n  }\n\n// contramap an existing RowDecoder\nval userSessionEncoder: RowEncoder[UserWithSession] = \n  userCodec.contramap[UserWithSession] { case userWithSession =\u003e\n    User(userWithSession.id, userWithSession.name, userWithSession.age)\n  } \n\n// combining decoders\n\ncase class UserInfo(id: String, lastBoughtItem: Int)\n\ncase class UserWithInfo(id: String, name: String, age: Int, lastBoughtItem: Int)\n\nval productColumn = Column(\"history\", \"last_bought_item\")\n\ndef decode(row: Row): Option[UserInfo] = for {\n  id                          \u003c- row.key.as[String]\n  CellValue(productBytes, _)  \u003c- row.values.get(productColumn)\n  product                     \u003c- productBytes.as[Int]\n} yield UserInfo(id, product)\n\nval userInfoDecoder = RowDecoder(decode, Set(productColumn))\n\nval userWithInfoDecoder: RowDecoder[UserWithInfo] = userCodec.combine(\n  userInfoDecoder, \n  (user: User, info: UserInfo) =\u003e UserWithInfo(user.id, user.name, user.age, info.lastBoughtItem)\n)\n\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsvenvdam%2Fhtypes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsvenvdam%2Fhtypes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsvenvdam%2Fhtypes/lists"}