Skip to content

Commit 1c8cd88

Browse files
authored
Merge pull request #1 from chtgupta/feature/folders
Feature/folders
2 parents b69c922 + 626c2c1 commit 1c8cd88

11 files changed

+209
-15
lines changed

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"description": "",
55
"main": "main.ts",
66
"scripts": {
7-
"start": "tsc && node ./dist/index.js"
7+
"start": "tsc && node ./dist/index.js",
8+
"run": "node ./dist/index.js"
89
},
910
"author": "Chahat Gupta",
1011
"license": "ISC",

readme.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Mock API Manager
1+
# MockModel API Manager
22

3-
Welcome to my hobby project - the Mock API Manager! This TypeScript-based tool simplifies the creation and management of mock APIs for your development and testing needs.
3+
Welcome to my hobby project - the MockModel API Manager! This TypeScript-based tool simplifies the creation and management of mock APIs for your development and testing needs.
44

55
<img width="1440" alt="Screenshot 2023-09-16 at 11 13 59 PM" src="https://github.com/chtgupta/mock_api_backend/assets/22120812/8a5cbab6-bb82-48d5-b1dc-4037367fac94">
66

File renamed without changes.

src/common/constants.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default class Constants {
2+
static rootPath: string = 'root'
3+
}

src/helper/mock.helper.ts

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import {MockModel} from "../models/mock.model";
2+
3+
export default class MockHelper {
4+
5+
static toJson(model: MockModel) {
6+
return {
7+
id: model._id,
8+
parentId: model.parentId,
9+
name: model.name,
10+
response: model.response
11+
}
12+
}
13+
14+
}

src/helper/mock_folder.helper.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {MockFolder, MockFolderModel} from "../models/mock_folder.model";
2+
import {MockModel} from "../models/mock.model";
3+
import MockHelper from "./mock.helper";
4+
5+
export default class MockFolderHelper {
6+
7+
static toJson(model: MockFolderModel, folders: MockFolderModel[] | null = null, files: MockModel[] | null = null) : any {
8+
return {
9+
id: model._id,
10+
parentId: model.parentId,
11+
name: model.name,
12+
folders: folders?.map((e) => MockFolderHelper.toJson(e)),
13+
files: files?.map((e) => MockHelper.toJson(e))
14+
}
15+
}
16+
17+
}

src/index.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,12 @@ function configureServer(): void {
2222
app.use(express.urlencoded({extended: true}))
2323
app.use(express.json())
2424

25-
const routes = require('./routes')
26-
app.use('/', routes)
25+
const mockRoutes = require('./routes/mock.routes')
26+
const mockFolderRoutes = require('./routes/mock_folder.routes')
27+
const allRoutes = require('./routes/all.routes')
28+
29+
app.use('/folder', mockFolderRoutes) // do not move this below '/' else it clashes with /:id
30+
app.use('/', mockRoutes)
2731

2832
app.listen(process.env.PORT, (): void => {
2933
console.log(`Server running on port ${process.env.PORT}..`)
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
import { Schema, Model, model } from 'mongoose'
2+
import Constants from "../common/constants";
23

34
export type MockModel = {
4-
name: string,
5+
_id: string
6+
parentId: string | null
7+
name: string
58
response: string
6-
};
9+
}
710

811
const MockSchema: Schema<MockModel> = new Schema<MockModel>({
12+
_id: Schema.Types.ObjectId,
13+
parentId: {
14+
type: String,
15+
required: false,
16+
default: Constants.rootPath
17+
},
918
name: {
1019
type: String,
1120
required: true
@@ -14,6 +23,6 @@ const MockSchema: Schema<MockModel> = new Schema<MockModel>({
1423
type: String,
1524
required: true
1625
}
17-
});
26+
})
1827

1928
export const Mock: Model<MockModel> = model('Mock', MockSchema)

src/models/mock_folder.model.ts

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Schema, Model, model } from 'mongoose'
2+
import Constants from "../common/constants";
3+
4+
export type MockFolderModel = {
5+
_id: string
6+
parentId: string | null
7+
name: string
8+
}
9+
10+
const MockFolderSchema: Schema<MockFolderModel> = new Schema<MockFolderModel>({
11+
_id: Schema.Types.ObjectId,
12+
parentId: {
13+
type: String,
14+
required: false,
15+
default: Constants.rootPath
16+
},
17+
name: {
18+
type: String,
19+
required: true
20+
}
21+
})
22+
23+
export const MockFolder: Model<MockFolderModel> = model('MockFolder', MockFolderSchema)

src/routes.ts renamed to src/routes/mock.routes.ts

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import express, { Request, Response } from 'express'
2-
import { Mock, MockModel } from './models/mock'
3-
import { ApiResponse } from './models/api_response'
2+
import { Mock, MockModel } from '../models/mock.model'
3+
import { ApiResponse } from '../common/api_response'
44
import mongoose from 'mongoose'
5+
import MockHelper from "../helper/mock.helper";
6+
import { Types } from "mongoose";
57

68
const router = express.Router()
79

810
router.get('/', async (req: Request, res: Response): Promise<void> => {
911
try {
1012
const mocks: MockModel[] = await Mock.find()
11-
const response: ApiResponse = ApiResponse.success(mocks)
13+
const response: ApiResponse = ApiResponse.success(mocks.map((e) => MockHelper.toJson(e)))
1214
res.status(200).json(response)
1315
} catch (error: unknown) {
1416
const response: ApiResponse = ApiResponse.error((error as Error).message)
@@ -20,14 +22,14 @@ router.get('/:id', async (req: Request, res: Response): Promise<void> => {
2022
try {
2123
const mock: MockModel | null = await Mock.findById(req.params.id)
2224
if (mock != null) {
23-
const response: ApiResponse = ApiResponse.success(mock)
25+
const response: ApiResponse = ApiResponse.success(MockHelper.toJson(mock))
2426
res.status(200).json(response)
2527
} else {
2628
const response: ApiResponse = ApiResponse.error(`No document found with id ${req.params.id}`)
2729
res.status(404).json(response)
2830
}
2931
} catch (error: unknown) {
30-
const response: ApiResponse = ApiResponse.error('An error occured')
32+
const response: ApiResponse = ApiResponse.error('An error occurred')
3133
res.status(500).json(response)
3234
}
3335
})
@@ -42,20 +44,22 @@ router.get('/mock/:id', async (req: Request, res: Response): Promise<void> => {
4244
res.status(404).json(response)
4345
}
4446
} catch (error: unknown) {
45-
const response: ApiResponse = ApiResponse.error('An error occured')
47+
const response: ApiResponse = ApiResponse.error('An error occurred')
4648
res.status(500).json(response)
4749
}
4850
})
4951

5052
router.post('/', async (req: Request, res: Response): Promise<void> => {
5153

5254
const data = new Mock({
55+
_id: new Types.ObjectId(),
56+
parentId: req.body.parentId,
5357
name: req.body.name,
5458
response: req.body.response
5559
})
5660
try {
5761
const mock: MockModel = await data.save()
58-
const response: ApiResponse = ApiResponse.success(mock, 'Document created')
62+
const response: ApiResponse = ApiResponse.success(MockHelper.toJson(mock), 'Document created')
5963
res.status(201).json(response)
6064
} catch (error: unknown) {
6165
const response: ApiResponse = ApiResponse.error((error as Error).message)

src/routes/mock_folder.routes.ts

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import express, { Request, Response } from 'express'
2+
import { MockFolder, MockFolderModel } from '../models/mock_folder.model'
3+
import { ApiResponse } from '../common/api_response'
4+
import mongoose, {Types} from 'mongoose'
5+
import {Mock, MockModel} from "../models/mock.model";
6+
import MockFolderHelper from "../helper/mock_folder.helper";
7+
import Constants from "../common/constants";
8+
9+
const router = express.Router()
10+
11+
router.get('/', async (req: Request, res: Response): Promise<void> => {
12+
try {
13+
const root: MockFolderModel = {
14+
_id: Constants.rootPath,
15+
parentId: null,
16+
name: 'Root'
17+
}
18+
const mockFolders: MockFolderModel[] = await MockFolder.find({ parentId: Constants.rootPath })
19+
const mocks: MockModel[] = await Mock.find({ parentId: Constants.rootPath })
20+
const response: ApiResponse = ApiResponse.success(MockFolderHelper.toJson(root, mockFolders, mocks))
21+
res.status(200).json(response)
22+
} catch (error: unknown) {
23+
const response: ApiResponse = ApiResponse.error((error as Error).message)
24+
res.status(500).json(response)
25+
}
26+
})
27+
28+
router.get('/:id', async (req: Request, res: Response): Promise<void> => {
29+
try {
30+
const mockFolder: MockFolderModel | null = await MockFolder.findById(req.params.id)
31+
if (mockFolder != null) {
32+
const subFolders: MockFolderModel[] = await MockFolder.find({ parentId: req.params.id })
33+
const mocks: MockModel[] = await Mock.find({ parentId: req.params.id })
34+
const response: ApiResponse = ApiResponse.success(MockFolderHelper.toJson(mockFolder, subFolders, mocks))
35+
res.status(200).json(response)
36+
} else {
37+
const response: ApiResponse = ApiResponse.error(`No document found with id ${req.params.id}`)
38+
res.status(404).json(response)
39+
}
40+
} catch (error: unknown) {
41+
const response: ApiResponse = ApiResponse.error('An error occurred')
42+
res.status(500).json(response)
43+
}
44+
})
45+
46+
router.post('/', async (req: Request, res: Response): Promise<void> => {
47+
48+
const data = new MockFolder({
49+
_id: new Types.ObjectId(),
50+
parentId: req.body.parentId,
51+
name: req.body.name
52+
})
53+
try {
54+
const mockFolder: MockFolderModel = await data.save()
55+
const response: ApiResponse = ApiResponse.success(MockFolderHelper.toJson(mockFolder), 'Document created')
56+
res.status(201).json(response)
57+
} catch (error: unknown) {
58+
const response: ApiResponse = ApiResponse.error((error as Error).message)
59+
res.status(401).json(response)
60+
}
61+
})
62+
63+
router.put('/:id', async (req: Request, res: Response): Promise<void> => {
64+
try {
65+
66+
const newName: string | null = req.body.name
67+
68+
const query: mongoose.UpdateQuery<MockFolderModel> = { name: newName }
69+
70+
MockFolder.findByIdAndUpdate(req.params.id, query, (updateError: mongoose.CallbackError) => {
71+
if (updateError) {
72+
const response: ApiResponse = ApiResponse.error((updateError as Error).message)
73+
res.status(500).json(response)
74+
} else {
75+
const response: ApiResponse = ApiResponse.success(null, 'Document updated successfully')
76+
res.status(200).json(response)
77+
}
78+
})
79+
} catch (error: unknown) {
80+
const response: ApiResponse = ApiResponse.error((error as Error).message)
81+
res.status(500).json(response)
82+
}
83+
})
84+
85+
router.delete('/:id', async (req: Request, res: Response): Promise<void> => {
86+
87+
try {
88+
await deleteChildren(req.params.id)
89+
const response: ApiResponse = ApiResponse.success(null, `Document with id ${req.params.id} removed`)
90+
res.status(200).json(response)
91+
} catch (error: unknown) {
92+
const response: ApiResponse = ApiResponse.error((error as Error).message)
93+
res.status(500).json(response)
94+
}
95+
96+
})
97+
98+
async function deleteChildren(folderId: string): Promise<void> {
99+
100+
// deleting folder
101+
await MockFolder.findByIdAndDelete(folderId)
102+
103+
// deleting child files
104+
await Mock.deleteMany({ parentId: folderId })
105+
106+
// getting child folders
107+
const childFolders: MockFolderModel[] = await MockFolder.find({ parentId: folderId })
108+
109+
// deleting child folders
110+
await MockFolder.deleteMany({ parentId: folderId })
111+
112+
// recursively deleting children folder contents
113+
for (const childFolder of childFolders) {
114+
await deleteChildren(childFolder._id);
115+
}
116+
117+
}
118+
119+
module.exports = router

0 commit comments

Comments
 (0)