Skip to content

Commit

Permalink
Release v0.36.0 (#52)
Browse files Browse the repository at this point in the history
* feat: add router within the app, making the use of routing more flexible

* fix: route created after being injected into the app

* fix: work with multiple router instances and create routes in the app

* test: work with multiple router instances and create routes in the app

* docs: update readme

* feat: release v0.36.0
  • Loading branch information
jukerah committed May 1, 2024
1 parent ab4283c commit 4133d73
Show file tree
Hide file tree
Showing 13 changed files with 469 additions and 173 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,9 @@
# VkrunJS Releases

## 0.36.0

- adjust the router to work with multiple router instances and create a route directly in the app

## 0.35.0

- change create session from middleware to function
Expand Down
5 changes: 1 addition & 4 deletions README.md
Expand Up @@ -20,15 +20,12 @@ npm install vkrun
import v from 'vkrun'

const app = v.App()
const router = v.Router()

router.get('/', (req, res) => {
app.get('/', (req, res) => {
res.setHeader('Content-Type', 'text/plain')
res.status(200).end('Hello World!')
})

app.use(router)

app.server().listen(3000, () => {
console.log('Vkrun started on port 3000')
})
Expand Down
6 changes: 4 additions & 2 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "vkrun",
"version": "0.35.0",
"version": "0.36.0",
"description": "Vkrun is a Node.js framework for building server-side applications",
"author": "Mario Elvio",
"license": "MIT",
Expand All @@ -26,7 +26,9 @@
"jwt",
"logger",
"session",
"super request"
"super request",
"backend",
"back-end"
],
"files": [
"LICENSE",
Expand Down
133 changes: 101 additions & 32 deletions src/modules/app/index.ts
@@ -1,64 +1,133 @@
import * as http from 'http'
import { VkrunRouter } from '../router'
import * as routerHelper from '../router/helpers'
import { customResponse } from '../router/helpers/custom-response'
import * as type from '../types'
import { loggerSanitizeInterval } from '../logger'
import { RouterHandler } from '../router/helpers/router-handler'

export const App = (): type.App => {
let instance: 'server' | '_reqWithoutServer' | 'closed' | undefined
let router: VkrunRouter
const middlewares: any[] = []
let createdServer: any
let timers: any[] = []
class VkrunApp implements type.VkrunApp {
private instance: 'server' | '_reqWithoutServer' | 'closed' | undefined
private routes: type.Route[] = []
private readonly routerHandler: RouterHandler
private readonly middlewares: any[]
private createdServer: any
private timers: any[]

const setTimer = (callback: () => void, ms: number): NodeJS.Timeout => {
constructor () {
this.instance = undefined
this.routerHandler = new RouterHandler()
this.middlewares = []
this.timers = []
}

// Timeout management

public setTimer (callback: () => void, ms: number): NodeJS.Timeout {
const timeout = setTimeout(callback, ms)
timers.push(timeout)
this.timers.push(timeout)
return timeout
}

const clearTimers = (): void => {
timers.forEach(timerId => clearTimeout(timerId))
timers = []
public clearTimers (): void {
this.timers.forEach((timerId: NodeJS.Timeout) => clearTimeout(timerId))
this.timers = []
if (loggerSanitizeInterval) clearInterval(loggerSanitizeInterval)
}

const server = (): type.CreateServer => {
// Server Nodejs

public server (): type.CreateServer {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
createdServer = http.createServer(async (request, response) => {
instance = 'server'
this.createdServer = http.createServer(async (request, response) => {
this.instance = 'server'
const _request = request as type.Request
_request.setTimer = setTimer
_request.setTimer = this.setTimer.bind(this)
const _response = customResponse(response)
await router.handleRequest(_request, _response, middlewares)
await this.routerHandler.handleRequest(
_request,
_response,
this.routes,
this.middlewares
)
})

return createdServer
return this.createdServer
}

public close (): void {
if (this.instance === 'server') this.createdServer.close()
this.createdServer = null
this.clearTimers()
this.instance = 'closed'
}

const _reqWithoutServer = async (request: type.Request, response: type.Response): Promise<type.Response> => {
instance = '_reqWithoutServer'
// Method to simulate a request with superRequest

public async _reqWithoutServer (request: type.Request, response: type.Response): Promise<type.Response> {
this.instance = '_reqWithoutServer'
const _request = request
_request.setTimer = setTimer
createdServer = customResponse(response)
await router.handleRequest(request, createdServer, middlewares)
return createdServer
_request.setTimer = this.setTimer.bind(this)
this.createdServer = customResponse(response)
// await this.router.handleRequest(
// request, this.createdServer, this.middlewares)
await this.routerHandler.handleRequest(
_request,
this.createdServer,
this.routes,
this.middlewares
)
return this.createdServer
}

const use = (middleware: Record<string, any>): void => {
// Middleware management

public use (middleware: Record<string, any>): void {
if (middleware instanceof VkrunRouter) {
router = middleware
this.routes = [...this.routes, ...middleware._routes()]
} else {
middlewares.push(middleware)
this.middlewares.push(middleware)
}
}

const close = (): void => {
if (instance === 'server') createdServer.close()
createdServer = null
clearTimers()
instance = 'closed'
// Routing

public get (path: string, ...handlers: any): void {
routerHelper.routeExists(path, 'GET', this.routes)
this.routes.push({ path, method: 'GET', handlers })
}

public head (path: string, ...handlers: any): void {
routerHelper.routeExists(path, 'HEAD', this.routes)
this.routes.push({ path, method: 'HEAD', handlers })
}

return { server, use, _reqWithoutServer, close, setTimer, clearTimers }
public post (path: string, ...handlers: any): void {
routerHelper.routeExists(path, 'POST', this.routes)
this.routes.push({ path, method: 'POST', handlers })
}

public put (path: string, ...handlers: any): void {
routerHelper.routeExists(path, 'PUT', this.routes)
this.routes.push({ path, method: 'PUT', handlers })
}

public patch (path: string, ...handlers: any): void {
routerHelper.routeExists(path, 'PATCH', this.routes)
this.routes.push({ path, method: 'PATCH', handlers })
}

public delete (path: string, ...handlers: any): void {
routerHelper.routeExists(path, 'DELETE', this.routes)
this.routes.push({ path, method: 'DELETE', handlers })
}

public options (path: string, ...handlers: any): void {
routerHelper.routeExists(path, 'OPTIONS', this.routes)
this.routes.push({ path, method: 'OPTIONS', handlers })
}
}

export const App = (): type.VkrunApp => {
return new VkrunApp()
}
8 changes: 4 additions & 4 deletions src/modules/logger/__tests__/index-e2e.spec.ts
Expand Up @@ -11,6 +11,10 @@ describe('Logger Middleware - end to end testing using super request', () => {
const app = v.App()
const logger = Logger({ level: 'http' })
const router = v.Router()
router.post('/:string/:integer/query', (_request: v.Request, response: v.Response) => {
response.status(200).json({ result: 'ok' })
})

app.use(v.parseData())
app.use(logger.middleware())
app.use(router)
Expand All @@ -22,10 +26,6 @@ describe('Logger Middleware - end to end testing using super request', () => {
}
}

router.post('/:string/:integer/query', (_request: v.Request, response: v.Response) => {
response.status(200).json({ result: 'ok' })
})

const path = '/any@mail.com/123/query?float=1.56&boolean=true&date=2000-02-03T02:00:00.000Z'

await v.superRequest(app).post(path, data).then((response) => {
Expand Down
9 changes: 5 additions & 4 deletions src/modules/logger/__tests__/index-e2e.test.ts
Expand Up @@ -22,6 +22,11 @@ describe('Logger Middleware - end to end testing using axios and app server', ()
const app = v.App()
const logger = Logger({ level: 'http' })
const router = v.Router()

router.post('/:string/:integer/query', (_request: v.Request, response: v.Response) => {
response.status(200).json({ result: 'ok' })
})

app.use(v.parseData())
app.use(logger.middleware())
app.use(router)
Expand All @@ -35,10 +40,6 @@ describe('Logger Middleware - end to end testing using axios and app server', ()
}
}

router.post('/:string/:integer/query', (_request: v.Request, response: v.Response) => {
response.status(200).json({ result: 'ok' })
})

server.listen(3699)

const url = 'http://localhost:3699/any@mail.com/123/query?float=1.56&boolean=true&date=2000-02-03T02:00:00.000Z'
Expand Down
100 changes: 100 additions & 0 deletions src/modules/router/__tests__/index-e2e.spec.ts
Expand Up @@ -492,4 +492,104 @@ describe('Router', () => {

app.close()
})

it('Should be able to use multiple Router instances', async () => {
const app = v.App()
const routerA = v.Router()
const routerB = v.Router()

routerA.get('/get', (_request: v.Request, response: v.Response) => {
response.status(200).send('GET ok')
})

routerB.post('/post', (_request: v.Request, response: v.Response) => {
response.status(200).send('POST ok')
})

app.use(routerA)
app.use(routerB)

await v.superRequest(app).get('/get').then((response) => {
expect(response.statusCode).toEqual(200)
expect(response.data).toEqual('GET ok')
})

await v.superRequest(app).post('/post').then((response) => {
expect(response.statusCode).toEqual(200)
expect(response.data).toEqual('POST ok')
})

app.close()
})

it('Should be able to create routes directly from the App instance', async () => {
const app = v.App()

app.get('/get', (_request: v.Request, response: v.Response) => {
response.status(200).send('GET ok')
})

app.post('/post', (_request: v.Request, response: v.Response) => {
response.status(200).send('POST ok')
})

await v.superRequest(app).get('/get').then((response) => {
expect(response.statusCode).toEqual(200)
expect(response.data).toEqual('GET ok')
})

await v.superRequest(app).post('/post').then((response) => {
expect(response.statusCode).toEqual(200)
expect(response.data).toEqual('POST ok')
})

app.close()
})

it('Should be able to work with multiple router instances and routes created directly in the App', async () => {
const app = v.App()
const routerA = v.Router()
const routerB = v.Router()

routerA.get('/example-a', (_request: v.Request, response: v.Response) => {
response.status(200).send('GET ok')
})

routerB.post('/example-b', (_request: v.Request, response: v.Response) => {
response.status(200).send('POST ok')
})

app.use(routerA)
app.use(routerB)

app.get('/example-c', (_request: v.Request, response: v.Response) => {
response.status(200).send('GET ok')
})

app.post('/example-d', (_request: v.Request, response: v.Response) => {
response.status(200).send('POST ok')
})

await v.superRequest(app).get('/example-a').then((response) => {
expect(response.statusCode).toEqual(200)
expect(response.data).toEqual('GET ok')
})

await v.superRequest(app).post('/example-b').then((response) => {
expect(response.statusCode).toEqual(200)
expect(response.data).toEqual('POST ok')
})

await v.superRequest(app).get('/example-c').then((response) => {
expect(response.statusCode).toEqual(200)
expect(response.data).toEqual('GET ok')
})

await v.superRequest(app).post('/example-d').then((response) => {
expect(response.statusCode).toEqual(200)
expect(response.data).toEqual('POST ok')
})

app.close()
})
})

0 comments on commit 4133d73

Please sign in to comment.