BlairAllegroTech / js-data-jsonapi

JsonApi Adapter for js-data

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Do not Ignore options.basePath when building urls

BlairAllegroTech opened this issue · comments

When returned jsonApi objects have relationship links the js-data basePath was being intentionally ignored.

This causes problems when your API returns relatives paths and is exposed on a different basePath than where your javascript was served from.

Base path is now always prefixed to all Urls if configured,
Unless a url begins with base path already, in which case we do not prefix it again.
This is so that an api can still return fully qualified Urls

Related to #25

In reply to #25 (comment)

I added the basePath to the default options when configuring my the js-data provider in angular (using $http as the adaptor) and same results as I mentioned before in #25.

angular.module('js-data').provider('DSJsonApiAdapter', function () {
    var _this = this;
    _this.defaults = {basePath: 'https://stage-api.localhost:8080/v3'};
    _this.$get = function (DSHttpAdapter, $http) {
        _this.defaults.adapter = _this.defaults.adapter || DSHttpAdapter;
        _this.defaults.adapter.http = function (config) {
            return $http(config).then(function (data) {
                return Object.assign({}, data, {
                    headers: data.headers()
                });
            });
        };
        return new DSJsonApiAdapter.JsonApiAdapter(_this.defaults);
    };
});

Console logging output:

Wed, 10 Aug 2016 13:12:14 GMT - GET https://stage-api.localhost:8080/v3/users/me - 200 369ms Object
user-directive.js:20 Users Users
user-directive.js:23 Users.account undefined

I am using version 17, from this changeset: 1966bd4

@rgant Can you try changing

DS.defineResource({
    name: 'users',
    relations: {
        hasOne: {
            accounts: {
                localField: 'account',
                localKey: 'accountid'
            }
        }
    }
});

to

DS.defineResource({
    name: 'users',
    relations: {
        belongsTo: {
            accounts: {
                localField: 'account',
                localKey: 'accountid'
            }
        }
    }
});

I'm still trying to understand how js-data handles a oneToMany without a belongsTo and if load relations can or should set up the relationship in this case ?

From my testing i can see that currently if you have a oneToMany without a belongsTo the data gets loaded into js-data but it does not tie up the relationships unless you have a belongsTo

Can you clarify that the system is making requests to the correct Urls.
Then we can close this issue and go back to #25.

I've spotted another problem there which i did not expect and didn't show up in tests as i was always using a belongsTo on my relationships

Blair, I updated to version alpha.18 and I got some results! There is an error from js-data about expecting an array instead of an object, but it still worked. Thanks again for all your efforts. Here is the output from my console.log:

File Log
js-data-angular-3.2.1.js:418 Thu, 11 Aug 2016 13:41:59 GMT - GET users/me - 200 441ms Object {data: Object, status: 200, headers: Object, config: Object, statusText: "OK"}
user-directive.js:20 Users Users {created_at: "2016-06-27T16:22:15+00:00", last_name: "test", type: "admin", first_name: "test", email_status: Object…}
js-data-angular-3.2.1.js:418 Thu, 11 Aug 2016 13:41:59 GMT - GET /v3/users/me/account - 200 350ms Object {data: Object, status: 200, headers: Object, config: Object, statusText: "OK"}
js-data-2.9.0.js:252 accounts Error: response is expected to be an array!(…) nulldefaultsPrototype.error @ js-data-2.9.0.js:252errorFn @ js-data-2.9.0.js:205processResults @ js-data-2.9.0.js:5206(anonymous function) @ js-data-2.9.0.js:5306processQueue @ angular-1.5.8.js:16383(anonymous function) @ angular-1.5.8.js:16399$eval @ angular-1.5.8.js:17682$digest @ angular-1.5.8.js:17495$apply @ angular-1.5.8.js:17790done @ angular-1.5.8.js:11831completeRequest @ angular-1.5.8.js:12033requestLoaded @ angular-1.5.8.js:11966
user-directive.js:23 Users.account Accounts {created_at: "2016-06-27T16:11:00+00:00", type: "grantee", location_lng: 34.2, website: "www.testgrantee.com", updated_at: null…}

And this is the configuration of my app:

angular.module('js-data').provider('DSJsonApiAdapter', function () {
    var _this = this;
    _this.defaults = {};
    _this.$get = function (DSHttpAdapter, $http) {
        _this.defaults.adapter = _this.defaults.adapter || DSHttpAdapter;
        _this.defaults.adapter.http = function (config) {
            return $http(config).then(function (data) {
                return Object.assign({}, data, {
                    headers: data.headers()
                });
            });
        };
        return new DSJsonApiAdapter.JsonApiAdapter(_this.defaults);
    };
});

angular.module('app.models', ['app', 'js-data'])
.run(function (DS, DSJsonApiAdapter) {
    DS.registerAdapter('jsonApi', DSJsonApiAdapter, {default: true});

    DS.defineResource({
        name: 'accounts',
        relations: {
            hasMany: {
                /* ..., */
                users: {
                    localField: 'users',
                    // One Account for many Users; use foreignKey.
                    foreignKey: 'accountid'
                }
            },
            hasOne: {/* ... */}
        }
    });
    /* ... */
    DS.defineResource({
        name: 'users',
        relations: {
            hasOne: {
                accounts: {
                    localField: 'account',
                    localKey: 'accountid'
                }
            }
        }
    });
});

Do you still want me to try the basePath & the belongsTo relationship? Like you I don't really understand precisely why I would use belongsTo vs hasOne. My understanding is that it only enforces that the relationship must exist, but I am not too worried about js-data handling that automatically.

I would recommend using the basePath just because it should be easier.
All your jsonapi calls will go to the correct place. Other resources that come from the same location that the web app was loaded should work unmodified e.g. relative paths for them are normally fine.

Just much cleaner.
I'll try to reproduce the error you are getting. It may be that i'm always using findAll to load related.
It could possibly be unrelated also?

Setting that variable wasn't making the js-data requests go to the right
server in version 16, but I will try it again now.

Did you get my email from you blog? Wanted to direct message you.

-_Rob

On Thu, Aug 11, 2016, 17:15 BlairJ notifications@github.com wrote:

I would recommend using the basePath just because it should be easier.
All your jsonapi calls will go to the correct place. Other resources that
come from the same location that the web app was loaded should work
unmodified e.g. relative paths for them are normally fine.

Just much cleaner.
I'll try to reproduce the error you are getting. It may be that im always
using findAll to load related data. Maybe for hasOne i need to use find.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#30 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AArXmSjWGXKyQhELEXw9pR4YWCnSz7Iaks5qe5DvgaJpZM4Jfjmm
.

I'm sorry my blog is a bit of a disaster at the moment.... (Its on the list of things to do!!)
There is an email address in the package,json file that i will receive. Thanks

I think this is working now in the latest master branch. I believe this and #25 can be closed.