Skip to content

Commit

Permalink
update docmaps-sdk dep
Browse files Browse the repository at this point in the history
  • Loading branch information
ships committed May 11, 2023
1 parent e0d77e9 commit 46ef9d6
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 24 deletions.
4 changes: 2 additions & 2 deletions packages/ts-etl/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
"tsconfig.json"
],
"dependencies": {
"commander": "^10.0.1",
"@commander-js/extra-typings": "^10.0.3",
"commander": "^10.0.1",
"crossref-openapi-client-ts": "^1.3.0",
"docmaps-sdk": "^0.5.0",
"docmaps-sdk": "^0.5.1",
"fp-ts": "^2.14.0"
},
"devDependencies": {
Expand Down
6 changes: 3 additions & 3 deletions packages/ts-etl/src/plugins/crossref/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as TE from 'fp-ts/lib/TaskEither'
import * as D from 'docmaps-sdk'
import { eqString } from 'fp-ts/lib/Eq'
import {
leftToStrError,
mapLeftToUnknownError,
decodeActionForWork,
stepArrayToDocmap,
thingForCrossrefWork,
Expand Down Expand Up @@ -56,7 +56,7 @@ function stepsForDoiRecursive(
},
],
})),
E.chain((action) => pipe(D.DocmapStep.decode(action), leftToStrError)),
E.chain((action) => pipe(D.DocmapStep.decode(action), mapLeftToUnknownError)),
E.map((s) => ({
all: [s],
head: s,
Expand Down Expand Up @@ -133,7 +133,7 @@ function stepsForDoiRecursive(
},
],
})),
TE.chainEitherK((rs) => leftToStrError(D.DocmapStep.decode(rs))),
TE.chainEitherK((rs) => mapLeftToUnknownError(D.DocmapStep.decode(rs))),
TE.map((reviewStep) => ({
head: prefixChain.head,
all: prefixChain.all.concat([reviewStep]),
Expand Down
64 changes: 45 additions & 19 deletions packages/ts-etl/src/plugins/crossref/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,17 @@ function nameForAuthor(a: { family: string; name?: string; given?: string }): st
export function decodeActionForWork(work: Work): E.Either<Error, D.DocmapActionT> {
return pipe(
E.Do,
// prepare the Thing which will be output
E.bind('wo', () => pipe(work, thingForCrossrefWork, E.right)),
// prepare the Authors
E.bind('wa', () =>
pipe(
work.author || [],
A.map((a) => ({
type: 'person',
name: nameForAuthor(a),
})),
E.traverseArray((a) => leftToStrError(D.DocmapActor.decode(a))),
E.traverseArray((a) => mapLeftToUnknownError(D.DocmapActor.decode(a))),
E.map((auths) =>
auths.map((a) => ({
actor: a,
Expand All @@ -42,25 +44,38 @@ export function decodeActionForWork(work: Work): E.Either<Error, D.DocmapActionT
),
),
),
// construct and decode the Action
E.chain(({ wo, wa }) =>
pipe(
{
participants: wa,
outputs: [wo],
},
D.DocmapAction.decode,
leftToStrError,
mapLeftToUnknownError,
),
),
)
}

/**
* stepArrayToDocmap - a helper function that processes a list of steps into a coherent docmap
*
* This function is needed because while a recursive process can produce a list of steps,
* those steps are not inherently doubly-linked the way they need to be in a docmap.
* (i.e., the Steps are each created independent from each other based on the crossref
* data for each DOI, but they need to be connected when they become a Workflow.)
* we additionally insert any step-independent info that is pertinent to the docmap, such as
* the Publisher of the docmap.
*
* This is an awkward moment that breaks some of the functional abstraction (see comments).
*/
export function stepArrayToDocmap(
publisher: D.DocmapPublisherT,
inputDoi: string,
[firstStep, ...steps]: D.DocmapStepT[],
): ErrorOrDocmap {
// TODO: extract this
// TODO: extract this logic
const dm_id = `https://docmaps-project.github.io/ex/docmap_for/${inputDoi}`

const now = new Date()
Expand All @@ -85,6 +100,9 @@ export function stepArrayToDocmap(
return E.right([dmObject.right])
}

// this reduction takes advantage of the fact that we have separated the firstStep
// from the ...steps argument, because the first & last step is only singly linked
// (see the last argument to #reduce).
const reduction = steps.reduce<E.Either<Error, Record<string, D.DocmapStepT>>>(
(memo, next) => {
if (E.isLeft(memo)) {
Expand Down Expand Up @@ -116,29 +134,37 @@ export function stepArrayToDocmap(

return E.right(m)
},
// initial memo: the first step only, whose next-step is inserted during
// the reduction loop and who doesn't need a first-step. since the reduce
// is creating an Either, we begin with an Either that never fails.
E.right({
'_:b0': firstStep,
}),
)

if (E.isLeft(reduction)) {
return reduction
}
const dmObject = D.Docmap.decode({
...dmBody,
'first-step': '_:b0',
steps: reduction.right,
})

if (E.isLeft(dmObject)) {
return E.left(new Error('unable to parse manuscript step', { cause: dmObject.left }))
}

return E.right([dmObject.right])
return pipe(
reduction,
E.map((r) => ({
...dmBody,
'first-step': '_:b0',
steps: r,
})),
E.chain((b) => pipe(
b,
D.Docmap.decode,
mapLeftToUnknownError,
)),
// requires to output Array of docmap
E.map((d) => [d])
)
}

// FIXME this is a weak upcast - use t.Errors more effectively in ts-sdk
export const leftToStrError = E.mapLeft((e: unknown) => {
/** mapLeftToUnknownError - helper function for interoperating between Either types
*
* specifically, io-ts codecs are always of type Either<ValidationError[], T>, and that
* validation error is not naturally upcastable to Error where we use Either<Error, T>.
*/
export const mapLeftToUnknownError = E.mapLeft((e: unknown) => {
if (e instanceof Error) {
return e
}
Expand Down

0 comments on commit 46ef9d6

Please sign in to comment.