chore: fix type errors and update bun sql syntax
This commit is contained in:
parent
b9fe32053c
commit
ae2455e73e
9 changed files with 325 additions and 398 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -47,3 +47,4 @@ package-lock.json
|
|||
/db
|
||||
/data
|
||||
/Bruno
|
||||
/tsconfig.tsbuildinfo
|
||||
|
|
@ -1,4 +1,7 @@
|
|||
export const BaseHtml = ({ children, title = "ConvertX" }) => (
|
||||
export const BaseHtml = ({
|
||||
children,
|
||||
title = "ConvertX",
|
||||
}: { children: JSX.Element; title?: string }) => (
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export const Header = ({
|
|||
}
|
||||
|
||||
return (
|
||||
<header className="container">
|
||||
<header class="container">
|
||||
<nav>
|
||||
<ul>
|
||||
<li>
|
||||
|
|
|
|||
|
|
@ -260,6 +260,7 @@ export const properties = {
|
|||
"mpegts",
|
||||
"mpegtsraw",
|
||||
"mpegvideo",
|
||||
"mpg",
|
||||
"mpjpeg",
|
||||
"mpl2",
|
||||
"mpo",
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ for (const converterName in properties) {
|
|||
}
|
||||
possibleInputs.sort();
|
||||
|
||||
export const getPossibleInputs = () => {
|
||||
const getPossibleInputs = () => {
|
||||
return possibleInputs;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,119 +0,0 @@
|
|||
import sharp from "sharp";
|
||||
import type { FormatEnum } from "sharp";
|
||||
|
||||
// declare possible conversions
|
||||
export const properties = {
|
||||
from: {
|
||||
images: [
|
||||
"avif",
|
||||
"bif",
|
||||
"csv",
|
||||
"exr",
|
||||
"fits",
|
||||
"gif",
|
||||
"hdr.gz",
|
||||
"hdr",
|
||||
"heic",
|
||||
"heif",
|
||||
"img.gz",
|
||||
"img",
|
||||
"j2c",
|
||||
"j2k",
|
||||
"jp2",
|
||||
"jpeg",
|
||||
"jpx",
|
||||
"jxl",
|
||||
"mat",
|
||||
"mrxs",
|
||||
"ndpi",
|
||||
"nia.gz",
|
||||
"nia",
|
||||
"nii.gz",
|
||||
"nii",
|
||||
"pdf",
|
||||
"pfm",
|
||||
"pgm",
|
||||
"pic",
|
||||
"png",
|
||||
"ppm",
|
||||
"raw",
|
||||
"scn",
|
||||
"svg",
|
||||
"svs",
|
||||
"svslide",
|
||||
"szi",
|
||||
"tif",
|
||||
"tiff",
|
||||
"v",
|
||||
"vips",
|
||||
"vms",
|
||||
"vmu",
|
||||
"webp",
|
||||
"zip",
|
||||
],
|
||||
},
|
||||
to: {
|
||||
images: [
|
||||
"avif",
|
||||
"dzi",
|
||||
"fits",
|
||||
"gif",
|
||||
"hdr.gz",
|
||||
"heic",
|
||||
"heif",
|
||||
"img.gz",
|
||||
"j2c",
|
||||
"j2k",
|
||||
"jp2",
|
||||
"jpeg",
|
||||
"jpx",
|
||||
"jxl",
|
||||
"mat",
|
||||
"nia.gz",
|
||||
"nia",
|
||||
"nii.gz",
|
||||
"nii",
|
||||
"png",
|
||||
"tiff",
|
||||
"vips",
|
||||
"webp",
|
||||
],
|
||||
},
|
||||
options: {
|
||||
svg: {
|
||||
scale: {
|
||||
description: "Scale the image up or down",
|
||||
type: "number",
|
||||
default: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export async function convert(
|
||||
filePath: string,
|
||||
fileType: string,
|
||||
convertTo: keyof FormatEnum,
|
||||
targetPath: string,
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
options?: any,
|
||||
) {
|
||||
if (fileType === "svg") {
|
||||
const scale = options.scale || 1;
|
||||
const metadata = await sharp(filePath).metadata();
|
||||
|
||||
if (!metadata || !metadata.width || !metadata.height) {
|
||||
throw new Error("Could not get metadata from image");
|
||||
}
|
||||
|
||||
const newWidth = Math.round(metadata.width * scale);
|
||||
const newHeight = Math.round(metadata.height * scale);
|
||||
|
||||
return await sharp(filePath)
|
||||
.resize(newWidth, newHeight)
|
||||
.toFormat(convertTo)
|
||||
.toFile(targetPath);
|
||||
}
|
||||
|
||||
return await sharp(filePath).toFormat(convertTo).toFile(targetPath);
|
||||
}
|
||||
|
|
@ -72,4 +72,14 @@ if (process.env.NODE_ENV === "production") {
|
|||
console.log(stdout.split("\n")[0]);
|
||||
}
|
||||
});
|
||||
|
||||
exec("bun -v", (error, stdout) => {
|
||||
if (error) {
|
||||
console.error("Bun is not installed. wait what");
|
||||
}
|
||||
|
||||
if (stdout) {
|
||||
console.log(`Bun v${stdout.split("\n")[0]}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
128
src/index.tsx
128
src/index.tsx
|
|
@ -75,27 +75,27 @@ if (dbVersion === 0) {
|
|||
|
||||
let FIRST_RUN = db.query("SELECT * FROM users").get() === null || false;
|
||||
|
||||
interface IUser {
|
||||
id: number;
|
||||
email: string;
|
||||
password: string;
|
||||
class User {
|
||||
id!: number;
|
||||
email!: string;
|
||||
password!: string;
|
||||
}
|
||||
|
||||
interface IFileNames {
|
||||
id: number;
|
||||
job_id: number;
|
||||
file_name: string;
|
||||
output_file_name: string;
|
||||
status: string;
|
||||
class Filename {
|
||||
id!: number;
|
||||
job_id!: number;
|
||||
file_name!: string;
|
||||
output_file_name!: string;
|
||||
status!: string;
|
||||
}
|
||||
|
||||
interface IJobs {
|
||||
finished_files: number;
|
||||
id: number;
|
||||
user_id: number;
|
||||
date_created: string;
|
||||
status: string;
|
||||
num_files: number;
|
||||
class Jobs {
|
||||
finished_files!: number;
|
||||
id!: number;
|
||||
user_id!: number;
|
||||
date_created!: string;
|
||||
status!: string;
|
||||
num_files!: number;
|
||||
}
|
||||
|
||||
// enable WAL mode
|
||||
|
|
@ -174,6 +174,7 @@ const app = new Elysia({
|
|||
|
||||
return (
|
||||
<BaseHtml title="ConvertX | Register">
|
||||
<>
|
||||
<Header accountRegistration={ACCOUNT_REGISTRATION} />
|
||||
<main class="container">
|
||||
<article>
|
||||
|
|
@ -204,6 +205,7 @@ const app = new Elysia({
|
|||
</form>
|
||||
</article>
|
||||
</main>
|
||||
</>
|
||||
</BaseHtml>
|
||||
);
|
||||
})
|
||||
|
|
@ -234,9 +236,17 @@ const app = new Elysia({
|
|||
savedPassword,
|
||||
);
|
||||
|
||||
const user = (await db
|
||||
const user = db
|
||||
.query("SELECT * FROM users WHERE email = ?")
|
||||
.get(body.email)) as IUser;
|
||||
.as(User)
|
||||
.get(body.email);
|
||||
|
||||
if (!user) {
|
||||
set.status = 500;
|
||||
return {
|
||||
message: "Failed to create user.",
|
||||
};
|
||||
}
|
||||
|
||||
const accessToken = await jwt.sign({
|
||||
id: String(user.id),
|
||||
|
|
@ -280,6 +290,7 @@ const app = new Elysia({
|
|||
|
||||
return (
|
||||
<BaseHtml title="ConvertX | Login">
|
||||
<>
|
||||
<Header accountRegistration={ACCOUNT_REGISTRATION} />
|
||||
<main class="container">
|
||||
<article>
|
||||
|
|
@ -317,15 +328,17 @@ const app = new Elysia({
|
|||
</form>
|
||||
</article>
|
||||
</main>
|
||||
</>
|
||||
</BaseHtml>
|
||||
);
|
||||
})
|
||||
.post(
|
||||
"/login",
|
||||
async function handler({ body, set, redirect, jwt, cookie: { auth } }) {
|
||||
const existingUser = (await db
|
||||
const existingUser = await db
|
||||
.query("SELECT * FROM users WHERE email = ?")
|
||||
.get(body.email)) as IUser;
|
||||
.as(User)
|
||||
.get(body.email);
|
||||
|
||||
if (!existingUser) {
|
||||
set.status = 403;
|
||||
|
|
@ -399,9 +412,10 @@ const app = new Elysia({
|
|||
}
|
||||
|
||||
// make sure user exists in db
|
||||
const existingUser = (await db
|
||||
const existingUser = await db
|
||||
.query("SELECT * FROM users WHERE id = ?")
|
||||
.get(user.id)) as IUser;
|
||||
.as(User)
|
||||
.get(user.id);
|
||||
|
||||
if (!existingUser) {
|
||||
if (auth?.value) {
|
||||
|
|
@ -438,6 +452,7 @@ const app = new Elysia({
|
|||
|
||||
return (
|
||||
<BaseHtml>
|
||||
<>
|
||||
<Header loggedIn />
|
||||
<main class="container">
|
||||
<article>
|
||||
|
|
@ -464,7 +479,8 @@ const app = new Elysia({
|
|||
<option selected disabled value="">
|
||||
Convert to
|
||||
</option>
|
||||
{Object.entries(getAllTargets()).map(([converter, targets]) => (
|
||||
{Object.entries(getAllTargets()).map(
|
||||
([converter, targets]) => (
|
||||
// biome-ignore lint/correctness/useJsxKeyInIterable: <explanation>
|
||||
<optgroup label={converter}>
|
||||
{targets.map((target) => (
|
||||
|
|
@ -474,13 +490,15 @@ const app = new Elysia({
|
|||
</option>
|
||||
))}
|
||||
</optgroup>
|
||||
))}
|
||||
),
|
||||
)}
|
||||
</select>
|
||||
</article>
|
||||
<input type="submit" value="Convert" />
|
||||
</form>
|
||||
</main>
|
||||
<script src="script.js" defer />
|
||||
</>
|
||||
</BaseHtml>
|
||||
);
|
||||
})
|
||||
|
|
@ -604,9 +622,10 @@ const app = new Elysia({
|
|||
return redirect("/", 302);
|
||||
}
|
||||
|
||||
const existingJob = (await db
|
||||
const existingJob = await db
|
||||
.query("SELECT * FROM jobs WHERE id = ? AND user_id = ?")
|
||||
.get(jobId.value, user.id)) as IJobs;
|
||||
.as(Jobs)
|
||||
.get(jobId.value, user.id);
|
||||
|
||||
if (!existingJob) {
|
||||
return redirect("/", 302);
|
||||
|
|
@ -635,14 +654,12 @@ const app = new Elysia({
|
|||
return redirect("/", 302);
|
||||
}
|
||||
|
||||
db.run(
|
||||
"UPDATE jobs SET num_files = ?, status = 'pending' WHERE id = ?",
|
||||
fileNames.length,
|
||||
jobId.value,
|
||||
);
|
||||
db.query(
|
||||
"UPDATE jobs SET num_files = ?1, status = 'pending' WHERE id = ?2",
|
||||
).run(fileNames.length, jobId.value);
|
||||
|
||||
const query = db.query(
|
||||
"INSERT INTO file_names (job_id, file_name, output_file_name, status) VALUES (?, ?, ?, ?)",
|
||||
"INSERT INTO file_names (job_id, file_name, output_file_name, status) VALUES (?1, ?2, ?3, ?4)",
|
||||
);
|
||||
|
||||
// Start the conversion process in the background
|
||||
|
|
@ -663,16 +680,18 @@ const app = new Elysia({
|
|||
{},
|
||||
converterName,
|
||||
);
|
||||
|
||||
if (jobId.value) {
|
||||
query.run(jobId.value, fileName, newFileName, result);
|
||||
}
|
||||
}),
|
||||
)
|
||||
.then(() => {
|
||||
// All conversions are done, update the job status to 'completed'
|
||||
db.run(
|
||||
"UPDATE jobs SET status = 'completed' WHERE id = ?",
|
||||
if (jobId.value) {
|
||||
db.query("UPDATE jobs SET status = 'completed' WHERE id = ?1").run(
|
||||
jobId.value,
|
||||
);
|
||||
}
|
||||
|
||||
// delete all uploaded files in userUploadsDir
|
||||
// rmSync(userUploadsDir, { recursive: true, force: true });
|
||||
|
|
@ -703,12 +722,14 @@ const app = new Elysia({
|
|||
|
||||
let userJobs = db
|
||||
.query("SELECT * FROM jobs WHERE user_id = ?")
|
||||
.all(user.id) as IJobs[];
|
||||
.as(Jobs)
|
||||
.all(user.id);
|
||||
|
||||
for (const job of userJobs) {
|
||||
const files = db
|
||||
.query("SELECT * FROM file_names WHERE job_id = ?")
|
||||
.all(job.id) as IFileNames[];
|
||||
.as(Filename)
|
||||
.all(job.id);
|
||||
|
||||
job.finished_files = files.length;
|
||||
}
|
||||
|
|
@ -718,6 +739,7 @@ const app = new Elysia({
|
|||
|
||||
return (
|
||||
<BaseHtml title="ConvertX | Results">
|
||||
<>
|
||||
<Header loggedIn />
|
||||
<main class="container">
|
||||
<article>
|
||||
|
|
@ -749,6 +771,7 @@ const app = new Elysia({
|
|||
</table>
|
||||
</article>
|
||||
</main>
|
||||
</>
|
||||
</BaseHtml>
|
||||
);
|
||||
})
|
||||
|
|
@ -769,9 +792,10 @@ const app = new Elysia({
|
|||
return redirect("/login", 302);
|
||||
}
|
||||
|
||||
const job = (await db
|
||||
const job = await db
|
||||
.query("SELECT * FROM jobs WHERE user_id = ? AND id = ?")
|
||||
.get(user.id, params.jobId)) as IJobs;
|
||||
.as(Jobs)
|
||||
.get(user.id, params.jobId);
|
||||
|
||||
if (!job) {
|
||||
set.status = 404;
|
||||
|
|
@ -784,10 +808,12 @@ const app = new Elysia({
|
|||
|
||||
const files = db
|
||||
.query("SELECT * FROM file_names WHERE job_id = ?")
|
||||
.all(params.jobId) as IFileNames[];
|
||||
.as(Filename)
|
||||
.all(params.jobId);
|
||||
|
||||
return (
|
||||
<BaseHtml title="ConvertX | Result">
|
||||
<>
|
||||
<Header loggedIn />
|
||||
<main class="container">
|
||||
<article>
|
||||
|
|
@ -843,6 +869,7 @@ const app = new Elysia({
|
|||
</article>
|
||||
</main>
|
||||
<script src="/results.js" defer />
|
||||
</>
|
||||
</BaseHtml>
|
||||
);
|
||||
},
|
||||
|
|
@ -864,9 +891,10 @@ const app = new Elysia({
|
|||
return redirect("/login", 302);
|
||||
}
|
||||
|
||||
const job = (await db
|
||||
const job = await db
|
||||
.query("SELECT * FROM jobs WHERE user_id = ? AND id = ?")
|
||||
.get(user.id, params.jobId)) as IJobs;
|
||||
.as(Jobs)
|
||||
.get(user.id, params.jobId);
|
||||
|
||||
if (!job) {
|
||||
set.status = 404;
|
||||
|
|
@ -879,7 +907,8 @@ const app = new Elysia({
|
|||
|
||||
const files = db
|
||||
.query("SELECT * FROM file_names WHERE job_id = ?")
|
||||
.all(params.jobId) as IFileNames[];
|
||||
.as(Filename)
|
||||
.all(params.jobId);
|
||||
|
||||
return (
|
||||
<article>
|
||||
|
|
@ -975,6 +1004,7 @@ const app = new Elysia({
|
|||
|
||||
return (
|
||||
<BaseHtml title="ConvertX | Converters">
|
||||
<>
|
||||
<Header loggedIn />
|
||||
<main class="container">
|
||||
<article>
|
||||
|
|
@ -988,7 +1018,8 @@ const app = new Elysia({
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Object.entries(getAllTargets()).map(([converter, targets]) => {
|
||||
{Object.entries(getAllTargets()).map(
|
||||
([converter, targets]) => {
|
||||
const inputs = getAllInputs(converter);
|
||||
return (
|
||||
// biome-ignore lint/correctness/useJsxKeyInIterable: <explanation>
|
||||
|
|
@ -1014,11 +1045,13 @@ const app = new Elysia({
|
|||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
},
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</article>
|
||||
</main>
|
||||
</>
|
||||
</BaseHtml>
|
||||
);
|
||||
})
|
||||
|
|
@ -1065,7 +1098,8 @@ const clearJobs = () => {
|
|||
// get all files older than 24 hours
|
||||
const jobs = db
|
||||
.query("SELECT * FROM jobs WHERE date_created < ?")
|
||||
.all(new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString()) as IJobs[];
|
||||
.as(Jobs)
|
||||
.all(new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString());
|
||||
|
||||
for (const job of jobs) {
|
||||
// delete the directories
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@
|
|||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"allowJs": true,
|
||||
"types": [
|
||||
"bun-types" // add Bun global
|
||||
],
|
||||
// non bun init
|
||||
"plugins": [{ "name": "@kitajs/ts-html-plugin" }],
|
||||
"noUncheckedIndexedAccess": true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue