fix file uploading
This commit is contained in:
@ -80,12 +80,12 @@ import { isSiteBlockedForParse } from '../../utils/blocked'
|
||||
import {
|
||||
authorized,
|
||||
cleanUrl,
|
||||
errorHandler,
|
||||
generateSlug,
|
||||
isBase64Image,
|
||||
isParsingTimeout,
|
||||
libraryItemToArticle,
|
||||
libraryItemToSearchItem,
|
||||
pageError,
|
||||
titleForFilePath,
|
||||
userDataToUser,
|
||||
} from '../../utils/helpers'
|
||||
@ -153,7 +153,7 @@ export const createArticleResolver = authorized<
|
||||
|
||||
const userData = await userRepository.findById(uid)
|
||||
if (!userData) {
|
||||
return pageError(
|
||||
return errorHandler(
|
||||
{
|
||||
errorCodes: [CreateArticleErrorCode.Unauthorized],
|
||||
},
|
||||
@ -166,7 +166,7 @@ export const createArticleResolver = authorized<
|
||||
|
||||
try {
|
||||
if (isSiteBlockedForParse(url)) {
|
||||
return pageError(
|
||||
return errorHandler(
|
||||
{
|
||||
errorCodes: [CreateArticleErrorCode.NotAllowedToParse],
|
||||
},
|
||||
@ -190,7 +190,6 @@ export const createArticleResolver = authorized<
|
||||
let title: string | undefined
|
||||
let parsedContent: Readability.ParseResult | null = null
|
||||
let canonicalUrl
|
||||
let userArticleUrl: string | null = null
|
||||
let uploadFileHash = null
|
||||
let domContent = null
|
||||
let itemType = LibraryItemType.Unknown
|
||||
@ -226,7 +225,7 @@ export const createArticleResolver = authorized<
|
||||
*/
|
||||
const uploadFile = await findUploadFileById(uploadFileId)
|
||||
if (!uploadFile) {
|
||||
return pageError(
|
||||
return errorHandler(
|
||||
{ errorCodes: [CreateArticleErrorCode.UploadFileMissing] },
|
||||
uid,
|
||||
articleSavingRequestId,
|
||||
@ -238,7 +237,6 @@ export const createArticleResolver = authorized<
|
||||
uploadFile.fileName
|
||||
)
|
||||
uploadFileHash = uploadFileDetails.md5Hash
|
||||
userArticleUrl = uploadFileDetails.fileUrl
|
||||
canonicalUrl = uploadFile.url
|
||||
itemType = itemTypeForContentType(uploadFile.contentType)
|
||||
title = titleForFilePath(uploadFile.url)
|
||||
@ -282,7 +280,6 @@ export const createArticleResolver = authorized<
|
||||
title,
|
||||
parsedContent,
|
||||
userId: uid,
|
||||
itemId: articleSavingRequestId,
|
||||
slug,
|
||||
croppedPathname,
|
||||
originalHtml: domContent,
|
||||
@ -295,21 +292,15 @@ export const createArticleResolver = authorized<
|
||||
|
||||
log.info('New article saving', {
|
||||
parsedArticle: Object.assign({}, libraryItemToSave, {
|
||||
content: undefined,
|
||||
originalHtml: undefined,
|
||||
readableContent: undefined,
|
||||
originalContent: undefined,
|
||||
}),
|
||||
userArticleUrl,
|
||||
labels: {
|
||||
source: 'resolver',
|
||||
resolver: 'createArticleResolver',
|
||||
userId: uid,
|
||||
},
|
||||
})
|
||||
|
||||
if (uploadFileId) {
|
||||
const uploadFileData = await setFileUploadComplete(uploadFileId)
|
||||
if (!uploadFileData || !uploadFileData.id || !uploadFileData.fileName) {
|
||||
return pageError(
|
||||
return errorHandler(
|
||||
{
|
||||
errorCodes: [CreateArticleErrorCode.UploadFileMissing],
|
||||
},
|
||||
@ -344,7 +335,7 @@ export const createArticleResolver = authorized<
|
||||
pubsub
|
||||
)
|
||||
} else {
|
||||
// create new page in elastic
|
||||
// create new page in database
|
||||
libraryItemToReturn = await createLibraryItem(
|
||||
libraryItemToSave,
|
||||
uid,
|
||||
@ -353,7 +344,7 @@ export const createArticleResolver = authorized<
|
||||
}
|
||||
|
||||
log.info(
|
||||
'page created in elastic',
|
||||
'item created in database',
|
||||
libraryItemToReturn.id,
|
||||
libraryItemToReturn.originalUrl,
|
||||
libraryItemToReturn.slug,
|
||||
@ -367,7 +358,7 @@ export const createArticleResolver = authorized<
|
||||
}
|
||||
} catch (error) {
|
||||
log.error('Error creating article', error)
|
||||
return pageError(
|
||||
return errorHandler(
|
||||
{
|
||||
errorCodes: [CreateArticleErrorCode.ElasticError],
|
||||
},
|
||||
@ -399,6 +390,7 @@ export const getArticleResolver = authorized<
|
||||
user: true,
|
||||
labels: true,
|
||||
},
|
||||
uploadFile: true,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
@ -383,7 +383,7 @@ export const functionResolvers = {
|
||||
}
|
||||
return article.url
|
||||
},
|
||||
async originalArticleUrl(article: { url: string }) {
|
||||
originalArticleUrl(article: { url: string }) {
|
||||
return article.url
|
||||
},
|
||||
hasContent(article: {
|
||||
@ -464,6 +464,9 @@ export const functionResolvers = {
|
||||
image(item: SearchItem) {
|
||||
return item.image && createImageProxyUrl(item.image, 320, 320)
|
||||
},
|
||||
originalArticleUrl(item: { url: string }) {
|
||||
return item.url
|
||||
},
|
||||
},
|
||||
Subscription: {
|
||||
newsletterEmail(subscription: Subscription) {
|
||||
|
||||
@ -20,6 +20,7 @@ import {
|
||||
import { analytics } from '../../utils/analytics'
|
||||
import { authorized, generateSlug } from '../../utils/helpers'
|
||||
import {
|
||||
contentReaderForLibraryItem,
|
||||
generateUploadFilePathName,
|
||||
generateUploadSignedUrl,
|
||||
getFilePublicUrl,
|
||||
@ -127,25 +128,21 @@ export const uploadFileRequestResolver = authorized<
|
||||
// If we have a file:// URL, don't try to match it
|
||||
// and create a copy of the page, just create a
|
||||
// new item.
|
||||
const item = isFileUrl(input.url)
|
||||
? await findLibraryItemByUrl(input.url, uid)
|
||||
: undefined
|
||||
|
||||
const item = await findLibraryItemByUrl(input.url, uid)
|
||||
if (item) {
|
||||
if (
|
||||
!(await updateLibraryItem(
|
||||
item.id,
|
||||
{
|
||||
savedAt: new Date(),
|
||||
archivedAt: null,
|
||||
},
|
||||
uid
|
||||
))
|
||||
) {
|
||||
return { errorCodes: [UploadFileRequestErrorCode.FailedCreate] }
|
||||
}
|
||||
await updateLibraryItem(
|
||||
item.id,
|
||||
{
|
||||
savedAt: new Date(),
|
||||
archivedAt: null,
|
||||
state: LibraryItemState.Processing,
|
||||
},
|
||||
uid
|
||||
)
|
||||
createdItemId = item.id
|
||||
} else {
|
||||
const itemType = itemTypeForContentType(input.contentType)
|
||||
const uploadFileId = uploadFileData.id
|
||||
const item = await createLibraryItem(
|
||||
{
|
||||
originalUrl: isFileUrl(input.url) ? publicUrl : input.url,
|
||||
@ -153,9 +150,11 @@ export const uploadFileRequestResolver = authorized<
|
||||
user: { id: uid },
|
||||
title,
|
||||
readableContent: '',
|
||||
itemType: itemTypeForContentType(input.contentType),
|
||||
itemType,
|
||||
uploadFile: { id: uploadFileData.id },
|
||||
slug: generateSlug(uploadFilePathName),
|
||||
state: LibraryItemState.Processing,
|
||||
contentReader: contentReaderForLibraryItem(itemType, uploadFileId),
|
||||
},
|
||||
uid
|
||||
)
|
||||
|
||||
@ -81,7 +81,7 @@ export const createPageSaveRequest = async ({
|
||||
userId,
|
||||
url,
|
||||
pubsub = createPubSubClient(),
|
||||
articleSavingRequestId = uuidv4(),
|
||||
articleSavingRequestId,
|
||||
state,
|
||||
priority,
|
||||
labels,
|
||||
@ -149,7 +149,7 @@ export const createPageSaveRequest = async ({
|
||||
await enqueueParseRequest({
|
||||
url,
|
||||
userId,
|
||||
saveRequestId: articleSavingRequestId,
|
||||
saveRequestId: libraryItem.id,
|
||||
priority,
|
||||
state,
|
||||
labels,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { LibraryItemState } from '../entity/library_item'
|
||||
import { User } from '../entity/user'
|
||||
import { homePageURL } from '../env'
|
||||
import {
|
||||
@ -6,7 +7,6 @@ import {
|
||||
SaveFileInput,
|
||||
SaveResult,
|
||||
} from '../generated/graphql'
|
||||
import { logger } from '../utils/logger'
|
||||
import { getStorageFileDetails } from '../utils/uploads'
|
||||
import { findOrCreateLabels } from './labels'
|
||||
import { updateLibraryItem } from './library_item'
|
||||
@ -16,8 +16,6 @@ export const saveFile = async (
|
||||
input: SaveFileInput,
|
||||
user: User
|
||||
): Promise<SaveResult> => {
|
||||
logger.info('saving file with input', input)
|
||||
const pageId = input.clientRequestId
|
||||
const uploadFile = await findUploadFileById(input.uploadFileId)
|
||||
if (!uploadFile) {
|
||||
return {
|
||||
@ -35,28 +33,25 @@ export const saveFile = async (
|
||||
}
|
||||
}
|
||||
|
||||
// save state
|
||||
const archivedAt =
|
||||
input.state === ArticleSavingRequestStatus.Archived ? new Date() : null
|
||||
// add labels to page
|
||||
const labels = input.labels
|
||||
? await findOrCreateLabels(input.labels, user.id)
|
||||
: undefined
|
||||
if (input.state || input.labels) {
|
||||
const updated = await updateLibraryItem(
|
||||
pageId,
|
||||
// save state
|
||||
const archivedAt =
|
||||
input.state === ArticleSavingRequestStatus.Archived ? new Date() : null
|
||||
// add labels to page
|
||||
const labels = input.labels
|
||||
? await findOrCreateLabels(input.labels, user.id)
|
||||
: undefined
|
||||
await updateLibraryItem(
|
||||
input.clientRequestId,
|
||||
{
|
||||
archivedAt,
|
||||
labels,
|
||||
state: input.state
|
||||
? (input.state as unknown as LibraryItemState)
|
||||
: LibraryItemState.Succeeded,
|
||||
},
|
||||
user.id
|
||||
)
|
||||
if (!updated) {
|
||||
logger.info('error updating page', pageId)
|
||||
return {
|
||||
errorCodes: [SaveErrorCode.Unknown],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@ -28,6 +28,7 @@ import {
|
||||
} from '../utils/helpers'
|
||||
import { logger } from '../utils/logger'
|
||||
import { parsePreparedContent } from '../utils/parser'
|
||||
import { contentReaderForLibraryItem } from '../utils/uploads'
|
||||
import { createPageSaveRequest } from './create_page_save_request'
|
||||
import { createHighlight } from './highlights'
|
||||
import { findOrCreateLabels } from './labels'
|
||||
@ -258,5 +259,6 @@ export const parsedContentToLibraryItem = ({
|
||||
itemLanguage: parsedContent?.language,
|
||||
siteIcon: parsedContent?.siteIcon,
|
||||
wordCount: wordsCount(parsedContent?.textContent || ''),
|
||||
contentReader: contentReaderForLibraryItem(itemType, uploadFileId),
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,8 +7,12 @@ export const findUploadFileById = async (id: string) => {
|
||||
|
||||
export const setFileUploadComplete = async (id: string, userId?: string) => {
|
||||
return authTrx(
|
||||
async (tx) =>
|
||||
tx.getRepository(UploadFile).save({ id, status: 'COMPLETED' }),
|
||||
async (tx) => {
|
||||
const repo = tx.getRepository(UploadFile)
|
||||
await repo.update(id, { status: 'COMPLETED' })
|
||||
|
||||
return repo.findOneByOrFail({ id })
|
||||
},
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
|
||||
@ -178,7 +178,7 @@ export const generateSlug = (title: string): string => {
|
||||
|
||||
export const MAX_CONTENT_LENGTH = 5e7 //50MB
|
||||
|
||||
export const pageError = async (
|
||||
export const errorHandler = async (
|
||||
result: CreateArticleError,
|
||||
userId: string,
|
||||
pageId?: string | null,
|
||||
@ -242,6 +242,8 @@ export const libraryItemToArticle = (item: LibraryItem): Article => ({
|
||||
readingProgressAnchorIndex: item.readingProgressHighestReadAnchor,
|
||||
readingProgressPercent: item.readingProgressTopPercent,
|
||||
highlights: item.highlights?.map(highlightDataToHighlight) || [],
|
||||
uploadFileId: item.uploadFile?.id,
|
||||
pageType: item.itemType as unknown as PageType,
|
||||
})
|
||||
|
||||
export const libraryItemToSearchItem = (item: LibraryItem): SearchItem => ({
|
||||
@ -260,6 +262,7 @@ export const libraryItemToSearchItem = (item: LibraryItem): SearchItem => ({
|
||||
),
|
||||
image: item.thumbnail,
|
||||
highlights: item.highlights?.map(highlightDataToHighlight),
|
||||
uploadFileId: item.uploadFile?.id,
|
||||
})
|
||||
|
||||
export const isParsingTimeout = (libraryItem: LibraryItem): boolean => {
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import { File, GetSignedUrlConfig, Storage } from '@google-cloud/storage'
|
||||
import { ContentReaderType, LibraryItemType } from '../entity/library_item'
|
||||
import { env } from '../env'
|
||||
import { ContentReader, PageType } from '../generated/graphql'
|
||||
import { logger } from './logger'
|
||||
|
||||
export const contentReaderForPage = (
|
||||
pageType: PageType,
|
||||
export const contentReaderForLibraryItem = (
|
||||
itemType: LibraryItemType,
|
||||
uploadFileId: string | null | undefined
|
||||
) => {
|
||||
if (!uploadFileId) {
|
||||
return ContentReader.Web
|
||||
return ContentReaderType.WEB
|
||||
}
|
||||
switch (pageType) {
|
||||
case PageType.Book:
|
||||
return ContentReader.Epub
|
||||
case PageType.File:
|
||||
return ContentReader.Pdf
|
||||
switch (itemType) {
|
||||
case LibraryItemType.Book:
|
||||
return ContentReaderType.EPUB
|
||||
case LibraryItemType.File:
|
||||
return ContentReaderType.PDF
|
||||
default:
|
||||
return ContentReader.Web
|
||||
return ContentReaderType.WEB
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,10 +47,6 @@ export const generateUploadSignedUrl = async (
|
||||
contentType: string,
|
||||
selectedBucket?: string
|
||||
): Promise<string> => {
|
||||
// if (env.dev.isLocal) {
|
||||
// return 'http://localhost:3000/uploads/' + filePathName
|
||||
// }
|
||||
|
||||
// These options will allow temporary uploading of file with requested content type
|
||||
const options: GetSignedUrlConfig = {
|
||||
version: 'v4',
|
||||
|
||||
Reference in New Issue
Block a user