Merge branch 'dev' into feature/list-your-product-ui

This commit is contained in:
MTG2000
2022-09-15 13:25:06 +03:00
74 changed files with 2691 additions and 792 deletions

View File

@@ -28,6 +28,11 @@ declare global {
}
export interface NexusGenInputs {
ImageInput: { // input type
id?: string | null; // String
name?: string | null; // String
url: string; // String!
}
MakerRoleInput: { // input type
id: number; // Int!
level: NexusGenEnums['RoleLevelEnum']; // RoleLevelEnum!
@@ -36,7 +41,7 @@ export interface NexusGenInputs {
id: number; // Int!
}
ProfileDetailsInput: { // input type
avatar?: string | null; // String
avatar?: NexusGenInputs['ImageInput'] | null; // ImageInput
bio?: string | null; // String
discord?: string | null; // String
email?: string | null; // String
@@ -59,7 +64,7 @@ export interface NexusGenInputs {
}
StoryInputType: { // input type
body: string; // String!
cover_image?: string | null; // String
cover_image?: NexusGenInputs['ImageInput'] | null; // ImageInput
id?: number | null; // Int
is_published?: boolean | null; // Boolean
tags: string[]; // [String!]!
@@ -95,7 +100,6 @@ export interface NexusGenScalars {
export interface NexusGenObjects {
Author: { // root type
avatar: string; // String!
id: number; // Int!
join_date: NexusGenScalars['Date']; // Date!
lightning_address?: string | null; // String
@@ -111,7 +115,6 @@ export interface NexusGenObjects {
applicants_count: number; // Int!
applications: NexusGenRootTypes['BountyApplication'][]; // [BountyApplication!]!
body: string; // String!
cover_image?: string | null; // String
createdAt: NexusGenScalars['Date']; // Date!
deadline: string; // String!
excerpt: string; // String!
@@ -129,7 +132,6 @@ export interface NexusGenObjects {
workplan: string; // String!
}
Category: { // root type
cover_image?: string | null; // String
icon?: string | null; // String
id: number; // Int!
title: string; // String!
@@ -154,7 +156,6 @@ export interface NexusGenObjects {
title: string; // String!
}
Hackathon: { // root type
cover_image: string; // String!
description: string; // String!
end_date: NexusGenScalars['Date']; // Date!
id: number; // Int!
@@ -181,7 +182,6 @@ export interface NexusGenObjects {
}
Mutation: {};
MyProfile: { // root type
avatar: string; // String!
bio?: string | null; // String
discord?: string | null; // String
email?: string | null; // String
@@ -213,13 +213,10 @@ export interface NexusGenObjects {
votes_count: number; // Int!
}
Project: { // root type
cover_image: string; // String!
description: string; // String!
id: number; // Int!
lightning_address?: string | null; // String
lnurl_callback_url?: string | null; // String
screenshots: string[]; // [String!]!
thumbnail_image: string; // String!
title: string; // String!
votes_count: number; // Int!
website: string; // String!
@@ -237,7 +234,6 @@ export interface NexusGenObjects {
}
Story: { // root type
body: string; // String!
cover_image?: string | null; // String
createdAt: NexusGenScalars['Date']; // Date!
excerpt: string; // String!
id: number; // Int!
@@ -254,13 +250,11 @@ export interface NexusGenObjects {
title: string; // String!
}
Tournament: { // root type
cover_image: string; // String!
description: string; // String!
end_date: NexusGenScalars['Date']; // Date!
id: number; // Int!
location: string; // String!
start_date: NexusGenScalars['Date']; // Date!
thumbnail_image: string; // String!
title: string; // String!
website: string; // String!
}
@@ -268,7 +262,6 @@ export interface NexusGenObjects {
description: string; // String!
ends_at: NexusGenScalars['Date']; // Date!
id: number; // Int!
image: string; // String!
location: string; // String!
starts_at: NexusGenScalars['Date']; // Date!
title: string; // String!
@@ -280,7 +273,6 @@ export interface NexusGenObjects {
question: string; // String!
}
TournamentJudge: { // root type
avatar: string; // String!
company: string; // String!
name: string; // String!
}
@@ -296,7 +288,6 @@ export interface NexusGenObjects {
}
TournamentPrize: { // root type
amount: string; // String!
image: string; // String!
title: string; // String!
}
TournamentProjectsResponse: { // root type
@@ -305,7 +296,6 @@ export interface NexusGenObjects {
projects: NexusGenRootTypes['Project'][]; // [Project!]!
}
User: { // root type
avatar: string; // String!
bio?: string | null; // String
discord?: string | null; // String
github?: string | null; // String

View File

@@ -115,6 +115,12 @@ type Hackathon {
website: String!
}
input ImageInput {
id: String
name: String
url: String!
}
type LnurlDetails {
commentAllowed: Int
maxSendable: Int
@@ -219,7 +225,7 @@ type PostComment {
}
input ProfileDetailsInput {
avatar: String
avatar: ImageInput
bio: String
discord: String
email: String
@@ -331,7 +337,7 @@ type Story implements PostBase {
input StoryInputType {
body: String!
cover_image: String
cover_image: ImageInput
id: Int
is_published: Boolean
tags: [String!]!

View File

@@ -4,7 +4,8 @@ const {
extendType,
nonNull,
} = require('nexus');
const { prisma } = require('../../../prisma')
const { prisma } = require('../../../prisma');
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
const Category = objectType({
@@ -12,7 +13,11 @@ const Category = objectType({
definition(t) {
t.nonNull.int('id');
t.nonNull.string('title');
t.string('cover_image');
t.string('cover_image', {
async resolve(parent) {
return prisma.category.findUnique({ where: { id: parent.id } }).cover_image_rel().then(resolveImgObjectToUrl)
}
});
t.string('icon');

View File

@@ -6,6 +6,7 @@ const {
nonNull,
} = require('nexus');
const { prisma } = require('../../../prisma');
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
@@ -15,7 +16,11 @@ const Hackathon = objectType({
t.nonNull.int('id');
t.nonNull.string('title');
t.nonNull.string('description');
t.nonNull.string('cover_image');
t.nonNull.string('cover_image', {
async resolve(parent) {
return prisma.hackathon.findUnique({ where: { id: parent.id } }).cover_image_rel().then(resolveImgObjectToUrl)
}
});
t.nonNull.date('start_date');
t.nonNull.date('end_date');
t.nonNull.string('location');

View File

@@ -1,4 +1,5 @@
const scalars = require('./_scalars')
const misc = require('./misc')
const category = require('./category')
const project = require('./project')
const vote = require('./vote')
@@ -10,6 +11,7 @@ const donation = require('./donation')
const tag = require('./tag')
module.exports = {
...misc,
...tag,
...scalars,
...category,

View File

@@ -0,0 +1,19 @@
const { objectType, extendType, inputObjectType } = require("nexus");
const { prisma } = require('../../../prisma');
const ImageInput = inputObjectType({
name: 'ImageInput',
definition(t) {
t.string('id');
t.string('name');
t.nonNull.string('url');
}
});
module.exports = {
// Types
ImageInput,
// Queries
}

View File

@@ -15,6 +15,9 @@ const { prisma } = require('../../../prisma');
const { getUserByPubKey } = require('../../../auth/utils/helperFuncs');
const { ApolloError } = require('apollo-server-lambda');
const { marked } = require('marked');
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
const { ImageInput } = require('./misc');
const { deleteImage } = require('../../../services/imageUpload.service');
const POST_TYPE = enumType({
@@ -37,7 +40,11 @@ const Author = objectType({
definition(t) {
t.nonNull.int('id');
t.nonNull.string('name');
t.nonNull.string('avatar');
t.nonNull.string('avatar', {
async resolve(parent) {
return prisma.user.findUnique({ where: { id: parent.id } }).avatar_rel().then(resolveImgObjectToUrl)
}
});
t.nonNull.date('join_date');
t.string('lightning_address');
@@ -71,7 +78,11 @@ const Story = objectType({
t.nonNull.string('type', {
resolve: () => t.typeName
});
t.string('cover_image');
t.string('cover_image', {
async resolve(parent) {
return prisma.story.findUnique({ where: { id: parent.id } }).cover_image_rel().then(resolveImgObjectToUrl)
}
});
t.nonNull.list.nonNull.field('comments', {
type: "PostComment",
resolve: (parent) => []
@@ -111,7 +122,9 @@ const StoryInputType = inputObjectType({
t.int('id');
t.nonNull.string('title');
t.nonNull.string('body');
t.string('cover_image');
t.field('cover_image', {
type: ImageInput
})
t.nonNull.list.nonNull.string('tags');
t.boolean('is_published')
}
@@ -342,6 +355,64 @@ const getPostById = extendType({
}
})
const addCoverImage = async (providerImageId) => {
const newCoverImage = await prisma.hostedImage.findFirst({
where: {
provider_image_id: providerImageId
}
})
if (!newCoverImage) throw new ApolloError("New cover image not found")
await prisma.hostedImage.update({
where: {
id: newCoverImage.id
},
data: {
is_used: true
}
})
return newCoverImage
}
const getHostedImageIdsFromBody = async (body, oldBodyImagesIds = null) => {
let bodyImageIds = []
const regex = /(?:!\[(.*?)\]\((.*?)\))/g
let match;
while ((match = regex.exec(body))) {
const [, , value] = match
// Useful for old external images in case of duplicates. We need to be sure we are targeting an image from the good story.
const where = oldBodyImagesIds ? {
AND: [
{ url: value },
{ id: { in: oldBodyImagesIds } }
]
} :
{
url: value,
}
const hostedImage = await prisma.hostedImage.findFirst({
where
})
if (hostedImage) {
bodyImageIds.push(hostedImage.id)
await prisma.hostedImage.update({
where: {
id: hostedImage.id
},
data: {
is_used: true
}
})
}
}
return bodyImageIds
}
const createStory = extendType({
type: 'Mutation',
definition(t) {
@@ -358,20 +429,64 @@ const createStory = extendType({
let was_published = false;
// TODO: validate post data
let coverImage = null
let bodyImageIds = []
// Edit story
if (id) {
const oldPost = await prisma.story.findFirst({
where: { id },
select: {
user_id: true,
is_published: true
is_published: true,
cover_image_id: true,
body_image_ids: true
}
})
was_published = oldPost.is_published;
if (user.id !== oldPost.user_id)
throw new ApolloError("Not post author")
}
// TODO: validate post data
if (user.id !== oldPost.user_id) throw new ApolloError("Not post author")
// Body images
bodyImageIds = await getHostedImageIdsFromBody(body, oldPost.body_image_ids)
// Old cover image is found
if (oldPost.cover_image_id) {
const oldCoverImage = await prisma.hostedImage.findFirst({
where: {
id: oldPost.cover_image_id
}
})
// New cover image
if (cover_image?.id && cover_image.id !== oldCoverImage?.provider_image_id) {
await deleteImage(oldCoverImage.id)
coverImage = await addCoverImage(cover_image.id)
} else {
coverImage = oldCoverImage
}
} else {
// No old image found and new cover image
if (cover_image?.id) {
coverImage = await addCoverImage(cover_image.id)
}
}
// Remove unused body images
const unusedImagesIds = oldPost.body_image_ids.filter(x => !bodyImageIds.includes(x));
unusedImagesIds.map(async i => await deleteImage(i))
} else {
// Body images
bodyImageIds = await getHostedImageIdsFromBody(body)
// New story and new cover image
if (cover_image?.id) {
coverImage = await addCoverImage(cover_image.id)
}
}
// Preprocess & insert
const htmlBody = marked.parse(body);
@@ -383,6 +498,16 @@ const createStory = extendType({
.replace(/"/g, '"')
;
const coverImageRel = coverImage ? {
cover_image_rel: {
connect:
{
id: coverImage ? coverImage.id : null
}
}
} : {}
if (id) {
await prisma.story.update({
where: { id },
@@ -398,7 +523,7 @@ const createStory = extendType({
data: {
title,
body,
cover_image,
cover_image: '',
excerpt,
is_published: was_published || is_published,
tags: {
@@ -415,16 +540,17 @@ const createStory = extendType({
}
})
},
body_image_ids: bodyImageIds,
...coverImageRel
}
})
}
return prisma.story.create({
return await prisma.story.create({
data: {
title,
body,
cover_image,
cover_image: '',
excerpt,
is_published,
tags: {
@@ -445,7 +571,9 @@ const createStory = extendType({
connect: {
id: user.id,
}
}
},
body_image_ids: bodyImageIds,
...coverImageRel
}
})
}
@@ -470,17 +598,39 @@ const deleteStory = extendType({
const oldPost = await prisma.story.findFirst({
where: { id },
select: {
user_id: true
user_id: true,
body_image_ids: true,
cover_image_id: true
}
})
if (user.id !== oldPost.user_id)
throw new ApolloError("Not post author")
return prisma.story.delete({
const deletedPost = await prisma.story.delete({
where: {
id
}
})
const coverImage = await prisma.hostedImage.findMany({
where: {
OR: [
{ id: oldPost.cover_image_id },
{
id: {
in: oldPost.body_image_ids
}
}
]
},
select: {
id: true,
provider_image_id: true
}
})
coverImage.map(async i => await deleteImage(i.id))
return deletedPost
}
})
},

View File

@@ -8,6 +8,7 @@ const {
inputObjectType,
} = require('nexus')
const { prisma } = require('../../../prisma');
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
const { paginationArgs, getLnurlDetails, lightningAddressToLnurl } = require('./helpers');
const { MakerRole } = require('./users');
@@ -19,9 +20,30 @@ const Project = objectType({
t.nonNull.int('id');
t.nonNull.string('title');
t.nonNull.string('description');
t.nonNull.string('cover_image');
t.nonNull.string('thumbnail_image');
t.nonNull.list.nonNull.string('screenshots');
t.nonNull.string('cover_image', {
async resolve(parent) {
return prisma.project.findUnique({ where: { id: parent.id } }).cover_image_rel().then(resolveImgObjectToUrl)
}
});
t.nonNull.string('thumbnail_image', {
async resolve(parent) {
return prisma.project.findUnique({ where: { id: parent.id } }).thumbnail_image_rel().then(resolveImgObjectToUrl)
}
});
t.nonNull.list.nonNull.string('screenshots', {
async resolve(parent) {
if (!parent.screenshots_ids) return null
const imgObject = await prisma.hostedImage.findMany({
where: {
id: { in: parent.screenshots_ids }
}
});
return imgObject.map(img => {
return resolveImgObjectToUrl(img);
});
}
});
t.nonNull.string('website');
t.string('lightning_address');
t.string('lnurl_callback_url');

View File

@@ -9,6 +9,7 @@ const {
booleanArg,
} = require('nexus');
const { getUserByPubKey } = require('../../../auth/utils/helperFuncs');
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
const { prisma } = require('../../../prisma');
const { paginationArgs, removeNulls } = require('./helpers');
@@ -19,7 +20,11 @@ const TournamentPrize = objectType({
definition(t) {
t.nonNull.string('title');
t.nonNull.string('amount');
t.nonNull.string('image');
t.nonNull.string('image', {
async resolve(parent) {
return prisma.tournamentPrize.findUnique({ where: { id: parent.id } }).image_rel().then(resolveImgObjectToUrl)
}
});
}
})
@@ -28,7 +33,11 @@ const TournamentJudge = objectType({
definition(t) {
t.nonNull.string('name');
t.nonNull.string('company');
t.nonNull.string('avatar');
t.nonNull.string('avatar', {
async resolve(parent) {
return prisma.tournamentJudge.findUnique({ where: { id: parent.id } }).avatar_rel().then(resolveImgObjectToUrl)
}
});
}
})
@@ -74,7 +83,11 @@ const TournamentEvent = objectType({
definition(t) {
t.nonNull.int('id');
t.nonNull.string('title');
t.nonNull.string('image');
t.nonNull.string('image', {
async resolve(parent) {
return prisma.tournamentEvent.findUnique({ where: { id: parent.id } }).image_rel().then(resolveImgObjectToUrl)
}
});
t.nonNull.string('description');
t.nonNull.date('starts_at');
t.nonNull.date('ends_at');
@@ -91,8 +104,16 @@ const Tournament = objectType({
t.nonNull.int('id');
t.nonNull.string('title');
t.nonNull.string('description');
t.nonNull.string('thumbnail_image');
t.nonNull.string('cover_image');
t.nonNull.string('thumbnail_image', {
async resolve(parent) {
return prisma.tournament.findUnique({ where: { id: parent.id } }).thumbnail_image_rel().then(resolveImgObjectToUrl)
}
});
t.nonNull.string('cover_image', {
async resolve(parent) {
return prisma.tournament.findUnique({ where: { id: parent.id } }).cover_image_rel().then(resolveImgObjectToUrl)
}
});
t.nonNull.date('start_date');
t.nonNull.date('end_date');
t.nonNull.string('location');

View File

@@ -3,7 +3,10 @@ const { prisma } = require('../../../prisma');
const { objectType, extendType, intArg, nonNull, inputObjectType, stringArg, interfaceType, list, enumType } = require("nexus");
const { getUserByPubKey } = require("../../../auth/utils/helperFuncs");
const { removeNulls } = require("./helpers");
const { ImageInput } = require('./misc');
const { Tournament } = require('./tournament');
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
const { deleteImage } = require('../../../services/imageUpload.service');
@@ -13,7 +16,11 @@ const BaseUser = interfaceType({
definition(t) {
t.nonNull.int('id');
t.nonNull.string('name');
t.nonNull.string('avatar');
t.nonNull.string('avatar', {
async resolve(parent) {
return prisma.user.findUnique({ where: { id: parent.id } }).avatar_rel().then(resolveImgObjectToUrl)
}
});
t.nonNull.date('join_date');
t.string('role');
t.string('jobTitle')
@@ -289,7 +296,9 @@ const ProfileDetailsInput = inputObjectType({
name: 'ProfileDetailsInput',
definition(t) {
t.string('name');
t.string('avatar');
t.field('avatar', {
type: ImageInput
})
t.string('email')
t.string('jobTitle')
t.string('lightning_address')
@@ -317,14 +326,48 @@ const updateProfileDetails = extendType({
throw new Error("You have to login");
// TODO: validate new data
// ----------------
// Check if the user uploaded a new image, and if so,
// remove the old one from the hosting service, then replace it with this one
// ----------------
let avatarId = user.avatar_id;
if (args.data.avatar.id) {
const newAvatarProviderId = args.data.avatar.id;
const newAvatar = await prisma.hostedImage.findFirst({
where: {
provider_image_id: newAvatarProviderId
}
})
if (newAvatar && newAvatar.id !== user.avatar_id) {
avatarId = newAvatar.id;
await prisma.hostedImage.update({
where: {
id: newAvatar.id
},
data: {
is_used: true
}
});
await deleteImage(user.avatar_id)
}
}
// Preprocess & insert
return prisma.user.update({
where: {
id: user.id,
},
data: removeNulls(args.data)
data: removeNulls({
...args.data,
avatar_id: avatarId,
//hack to remove avatar from args.data
// can be removed later with a schema data validator
avatar: '',
})
})
}
})

View File

@@ -85,11 +85,21 @@ const loginHandler = async (req, res) => {
const nostr_prv_key = generatePrivateKey();
const nostr_pub_key = getPublicKey(nostr_prv_key);
const avatar = await prisma.hostedImage.create({
data: {
filename: 'avatar.svg',
provider: 'external',
is_used: true,
url: `https://avatars.dicebear.com/api/bottts/${key}.svg`,
provider_image_id: ''
}
})
const createdUser = await prisma.user.create({
data: {
pubKey: key,
name: key,
avatar: `https://avatars.dicebear.com/api/bottts/${key}.svg`,
avatar_id: avatar.id,
nostr_prv_key,
nostr_pub_key,
},

View File

@@ -5,11 +5,10 @@ const extractKeyFromCookie = require('../../utils/extractKeyFromCookie')
const { getUserByPubKey } = require('../../auth/utils/helperFuncs')
const { getDirectUploadUrl } = require('../../services/imageUpload.service')
const { prisma } = require('../../prisma')
const { getUrlFromProvider } = require('../../utils/resolveImageUrl')
const postUploadImageUrl = async (req, res) => {
return res.status(404).send("This api is in progress");
const userPubKey = await extractKeyFromCookie(req.headers.cookie ?? req.headers.Cookie)
const user = await getUserByPubKey(userPubKey)
@@ -22,11 +21,16 @@ const postUploadImageUrl = async (req, res) => {
try {
const uploadUrl = await getDirectUploadUrl()
await prisma.hostedImage.create({
data: { id: uploadUrl.id, filename },
const hostedImage = await prisma.hostedImage.create({
data: {
filename,
url: getUrlFromProvider(uploadUrl.provider, uploadUrl.id),
provider_image_id: uploadUrl.id,
provider: uploadUrl.provider
},
})
return res.status(200).json(uploadUrl)
return res.status(200).json({ id: hostedImage.id, uploadURL: uploadUrl.uploadURL })
} catch (error) {
res.status(500).send('Unexpected error happened, please try again')
}

View File

@@ -1,11 +1,21 @@
const { CONSTS } = require('../utils')
const axios = require('axios')
const FormData = require('form-data')
const { prisma } = require('../prisma')
const BASE_URL = 'https://api.cloudflare.com/client/v4'
const operationUrls = {
'image.uploadUrl': `${BASE_URL}/accounts/${CONSTS.CLOUDFLARE_IMAGE_ACCOUNT_ID}/images/v2/direct_upload`,
'image.delete': `${BASE_URL}/accounts/${CONSTS.CLOUDFLARE_IMAGE_ACCOUNT_ID}/images/v1/`,
}
function getAxiosConfig() {
return {
headers: {
Authorization: `Bearer ${CONSTS.CLOUDFLARE_IMAGE_API_KEY}`,
},
}
}
async function getDirectUploadUrl() {
@@ -27,9 +37,62 @@ async function getDirectUploadUrl() {
throw new Error(result.data, { cause: result.data.errors })
}
return result.data.result
const data = result.data.result
return { id: data.id, uploadURL: data.uploadURL, provider: 'cloudflare' }
}
async function deleteImageFromProvider(providerImageId) {
try {
const url = operationUrls['image.delete'] + providerImageId
const result = await axios.delete(url, getAxiosConfig())
if (!result.data.success) {
throw new Error(result.data, { cause: result.data.errors })
}
} catch (error) {
throw error
}
}
async function deleteImage(hostedImageId) {
if (!hostedImageId) throw new Error("argument 'hostedImageId' must be provider")
const hostedImage = await prisma.hostedImage.findFirst({
where: {
id: hostedImageId,
},
})
if (!hostedImage) throw new Error(`No HostedImage row found for HostedImage.id=${hostedImageId}`)
if (hostedImage.provider_image_id && hostedImage.provider_image_id === '')
throw new Error(`Field 'provider_image_id' for HostedImage.id=${hostedImageId} must not be empty. Current value '${hostedImage.provider_image_id}'`)
// Set is_used to false in case of deletion fail from the hosting image provider. The scheduled job will try to delete the HostedImage row
await prisma.hostedImage.update({
where: {
id: hostedImage.id,
},
data: {
is_used: false,
},
})
if (hostedImage.provider_image_id && hostedImage.provider_image_id !== '') {
deleteImageFromProvider(hostedImage.provider_image_id)
.then(async () => {
await prisma.hostedImage.delete({
where: {
id: hostedImageId,
},
})
})
.catch((error) => console.error(error))
}
}
module.exports = {
getDirectUploadUrl,
deleteImage,
deleteImageFromProvider,
}

View File

@@ -3,6 +3,7 @@ const JWT_SECRET = process.env.JWT_SECRET
const LNURL_AUTH_HOST = process.env.LNURL_AUTH_HOST
const CLOUDFLARE_IMAGE_ACCOUNT_ID = process.env.CLOUDFLARE_IMAGE_ACCOUNT_ID
const CLOUDFLARE_IMAGE_API_KEY = process.env.CLOUDFLARE_IMAGE_API_KEY
const CLOUDFLARE_IMAGE_ACCOUNT_HASH = process.env.CLOUDFLARE_IMAGE_ACCOUNT_HASH
const CONSTS = {
JWT_SECRET,
@@ -10,6 +11,7 @@ const CONSTS = {
LNURL_AUTH_HOST,
CLOUDFLARE_IMAGE_ACCOUNT_ID,
CLOUDFLARE_IMAGE_API_KEY,
CLOUDFLARE_IMAGE_ACCOUNT_HASH
}
module.exports = CONSTS

View File

@@ -0,0 +1,45 @@
const { CLOUDFLARE_IMAGE_ACCOUNT_HASH } = require('./consts')
const PROVIDERS = [
{
name: 'cloudflare',
prefixUrl: `https://imagedelivery.net/${CLOUDFLARE_IMAGE_ACCOUNT_HASH}/`,
variants: [
{
default: true,
name: 'public',
},
],
},
]
/**
* resolveImgObjectToUrl
* @param {object} imgObject
* @param {string} variant - List to be defined. DEFAULT TO 'public'
* @returns {string} image url
*/
function resolveImgObjectToUrl(imgObject, variant = null) {
if (!imgObject) return null;
if (imgObject.provider === 'external') {
return imgObject.url
}
return getUrlFromProvider(imgObject.provider, imgObject.provider_image_id, variant)
}
function getUrlFromProvider(provider, providerImageId, variant = null) {
const p = PROVIDERS.find((p) => p.name === provider)
if (p) {
if (p && p.name === 'cloudflare') {
const variantName = variant ?? p.variants.find((v) => v.default).name
return p.prefixUrl + providerImageId + '/' + variantName
}
}
throw new Error('Hosting images provider not supported')
}
module.exports = { resolveImgObjectToUrl, getUrlFromProvider }