{"id":13409611,"url":"https://github.com/pocketbase/dart-sdk","last_synced_at":"2025-04-14T15:54:26.647Z","repository":{"id":50660219,"uuid":"519728947","full_name":"pocketbase/dart-sdk","owner":"pocketbase","description":"PocketBase Dart SDK","archived":false,"fork":false,"pushed_at":"2024-10-16T08:22:07.000Z","size":236,"stargazers_count":512,"open_issues_count":0,"forks_count":51,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-10-17T20:28:18.143Z","etag":null,"topics":["dart","pocketbase"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/pocketbase","language":"Dart","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/pocketbase.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2022-07-31T09:15:24.000Z","updated_at":"2024-10-17T15:53:39.000Z","dependencies_parsed_at":"2024-10-26T00:11:06.367Z","dependency_job_id":"df178513-2b8c-4994-89ec-4460c685d4dd","html_url":"https://github.com/pocketbase/dart-sdk","commit_stats":{"total_commits":93,"total_committers":4,"mean_commits":23.25,"dds":"0.032258064516129004","last_synced_commit":"d7c0c877587befce623608c899be657bd2f710e2"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pocketbase%2Fdart-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pocketbase%2Fdart-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pocketbase%2Fdart-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pocketbase%2Fdart-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pocketbase","download_url":"https://codeload.github.com/pocketbase/dart-sdk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248911944,"owners_count":21182180,"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":["dart","pocketbase"],"created_at":"2024-07-30T20:01:02.324Z","updated_at":"2025-04-14T15:54:26.624Z","avatar_url":"https://github.com/pocketbase.png","language":"Dart","funding_links":[],"categories":["Official Packages"],"sub_categories":[],"readme":"PocketBase Dart SDK [![Pub Package](https://img.shields.io/pub/v/pocketbase.svg)](https://pub.dev/packages/pocketbase)\n======================================================================\n\nOfficial Multi-platform Dart SDK for interacting with the [PocketBase Web API](https://pocketbase.io/docs).\n\n- [Installation](#installation)\n- [Caveats](#caveats)\n    - [File upload](#file-upload)\n    - [RecordModel](#recordmodel)\n    - [Error handling](#error-handling)\n    - [AuthStore](#authstore)\n    - [Binding filter parameters](#binding-filter-parameters)\n- [Services](#services)\n- [Limitations](#limitations)\n- [Development](#development)\n\n\n## Installation\n\nAdd the library to your `dependencies`:\n\n```sh\ndart pub add pocketbase\n\n# or with Flutter:\nflutter pub add pocketbase\n```\n\nImport it in your Dart code:\n\n```dart\nimport 'package:pocketbase/pocketbase.dart';\n\nfinal pb = PocketBase('http://127.0.0.1:8090');\n\n...\n\n// authenticate as regular user\nfinal userData = await pb.collection('users').authWithPassword('test@example.com', '123456');\n\n// list and filter \"example\" collection records\nfinal result = await pb.collection('example').getList(\n  page:    1,\n  perPage: 20,\n  filter:  'status = true \u0026\u0026 created \u003e= \"2022-08-01\"',\n  sort:    '-created',\n  expand:  'someRelField',\n);\n\n// subscribe to realtime \"example\" collection changes\npb.collection('example').subscribe(\"*\", (e) {\n  print(e.action); // create, update, delete\n  print(e.record); // the changed record\n}, filter: \"someField \u003e 10\");\n\n// and much more...\n```\n\n\u003e More detailed API docs and copy-paste examples could be found in the [API documentation for each service](https://pocketbase.io/docs/api-authentication)\n\u003e or in the [Services section](#services) below.\n\n\n## Caveats\n\n#### File upload\n\nPocketBase Dart SDK handles file upload seamlessly by using `http.MultipartFile` list.\n\nHere is a simple example of uploading a single text file together with some other regular fields:\n\n```dart\nimport 'package:http/http.dart' as http;\nimport 'package:pocketbase/pocketbase.dart';\n\nfinal pb = PocketBase('http://127.0.0.1:8090');\n\npb.collection('example').create(\n  body: {\n    'title': 'Hello world!',\n    // ... any other regular field\n  },\n  files: [\n    http.MultipartFile.fromString(\n      'document', // the name of the file field\n      'example content...',\n      filename: 'example_document.txt',\n    ),\n  ],\n).then((record) {\n  print(record.id);\n  print(record.get\u003cString\u003e('title'));\n});\n```\n\n#### RecordModel\n\nThe SDK comes with several helpers to make it easier working with the `RecordService` and `RecordModel` DTO.\nYou could find more detailed documentation in the [`RecordModel` class reference](https://pub.dev/documentation/pocketbase/latest/pocketbase/RecordModel-class.html),\nbut below is an example how to access and cast record data values:\n\n```dart\nfinal record = await pb.collection('example').getOne('RECORD_ID');\n\nfinal options  = record.get\u003cList\u003cString\u003e\u003e('options');\nfinal email    = record.get\u003cString\u003e('email');\nfinal status   = record.get\u003cbool\u003e('status');\nfinal total    = record.get\u003cint\u003e('total');\nfinal price    = record.get\u003cdouble\u003e('price');\nfinal nested1  = record.get\u003cRecordModel\u003e('expand.user', null);\nfinal nested2  = record.get\u003cString\u003e('expand.user.title', 'N/A');\n```\n\nAlternatively, you can also create your own typed DTO data classes and use for example the `record.toJson()` to populate your object, eg:\n\n```dart\nimport \"package:pocketbase/pocketbase.dart\";\nimport 'package:json_annotation/json_annotation.dart';\n\npart 'task.g.dart';\n\n@JsonSerializable()\nclass Task {\n  Task({this.id = '', this.description = ''});\n\n  // type the collection fields you want to use...\n  final String id;\n  final String description;\n\n  /// Creates a new Task instance form the provided RecordModel.\n  factory Task.fromRecord(RecordModel record) =\u003e Task.fromJson(record.toJson());\n\n  /// Connect the generated [_$Task] function to the `fromJson` factory.\n  factory Task.fromJson(Map\u003cString, dynamic\u003e json) =\u003e _$Task(json);\n\n  /// Connect the generated [_$Task] function to the `toJson` method.\n  Map\u003cString, dynamic\u003e toJson() =\u003e _$Task(this);\n}\n\n...\n\n// fetch your raw record model\nfinal record = await pb.collection('tasks').getOne('TASK_ID');\n\nfinal task = Task.fromRecord(record);\n```\n\n#### Error handling\n\nAll services return a standard Future-based response, so the error handling is straightforward:\n\n```dart\npb.collection('example').getList(page: 1, perPage: 50).then((result) {\n  // success...\n  print('Result: $result');\n}).catchError((error) {\n  // error...\n  print('Error: $error');\n});\n\n// OR if you are using the async/await syntax:\ntry {\n  final result = await pb.collection('example').getList(page: 1, perPage: 50);\n} catch (error) {\n  print('Error: $error');\n}\n```\n\nAll response errors are normalized and wrapped as `ClientException` with the following public members that you could use:\n\n```dart\nClientException {\n    url            Uri     // The address of the failed request\n    statusCode     int     // The status code of the failed request\n    response       Map     // The JSON API error response\n    isAbort        bool    // Indicates whether the request was aborted/cancelled\n    originalError  dynamic // The original response error\n}\n```\n\n#### AuthStore\n\nThe SDK keeps track of the authenticated token and auth record for you via the `pb.authStore` service.\nThe default `AuthStore` class has the following public members that you could use:\n\n```dart\nAuthStore {\n    token:    String           // Getter for the stored auth token\n    record:   RecordModel|null // Getter for the stored auth RecordModel\n    isValid   bool             // Getter to loosely check if the store has an existing and unexpired token\n    onChange  Stream           // Stream that gets triggered on each auth store change\n\n    // methods\n    save(token, record)        // update the store with the new auth data\n    clear()                    // clears the current auth store state\n}\n```\n\nTo _\"logout\"_ an authenticated record, you can just call `pb.authStore.clear()`.\n\nTo _\"listen\"_ for changes in the auth store, you can _listen_ to the `onChange` broadcast stream:\n```dart\npb.authStore.onChange.listen((e) {\n  print(e.token);\n  print(e.record);\n});\n```\n\n**The default `AuthStore` is not persistent!**\n\nIf you want to persist the `AuthStore` state (eg. in case the app get closed), you can extend the default store and pass a new custom instance as constructor argument to the client.\nTo make it slightly easier, the SDK has a builtin `AsyncAuthStore` that you can combine with any async persistent layer (`shared_preferences`, `hive`, local file, etc.).\nHere is an example using Flutter's [`shared_preferences`](https://pub.dev/packages/shared_preferences):\n\n```dart\nfinal prefs = await SharedPreferences.getInstance();\n\nfinal store = AsyncAuthStore(\n save:    (String data) async =\u003e prefs.setString('pb_auth', data),\n initial: prefs.getString('pb_auth'),\n);\n\nfinal pb = PocketBase('http://example.com', authStore: store);\n```\n\n#### Binding filter parameters\n\nThe SDK comes with a helper `pb.filter(expr, params)` method to generate a filter string with placeholder parameters (`{:paramName}`) populated from a `Map`.\n\n```dart\nfinal records = await pb.collection('example').getList(filter: pb.filter(\n  // the same as: \"title ~ 'exa\\\\'mple' \u0026\u0026 created = '2023-10-18 18:20:00.123Z'\"\n  'title ~ {:title} \u0026\u0026 created \u003e= {:created}',\n  { \"title\": \"exa'mple\", \"created\": DateTime.now() },\n));\n```\n\nThe supported placeholder parameter values are:\n\n- `String` (_single quotes are autoescaped_)\n- `DateTime`\n- `bool`\n- `num`\n- `null`\n- everything else is converted to a string using `jsonEncode()`\n\n\n## Services\n\n#### RecordService ([Detailed class reference](https://pub.dev/documentation/pocketbase/latest/pocketbase/RecordService-class.html), [API docs](https://pocketbase.io/docs/api-records))\n\n###### _Crud handlers_\n\n```dart\n// Returns a paginated records list.\n🔓 pb.collection(collectionIdOrName).getList({page = 1, perPage = 30, filter?, sort?, expand?, fields?, query, headers});\n\n// Returns a list with all records batch fetched at once.\n🔓 pb.collection(collectionIdOrName).getFullList({batch = 100, filter?, sort?, expand?, fields?, query, headers});\n\n// Returns the first found record matching the specified filter.\n🔓 pb.collection(collectionIdOrName).getFirstListItem(filter, {expand?, fields?, query, headers});\n\n// Returns a single record by its id.\n🔓 pb.collection(collectionIdOrName).getOne(recordId, {expand?, fields?, query, headers});\n\n// Creates (aka. register) a new record.\n🔓 pb.collection(collectionIdOrName).create({body, files, expand?, fields?, query, headers});\n\n// Updates an existing record by its id.\n🔓 pb.collection(collectionIdOrName).update(recordId, {body, files, expand?, fields?, query, headers});\n\n// Deletes a single record by its id.\n🔓 pb.collection(collectionIdOrName).delete(recordId, {query, body, headers});\n```\n\n###### _Realtime handlers_\n\n```dart\n// Subscribe to realtime changes to the specified topic (\"*\" or recordId).\n//\n// It is safe to subscribe multiple times to the same topic.\n//\n// You can use the returned UnsubscribeFunc to remove a single registered subscription.\n// If you want to remove all subscriptions related to the topic use unsubscribe(topic).\n🔓 pb.collection(collectionIdOrName).subscribe(topic, callback, {filter?, expand?, fields?, query, headers});\n\n// Unsubscribe from all registered subscriptions to the specified topic (\"*\" or recordId).\n// If topic is not set, then it will remove all registered collection subscriptions.\n🔓 pb.collection(collectionIdOrName).unsubscribe([topic]);\n```\n\n###### _Auth handlers_\n\n\u003e Available only for \"auth\" type collections.\n\n```dart\n// Returns all available application auth methods.\n🔓 pb.collection(collectionIdOrName).listAuthMethods({query, headers});\n\n// Refreshes the current authenticated record model and auth token.\n🔐 pb.collection(collectionIdOrName).authRefresh({expand?, fields?, query, body, headers});\n\n// Authenticates a record with their username/email and password.\n🔓 pb.collection(collectionIdOrName).authWithPassword(usernameOrEmail, password, {expand?, fields?, query, body, headers});\n\n// Authenticates a record with OAuth2 provider without custom redirects, deeplinks or even page reload.\n🔓 pb.collection(collectionIdOrName).authWithOAuth2(provider, urlCallback {scopes, createData, expand?});\n\n// Authenticates a record with OAuth2 code.\n🔓 pb.collection(collectionIdOrName).authWithOAuth2Code(provider, code, codeVerifier, redirectURL, {createData?, expand?, fields?, query, body, headers});\n\n// Sends auth record OTP request to the provided email.\n🔓 pb.collection(collectionIdOrName).requestOTP(email, {query, body, headers});\n\n// Authenticates a record with OTP (email code).\n🔓 pb.collection(collectionIdOrName).authWithOTP(otpId, password, {expand?, fields?, query, body, headers});\n\n// Sends a user password reset email.\n🔓 pb.collection(collectionIdOrName).requestPasswordReset(email, {query, body, headers});\n\n// Confirms a record password reset request.\n🔓 pb.collection(collectionIdOrName).confirmPasswordReset(resetToken, newPassword, newPasswordConfirm, {expand?, fields?, query, body, headers});\n\n// Sends a record verification email request.\n🔓 pb.collection(collectionIdOrName).requestVerification(email, {query, body, headers});\n\n// Confirms a record email verification request.\n🔓 pb.collection(collectionIdOrName).confirmVerification(verificationToken, {expand?, fields?, query, body, headers});\n\n// Sends a record email change request to the provider email.\n🔐 pb.collection(collectionIdOrName).requestEmailChange(newEmail, {query, body, headers});\n\n// Confirms record new email address.\n🔓 pb.collection(collectionIdOrName).confirmEmailChange(emailChangeToken, userPassword, {expand?, fields?, query, body, headers});\n\n// Impersonate authenticates with the specified recordId and returns a new client with the received auth token in a memory store.\n🔐 pb.collection(collectionIdOrName).impersonate(recordId, duration, {expand?, fields?, query, body, headers});\n```\n\n---\n\n##### FileService ([Detailed class reference](https://pub.dev/documentation/pocketbase/latest/pocketbase/FileService-class.html))\n\n```js\n// Builds and returns an absolute record file url for the provided filename.\n🔓 pb.files.getURL(record, filename, {thumb?, token?, query, body, headers});\n\n// Requests a new private file access token for the current auth record.\n🔐 pb.files.getToken({query, body, headers});\n```\n\n---\n\n#### CollectionService ([Detailed class reference](https://pub.dev/documentation/pocketbase/latest/pocketbase/CollectionService-class.html), [API docs](https://pocketbase.io/docs/api-collections))\n\n```dart\n// Returns a paginated collections list.\n🔐 pb.collections.getList({page = 1, perPage = 30, filter?, sort?, query, headers});\n\n// Returns a list with all collections batch fetched at once.\n🔐 pb.collections.getFullList({batch = 100, filter?, sort?, query, headers});\n\n// Returns the first found collection matching the specified filter.\n🔐 pb.collections.getFirstListItem(filter, {query, headers});\n\n// Returns a single collection by its id or name.\n🔐 pb.collections.getOne(idOrName, {query, headers});\n\n// Creates (aka. register) a new collection.\n🔐 pb.collections.create({body, files, query, headers});\n\n// Updates an existing collection by its id or name.\n🔐 pb.collections.update(idOrName, {body, files, query, headers});\n\n// Deletes a single collection by its id or name.\n🔐 pb.collections.delete(idOrName, {query, body, headers});\n\n// Deletes all records associated with the specified collection.\n🔐 pb.collections.truncate(idOrName, {query, body, headers});\n\n// Imports the provided collections.\n🔐 pb.collections.import(collections, {deleteMissing=false, query, body, headers});\n\n// Returns type indexed map with scaffolded collection models populated with their default field values.\n🔐 pb.collections.getScaffolds({query, body, headers});\n```\n\n---\n\n#### LogService ([Detailed class reference](https://pub.dev/documentation/pocketbase/latest/pocketbase/LogService-class.html), [API docs](https://pocketbase.io/docs/api-logs))\n\n```dart\n// Returns a paginated logs list.\n🔐 pb.logs.getList({page = 1, perPage = 30, filter?, sort?, query, headers});\n\n// Returns a single log by its id.\n🔐 pb.logs.getOne(id, {query, headers});\n\n// Returns logs statistics.\n🔐 pb.logs.getStats({query, headers});\n```\n\n---\n\n#### SettingsService ([Detailed class reference](https://pub.dev/documentation/pocketbase/latest/pocketbase/SettingsService-class.html), [API docs](https://pocketbase.io/docs/api-settings))\n\n```dart\n// Returns a map with all available app settings.\n🔐 pb.settings.getAll({query, headers});\n\n// Bulk updates app settings.\n🔐 pb.settings.update({body, query, headers});\n\n// Performs a S3 storage connection test.\n🔐 pb.settings.testS3({body, query, headers});\n\n// Sends a test email (verification, password-reset, email-change).\n🔐 pb.settings.testEmail(toEmail, template, {collection, body, query, headers});\n\n// Generates a new Apple OAuth2 client secret.\n🔐 pb.settings.generateAppleClientSecret(clientId, teamId, keyId, privateKey, duration, {body, query, headers});\n```\n\n---\n\n#### RealtimeService ([Detailed class reference](https://pub.dev/documentation/pocketbase/latest/pocketbase/RealtimeService-class.html), [API docs](https://pocketbase.io/docs/api-realtime))\n\n\u003e This service is usually used with custom realtime actions.\n\u003e For records realtime subscriptions you can use the subscribe/unsubscribe\n\u003e methods available in the `pb.collection()` RecordService.\n\n```dart\n// Initialize the realtime connection (if not already) and register the subscription.\n//\n// You can subscribe to the `PB_CONNECT` event if you want to listen to the realtime connection connect/reconnect events.\n🔓 pb.realtime.subscribe(subscription, callback, {filter?, expand?, fields?, query, headers});\n\n// Unsubscribe from a subscription (if empty - unsubscibe from all registered subscriptions).\n🔓 pb.realtime.unsubscribe([subscription = '']);\n\n// Unsubscribe from all subscriptions starting with the provided prefix.\n🔓 pb.realtime.unsubscribeByPrefix(subscriptionsPrefix);\n\n// An optional hook that is invoked when the realtime client disconnects\n// either when unsubscribing from all subscriptions or when the connection\n// was interrupted or closed by the server.\n//\n// Note that the realtime client autoreconnect on its own and this hook is\n// useful only for the cases where you want to apply a special behavior on\n// server error or after closing the realtime connection.\npb.realtime.onDisconnect = (subscriptions) { ... }\n```\n\n---\n\n##### BackupService ([Detailed class reference](https://pub.dev/documentation/pocketbase/latest/pocketbase/BackupService-class.html), [API docs](https://pocketbase.io/docs/api-backups))\n\n```js\n// Returns list with all available backup files.\n🔐 pb.backups.getFullList({query, headers});\n\n// Initializes a new backup.\n🔐 pb.backups.create(basename, {body, query, headers});\n\n// Uploads an existing backup file (_the multipart file key is \"file\"_).\n🔐 pb.backups.upload(file, {body, query, headers});\n\n// Deletes a single backup by its file key.\n🔐 pb.backups.delete(key, {body, query, headers});\n\n// Initializes an app data restore from an existing backup.\n🔐 pb.backups.restore(key, {body, query, headers});\n\n// Builds a download url for a single existing backup using an\n// superuser file token and the backup file key.\n🔐 pb.backups.getDownloadURL(token, key, {query});\n```\n\n---\n\n##### CronService ([Detailed class reference](https://pub.dev/documentation/pocketbase/latest/pocketbase/CronService-class.html), [API docs](https://pocketbase.io/docs/api-crons))\n\n```js\n// Returns list with all registered app cron jobs.\n🔐 pb.crons.getFullList({query, headers});\n\n// Runs the specified cron job.\n🔐 pb.backups.run(jobId, {body, query, headers});\n```\n\n---\n\n##### HealthService  ([Detailed class reference](https://pub.dev/documentation/pocketbase/latest/pocketbase/HealthService-class.html), [API docs](https://pocketbase.io/docs/api-health))\n\n```dart\n// Checks the health status of the api.\n🔓 pb.health.check({query, headers});\n```\n\n---\n\n#### BatchService ([Detailed class reference](https://pub.dev/documentation/pocketbase/latest/pocketbase/BatchService-class.html), [API docs](https://pocketbase.io/docs/api-bach))\n\n```dart\n// create a new batch instance\nfinal batch = pb.createBatch();\n\n// register create/update/delete/upsert requests to the created batch\nbatch.collection('example1').create(body: { ... });\nbatch.collection('example2').update('RECORD_ID', body: { ... });\nbatch.collection('example3').delete('RECORD_ID');\nbatch.collection('example4').upsert(body: { ... });\n\n// send the batch request\nfinal result = await batch.send()\n```\n\n\n## Limitations\n\nPocketBase Dart SDK is built on top of the standard `dart-lang/http` package and inherits some of its limitations:\n\n- Requests cancellation/abort is not supported yet - [dart-lang/http #424](https://github.com/dart-lang/http/issues/424)\n\n\n## Development\n\n```sh\n# run the unit tests\ndart test\n\n# view dartdoc locally\ndart doc\n\n# run the example\ndart run example/example.dart\n\n# generate the DTOs json serializable artifacts\ndart run build_runner build\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpocketbase%2Fdart-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpocketbase%2Fdart-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpocketbase%2Fdart-sdk/lists"}