@arkstack/driver-express 0.10.10 → 0.11.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/dist/app.d.ts +21 -0
- package/dist/index.d.ts +1 -0
- package/dist/middlewares/index.js +2 -1
- package/dist/middlewares/index.js.map +1 -1
- package/package.json +6 -5
package/dist/app.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Request, Response } from 'express'
|
|
2
|
+
|
|
3
|
+
declare module '@arkstack/common' {
|
|
4
|
+
interface HookRegistry {
|
|
5
|
+
'middleware:auth': {
|
|
6
|
+
before: (ctx: { req: Request, res: Response }) => Promise<void>
|
|
7
|
+
after: (ctx: { req: Request, res: Response }) => Promise<void>
|
|
8
|
+
error: (error: unknown, ctx: { req: Request, res: Response }) => Promise<void>
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
declare module '@arkstack/foundry' {
|
|
14
|
+
interface HookRegistry {
|
|
15
|
+
'middleware:auth': {
|
|
16
|
+
before: (ctx: { req: Request, res: Response }) => Promise<void>
|
|
17
|
+
after: (ctx: { req: Request, res: Response }) => Promise<void>
|
|
18
|
+
error: (error: unknown, ctx: { req: Request, res: Response }) => Promise<void>
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference path="./app.d.ts" />
|
|
1
2
|
import { ErrorRequestHandler, Express, Handler, Router as Router$1 } from "express";
|
|
2
3
|
import { ArkstackKitDriver, ArkstackMiddlewareConfig, ArkstackRouteListOptions, PromiseOrValue } from "@arkstack/contract";
|
|
3
4
|
import { Router as Router$2 } from "clear-router/express";
|
|
@@ -91,7 +91,8 @@ const colors = {
|
|
|
91
91
|
* @returns
|
|
92
92
|
*/
|
|
93
93
|
const requestLogger = ({ allowInProduction = false } = {}) => async (req, res, next) => {
|
|
94
|
-
|
|
94
|
+
const VERBOSE = process.env.VERBOSITY != "0";
|
|
95
|
+
if (nodeEnv() === "prod" && !allowInProduction || !VERBOSE) return next();
|
|
95
96
|
const start = Date.now();
|
|
96
97
|
const status = res.statusCode || 200;
|
|
97
98
|
const duration = Date.now() - start;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/middlewares/auth.ts","../../src/middlewares/formdata.ts","../../src/Exceptions/RateLimitExceededException.ts","../../src/middlewares/limiter.ts","../../src/middlewares/request-logger.ts"],"sourcesContent":["import type { Handler } from 'express'\nimport { Hook } from '@arkstack/common'\n\nexport const auth: Handler = async (req, res, next) => {\n const { Auth, AuthenticationException } = await import('@arkstack/auth')\n\n try {\n if (Hook.has('middleware:auth', 'before'))\n await Promise.resolve(Hook.get('middleware:auth', 'before')?.({ req, res }))\n\n const token = readBearerToken(req.headers.authorization)\n\n if (!token) {\n throw new AuthenticationException('Unauthenticated', { req, status: 401 })\n }\n\n const auth = Auth.make().setRequest(req)\n const user = await Auth.make().setRequest(req).authorizeToken(token)\n\n req.user = user\n req.auth = auth\n req.authUser = user\n req.session = auth.session()\n req.authToken = token\n\n if (Hook.has('middleware:auth', 'after'))\n await Promise.resolve(Hook.get('middleware:auth', 'after')?.({ req, res }))\n\n next()\n } catch (error) {\n if (Hook.has('middleware:auth', 'error'))\n await Promise.resolve(Hook.get('middleware:auth', 'error')?.(error, {\n req,\n res\n }))\n\n next(error)\n }\n}\n\nconst readBearerToken = (authorization: string | string[] | undefined) => {\n const value = Array.isArray(authorization) ? authorization[0] : authorization\n\n if (!value?.startsWith('Bearer ')) {\n return null\n }\n\n return value.substring(7)\n}\n","import multer from 'multer'\n\nexport const formdata = multer({ storage: multer.memoryStorage() })","import { Exception } from '@arkstack/common'\nimport { Options } from 'express-rate-limit'\n\nexport class RateLimitExceededException extends Exception {\n statusCode: number = 429\n name: string\n\n constructor(options: Options) {\n super(options.message)\n this.name = 'RateLimitExceededException'\n this.statusCode = options.statusCode ?? 429\n }\n}","import { ValueDeterminingMiddleware, rateLimit } from 'express-rate-limit'\n\nimport { RateLimitExceededException } from '../Exceptions/RateLimitExceededException'\nimport { env } from '@arkstack/common'\n\n/**\n * create a rate limiter middleware\n * \n * @param requests number of requests allowed per windowMs\n * @param perMin number of minutes for the window\n * @param message custom message to be returned when rate limit is exceeded\n * @returns \n */\nexport const limiter = (\n requests: number | ValueDeterminingMiddleware<number> = 100,\n perSec: number = 900,\n message?: string | ValueDeterminingMiddleware<string>\n) => rateLimit({\n message,\n limit: requests, // Limit each IP to 100 requests per `window` (here, per 15 minutes)\n windowMs: (env('NODE_ENV') === 'production' ? perSec : 30) * 1000, // 15 minutes\n standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers\n legacyHeaders: false, // Disable the `X-RateLimit-*` headers\n ipv6Subnet: 56, // Set to 60 or 64 to be less aggressive, or 52 or 48 to be more aggressive\n handler: (_, __, ___, options) => {\n throw new RateLimitExceededException(options)\n }\n})","import { Logger, nodeEnv } from '@arkstack/common'\nimport { NextFunction, Request, Response } from 'express'\n\nconst colors: Record<string, 'green' | 'blue' | 'yellow' | 'red' | 'cyan'> = {\n GET: 'green',\n POST: 'blue',\n PUT: 'yellow',\n DELETE: 'red',\n PATCH: 'cyan',\n}\n\n/**\n * Middleware to log incoming requests and their response times.\n * \n * @param config Configuration options for the request logger middleware.\n * @param config.allowInProduction If true, the logger will also log requests in production environment. Default is false. \n * @returns \n */\nexport const requestLogger = ({\n allowInProduction = false,\n}: {\n allowInProduction?: boolean\n} = {}) => async (req: Request, res: Response, next: NextFunction) => {\n if (nodeEnv() === 'prod' && !allowInProduction) return next()\n\n const start = Date.now()\n\n const status = res.statusCode || 200\n const duration = Date.now() - start\n Logger.log([\n [`[${req.method}]`, colors[req.method] || 'white'],\n [req.url, 'cyan'],\n [status.toString(), status >= 500 ? 'red' : status >= 400 ? 'yellow' : 'green'],\n [`- ${duration}ms`, 'dim']\n ], ' ')\n\n next()\n}"],"mappings":";;;;AAGA,MAAa,OAAgB,OAAO,KAAK,KAAK,SAAS;CACnD,MAAM,EAAE,MAAM,4BAA4B,MAAM,OAAO;CAEvD,IAAI;EACA,IAAI,KAAK,IAAI,mBAAmB,SAAS,EACrC,MAAM,QAAQ,QAAQ,KAAK,IAAI,mBAAmB,SAAS,GAAG;GAAE;GAAK;GAAK,CAAC,CAAC;EAEhF,MAAM,QAAQ,gBAAgB,IAAI,QAAQ,cAAc;EAExD,IAAI,CAAC,OACD,MAAM,IAAI,wBAAwB,mBAAmB;GAAE;GAAK,QAAQ;GAAK,CAAC;EAG9E,MAAM,OAAO,KAAK,MAAM,CAAC,WAAW,IAAI;EACxC,MAAM,OAAO,MAAM,KAAK,MAAM,CAAC,WAAW,IAAI,CAAC,eAAe,MAAM;EAEpE,IAAI,OAAO;EACX,IAAI,OAAO;EACX,IAAI,WAAW;EACf,IAAI,UAAU,KAAK,SAAS;EAC5B,IAAI,YAAY;EAEhB,IAAI,KAAK,IAAI,mBAAmB,QAAQ,EACpC,MAAM,QAAQ,QAAQ,KAAK,IAAI,mBAAmB,QAAQ,GAAG;GAAE;GAAK;GAAK,CAAC,CAAC;EAE/E,MAAM;UACD,OAAO;EACZ,IAAI,KAAK,IAAI,mBAAmB,QAAQ,EACpC,MAAM,QAAQ,QAAQ,KAAK,IAAI,mBAAmB,QAAQ,GAAG,OAAO;GAChE;GACA;GACH,CAAC,CAAC;EAEP,KAAK,MAAM;;;AAInB,MAAM,mBAAmB,kBAAiD;CACtE,MAAM,QAAQ,MAAM,QAAQ,cAAc,GAAG,cAAc,KAAK;CAEhE,IAAI,CAAC,OAAO,WAAW,UAAU,EAC7B,OAAO;CAGX,OAAO,MAAM,UAAU,EAAE;;;;AC7C7B,MAAa,WAAW,OAAO,EAAE,SAAS,OAAO,eAAe,EAAE,CAAA;;;ACClE,IAAa,6BAAb,cAAgD,UAAU;CACtD,aAAqB;CACrB;CAEA,YAAY,SAAkB;EAC1B,MAAM,QAAQ,QAAQ;EACtB,KAAK,OAAO;EACZ,KAAK,aAAa,QAAQ,cAAc;;;;;;;;;;;;;ACGhD,MAAa,WACT,WAAwD,KACxD,SAAiB,KACjB,YACC,UAAU;CACX;CACA,OAAO;CACP,WAAW,IAAI,WAAW,KAAK,eAAe,SAAS,MAAM;CAC7D,iBAAiB;CACjB,eAAe;CACf,YAAY;CACZ,UAAU,GAAG,IAAI,KAAK,YAAY;EAC9B,MAAM,IAAI,2BAA2B,QAAQ;;CAEpD,CAAA;;;ACxBD,MAAM,SAAuE;CACzE,KAAK;CACL,MAAM;CACN,KAAK;CACL,QAAQ;CACR,OAAO;CACV;;;;;;;;AASD,MAAa,iBAAiB,EAC1B,oBAAoB,UAGpB,EAAE,KAAK,OAAO,KAAc,KAAe,SAAuB;CAClE,IAAI,SAAS,KAAK,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/middlewares/auth.ts","../../src/middlewares/formdata.ts","../../src/Exceptions/RateLimitExceededException.ts","../../src/middlewares/limiter.ts","../../src/middlewares/request-logger.ts"],"sourcesContent":["import type { Handler } from 'express'\nimport { Hook } from '@arkstack/common'\n\nexport const auth: Handler = async (req, res, next) => {\n const { Auth, AuthenticationException } = await import('@arkstack/auth')\n\n try {\n if (Hook.has('middleware:auth', 'before'))\n await Promise.resolve(Hook.get('middleware:auth', 'before')?.({ req, res }))\n\n const token = readBearerToken(req.headers.authorization)\n\n if (!token) {\n throw new AuthenticationException('Unauthenticated', { req, status: 401 })\n }\n\n const auth = Auth.make().setRequest(req)\n const user = await Auth.make().setRequest(req).authorizeToken(token)\n\n req.user = user\n req.auth = auth\n req.authUser = user\n req.session = auth.session()\n req.authToken = token\n\n if (Hook.has('middleware:auth', 'after'))\n await Promise.resolve(Hook.get('middleware:auth', 'after')?.({ req, res }))\n\n next()\n } catch (error) {\n if (Hook.has('middleware:auth', 'error'))\n await Promise.resolve(Hook.get('middleware:auth', 'error')?.(error, {\n req,\n res\n }))\n\n next(error)\n }\n}\n\nconst readBearerToken = (authorization: string | string[] | undefined) => {\n const value = Array.isArray(authorization) ? authorization[0] : authorization\n\n if (!value?.startsWith('Bearer ')) {\n return null\n }\n\n return value.substring(7)\n}\n","import multer from 'multer'\n\nexport const formdata = multer({ storage: multer.memoryStorage() })","import { Exception } from '@arkstack/common'\nimport { Options } from 'express-rate-limit'\n\nexport class RateLimitExceededException extends Exception {\n statusCode: number = 429\n name: string\n\n constructor(options: Options) {\n super(options.message)\n this.name = 'RateLimitExceededException'\n this.statusCode = options.statusCode ?? 429\n }\n}","import { ValueDeterminingMiddleware, rateLimit } from 'express-rate-limit'\n\nimport { RateLimitExceededException } from '../Exceptions/RateLimitExceededException'\nimport { env } from '@arkstack/common'\n\n/**\n * create a rate limiter middleware\n * \n * @param requests number of requests allowed per windowMs\n * @param perMin number of minutes for the window\n * @param message custom message to be returned when rate limit is exceeded\n * @returns \n */\nexport const limiter = (\n requests: number | ValueDeterminingMiddleware<number> = 100,\n perSec: number = 900,\n message?: string | ValueDeterminingMiddleware<string>\n) => rateLimit({\n message,\n limit: requests, // Limit each IP to 100 requests per `window` (here, per 15 minutes)\n windowMs: (env('NODE_ENV') === 'production' ? perSec : 30) * 1000, // 15 minutes\n standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers\n legacyHeaders: false, // Disable the `X-RateLimit-*` headers\n ipv6Subnet: 56, // Set to 60 or 64 to be less aggressive, or 52 or 48 to be more aggressive\n handler: (_, __, ___, options) => {\n throw new RateLimitExceededException(options)\n }\n})","import { Logger, nodeEnv } from '@arkstack/common'\nimport { NextFunction, Request, Response } from 'express'\n\nconst colors: Record<string, 'green' | 'blue' | 'yellow' | 'red' | 'cyan'> = {\n GET: 'green',\n POST: 'blue',\n PUT: 'yellow',\n DELETE: 'red',\n PATCH: 'cyan',\n}\n\n/**\n * Middleware to log incoming requests and their response times.\n * \n * @param config Configuration options for the request logger middleware.\n * @param config.allowInProduction If true, the logger will also log requests in production environment. Default is false. \n * @returns \n */\nexport const requestLogger = ({\n allowInProduction = false,\n}: {\n allowInProduction?: boolean\n} = {}) => async (req: Request, res: Response, next: NextFunction) => {\n const VERBOSE = process.env.VERBOSITY != '0'\n if ((nodeEnv() === 'prod' && !allowInProduction) || !VERBOSE) return next()\n\n const start = Date.now()\n\n const status = res.statusCode || 200\n const duration = Date.now() - start\n Logger.log([\n [`[${req.method}]`, colors[req.method] || 'white'],\n [req.url, 'cyan'],\n [status.toString(), status >= 500 ? 'red' : status >= 400 ? 'yellow' : 'green'],\n [`- ${duration}ms`, 'dim']\n ], ' ')\n\n next()\n}"],"mappings":";;;;AAGA,MAAa,OAAgB,OAAO,KAAK,KAAK,SAAS;CACnD,MAAM,EAAE,MAAM,4BAA4B,MAAM,OAAO;CAEvD,IAAI;EACA,IAAI,KAAK,IAAI,mBAAmB,SAAS,EACrC,MAAM,QAAQ,QAAQ,KAAK,IAAI,mBAAmB,SAAS,GAAG;GAAE;GAAK;GAAK,CAAC,CAAC;EAEhF,MAAM,QAAQ,gBAAgB,IAAI,QAAQ,cAAc;EAExD,IAAI,CAAC,OACD,MAAM,IAAI,wBAAwB,mBAAmB;GAAE;GAAK,QAAQ;GAAK,CAAC;EAG9E,MAAM,OAAO,KAAK,MAAM,CAAC,WAAW,IAAI;EACxC,MAAM,OAAO,MAAM,KAAK,MAAM,CAAC,WAAW,IAAI,CAAC,eAAe,MAAM;EAEpE,IAAI,OAAO;EACX,IAAI,OAAO;EACX,IAAI,WAAW;EACf,IAAI,UAAU,KAAK,SAAS;EAC5B,IAAI,YAAY;EAEhB,IAAI,KAAK,IAAI,mBAAmB,QAAQ,EACpC,MAAM,QAAQ,QAAQ,KAAK,IAAI,mBAAmB,QAAQ,GAAG;GAAE;GAAK;GAAK,CAAC,CAAC;EAE/E,MAAM;UACD,OAAO;EACZ,IAAI,KAAK,IAAI,mBAAmB,QAAQ,EACpC,MAAM,QAAQ,QAAQ,KAAK,IAAI,mBAAmB,QAAQ,GAAG,OAAO;GAChE;GACA;GACH,CAAC,CAAC;EAEP,KAAK,MAAM;;;AAInB,MAAM,mBAAmB,kBAAiD;CACtE,MAAM,QAAQ,MAAM,QAAQ,cAAc,GAAG,cAAc,KAAK;CAEhE,IAAI,CAAC,OAAO,WAAW,UAAU,EAC7B,OAAO;CAGX,OAAO,MAAM,UAAU,EAAE;;;;AC7C7B,MAAa,WAAW,OAAO,EAAE,SAAS,OAAO,eAAe,EAAE,CAAA;;;ACClE,IAAa,6BAAb,cAAgD,UAAU;CACtD,aAAqB;CACrB;CAEA,YAAY,SAAkB;EAC1B,MAAM,QAAQ,QAAQ;EACtB,KAAK,OAAO;EACZ,KAAK,aAAa,QAAQ,cAAc;;;;;;;;;;;;;ACGhD,MAAa,WACT,WAAwD,KACxD,SAAiB,KACjB,YACC,UAAU;CACX;CACA,OAAO;CACP,WAAW,IAAI,WAAW,KAAK,eAAe,SAAS,MAAM;CAC7D,iBAAiB;CACjB,eAAe;CACf,YAAY;CACZ,UAAU,GAAG,IAAI,KAAK,YAAY;EAC9B,MAAM,IAAI,2BAA2B,QAAQ;;CAEpD,CAAA;;;ACxBD,MAAM,SAAuE;CACzE,KAAK;CACL,MAAM;CACN,KAAK;CACL,QAAQ;CACR,OAAO;CACV;;;;;;;;AASD,MAAa,iBAAiB,EAC1B,oBAAoB,UAGpB,EAAE,KAAK,OAAO,KAAc,KAAe,SAAuB;CAClE,MAAM,UAAU,QAAQ,IAAI,aAAa;CACzC,IAAK,SAAS,KAAK,UAAU,CAAC,qBAAsB,CAAC,SAAS,OAAO,MAAM;CAE3E,MAAM,QAAQ,KAAK,KAAK;CAExB,MAAM,SAAS,IAAI,cAAc;CACjC,MAAM,WAAW,KAAK,KAAK,GAAG;CAC9B,OAAO,IAAI;EACP,CAAC,IAAI,IAAI,OAAO,IAAI,OAAO,IAAI,WAAW,QAAQ;EAClD,CAAC,IAAI,KAAK,OAAO;EACjB,CAAC,OAAO,UAAU,EAAE,UAAU,MAAM,QAAQ,UAAU,MAAM,WAAW,QAAQ;EAC/E,CAAC,KAAK,SAAS,KAAK,MAAM;EAC7B,EAAE,IAAI;CAEP,MAAM"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arkstack/driver-express",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Express driver for Arkstack, providing Express-based runtime integration for the framework.",
|
|
6
6
|
"homepage": "https://arkstack.toneflix.net",
|
|
@@ -42,12 +42,13 @@
|
|
|
42
42
|
"express-rate-limit": "^8.4.1",
|
|
43
43
|
"@resora/plugin-clear-router": "^1.0.33",
|
|
44
44
|
"resora": "^1.3.6",
|
|
45
|
-
"@arkstack/contract": "^0.
|
|
45
|
+
"@arkstack/contract": "^0.11.1"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"express": "^5.2.1",
|
|
49
|
-
"@arkstack/
|
|
50
|
-
"@arkstack/
|
|
49
|
+
"@arkstack/foundry": "^0.11.1",
|
|
50
|
+
"@arkstack/auth": "^0.11.1",
|
|
51
|
+
"@arkstack/common": "^0.11.1"
|
|
51
52
|
},
|
|
52
53
|
"peerDependenciesMeta": {
|
|
53
54
|
"@arkstack/auth": {
|
|
@@ -59,7 +60,7 @@
|
|
|
59
60
|
"@types/express": "^5.0.6"
|
|
60
61
|
},
|
|
61
62
|
"scripts": {
|
|
62
|
-
"build": "tsdown",
|
|
63
|
+
"build": "tsdown --config-loader unrun",
|
|
63
64
|
"version:patch": "pnpm version patch"
|
|
64
65
|
}
|
|
65
66
|
}
|