@autofleet/super-express 6.0.11 → 7.0.0

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
@@ -28,8 +28,10 @@ To use SuperExpress, you need to import and initialize it in your application:
28
28
 
29
29
  ```javascript
30
30
  import createSuperExpressApp from './index.js';
31
+ import logger from './logger.js';
31
32
 
32
33
  const options = {
34
+ logger,
33
35
  bodyParser: true,
34
36
  helmet: true,
35
37
  morgan: true,
@@ -51,6 +53,7 @@ app.listen(3000, () => {
51
53
 
52
54
  You can customize the behavior of SuperExpress by passing an options object:
53
55
 
56
+ - `logger` (object): A `@autofleet/logger` instance.
54
57
  - `bodyParser` (boolean|string): Enables or disables the body parser middleware.
55
58
  - `helmet` (boolean): Enables or disables security headers.
56
59
  - `morgan` (boolean): Enables or disables HTTP request logging.
@@ -88,8 +91,10 @@ Here's an example of how to set up and run the server:
88
91
 
89
92
  ```javascript
90
93
  import createSuperExpressApp from './index.js';
94
+ import logger from './logger.js';
91
95
 
92
96
  const options = {
97
+ logger,
93
98
  bodyParser: true,
94
99
  helmet: true,
95
100
  morgan: true,
@@ -107,6 +112,10 @@ app.listen(3000, () => {
107
112
  });
108
113
  ```
109
114
 
110
- ## Contributing
115
+ # V7 migration
111
116
 
112
- Feel free to submit issues or pull requests. Contributions are welcome!
117
+ The breaking change in this version is the update of the `zehut` peer-dependency to version `^4.0.0`.
118
+
119
+ This was changed in order to ensure that the version of `zehut` used here is the same as used in the MS, and not risk the package using v4 while the service is using v3, which would cause `zehut` to have multiple traces, which will not all hold the correct data.
120
+
121
+ Additionally, the minimum node version is now 18, due to the minimum version of node defined in `zehut`.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var f=require('node:fs'),b=require('node:path'),node_module=require('node:module'),c=require('express');var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var f__default=/*#__PURE__*/_interopDefault(f);var b__default=/*#__PURE__*/_interopDefault(b);var c__default=/*#__PURE__*/_interopDefault(c);var d={bodyParser:"1000mb",helmet:true,morgan:true,nitur:true,stats:true,tracing:true,eagerLoadUserPermissions:true};var{url:l}=({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }),p=node_module.createRequire(l),y=b__default.default.dirname(l),x=JSON.parse(f__default.default.readFileSync(new URL("package.json",y),"utf8"));function S({logger:e,...m}){let o=c__default.default(),r={...d,...m};if(r.morgan){let t=p("morgan");e.debug("[SuperExpress] formatting is enabled \u2705"),o.use(t((n,s,i)=>{let a={method:n.method(s,i),url:n.url(s,i)??"unknown URL",status:n.status(s,i),contentLength:n.res(s,i,"content-length"),responseTime:n["response-time"](s,i)??"0",userAgent:n["user-agent"](s,i)};e.info(a.url,{httpRequest:{status:a.status,requestUrl:a.url,requestMethod:a.method,responseSize:a.contentLength,latency:{seconds:Number.parseInt(a.responseTime,10)/1e3,nanos:Number.parseInt(a.responseTime,10)*1e6},userAgent:a.userAgent}});}));}if(r.helmet){e.debug("[SuperExpress] security is enabled \u2705");let t={"Content-Security-Policy":"default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests","Cross-Origin-Opener-Policy":"same-origin","Cross-Origin-Resource-Policy":"same-origin","Origin-Agent-Cluster":"?1","Referrer-Policy":"no-referrer","Strict-Transport-Security":"max-age=15552000; includeSubDomains","X-Content-Type-Options":"nosniff","X-DNS-Prefetch-Control":"off","X-Download-Options":"noopen","X-Frame-Options":"SAMEORIGIN","X-Permitted-Cross-Domain-Policies":"none","X-XSS-Protection":"0"};o.use((n,s,i)=>{s.set(t),i();}),o.disable("x-powered-by");}else e.warn("[SuperExpress] security headers are disabled \u{1F628}");if(r.bodyParser){e.debug("[SuperExpress] body-parser is enabled \u2705");let t=typeof r.bodyParser=="string"?r.bodyParser:"1000mb";o.use(c__default.default.json({limit:t}));}else e.debug("[SuperExpress] body-parser is disabled \u274C");if(r.nitur){let{aliveEndpoint:t}=p("@autofleet/nitur");o.get("/alive",t({logger:e,...r.aliveEndpointOptions})),e.debug("[SuperExpress] added /alive endpoint \u2705");}if(r.stats){let t=new Date;o.get("/stats",(n,s)=>{s.json({name:r.name||"default-name",version:r.version||"default-version",serverRunningSince:t});}),e.debug("[SuperExpress] added /stats endpoint \u2705");}if(r.tracing){let{enableTracing:t,middleware:n,outbreak:s}=p("@autofleet/zehut");t(),e.addContextMiddleware(()=>({traceId:s.getCurrentContext()?.context?.get("x-trace-id")})),o.use(n({eagerLoadUserPermissions:r.eagerLoadUserPermissions})),e.debug("[SuperExpress] tracing is enabled \u2705");}let u=o.listen.bind(o);return o.listen=function(t,n){let s=process.env.NODE_ENV==="production",i=x?.version||"unknown";return e.debug(`[SuperExpress] is started with version ${i}`),e.debug(`[SuperExpress] will listen on port ${t}`),e.debug(`[SuperExpress] production mode: ${s}`),u(t,n)},Object.assign(o,{nativeListen:u})}var w=S;exports.default=w;exports.superExpress=S;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var f=require('node:fs'),b=require('node:path'),node_module=require('node:module'),l=require('express');var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var f__default=/*#__PURE__*/_interopDefault(f);var b__default=/*#__PURE__*/_interopDefault(b);var l__default=/*#__PURE__*/_interopDefault(l);var d={bodyParser:"1000mb",helmet:true,morgan:true,nitur:true,stats:true,tracing:true,eagerLoadUserPermissions:true};var{url:c}=({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }),p=node_module.createRequire(c),y=b__default.default.dirname(c),S=JSON.parse(f__default.default.readFileSync(new URL("package.json",y),"utf8"));function x({logger:e,...m}){let o=l__default.default(),s={...d,...m};if(s.morgan){let t=p("morgan");e.debug("[SuperExpress] formatting is enabled \u2705"),o.use(t((r,n,i)=>{let a={method:r.method(n,i),url:r.url(n,i)??"unknown URL",status:r.status(n,i),contentLength:r.res(n,i,"content-length"),responseTime:r["response-time"](n,i)??"0",userAgent:r["user-agent"](n,i)};e.info(a.url,{httpRequest:{status:a.status,requestUrl:a.url,requestMethod:a.method,responseSize:a.contentLength,latency:{seconds:Number.parseInt(a.responseTime,10)/1e3,nanos:Number.parseInt(a.responseTime,10)*1e6},userAgent:a.userAgent}});}));}if(s.helmet){e.debug("[SuperExpress] security is enabled \u2705");let t={"Content-Security-Policy":"default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests","Cross-Origin-Opener-Policy":"same-origin","Cross-Origin-Resource-Policy":"same-origin","Origin-Agent-Cluster":"?1","Referrer-Policy":"no-referrer","Strict-Transport-Security":"max-age=15552000; includeSubDomains","X-Content-Type-Options":"nosniff","X-DNS-Prefetch-Control":"off","X-Download-Options":"noopen","X-Frame-Options":"SAMEORIGIN","X-Permitted-Cross-Domain-Policies":"none","X-XSS-Protection":"0"};o.use((r,n,i)=>{n.set(t),i();}),o.disable("x-powered-by");}else e.warn("[SuperExpress] security headers are disabled \u{1F628}");if(s.bodyParser){e.debug("[SuperExpress] body-parser is enabled \u2705");let t=typeof s.bodyParser=="string"?s.bodyParser:"1000mb";o.use(l__default.default.json({limit:t}));}else e.debug("[SuperExpress] body-parser is disabled \u274C");if(s.nitur){let{aliveEndpoint:t}=p("@autofleet/nitur");o.get("/alive",t({logger:e,...s.aliveEndpointOptions})),e.debug("[SuperExpress] added /alive endpoint \u2705");}if(s.stats){let t=new Date;o.get("/stats",(r,n)=>{n.json({name:s.name||"default-name",version:s.version||"default-version",serverRunningSince:t});}),e.debug("[SuperExpress] added /stats endpoint \u2705");}if(s.tracing){let{enableTracing:t,middleware:r}=p("@autofleet/zehut");t({logger:e}),o.use(r({eagerLoadUserPermissions:s.eagerLoadUserPermissions})),e.debug("[SuperExpress] tracing is enabled \u2705");}let u=o.listen.bind(o);return o.listen=function(t,r){let n=process.env.NODE_ENV==="production",i=S?.version||"unknown";return e.debug(`[SuperExpress] is started with version ${i}`),e.debug(`[SuperExpress] will listen on port ${t}`),e.debug(`[SuperExpress] production mode: ${n}`),u(t,r)},Object.assign(o,{nativeListen:u})}var A=x;exports.default=A;exports.superExpress=x;//# sourceMappingURL=index.cjs.map
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../config/default-options.ts","../src/index.ts"],"names":["defaultOptions","url","safeRequire","createRequire","dirname","path","packageJson","fs","superExpress","logger","options","app","express","mergedOptions","morgan","tokens","req","res","values","HEADERS","_req","next","limit","aliveEndpoint","serverRunningSince","enableTracing","middleware","outbreak","nativeListen","port","callback","isProd","version","index_default"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { LoggerInstanceManager } from '@autofleet/logger';\nimport type { aliveEndpoint } from '@autofleet/nitur';\n\n/** Options to customize the behavior of the SuperExpress application. */\nexport interface Options {\n /** The name of the application. @default 'default-name' */\n name?: string;\n /** The version of the application. @default 'default-version' */\n version?: string;\n /** Enables or disables body parser middleware. if given a string, will be used as the limit for body size @default '1000mb' */\n bodyParser?: boolean | string;\n /** Enables or disables security headers middleware. @default true */\n helmet?: boolean;\n /** Enables or disables HTTP request logging middleware. @default true */\n morgan?: boolean;\n /** Enables or disables the alive endpoint middleware. @default true */\n nitur?: boolean;\n /** Enables or disables the stats endpoint middleware. @default true */\n stats?: boolean;\n /** Enables or disables request tracing middleware. @default true */\n tracing?: boolean;\n /** Enables or disables eager loading of user permissions for tracing middleware. @default true */\n eagerLoadUserPermissions?: boolean;\n /** Options to customize the alive endpoint middleware. */\n aliveEndpointOptions?: Omit<Parameters<typeof aliveEndpoint>[0], 'logger'>;\n /** The servers logger instance. */\n logger: LoggerInstanceManager;\n}\n\nexport const defaultOptions = {\n bodyParser: '1000mb',\n helmet: true,\n morgan: true,\n nitur: true,\n stats: true,\n tracing: true,\n eagerLoadUserPermissions: true,\n} satisfies Omit<Options, 'logger'>;\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport type { Server } from 'node:http';\nimport { createRequire } from 'node:module';\nimport express from 'express';\nimport { defaultOptions, type Options } from '../config/default-options.js';\n\nconst { url } = import.meta;\nconst safeRequire = createRequire(url);\nconst dirname = path.dirname(url);\nconst packageJson = JSON.parse(fs.readFileSync(new URL('package.json', dirname), 'utf8'));\n\n/** Extended express.Application interface which includes nativeListen and the overridden listen method. */\ninterface SuperExpressApp extends Omit<express.Application, 'listen'> {\n /** Original express listen method. */\n nativeListen: express.Application['listen'];\n\n /**\n * Overridden listen method to add custom behavior.\n * @param port - The port number to listen on.\n * @param cb - Optional callback function to execute after the server starts listening.\n */\n listen(port: number, cb?: () => void): Server;\n}\n\n/**\n * Creates a new SuperExpress application with the given options.\n * @param options Optional settings to customize the application.\n * @returns A SuperExpress application instance.\n */\nexport function superExpress({ logger, ...options }: Options): SuperExpressApp {\n const app = express();\n const mergedOptions = { ...defaultOptions, ...options };\n /** Formatting */\n if (mergedOptions.morgan) {\n const morgan = safeRequire('morgan') as typeof import('morgan');\n logger.debug('[SuperExpress] formatting is enabled ✅');\n app.use(morgan((tokens, req, res) => {\n const values = {\n method: tokens.method(req, res),\n url: tokens.url(req, res) ?? 'unknown URL',\n status: tokens.status(req, res),\n contentLength: tokens.res(req, res, 'content-length'),\n responseTime: tokens['response-time'](req, res) ?? '0',\n userAgent: tokens['user-agent'](req, res),\n };\n logger.info(values.url, {\n httpRequest: {\n status: values.status,\n requestUrl: values.url,\n requestMethod: values.method,\n responseSize: values.contentLength,\n latency: {\n seconds: Number.parseInt(values.responseTime, 10) / 1_000,\n nanos: Number.parseInt(values.responseTime, 10) * 1_000_000,\n },\n userAgent: values.userAgent,\n },\n });\n return undefined;\n }));\n }\n /** Security */\n if (mergedOptions.helmet) {\n logger.debug('[SuperExpress] security is enabled ✅');\n // this is what helmet does by default. https://helmetjs.github.io/faq/you-might-not-need-helmet/\n const HEADERS = {\n 'Content-Security-Policy':\n // eslint-disable-next-line @stylistic/max-len\n 'default-src \\'self\\';base-uri \\'self\\';font-src \\'self\\' https: data:;form-action \\'self\\';frame-ancestors \\'self\\';img-src \\'self\\' data:;object-src \\'none\\';script-src \\'self\\';script-src-attr \\'none\\';style-src \\'self\\' https: \\'unsafe-inline\\';upgrade-insecure-requests',\n 'Cross-Origin-Opener-Policy': 'same-origin',\n 'Cross-Origin-Resource-Policy': 'same-origin',\n 'Origin-Agent-Cluster': '?1',\n 'Referrer-Policy': 'no-referrer',\n 'Strict-Transport-Security': 'max-age=15552000; includeSubDomains',\n 'X-Content-Type-Options': 'nosniff',\n 'X-DNS-Prefetch-Control': 'off',\n 'X-Download-Options': 'noopen',\n 'X-Frame-Options': 'SAMEORIGIN',\n 'X-Permitted-Cross-Domain-Policies': 'none',\n 'X-XSS-Protection': '0',\n };\n app.use((_req, res, next) => {\n res.set(HEADERS);\n next();\n });\n app.disable('x-powered-by');\n } else {\n logger.warn('[SuperExpress] security headers are disabled 😨');\n }\n /** Body Parser */\n if (mergedOptions.bodyParser) {\n logger.debug('[SuperExpress] body-parser is enabled ✅');\n const limit = typeof mergedOptions.bodyParser === 'string' ? mergedOptions.bodyParser : '1000mb';\n app.use(express.json({ limit }));\n } else {\n logger.debug('[SuperExpress] body-parser is disabled ❌');\n }\n /** Alive Endpoint */\n if (mergedOptions.nitur) {\n const { aliveEndpoint } = safeRequire('@autofleet/nitur') as typeof import('@autofleet/nitur');\n app.get('/alive', aliveEndpoint({ logger, ...mergedOptions.aliveEndpointOptions }));\n logger.debug('[SuperExpress] added /alive endpoint ✅');\n }\n /** Stats Endpoint */\n if (mergedOptions.stats) {\n const serverRunningSince = new Date();\n app.get('/stats', (_req, res) => {\n res.json({\n name: mergedOptions.name || 'default-name',\n version: mergedOptions.version || 'default-version',\n serverRunningSince,\n });\n });\n logger.debug('[SuperExpress] added /stats endpoint ✅');\n }\n /** Tracing */\n if (mergedOptions.tracing) {\n const { enableTracing, middleware, outbreak } = safeRequire('@autofleet/zehut') as typeof import('@autofleet/zehut');\n enableTracing();\n logger.addContextMiddleware(() => ({\n traceId: outbreak.getCurrentContext()?.context?.get('x-trace-id'),\n }));\n\n app.use(middleware({\n eagerLoadUserPermissions: mergedOptions.eagerLoadUserPermissions,\n }));\n logger.debug('[SuperExpress] tracing is enabled ✅');\n }\n\n const nativeListen: typeof app['listen'] = app.listen.bind(app);\n app.listen = function (port: number, callback?: () => void) {\n const isProd = process.env.NODE_ENV === 'production';\n const version = packageJson?.version || 'unknown';\n logger.debug(`[SuperExpress] is started with version ${version}`);\n logger.debug(`[SuperExpress] will listen on port ${port}`);\n logger.debug(`[SuperExpress] production mode: ${isProd}`);\n return nativeListen(port, callback);\n } as typeof app['listen'];\n\n return Object.assign(app, { nativeListen }) as SuperExpressApp;\n}\n\nexport default superExpress;\n"]}
1
+ {"version":3,"sources":["../config/default-options.ts","../src/index.ts"],"names":["defaultOptions","url","safeRequire","createRequire","dirname","path","packageJson","fs","superExpress","logger","options","app","express","mergedOptions","morgan","tokens","req","res","values","HEADERS","_req","next","limit","aliveEndpoint","serverRunningSince","enableTracing","middleware","nativeListen","port","callback","isProd","version","index_default"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { LoggerInstanceManager } from '@autofleet/logger';\nimport type { aliveEndpoint } from '@autofleet/nitur';\n\n/** Options to customize the behavior of the SuperExpress application. */\nexport interface Options {\n /** The name of the application. @default 'default-name' */\n name?: string;\n /** The version of the application. @default 'default-version' */\n version?: string;\n /** Enables or disables body parser middleware. if given a string, will be used as the limit for body size @default '1000mb' */\n bodyParser?: boolean | string;\n /** Enables or disables security headers middleware. @default true */\n helmet?: boolean;\n /** Enables or disables HTTP request logging middleware. @default true */\n morgan?: boolean;\n /** Enables or disables the alive endpoint middleware. @default true */\n nitur?: boolean;\n /** Enables or disables the stats endpoint middleware. @default true */\n stats?: boolean;\n /** Enables or disables request tracing middleware. @default true */\n tracing?: boolean;\n /** Enables or disables eager loading of user permissions for tracing middleware. @default true */\n eagerLoadUserPermissions?: boolean;\n /** Options to customize the alive endpoint middleware. */\n aliveEndpointOptions?: Omit<Parameters<typeof aliveEndpoint>[0], 'logger'>;\n /** The servers logger instance. */\n logger: LoggerInstanceManager;\n}\n\nexport const defaultOptions = {\n bodyParser: '1000mb',\n helmet: true,\n morgan: true,\n nitur: true,\n stats: true,\n tracing: true,\n eagerLoadUserPermissions: true,\n} satisfies Omit<Options, 'logger'>;\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport type { Server } from 'node:http';\nimport { createRequire } from 'node:module';\nimport express from 'express';\nimport { defaultOptions, type Options } from '../config/default-options.js';\n\nconst { url } = import.meta;\nconst safeRequire = createRequire(url);\nconst dirname = path.dirname(url);\nconst packageJson = JSON.parse(fs.readFileSync(new URL('package.json', dirname), 'utf8'));\n\n/** Extended express.Application interface which includes nativeListen and the overridden listen method. */\ninterface SuperExpressApp extends Omit<express.Application, 'listen'> {\n /** Original express listen method. */\n nativeListen: express.Application['listen'];\n\n /**\n * Overridden listen method to add custom behavior.\n * @param port - The port number to listen on.\n * @param cb - Optional callback function to execute after the server starts listening.\n */\n listen(port: number, cb?: () => void): Server;\n}\n\n/**\n * Creates a new SuperExpress application with the given options.\n * @param options Optional settings to customize the application.\n * @returns A SuperExpress application instance.\n */\nexport function superExpress({ logger, ...options }: Options): SuperExpressApp {\n const app = express();\n const mergedOptions = { ...defaultOptions, ...options };\n /** Formatting */\n if (mergedOptions.morgan) {\n const morgan = safeRequire('morgan') as typeof import('morgan');\n logger.debug('[SuperExpress] formatting is enabled ✅');\n app.use(morgan((tokens, req, res) => {\n const values = {\n method: tokens.method(req, res),\n url: tokens.url(req, res) ?? 'unknown URL',\n status: tokens.status(req, res),\n contentLength: tokens.res(req, res, 'content-length'),\n responseTime: tokens['response-time'](req, res) ?? '0',\n userAgent: tokens['user-agent'](req, res),\n };\n logger.info(values.url, {\n httpRequest: {\n status: values.status,\n requestUrl: values.url,\n requestMethod: values.method,\n responseSize: values.contentLength,\n latency: {\n seconds: Number.parseInt(values.responseTime, 10) / 1_000,\n nanos: Number.parseInt(values.responseTime, 10) * 1_000_000,\n },\n userAgent: values.userAgent,\n },\n });\n return undefined;\n }));\n }\n /** Security */\n if (mergedOptions.helmet) {\n logger.debug('[SuperExpress] security is enabled ✅');\n // this is what helmet does by default. https://helmetjs.github.io/faq/you-might-not-need-helmet/\n const HEADERS = {\n 'Content-Security-Policy':\n // eslint-disable-next-line @stylistic/max-len\n 'default-src \\'self\\';base-uri \\'self\\';font-src \\'self\\' https: data:;form-action \\'self\\';frame-ancestors \\'self\\';img-src \\'self\\' data:;object-src \\'none\\';script-src \\'self\\';script-src-attr \\'none\\';style-src \\'self\\' https: \\'unsafe-inline\\';upgrade-insecure-requests',\n 'Cross-Origin-Opener-Policy': 'same-origin',\n 'Cross-Origin-Resource-Policy': 'same-origin',\n 'Origin-Agent-Cluster': '?1',\n 'Referrer-Policy': 'no-referrer',\n 'Strict-Transport-Security': 'max-age=15552000; includeSubDomains',\n 'X-Content-Type-Options': 'nosniff',\n 'X-DNS-Prefetch-Control': 'off',\n 'X-Download-Options': 'noopen',\n 'X-Frame-Options': 'SAMEORIGIN',\n 'X-Permitted-Cross-Domain-Policies': 'none',\n 'X-XSS-Protection': '0',\n };\n app.use((_req, res, next) => {\n res.set(HEADERS);\n next();\n });\n app.disable('x-powered-by');\n } else {\n logger.warn('[SuperExpress] security headers are disabled 😨');\n }\n /** Body Parser */\n if (mergedOptions.bodyParser) {\n logger.debug('[SuperExpress] body-parser is enabled ✅');\n const limit = typeof mergedOptions.bodyParser === 'string' ? mergedOptions.bodyParser : '1000mb';\n app.use(express.json({ limit }));\n } else {\n logger.debug('[SuperExpress] body-parser is disabled ❌');\n }\n /** Alive Endpoint */\n if (mergedOptions.nitur) {\n const { aliveEndpoint } = safeRequire('@autofleet/nitur') as typeof import('@autofleet/nitur');\n app.get('/alive', aliveEndpoint({ logger, ...mergedOptions.aliveEndpointOptions }));\n logger.debug('[SuperExpress] added /alive endpoint ✅');\n }\n /** Stats Endpoint */\n if (mergedOptions.stats) {\n const serverRunningSince = new Date();\n app.get('/stats', (_req, res) => {\n res.json({\n name: mergedOptions.name || 'default-name',\n version: mergedOptions.version || 'default-version',\n serverRunningSince,\n });\n });\n logger.debug('[SuperExpress] added /stats endpoint ✅');\n }\n /** Tracing */\n if (mergedOptions.tracing) {\n const { enableTracing, middleware } = safeRequire('@autofleet/zehut') as typeof import('@autofleet/zehut');\n enableTracing({ logger });\n\n app.use(middleware({\n eagerLoadUserPermissions: mergedOptions.eagerLoadUserPermissions,\n }));\n logger.debug('[SuperExpress] tracing is enabled ✅');\n }\n\n const nativeListen: typeof app['listen'] = app.listen.bind(app);\n app.listen = function (port: number, callback?: () => void) {\n const isProd = process.env.NODE_ENV === 'production';\n const version = packageJson?.version || 'unknown';\n logger.debug(`[SuperExpress] is started with version ${version}`);\n logger.debug(`[SuperExpress] will listen on port ${port}`);\n logger.debug(`[SuperExpress] production mode: ${isProd}`);\n return nativeListen(port, callback);\n } as typeof app['listen'];\n\n return Object.assign(app, { nativeListen }) as SuperExpressApp;\n}\n\nexport default superExpress;\n"]}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import f from'node:fs';import b from'node:path';import {createRequire}from'node:module';import c from'express';var d={bodyParser:"1000mb",helmet:true,morgan:true,nitur:true,stats:true,tracing:true,eagerLoadUserPermissions:true};var{url:l}=import.meta,p=createRequire(l),y=b.dirname(l),x=JSON.parse(f.readFileSync(new URL("package.json",y),"utf8"));function S({logger:e,...m}){let o=c(),r={...d,...m};if(r.morgan){let t=p("morgan");e.debug("[SuperExpress] formatting is enabled \u2705"),o.use(t((n,s,i)=>{let a={method:n.method(s,i),url:n.url(s,i)??"unknown URL",status:n.status(s,i),contentLength:n.res(s,i,"content-length"),responseTime:n["response-time"](s,i)??"0",userAgent:n["user-agent"](s,i)};e.info(a.url,{httpRequest:{status:a.status,requestUrl:a.url,requestMethod:a.method,responseSize:a.contentLength,latency:{seconds:Number.parseInt(a.responseTime,10)/1e3,nanos:Number.parseInt(a.responseTime,10)*1e6},userAgent:a.userAgent}});}));}if(r.helmet){e.debug("[SuperExpress] security is enabled \u2705");let t={"Content-Security-Policy":"default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests","Cross-Origin-Opener-Policy":"same-origin","Cross-Origin-Resource-Policy":"same-origin","Origin-Agent-Cluster":"?1","Referrer-Policy":"no-referrer","Strict-Transport-Security":"max-age=15552000; includeSubDomains","X-Content-Type-Options":"nosniff","X-DNS-Prefetch-Control":"off","X-Download-Options":"noopen","X-Frame-Options":"SAMEORIGIN","X-Permitted-Cross-Domain-Policies":"none","X-XSS-Protection":"0"};o.use((n,s,i)=>{s.set(t),i();}),o.disable("x-powered-by");}else e.warn("[SuperExpress] security headers are disabled \u{1F628}");if(r.bodyParser){e.debug("[SuperExpress] body-parser is enabled \u2705");let t=typeof r.bodyParser=="string"?r.bodyParser:"1000mb";o.use(c.json({limit:t}));}else e.debug("[SuperExpress] body-parser is disabled \u274C");if(r.nitur){let{aliveEndpoint:t}=p("@autofleet/nitur");o.get("/alive",t({logger:e,...r.aliveEndpointOptions})),e.debug("[SuperExpress] added /alive endpoint \u2705");}if(r.stats){let t=new Date;o.get("/stats",(n,s)=>{s.json({name:r.name||"default-name",version:r.version||"default-version",serverRunningSince:t});}),e.debug("[SuperExpress] added /stats endpoint \u2705");}if(r.tracing){let{enableTracing:t,middleware:n,outbreak:s}=p("@autofleet/zehut");t(),e.addContextMiddleware(()=>({traceId:s.getCurrentContext()?.context?.get("x-trace-id")})),o.use(n({eagerLoadUserPermissions:r.eagerLoadUserPermissions})),e.debug("[SuperExpress] tracing is enabled \u2705");}let u=o.listen.bind(o);return o.listen=function(t,n){let s=process.env.NODE_ENV==="production",i=x?.version||"unknown";return e.debug(`[SuperExpress] is started with version ${i}`),e.debug(`[SuperExpress] will listen on port ${t}`),e.debug(`[SuperExpress] production mode: ${s}`),u(t,n)},Object.assign(o,{nativeListen:u})}var w=S;export{w as default,S as superExpress};//# sourceMappingURL=index.js.map
1
+ import f from'node:fs';import b from'node:path';import {createRequire}from'node:module';import l from'express';var d={bodyParser:"1000mb",helmet:true,morgan:true,nitur:true,stats:true,tracing:true,eagerLoadUserPermissions:true};var{url:c}=import.meta,p=createRequire(c),y=b.dirname(c),S=JSON.parse(f.readFileSync(new URL("package.json",y),"utf8"));function x({logger:e,...m}){let o=l(),s={...d,...m};if(s.morgan){let t=p("morgan");e.debug("[SuperExpress] formatting is enabled \u2705"),o.use(t((r,n,i)=>{let a={method:r.method(n,i),url:r.url(n,i)??"unknown URL",status:r.status(n,i),contentLength:r.res(n,i,"content-length"),responseTime:r["response-time"](n,i)??"0",userAgent:r["user-agent"](n,i)};e.info(a.url,{httpRequest:{status:a.status,requestUrl:a.url,requestMethod:a.method,responseSize:a.contentLength,latency:{seconds:Number.parseInt(a.responseTime,10)/1e3,nanos:Number.parseInt(a.responseTime,10)*1e6},userAgent:a.userAgent}});}));}if(s.helmet){e.debug("[SuperExpress] security is enabled \u2705");let t={"Content-Security-Policy":"default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests","Cross-Origin-Opener-Policy":"same-origin","Cross-Origin-Resource-Policy":"same-origin","Origin-Agent-Cluster":"?1","Referrer-Policy":"no-referrer","Strict-Transport-Security":"max-age=15552000; includeSubDomains","X-Content-Type-Options":"nosniff","X-DNS-Prefetch-Control":"off","X-Download-Options":"noopen","X-Frame-Options":"SAMEORIGIN","X-Permitted-Cross-Domain-Policies":"none","X-XSS-Protection":"0"};o.use((r,n,i)=>{n.set(t),i();}),o.disable("x-powered-by");}else e.warn("[SuperExpress] security headers are disabled \u{1F628}");if(s.bodyParser){e.debug("[SuperExpress] body-parser is enabled \u2705");let t=typeof s.bodyParser=="string"?s.bodyParser:"1000mb";o.use(l.json({limit:t}));}else e.debug("[SuperExpress] body-parser is disabled \u274C");if(s.nitur){let{aliveEndpoint:t}=p("@autofleet/nitur");o.get("/alive",t({logger:e,...s.aliveEndpointOptions})),e.debug("[SuperExpress] added /alive endpoint \u2705");}if(s.stats){let t=new Date;o.get("/stats",(r,n)=>{n.json({name:s.name||"default-name",version:s.version||"default-version",serverRunningSince:t});}),e.debug("[SuperExpress] added /stats endpoint \u2705");}if(s.tracing){let{enableTracing:t,middleware:r}=p("@autofleet/zehut");t({logger:e}),o.use(r({eagerLoadUserPermissions:s.eagerLoadUserPermissions})),e.debug("[SuperExpress] tracing is enabled \u2705");}let u=o.listen.bind(o);return o.listen=function(t,r){let n=process.env.NODE_ENV==="production",i=S?.version||"unknown";return e.debug(`[SuperExpress] is started with version ${i}`),e.debug(`[SuperExpress] will listen on port ${t}`),e.debug(`[SuperExpress] production mode: ${n}`),u(t,r)},Object.assign(o,{nativeListen:u})}var A=x;export{A as default,x as superExpress};//# sourceMappingURL=index.js.map
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../config/default-options.ts","../src/index.ts"],"names":["defaultOptions","url","safeRequire","createRequire","dirname","path","packageJson","fs","superExpress","logger","options","app","express","mergedOptions","morgan","tokens","req","res","values","HEADERS","_req","next","limit","aliveEndpoint","serverRunningSince","enableTracing","middleware","outbreak","nativeListen","port","callback","isProd","version","index_default"],"mappings":"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","file":"index.js","sourcesContent":["import type { LoggerInstanceManager } from '@autofleet/logger';\nimport type { aliveEndpoint } from '@autofleet/nitur';\n\n/** Options to customize the behavior of the SuperExpress application. */\nexport interface Options {\n /** The name of the application. @default 'default-name' */\n name?: string;\n /** The version of the application. @default 'default-version' */\n version?: string;\n /** Enables or disables body parser middleware. if given a string, will be used as the limit for body size @default '1000mb' */\n bodyParser?: boolean | string;\n /** Enables or disables security headers middleware. @default true */\n helmet?: boolean;\n /** Enables or disables HTTP request logging middleware. @default true */\n morgan?: boolean;\n /** Enables or disables the alive endpoint middleware. @default true */\n nitur?: boolean;\n /** Enables or disables the stats endpoint middleware. @default true */\n stats?: boolean;\n /** Enables or disables request tracing middleware. @default true */\n tracing?: boolean;\n /** Enables or disables eager loading of user permissions for tracing middleware. @default true */\n eagerLoadUserPermissions?: boolean;\n /** Options to customize the alive endpoint middleware. */\n aliveEndpointOptions?: Omit<Parameters<typeof aliveEndpoint>[0], 'logger'>;\n /** The servers logger instance. */\n logger: LoggerInstanceManager;\n}\n\nexport const defaultOptions = {\n bodyParser: '1000mb',\n helmet: true,\n morgan: true,\n nitur: true,\n stats: true,\n tracing: true,\n eagerLoadUserPermissions: true,\n} satisfies Omit<Options, 'logger'>;\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport type { Server } from 'node:http';\nimport { createRequire } from 'node:module';\nimport express from 'express';\nimport { defaultOptions, type Options } from '../config/default-options.js';\n\nconst { url } = import.meta;\nconst safeRequire = createRequire(url);\nconst dirname = path.dirname(url);\nconst packageJson = JSON.parse(fs.readFileSync(new URL('package.json', dirname), 'utf8'));\n\n/** Extended express.Application interface which includes nativeListen and the overridden listen method. */\ninterface SuperExpressApp extends Omit<express.Application, 'listen'> {\n /** Original express listen method. */\n nativeListen: express.Application['listen'];\n\n /**\n * Overridden listen method to add custom behavior.\n * @param port - The port number to listen on.\n * @param cb - Optional callback function to execute after the server starts listening.\n */\n listen(port: number, cb?: () => void): Server;\n}\n\n/**\n * Creates a new SuperExpress application with the given options.\n * @param options Optional settings to customize the application.\n * @returns A SuperExpress application instance.\n */\nexport function superExpress({ logger, ...options }: Options): SuperExpressApp {\n const app = express();\n const mergedOptions = { ...defaultOptions, ...options };\n /** Formatting */\n if (mergedOptions.morgan) {\n const morgan = safeRequire('morgan') as typeof import('morgan');\n logger.debug('[SuperExpress] formatting is enabled ✅');\n app.use(morgan((tokens, req, res) => {\n const values = {\n method: tokens.method(req, res),\n url: tokens.url(req, res) ?? 'unknown URL',\n status: tokens.status(req, res),\n contentLength: tokens.res(req, res, 'content-length'),\n responseTime: tokens['response-time'](req, res) ?? '0',\n userAgent: tokens['user-agent'](req, res),\n };\n logger.info(values.url, {\n httpRequest: {\n status: values.status,\n requestUrl: values.url,\n requestMethod: values.method,\n responseSize: values.contentLength,\n latency: {\n seconds: Number.parseInt(values.responseTime, 10) / 1_000,\n nanos: Number.parseInt(values.responseTime, 10) * 1_000_000,\n },\n userAgent: values.userAgent,\n },\n });\n return undefined;\n }));\n }\n /** Security */\n if (mergedOptions.helmet) {\n logger.debug('[SuperExpress] security is enabled ✅');\n // this is what helmet does by default. https://helmetjs.github.io/faq/you-might-not-need-helmet/\n const HEADERS = {\n 'Content-Security-Policy':\n // eslint-disable-next-line @stylistic/max-len\n 'default-src \\'self\\';base-uri \\'self\\';font-src \\'self\\' https: data:;form-action \\'self\\';frame-ancestors \\'self\\';img-src \\'self\\' data:;object-src \\'none\\';script-src \\'self\\';script-src-attr \\'none\\';style-src \\'self\\' https: \\'unsafe-inline\\';upgrade-insecure-requests',\n 'Cross-Origin-Opener-Policy': 'same-origin',\n 'Cross-Origin-Resource-Policy': 'same-origin',\n 'Origin-Agent-Cluster': '?1',\n 'Referrer-Policy': 'no-referrer',\n 'Strict-Transport-Security': 'max-age=15552000; includeSubDomains',\n 'X-Content-Type-Options': 'nosniff',\n 'X-DNS-Prefetch-Control': 'off',\n 'X-Download-Options': 'noopen',\n 'X-Frame-Options': 'SAMEORIGIN',\n 'X-Permitted-Cross-Domain-Policies': 'none',\n 'X-XSS-Protection': '0',\n };\n app.use((_req, res, next) => {\n res.set(HEADERS);\n next();\n });\n app.disable('x-powered-by');\n } else {\n logger.warn('[SuperExpress] security headers are disabled 😨');\n }\n /** Body Parser */\n if (mergedOptions.bodyParser) {\n logger.debug('[SuperExpress] body-parser is enabled ✅');\n const limit = typeof mergedOptions.bodyParser === 'string' ? mergedOptions.bodyParser : '1000mb';\n app.use(express.json({ limit }));\n } else {\n logger.debug('[SuperExpress] body-parser is disabled ❌');\n }\n /** Alive Endpoint */\n if (mergedOptions.nitur) {\n const { aliveEndpoint } = safeRequire('@autofleet/nitur') as typeof import('@autofleet/nitur');\n app.get('/alive', aliveEndpoint({ logger, ...mergedOptions.aliveEndpointOptions }));\n logger.debug('[SuperExpress] added /alive endpoint ✅');\n }\n /** Stats Endpoint */\n if (mergedOptions.stats) {\n const serverRunningSince = new Date();\n app.get('/stats', (_req, res) => {\n res.json({\n name: mergedOptions.name || 'default-name',\n version: mergedOptions.version || 'default-version',\n serverRunningSince,\n });\n });\n logger.debug('[SuperExpress] added /stats endpoint ✅');\n }\n /** Tracing */\n if (mergedOptions.tracing) {\n const { enableTracing, middleware, outbreak } = safeRequire('@autofleet/zehut') as typeof import('@autofleet/zehut');\n enableTracing();\n logger.addContextMiddleware(() => ({\n traceId: outbreak.getCurrentContext()?.context?.get('x-trace-id'),\n }));\n\n app.use(middleware({\n eagerLoadUserPermissions: mergedOptions.eagerLoadUserPermissions,\n }));\n logger.debug('[SuperExpress] tracing is enabled ✅');\n }\n\n const nativeListen: typeof app['listen'] = app.listen.bind(app);\n app.listen = function (port: number, callback?: () => void) {\n const isProd = process.env.NODE_ENV === 'production';\n const version = packageJson?.version || 'unknown';\n logger.debug(`[SuperExpress] is started with version ${version}`);\n logger.debug(`[SuperExpress] will listen on port ${port}`);\n logger.debug(`[SuperExpress] production mode: ${isProd}`);\n return nativeListen(port, callback);\n } as typeof app['listen'];\n\n return Object.assign(app, { nativeListen }) as SuperExpressApp;\n}\n\nexport default superExpress;\n"]}
1
+ {"version":3,"sources":["../config/default-options.ts","../src/index.ts"],"names":["defaultOptions","url","safeRequire","createRequire","dirname","path","packageJson","fs","superExpress","logger","options","app","express","mergedOptions","morgan","tokens","req","res","values","HEADERS","_req","next","limit","aliveEndpoint","serverRunningSince","enableTracing","middleware","nativeListen","port","callback","isProd","version","index_default"],"mappings":"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","file":"index.js","sourcesContent":["import type { LoggerInstanceManager } from '@autofleet/logger';\nimport type { aliveEndpoint } from '@autofleet/nitur';\n\n/** Options to customize the behavior of the SuperExpress application. */\nexport interface Options {\n /** The name of the application. @default 'default-name' */\n name?: string;\n /** The version of the application. @default 'default-version' */\n version?: string;\n /** Enables or disables body parser middleware. if given a string, will be used as the limit for body size @default '1000mb' */\n bodyParser?: boolean | string;\n /** Enables or disables security headers middleware. @default true */\n helmet?: boolean;\n /** Enables or disables HTTP request logging middleware. @default true */\n morgan?: boolean;\n /** Enables or disables the alive endpoint middleware. @default true */\n nitur?: boolean;\n /** Enables or disables the stats endpoint middleware. @default true */\n stats?: boolean;\n /** Enables or disables request tracing middleware. @default true */\n tracing?: boolean;\n /** Enables or disables eager loading of user permissions for tracing middleware. @default true */\n eagerLoadUserPermissions?: boolean;\n /** Options to customize the alive endpoint middleware. */\n aliveEndpointOptions?: Omit<Parameters<typeof aliveEndpoint>[0], 'logger'>;\n /** The servers logger instance. */\n logger: LoggerInstanceManager;\n}\n\nexport const defaultOptions = {\n bodyParser: '1000mb',\n helmet: true,\n morgan: true,\n nitur: true,\n stats: true,\n tracing: true,\n eagerLoadUserPermissions: true,\n} satisfies Omit<Options, 'logger'>;\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport type { Server } from 'node:http';\nimport { createRequire } from 'node:module';\nimport express from 'express';\nimport { defaultOptions, type Options } from '../config/default-options.js';\n\nconst { url } = import.meta;\nconst safeRequire = createRequire(url);\nconst dirname = path.dirname(url);\nconst packageJson = JSON.parse(fs.readFileSync(new URL('package.json', dirname), 'utf8'));\n\n/** Extended express.Application interface which includes nativeListen and the overridden listen method. */\ninterface SuperExpressApp extends Omit<express.Application, 'listen'> {\n /** Original express listen method. */\n nativeListen: express.Application['listen'];\n\n /**\n * Overridden listen method to add custom behavior.\n * @param port - The port number to listen on.\n * @param cb - Optional callback function to execute after the server starts listening.\n */\n listen(port: number, cb?: () => void): Server;\n}\n\n/**\n * Creates a new SuperExpress application with the given options.\n * @param options Optional settings to customize the application.\n * @returns A SuperExpress application instance.\n */\nexport function superExpress({ logger, ...options }: Options): SuperExpressApp {\n const app = express();\n const mergedOptions = { ...defaultOptions, ...options };\n /** Formatting */\n if (mergedOptions.morgan) {\n const morgan = safeRequire('morgan') as typeof import('morgan');\n logger.debug('[SuperExpress] formatting is enabled ✅');\n app.use(morgan((tokens, req, res) => {\n const values = {\n method: tokens.method(req, res),\n url: tokens.url(req, res) ?? 'unknown URL',\n status: tokens.status(req, res),\n contentLength: tokens.res(req, res, 'content-length'),\n responseTime: tokens['response-time'](req, res) ?? '0',\n userAgent: tokens['user-agent'](req, res),\n };\n logger.info(values.url, {\n httpRequest: {\n status: values.status,\n requestUrl: values.url,\n requestMethod: values.method,\n responseSize: values.contentLength,\n latency: {\n seconds: Number.parseInt(values.responseTime, 10) / 1_000,\n nanos: Number.parseInt(values.responseTime, 10) * 1_000_000,\n },\n userAgent: values.userAgent,\n },\n });\n return undefined;\n }));\n }\n /** Security */\n if (mergedOptions.helmet) {\n logger.debug('[SuperExpress] security is enabled ✅');\n // this is what helmet does by default. https://helmetjs.github.io/faq/you-might-not-need-helmet/\n const HEADERS = {\n 'Content-Security-Policy':\n // eslint-disable-next-line @stylistic/max-len\n 'default-src \\'self\\';base-uri \\'self\\';font-src \\'self\\' https: data:;form-action \\'self\\';frame-ancestors \\'self\\';img-src \\'self\\' data:;object-src \\'none\\';script-src \\'self\\';script-src-attr \\'none\\';style-src \\'self\\' https: \\'unsafe-inline\\';upgrade-insecure-requests',\n 'Cross-Origin-Opener-Policy': 'same-origin',\n 'Cross-Origin-Resource-Policy': 'same-origin',\n 'Origin-Agent-Cluster': '?1',\n 'Referrer-Policy': 'no-referrer',\n 'Strict-Transport-Security': 'max-age=15552000; includeSubDomains',\n 'X-Content-Type-Options': 'nosniff',\n 'X-DNS-Prefetch-Control': 'off',\n 'X-Download-Options': 'noopen',\n 'X-Frame-Options': 'SAMEORIGIN',\n 'X-Permitted-Cross-Domain-Policies': 'none',\n 'X-XSS-Protection': '0',\n };\n app.use((_req, res, next) => {\n res.set(HEADERS);\n next();\n });\n app.disable('x-powered-by');\n } else {\n logger.warn('[SuperExpress] security headers are disabled 😨');\n }\n /** Body Parser */\n if (mergedOptions.bodyParser) {\n logger.debug('[SuperExpress] body-parser is enabled ✅');\n const limit = typeof mergedOptions.bodyParser === 'string' ? mergedOptions.bodyParser : '1000mb';\n app.use(express.json({ limit }));\n } else {\n logger.debug('[SuperExpress] body-parser is disabled ❌');\n }\n /** Alive Endpoint */\n if (mergedOptions.nitur) {\n const { aliveEndpoint } = safeRequire('@autofleet/nitur') as typeof import('@autofleet/nitur');\n app.get('/alive', aliveEndpoint({ logger, ...mergedOptions.aliveEndpointOptions }));\n logger.debug('[SuperExpress] added /alive endpoint ✅');\n }\n /** Stats Endpoint */\n if (mergedOptions.stats) {\n const serverRunningSince = new Date();\n app.get('/stats', (_req, res) => {\n res.json({\n name: mergedOptions.name || 'default-name',\n version: mergedOptions.version || 'default-version',\n serverRunningSince,\n });\n });\n logger.debug('[SuperExpress] added /stats endpoint ✅');\n }\n /** Tracing */\n if (mergedOptions.tracing) {\n const { enableTracing, middleware } = safeRequire('@autofleet/zehut') as typeof import('@autofleet/zehut');\n enableTracing({ logger });\n\n app.use(middleware({\n eagerLoadUserPermissions: mergedOptions.eagerLoadUserPermissions,\n }));\n logger.debug('[SuperExpress] tracing is enabled ✅');\n }\n\n const nativeListen: typeof app['listen'] = app.listen.bind(app);\n app.listen = function (port: number, callback?: () => void) {\n const isProd = process.env.NODE_ENV === 'production';\n const version = packageJson?.version || 'unknown';\n logger.debug(`[SuperExpress] is started with version ${version}`);\n logger.debug(`[SuperExpress] will listen on port ${port}`);\n logger.debug(`[SuperExpress] production mode: ${isProd}`);\n return nativeListen(port, callback);\n } as typeof app['listen'];\n\n return Object.assign(app, { nativeListen }) as SuperExpressApp;\n}\n\nexport default superExpress;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/super-express",
3
- "version": "6.0.11",
3
+ "version": "7.0.0",
4
4
  "description": "AF Express with built in boilerplate",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -45,7 +45,7 @@
45
45
  "devDependencies": {
46
46
  "@autofleet/logger": "^4.2.1",
47
47
  "@autofleet/nitur": "^2.1.0",
48
- "@autofleet/zehut": "3.2.0",
48
+ "@autofleet/zehut": "^4.0.0",
49
49
  "@types/express": "^4.17.21",
50
50
  "@types/morgan": "^1.9.9",
51
51
  "@types/supertest": "^6.0.2",
@@ -58,7 +58,7 @@
58
58
  "peerDependencies": {
59
59
  "@autofleet/logger": ">=4.0.0",
60
60
  "@autofleet/nitur": ">=2.1.0",
61
- "@autofleet/zehut": ">=3.2.0",
61
+ "@autofleet/zehut": ">=4.0.0",
62
62
  "morgan": "^1.10.0"
63
63
  },
64
64
  "peerDependenciesMeta": {