{"id":13409863,"url":"https://github.com/agrevster/pocketbase-kotlin","last_synced_at":"2026-01-11T16:58:59.342Z","repository":{"id":184563294,"uuid":"672076191","full_name":"agrevster/pocketbase-kotlin","owner":"agrevster","description":"A multi-platform Kotlin SDK for Pocketbase.","archived":false,"fork":false,"pushed_at":"2024-08-29T21:44:07.000Z","size":1296,"stargazers_count":17,"open_issues_count":1,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-08-29T23:36:05.057Z","etag":null,"topics":["kotlin","kotlin-library","kotlin-multiplatform","pocketbase"],"latest_commit_sha":null,"homepage":"https://agrevster.github.io/pocketbase-kotlin/","language":"Kotlin","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/agrevster.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}},"created_at":"2023-07-28T21:28:48.000Z","updated_at":"2024-08-29T21:16:59.000Z","dependencies_parsed_at":null,"dependency_job_id":"53c1503c-b4dc-47f1-ab11-d671e15e6a60","html_url":"https://github.com/agrevster/pocketbase-kotlin","commit_stats":null,"previous_names":["agrevster/pocketbase-kotlin"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agrevster%2Fpocketbase-kotlin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agrevster%2Fpocketbase-kotlin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agrevster%2Fpocketbase-kotlin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agrevster%2Fpocketbase-kotlin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/agrevster","download_url":"https://codeload.github.com/agrevster/pocketbase-kotlin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221477228,"owners_count":16829004,"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":["kotlin","kotlin-library","kotlin-multiplatform","pocketbase"],"created_at":"2024-07-30T20:01:03.776Z","updated_at":"2026-01-11T16:58:59.335Z","avatar_url":"https://github.com/agrevster.png","language":"Kotlin","funding_links":[],"categories":["Unofficial PocketBase Clients (SDKs)","Kotlin","API\u0026客户端"],"sub_categories":["Node.js","文件同步"],"readme":"# Pocketbase Kotlin\n\n\u003e Pocketbase Kotlin is a multiplatform Kotlin SDK for [Pocketbase](https://pocketbase.io) designed to be used both\n\u003e client and server side.\n---\n\n## Support\n\nPocketbase Kotlin offers support for [Pocketbase 0.24](https://github.com/pocketbase/pocketbase/releases/tag/v0.24.0)\nand above.\nSupport for new Pocketbase releases will be added as soon as possible.\n\nCurrently, the following platforms are supported,\n\n| Supported Platforms               |       \n|-----------------------------------|       \n| JVM                               |       \n| Linux (x64)                       |       \n| Windows (x64)                     |       \n| Mac OS (x64) (arm x64)            |       \n| IOS (arm x64) (x64) (sim arm x64) |\n| Android                           |\n\n\u003e [!Warning]\n\u003e I will not be adding new features to this project, as I no longer use Kotlin.\n\u003e Going forward, I will only provide dependency updates and minor maintenance to ensure the API is still compatible with\n\u003e Pocketbase.\n\n## Installation\n\n**Using this library requires the**\n[KotlinX Serialization plugin](https://github.com/Kotlin/kotlinx.serialization#using-the-plugins-block)\n\nTo use Pocketbase Kotlin just add the following into your buildscript:\n\n```kotlin\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    implementation(\"io.github.agrevster:pocketbase-kotlin:2.7.3\")\n}\n```\n\n## Usage\n\n### The client\n\nThe `PocketbaseClient` is the class used to access the Pocketbase API.\n\n```kotlin\n//Creates a new pocketbase client with the given url \n// The client is used to access everything in the Pocketbase API \nval client = PocketbaseClient({\n    protocol = URLProtocol.HTTP\n    host = \"localhost\"\n    port = 8090\n})\n```\n\n### Logging in\n\nLogging the client in allows it to call methods that require Pocketbase authentication.\nThe current login token is saved and applied to every api request.\n\nIf you want to log the client out simply use `client.logout()`\n\n```kotlin\n val client = PocketbaseClient({\n    protocol = URLProtocol.HTTP\n    host = \"localhost\"\n    port = 8090\n\n})\nvar loginToken: String\n\n//Logs in as an admin/superuser\nloginToken = client.records.authWithPassword\u003cAuthRecord\u003e(\"_superusers\", email = \"email\", password = \"password\").token\n\n// This authenticates a user rather than an admin\nloginToken = client.records.authWithPassword\u003cAuthRecord\u003e(\"collectionName\", \"email\", \"password\").token\n//You can also use oauth2\nloginToken =\n    client.records.authWithOauth2\u003cAuthRecord\u003e(\"collectionName\", \"provider\", \"code\", \"codeVerifier\", \"redirectUrl\").token\n\nclient.login { token = loginToken }\n```\n\n### Calling the Pocketbase API\n\n```kotlin\n val client = PocketbaseClient({\n    protocol = URLProtocol.HTTP\n    host = \"localhost\"\n    port = 8090\n})\n\nclient.login { token = client.records.authWithPassword\u003cAuthRecord\u003e(\"users\", \"email\", \"password\").token }\n\n//We are using this to hold records created in the collection \"people\".\n//Each record has a name (required), age (required number) and a pet optional.\n//If a value is optional in the collection's schema make sure the kotlin type is nullable and defaults to null.\n//All record classes mst be @Serializable and extend Record.\n@Serializable\ndata class PersonRecord(val name: String, val age: Int, val pet: String? = null) : Record()\n\nval recordToCreate = PersonRecord(\"Tim\", 4)\n//Generics are used to define the return type of api calls, just make sure that the record class you created matches the collection's schema.\nval response = client.records.create\u003cPersonRecord\u003e(\"people\", Json.encodeToString(recordToCreate))\n//You can now use the data from the response.\nval collectionId = response.collectionId\n```\n\n### Congratulations\n\n**All done!** Now that you have a Pocketbase client set up and know how to log in, the rest is easy!\nSimply follow the [Pocketbase Web API Docs](https://pocketbase.io/docs/api-records/) and our internal KDocs to find your\nway around the Pocketbase API.\nThere are a few exceptions for features that could not be made to match the other SDKs, for a guide on them go to\nour [caveats page](#caveats)\n\n---\n\n## Caveats\n\nThis section is dedicated to informing users of the small quirks and irregularities between Pocketbase Kotlin and\nthe [official Pocketbase web API](https://pocketbase.io/docs/api-records/).\n\n### Caveats in the Collections Service\n\nVery seldom do users need to create a new collection with the API, but in the rare instances where this is necessary,\nthere are a couple of differences that should be noted.\n\n#### Creation\n\nThere is no need to create your own collection data class like with the record service, we helpfully provide one with\nall the features needed to create a collection.\n\n#### Example:\n\nIn this example we create the collection used in the [usage example](#calling-the-pocketbase-api) using\nPocketbase Kotlin.\n\n```kotlin\nval client = PocketbaseClient({\n    protocol = URLProtocol.HTTP\n    host = \"localhost\"\n    port = 8090\n})\n\nclient.login {\n    token = client.admins.authWithPassword(\"email\", \"password\").token\n}\n\n//Simply use the collection object and fill out the fields as needed\nval collection = Collection(\n    name = \"people\", type = Collection.CollectionType.BASE, schema = listOf(\n        SchemaField(\n            name = \"name\",\n            type = SchemaField.SchemaFieldType.TEXT,\n            required = true,\n        ),\n        SchemaField(\n            name = \"age\",\n            type = SchemaField.SchemaFieldType.NUMBER,\n            required = true,\n            options = SchemaField.SchemaOptions(\n                //Some options such as min and max can different types\n                //to fix this issue we serialise them as JsonPrimitives\n                min = 0.toJsonPrimitive(), max = 150.toJsonPrimitive()\n            )\n        ),\n        SchemaField(\n            name = \"pet\",\n            type = SchemaField.SchemaFieldType.SELECT,\n            required = false,\n            options = SchemaField.SchemaOptions(values = listOf(\"Dog\", \"Cat\", \"Bird\"))\n        )\n    )\n)\n//The generic '\u003cCollection\u003e' encodes our collection to JSON based on the Collection class\nclient.collections.create\u003cCollection\u003e(Json.encodeToString(collection))\n```\n\n### Caveats in the Records Service\n\n#### File uploading\n\nDue to the fact that Pocketbase Kotlin is multiplatform, file uploads do not use the Java `File` class.\nThere is a special utility class called `FileUpload` designed specifically for this task.\nAlthough there are some caveats to using file uploads, as the way we handle multipart form data prevents using\nserialised records. Meaning that we must use a key value map of Json elements.\n\n#### Example:\n\n```kotlin\nval client = PocketbaseClient({\n    protocol = URLProtocol.HTTP\n    host = \"localhost\"\n    port = 8090\n})\n\nclient.login {\n    token = client.records.authWithPassword\u003cAuthRecord\u003e(\"users\", \"email\", \"password\").token\n}\n\n//Make sure that the field for your file is a string\n//If you have multiple file uploads in your schema make it a list of strings\n@Serializable\ndata class FileUploadRecord(val imageFile: String, val imageDescription: String) : Record()\n\nclient.records.create\u003cFileUploadRecord\u003e(\n    \"fileUploadCollection\",\n    //A workaround to the limitations on JSON with multipart form data\n    mapOf(\"imageDescription\" to \"A house\".toJsonPrimitive()),\n    //Here is where the files are uploaded from\n    //Swap ByteArray(0) with the file's content as a ByteArray\n    listOf(FileUpload(\"imageFile\", ByteArray(0), \"house.png\"))\n)\n```\n\n#### Expanding related fields\n\n```kotlin\nval client = PocketbaseClient({\n    protocol = URLProtocol.HTTP\n    host = \"localhost\"\n    port = 8090\n})\n\nclient.login {\n    token = client.records.authWithPassword\u003cAuthRecord\u003e(\"users\", \"email\", \"password\").token\n}\n\n//For this example imagine we have two collections. One that contains users...\n@Serializable\ndata class PersonRecord(val name: String) : Record()\n\n//And one that contains their pets\n//Each Pet has a name (text), owner (relation), and each Person has a name (text)\n@Serializable\ndata class PetRecord(val owner: String, val name: String) : ExpandRecord\u003cPersonRecord\u003e()\n//This example gets a list of pets, selects the first one and gets its owner\n\nval records = client.records.getList\u003cPetRecord\u003e(\n    \"pets_collection\", 1, 3,\n//This tells Pocketbase to expand the relation field of owner\n    expandRelations = ExpandRelations(\"owner\")\n)\n\n//This returns the expanded record with the field name of owner\nval owner: PersonRecord? = records.items[0].expand?.get(\"owner\")\n```\n\n#### Expanding lists of related fields\n\n*Sometimes people own multiple pets*\n\n```kotlin\nval client = PocketbaseClient({\n    protocol = URLProtocol.HTTP\n    host = \"localhost\"\n    port = 8090\n})\n\nclient.login {\n    token = client.records.authWithPassword\u003cAuthRecord\u003e(\"users\", \"email\", \"password\").token\n}\n\n//For this example we have two collections. One for people and another for their pets\n//Each pet has a name (text)\n@Serializable\ndata class PetRecord(val name: String) : Record()\n\n//Each person has a name (text) and pets (relation)[multiple]\n@Serializable\n//It extends expand record list : used for when you need more than one of the same relation type\ndata class PersonRecord(val name: String, val pets: List\u003cString\u003e) : ExpandRecordList\u003cPetRecord\u003e()\n//\nval records = client.records.getList\u003cPersonRecord\u003e(\n    //This tells Pocketbase to expand the relation field of pets\n    \"people_collection\", 1, 5, expandRelations = ExpandRelations(\"pets\")\n)\n\n//This returns the expanded record with the field name of owner\nval pets: List\u003cPetRecord\u003e? = records.items.first().expand?.get(\"pets\")\n```\n\n#### Making batch requests\n\n\u003e NOTE: Batch requests in Pocketbase are experimental and may break with later versions. Be sure that you are using a\n\u003e version of Pocketbase Kotlin that is compatible with your Pocketbase version.\n\n```kotlin\n    val client = PocketbaseClient({\n    protocol = URLProtocol.HTTP\n    host = \"localhost\"\n    port = 8090\n})\n\nclient.login {\n    token = client.records.authWithPassword\u003cAuthRecord\u003e(\"users\", \"email\", \"password\").token\n}\n\n// What if we want to create a lot of people and don't want to send lots of requests?\n//The personRecordId field is needed so that we can set the ID of the record for upsert operations\n@Serializable\ndata class PersonRecord(val name: String, val age: Int, @Transient val personRecordId: String? = null) :\n    Record(personRecordId)\n\n//They should be at least 18... we don't want example minors in our database without their parent's consent!\nval people =\n    listOf(PersonRecord(\"Tim\", 18), PersonRecord(\"Tom\", 22), PersonRecord(\"Jane\", 83), PersonRecord(\"John\", 34))\n\n//Creates and sends a batch request with the batch service\nval createdRecords = client.batch.send {\n    people.forEach { person -\u003e\n        //Adds a create request to the batch for every person in the people list.\n        create(collectionId = \"COLLECTION_ID\", Json.encodeToJsonElement\u003cPersonRecord\u003e(person).jsonObject)\n    }\n\n    //We can also upload files with the files parameter\n    create(\n        collectionId = \"COLLECTION_ID\",\n        Json.encodeToJsonElement\u003cPersonRecord\u003e(PersonRecord(\"Que\", 49)).jsonObject,\n        files = listOf(FileUpload(\"headshot\", byteArrayOf(), \"que_headshot.png\"))\n    )\n\n    //Nancy got older...\n    update(\n        \"COLLECTION_ID\",\n        \"ALEX_RECORD_ID\",\n        Json.encodeToJsonElement\u003cPersonRecord\u003e(PersonRecord(\"Nancy\", 19)).jsonObject\n    )\n\n    //We can also delete records\n    delete(\"COLLECTION_ID\", \"RECORD_ID_TO_DELETE\")\n\n    //And upsert (update or insert)\n    //just make sure the object has a record ID parameter that is set\n    upsert(\"COLLECTION_ID\", Json.encodeToJsonElement(PersonRecord(\"Tim\", 18, \"TIM_ID\")).jsonObject)\n}\n```\n\n#### Realtime Service\n```kotlin\n// In this example we want to know whenever someone does something with our to-do list.\n@Serializable\ndata class ToDoItem(val text: String) : Record()\n\n// We need to connect to the realtime service. This should be done asynchronously, so that this connection does not block the main thread.\nrunBlocking { launch { client.realtime.connect() } }\n\n\n//Now we need to tell Pocketbase that we want to be notified whenever a to-do list item updates.\n//Our collection is called todo\nclient.realtime.subscribe(\"todo\")\n\n\nclient.realtime.listen {\n    //This filters out connection events\n    if (action.isBodyEvent()) {\n        //This parses the JSON from the realtime event, allowing us to use it\n        val todoItem = parseRecord\u003cToDoItem\u003e()\n        println(\"TO-DO Item: ${todoItem.text} : ${action.name}\")\n    }\n}\n```\n\n\n---\n\n## Testing\n\nFor instructions on how to run the integration tests to see if a pocketbase version is compatible\nsee [testing.md](testing.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagrevster%2Fpocketbase-kotlin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fagrevster%2Fpocketbase-kotlin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagrevster%2Fpocketbase-kotlin/lists"}