Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions app/(api)/_actions/cloudinary/deleteCloudinaryItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use server';
import HttpError from '@utils/response/HttpError';
import { v2 as cloudinary } from 'cloudinary';

cloudinary.config({
cloud_name: process.env.CLOUDINARY_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});

export default async function DeleteCloudinaryObject(
cloudinary_id: string,
type: string
) {
try {
const result = await cloudinary.uploader.destroy(cloudinary_id, {
resource_type: type,
});
return {
ok: true,
body: result,
error: null,
};
} catch (e) {
const err = e as HttpError;
return {
ok: false,
body: null,
error: err.message,
};
}
}
32 changes: 32 additions & 0 deletions app/(api)/_actions/cloudinary/generateCloudinarySignature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use server';
import HttpError from '@utils/response/HttpError';
import { v2 as cloudinary } from 'cloudinary';

export default async function GenerateCloudinarySignature(
requestParams: object
) {
try {
const timestamp = Math.round(new Date().getTime() / 1000);
const signature = cloudinary.utils.api_sign_request(
{
timestamp,
...requestParams,
},
process.env.CLOUDINARY_API_SECRET as string
);

const body = {
cloudUrl: `https://api.cloudinary.com/v1_1/${process.env.CLOUDINARY_NAME}`,
requestParams: {
api_key: process.env.CLOUDINARY_API_KEY,
timestamp,
signature,
...requestParams,
},
};
return { ok: true, body, error: null };
} catch (e) {
const error = e as HttpError;
return { ok: false, body: null, error: error.message };
}
}
11 changes: 11 additions & 0 deletions app/(api)/_actions/media/createMediaItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use server';
import { createMediaItem } from '@datalib/media/createMediaItem';
import { revalidatePath } from 'next/cache';
// import WithCallback from '@app/(api)/_utils/callback/withCallback';
import WithCallback from '@utils/callback/withCallback';

export const CreateMediaItem = WithCallback(async (body: object) => {
const createMediaItemRes = await createMediaItem(body);
revalidatePath('/uploaded-media');
return createMediaItemRes;
});
11 changes: 11 additions & 0 deletions app/(api)/_actions/media/deleteMediaItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use server';
import { deleteMediaItem } from '@datalib/media/deleteMediaItem';
import { revalidatePath } from 'next/cache';
// import WithCallback from '@app/(api)/_utils/callback/withCallback';
import WithCallback from '@utils/callback/withCallback';

export const DeleteMediaItem = WithCallback(async (id: string) => {
const deleteMediaRes = await deleteMediaItem(id);
revalidatePath('/uploaded-media');
return deleteMediaRes;
});
11 changes: 11 additions & 0 deletions app/(api)/_actions/media/findMediaItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use server';

import { findMediaItem, findMediaItems } from '@datalib/media/findMediaItem';

export async function FindMediaItem(id: string) {
return findMediaItem(id);
}

export async function FindMediaItems(query: object = {}) {
return findMediaItems(query);
}
11 changes: 11 additions & 0 deletions app/(api)/_actions/media/updateMediaItems.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use server';
import { createMediaItem } from '@datalib/media/createMediaItem';
import { revalidatePath } from 'next/cache';
// import WithCallback from '@app/(api)/_utils/callback/withCallback';
import WithCallback from '@utils/callback/withCallback';
// import WithCallback from '@utils/callback/withCallback';
export const CreateMediaItem = WithCallback(async (body: object) => {
const createMediaItemRes = await createMediaItem(body);
revalidatePath('/uploaded-media');
return createMediaItemRes;
});
87 changes: 87 additions & 0 deletions app/(api)/_datalib/_services/Media.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import prisma from '../_prisma/client';
import { MediaInput } from '@datatypes/Media';
export default class MediaService {
// CREATE
static async create(input: MediaInput) {
const media = await prisma.media.create({
data: {
cloudinary_id: input.cloudinary_id,
name: input.name,
type: input.type,
format: input.format,
src: input.src,
alt: input.alt || null,
size: input.size,
width: input.width,
height: input.height,
created_at: input.created_at || new Date().toISOString(),
last_modified: input.last_modified || new Date().toISOString(),
},
});
return media;
}

// READ
static async find(id: string) {
return prisma.media.findUnique({
where: {
id,
},
});
}

// READ
static async findMany(ids: string[]) {
if (!ids || ids.length === 0) {
return prisma.media.findMany();
}

return prisma.media.findMany({
where: {
id: {
in: ids,
},
},
});
}

// UPDATE
static async update(id: string, input: Partial<MediaInput>) {
try {
const media = await prisma.media.update({
where: {
id,
},
data: {
cloudinary_id: input.cloudinary_id || undefined,
name: input.name || undefined,
type: input.type || undefined,
format: input.format || undefined,
src: input.src || undefined,
alt: input.alt || null, // If `alt` is not provided, set it to null
size: input.size || undefined,
width: input.width || undefined,
height: input.height || undefined,
last_modified: new Date().toISOString(), // Automatically set `last_modified` to current time
},
});
return media;
} catch (e) {
return null; // If update fails, return null
}
}

// DELETE
static async delete(id: string) {
try {
await prisma.media.delete({
where: {
id,
},
});
return true;
} catch (e) {
return false;
}
}
}
30 changes: 30 additions & 0 deletions app/(api)/_types/Media.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
interface Media {
_id: string | null;
cloudinary_id: string | null;
name: string;
type: string;
format: string;
src: string;
alt?: string;
size: number;
width: number | null;
height: number | null;
created_at?: string | null;
last_modified?: string | null;
}

