pocketbase_helpers 0.7.0 copy "pocketbase_helpers: ^0.7.0" to clipboard
pocketbase_helpers: ^0.7.0 copied to clipboard

Utilities for using typed data together with pocketbase.

pocketbase_helpers #

A Dart package that simplifies working with PocketBase using type-safe Dart models.

It provides helpers for collections, authentication, connection management, search utilities, file handling, and relation expansion.

The package is modular, you can use only the parts you need.


Features #

  • Type-safe models generated from PocketBase schema
  • Concise collection API wrapper
  • Authentication helpers
  • File and relation utilities
  • Keyword search across multiple fields
  • Connection manager with lifecycle hooks
  • Modular architecture

Quick Start #

1. Install the package #

dart pub add pocketbase pocketbase_helpers

Before writing any code, generate Dart models from your PocketBase schema.

Install the CLI:

dart pub global activate pocketbase_helpers_cli

Generate models:

pb_generate -s pb_schema.json -o lib/models.dart

This generates strongly typed models with built-in API helpers.

3. Use Your Generated Models #

You can use your models by opening a connection and calling the api.

import 'models.dart';

void main() async {
  PocketBaseConnection.open('http://127.0.0.1:8090');

  await Users.auth().withPassword('johndoe@gmail.com', 'supersecretpassword');

  if(User.isAuthenticated()){
    final blog = await Blogs.api().create(
      data: {'title': 'Powering flutter apps with pocketbase!'},
    );
  }

  //Connection should be closed at the end of your program
  PocketBaseConnection.close();
}

This is all you need to get started with this package, but if you want to learn about all the cool features this package has keep on reading!


Mental Model #

When using this package there are four main pieces:

Component Purpose
PocketBaseConnection Manages the global PocketBase instance
Model (User) Represents a single database record
Collection API (Users) Provides static helpers for interacting with the collection
CollectionHelper, AuthHelper, FileHelper, BaseHelper The underlying helpers that make the api calls

Example flow:

Users.api().getFullList()
  1. Users.api() returns a CollectionHelper<User>
  2. The helper performs the query through PocketBase
  3. Results are mapped to User models

These components can be mixed and matched, if you dont use the generator you can ignore the Model and CollectionAPI components. If you have your own PocketBase instance you can ignore the PocketBaseConnection component.


Index #


Connection Management #

PocketBaseConnection #

PocketBaseConnection manages a shared PocketBase instance.

PocketBaseConnection.open(
  'http://127.0.0.1:8090',
  lang: 'en-US',
  authStore: persistentAuthStore,
);

Access the active connection:

final pb = PocketBaseConnection.pb;

Close it when the application shuts down:

PocketBaseConnection.close();

Connection Hooks #

Hooks allow modifying data before create or update.

PocketBaseConnection.setHooks(
  preCreationHook: (collection, pb, map) {
    if (pb.authStore.isValid) {
      map['created_by'] = pb.authStore.record?.id;
    }
    return map;
  },
  preUpdateHook: (collection, pb, map) {
    if (pb.authStore.isValid) {
      map['updated_by'] = pb.authStore.record?.id;
    }
    return map;
  },
);

Reset hooks by returning the map immediately.


Generated Models #

The CLI generates two classes per collection.

Class Purpose
User Data model representing a record
Users Static API helper for interacting with the collection

Example for a users collection.


Entity Model #

The entity represents a record in the database. Below is an example of what such a record looks like.

class User implements PocketBaseRecord {
  final String id;
  final String email;

  factory User.fromMap(Map<String,dynamic> map);

  Map<String,dynamic> toMap();

  Url getFileUrl(String fileName);
}

Responsibilities:

  • Store record data
  • Convert between Dart objects and PocketBase JSON

Collection API #

The generator creates a companion class exposing static helpers.

final users = Users.api();

This returns a configured CollectionHelper<User>.

Equivalent manual setup:

CollectionHelper<User>(
  pocketBaseInstance: PocketBaseConnection.pb,
  collection: 'users',
  mapper: User.fromMap,
);

Generated Static Methods #

api() #

Returns a CollectionHelper for the collection.

final users = Users.api();

auth() #

Returns an authentication helper.

await Users.auth().withPassword(email, password);

Only available for auth collections.


File Field APIs #

Each file field generates a helper method.

Example:

Users.avatarApi(userId);

This returns a FileHelper.


Collection API #

CollectionHelper performs database operations for a collection.

CRUD Operations #

// fetch one
final user = await Users.api().getOne(id);

// fetch multiple
final users = await Users.api().getMultiple([id1, id2]);

// create
final newUser = await Users.api().create(data: {
  'email': 'user@example.com'
});

// update
await Users.api().update(
  user.copyWith(name: 'Jane')
);

// delete
await Users.api().delete(user.id);

Querying Data #

// Get a paginated list
await Users.api().getList(
  page: 1,
  perPage: 20,
  sort: '-created',
);
// get a full list
await Users.api().getFullList();
// get the first record matching the query or null if there was no match
await Users.api().getOneOrNull();
// count the records matching the query
await Users.api().count();

Filtering #

All queries support PocketBase filter and sorting expressions.

await Users.api().getList(
  expr: 'active = {:active}',
  params: {'active': true},
  sort: '-created,name',
);

Authentication #

Authentication is handled through AuthHelper.

final result = await Users.auth()
  .withPassword(email, password);

print(result.status);
print(result.record);

All authentication methods from the PocketBase SDK are supported.


Searching #

Search keywords across multiple fields.

await Products.api().search(
  keywords: ['phone', 'apple'],
  searchableFields: ['name','description'],
  page: 1,
  perPage: 20,
);

Additional filters can be added.

await Products.api().search(
  keywords: ['laptop'],
  searchableFields: ['name','description'],
  additionalExpressions: ['price > {:minPrice}'],
  additionalParams: {'minPrice': 500},
);

File Handling #

File fields are managed through FileHelper.

Generated helpers:

final avatar = Users.avatarApi(user.id);

Manual helper:

final avatar = Users.api().fileField(user.id, 'avatar');

Set a file:

await avatar.set('photo.jpg', bytes);

Remove a file:

await avatar.unset();

Multiple files:

await gallery.add('image1.jpg', bytes);
await gallery.remove('image1.jpg');
await gallery.removeAll();

File URLs:

user.getFileUrl(user.avatar);

Users.api().buildFileUrl(user.id, user.avatar);

Relation Expansions #

PocketBase supports expanding relations.

Models can map these directly.

Example:

class Post implements PocketBaseRecord {
  final String id;
  final String userId;
  final User user;
}

Configure mapping:

CollectionHelper(
  pocketBaseInstance: pb,
  collection: 'posts',
  mapper: Post.fromMap,
  expansions: {'user_id': 'user'},
);

Query:

final post = await helper.getOne(postId);

print(post.user.name);

Additional expansions can be specified per query.


Manual Models #

Helpers can also be used without the generator.

class User implements PocketBaseRecord {

  final String id;
  final String email;

  static User fromMap(Map<String,dynamic> map) {
    return User(
      id: map['id'],
      email: map['email'],
    );
  }

  @override
  Map<String,dynamic> toMap() => {
    'id': id,
    'email': email,
  };
}

Create a helper:

CollectionHelper(
  pocketBaseInstance: PocketBase('http://127.0.0.1:8090'),
  collection: 'users',
  mapper: User.fromMap,
);

Low-Level API #

BaseHelper provides minimal wrappers around PocketBase.

final helper = BaseHelper(
  pocketBaseInstance: pb,
);

await helper.getFullList(
  'users',
  mapper: User.fromMap,
);

Utilities #

HelperUtils contains helper functions.

// clean up a map, prunes empty strings and maps to work with dart null safety.
HelperUtils.cleanMap(rawMap);

// gets file names from a list of file urls
HelperUtils.getNamesFromUrls(urls);

// builds a sort string for sorting by a singular field.
HelperUtils.buildSortString('created', false);

// builds the expression and escaped parameters to preform a search query
// requires a list of keywords and searchable fields as parameters.
final (expr, params) = HelperUtils.buildQuery(
  ['apple','phone'],
  ['name','description'],
);

// build a file url for a file on a record
HelperUtils.buildFileUrl(collection, recordId, fileName);

Modular Usage #

You can use individual components if desired.

Full stack:

PocketBaseConnection.open(url);

await Users.api().getFullList();

Collection helper only:

CollectionHelper(...);

Low-level API:

BaseHelper(...);

Utilities only:

HelperUtils.cleanMap(data);

License #

MIT licensed.

Contributions and pull requests are welcome.

3
likes
0
points
576
downloads

Publisher

verified publishervanzwolsoftware.nl

Weekly Downloads

Utilities for using typed data together with pocketbase.

Repository (GitHub)
View/report issues

Topics

#pocketbase #models

License

unknown (license)

Dependencies

http, pocketbase

More

Packages that depend on pocketbase_helpers