Skip to content

Instantly share code, notes, and snippets.

@mk0y
Last active January 14, 2021 12:02
Show Gist options
  • Save mk0y/9604452373a60593f3773a9e4b82ac27 to your computer and use it in GitHub Desktop.
Save mk0y/9604452373a60593f3773a9e4b82ac27 to your computer and use it in GitHub Desktop.
const asyncCompose = (...fns) => input =>
fns.reduceRight(
(chain, fn) => chain.then(fn),
Promise.resolve(input)
)
// import { authService } from 'authservice'
const authService = null
const getUser = async ({ auth = authService, ...dependencies }) => {
try {
const user = await auth()
return { username: user.username, ...dependencies }
} catch (e) {
// you could also throw exception if you want to fail fast, meaning if flow isn't possible without auth service
return { error: e, username: 'default', ...dependencies }
}
}
// import { dbService } from 'dbservice'
const dbService = null
const withDB = async ({ db = dbService, ...dependencies }) => {
// managing db is usually much more complex
// this also can be wrapped with try-catch, depends on your needs
const dbInstance = db.currentInstance()
if (!dbInstance) {
throw new Error('no database :(')
}
return { coll: dbInstance, ...dependencies }
}
// dependencies is optional since filterSketchesBy only needs sketches
// this function is future proof since it passes through dependencies
const findSketches = async ({ coll, ...dependencies }) => {
const { username, sketch: sketchSearch } = dependencies
const sketchesByName = await coll.findByName(username, sketchSearch)
return { sketches: sketchesByName, ...dependencies }
}
const filterSketchesBy = ({ sketches, filter, ...dependencies }) => {
if (!sketches.length) {
return { sketches, ...dependencies }
}
const filtered = sketches.filter(sketch => sketch.name.toLowerCase().includes(filter.toLowerCase()))
return { sketches: filtered, ...dependencies }
}
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] => [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9 ] ]
const paginateSketches = ({ sketches, perPage = 4, ...dependencies }) => {
if (!sketches.length) {
return { sketches, ...dependencies }
}
const paginated = sketches.reduce(
(acc, cur, i) => {
const ii = i + 1;
if (i % 4 === 0) { acc.push([]); }
acc[Math.ceil(ii / perPage) - 1].push(cur);
return acc;
},
[]
)
return { sketches: paginated, ...dependencies }
}
const getAllUserSketches = asyncCompose(findSketches, withDB, getUser)
const withAdditionalFilter = asyncCompose(filterSketchesBy, getAllUserSketches)
const paginatedSketches = asyncCompose(paginateSketches, withAdditionalFilter)
const sketchesSuccess = [{
name: 'jiberish'
}, {
name: 'mock this'
}, {
name: 'mock that'
}, {
name: 'little house'
}, {
name: 'awesome logo'
}]
// happy path, get all, no filter
getAllUserSketches({
auth: () => Promise.resolve({ username: 'bojack' }),
db: { currentInstance: () => ({ findByName: () => Promise.resolve(sketchesSuccess) }) },
}).then(console.log)
// with filter
withAdditionalFilter({
auth: () => Promise.resolve({ username: 'juju876' }),
db: { currentInstance: () => ({ findByName: () => Promise.resolve(sketchesSuccess) }) },
filter: 'mock',
}).then(console.log)
// paginated
paginatedSketches({
auth: () => Promise.resolve({ username: 'zhu1234567' }),
db: { currentInstance: () => ({ findByName: () => Promise.resolve(sketchesSuccess) }) },
filter: 'mock',
}).then(console.log)
// auth service is allowing further flow
// find error in result.error
paginatedSketches({
auth: () => Promise.reject('auth service is down'),
db: { currentInstance: () => ({ findByName: () => Promise.resolve(sketchesSuccess) }) },
filter: 'mock',
}).then(console.log)
// db exits early, result is only "no database :("
paginatedSketches({
auth: () => Promise.resolve({ username: 'shmoopie' }),
db: { currentInstance: () => null },
filter: 'mock',
}).then(console.log).catch(({ message }) => console.error(message))
// db exits early, result is only "timed out..."
paginatedSketches({
auth: () => Promise.resolve({ username: 'hoopie' }),
db: { currentInstance: () => ({ findByName: () => Promise.reject(new Error('timed out...')) }) },
filter: 'mock',
}).then(console.log).catch(({ message }) => console.error(message))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment