api image refactoring

- standart image definition for old preview and new cover
This commit is contained in:
tmshv committed 2020-03-11 13:36:15 +03:00
1 parent a3ffb00ed7
commit 877c63a874
11 files changed
+104 -188

No files matched your search

+7 -26
View File
@@ -1,35 +1,16 @@
import { Request, Response } from 'express'
import Document from '../core/Document'
import { encodeFile } from '../factory/file'
import { encodeFile, encodeFileUrl } from '../factory/file'
export async function getItem(req: Request, res: Response) {
const id = req.params.slug
const document = await Document.findById(id)
if (document) {
res.json(encodeFile(document))
const slug = req.params.slug
const item = await Document.findBySlug(slug)
if (item) {
res.json(encodeFile(item))
} else {
res.status(404)
res.json({
error: `Resource ${id} not found`
})
}
}
export async function getAll(req: Request, res: Response) {
const documents = await Document.find({ hidden: false })
if (documents) {
const items = documents
.map(encodeFile)
.filter(x => x.imageUrl) // skip documents without preview image; needs to be refactored
res.json({
items,
})
} else {
res.status(404)
res.json({
error: `Not found`
error: `Resource ${slug} not found`
})
}
}
@@ -38,7 +19,7 @@ export async function getUrls(req: Request, res: Response) {
const data = await Document.find({})
if (data) {
const items = data.map(x => `/document/${x.id}`)
const items = data.map(encodeFileUrl)
res.json({
items
})
+23 -1
View File
@@ -1,11 +1,33 @@
import Image from '../core/Image'
import { encodeImage } from '../factory/image'
import { Request, Response } from 'express'
import { oid } from '../db'
export async function getItem(req: Request, res: Response) {
const slug = req.params.slug
const id = oid(slug)
if (!id) {
res.status(400)
return res.json({
error: `Failed to parse ${slug} as ObjectId`
})
}
const image = await Image.findById(id)
if (image) {
res.json(encodeImage(image))
} else {
res.status(404)
res.json({
error: `Resource ${slug} not found`
})
}
}
export async function getItemByFile(req: Request, res: Response) {
const file = req.query.file
const image = await Image.findByFile(file)
if (image) {
res.json(encodeImage(image))
} else {
+10 -10
View File
@@ -11,8 +11,8 @@ export default class Document {
return Promise.all(items.map(processDocument))
}
static async findById(id) {
const data = await findOne(store(), { id })
static async findBySlug(slug: string) {
const data = await findOne(store(), { id: slug })
if (!data) return null
return processDocument(data)
@@ -21,22 +21,22 @@ export default class Document {
public id: any
public hash: any
public file: any
public fileInfo: any
public fileInfo: FileInfo
public type: any
public title: any
public category: any
public url: any
public preview: any
public preview: Image
public viewUrl: any
constructor(data) {
constructor(data: { preview: Image, [name: string]: any }) {
this.id = data.id
this.hash = data.hash
this.file = data.file
// In the future: use fileInfo only
this.fileInfo = data.fileInfo
? new DocumentFile(data.fileInfo)
: new DocumentFile(data.file)
? new FileInfo(data.fileInfo)
: new FileInfo(data.file)
this.type = data.type
this.title = data.title
this.category = data.category
@@ -47,9 +47,9 @@ export default class Document {
}
}
class DocumentFile {
public name: any
public size: any
class FileInfo {
public name: string
public size: number
constructor(data) {
this.name = data.name
+1 -40
View File
@@ -1,5 +1,4 @@
import Data from './Data'
import ImageArtifactType from './ImageArtifactType'
import { findOne } from '../lib/store'
import { ObjectId } from 'mongodb'
@@ -47,47 +46,9 @@ export default class Image {
this.artifacts = mapOf(ImageArtifact, artifacts)
}
getArtifact(size) {
getArtifact(size: string) {
return this.artifacts.get(size)
}
findArtifact(sizes) {
for (let size of sizes) {
const a = this.getArtifact(size)
if (a) return a
}
return null
}
getPicture(size) {
const retinaSize = ImageArtifactType.retina(size)
const a = this.getArtifact(size)
const a2 = this.getArtifact(retinaSize)
const srcset = !a2
? []
: [{
url: a2.url,
density: ImageArtifactType.RETINA_DENSITY,
}]
return {
src: a.url,
width: a.width,
height: a.height,
set: srcset,
}
}
getSrc(): string | null {
const a = this.getArtifact(ImageArtifactType.ORIGINAL)
if (!a) {
return null
}
return a.url
}
}
class ImageArtifact {
@@ -1,19 +0,0 @@
class ImageArtifactType {
constructor() {
throw new Error('Cannot create instance of ImageArtifactType')
}
}
ImageArtifactType.SMALL = 'small'
ImageArtifactType.MEDIUM = 'medium'
ImageArtifactType.BIG = 'big'
ImageArtifactType.LARGE = 'large'
ImageArtifactType.ORIGIN = 'original'
ImageArtifactType.ORIGINAL = 'original'
ImageArtifactType.FACEBOOK = 'fb'
ImageArtifactType.RETINA_DENSITY = 2
ImageArtifactType.retina = type => `${type}@${ImageArtifactType.RETINA_DENSITY}`
module.exports = ImageArtifactType
-8
View File
@@ -20,14 +20,6 @@ export default class Page {
return Promise.all(items.map(processPage))
}
static async findById(id) {
const item = await findOne(store(), { id })
return !item
? null
: processPage(item)
}
static async findByUrl(url: string) {
const item = await findOne(store(), { url })
+16 -5
View File
@@ -12,14 +12,25 @@ export async function connect(dbName: string, mongoUri: string) {
return db
}
export function collection(name) {
export function collection(name: string) {
return db.collection(name)
}
export function id(i) {
if (typeof i === 'string') return new ObjectId(i)
else if (i instanceof ObjectId) return i
else if (i instanceof Object) return '_id' in i ? new ObjectId(i._id) : null
export type ObjectIdLike = ObjectId | string
export function oid(i: ObjectIdLike | { _id: ObjectIdLike }): ObjectId | null {
if (i instanceof ObjectId) {
return i
} else if (typeof i === 'string') {
try {
return new ObjectId(i)
} catch (error) {
console.error(error)
return null
}
} else if (i instanceof Object) {
return '_id' in i ? oid(i._id) : null
}
return null
}
+33 -32
View File
@@ -1,35 +1,36 @@
import ImageArtifactType from '../core/ImageArtifactType'
import Document from '../core/Document'
import { encodeImage, ImageDto } from './image'
const sizes = [
ImageArtifactType.MEDIUM,
ImageArtifactType.BIG,
ImageArtifactType.ORIGIN,
]
export function encodeFilePreview(file, sizes) {
const preview = file.preview
if (!preview) return null
const image = preview.findArtifact(sizes)
if (!image) return null
return image.url
}
export function encodeFile(file) {
const imageUrl = encodeFilePreview(file, sizes)
const category = (file.category || '')
.replace('Documents/', '')
.replace('Pages/', '')
.replace('Articles /', '')
return {
imageUrl,
category,
title: file.title,
fileName: file.fileInfo.name,
fileSize: file.fileInfo.size,
fileUrl: file.url,
url: file.viewUrl,
export type FileDto = {
url: string
slug: string
name: string
cover?: ImageDto
file: {
name: string
size: number
type: string
src: string
}
}
export function encodeFile(file: Document): FileDto {
const cover = file.preview ? encodeImage(file.preview) : null
return {
url: encodeFileUrl(file),
slug: file.id,
cover,
name: file.title,
file: {
type: 'application/pdf',
name: file.fileInfo.name,
size: file.fileInfo.size,
src: file.url,
}
}
}
export function encodeFileUrl(file: Document): string {
return `/document/${file.id}`
}
+11 -37
View File
@@ -1,48 +1,22 @@
import ImageArtifactType from '../core/ImageArtifactType'
import Image from '../core/Image'
export type ImageArtifactDto = {
height: number
width: number
src: string
set: Array<{
density: number
url: string
}>
}
const ORIGINAL = 'original'
export type ImageDto = {
artifacts: {
original: ImageArtifactDto,
large: ImageArtifactDto,
big: ImageArtifactDto,
medium: ImageArtifactDto,
small: ImageArtifactDto,
fb: ImageArtifactDto,
},
hash: string
file: string
width: number
height: number
src: string
}
export function encodeImage(image: Image): ImageDto {
const artifacts = [
ImageArtifactType.SMALL,
ImageArtifactType.MEDIUM,
ImageArtifactType.BIG,
ImageArtifactType.LARGE,
ImageArtifactType.ORIGIN,
ImageArtifactType.ORIGINAL,
ImageArtifactType.FACEBOOK = 'fb'
].reduce((acc, size) => {
return {
...acc,
[size]: image.getPicture(size),
}
}, {})
const a = image.getArtifact(ORIGINAL)
if (!image) {
return null
}
return {
artifacts: artifacts as any,
hash: image.hash,
file: image.file,
src: a.url,
width: a.width,
height: a.height,
}
}
+3 -9
View File
@@ -9,29 +9,24 @@ type Token = {
}
type PageDto = {
id: string
title: string
date?: string
url: string
data: string
description: string
preview?: ImageDto
cover?: ImageDto
tokens: Token[]
tags: Tag[]
featured: boolean
breadcrumb: Breadcrumb
coverSrc?: string
}
export function encodePage(page: Page): PageDto {
const preview = page.preview ? encodeImage(page.preview) : null
const cover = page.preview ? encodeImage(page.preview) : null
const date = page.date ? page.date.toString() : null
const breadcrumb = page.getBreadcrumb()
const coverSrc = page.preview ? page.preview.getSrc() : null
return {
id: page.id,
title: page.title,
url: page.url,
data: page.data,
@@ -39,9 +34,8 @@ export function encodePage(page: Page): PageDto {
tokens: page.tokens,
tags: page.tags,
featured: page.featured,
preview,
cover,
date,
breadcrumb,
coverSrc,
}
}
-1
View File
@@ -21,7 +21,6 @@ async function main() {
}
const app = express()
app.get('/files', file.getAll)
app.get('/files/urls', file.getUrls)
app.get('/files/:slug', file.getItem)