export type MediaInput = {
cloudinary_id: string | null;
name: string;
type: string;
format: string;
src: string;
alt?: string;
size: number;
width: number | null;
height: number | null;
created_at?: string | null;
last_modified?: string | null;
};

export default Media;
10 changes: 10 additions & 0 deletions app/(api)/_utils/callback/withCallback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// import callbacks from '@app/_utils/callbacks';

// type CallbackFunction = (...args: any[]) => any;
// export default function WithCallback(func: (..._: any) => any) {
// return async (...args: any) => {
// const res = await func(...args);
// callbacks.onUpdate();
// return res;
// };
// }
62 changes: 62 additions & 0 deletions app/(api)/_utils/request/getQueries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { NextRequest } from 'next/server';
import prisma from '@datalib/_prisma/client';
// import { DMMF } from '@prisma/client/runtime';

function typeCast(value: string, type: string) {
switch (type) {
case 'Int':
return isNaN(+value) ? value : +value;
case 'String':
return value;
case 'Boolean':
if (value === 'true') {
return true;
} else if (value === 'false') {
return false;
} else {
return value;
}
default:
return value;
}
}

export default async function getQueries(
request: NextRequest,
content_type: string
) {
// Get the schema for the model in Prisma

interface Field {
name: string;
type: string;
}

interface Schema {
fields: Field[];
}

const schema: Schema | undefined = prisma
._getDmmf()
.datamodel.models.find(
(model: { name: string }) => model.name === content_type
);

if (!schema) {
throw new Error(`Model ${content_type} not found in Prisma schema.`);
}

const query_entries = request.nextUrl.searchParams.entries();
const output: { [key: string]: string | number | boolean } = {};

for (const [key, val] of query_entries) {
// Fetch the field type from the Prisma schema
const field = schema.fields.find((field) => field.name === key);
if (field) {
output[key] = typeCast(val, field.type);
} else {
output[key] = val; // If field is not found in schema, return as is
}
}
return output;
}
3 changes: 3 additions & 0 deletions app/(api)/_utils/request/isBodyEmpty.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function isBodyEmpty(obj: object) {
return Object.keys(obj).length === 0;
}
71 changes: 71 additions & 0 deletions app/(api)/_utils/request/prependAttributes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* Takes in a json object and renames one attribute.
*/
export function renameAttribute(jsonObj, oldFieldName, newFieldName) {
if (jsonObj[oldFieldName]) {
// Create a new object with the renamed attribute
const renamedObject = {
...jsonObj,
[newFieldName]: jsonObj[oldFieldName],
};

// Delete the old attribute
delete renamedObject[oldFieldName];
return renamedObject;
}

// Return the original object if the old attribute doesn't exist
return jsonObj;
}

/**
* subset of renaming attribute, appends a prefix of "prefix" before the attribute name
* "prefix" comes from mongodb nested documents
*/
export function prependToAttribute(jsonObj, attribute, prefix) {
return renameAttribute(jsonObj, attribute, `${prefix}${attribute}`);
}

/**
* For each attribute within an updater such as:
* {
* "$set": {"name": "austin", "age": 20}
* }
* (in this case, the fields in question are "name" and "age" and the updater is "$set")
* Append the prefix of prefix to each attribute.
*
* This results in:
* {
* "$set": {"PREFIXname": "austin", "PREFIXage": 20},
* }
* where prefix = PREFIX
*/
export function prependObjectAttributes(jsonObj, prefix) {
for (const key of Object.keys(jsonObj)) {
jsonObj = prependToAttribute(jsonObj, key, prefix);
}
return jsonObj;
}

/**
* For each updater within a request body
* {
* "$set": {"name": "austin", "age": 20},
* "$push": {"pokemon": ..., ...}
* }
* (in this case, the updaters in question are "$set" and "$push"
* run prependObjectAttributes() on the content within
*
* This results in:
* {
* "$set": {"PREFIXname": "austin", "PREFIXage": 20},
* "$push": {"PREFIXpokemon": ..., ...}
* }
* where prefix = PREFIX
*/
export function prependAllAttributes(jsonObj, prefix) {
for (const [key, val] of Object.entries(jsonObj)) {
jsonObj[key] = prependObjectAttributes(val, prefix);
}
return jsonObj;
}
9 changes: 9 additions & 0 deletions app/(api)/_utils/response/DuplicateError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import HttpError from './HttpError';

export default class DuplicateError extends HttpError {
constructor(message: string) {
super(message);
this.name = 'DuplicateError';
this.status = 409;
}
}
Loading
Loading