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
1 change: 0 additions & 1 deletion Announcement.md

This file was deleted.

42 changes: 20 additions & 22 deletions build/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ const body_parser_1 = __importDefault(require("body-parser"));
const cors_1 = __importDefault(require("cors"));
const path_1 = __importDefault(require("path"));
const helmet_1 = __importDefault(require("helmet"));
const logger_1 = __importDefault(require("./logging/logger"));
const logger_1 = require("./logging/logger");
const dotenv_1 = __importDefault(require("dotenv"));
const express_rate_limit_1 = __importDefault(require("express-rate-limit"));
const httpLogger_1 = __importDefault(require("./logging/httpLogger"));
const httpLogger_1 = require("./logging/httpLogger");
const redis_1 = require("redis");
const http_errors_1 = __importDefault(require("http-errors"));
const connect_1 = __importDefault(require("./db/connect"));
dotenv_1.default.config({ path: "./.env" });
const connect_1 = require("./db/connect");
const url_1 = __importDefault(require("./route/url"));
const user_1 = __importDefault(require("./route/user"));
const base_1 = __importDefault(require("./route/base"));
dotenv_1.default.config({ path: './.env' });
const app = (0, express_1.default)();
const redisClient = (0, redis_1.createClient)({
password: process.env.REDIS_PASSWORD,
Expand All @@ -24,53 +27,48 @@ const redisClient = (0, redis_1.createClient)({
port: parseInt(process.env.REDIS_PORT || '6379'),
},
});
redisClient.on("error", (err) => console.log("Redis Client Error", err));
redisClient.on("connect", () => console.log("Redis connected successfully"));
app.use((req, res, next) => {
req.redisClient = redisClient;
next();
});
redisClient.on('error', (err) => console.log('Redis Client Error', err));
redisClient.on('connect', () => console.log('Redis connected successfully'));
const limiter = (0, express_rate_limit_1.default)({
windowMs: 0.5 * 60 * 1000, // 15 minutes
windowMs: 0.5 * 60 * 1000, // 30 seconds
max: 4,
standardHeaders: true,
legacyHeaders: false,
});
app.use(limiter);
const urlRouter = require("./route/url");
const userRouter = require("./route/user");
const mainRouter = require("./route/base");
app.use((0, helmet_1.default)());
app.use(httpLogger_1.default);
app.use(httpLogger_1.httpLogger);
app.use(express_1.default.json());
app.use(body_parser_1.default.json());
app.use((0, cors_1.default)());
app.use(express_1.default.static('public'));
app.set('view engine', 'ejs');
app.set('views', path_1.default.join(__dirname, 'views'));
app.use(express_1.default.urlencoded({ extended: false }));
app.use("/api/auth", userRouter);
app.use("/api/url", urlRouter);
app.use("/", mainRouter);
app.use('/api/auth', user_1.default);
app.use('/api/url', url_1.default);
app.use('/', base_1.default);
app.use((req, res, next) => {
next(http_errors_1.default.NotFound());
});
app.use((err, req, res, next) => {
const status = err.status || 500;
const message = err.message || 'Internal Server Error';
logger_1.default.error(err.message);
logger_1.logger.error(err.message);
res.status(status).json({ status, message });
});
const port = process.env.PORT || 4400;
const start = async () => {
try {
await (0, connect_1.default)(process.env.MONGO_URI || '');
await (0, connect_1.connect)(process.env.MONGO_URI || '');
await redisClient.connect();
app.listen(port, () => {
logger_1.default.info(`Server is running on port ${port}...`);
logger_1.logger.info(`Server is running on port ${port}...`);
});
}
catch (err) {
console.log(err);
console.error('Failed to start server:', err);
process.exit(1);
}
};
start();
19 changes: 19 additions & 0 deletions build/config/redis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const redis_1 = require("redis");
const dotenv_1 = __importDefault(require("dotenv"));
dotenv_1.default.config();
const redisClient = (0, redis_1.createClient)({
password: process.env.REDIS_PASSWORD,
socket: {
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT || '6379'),
},
});
// Log redis errors
redisClient.on('error', (err) => console.log('Redis Client Error', err));
redisClient.on('connect', () => console.log('Redis connected successfully'));
exports.default = redisClient;
Binary file added build/controller/auth.js
Binary file not shown.
Binary file added build/controller/urlController.js
Binary file not shown.
Binary file added build/controller/userController.js
Binary file not shown.
43 changes: 43 additions & 0 deletions build/db/connect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.connect = void 0;
const mongoose_1 = __importDefault(require("mongoose"));
const dotenv = __importStar(require("dotenv"));
dotenv.config();
const connect = async (url) => {
try {
await mongoose_1.default.connect(url);
console.log('MongoDB connected successfully');
}
catch (error) {
console.error('MongoDB connection error:', error);
throw error;
}
};
exports.connect = connect;
33 changes: 33 additions & 0 deletions build/logging/httpLogger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.httpLogger = void 0;
const morgan_1 = __importDefault(require("morgan"));
const logger_1 = require("./logger");
// Create a simple format function since morgan-json types are problematic
const format = (tokens, req, res) => {
return JSON.stringify({
method: tokens.method(req, res),
url: tokens.url(req, res),
status: tokens.status(req, res),
contentLength: tokens.res(req, res, 'content-length'),
responseTime: tokens['response-time'](req, res),
});
};
exports.httpLogger = (0, morgan_1.default)(format, {
stream: {
write: (message) => {
const { method, url, status, contentLength, responseTime, } = JSON.parse(message);
logger_1.logger.info('HTTP Access Log', {
timestamp: new Date().toString(),
method,
url,
status: Number(status),
contentLength,
responseTime: Number(responseTime),
});
},
},
});
31 changes: 31 additions & 0 deletions build/logging/logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.logger = void 0;
const winston_1 = __importDefault(require("winston"));
const options = {
files: {
level: 'info',
filename: './logs/app.log',
handleExceptions: true,
maxsize: 5242880, // 5MB
maxFiles: 5,
colorize: false,
},
console: {
level: 'debug',
handleExceptions: true,
json: false,
colorize: true,
},
};
exports.logger = winston_1.default.createLogger({
level: 'info',
transports: [
new winston_1.default.transports.File(options.files),
new winston_1.default.transports.Console(options.console),
],
exitOnError: false,
});
Binary file added build/middleware/authentication.js
Binary file not shown.
21 changes: 21 additions & 0 deletions build/models/clicks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Clicks = void 0;
const mongoose_1 = __importDefault(require("mongoose"));
const clicksSchema = new mongoose_1.default.Schema({
urlId: {
type: mongoose_1.default.Schema.Types.ObjectId,
ref: 'Url',
},
createdAt: {
type: Date,
default: Date.now,
},
ipAddress: {
type: String,
},
});
exports.Clicks = mongoose_1.default.model('Clicks', clicksSchema);
Binary file added build/models/url.js
Binary file not shown.
28 changes: 28 additions & 0 deletions build/models/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.User = void 0;
const mongoose_1 = __importDefault(require("mongoose"));
const validator_1 = __importDefault(require("validator"));
const userSchema = new mongoose_1.default.Schema({
username: {
type: String,
required: true,
},
email: {
type: String,
unique: true,
required: [true, 'Please provide email'],
validate: {
validator: (value) => validator_1.default.isEmail(value),
message: 'Please provide a valid email',
},
},
password: {
type: String,
required: true,
}
}, { timestamps: true });
exports.User = mongoose_1.default.model('User', userSchema);
14 changes: 14 additions & 0 deletions build/route/base.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const urlController_1 = require("../controller/urlController");
const router = express_1.default.Router();
router.route('/').get((req, res) => {
res.render('landing');
});
// Redirect route for short URLs - must be last to catch all shortId patterns
router.get('/:shortId', urlController_1.redirectToLongUrl);
exports.default = router;
Binary file added build/route/url.js
Binary file not shown.
27 changes: 27 additions & 0 deletions build/route/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const auth_1 = require("../controller/auth");
const userController_1 = require("../controller/userController");
const router = express_1.default.Router();
router.get('/signup', (req, res) => {
res.render('signup');
});
router.post('/signup', auth_1.register);
router.get('/login', (req, res) => {
res.render('login');
});
router.post('/login', auth_1.login);
router.get('/history/:userId', (req, res) => {
res.render('link history');
});
// Get link history
router.get('/link-history/:userId', userController_1.getLinkHistory);
// Get by Id
router.get('/user/:userId', userController_1.getUserById);
// Get all users
router.get('/users', userController_1.getAllUsers);
exports.default = router;
Binary file added build/services/authService.js
Binary file not shown.
Binary file added build/services/urlService.js
Binary file not shown.
42 changes: 42 additions & 0 deletions build/services/userService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserService = void 0;
const user_1 = require("../models/user");
class UserService {
/**
* Find user by email
*/
async findByEmail(email) {
return await user_1.User.findOne({ email });
}
/**
* Find user by ID
*/
async findById(userId) {
return await user_1.User.findById(userId);
}
/**
* Create a new user
*/
async createUser(username, email, hashedPassword) {
return await user_1.User.create({
username,
email,
password: hashedPassword,
});
}
/**
* Get all users
*/
async getAllUsers() {
return await user_1.User.find();
}
/**
* Check if user exists by email
*/
async userExists(email) {
const user = await user_1.User.findOne({ email });
return !!user;
}
}
exports.UserService = UserService;
Binary file added build/types/index.js
Binary file not shown.
Loading