Skip to content
Merged
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
26 changes: 26 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Lint

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
eslint:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run ESLint
run: npm run lint
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[![Dependabot Updates](https://github.com/adminvns/testapi/actions/workflows/dependabot/dependabot-updates/badge.svg?branch=main)](https://github.com/adminvns/testapi/actions/workflows/dependabot/dependabot-updates)
[![Version](https://img.shields.io/github/v/tag/adminvns/testapi?label=version&color=blue)](https://github.com/adminvns/testapi/tags)
[![Lint](https://github.com/adminvns/testapi/actions/workflows/lint.yml/badge.svg)](https://github.com/adminvns/testapi/actions/workflows/lint.yml)
# testapi

A lightweight and customizable RESTful API built with Node.js and Express, designed for testing and learning purposes. This project serves as a foundational template for developers looking to understand API development, middleware integration, and deployment workflows.
Expand Down
46 changes: 23 additions & 23 deletions api/routes/orders.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
const express = require('express');
const router = express.Router();

router.get('/',(req, res, next)=> {
router.get('/', (req, res) => {

res.status(200).json({
res.status(200).json({

message: "Order was fetched"
});
message: 'Order was fetched'
});

});

router.post('/',(req, res, next)=> {
router.post('/', (req, res) => {

res.status(201).json({

message: 'Order was created'
});

res.status(201).json({

message: "Order was created"
});

});
});


router.get('/:orderID',(req, res, next)=>{
router.get('/:orderID', (req, res) => {

res.status(200).json({
message: "order details",
id: req.params.orderID
})
res.status(200).json({
message: 'order details',
id: req.params.orderID
});

})
});

router.delete('/:orderID',(req, res, next)=>{
router.delete('/:orderID', (req, res) => {

res.status(200).json({
message: "order deleted",
id: req.params.orderID
})
res.status(200).json({
message: 'order deleted',
id: req.params.orderID
});

})
});


module.exports = router;
56 changes: 28 additions & 28 deletions api/routes/products.js
Original file line number Diff line number Diff line change
@@ -1,59 +1,59 @@
const express = require('express');
const router = express.Router();

router.get('/', (req, res, next) => {
router.get('/', (req, res) => {

res.status(200).json({
res.status(200).json({

message: "Products(GET method)"
});
message: 'Products(GET method)'
});

});

router.post('/', (req, res, next) => {
router.post('/', (req, res) => {

res.status(201).json({
res.status(201).json({

message: "Products(POST method)"
});
message: 'Products(POST method)'
});
});



router.get('/:productID', (req, res, next) => {
router.get('/:productID', (req, res) => {

const id = req.params.productID;
if (id == 123) {
const id = req.params.productID;
if (id == 123) {

res.status(200).json({
message: "Congratulations on winning it",
id: id
});
res.status(200).json({
message: 'Congratulations on winning it',
id: id
});

} else {
} else {

res.status(200).json({
res.status(200).json({

message: "This is random id"
});
}
message: 'This is random id'
});
}

});


router.patch('/:productID', (req, res, next) => {
res.status(200).json({
router.patch('/:productID', (req, res) => {
res.status(200).json({

message: " Product updated successfully!"
})
message: ' Product updated successfully!'
});
Comment thread
adminvns marked this conversation as resolved.
Resolved
});


router.delete('/:productID', (req, res, next) => {
res.status(200).json({
router.delete('/:productID', (req, res) => {
res.status(200).json({

message: " Product deleted successfully."
})
message: ' Product deleted successfully.'
});
Comment on lines +52 to +56

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove leading space in message string.

Same issue here — ' Product deleted successfully.' has a leading space.

Suggested fix
-    message: ' Product deleted successfully.'
+    message: 'Product deleted successfully.'
🤖 Prompt for AI Agents
In @api/routes/products.js around lines 52 - 56, The response message in the
DELETE route handler for router.delete('/:productID', (req, res) => { ... })
contains a leading space (" Product deleted successfully."); remove the extra
leading space from the message string so it reads "Product deleted
successfully." to ensure consistent formatting in JSON responses.

});

module.exports = router;
44 changes: 22 additions & 22 deletions api/routes/visitors.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,35 @@ const router = express.Router();
const visitorLogs = [];

router.get('/', (req, res) => {
const ip = req.ip || req.connection.remoteAddress;
const timestamp = new Date().toISOString();
const ip = req.ip || req.connection.remoteAddress;
const timestamp = new Date().toISOString();

// Add new visit to logs
visitorLogs.push({
ip,
timestamp,
userAgent: req.get('User-Agent')
});
// Add new visit to logs
visitorLogs.push({
ip,
timestamp,
userAgent: req.get('User-Agent')
});

// Return all logs
res.status(200).json({
status: 'ok',
message: 'Visitor logs retrieved successfully',
totalVisits: visitorLogs.length,
logs: visitorLogs
});
// Return all logs
res.status(200).json({
status: 'ok',
message: 'Visitor logs retrieved successfully',
totalVisits: visitorLogs.length,
logs: visitorLogs
});
});

// Get statistics about visitors
router.get('/stats', (req, res) => {
const uniqueIPs = new Set(visitorLogs.map(log => log.ip)).size;
const uniqueIPs = new Set(visitorLogs.map(log => log.ip)).size;

res.status(200).json({
status: 'ok',
totalVisits: visitorLogs.length,
uniqueVisitors: uniqueIPs,
lastVisit: visitorLogs.length > 0 ? visitorLogs[visitorLogs.length - 1] : null
});
res.status(200).json({
status: 'ok',
totalVisits: visitorLogs.length,
uniqueVisitors: uniqueIPs,
lastVisit: visitorLogs.length > 0 ? visitorLogs[visitorLogs.length - 1] : null
});
});

module.exports = router;
40 changes: 20 additions & 20 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
var express = require('express');
var app = express();
const morgan = require('morgan')
const prodRoute = require('./api/routes/products')
const prodOrder = require('./api/routes/orders')
const express = require('express');
const app = express();
const morgan = require('morgan');
const prodRoute = require('./api/routes/products');
const prodOrder = require('./api/routes/orders');
const healthRoute = require('./api/routes/healthCheck');
const visitorsRoute = require('./api/routes/visitors');
//rerouting requests

app.use(morgan('dev'));
app.use('/products', prodRoute);
app.use('/orders',prodOrder);
app.use('/orders', prodOrder);
app.use('/health', healthRoute);
app.use('/visitors', visitorsRoute);

//error handling
app.use((req,res,next)=>{
app.use((req, res, next) => {

const err = new Error('This page does not exist, Navigate to /products or /orders or /visitors or /health');
err.status = 404;
next(err);
const err = new Error('This page does not exist, Navigate to /products or /orders or /visitors or /health');
err.status = 404;
next(err);


})
app.use((err,req,res,next)=>{

res.status(err.status || 500)
res.json({
error:{
message: err.message
},
});
});
app.use((err, req, res) => {

res.status(err.status || 500);
res.json({
error: {
message: err.message
},
});
});
Comment thread
adminvns marked this conversation as resolved.
Resolved


module.exports= app;
module.exports = app;
35 changes: 35 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const js = require('@eslint/js');

Check warning on line 1 in eslint.config.js

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

eslint.config.js#L1

Require statement not part of import statement.

module.exports = [
js.configs.recommended,
{
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'commonjs',
globals: {
console: 'readonly',
process: 'readonly',
require: 'readonly',
module: 'readonly',
__dirname: 'readonly',
__filename: 'readonly',
exports: 'readonly',
Buffer: 'readonly',
setTimeout: 'readonly',
setInterval: 'readonly',
clearTimeout: 'readonly',
clearInterval: 'readonly'
}
},
rules: {
'indent': ['error', 2],
'quotes': ['error', 'single'],
'semi': ['error', 'always'],
'no-unused-vars': ['warn'],
'no-console': 'off'
}
},
{
ignores: ['node_modules/', '*.log', '.env', 'coverage/', 'dist/', 'build/']
}
];
Loading