orbitjs / orbit

Composable data framework for ambitious web applications.
https://orbitjs.com
MIT License
2.33k stars 134 forks source link

[JSON:API] Sync records and included relationships with memory source. #939

Closed easybi-rm closed 2 years ago

easybi-rm commented 2 years ago

Hello everyone,

I use JSON:API to fetch a resource and include relationships in the result. The source is synced with the coordinator to the memory source. It works for the original resource, but the included resources are not saved to the memory source. The response from the request is correct. This is my code, which I use:

    this.remote = new JSONAPISource({
      schema: this.schema,
      host: this.host,
      namespace: 'api',
    });
    this.memory = new MemorySource({ schema: this.schema });
    this.coordinator = new Coordinator();
    this.coordinator.addSource(this.memory);
    this.coordinator.addSource(this.remote);
    this.coordinator.addStrategy(new RequestStrategy({
      source: 'memory',
      target: 'jsonapi',
      on: 'beforeQuery',
      action: 'query',
      blocking: true,
    }));
    this.coordinator.addStrategy(new SyncStrategy({
      source: 'jsonapi',
      target: 'memory',
      blocking: true,
    }));

Is there something that I did wrong or misunderstood?

Thanks for your help, Rok

dgeb commented 2 years ago

I'd recommend also adding an event logging strategy to your coordinator to help debug this. Check the transform events coming from the jsonapi source for transforms that include the included records. If they are not present then that will tell you that it's an issue deserializing the json:api response rather than a coordination issue.

easybi-rm commented 2 years ago

Hi,

thank you for your reply. You suggestion helped me solve the error, which was caused by a typo in the schema; Now the data is loaded with all relationships from the include options parameters in the JSON:API request. Now my question remains why is the data not included in the relationships of the result returned from the OrbitJS memory source, even when I include it in the query; My query looks like this:

this.remote.query<Task[]>((q) =>
      q.findRecords('workordertasks').options({
        include: ['order', 'order.location', 'order.outcomes', 'order.outcomes.article'],
        filter: {
          responsibleUser: '1',
          status: [TaskStatus.Planed, TaskStatus.InProgress].join(',')
        },
      })
    )

Attributes from order, order.location, order.outcomes, order.outcomes.articles are returned from the request but not included in the result of the query; It only has array of relationships with { type: string, id: string } parameters; I can do a manual query for each of these, but I would prefer to have them included in the result, is this currently possible?

Thanks for your reply, Rok

bradjones1 commented 2 years ago

You either need to load them separately or use fullResponse. https://orbitjs.com/docs/whats-new#full-vs-data-only-responses

dgeb commented 2 years ago

@easybi-rm if you are working with orbit directly, @bradjones1's response is the correct solution for now.

Other model-based approaches exist like ember-orbit and the in-development orbit-model. Both libraries provide a model abstraction to easily traverse data in a cache using models, allowing access to both attributes and related models.

I'd like to bring an official framework-agnostic model-based solution (perhaps orbit-model itself) into orbit core eventually.