Files
omnivore/packages/api/src/services/highlights.ts
2023-11-01 13:26:36 +08:00

171 lines
4.3 KiB
TypeScript

import { diff_match_patch } from 'diff-match-patch'
import { DeepPartial } from 'typeorm'
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity'
import { Highlight } from '../entity/highlight'
import { homePageURL } from '../env'
import { createPubSubClient, EntityType } from '../pubsub'
import { authTrx } from '../repository'
import { highlightRepository } from '../repository/highlight'
type HighlightEvent = { id: string; pageId: string }
type CreateHighlightEvent = DeepPartial<Highlight> & HighlightEvent
type UpdateHighlightEvent = QueryDeepPartialEntity<Highlight> & HighlightEvent
export const getHighlightLocation = (patch: string): number | undefined => {
const dmp = new diff_match_patch()
const patches = dmp.patch_fromText(patch)
return patches[0].start1 || undefined
}
export const getHighlightUrl = (slug: string, highlightId: string): string =>
`${homePageURL()}/me/${slug}#${highlightId}`
export const createHighlights = async (
highlights: DeepPartial<Highlight>[],
userId: string
) => {
return authTrx(
async (tx) =>
tx.withRepository(highlightRepository).createAndSaves(highlights),
undefined,
userId
)
}
export const createHighlight = async (
highlight: DeepPartial<Highlight>,
libraryItemId: string,
userId: string,
pubsub = createPubSubClient()
) => {
const newHighlight = await authTrx(
async (tx) => {
const repo = tx.withRepository(highlightRepository)
const newHighlight = await repo.createAndSave(highlight)
return repo.findOneOrFail({
where: { id: newHighlight.id },
relations: {
user: true,
},
})
},
undefined,
userId
)
await pubsub.entityCreated<CreateHighlightEvent>(
EntityType.HIGHLIGHT,
{ ...newHighlight, pageId: libraryItemId, user: undefined },
userId
)
return newHighlight
}
export const mergeHighlights = async (
highlightsToRemove: string[],
highlightToAdd: DeepPartial<Highlight>,
libraryItemId: string,
userId: string,
pubsub = createPubSubClient()
) => {
const newHighlight = await authTrx(async (tx) => {
const highlightRepo = tx.withRepository(highlightRepository)
await highlightRepo.delete(highlightsToRemove)
const newHighlight = await highlightRepo.createAndSave(highlightToAdd)
return highlightRepo.findOneOrFail({
where: { id: newHighlight.id },
relations: {
user: true,
},
})
})
await pubsub.entityCreated<CreateHighlightEvent>(
EntityType.HIGHLIGHT,
{ ...newHighlight, pageId: libraryItemId, user: undefined },
userId
)
return newHighlight
}
export const updateHighlight = async (
highlightId: string,
highlight: QueryDeepPartialEntity<Highlight>,
userId: string,
pubsub = createPubSubClient()
) => {
const updatedHighlight = await authTrx(async (tx) => {
const highlightRepo = tx.withRepository(highlightRepository)
await highlightRepo.updateAndSave(highlightId, highlight)
return highlightRepo.findOneOrFail({
where: { id: highlightId },
relations: {
libraryItem: true,
user: true,
},
})
})
await pubsub.entityUpdated<UpdateHighlightEvent>(
EntityType.HIGHLIGHT,
{ ...highlight, id: highlightId, pageId: updatedHighlight.libraryItem.id },
userId
)
return updatedHighlight
}
export const deleteHighlightById = async (highlightId: string) => {
return authTrx(async (tx) => {
const highlightRepo = tx.withRepository(highlightRepository)
const highlight = await highlightRepo.findOneOrFail({
where: { id: highlightId },
relations: {
user: true,
},
})
await highlightRepo.delete(highlightId)
return highlight
})
}
export const findHighlightById = async (
highlightId: string,
userId: string
) => {
return authTrx(
async (tx) => {
const highlightRepo = tx.withRepository(highlightRepository)
return highlightRepo.findOneByOrFail({
id: highlightId,
})
},
undefined,
userId
)
}
export const findHighlightsByLibraryItemId = async (
libraryItemId: string,
userId: string
) => {
return authTrx(
async (tx) =>
tx.withRepository(highlightRepository).find({
where: { libraryItem: { id: libraryItemId } },
relations: {
user: true,
labels: true,
},
}),
undefined,
userId
)
}