api image refactoring
- standart image definition for old preview and new cover
This commit is contained in:
1 parent
a3ffb00ed7
commit
877c63a874
11 files changed
+104
-188
No files matched your search
@@ -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
|
||||
})
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,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
|
||||
@@ -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 })
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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}`
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in new issue
Block a user