@forklaunch/express 1.2.36 → 1.2.38

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/lib/index.js CHANGED
@@ -1417,13 +1417,23 @@ function serveExpress(app, openTelemetryCollector, opts = {}) {
1417
1417
  writer.abort("client aborted");
1418
1418
  };
1419
1419
  abort.signal.addEventListener("abort", onAbort);
1420
+ const onClientAbort = () => abort.abort();
1421
+ if (request.signal.aborted) {
1422
+ abort.abort();
1423
+ } else {
1424
+ request.signal.addEventListener("abort", onClientAbort, {
1425
+ once: true
1426
+ });
1427
+ }
1420
1428
  res.once("finish", cleanup);
1421
1429
  res.once("close", cleanup);
1422
1430
  res.once("finish", () => {
1423
1431
  abort.signal.removeEventListener("abort", onAbort);
1432
+ request.signal.removeEventListener("abort", onClientAbort);
1424
1433
  });
1425
1434
  res.once("close", () => {
1426
1435
  abort.signal.removeEventListener("abort", onAbort);
1436
+ request.signal.removeEventListener("abort", onClientAbort);
1427
1437
  });
1428
1438
  try {
1429
1439
  req.on("error", (error) => {
@@ -1895,14 +1905,66 @@ var import_common2 = require("@forklaunch/common");
1895
1905
  var import_http = require("@forklaunch/core/http");
1896
1906
  var import_busboy = __toESM(require("busboy"));
1897
1907
  var import_express = __toESM(require("express"));
1908
+ var DEFAULT_CONTENT_TYPES = {
1909
+ json: "application/json",
1910
+ text: "text/plain",
1911
+ urlEncoded: "application/x-www-form-urlencoded",
1912
+ file: "application/octet-stream",
1913
+ multipart: "multipart/form-data"
1914
+ };
1898
1915
  function contentParse(options2) {
1899
- const jsonParser = import_express.default.json(options2?.json);
1900
- const urlencodedParser = import_express.default.urlencoded({
1901
- extended: true,
1902
- ...options2?.urlencoded
1903
- });
1904
- const textParser = import_express.default.text(options2?.text);
1905
- const rawParser = import_express.default.raw(options2?.raw);
1916
+ let resolvedOptions;
1917
+ const parserCache = /* @__PURE__ */ new Map();
1918
+ const captureRawBody = (base) => {
1919
+ const userVerify = base?.verify;
1920
+ return (req, res, buf, encoding) => {
1921
+ userVerify?.(req, res, buf, encoding);
1922
+ req._rawBody = buf;
1923
+ };
1924
+ };
1925
+ const buildParser = (parserType, contentTypeOverride) => {
1926
+ const typeOverride = contentTypeOverride ? { type: contentTypeOverride } : {};
1927
+ switch (parserType) {
1928
+ case "json":
1929
+ return import_express.default.json({
1930
+ ...resolvedOptions?.json,
1931
+ verify: captureRawBody(resolvedOptions?.json),
1932
+ ...typeOverride
1933
+ });
1934
+ case "urlEncoded":
1935
+ return import_express.default.urlencoded({
1936
+ extended: true,
1937
+ ...resolvedOptions?.urlencoded,
1938
+ verify: captureRawBody(resolvedOptions?.urlencoded),
1939
+ ...typeOverride
1940
+ });
1941
+ case "text":
1942
+ return import_express.default.text({
1943
+ ...resolvedOptions?.text,
1944
+ verify: captureRawBody(resolvedOptions?.text),
1945
+ ...typeOverride
1946
+ });
1947
+ case "file":
1948
+ return import_express.default.raw({
1949
+ ...resolvedOptions?.raw,
1950
+ verify: captureRawBody(resolvedOptions?.raw),
1951
+ ...typeOverride
1952
+ });
1953
+ default:
1954
+ (0, import_common2.isNever)(parserType);
1955
+ throw new Error("Unsupported parser type: " + parserType);
1956
+ }
1957
+ };
1958
+ const parserFor = (parserType, contentType) => {
1959
+ const contentTypeOverride = contentType !== DEFAULT_CONTENT_TYPES[parserType] ? contentType : void 0;
1960
+ const cacheKey = `${parserType}:${contentTypeOverride ?? ""}`;
1961
+ let parser = parserCache.get(cacheKey);
1962
+ if (!parser) {
1963
+ parser = buildParser(parserType, contentTypeOverride);
1964
+ parserCache.set(cacheKey, parser);
1965
+ }
1966
+ return parser;
1967
+ };
1906
1968
  return async (req, res, next) => {
1907
1969
  try {
1908
1970
  const coercedRequest = req;
@@ -1919,24 +1981,39 @@ function contentParse(options2) {
1919
1981
  if (!discriminatedBody) {
1920
1982
  return next();
1921
1983
  }
1984
+ if (!resolvedOptions) {
1985
+ const globalOptions = coercedRequest._globalOptions?.();
1986
+ resolvedOptions = {
1987
+ busboy: globalOptions?.busboy ?? options2?.busboy,
1988
+ text: globalOptions?.text ?? options2?.text,
1989
+ json: globalOptions?.json ?? options2?.json,
1990
+ urlencoded: globalOptions?.urlencoded ?? options2?.urlencoded,
1991
+ raw: globalOptions?.raw ?? options2?.raw
1992
+ };
1993
+ }
1922
1994
  switch (discriminatedBody.parserType) {
1923
1995
  case "json":
1924
- return jsonParser(req, res, next);
1925
1996
  case "urlEncoded":
1926
- return urlencodedParser(req, res, next);
1927
1997
  case "text":
1928
- return textParser(req, res, next);
1998
+ return parserFor(
1999
+ discriminatedBody.parserType,
2000
+ discriminatedBody.contentType
2001
+ )(req, res, next);
1929
2002
  case "file":
1930
- return rawParser(req, res, async (err) => {
1931
- if (err) {
1932
- return next(err);
2003
+ return parserFor("file", discriminatedBody.contentType)(
2004
+ req,
2005
+ res,
2006
+ async (err) => {
2007
+ if (err) {
2008
+ return next(err);
2009
+ }
2010
+ next();
1933
2011
  }
1934
- next();
1935
- });
2012
+ );
1936
2013
  case "multipart": {
1937
2014
  const bb = (0, import_busboy.default)({
1938
2015
  headers: req.headers,
1939
- ...options2?.busboy
2016
+ ...resolvedOptions?.busboy
1940
2017
  });
1941
2018
  const body = {};
1942
2019
  bb.on("file", (fieldname, file) => {
package/lib/index.mjs CHANGED
@@ -1391,13 +1391,23 @@ function serveExpress(app, openTelemetryCollector, opts = {}) {
1391
1391
  writer.abort("client aborted");
1392
1392
  };
1393
1393
  abort.signal.addEventListener("abort", onAbort);
1394
+ const onClientAbort = () => abort.abort();
1395
+ if (request.signal.aborted) {
1396
+ abort.abort();
1397
+ } else {
1398
+ request.signal.addEventListener("abort", onClientAbort, {
1399
+ once: true
1400
+ });
1401
+ }
1394
1402
  res.once("finish", cleanup);
1395
1403
  res.once("close", cleanup);
1396
1404
  res.once("finish", () => {
1397
1405
  abort.signal.removeEventListener("abort", onAbort);
1406
+ request.signal.removeEventListener("abort", onClientAbort);
1398
1407
  });
1399
1408
  res.once("close", () => {
1400
1409
  abort.signal.removeEventListener("abort", onAbort);
1410
+ request.signal.removeEventListener("abort", onClientAbort);
1401
1411
  });
1402
1412
  try {
1403
1413
  req.on("error", (error) => {
@@ -1869,14 +1879,66 @@ import { isNever } from "@forklaunch/common";
1869
1879
  import { discriminateBody } from "@forklaunch/core/http";
1870
1880
  import Busboy from "busboy";
1871
1881
  import express from "express";
1882
+ var DEFAULT_CONTENT_TYPES = {
1883
+ json: "application/json",
1884
+ text: "text/plain",
1885
+ urlEncoded: "application/x-www-form-urlencoded",
1886
+ file: "application/octet-stream",
1887
+ multipart: "multipart/form-data"
1888
+ };
1872
1889
  function contentParse(options2) {
1873
- const jsonParser = express.json(options2?.json);
1874
- const urlencodedParser = express.urlencoded({
1875
- extended: true,
1876
- ...options2?.urlencoded
1877
- });
1878
- const textParser = express.text(options2?.text);
1879
- const rawParser = express.raw(options2?.raw);
1890
+ let resolvedOptions;
1891
+ const parserCache = /* @__PURE__ */ new Map();
1892
+ const captureRawBody = (base) => {
1893
+ const userVerify = base?.verify;
1894
+ return (req, res, buf, encoding) => {
1895
+ userVerify?.(req, res, buf, encoding);
1896
+ req._rawBody = buf;
1897
+ };
1898
+ };
1899
+ const buildParser = (parserType, contentTypeOverride) => {
1900
+ const typeOverride = contentTypeOverride ? { type: contentTypeOverride } : {};
1901
+ switch (parserType) {
1902
+ case "json":
1903
+ return express.json({
1904
+ ...resolvedOptions?.json,
1905
+ verify: captureRawBody(resolvedOptions?.json),
1906
+ ...typeOverride
1907
+ });
1908
+ case "urlEncoded":
1909
+ return express.urlencoded({
1910
+ extended: true,
1911
+ ...resolvedOptions?.urlencoded,
1912
+ verify: captureRawBody(resolvedOptions?.urlencoded),
1913
+ ...typeOverride
1914
+ });
1915
+ case "text":
1916
+ return express.text({
1917
+ ...resolvedOptions?.text,
1918
+ verify: captureRawBody(resolvedOptions?.text),
1919
+ ...typeOverride
1920
+ });
1921
+ case "file":
1922
+ return express.raw({
1923
+ ...resolvedOptions?.raw,
1924
+ verify: captureRawBody(resolvedOptions?.raw),
1925
+ ...typeOverride
1926
+ });
1927
+ default:
1928
+ isNever(parserType);
1929
+ throw new Error("Unsupported parser type: " + parserType);
1930
+ }
1931
+ };
1932
+ const parserFor = (parserType, contentType) => {
1933
+ const contentTypeOverride = contentType !== DEFAULT_CONTENT_TYPES[parserType] ? contentType : void 0;
1934
+ const cacheKey = `${parserType}:${contentTypeOverride ?? ""}`;
1935
+ let parser = parserCache.get(cacheKey);
1936
+ if (!parser) {
1937
+ parser = buildParser(parserType, contentTypeOverride);
1938
+ parserCache.set(cacheKey, parser);
1939
+ }
1940
+ return parser;
1941
+ };
1880
1942
  return async (req, res, next) => {
1881
1943
  try {
1882
1944
  const coercedRequest = req;
@@ -1893,24 +1955,39 @@ function contentParse(options2) {
1893
1955
  if (!discriminatedBody) {
1894
1956
  return next();
1895
1957
  }
1958
+ if (!resolvedOptions) {
1959
+ const globalOptions = coercedRequest._globalOptions?.();
1960
+ resolvedOptions = {
1961
+ busboy: globalOptions?.busboy ?? options2?.busboy,
1962
+ text: globalOptions?.text ?? options2?.text,
1963
+ json: globalOptions?.json ?? options2?.json,
1964
+ urlencoded: globalOptions?.urlencoded ?? options2?.urlencoded,
1965
+ raw: globalOptions?.raw ?? options2?.raw
1966
+ };
1967
+ }
1896
1968
  switch (discriminatedBody.parserType) {
1897
1969
  case "json":
1898
- return jsonParser(req, res, next);
1899
1970
  case "urlEncoded":
1900
- return urlencodedParser(req, res, next);
1901
1971
  case "text":
1902
- return textParser(req, res, next);
1972
+ return parserFor(
1973
+ discriminatedBody.parserType,
1974
+ discriminatedBody.contentType
1975
+ )(req, res, next);
1903
1976
  case "file":
1904
- return rawParser(req, res, async (err) => {
1905
- if (err) {
1906
- return next(err);
1977
+ return parserFor("file", discriminatedBody.contentType)(
1978
+ req,
1979
+ res,
1980
+ async (err) => {
1981
+ if (err) {
1982
+ return next(err);
1983
+ }
1984
+ next();
1907
1985
  }
1908
- next();
1909
- });
1986
+ );
1910
1987
  case "multipart": {
1911
1988
  const bb = Busboy({
1912
1989
  headers: req.headers,
1913
- ...options2?.busboy
1990
+ ...resolvedOptions?.busboy
1914
1991
  });
1915
1992
  const body = {};
1916
1993
  bb.on("file", (fieldname, file) => {
@@ -1 +1 @@
1
- {"version":3,"file":"bun.serve.shim.d.ts","sourceRoot":"","sources":["../../../src/cluster/bun.serve.shim.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,OAAO,EAIR,MAAM,SAAS,CAAC;AA4KjB,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE;QACJ,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,EACZ,sBAAsB,EAAE,sBAAsB,CAAC,iBAAiB,CAAC,EACjE,IAAI,GAAE,YAAiB;;;;;;;QAy0CjB,IAAI;QACJ,MAAM;QACN,OAAO;;;;;gBAQC,MAAM,YAAY,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;kBAO5C,MAAM,YAAY,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;kBAO9C,MAAM,WAAW,OAAO,EAAE;qBAIjB,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI;6BAUnB,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI;EAgBtE"}
1
+ {"version":3,"file":"bun.serve.shim.d.ts","sourceRoot":"","sources":["../../../src/cluster/bun.serve.shim.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,OAAO,EAIR,MAAM,SAAS,CAAC;AA4KjB,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE;QACJ,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,EACZ,sBAAsB,EAAE,sBAAsB,CAAC,iBAAiB,CAAC,EACjE,IAAI,GAAE,YAAiB;;;;;;;QAs1CjB,IAAI;QACJ,MAAM;QACN,OAAO;;;;;gBAQC,MAAM,YAAY,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;kBAO5C,MAAM,YAAY,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;kBAO9C,MAAM,WAAW,OAAO,EAAE;qBAIjB,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI;6BAUnB,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI;EAgBtE"}
@@ -2,12 +2,13 @@ import { AnySchemaValidator } from '@forklaunch/validator';
2
2
  import { Options, OptionsJson, OptionsText, OptionsUrlencoded } from 'body-parser';
3
3
  import { BusboyConfig } from 'busboy';
4
4
  import { NextFunction, Request, Response } from 'express';
5
- declare function contentParse<SV extends AnySchemaValidator>(options?: {
5
+ type ContentParseOptions = {
6
6
  busboy?: BusboyConfig;
7
7
  text?: OptionsText;
8
8
  json?: OptionsJson;
9
9
  urlencoded?: OptionsUrlencoded;
10
10
  raw?: Options;
11
- }): (req: Request, res: Response, next: NextFunction) => Promise<void>;
11
+ };
12
+ declare function contentParse<SV extends AnySchemaValidator>(options?: ContentParseOptions): (req: Request, res: Response, next: NextFunction) => Promise<unknown>;
12
13
  export { contentParse };
13
14
  //# sourceMappingURL=content.parse.middleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"content.parse.middleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/content.parse.middleware.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EACL,OAAO,EACP,WAAW,EACX,WAAW,EACX,iBAAiB,EAClB,MAAM,aAAa,CAAC;AACrB,OAAe,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAgB,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAMnE,iBAAS,YAAY,CAAC,EAAE,SAAS,kBAAkB,EAAE,OAAO,CAAC,EAAE;IAC7D,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,SASoB,OAAO,OAAO,QAAQ,QAAQ,YAAY,mBAoF9D;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"content.parse.middleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/content.parse.middleware.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EACL,OAAO,EACP,WAAW,EACX,WAAW,EACX,iBAAiB,EAClB,MAAM,aAAa,CAAC;AACrB,OAAe,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAgB,EAAE,YAAY,EAAE,OAAO,EAAkB,QAAQ,EAAE,MAAM,SAAS,CAAC;AAMnF,KAAK,mBAAmB,GAAG;IACzB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAuBF,iBAAS,YAAY,CAAC,EAAE,SAAS,kBAAkB,EACjD,OAAO,CAAC,EAAE,mBAAmB,SAyEV,OAAO,OAAO,QAAQ,QAAQ,YAAY,sBAqG9D;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forklaunch/express",
3
- "version": "1.2.36",
3
+ "version": "1.2.38",
4
4
  "description": "Forklaunch framework for express.",
5
5
  "homepage": "https://github.com/forklaunch/forklaunch-js#readme",
6
6
  "bugs": {
@@ -20,10 +20,7 @@
20
20
  "default": "./lib/index.js"
21
21
  },
22
22
  "./*": {
23
- "types": "./lib/*.d.ts",
24
- "import": "./lib/*.mjs",
25
- "require": "./lib/*.js",
26
- "default": "./lib/*.js"
23
+ "types": "./lib/*.d.ts"
27
24
  }
28
25
  },
29
26
  "types": "lib/index.d.ts",
@@ -43,9 +40,9 @@
43
40
  "qs": "^6.15.3",
44
41
  "range-parser": "^1.3.0",
45
42
  "swagger-ui-express": "^5.0.1",
46
- "@forklaunch/common": "^1.2.21",
47
- "@forklaunch/core": "^1.5.8",
48
- "@forklaunch/validator": "^1.2.22"
43
+ "@forklaunch/common": "^1.2.22",
44
+ "@forklaunch/core": "^1.5.11",
45
+ "@forklaunch/validator": "^1.2.23"
49
46
  },
50
47
  "devDependencies": {
51
48
  "@eslint/js": "^10.0.1",