supapod 1.0.2 copy "supapod: ^1.0.2" to clipboard
supapod: ^1.0.2 copied to clipboard

Seamlessly integrate Supabase into your Serverpod applications.

Supapod : supabase πŸš€ + serverpod 🐎 = πŸ”₯ #

pub package License: MIT

Seamlessly integrate Supabase into your Serverpod applications. Use Supabase as your primary database backend with familiar Serverpod-style syntax, and get full access to Supabase's powerful features like Authentication, Realtime, and Storage.

supapod acts as a compatibility layer, allowing you to leverage Serverpod's code generation for models and table definitions while interacting with a Supabase database.

Features #

  • Serverpod-like Database Operations: Use familiar methods like insertRow, findFirstRow, find, updateRow, deleteRow directly on your Supabase tables.
  • Leverages Serverpod's Code Generation: Supapod intelligently uses the table and column definitions generated by Serverpod (*.generated.dart files) for type-safe queries and correct data mapping.
  • Full Supabase SDK Access: Easily access other Supabase services:
    • Supabase.instance.auth for user authentication.
    • Supabase.instance.storage for file storage.
    • Supabase.instance.realtime for live data synchronization.
    • Supabase.instance.functions for serverless functions.
  • Easy Setup: Minimal configuration to get started.

Why Supapod? #

  • Best of Both Worlds: Combine Serverpod's robust server-side framework and code generation with Supabase's managed backend-as-a-service features.
  • Familiar Syntax: If you're used to Serverpod's database interaction, supapod provides a very similar experience for Supabase, reducing the learning curve.
  • Rapid Development: Quickly build powerful backends by leveraging Supabase's out-of-the-box solutions for common needs.

Prerequisites #

  1. A Serverpod project.
  2. A Supabase project: You'll need your Supabase Project URL and Anon Key.
  3. Important: Your Supabase tables and columns should match the structure defined in your Serverpod model files (*.spy.yaml). supapod uses Serverpod's generated code for table/column names and types but does not handle schema migrations to Supabase. You need to ensure your Supabase schema is compatible.

Installation #

  1. Add supapod to your Serverpod project's pubspec.yaml file in the dependencies section:

    dependencies:
      serverpod: # your serverpod version
      supapod: ^latest_version # Replace with the latest version from pub.flutter-io.cn
    
  2. Run dart pub get in your Serverpod project's root directory.

Setup #

Initialize Supabase when your Serverpod server starts. This is typically done in your server.dart file.

// server.dart
import 'package:serverpod/serverpod.dart';
import 'package:supapod/supapod.dart'; // Main supapod import

import 'src/generated/protocol.dart';
import 'src/generated/endpoints.dart';

// This will initialize the Supabase client
Future<void> initializeSupabase() async {
  const supabaseUrl = 'YOUR_SUPABASE_URL';        // Replace with your Supabase Project URL
  const supabaseAnonKey = 'YOUR_SUPABASE_ANON_KEY'; // Replace with your Supabase Anon Key

  await Supabase.initialize(
    url: supabaseUrl,
    anonKey: supabaseAnonKey,
    // Optional:
    // authOptions: const AuthClientOptions(),
    // debug: true,
  );
  print('Supabase initialized!');
}

void run(List<String> args) async {
  // Initialize Supabase BEFORE Serverpod starts
  await initializeSupabase();

  // Initialize Serverpod and connect it with arguments.
  final pod = Serverpod(
    args,
    Protocol(),
    Endpoints(),
  );

  // Start the server.
  await pod.start();
}

Usage Example #

Let's assume you have a Serverpod model defined in greeting.spy.yaml in serverpod:

# greeting.spy.yaml

class: Greeting
table: greeting # This will be the table name in Supabase
fields:
  message: String
  author: String
  timestamp: DateTime

After running serverpod generate, you'll have Greeting and GreetingTable models available.

Here's how you can use supapod in an endpoint:

// initialize.dart

import 'greeting.dart';
import 'package:supapod/supapod.dart';
import 'package:supapod/supapod.dart' show Supabase, SupabaseRepository;

void initializeSupabase() {
  Supabase.initialize(
    supabaseUrl: 'SUPABASE_URL',
    supabaseAnonKey: 'SUPABASE_ANON_KEY',
  );

  var greetingInstance = GreetingSupabaseRepository(Greeting.t);
  Supabase.register<Greeting>(Greeting.t, greetingInstance);

  // --- Initialize all your auto-generated Models here like above ---
}

// --- Initialize all your auto-generated Models here like above ---

class GreetingSupabaseRepository extends SupabaseRepository<Greeting> {
  GreetingSupabaseRepository(super._table);
}
// greeting_endpoint.dart
import 'package:serverpod/serverpod.dart';
import 'package:supapod/supapod.dart'; // Import supapod

// Import your Serverpod generated model
import '../generated/greeting.dart';

class GreetingEndpoint extends Endpoint {
  Future<Greeting> hello(Session session, String name) async {
    final greeting = Greeting(
      message: 'Hello $name from Supapod!',
      author: 'Supapod User',
      timestamp: DateTime.now().toUtc(),
    );

    // The usual command in serverpod to interact with postgres database
    Greeting.db.insertRow(session, greeting);
    Greeting.db.findFirstRow(session, where: (t) => t.author.equals('John Doe'));
    
    // supapod command to interact with supabase database
    Supabase.db<Greeting>()?.insertRow(session, greeting);
    
    // Supapod internally handles the tables and columns as well from the auto-generated code from serverpod
    // so you can expect column names and types to be correct
    Supabase.db<Greeting>()?.findFirstRow(session, where: (t) => (t as GreetingTable).author.equals('John Doe'));
    
    // with obviously all the goodies that supabase provides like Auth, Realtime, Storage
    Supabase.instance.storage.from('avatars').getPublicUrl('public/avatar1.png');

    return greeting;
  }
}

How Supabase.db<T>() works: #

  • Supabase.db<YourModel>() gives you a specialized database handler for your YourModel type.
  • This handler uses Serverpod's generated YourModelTable (e.g., GreetingTable) to understand the table structure, column names, and data types.
  • When you write where: (t) => (t as YourModelTable).columnName.equals('value'), supapod translates this into a Supabase query filter.

Supported Operations #

Supabase.db<T>() aims to support common operations:

  • insertRow(session, object)
  • insertRows(session, objects)
  • findFirstRow(session, where: ..., orderBy: ..., orderDescending: ..., offset: ...)
  • find(session, where: ..., orderBy: ..., orderDescending: ..., limit: ..., offset: ...)
  • findById(session, id)
  • updateRow(session, object)
  • updateRows(session, objects)
  • deleteRow(session, where: ...)
  • deleteRows(session, where: ...)
  • count(session, where: ...)

Important Considerations #

  • Schema Management: As mentioned, supapod does not handle database schema migrations. You can ensure your Supabase database schema (table names, column names, types, constraints, RLS policies) matches your Serverpod model definitions with the serverpod --apply-migration on the supabase database directly.
  • Row Level Security (RLS): Leverage Supabase's powerful RLS policies for fine-grained access control. supapod operations will respect these policies. Ensure your RLS is set up correctly for the operations your server intends to perform.
  • Transactions: Supabase itself doesn't offer multi-statement transactions in the same way traditional SQL databases do over a single client connection. If you need atomicity for multiple operations, you'll typically use Supabase Edge Functions (Database Functions - plpgsql). supapod itself won't provide cross-table transactions since the underlying Supabase client doesn't.
  • Error Handling: Wrap Supabase.db calls and Supabase.instance calls in try-catch blocks to handle potential errors from Supabase (e.g., network issues, RLS violations, data conflicts).

Contributing #

Contributions are welcome! If you'd like to contribute, please:

  1. Fork the repository.
  2. Create a new branch for your feature or bug fix.
  3. Make your changes.
  4. Add tests for your changes.
  5. Ensure all tests pass.
  6. Submit a pull request with a clear description of your changes.

License #

This package is licensed under the MIT License - see the LICENSE file for details

2
likes
150
points
46
downloads

Publisher

verified publisheryashmakan.com

Weekly Downloads

Seamlessly integrate Supabase into your Serverpod applications.

Repository (GitHub)
View/report issues

Topics

#serverpod #supabase #database

Documentation

API reference

License

MIT (license)

Dependencies

serverpod, supabase

More

Packages that depend on supapod