deblockt / hal-rest-client

Typescript HAL Rest client
Apache License 2.0
25 stars 11 forks source link

Fetching from a link isn't working (in Angular?) #22

Open Smolli opened 6 years ago

Smolli commented 6 years ago

There is this setup:

export class CustomerResource extends HalResource {
    @HalProperty()
    id: number
    @HalProperty()
    name: string
    // @HalProperty(StoreResource)
    // stores: Array<Store>
}

@Injectable()
export class CustomerService {

    getCustomers(): Promise<CustomerResource[]> {
        const uri = this.createUrl('customer')
        return this.client.fetchArray(uri, CustomerResource)
    }

    getStores(customer: CustomerResource): Promise<StoreResource[]> {
        const resource = customer.link('stores')
        const link = resource.fetch()
        return (<Promise<any>>link)
    }    
}

When I call customerService.getStores(customer) I get the error Error: object is not hal resource [<array of stores>]. It doesn't change a thing if I comment out the stores field in the CustomerResource type or not. However, fetching the customer in the first place works fine. And I don't see any difference to your example code (besides the await statements) in the wiki.

There is a alternate approach that actually works, but I guess it wasn't meant to be (looks a bit ugly to me ;)

const link = customer.link('stores').uri.uri
return this.client.fetchArray(link, StoreResource)

As you may already have guessed by the @Injectable() decorator, I'm using Angular 5 and calling resource.fetch() returns a ZoneAwarePromise. Maybe that's a clue.

deblockt commented 6 years ago

can you provide a json representation of /customerand /stores?

I will try to reproduce this issue

Smolli commented 6 years ago

Sure. All resources are 0..n. For the sake of readability, I just provided one object per resource.


/api/v1/customer

[
    {
        "id": 22,
        "name": "Customer 22",
        "_links": {
            "self": {
                "href": "/api/v1/customer/22"
            },
            "stores": {
                "href": "/api/v1/customer/22/store"
            }
        }
    }
]

/api/v1/customer/22/store

[
    {
        "id": 144102,
        "customer_id": 22,
        "name": "City Store",
        "_links": {
            "self": {
                "href": "/api/v1/store/144102_22_KU"
            },
            "customer": {
                "href": "/api/v1/customer/22"
            },
            "sector": {
                "href": "/api/v1/sector/KU_22"
            }
        }
    }
]

/api/v1/store

[
    {
        "id": 0,
        "customer_id": 22,
        "_links": {
            "self": {
                "href": "/api/v1/store/0_22_D"
            },
            "customer": {
                "href": "/api/v1/customer/22"
            }
        }
    }
]
deblockt commented 6 years ago

Thank's, this doesn' work because your stores link is not an HalResource. It's juste an array of HalResource.

each link must be an HalResource. If you want that's works, you must have a json like this :

{
    "_links": {
        "self": { "href": "/stores" },
     },
    "_embedded": {
        "stores": [
            {
                "id": 144102,
                "customer_id": 22,
                "name": "City Store",
                "_links": {
                    "self": {
                        "href": "/api/v1/store/144102_22_KU"
                    },
                    "customer": {
                        "href": "/api/v1/customer/22"
                    },
                    "sector": {
                        "href": "/api/v1/sector/KU_22"
                    }
                }
            }
        ]
    }
}
Smolli commented 6 years ago

Ok, got it. So I guess there is no other way as to do it with the .uri.uri thingi and fetch them all by hand.

Thanks!

deblockt commented 6 years ago

Sorry, but at the moment, I think link can not be an Array. I will perform some tests. I think i will manage this case. But that can take some time.

meanwhile, you umust use uri.uri, I will update fetch method to take URI on parameter, It'll be less ugly.

Smolli commented 6 years ago

Sorry, but I think link can not be an Array.

Why not? I don't see why a link should be exclusively pointing to a single resource. As far as I understood HATEOAS, it can be any action or resource. But if I'm wrong, please tell me. I'm not that far into the topic (yet). 😁

deblockt commented 6 years ago

I have edited my previous comment.

I think this is the case now, but this feature will be implemented soon.