1
0
Эх сурвалжийг харах

add dotenv, simple logger

Aneurin Barker Snook 1 жил өмнө
parent
commit
671fed6513
8 өөрчлөгдсөн 103 нэмэгдсэн , 6 устгасан
  1. 1 0
      .gitignore
  2. 12 0
      package-lock.json
  3. 1 0
      package.json
  4. 6 0
      src/http.ts
  5. 6 0
      src/index.ts
  6. 60 0
      src/log.ts
  7. 11 6
      src/main.ts
  8. 6 0
      src/types.ts

+ 1 - 0
.gitignore

@@ -1,2 +1,3 @@
 node_modules/
 out/
+.env

+ 12 - 0
package-lock.json

@@ -9,6 +9,7 @@
       "version": "0.0.0",
       "license": "SEE LICENSE IN LICENSE.md",
       "dependencies": {
+        "dotenv": "^16.3.1",
         "express": "^4.18.2"
       },
       "devDependencies": {
@@ -899,6 +900,17 @@
         "node": ">=6.0.0"
       }
     },
+    "node_modules/dotenv": {
+      "version": "16.3.1",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
+      "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/motdotla/dotenv?sponsor=1"
+      }
+    },
     "node_modules/ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",

+ 1 - 0
package.json

@@ -23,6 +23,7 @@
     "typescript": "^5.3.2"
   },
   "dependencies": {
+    "dotenv": "^16.3.1",
     "express": "^4.18.2"
   }
 }

+ 6 - 0
src/http.ts

@@ -11,5 +11,11 @@ export function createExpress(ctx: Context) {
   app.post(`${prefix}/account`, account.createAccount(ctx))
   app.delete(`${prefix}/account`, account.deleteAccount(ctx))
 
+  // Log request after handling
+  app.use((req, res, next) => {
+    ctx.log.debug(`[${req.socket.remoteAddress}] ${req.method} ${req.url} ${res.statusCode}`)
+    next()
+  })
+
   return app
 }

+ 6 - 0
src/index.ts

@@ -1,5 +1,8 @@
+import dotenv from 'dotenv'
 import main from './main'
 
+dotenv.config()
+
 main({
   api: {
     prefix: process.env.API_PREFIX || '/api',
@@ -8,6 +11,9 @@ main({
     host: process.env.HTTP_HOST || '',
     port: parseInt(process.env.HTTP_PORT || '5001'),
   },
+  log: {
+    level: process.env.LOG_LEVEL || 'info',
+  },
 }).catch(err => {
   if (err) console.error(err)
 })

+ 60 - 0
src/log.ts

@@ -0,0 +1,60 @@
+import type { Context } from './types'
+
+export type Logger = ReturnType<typeof createLogger>
+
+export type LogLevel = keyof typeof LogLevels
+
+const LogLevels = {
+  trace: 1,
+  debug: 2,
+  info: 3,
+  warn: 4,
+  error: 5,
+}
+
+const LogLevelStrings: Record<LogLevel, string> = {
+  trace: 'TRC',
+  debug: 'DBG',
+  info: 'INF',
+  warn: 'WRN',
+  error: 'ERR',
+}
+
+function createLogger({ config }: Context) {
+  // If an invalid log level is provided, default to info level
+  const minLevel = LogLevels[config.log.level as LogLevel] || LogLevels.info
+
+  function write(level: LogLevel, ...a: unknown[]) {
+    const time = new Date().toLocaleTimeString()
+    if (level === 'trace') {
+      // Don't print TRC as console.trace prefixes "Trace: " and prints stack
+      console.trace(time, ...a)
+    } else {
+      console[level](time, LogLevelStrings[level], ...a)
+    }
+  }
+
+  function trace(...a: unknown[]) {
+    if (minLevel <= LogLevels.trace) write('trace', ...a)
+  }
+
+  function debug(...a: unknown[]) {
+    if (minLevel <= LogLevels.debug) write('debug', ...a)
+  }
+
+  function info(...a: unknown[]) {
+    if (minLevel <= LogLevels.info) write('info', ...a)
+  }
+
+  function warn(...a: unknown[]) {
+    if (minLevel <= LogLevels.warn) write('warn', ...a)
+  }
+
+  function error(...a: unknown[]) {
+    if (minLevel <= LogLevels.error) write('error', ...a)
+  }
+
+  return { trace, debug, info, warn, error }
+}
+
+export default createLogger

+ 11 - 6
src/main.ts

@@ -1,5 +1,6 @@
 import type { SignalConstants } from 'os'
 import { createExpress } from './http'
+import createLogger from './log'
 import process from 'process'
 import type { Config, Context } from './types'
 
@@ -7,9 +8,12 @@ import type { Config, Context } from './types'
  * Server application entrypoint.
  */
 async function main(config: Config): Promise<void> {
-  // Initialize context
+  // Create context
   const ctx = <Context>{ config }
 
+  // Initialize logger
+  ctx.log = createLogger(ctx)
+
   // Initialize Express app
   const app = createExpress(ctx)
 
@@ -26,20 +30,21 @@ async function main(config: Config): Promise<void> {
         new Promise<void>((res, rej) => {
           server.close(err => {
             if (err) {
-              console.error(err)
+              ctx.log.error(err)
               rej(err)
             } else {
-              console.log('Stopped HTTP server')
+              ctx.log.info('Stopped HTTP server')
               res()
             }
           })
         }),
       ])
 
-      rej(new Error(`Received ${e}`))
+      ctx.log.error(`Received ${e}`)
+      rej()
     }
-    process.on('SIGINT', stop)
-    process.on('SIGTERM', stop)
+    process.on('SIGINT', e => stop(e).catch(rej))
+    process.on('SIGTERM', e => stop(e).catch(rej))
   })
 }
 

+ 6 - 0
src/types.ts

@@ -1,3 +1,5 @@
+import type { Logger } from './log'
+
 export interface Config {
   api: {
     prefix: string
@@ -6,8 +8,12 @@ export interface Config {
     host: string
     port: number
   }
+  log: {
+    level: string
+  }
 }
 
 export interface Context {
   config: Config
+  log: Logger
 }