Skip to content

Instantly share code, notes, and snippets.

@DavidWells
Last active February 27, 2022 01:35
Show Gist options
  • Save DavidWells/ba3cbeb5ca8e486eff839fa9dcc0f549 to your computer and use it in GitHub Desktop.
Save DavidWells/ba3cbeb5ca8e486eff839fa9dcc0f549 to your computer and use it in GitHub Desktop.
const fetch = async (...args) => {
console.log(...args)
return {
statusCode: 200,
data: {},
}
}
function httpRequest(url, method, data, opts, cb) {
const init = { method }
switch (method) {
case 'GET':
if (data) {
url = `${url}?${new URLSearchParams(data)}`
}
break
case 'POST':
case 'PUT':
case 'PATCH':
init.body = JSON.stringify(data)
}
// Run promise or callback
return fetch(url, init).then((d) => {
if (cb) return cb(undefined, d)
return d
}).catch((err) => {
if (cb) return cb(err)
throw err
})
}
function generateAPI(url, scope = []) {
// a hack, so we can use field either as property or a method
const callable = () => {}
callable.url = url
return new Proxy(callable, {
get({ url }, propKey) {
const upperKey = propKey.toUpperCase()
const prevScope = scope[scope.length - 1]
const path = scope.concat(propKey)
console.log('prevScope', prevScope)
if (['GET', 'POST', 'PUT', 'DELETE', 'PATCH'].includes(upperKey)) {
const resolvedPath = path.slice(0, -1)
console.log('resolved SDK path', resolvedPath)
const func = (data, options = {}, callback) => {
console.log('data', data)
console.log('options', options)
const config = typeof options === 'function' ? {} : options
const cb = typeof options === 'function' ? options : callback
return httpRequest(url, upperKey, data, config, cb)
}
/* Add callable sub keys after HTTP method */
func.sync = (data, options = {}) => {
console.log('run sync thing', data)
console.log('run sync opts', options)
}
/* Client signature */
return func
}
return generateAPI(`${url}/${propKey}`, path)
},
apply({ url }, thisArg, [arg] = []) {
// Mid chain function call ()
// e.g. client.product(7).get()
console.log('apply called', url)
console.log('arg used', arg)
const path = url.split('/')
return generateAPI(arg ? `${url}/${arg}` : url, path)
}
})
}
/* Init client */
const client = generateAPI('https://base.com')
/* Usage example client.thing.xyz.operation() */
client.get() // GET https://base.com
client.post() // PUT https://base.com
client.put() // POST https://base.com
client.delete() // DELETE https://base.com
const opts = { foo: 'bar' }
/* Mid chain calls with () work too but look weird */
// GET https://base.com/product/7
client.product(7).get()
// GET with query strings https://base.com/base/tiles/public/static/2.json?turn=37038&games=wot
client.product(7).get({
turn: 37,
games: 'wot'
})
// DELETE https://base.com/product/7/whatever
client.product(7).whatever.delete(1, opts)
// PUT with body https://base.com/product/7
client.product(7).put({
whatever: 1
})
// POST with body https://base.com/product/7 w/ body
client.product(7).post({
whatever: 1
})
// GET https://base.com/base/tiles/public/static/3/4/2.json
client.tiles.public.static(3)(4)(`${2}.json`).get()
/* Bracket syntax for numbers */
// GET https://base.com/product/7
client.product[7].get()
// GET with query strings https://base.com/base/tiles/public/static/2.json?turn=37038&games=wot
client.product[7].get({
turn: 37,
games: 'wot'
})
// DELETE https://base.com/product/7/whatever
client.product[7].whatever.delete(1, opts)
// PUT with body https://base.com/product/7
client.product[7].put({
whatever: 1
})
// POST with body https://base.com/product/7
client.product[7].post({
whatever: 1
})
/* Clean API */
// GET https://base.com/entities/product
client.entities.product.get()
// GET with query strings https://base.com/entities/product?turn=37038&games=wot
client.entities.product.get({
turn: 37,
games: 'wot'
})
// DELETE https://base.com/entities/product
client.entities.product.delete(1, opts)
// PUT with body https://base.com/entities/product
client.entities.product.put({
whatever: 1
})
// POST with body https://base.com/entities/product
client.entities.product.post({
whatever: 1
})
const payload = {
foo: 'bar'
}
/* Callback Usage */
client.entity.shape[1].post(payload, (err, resp) => {
console.log('callback', resp)
})
/* Promise Usage */
client.entity.shape.post(payload).then((resp) => {
console.log('promise', resp)
})
/* Sync Usage */
client.entity.shape.post.sync(payload)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment