Coder Social home page Coder Social logo

milroyfraser / sarala Goto Github PK

View Code? Open in Web Editor NEW
110.0 110.0 8.0 455 KB

Javascript library to communicate with RESTful API built following JSON API specification. inspired by Laravel’s Eloquent

License: MIT License

JavaScript 99.85% Shell 0.15%
eloquent javascript json-api laravel orm restful-api

sarala's People

Contributors

aidan-casey avatar ishiahirake avatar milroyfraser 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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

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

sarala's Issues

Cannot read property 'self' of undefined

When trying to save updated resource:
Uncaught TypeError: Cannot read property 'self' of undefined in Model.js:223

Looks like it tries to access url: this.links.self,, but my API response does not contain links.self when I fetch resources with all() or paginate().

I think we should try to get/build PUT url different way.

What do you think?

Set a customized property in Model subclass will affect the other.

When set a customized property in JSON:API's response collection Model, it will affect all other model in the collection, since the customized property won't be copied when hydrate the model.

For example:

export default class Post extends Model {
    constructor () {
        super()

        this.metadata = []
    }

    resourceName () {
        return 'posts'
    }

    fields () {
        return ['title', 'subtitle', 'body', 'slug']
    }
}

// 

let result = await (new Post()).all()

let post1 = result.data[0]
let post2 = result.data[1]

// Set metadata of post1 to ['cool']
post1.metadata.push('cool')

expect(post1.metadata).toEqual(['cool'])
// Except metadata of post2 to be [], but got ['cool']
expect(post2.metadata).toEqual([])

Have to access relation through .data?

I'm in the process of mocking a front-end dashboard, and I'm feeding fake data into Sarala. I have the following relationship structure:

User

  • relationships
    -- parkingAuthorities

Once the data comes back, I can't just access user.parkingAuthorities to get the relationship collection. I have to to access user.parkingAuthorities.data. This seems odd and doesn't follow the Laravel relationship collection pattern.

Is this intended? Am I perhaps doing something wrong?

There's no documentation on how to actually use/access the relationships; just on how to define them and fetch them.

JSON API for LARAVEL

What package do you use on Laravel for handling JSON API specs suported by sarala ?

how to POST with relationship

https://jsonapi.org/format/#crud-creating

how do i send post request with relationships

POST /photos HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "data": {
    "type": "photos",
    "attributes": {
      "title": "Ember Hamster",
      "src": "http://example.com/images/productivity.png"
    },
    "relationships": {
      "photographer": {
        "data": { "type": "people", "id": "9" }
      }
    }
  }
}

Empty or invalid date passed to server

When an empty or invalid date is set, it's value is passed as "Invalid date" to the JSON API server.

I'd recommend changing the code on line 337 from:

forOwn(this.dates(), (format, field) => {
    if (!isUndefined(this[field])) {
        data[field] = moment(this[field]).format(format)
    }
})

to:

forOwn(this.dates(), (format, field) => {
    if (isUndefined(this[field])) {
        return false
    }

    var date = moment(this[field])

    if (!date.isValid()) {
        date = null
    } else {
        date = date.format(format)
    }
    
    data[field] = date
})

If you'd like to stay away from automatically correcting the date, an exception could just as easily be thrown.

API Documentation missing

Hi Milroy,

You explain very well how to properly configure the javascript models, however there's nothing that can help me configuring a proper format for the response from my API. Both, a single resource and a collection are working fine, I'm struggling with the relationships though. I'm using the Laravel's Resources, and I tried to reverse engineer the json-formatter to find out the right format, but I could not.

Here is an exampe of my response(s):

