Skip to content

Instantly share code, notes, and snippets.

@fes300
Last active November 15, 2019 18:08
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 fes300/171c631d25fcd6c15632c400d4df4559 to your computer and use it in GitHub Desktop.
Save fes300/171c631d25fcd6c15632c400d4df4559 to your computer and use it in GitHub Desktop.
const getDocsByRole = (limit: number) => (role: string) => { // finally I can use it...
return new TaskEither(
new Task(() =>
db
.collection("documents")
.where("roles", "array-contains", role)
.orderBy("updated")
.limit(limit)
.get()
.then(r => r.docs.map(d => d.data()))
.then(docs => GetDocumentsResponse.decode(docs))
)
);
};
const getDocsByRoles = (limit: number) => (roles: string[]): TaskEither<Errors, Document[]> => // I have to pass down the limit...
traverseTaskEither(roles.map(getDocsByRole(limit))).map(flatten);
export const getUserDocsFunc = (
d: any,
c: functions.https.CallableContext
): TaskEither<Errors, GetUserDocumentsResponse> => {
return taskEither.fromEither(
sequenceSEither({
params: GetUserDocsRequest.decode({
limit: d.limit,
nameFilter: d.nameFilter,
tagFilter: d.tagFilter,
}),
userId: t.string.decode(c.auth && c.auth.uid)
})
)
// I have to nidify monad chaining because I need to keep the params in scope
// to access them later! it is sooo hard to read now...
.chain(({ params, userId }) => getUserRoles(userId)
.chain(getDocsByRoles(params.limit)) // I have to pass down the limit...
.map(uniq(eqDocument))
.chain(docs =>
takeLeft(params.limit)(
docs.filter(
({ title, tags }) =>
title.toLowerCase().includes(nameFilter.toLowerCase()) &&
difference(eqTag)(tagFilter, tags).length === 0
)
)
)
).map(GetUserDocumentsResponse.encode)
}
const getDocsByRole = (
role: string
): ReaderTaskEither<DocsRequestStrict, t.Errors, Document[]> =>
ask<DocsRequestStrict, Errors>().chain(({ limit }) =>
fromTaskEither(
new TaskEither(
new Task(() =>
db
.collection("documents")
.where("roles", "array-contains", role)
.orderBy("updated", "desc")
.limit(limit)
.get()
.then(r => r.docs.map(d => d.data()))
.then(docs => GetDocumentsResponse.decode(docs))
)
)
)
);
const getDocsByRoles = (
roles: string[]
): ReaderTaskEither<DocsRequestStrict, Errors, Document[]> =>
traverseReaderTaskEither(roles, getDocsByRole).map(flatten);
export const getUserDocsFunc = (c: functions.https.CallableContext) =>
readerTaskEither
.fromEither<DocsRequestStrict, Errors, string>(
t.string.decode(c.auth && c.auth.uid)
)
.chain(userId => fromTaskEither(getUserRoles(userId)))
.chain(getDocsByRoles)
.map(uniq(eqDocument))
.chain(docs =>
ask<DocsRequestStrict, Errors>().map(({ nameFilter, tagFilter, limit }) => // now I just "ask" things whenever I need them
takeLeft(limit)(
docs.filter(
({ title, tags }) =>
title.toLowerCase().includes(nameFilter.toLowerCase()) &&
difference(eqTag)(tagFilter, tags).length === 0
)
)
)
)
.map(GetUserDocumentsResponse.encode);
/* I had all these nice little functions working inside TaskEither
* so nice and cosy...
* unfortunately a new requirement came: the call needed to handle a custom limit
* a filter on the title of the documents and a filter on the tags
*/
const getDocsByRole = (role: string) => {
return new TaskEither(
new Task(() =>
db
.collection("documents")
.where("roles", "array-contains", role)
.orderBy("updated")
.get()
.then(r => r.docs.map(d => d.data()))
.then(docs => GetDocumentsResponse.decode(docs))
)
);
};
const getDocsByRoles = (roles: string[]): TaskEither<Errors, Document[]> =>
sequenceTaskEither(roles.map(getDocsByRole)).map(flatten);
export const getUserDocsFunc = (
c: functions.https.CallableContext
): TaskEither<Errors, GetUserDocumentsResponse> => {
return taskEither
.fromEither(t.string.decode(c.auth && c.auth.uid))
.chain(getUserRoles)
.chain(getDocsByRoles)
.map(uniq(eqDocument))
.map(takeLeft(15))
.map(GetUserDocumentsResponse.encode);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment