Git Product home page Git Product logo

laravel-watermelon's Introduction

Laravel Watermelon

This package provides a Watermelon DB backend sync implementation for Laravel. Watermelon DB is a robust local database synchronization tool to help develop offline-first application. One of the biggest hurdles is implementing the logic on your server to handle the synchronization process.

That's where this package comes in to provide a quick synchronization route you can get up and running in minutes.

This project is still in active development and does not support schema versions or migrations yet. Both of these are major parts of the Watermelon DB spec. Please expect large changes at least until those features are implemented.

Installation

Before getting started you'll need to install the package and publish the config file.

composer require nathanheffley/laravel-watermelon
php artisan vendor:publish --tag="watermelon-config"

Usage

Once you've installed the package, you need to specify which models will be available through the synchronization endpoint. Open up the config/watermelon.php file and update the models array. The key needs to be the name of table used locally in your application, and the value must be classname of the related model.

You can also change the route to be something other than /sync by editing the config file or setting the WATERMELON_ROUTE environment variable. You will have to ensure your application makes synchronization requests to whatever route you specify.

By default, only your global middleware will be applied to the synchronization endpoint. This means that unless you changed the default global middleware in your Laravel project the synchronization endpoint will be unauthenticated. If you want to have access to the currently authenticated user you will need to add the web middleware to the config file's middleware array. If you want to restrict access to the synchronization endpoint to authenticated users only, you can add the auth middleware in addition to the web middleware. Of course, you can add any middleware you would like as long as it's registered in your project.

<?php

use App\Models\Project;
use App\Models\Task;

return [

    'route' => env('WATERMELON_ROUTE', '/watermelon'),
    
    'middleware' => [
        'web',
        'auth',
    ],

    'models' => [
         'projects' => Project::class,
         'tasks' => Task::class,
    ],

];

Once you've specified which models should be available through the synchronization endpoint, you'll need to implement some functionality in the models to support being served as Watermelon change objects.

You will need to add a database column to all of your models to keep track of what the Watermelon ID is, called watermelon_id. The default IDs generated by Watermelon are alphanumeric strings, although you can change the type of the column if you don't use the default IDs autogenerated by Watermelon. A unique index on the column is recommended, and I like placing it directly after the id column.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddWatermelonIdToTasksTable extends Migration
{
    public function up()
    {
        Schema::table('tasks', function (Blueprint $table) {
            $table->string('watermelon_id')->after('id')->unique();
        });
    }

    public function down()
    {
        Schema::table('tasks', function (Blueprint $table) {
            $table->dropColumn('watermelon_id');
        });
    }
}

If you did not originally include the created_at, updated_at, and deleted_at timestamp columns, you will also need to add those columns. Please refer to the Laravel documentation for implementing the timestamps and soft deleting functionality.

The only thing you must change in your model class is to use the Watermelon trait.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use NathanHeffley\LaravelWatermelon\Traits\Watermelon;

class Task extends Model
{
    use SoftDeletes, Watermelon;
}

The attributes returned through the synchronization endpoint are whitelisted by default. Out of the box, only the watermelon_id will be returned (although it will be passed through the endpoint as just id, this is intentional). To include more attributes, you will need to add a watermelonAttributes property to your class. These attributes will be included alongside the Watermelon ID and can be updated by change objects posted to the synchronization endpoint.

class Task extends Model
{
    use SoftDeletes, Watermelon;

    protected array $watermelonAttributes = [
        'content',
        'is_completed',
    ];
}

If you need more control over the attributes returned you can override the entire toWatermelonArray function.

Authorization

By default, all models will be accessible and able to be updated through the synchronization endpoint. This is obviously not ideal in most projects where you need control to authorize which models users can see and what they can update.

Scoping entire records

You can implement a query scope on your models by overriding the scopeWatermelon function. This scope will be applied before returning data to pull requests. This can be used, for example, to restrict records to only be retrievable by users authorized to see them (to have access to the Auth::user() like in this example, don't forget to add the web and auth middlewares as shown in the config example at the start of the Usage section).

use Illuminate\Support\Facades\Auth;

class Task extends Model
{
    // ...

    public function scopeWatermelon($query)
    {
        return $query->where('user_id', Auth::user()->id);
    }
}

Package Development

If you have PHP and Composer installed on your local machine you should be able to easily run the PHPUnit test suite.

./vendor/bin/phpunit

If you prefer to run the tests within a Docker container, this project includes Laravel Sail.

To install the dependencies:

docker run --rm \
    -u "$(id -u):$(id -g)" \
    -v $(pwd):/opt \
    -w /opt \
    laravelsail/php80-composer:latest \
    composer install --ignore-platform-reqs

docker-compose up -d
sail exec laravel.test ./vendor/bin/phpunit

laravel-watermelon's People

Contributors

bilalswiftsolutions avatar nathanheffley avatar sroske avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

laravel-watermelon's Issues

Link Watermelon demos in README

@doobe01 pointed out that the nathanheffley/laravel-watermelom-demos isn't linked in the README anywhere. A link to that repo should definitely be added near the top of the README.

currently push() method is not working as expected for me is this the case with anyone else as well?

when data was pushed from local it was not updating watermelon_id column in db. when i start debuging

I see that in package controller i have to get data like this?

 public function push(SyncService $watermelon, Request $request): JsonResponse
    {
        **return response()->json( $request->json()->all());**
        return $watermelon->push($request);
    }

otherwise in SeyncService it was always returned from foreach loop

public function push(Request $request): JsonResponse
    {
       
        // DB::beginTransaction();

        foreach ($this->models as $name => $class) {
           
            if (!$request->input($name)) {
                continue;
            }   
 }

this problem is with me only or anyone else is also having this issue?
because i can not believe this should happen like this, it must be working for you guys.
what am i doing wrong here?

i didn't customized client side functions as well those are as same provided by library

Watermelon_ID Not Syncing to Backend DB

I have implemented your sync adapter and doing some tests with my react-native app. I cannot get the watermelon_id to populate in my MySQL database. Maybe I am not understanding how this works. I have a sync button in my app that successfully pulls the data from my backend database to WatermelonDB. But if I change anything on the backend and try to sync it does not update the data on the app. Am I missing something? Thanks much!

Compatibility with Laravel 10

Hello guys.

It seems this package is not able to be installed on Laravel 10 with PHP 8.2. Will you be updating it for Laravel 10?

image

Many thanks!

Migrations support

Hi!

This package support migrations implementation? I did a test here but the new columns who I've added aren't pulled then sync.

Incorrect date formatting created_at

I'm trying this package, but it doesnt seem to work when pushing changes:

Incorrect datetime value: '56578-08-03 05:33:14' for column 'created_at' at row 1

Laravel 11 support

Can't really install the package in Laravel 11, would provide a PR, but don't really know what needs to be changed to make it installable and I don't know what to change to make it compatible with Laravel 9,10 and 11 at the same time.

This is the error message from composer:

 Problem 1
    - nathanheffley/laravel-watermelon[v0.0.1, ..., v0.0.2] require illuminate/database ^8.0 -> found illuminate/database[v8.0.0, ..., v8.83.27] but these were not loaded, likely because it conflicts with another require.
    - nathanheffley/laravel-watermelon[v0.0.3, v1.0.0] require illuminate/database ^10.13.2 -> found illuminate/database[v10.13.2, ..., v10.48.4] but these were not loaded, likely because it conflicts with another require.
    - Root composer.json requires nathanheffley/laravel-watermelon * -> satisfiable by nathanheffley/laravel-watermelon[v0.0.1, v0.0.2, v0.0.3, v1.0.0].

Laravel accessors and mutators does not work as expected when eloquent model is syncable

Currently, I've encountered an issue where the use of accessors and mutators during record synchronization modifies records, leading to unexpected bugs. Is there any way to to leverage these functionalities (accessors and mutators ) for web actions (modify model from website ) not for syncing.

Model :

class TimeRecord extends Model
{
    use SoftDeletes, HasUuids, Watermelon;

    protected $guarded = [];

    protected array $watermelonAttributes = [
        'time_record_guid',
        'employee_guid',
        'employee_name_last_name_first',
        'work_date',
    ];

    protected function workDate(): Attribute
    {
        return Attribute::make(
            get: fn($value) => formatDateUserTz($value, 'm/d/Y'),
            set: fn($value) => strtotime($value)
        );
    }

}


Controller :

  public function update(Request $request, TimeRecord $timeRecord)
    {

        $timeRecord->work_date = strtotime($request->work_date);

        $timeRecord->save();
    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.