{"id":21040962,"url":"https://github.com/chfoo/resdb","last_synced_at":"2025-10-01T04:30:50.935Z","repository":{"id":145909780,"uuid":"142244681","full_name":"chfoo/resdb","owner":"chfoo","description":"Read-only, key-value database using a resource embedding system for Haxe","archived":false,"fork":false,"pushed_at":"2018-09-05T19:20:54.000Z","size":45,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-10-20T18:49:00.450Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Haxe","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/chfoo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2018-07-25T03:52:43.000Z","updated_at":"2023-10-20T18:49:01.039Z","dependencies_parsed_at":null,"dependency_job_id":"36e62d8d-fc47-46bc-8b2b-465216b13198","html_url":"https://github.com/chfoo/resdb","commit_stats":null,"previous_names":[],"tags_count":2,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chfoo%2Fresdb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chfoo%2Fresdb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chfoo%2Fresdb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chfoo%2Fresdb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chfoo","download_url":"https://codeload.github.com/chfoo/resdb/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225364418,"owners_count":17462797,"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":[],"created_at":"2024-11-19T13:49:17.402Z","updated_at":"2025-10-01T04:30:50.573Z","avatar_url":"https://github.com/chfoo.png","language":"Haxe","readme":"Resdb\n=====\n\nResdb is a read-only, key-value database using a resource embedding system for Haxe. It can be used for querying moderately sized datasets in a portable manner.\n\n\nGetting started\n---------------\n\nRequires Haxe 3 or 4.\n\nInstall the library using haxelib:\n\n        haxelib install resdb\n\nAlternatively, you may install the lastest git version:\n\n        haxelib git resdb \u003cURL of this repository\u003e\n\n\n### Packing records into pages\n\nResdb stores the records into separate resources called pages. To prepare the records, use a page packer:\n\n```haxe\nvar pagePacker = new PagePacker({name: \"myDatabase\"});\n```\n\nThen add your records:\n\n```haxe\npagePacker.addRecord(Bytes.ofString(\"key1\"), Bytes.ofString(\"value1\"));\npagePacker.addRecord(Bytes.ofString(\"key2\"), Bytes.ofString(\"value2\"));\n```\n\nThe database should be prepared outside the runtime of your program. You can do this during compile time with an initialization macro.\n\nA helper function that uses Haxe's resource system is provided:\n\n```haxe\nclass MyDatabase {\n    #if macro\n    public static function packAndEmbed() {\n        // ...\n        // Your page packer code\n        // ...\n\n        ResourceHelper.addResource(pagePacker);\n    }\n    #end\n}\n```\n\nThen, add the following compile time option:\n\n```\n--macro MyDatabase.packAndEmbed()\n```\n\n### Compiler performance\n\nIf your IDE uses compiler completion services, you may want to use conditional compilation to skip embedding the resources to avoid slowing down the completion service:\n\n```haxe\n#if !embed_resources\nreturn;\n#else\n// Your page packer code\n```\n\nThen, specify `-D embed_resources` argument when building to a target.\n\n\n### Accessing the database\n\nWhen you need to access your database in your program, you need to obtain the appropriate page store. When using Haxe's system, a helper function is provided:\n\n```haxe\nvar database = ResourcePageStore.getDatabase({name: \"myDatabase\"});\n```\n\nYou can then retrieve a record's value using a key:\n\n```haxe\nswitch database.get(Bytes.ofString(\"key1\")) {\n    case Some(value):\n        trace('Value = $value');\n    case None:\n        trace(\"Not found\");\n}\n```\n\n### Cursors\n\nCursors provide a way to navigate and query records by key in sorted order. You can create a cursor from your database instance:\n\n```haxe\nvar cursor = database.cursor();\n```\n\nThen you can navigate in order, or to the first or last key:\n\n```haxe\nvar firstKey = cursor.first();\nvar lastKey = cursor.last();\n\nswitch cursor.next() {\n    case Some(nextKey):\n        trace('Got next $nextKey');\n    case None:\n        trace(\"At last key\");\n}\n\nswitch cursor.previous() {\n    case Some(previousKey):\n        trace('Got next $previousKey');\n    case None:\n        trace(\"At last key\");\n}\n```\n\nYou can get the current record that the cursor points to:\n\n```haxe\nvar key = cursor.key();\nvar value = cursor.value();\n```\n\nTo query for a key, use the `find()` method:\n\n```haxe\nvar resultKey = cursor.find(Bytes.ofString(\"key5\"));\n```\n\nThe `find()` method will return the nearest key that is equal or less than the given key. The ordering is determined by `Bytes.compare`. In the example above, given a database containing keys `\"key2\", \"key4\", \"key8\"`, the resulting key will be `\"key4\"`.\n\n\n### Adapters\n\nWhile the underlying database uses `Bytes`, it may be more useful to use alternative types. By using `CursorAdapter`, and static extensions, you can bring your own wrappers and serializers.\n\nThe library includes `IntAdapter` that allows the use of integer `Int` as keys:\n\n```haxe\nusing resdb.adapter.IntAdapter;\n\nvar database = ResourcePageStore.getDatabase(\"myDatabase\");\nvar result = database.intGet(123);\ntrace(result);\n\nvar cursor = database.intCursor();\nvar findResult = cursor.find(456);\ntrace(findResult);\n```\n\n### Further details\n\n* [API documentation](https://chfoo.github.io/resdb/api/)\n\n\nOpenFL Assets\n-------------\n\nThe OpenFL asset system support demonstrates how to use Resdb with another resource system.\n\nPrepare the database pages by packing and saving them to your assets directory:\n\n```haxe\nvar pagePacker = new PagePacker({ name: \"myDatabase\" });\n// [do packing]\nFilePageStore.saveDataPages(\"assets/\", \"myDatabase\", pagePacker.packPages());\n```\n\nThen in your application, use:\n\n```haxe\nvar database = OpenFLAssetPageStore.getDatabase({ name: \"assets/myDatabase\" });\n```\n\n\nDatabase format\n---------------\n\nThe database stores records into pages. When the page packer processes the records, it sorts them by key, and fills pages with the serialized data. Records are not equally distributed and pages are filled up sequentially without splitting a record. As such, the maximum page size dictates how large a record may be.\n\nOnce all the records are packed and serialized into pages, the ranges of the records for each page are collected and serialized as the first page. The ranges serve as an index for looking up the appropriate page with the given key.\n\nThe maximum number of records \u0026 pages and the maximum length of keys \u0026 values is 2147483647 which is the limit of the integer type.\n\n\nCompiler flags\n--------------\n\nTo gain some performance, some compiler flags (`-D`) are provided to enable target specific optimizations.\n\n| Flag | Target | Description |\n|------|--------|-------------|\n| `resdb-js-optimize-page-store` | JS (HTML) | In `ResourcePageStore`, uses native `atob()` for base64 decoding as a replacement for `haxe.Resource.getBytes()`. |\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchfoo%2Fresdb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchfoo%2Fresdb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchfoo%2Fresdb/lists"}