public function toArray($request): array
{
    return [
        'id' => $this->id,
        'type' => 'whatever_type',
        'attributes' => [
            'my' => 'data', // that's working fine, it's my data
            // Attempt 1: this next line doesn't fill my JS model
            'rel_1' => new MyRelResource($this->rel_1)->toArray($request)
            // Attempt 2: nothing either:
            'rel_2' => ['data' => new MyRelResource($this->rel_2)->toArray($request)
        ],
        'relationships' => [
            // Attampt 3: The line below doesn't fill my relationship in the JS model either
            'rel_3' => new MyRelResource($this->rel_3)->toArray($request)
            // Attempt 4: still not getting the JS model filled:
            'rel_4' => ['data' => new MyRelResource($this->rel_4)->toArray($request)
        ]
    ];
}

I also tried adding the rel_ properties at the same level than the attributes property with no result.

What is the exact format I need to follow in order to get my relationships filled in the front end? I followed a link from other issue where you reference the good practices in a API, but couldn't achieve anything either.

Thanks, and thanks for the package

Collection of Models have empty properties

Hi, really excited for the potential of the package!

I'm using the sarala-io/laravel-companion but with Laravel's API Resources for the API. My model is set up like so:

My model:

import Model from './BaseAdminModel';

export default class VendorRequest extends Model {
    resourceName () {
        return 'vendor-requests';
    }

    fields () {
        return [
            'vendor',
            'category',
            'status_code',
            'success',
            'response_attributes'
        ];
    }

    dates () {
        return {
            created_at: 'YYYY-MM-DD H:i:s',
            updated_at: 'YYYY-MM-DD H:i:s',
        };
    }
}

Usage in Vue Component:

//
getResources() {
    this.isLoading = true;
    const vendorRequest = new VendorRequest();

    vendorRequest.all().then((data) => {
        this.resources = data.data;
        console.log(data.data);
    }, () => {
        this.hasError = true;
        this.errorMessage = 'Could not retrieve resources';
    }).then(() => { this.isLoading = false; });
}
//

I can see the API response in the Network tab of Chrome:

{
  "data":[
    {
      "vendor":"odds-api",
      "category":"sports",
      "status_code":200,
      "success":true,
      "response_attributes":{
        "requests_remaining":"149",
        "requests_used":"1"
      },
      "created_at":"2018-03-25 06:06:44",
      "updated_at":"2018-03-25 06:06:46"
    },
    {
      "vendor":"odds-api",
      "category":"sports",
      "status_code":200,
      "success":true,
      "response_attributes":{
        "requests_remaining":"149",
        "requests_used":"1"
      },
      "created_at":"2018-03-25 06:53:35",
      "updated_at":"2018-03-25 06:53:37"
    }
  ]
}

And the console.log(data.data); within the Promise outputs correctly an array of two VendorRequest models, however the properties are not hydrated:

screen shot 2018-03-25 at 08 25 36

Any help would be much appreciated

Invalid Method of Updating Relationships

The code used to update a relationship does not appear to be within JSON:API spec. It violates it in two ways.

  1. PATCH requests should allow a relationship to be updated within them.
  2. The current code sends a POST request to {{selfUrl}}/{{modelType}}/{{modelID}}, when it should POST a request body to {{selfUrl}}/relationships/{{relationshipName}}

https://jsonapi.org/format/#crud-updating-resource-relationships
https://jsonapi.org/format/#crud-updating-relationships

No Support for Persist Requests with No Content

The makePersistRequest function assumes there will be data on return, which will in turn throw an error when making a POST or DELETE request that returns 204 as listed in the JSON:API specification. This should be an easy fix, by just checking the response code before making a return.

A possibility I'm toying with is adding the below to the function. Just have to make sure that wouldn't cause any problems.

if (response.status === 204) {
    return this.respond(this.clone())
}

https://jsonapi.org/format/#crud-creating
https://jsonapi.org/format/#crud-deleting

Can't resolve 'sarala'

Hello, looks like npm package is broken, fresh installed package can't be resolved:

This dependency was not found:

* sarala in ./src/models/BaseModel.js

To install it, you can run: npm install --save sarala

Looks like build folder is missing after npm install.
Published wrong way, I believe.

Response Parser

Hi @milroyfraser
seems that relationship must be mandatory.
Without 'with' keyword an error is thrown: 'cannot read id of undefined'.
i suppose the error is on Formatter.js at line 86.

if (_.isArray(data.relationships[key].data)) { relationship.data_collection = true relationship.data = this.resolveRelationCollection(data.relationships[key].data) } else { relationship.data = this.resolveRelation(data.relationships[key].data) }
where this check is left !!data.relationships[key].data (or something equivalent)

i hope should be helpfull
Diego

Headers

How to add authorizations and other headers?

Use self url if available before generating.

By the way,

I checked your commits on that, and I can tell you that approach is good, but you forgot to handle the case when api will provide self url, so I think you need to additionally check for self url in the model, and if it does not exist, then use current approach.

Or, we need to have some setting in each model or just in base model which will define how user will want to use self urls - default, or from the response.

Originally posted by @subotkevic in #7 (comment)

Replace axios with fetch

Fetch is becoming the new standard either built into browsers or as a polyfill.

Would be nice to see it used in the examples.

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.