Skip to content

Instantly share code, notes, and snippets.

@heisian
Last active November 20, 2019 17:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save heisian/fdd5b42e35e98c906488eca0193f21c9 to your computer and use it in GitHub Desktop.
Save heisian/fdd5b42e35e98c906488eca0193f21c9 to your computer and use it in GitHub Desktop.
FYSTSXHR
import Xhr from 'Xhr'
const xhr = new Xhr()
// Or alternatively, xhr is just functional:
// import xhr from 'xhr'
// Assume xhr instance (or functional equivalent) is being passed in
;(async (xhr) => {
// Current API
let response = await xhr('patch')
.user(2)
.identity(2)
.data({
email: 'tim@getethos.com',
password: 'somethignReally.Good!',
nameFirst: 'Timothy',
nameLast: 'Huang',
birthDate: '1985-10-21',
gender: 'Male',
})
.fetch()
// Hypothetical API, closure/DI-style
response = await xhr.patch((request) => {
request.path.user(2).identity(2)
request.headers({ 'Content-Type': 'application/json' })
request.data({
email: 'tim@getethos.com',
password: 'somethignReally.Good!',
nameFirst: 'Timothy',
nameLast: 'Huang',
birthDate: '1985-10-21',
gender: 'Male',
})
})
// Hypothetical again, using destructuring
response = await xhr.patch(({ path, headers, data }) => {
path.user(2).identity(2)
headers({ 'Content-Type': 'application/json' })
data({
email: 'tim@getethos.com',
password: 'somethignReally.Good!',
nameFirst: 'Timothy',
nameLast: 'Huang',
birthDate: '1985-10-21',
gender: 'Male',
})
})
// Hypothetical again, with custom path and query params
response = await xhr.get(({ path, params, headers, data }) => {
path('/some/custom/path')
params({
some: 'data',
will: 'getQueryStringified',
})
})
})
@heisian
Copy link
Author

heisian commented Nov 20, 2019

@zach-ethos @roblevintennis what do ya'll think about the "Hypothetical" API vs. what Xhr currently has?

@roblevintennis
Copy link

roblevintennis commented Nov 20, 2019

Calling patch feels off xhr.patch as patch usually means some sort of update to an existing thing in my experience.

response = await xhr.patch((request) => {} implies to me that the internals is going to call this back with a request param that is used by consumer to set these properties, and then Xhr will use that to set things up internally and then execute the fetch; but why not then just have these passed in directly by client and do the same?

For the last custom path and query params one, I first read the { path, params, headers, data } inputs as properties, but they're actually methods the consumer uses to inject the values back to Xhr. Again, I think just letting the consumer do it and pass in is more straight forward.

I do like the idea of having convenience methods based on HTTP verb. It's familiar based on old jQuery days, and I think we could share same GET vs. POST interface as setting up xhr directly.

Here's my take on going all in on DI:

/*
interface XhrConfig {
  baseUrl?: string, /* internall will have a sensible default */
  httpMethod: HttpMethodType,
  requestOptions: XhrOptions = {}
  pathBuilder: PathBuilder,
  requestBody?: string, /* only for POST/PUT etc. */
}
*/

function Xhr({ baseUrl, method, path, requestBody }: XhrConfig) {...}
export Xhr

import Xhr from 'Xhr'
import pathBuilder from 'PathBuilder'

const xhr = new Xhr()

// GET
function termPolicyXhr(userId, identityId, termPolicyId) {
  return (method): Promise<XhrResponse> {
    // You still have the nice chaining for PathBuilder
    const path = new pathBuilder() 
      .user(userId)
      .identity(identityId)
      .termPolicy(termPolicyId)

    // Xhr calls fetch internally
    return xhr(/* baseUrl--optional, maybe has a default */, method, path, /* requestBody not meaningful here */) 
  }
}

// POST
function termPolicyCreateXhr(userId, identityId, termPolicyId, requestBody) {
  return (method): Promise<XhrResponse> {
    // You still have the nice chaining for PathBuilder
    const path = new pathBuilder() 
      .user(userId)
      .identity(identityId)
      .termPolicy(termPolicyId)

    // Xhr calls fetch internally
    return xhr(myBaseUrlOverride, method, path, requestBody) 
  }
}

@heisian
Copy link
Author

heisian commented Nov 20, 2019

how would I invoke termPolicyCreateXhr in this example?

perhaps,

import Xhr from 'xhr'
import termPolicyCreateXhr from 'termPolicyCreateXhr'

const xhrInstance = new Xhr()

;(async() => {
  const response = await termPolicyCreateXhr(1, 2, 3, {
    some: 'data',
  })
})()

@heisian
Copy link
Author

heisian commented Nov 20, 2019

simplified, after speaking IRL w/ @roblevintennis:

import xhr from 'xhr'

;(async() => {

  const path = new xhr.path
    .user(userId)
    .identity(identityId)
    .termPolicy(termPolicyId)

  // Xhr calls fetch internally
  const { err, response } = await xhr({
    baseURL: 'somethingelse.com',
    method: xhr.POST,
    path,
    { some: 'data' },
  })

  if (err) {
    // handle it
  }

})()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment