Skip to content

Commit

Permalink
Avoid a union of strings with a dedicated type
Browse files Browse the repository at this point in the history
Refs #976
  • Loading branch information
thewilkybarkid committed Jun 2, 2023
1 parent 460ad81 commit dd1b4a8
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 119 deletions.
14 changes: 14 additions & 0 deletions src/profile-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { Orcid } from 'orcid-id-ts'
import type { Pseudonym } from './pseudonym'

export type ProfileId = OrcidProfileId | PseudonymProfileId

export interface OrcidProfileId {
readonly type: 'orcid'
readonly value: Orcid
}

export interface PseudonymProfileId {
readonly type: 'pseudonym'
readonly value: Pseudonym
}
11 changes: 6 additions & 5 deletions src/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { type Html, html, plainText, rawHtml, sendHtml } from './html'
import { notFound, serviceUnavailable } from './middleware'
import { page } from './page'
import type { PreprintId } from './preprint-id'
import type { ProfileId } from './profile-id'
import type { Pseudonym } from './pseudonym'
import { reviewMatch } from './routes'
import { renderDate } from './time'
Expand All @@ -35,17 +36,17 @@ export type Prereviews = ReadonlyArray<{
}>

export interface GetPrereviewsEnv {
getPrereviews: (profile: Orcid | Pseudonym) => TE.TaskEither<'unavailable', Prereviews>
getPrereviews: (profile: ProfileId) => TE.TaskEither<'unavailable', Prereviews>
}

export interface GetNameEnv {
getName: (orcid: Orcid) => TE.TaskEither<'not-found' | 'unavailable', string>
}

const getPrereviews = (orcid: Orcid | Pseudonym) =>
const getPrereviews = (profile: ProfileId) =>
pipe(
RTE.ask<GetPrereviewsEnv>(),
RTE.chainTaskEitherK(({ getPrereviews }) => getPrereviews(orcid)),
RTE.chainTaskEitherK(({ getPrereviews }) => getPrereviews(profile)),
)

const getName = (orcid: Orcid) =>
Expand All @@ -56,7 +57,7 @@ const getName = (orcid: Orcid) =>

export const profile = (orcid: Orcid) =>
pipe(
RM.fromReaderTaskEither(getPrereviews(orcid)),
RM.fromReaderTaskEither(getPrereviews({ type: 'orcid', value: orcid })),
RM.bindTo('prereviews'),
RM.apSW('name', RM.fromReaderTaskEither(getName(orcid))),
RM.apSW('user', maybeGetUser),
Expand All @@ -74,7 +75,7 @@ export const profile = (orcid: Orcid) =>

export const profilePseudonym = (pseudonym: Pseudonym) =>
pipe(
RM.fromReaderTaskEither(getPrereviews(pseudonym)),
RM.fromReaderTaskEither(getPrereviews({ type: 'pseudonym', value: pseudonym })),
RM.bindTo('prereviews'),
RM.apSW('name', RM.of(pseudonym)),
RM.apSW('user', maybeGetUser),
Expand Down
10 changes: 4 additions & 6 deletions src/zenodo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ import * as D from 'io-ts/Decoder'
import iso6391, { type LanguageCode } from 'iso-639-1'
import iso6393To1 from 'iso-639-3/to-1.json'
import * as L from 'logger-fp-ts'
import type { Orcid } from 'orcid-id-ts'
import { isOrcid } from 'orcid-id-ts'
import { get } from 'spectacles-ts'
import { P, match } from 'ts-pattern'
import {
Expand All @@ -38,7 +36,7 @@ import type { RecentPrereview } from './home'
import { plainText, sanitizeHtml } from './html'
import { type GetPreprintEnv, type GetPreprintTitleEnv, getPreprint, getPreprintTitle } from './preprint'
import { type IndeterminatePreprintId, PreprintDoiD, type PreprintId, fromPreprintDoi, fromUrl } from './preprint-id'
import { type Pseudonym, isPseudonym } from './pseudonym'
import type { ProfileId } from './profile-id'
import type { Prereview } from './review'
import type { NewPrereview } from './write-review'

Expand Down Expand Up @@ -105,12 +103,12 @@ export const getPrereviewFromZenodo = flow(
)

export const getPrereviewsForProfileFromZenodo = flow(
(profile: Orcid | Pseudonym) =>
(profile: ProfileId) =>
new URLSearchParams({
communities: 'prereview-reviews',
q: match(profile)
.when(isOrcid, orcid => `creators.orcid:${orcid}`)
.when(isPseudonym, pseudonym => `creators.name:"${pseudonym}"`)
.with({ type: 'orcid', value: P.select() }, orcid => `creators.orcid:${orcid}`)
.with({ type: 'pseudonym', value: P.select() }, pseudonym => `creators.name:"${pseudonym}"`)
.exhaustive(),
size: '100',
sort: '-publication_date',
Expand Down
15 changes: 15 additions & 0 deletions test/fc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import type {
ZenodoOrAfricarxivPreprintId,
ZenodoPreprintId,
} from '../src/preprint-id'
import type { OrcidProfileId, ProfileId, PseudonymProfileId } from '../src/profile-id'
import type { Pseudonym } from '../src/pseudonym'
import { type NonEmptyString, isNonEmptyString } from '../src/string'
import type { User } from '../src/user'
Expand Down Expand Up @@ -509,6 +510,20 @@ export const pseudonym = (): fc.Arbitrary<Pseudonym> =>
.tuple(fc.constantFrom(...colors), fc.constantFrom(...animals))
.map(parts => capitalCase(parts.join(' ')) as Pseudonym)

export const profileId = (): fc.Arbitrary<ProfileId> => fc.oneof(orcidProfileId(), pseudonymProfileId())

export const orcidProfileId = (): fc.Arbitrary<OrcidProfileId> =>
fc.record({
type: fc.constant('orcid'),
value: orcid(),
})

export const pseudonymProfileId = (): fc.Arbitrary<PseudonymProfileId> =>
fc.record({
type: fc.constant('pseudonym'),
value: pseudonym(),
})

export const year = (): fc.Arbitrary<number> => fc.integer({ min: -271820, max: 275759 })

export const plainYearMonth = (): fc.Arbitrary<Temporal.PlainYearMonth> =>
Expand Down
4 changes: 2 additions & 2 deletions test/profile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('profile', () => {
]),
)
expect(getName).toHaveBeenCalledWith(orcid)
expect(getPrereviews).toHaveBeenCalledWith(orcid)
expect(getPrereviews).toHaveBeenCalledWith({ type: 'orcid', value: orcid })
})

test.prop([
Expand Down Expand Up @@ -168,7 +168,7 @@ describe('profilePseudonym', () => {
{ type: 'setBody', body: expect.anything() },
]),
)
expect(getPrereviews).toHaveBeenCalledWith(pseudonym)
expect(getPrereviews).toHaveBeenCalledWith({ type: 'pseudonym', value: pseudonym })
})

test.prop([
Expand Down
Loading

0 comments on commit dd1b4a8

Please sign in to comment.