atproto 0.2.9 copy "atproto: ^0.2.9" to clipboard
atproto: ^0.2.9 copied to clipboard

The easiest and powerful Dart/Flutter library for AT Protocol.

atproto

The Easiest and Powerful Dart/Flutter Library for AT Protocol 🎯


GitHub Sponsor GitHub Sponsor

pub package Dart SDK Version CICD codecov Issues Pull Requests Stars Contributors Last Commits License Contributor Covenant


1. Guide 🌎 #

This library provides the easiest way to use AT Protocol in Dart and Flutter apps.

Show some ❤️ and star the repo to support the project.

This package provides the most basic features of AT Protocol. If you want to use Bluesky's API, please use bluesky!

Also, the core HTTP request portion of this package is also provided in the atproto_core and xrpc packages.

1.1. Features 💎 #

✅ The wrapper library for AT Protocol.
Easily integrates with the Dart & Flutter apps.
✅ Provides response objects with a guaranteed safe types.
Well documented and well tested.
✅ Supports the powerful automatic retry.

1.2. Getting Started ⚡ #

1.2.1. Install Library #

With Dart:

 dart pub add atproto

Or With Flutter:

 flutter pub add atproto

1.2.2. Import #

import 'package:atproto/atproto.dart';

1.2.3. Implementation #

import 'package:atproto/atproto.dart' as atp;

Future<void> main() async {
  try {
    //! First you need to establish session with ATP server.
    final session = await atp.createSession(
      service: 'SERVICE_NAME', //! The default is `bsky.social`
      identifier: 'YOUR_HANDLE_OR_EMAIL', //! Like `shinyakato.bsky.social`
      password: 'YOUR_PASSWORD',
    );

    print(session);

    final atproto = atp.ATProto.fromSession(
      session.data,

      //! Automatic retry is available when server error or network error occurs
      //! when communicating with the API.
      retryConfig: atp.RetryConfig(
        maxAttempts: 5,
        jitter: atp.Jitter(
          minInSeconds: 2,
          maxInSeconds: 5,
        ),
        onExecute: (event) => print(
          'Retry after ${event.intervalInSeconds} seconds...'
          '[${event.retryCount} times]',
        ),
      ),

      //! The default timeout is 10 seconds.
      timeout: Duration(seconds: 20),
    );

    //! Create a record to specific service.
    final createdRecord = await atproto.repositories.createRecord(
      collection: atp.NSID.create(
        'feed.bsky.app',
        'post',
      ),
      record: {
        'text': 'Hello, Bluesky!',
        "createdAt": DateTime.now().toUtc().toIso8601String(),
      },
    );

    //! And delete it.
    await atproto.repositories.deleteRecord(
      uri: createdRecord.data.uri,
    );

    //! You can use Stream API easily.
    final subscription = await atproto.sync.subscribeRepoUpdates();
    subscription.data.stream.listen((event) {
      print(event.toJson());
    });
  } on atp.UnauthorizedException catch (e) {
    print(e);
  } on atp.XRPCException catch (e) {
    print(e);
  }
}

1.3. Supported Lexicons 👀 #

1.3.1. Servers #

Lexicon Method Name
POST com.atproto.server.createSession createSession
POST com.atproto.server.refreshSession refreshSession
GET com.atproto.server.getSession findCurrentSession
POST com.atproto.server.createAccount createAccount
POST com.atproto.server.requestDeleteAccount requestDeleteAccount
POST com.atproto.server.deleteAccount deleteAccount
POST com.atproto.server.createInviteCode createInviteCode
GET com.atproto.server.getAccountInviteCodes findInviteCodes
POST com.atproto.server.requestPasswordReset requestPasswordReset
POST com.atproto.server.resetPassword updatePassword
POST com.atproto.server.createAppPassword createAppPassword
POST com.atproto.server.revokeAppPassword deleteAppPassword
GET com.atproto.server.listAppPasswords findAppPasswords

1.3.2. Identity #

Lexicon Method Name
GET com.atproto.identity.resolveHandle findDID
POST com.atproto.identity.updateHandle updateHandle

1.3.3. Repository #

Lexicon Method Name
POST com.atproto.repo.createRecord createRecord
GET com.atproto.repo.getRecord findRecord
POST com.atproto.repo.deleteRecord deleteRecord
POST com.atproto.repo.putRecord updateRecord
POST com.atproto.repo.uploadBlob uploadBlob
GET com.atproto.repo.describeRepo findRepo

1.3.4. Moderation #

Lexicon Method Name
POST com.atproto.moderation.createReport createReport

1.3.5. Sync #

Lexicon Method Name
com.atproto.sync.subscribeRepos subscribeRepos

1.4. Tips 🏄 #

1.4.1. Method Names #

atproto uses the following standard prefixes depending on endpoint characteristics. So it's very easy to find the method corresponding to the endpoint you want to use!

Prefix Description
find This prefix is attached to endpoints that reference post etc.
search This prefix is attached to endpoints that perform extensive searches.
subscribe This prefix is attached to endpoints with high-performance streaming.
create This prefix is attached to the endpoint performing the create state.
refresh This prefix is attached to the endpoint performing the refresh state.
delete This prefix is attached to the endpoint performing the delete state.
update This prefix is attached to the endpoint performing the update state.
upload This prefix is attached to the endpoint performing the upload contents.
request This prefix is attached to the endpoint performing the request via email.

1.4.2. Null Parameter at Request #

In this library, parameters that are not required at request time, i.e., optional parameters, are defined as nullable. However, developers do not need to be aware of the null parameter when sending requests when using this library.

It means the parameters specified with a null value are safely removed and ignored before the request is sent.

1.4.3. Change the Timeout Duration #

The library specifies a default timeout of 10 seconds for all API communications.

However, there may be times when you wish to specify an arbitrary timeout duration. If there is such a demand, an arbitrary timeout duration can be specified as follows.

import 'package:atproto/atproto.dart' as atp;

Future<void> main() async {
  final atproto = atp.ATProto(
    did: 'YOUR_DID',
    accessJwt: 'YOUR_TOKEN',

    //! The default timeout is 10 seconds.
    timeout: Duration(seconds: 20),
  );
}

1.4.4. Automatic Retry #

Due to the nature of this library's communication with external systems, timeouts may occur due to inevitable communication failures or temporary crashes of the server to which requests are sent.

When such timeouts occur, an effective countermeasure in many cases is to send the request again after a certain interval. And atproto provides an automatic retry feature as a solution to this problem.

Also, errors subject to retry are as follows.

  • When the status code of the response returned from ATP server is 500 or 503.
  • When the network is temporarily lost and a SocketException is thrown.
  • When communication times out temporarily and a TimeoutException is thrown

1.4.4.1. Exponential Backoff and Jitter

Although the algorithm introduced earlier that exponentially increases the retry interval is already powerful, some may believe that it is not yet sufficient to distribute the sensation of retries. It's more distributed than equally spaced retries, but retries still occur at static intervals.

This problem can be solved by adding a random number called Jitter, and this method is called the Exponential Backoff and Jitter algorithm. By adding a random number to the exponentially increasing retry interval, the retry interval can be distributed more flexibly.

Similar to the previous example, atproto can be implemented as follows.

import 'package:atproto/atproto.dart' as atp;

Future<void> main() async {
  final atproto = atp.ATProto(
    did: 'YOUR_DID',
    accessJwt: 'YOUR_TOKEN',

    //! Add these lines.
    retryConfig: atp.RetryConfig(
      maxAttempts: 3,
    ),
  );
}

In the above implementation, the interval increases exponentially for each retry count with jitter. It can be expressed by next formula.

(2 ^ retryCount) + jitter(Random Number between 0 ~ 3)

1.4.4.2. Do Something on Retry

It would be useful to output logging on retries and a popup notifying the user that a retry has been executed. So atproto provides callbacks that can perform arbitrary processing when retries are executed.

It can be implemented as follows.

import 'package:atproto/atproto.dart' as atp;

Future<void> main() async {
  final atproto = atp.ATProto(
    did: 'YOUR_DID',
    accessJwt: 'YOUR_TOKEN',

    retryConfig: atp.RetryConfig(
      maxAttempts: 3,

      //! Add this line.
      onExecute: (event) => print('Retrying... ${event.retryCount} times.'),
    ),
  );
}

The RetryEvent passed to the callback contains information on retries.

1.4.5. Thrown Exceptions #

atproto provides a convenient exception object for easy handling of exceptional responses and errors returned from AT Protocol.

Exception Description
XRPCException Parent class for all the following Exceptions.
UnauthorizedException Thrown when authentication fails with the specified access token.
RateLimitExceededException Thrown when the rate limit is reached.
InvalidRequestException Thrown when request parameters are invalid.
InternalServerErrorException Thrown when a failure occurs on the ATP server.

Also, all of the above exceptions thrown from the atproto process extend XRPCException. This means that you can take all exceptions as XRPCException or handle them as certain exception types, depending on the situation.

However note that, if you receive an individual type exception, be sure to define the process so that the individual exception type is cached before XRPCException. Otherwise, certain type exceptions will also be caught as XRPCException.

Therefore, if you need to catch a specific type of exception in addition to XRPCException, be sure to catch XRPCException in the bottom catch clause as in the following example.

import 'package:atproto/atproto.dart' as atp;

Future<void> main() async {
  final atproto = atp.ATProto(
    did: 'YOUR_DID',
    accessJwt: 'YOUR_TOKEN',
  );

  try {
    final response = await atproto.sessions.getCurrentSession();

    print(response);
  } on atp.UnauthorizedException catch (e) {
    print(e);
  } on atp.XRPCException catch (e) {
    print(e);
  }
}

1.5. Contribution 🏆 #

If you would like to contribute to atproto, please create an issue or create a Pull Request.

There are many ways to contribute to the OSS. For example, the following subjects can be considered:

  • There are request parameters or response fields that are not implemented.
  • Documentation is outdated or incomplete.
  • Have a better way or idea to achieve the functionality.
  • etc...

You can see more details from resources below:

Or you can create a discussion if you like.

Feel free to join this development, diverse opinions make software better!

1.6. Support ❤️ #

The simplest way to show us your support is by giving the project a star at GitHub and Pub.dev.

You can also support this project by becoming a sponsor on GitHub:

You can also show on your repository that your app is made with atproto by using one of the following badges:

Powered by atproto Powered by atproto Powered by atproto

[![Powered by atproto](https://img.shields.io/badge/Powered%20by-atproto-00acee.svg)](https://github.com/myConsciousness/atproto.dart)
[![Powered by atproto](https://img.shields.io/badge/Powered%20by-atproto-00acee.svg?style=flat-square)](https://github.com/myConsciousness/atproto.dart)
[![Powered by atproto](https://img.shields.io/badge/Powered%20by-atproto-00acee.svg?style=for-the-badge)](https://github.com/myConsciousness/atproto.dart)

1.7. License 🔑 #

All resources of atproto is provided under the BSD-3 license.

Copyright 2023 Shinya Kato. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided the conditions.

Note
License notices in the source are strictly validated based on .github/header-checker-lint.yml. Please check header-checker-lint.yml for the permitted standards.

1.8. More Information 🧐 #

atproto was designed and implemented by Shinya Kato (@myConsciousness).

12
likes
0
pub points
48%
popularity

Publisher

verified publisheratprotodart.com

The easiest and powerful Dart/Flutter library for AT Protocol.

Repository (GitHub)
View/report issues

Funding

Consider supporting this project:

github.com

License

unknown (LICENSE)

Dependencies

atproto_core, freezed_annotation, json_annotation

More

Packages that depend on atproto