ChuckJonas / ts-force

A Salesforce REST Client written in Typescript for Typescript
88 stars 21 forks source link

Composite Batch queries #75

Closed ChuckJonas closed 3 years ago

ChuckJonas commented 5 years ago

It's common to have some type of "load sequence" in applications that executes a bunch of queries.

Would be great to combine the query builder with composite batch to save time and API calls.

wuservices commented 3 years ago

The Composite API seems pretty powerful for reducing API calls when fetching data, and ensuring ad-hoc modifications complete transactionally without resorting to Apex REST. In ts-force, is typed support only built out when only doing queries via compositeRetrieve? Is there a typed way to use Composite with a ref, or to combine queries with DML, or does that become more manual?

ChuckJonas commented 3 years ago

You can use the generated classes, but it's somewhat manual.

This example show how you would implement the example from the official docs, plus I added another "GET" to show how the results can be parse back to the generated "RestObject".

    const restInstance = new Rest();
    const composite = new Composite();
    const acc = new Account({
      name: 'Sample Account'
    });
    composite.addRequest({
      referenceId: 'refAccount', 
      method: 'POST', 
      url: `/services/data/v${restInstance.config.version}/sobjects/Account`,
      body: acc.toJson( {dmlMode: 'insert'} )
    });

    const con = new Contact({
      name: 'Sample Contact',
      accountId : "@{refAccount.id}"
    });

    composite.addRequest({
      referenceId: 'refContact', 
      method: 'POST', 
      url: `/services/data/v${restInstance.config.version}/sobjects/Contact`, 
      body: con.toJson( {dmlMode: 'insert'} )
    });

    composite.addRequest({
      referenceId: 'contact', 
      method: 'GET', 
      url: `/services/data/v${restInstance.config.version}/sobjects/Contact/@{refContact.id}`, 
    });

    const results = await composite.send();
    const conWithData = Contact.fromSFObject(results.compositeResponse[2].body);

This could be streamlined by exposing methods to create requests for insert/update/delete for the rest objects.

Also, at some point I want to add the new CompositeGraph to be able to efficiently create/update entire object graphs via the object references.

wuservices commented 3 years ago

Thanks for confirming and the example is really helpful. That doesn't seem too bad right now, but I agree that some kind of slick Composite Graph integration could be really helpful in the future. Glad you mentioned Composite Graph as I hadn't seen that yet.

Before, I was using SOAP from Java/Scala when it could be transactional or when I could get away with one API call, but Apex REST otherwise. Now there are so many choices... It'll be interesting to see what ends up working best in the long run.