Skip to content

Commit

Permalink
feat: add commitlint and husky for commit message validation and work…
Browse files Browse the repository at this point in the history
…flow improvements

- Integrated commitlint with conventional commit configuration for standardized commit messages
- Set up husky with pre-commit and commit-msg hooks for automated checks
- Updated package.json with a prepare script for husky installation
- Configured commitlint rules to ensure consistent commit message formatting
- Updated dependencies to support commitlint and husky integration
- Improved development workflow by enforcing commit message validation
v0id-user committed Jan 27, 2025
1 parent e4b4e08 commit beb6497
Showing 15 changed files with 1,462 additions and 314 deletions.
2 changes: 2 additions & 0 deletions .husky/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
npx --no -- commitlint --edit ${1}
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npm run lint
2 changes: 1 addition & 1 deletion app/api/blog/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NextResponse } from 'next/server';
import { getPostPublished, getPublishedPosts } from '@/lib/blog';
export const maxDuration = 30;

export const maxDuration = 30;

export async function GET(request: Request) {
try {
40 changes: 19 additions & 21 deletions app/api/s3/presign/route.ts
Original file line number Diff line number Diff line change
@@ -2,7 +2,9 @@ import { getSpacerToken } from "@/lib/token";
import { S3Client, PutObjectCommand, HeadObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { NextResponse } from "next/server";
import { BlogPresignedUrlRequest, BlogPresignedUrlResponse } from "@/interfaces/blog";
export const maxDuration = 30;

// Initialize S3 client with standard AWS configuration
const s3Client = new S3Client({
region: process.env.AWS_REGION || 'auto',
@@ -34,23 +36,23 @@ export async function POST(request: Request) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}

const { filename, contentType, fileSize, hash } = await request.json();
const presignedUrlRequest = await request.json() as BlogPresignedUrlRequest | null;

// Validate required fields
if (!filename || !contentType || !fileSize || !hash) {
if (!presignedUrlRequest?.filename || !presignedUrlRequest?.contentType || !presignedUrlRequest?.fileSize || !presignedUrlRequest?.hash) {
return NextResponse.json({
error: "Missing required fields: filename, contentType, fileSize, or hash"
}, { status: 400 });
}

// Security checks
if (!ALLOWED_MIME_TYPES.includes(contentType)) {
if (!ALLOWED_MIME_TYPES.includes(presignedUrlRequest.contentType)) {
return NextResponse.json({
error: "File type not allowed"
}, { status: 400 });
}

if (fileSize > MAX_FILE_SIZE) {
if (presignedUrlRequest.fileSize > MAX_FILE_SIZE) {
return NextResponse.json({
error: "File size exceeds maximum allowed size of 5MB"
}, { status: 400 });
@@ -61,9 +63,9 @@ export async function POST(request: Request) {
}

// Extract file extension
const fileExtension = filename.split('.').pop()?.toLowerCase() || '';
const fileExtension = presignedUrlRequest.filename.split('.').pop()?.toLowerCase() || '';
// Generate key based on hash and original extension
const key = `uploads/${hash}.${fileExtension}`;
const key = `uploads/${presignedUrlRequest.hash}.${fileExtension}`;

try {
// Check if file already exists
@@ -77,22 +79,21 @@ export async function POST(request: Request) {
// File exists, return the public URL without generating a new presigned URL
const publicUrl = `${process.env.STORAGE_DOMAIN}/${key}`;

return NextResponse.json({
exists: true,
publicUrl,
key
});
const response: BlogPresignedUrlResponse = {
publicUrl
}
return NextResponse.json(response);
} catch (error) {
// File doesn't exist, generate presigned URL for upload
if (error instanceof Error && 'name' in error && error.name === 'NotFound') {
const command = new PutObjectCommand({
Bucket: process.env.AWS_BUCKET_NAME,
Key: key,
ContentType: contentType,
ContentType: presignedUrlRequest.contentType,
CacheControl: 'public, max-age=31536000',
Metadata: {
'original-filename': filename,
'content-hash': hash,
'original-filename': presignedUrlRequest.filename,
'content-hash': presignedUrlRequest.hash,
'upload-date': new Date().toISOString(),
}
});
@@ -102,14 +103,11 @@ export async function POST(request: Request) {
});

const publicUrl = `${process.env.STORAGE_DOMAIN}/${key}`;

return NextResponse.json({
exists: false,
presignedUrl,
const response: BlogPresignedUrlResponse = {
publicUrl,
expiresIn: 600,
key
});
presignedUrl
}
return NextResponse.json(response);
}
throw error;
}
14 changes: 14 additions & 0 deletions app/portfolio/projects.ts
Original file line number Diff line number Diff line change
@@ -105,6 +105,13 @@ export const projects: Project[] = [
technologies: ["C", "Networking", "Protocol Design"],
githubUrl: "https://github.com/v0id-user/DFTP"
},
{
name: "PMPS",
date: "May 2024",
description: "C/C++ library and tool for scanning a process's memory space on Windows to find regex string patterns.",
technologies: ["C", "Windows API", "Regex", "Memory Scanning"],
githubUrl: "https://github.com/GhaynOrg/PMPS"
},
{
name: "Postgres-Reactive-SSE-Example",
date: "December 2024",
@@ -118,5 +125,12 @@ export const projects: Project[] = [
description: "Experimented with implementing asynchronous functionality in C, exploring low-level concurrency concepts.",
technologies: ["C", "Asynchronous Programming"],
githubUrl: "https://github.com/v0id-user/CAsyncPolling"
},
{
name: "v0id-land",
date: "January 2025",
description: "My personal website, where I integrated my own blog system, portfolio, and other projects in it.",
technologies: ["Next.js", "Tailwind CSS", "PostgreSQL", "Prisma", "S3", "Shadcn/UI"],
githubUrl: "https://github.com/v0id-user/v0id-land"
}
];
Binary file modified bun.lockb
Binary file not shown.
28 changes: 28 additions & 0 deletions commitlint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
[
'build',
'chore',
'ci',
'docs',
'feat',
'fix',
'perf',
'refactor',
'revert',
'style',
'test'
]
],
'type-case': [2, 'always', 'lower-case'],
'type-empty': [2, 'never'],
'scope-case': [2, 'always', 'lower-case'],
'subject-empty': [2, 'never'],
'subject-full-stop': [2, 'never', '.'],
'header-max-length': [0, 'always', 100]
}
};
Loading
Oops, something went wrong.

0 comments on commit beb6497

Please sign in to comment.