@mattduffy/banner 1.2.1 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Readme.md CHANGED
@@ -30,9 +30,11 @@ app.use(banner.use())
30
30
  /*
31
31
  Emits at the beginning of each client request.
32
32
  #################################################################
33
- # GET: https://dev.example.com/map/getToken?debug=verbose
34
- # Referer: https://dev.example.com/?debug=verbose
35
- # From IP: 192.168.1.254
33
+ # GET: https://dev.example.com/map/getToken
34
+ # Query Params: ?debug=verbose
35
+ # Referer: https://dev.example.com/?debug=verbose
36
+ # From IP: 192.168.1.254
37
+ # Timestamp: 1/7/2026, 10:34:14 AM
36
38
  #################################################################
37
39
  */
38
40
  ```
@@ -43,36 +45,41 @@ the ```ctx.request.method``` property. The supported request methods are ```GET
43
45
 
44
46
  ```
45
47
  // GET
46
- ######################################################################
47
- # GET: https://banner.test/a/really/long/url/to/a/special/page
48
- # Referer: https://googoogle.com
49
- # From IP: 192.168.1.250
50
- ######################################################################
48
+ ##########################################################################
49
+ # GET: https://banner.test/a/really/long/url/to/a/special/page
50
+ # Query Params: ?param1=querty&param2=12345&param3=true
51
+ # Referer: https://googoogle.com
52
+ # From IP: 192.168.1.250
53
+ # Timestamp: 1/7/2026, 10:34:14 AM
54
+ ##########################################################################
51
55
  ```
52
56
 
53
57
  ```
54
58
  // PUT
55
59
  &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
56
- & PUT: https://banner.test/a/really/long/url/to/a/special/page
57
- & Referer: https://googoogle.com
58
- & From IP: 192.168.1.250
60
+ & PUT: https://banner.test/a/really/long/url/to/a/special/page
61
+ & Referer: https://googoogle.com
62
+ & From IP: 192.168.1.250
63
+ & Timestamp: 1/7/2026, 10:34:14 AM
59
64
  &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
60
65
  ```
61
66
 
62
67
  ```
63
68
  // POST
64
69
  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
65
- @ POST: https://banner.test/a/really/long/url/to/a/special/page
66
- @ Referer: https://googoogle.com
67
- @ From IP: 192.168.1.250
70
+ @ POST: https://banner.test/a/really/long/url/to/a/special/page
71
+ @ Referer: https://googoogle.com
72
+ @ From IP: 192.168.1.250
73
+ @ Timestamp: 1/7/2026, 10:34:14 AM
68
74
  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
69
75
  ```
70
76
 
71
77
  ```
72
78
  // DELETE
73
79
  **********************************************************************
74
- * DELETE: https://banner.test/a/really/long/url/to/a/special/page
75
- * Referer: https://googoogle.com
76
- * From IP: 192.168.1.250
80
+ * DELETE: https://banner.test/a/really/long/url/to/a/special/page
81
+ * Referer: https://googoogle.com
82
+ * From IP: 192.168.1.250
83
+ * Timestamp: 1/7/2026, 10:34:14 AM
77
84
  **********************************************************************
78
85
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mattduffy/banner",
3
- "version": "1.2.1",
3
+ "version": "1.3.1",
4
4
  "description": "Displays server start-up information.",
5
5
  "author": "Matthew Duffy",
6
6
  "license": "ISC",
package/src/index.js CHANGED
@@ -295,6 +295,7 @@ export class Banner {
295
295
  break
296
296
  case 'post':
297
297
  _g = gPOST
298
+ console.info(ctx.request.body)
298
299
  break
299
300
  case 'put':
300
301
  _g = gPUT
@@ -317,21 +318,66 @@ export class Banner {
317
318
  if (!ctx.request.url) {
318
319
  throw new Error('Missing required request url value.')
319
320
  }
321
+ const labels = []
322
+ const values = []
323
+ const lines = []
320
324
  const _urlLabel = `${ctx.request.method}:`
321
- const _url = `${ctx.request.protocol}://${ctx.request.header.host}${ctx.request.url}`
325
+ let _url = `${ctx.request.protocol}://${ctx.request.header.host}${ctx.request.url}`
326
+ const _queryStringIndex = _url.indexOf('?')
327
+ const _queryStringLabel = 'Query Params:'
328
+ let _queryString = ''
329
+ let _queryStringLine = ''
330
+ if (_queryStringIndex !== -1) {
331
+ _queryString = _url.slice(_url.indexOf('?'))
332
+ _queryStringLine = `${_queryStringLabel} ${_queryString}`
333
+ labels.push(_queryStringLabel)
334
+ values.push(_queryString)
335
+ lines.push(_queryStringLine)
336
+ // console.log('adding query string to request banner')
337
+ }
338
+ _url = (_queryString.length > 0) ? _url.slice(0, _url.indexOf('?')) : _url
339
+ values.push(_url)
322
340
  let _urlLine = `${_urlLabel} ${_url}`
323
341
  const _refLabel = 'Referer:'
324
342
  const _ref = ctx.request.header.referer ?? '<emtpy header field>'
343
+ values.push(_ref)
325
344
  let _refLine = `${_refLabel} ${_ref}`
326
345
  const _ipLabel = 'From IP:'
327
346
  const _ip = ctx.request.ip
347
+ values.push(_ip)
328
348
  let _ipLine = `${_ipLabel} ${_ip}`
329
- const _longestLabel = [_urlLabel, _refLabel, _ipLabel].reduce((a, c) => {
330
- if (a.length > (c.indexOf(':') + 1)) {
331
- return a
332
- }
333
- return (c.indexOf(':') + 1)
334
- }, '')
349
+ const _timestampLabel = 'Timestamp:'
350
+ const _timestamp = new Date().toLocaleString()
351
+ values.push(_timestamp)
352
+ let _timestampLine = `${_timestampLabel} ${_timestamp}`
353
+ labels.push(_urlLabel)
354
+ labels.push(_refLabel)
355
+ labels.push(_ipLabel)
356
+ labels.push(_timestampLabel)
357
+ // console.log(labels)
358
+
359
+ // console.log(values)
360
+ const _longestValue = values
361
+ .reduce((a, c) => {
362
+ if (a > c.length) return a
363
+ return c.length
364
+ }, '')
365
+ // console.log('longest value', _longestValue)
366
+
367
+ lines.push(_ipLine)
368
+ lines.push(_timestampLine)
369
+ lines.push(_urlLine)
370
+ lines.push(_refLine)
371
+ // console.log(lines)
372
+ const _longestLabel = labels
373
+ .reduce((a, c) => {
374
+ // console.log(a, c.indexOf(':') + 1)
375
+ if (a > (c.indexOf(':') + 1)) {
376
+ return a
377
+ }
378
+ return (c.indexOf(':') + 1)
379
+ }, '')
380
+ // console.log('longest label', _longestLabel)
335
381
  _refLine = _refLine.padStart(
336
382
  (_longestLabel - _refLine.indexOf(':')) + _refLine.length,
337
383
  ' ',
@@ -340,20 +386,38 @@ export class Banner {
340
386
  (_longestLabel - _urlLine.indexOf(':')) + _urlLine.length,
341
387
  ' ',
342
388
  )
389
+ if (_queryStringLine.length > 0) {
390
+ _queryStringLine = _queryStringLine.padStart(
391
+ (_longestLabel - _queryStringLine.indexOf(':')) + _queryStringLine.length,
392
+ ' ',
393
+ )
394
+ }
343
395
  _ipLine = _ipLine.padStart(
344
396
  (_longestLabel - _ipLine.indexOf(':')) + _ipLine.length,
345
397
  ' ',
346
398
  )
347
- const _longestLine = [_urlLine, _refLine, _ipLine].reduce((a, c) => {
348
- if (a > c.length) return a
349
- return c.length
350
- }, '')
351
- // _log('request banner _longestLine', _longestLine)
352
- _requestBanner = `${_g.padEnd(_longestLine + 5, _g)}\n`
399
+ _timestampLine = _timestampLine.padStart(
400
+ (_longestLabel - _timestampLine.indexOf(':')) + _timestampLine.length,
401
+ ' ',
402
+ )
403
+ const _longestLine = _longestLabel + _longestValue
404
+ // const _longestLine = lines
405
+ // .reduce((a, c) => {
406
+ // // console.log(a, c.length)
407
+ // if (a > c.length) return a
408
+ // return c.length
409
+ // }, '')
410
+ // console.log('longest line', _longestLine)
411
+ /* eslint-disable prefer-template */
412
+ const endDangler = 6
413
+ _requestBanner = `${_g.padEnd(_longestLine + endDangler, _g)}\n`
353
414
  + `${_g} ${_urlLine}\n`
415
+ + `${(_queryStringLine.length > 0) ? _g + ' ' + _queryStringLine + '\n' : ''}`
354
416
  + `${_g} ${_refLine}\n`
355
417
  + `${_g} ${_ipLine}\n`
356
- + `${_g.padEnd(_longestLine + 5, _g)}`
418
+ + `${_g} ${_timestampLine}\n`
419
+ + `${_g.padEnd(_longestLine + endDangler, _g)}`
420
+ /* eslint-enable prefer-template */
357
421
  _log(_requestBanner)
358
422
  if (next) {
359
423
  await next(ctx.request.method)
package/test/test.js CHANGED
@@ -1,15 +1,17 @@
1
1
  // import path from 'node:path'
2
2
  // import { randomBytes } from 'node:crypto'
3
3
  import {
4
- after,
4
+ // after,
5
5
  before,
6
6
  describe,
7
7
  it,
8
8
  } from 'node:test'
9
9
  import assert from 'node:assert/strict'
10
- import fs from 'node:fs/promises'
10
+ // import fs from 'node:fs/promises'
11
11
  import os from 'node:os'
12
12
  import { Banner } from '../src/index.js'
13
+
14
+ /* eslint-disable camelcase */
13
15
  const skip = { skip: true }
14
16
  console.log(skip)
15
17
  let cfg
@@ -22,23 +24,25 @@ let next
22
24
  describe('First test suite for banner package', async () => {
23
25
  before(() => {
24
26
  function getLocalIpAddress() {
25
- const networkInterfaces = os.networkInterfaces();
26
- let localIpAddress = null;
27
-
27
+ const networkInterfaces = os.networkInterfaces()
28
+ let localIpAddress = null
29
+
30
+ /* eslint-disable no-restricted-syntax */
31
+ /* eslint-disable guard-for-in */
28
32
  for (const interfaceName in networkInterfaces) {
29
- const networkInterface = networkInterfaces[interfaceName];
33
+ const networkInterface = networkInterfaces[interfaceName]
30
34
  for (const details of networkInterface) {
31
35
  // Check for IPv4, not internal (loopback), and a valid address
32
36
  if (details.family === 'IPv4' && !details.internal) {
33
- localIpAddress = details.address;
34
- break; // Found a suitable IPv4 address, exit inner loop
37
+ localIpAddress = details.address
38
+ break // Found a suitable IPv4 address, exit inner loop
35
39
  }
36
40
  }
37
41
  if (localIpAddress) {
38
- break; // Found a suitable IPv4 address, exit outer loop
42
+ break // Found a suitable IPv4 address, exit outer loop
39
43
  }
40
44
  }
41
- return localIpAddress;
45
+ return localIpAddress
42
46
  }
43
47
  ctx = {
44
48
  request: {
@@ -71,21 +75,22 @@ describe('First test suite for banner package', async () => {
71
75
  })
72
76
 
73
77
  it('Should create a start-up banner instance, with constructor param.', () => {
74
- const banner = new Banner(cfg)
78
+ const banner = new Banner(cfg)
75
79
  assert(banner.bannerText.length > 0)
76
80
  assert(typeof banner.bannerText === 'string')
77
81
  })
78
-
82
+
79
83
  it('Should fail', () => {
80
84
  const banner = new Banner()
81
85
  assert(!banner.print())
82
86
  })
83
87
 
84
88
  it('Should work as a koajs middleware function - POST method.', async () => {
85
- ctx_POST = Object.assign({}, ctx)
89
+ // ctx_POST = Object.assign({}, ctx)
90
+ ctx_POST = { ...ctx }
86
91
  ctx_POST.request.method = 'POST'
87
- ctx_POST.throw = (code, err, {} = null) => {
88
- throw new Error(`${code}, ${msg}`)
92
+ ctx_POST.throw = (code, err) => {
93
+ throw new Error(`${code}, ${err}`)
89
94
  }
90
95
  console.log(ctx_POST)
91
96
  const post = new Banner(ctx_POST)
@@ -93,10 +98,11 @@ describe('First test suite for banner package', async () => {
93
98
  })
94
99
 
95
100
  it('Should work as a koajs middleware function - GET method.', async () => {
96
- ctx_GET = Object.assign({}, ctx)
101
+ // ctx_GET = Object.assign({}, ctx)
102
+ ctx_GET = { ...ctx }
97
103
  ctx_GET.request.method = 'GET'
98
- ctx_GET.throw = (code, err, {} = null) => {
99
- throw new Error(`${code}, ${msg}`)
104
+ ctx_GET.throw = (code, err) => {
105
+ throw new Error(`${code}, ${err}`)
100
106
  }
101
107
  console.log(ctx_GET)
102
108
  const get = new Banner(ctx_GET)
@@ -104,10 +110,11 @@ describe('First test suite for banner package', async () => {
104
110
  })
105
111
 
106
112
  it('Should work as a koajs middleware function - PUT method.', async () => {
107
- ctx_PUT = Object.assign({}, ctx)
113
+ // ctx_PUT = Object.assign({}, ctx)
114
+ ctx_PUT = { ...ctx }
108
115
  ctx_PUT.request.method = 'PUT'
109
- ctx_PUT.throw = (code, err, {} = null) => {
110
- throw new Error(`${code}, ${msg}`)
116
+ ctx_PUT.throw = (code, err) => {
117
+ throw new Error(`${code}, ${err}`)
111
118
  }
112
119
  console.log(ctx_PUT)
113
120
  const put = new Banner(ctx_PUT)
@@ -115,22 +122,36 @@ describe('First test suite for banner package', async () => {
115
122
  })
116
123
 
117
124
  it('Should work as a koajs middleware function - DELETE method.', async () => {
118
- ctx_DEL = Object.assign({}, ctx)
125
+ // ctx_DEL = Object.assign({}, ctx)
126
+ ctx_DEL = { ...ctx }
119
127
  ctx_DEL.request.method = 'DELETE'
120
- ctx_DEL.throw = (code, err, {} = null) => {
121
- throw new Error(`${code}, ${msg}`)
128
+ ctx_DEL.throw = (code, err) => {
129
+ throw new Error(`${code}, ${err}`)
122
130
  }
123
131
  console.log(ctx_DEL)
124
132
  const del = new Banner(ctx_DEL)
125
133
  assert(await del.use()(ctx_DEL, next))
126
134
  })
127
135
 
128
- it('Should fail as a koajs middleware function, missing input parameters.', async () => {
136
+ it('Should work as a koajs middleware function - GET method, with query string.', async () => {
137
+ // ctx_GET = Object.assign({}, ctx)
138
+ ctx_GET = { ...ctx }
139
+ ctx_GET.request.method = 'GET'
140
+ ctx_GET.request.url += '?param1=querty&param2=12345&param3=true'
141
+ ctx_GET.throw = (code, err) => {
142
+ throw new Error(`${code}, ${err}`)
143
+ }
144
+ console.log(ctx_GET)
145
+ const get = new Banner(ctx_GET)
146
+ assert(await get.use()(ctx_GET, next))
147
+ })
148
+
149
+ it('Should fail as a koajs middleware function, missing input parameters.', async () => {
129
150
  ctx.request.header.host = null
130
151
  ctx.request.url = null
131
152
  ctx.throw = (code, err) => {
132
153
  // console.log(err.message)
133
- throw err
154
+ throw err
134
155
  }
135
156
  console.log(ctx)
136
157
  const req = new Banner()