@webpieces/http-server 0.4.878 → 0.4.880

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpieces/http-server",
3
- "version": "0.4.878",
3
+ "version": "0.4.880",
4
4
  "description": "WebPieces server with filter chain and dependency injection",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -22,10 +22,10 @@
22
22
  "access": "public"
23
23
  },
24
24
  "dependencies": {
25
- "@webpieces/core-context": "0.4.878",
26
- "@webpieces/core-util": "0.4.878",
27
- "@webpieces/gcp-identity": "0.4.878",
28
- "@webpieces/http-routing": "0.4.878",
25
+ "@webpieces/core-context": "0.4.880",
26
+ "@webpieces/core-util": "0.4.880",
27
+ "@webpieces/gcp-identity": "0.4.880",
28
+ "@webpieces/http-routing": "0.4.880",
29
29
  "cors": "2.8.5",
30
30
  "express": "5.1.0",
31
31
  "inversify": "7.10.4"
@@ -199,7 +199,8 @@ class JsonlDuplexExpressCall {
199
199
  if (line === undefined)
200
200
  break;
201
201
  if (line.charCodeAt(0) === 0x1e) {
202
- const error = new core_util_1.StreamErrorControl().decode(line);
202
+ // The SERVER is the receiver of a record its caller wrote mid-upload (#1173).
203
+ const error = new core_util_1.StreamErrorControl().decode(line, core_util_1.ClientRole.SERVER);
203
204
  await inbound.cancel(error);
204
205
  await outbound.cancel(error);
205
206
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"JsonlDuplexExpressCall.js","sourceRoot":"","sources":["../../../../../packages/http/http-server/src/JsonlDuplexExpressCall.ts"],"names":[],"mappings":";;;AAAA,6CAAmC;AAEnC,oDAU8B;AAC9B,0DAAoF;AAEpF,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnC,2FAA2F;AAC3F,MAAM,kBAAkB;IACH,QAAQ,CAAiC;IAClD,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,GAAG,KAAK,CAAC;IAErB,YAAY,GAAY;QACpB,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,EAAoC,CAAC;IAClF,CAAC;IAED,KAAK,CAAC,QAAQ;QACV,SAAS,CAAC;YACN,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACzC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;gBACf,IAAI,OAAO,GAAG,cAAc;oBACxB,MAAM,IAAI,+BAAmB,CAAC,wBAAwB,cAAc,SAAS,CAAC,CAAC;gBACnF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACnF,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;gBAClD,IAAI,IAAI,KAAK,EAAE;oBAAE,SAAS;gBAC1B,OAAO,IAAI,CAAC;YAChB,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACZ,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO,SAAS,CAAC;gBAChD,MAAM,IAAI,+BAAmB,CAAC,iCAAiC,CAAC,CAAC;YACrE,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACzC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;YAChC,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC5B,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBACpF,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;YACxD,CAAC;YACD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,cAAc,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvE,MAAM,IAAI,gCAAoB,CAAC,wBAAwB,cAAc,SAAS,CAAC,CAAC;YACpF,CAAC;QACL,CAAC;IACL,CAAC;CACJ;AAED,kFAAkF;AAClF,MAAa,mBAAmB;IASP;IACA;IACA;IAVb,MAAM,GAAG,KAAK,CAAC;IACf,KAAK,GAAG,KAAK,CAAC;IACd,YAAY,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IACvC,MAAM,GAAa,EAAE,CAAC;IAC/B,WAAW,GAAG,CAAC,CAAC;IAChB,OAAO,CAAS;IAExB,YACqB,GAAa,EACb,KAAoB,EACpB,SAA+B;QAF/B,QAAG,GAAH,GAAG,CAAU;QACb,UAAK,GAAL,KAAK,CAAe;QACpB,cAAS,GAAT,SAAS,CAAsB;QAEhD,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,GAAS,EAAE;YACzB,IAAI,CAAC,GAAG,CAAC,aAAa;gBAClB,IAAI,CAAC,OAAO,GAAG,IAAI,gCAAoB,CAAC,mCAAmC,CAAC,CAAC;QACrF,CAAC,CAAC,CAAC;IACP,CAAC;IAEQ,MAAM,GAAG;QACd,KAAK,EAAE,KAAK,EAAE,KAAe,EAAiB,EAAE;YAC5C,IAAI,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,CAAC,OAAO,CAAC;YACrC,IAAI,IAAI,CAAC,KAAK;gBACV,MAAM,IAAI,gCAAoB,CAAC,wCAAwC,CAAC,CAAC;YAC7E,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,cAAc,EAAE,CAAC;gBACvC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,cAAc,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;YACpF,CAAC;YACD,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;QACD,KAAK,EAAE,KAAK,IAAmB,EAAE;YAC7B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;YAClB,MAAM,IAAI,CAAC,YAAY,CAAC;YACxB,IAAI,IAAI,CAAC,MAAM;gBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QACpC,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,KAAa,EAAiB,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;KACrE,CAAC;IAEF,KAAK,CAAC,IAAI,CAAC,OAAiB,EAAE,OAA4B;QACtD,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,qBAAqB,EAAE,CAAC;YAC9C,IAAI,CAAC,SAAS,CAAC,QAAQ,CACnB,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,qBAAqB,EAC1C,OAAO,EACP,UAAU,CACb,CAAC;QACN,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,8CAA8C,CAAC,CAAC;QACnF,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,wBAAwB,CAAC,CAAC;QAC9D,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;QAC9C,KAAK,MAAM,KAAK,IAAI,OAAO;YAAE,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACxB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,IAAI,CAAC,YAAY,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa;QACtB,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,KAAK,IAAI,IAAI,gCAAoB,CAAC,4BAA4B,CAAC,CAAC;YAC/E,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/B,OAAO;QACX,CAAC;QACD,iJAAiJ;QACjJ,IAAI,CAAC;YACD,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,8BAAkB,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3D,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YACrB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;YAClB,IAAI,IAAI,CAAC,MAAM;gBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QACpC,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,IAAA,mBAAO,EAAC,GAAG,CAAC,CAAC;YAC3B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YACrB,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,OAAiB;QACxC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACjD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QACvB,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,MAAc;QAChC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAC9C,IAAI,IAAI,CAAC,WAAW,GAAG,EAAE,GAAG,IAAI;gBAC5B,MAAM,IAAI,gCAAoB,CAC1B,oDAAoD,CACvD,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzB,OAAO;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAkB,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QACjF,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAS,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1D,MAAM,QAAQ,CAAC;IACnB,CAAC;IAEO,KAAK,CAAC,KAAK,CAAC,MAAc;QAC9B,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YAC/C,MAAM,IAAI,gCAAoB,CAAC,mDAAmD,CAAC,CAAC;QACxF,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;YAAE,OAAO;QACnC,MAAM,OAAO,CAAC,IAAI,CAAC;YACf,IAAA,kBAAI,EAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC;YACvB,IAAA,kBAAI,EAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAU,EAAE;gBACrC,MAAM,IAAI,gCAAoB,CAAC,gDAAgD,CAAC,CAAC;YACrF,CAAC,CAAC;SACL,CAAC,CAAC;IACP,CAAC;CACJ;AA9GD,kDA8GC;AAED,2EAA2E;AAC3E,MAAa,sBAAsB;IAKV;IACA;IACA;IANJ,SAAS,GAAG,IAAI,gCAAoB,EAAE,CAAC;IAExD;IACI,wFAAwF;IACvE,YAAsD,EACtD,KAAoB,EACpB,OAA8B;QAF9B,iBAAY,GAAZ,YAAY,CAA0C;QACtD,UAAK,GAAL,KAAK,CAAe;QACpB,YAAO,GAAP,OAAO,CAAuB;IAChD,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,GAAY,EAAE,GAAa;QACrC,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,MAAM,CAAC,QAAQ,EAAE,EAAE,iBAAiB,CAAC,CAAC;QAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,SAAU,CAAC;QACvC,IAAI,QAAQ,CAAC,oBAAoB,EAAE,CAAC;YAChC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,oBAAoB,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QAC/E,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1E,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,eAAe,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;QACrD,MAAM,MAAM,GAAG,IAAI,iCAAkB,EAAE,CAAC;QACxC,MAAM,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;QAC1E,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,MAAM,MAAM,GAAG,KAAK,IAAmB,EAAE;YACrC,IAAI,SAAS;gBAAE,OAAO;YACtB,SAAS,GAAG,IAAI,CAAC;YACjB,MAAM,KAAK,GAAG,IAAI,gCAAoB,CAAC,mCAAmC,CAAC,CAAC;YAC5E,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC,CAAC;QACF,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,GAAS,EAAE,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC;QAC/C,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,GAAS,EAAE;YACzB,IAAI,CAAC,GAAG,CAAC,aAAa;gBAAE,KAAK,MAAM,EAAE,CAAC;QAC1C,CAAC,CAAC,CAAC;QACH,yHAAyH;QACzH,IAAI,CAAC;YACD,SAAS,CAAC;gBACN,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACrC,IAAI,IAAI,KAAK,SAAS;oBAAE,MAAM;gBAC9B,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;oBAC9B,MAAM,KAAK,GAAG,IAAI,8BAAkB,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;oBACpD,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBAC5B,MAAM,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBAC7B,OAAO;gBACX,CAAC;gBACD,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;gBACpD,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;oBACzB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,aAAa,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;gBACtE,CAAC;gBACD,MAAM,MAAM,CAAC,GAAG,CAAC,GAAkB,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;YAChE,CAAC;YACD,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YACtB,IAAI,QAAQ,CAAC,SAAS,KAAK,2BAAe,CAAC,OAAO;gBAAE,MAAM,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACtF,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,IAAA,mBAAO,EAAC,GAAG,CAAC,CAAC;YAC3B,MAAM,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC7B,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;IACL,CAAC;IAED,6GAA6G;IACrG,KAAK,CAAC,MAAM,CAAC,OAAiB,EAAE,QAA6B;QACjE,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,SAAS,KAAK,2BAAe,CAAC,IAAI,EAAE,CAAC;YAC3D,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,oFAAoF;IAC5E,aAAa,CAAC,KAAc;QAChC,IACI,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,KAAK,IAAI;YACd,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,oBAAoB,CAAC,KAAK,UAAU;YAC9D,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,UAAU;YACjD,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,UAAU;YACjD,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,UAAU,EACpD,CAAC;YACC,MAAM,IAAI,gCAAoB,CAAC,sDAAsD,CAAC,CAAC;QAC3F,CAAC;QACD,OAAO,KAA0C,CAAC;IACtD,CAAC;IAEO,SAAS,CAAC,IAAwB,EAAE,KAAa;QACrD,IAAI,IAAI,KAAK,SAAS;YAAE,MAAM,IAAI,gCAAoB,CAAC,WAAW,KAAK,gBAAgB,CAAC,CAAC;QACzF,4GAA4G;QAC5G,IAAI,CAAC;YACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAa,CAAC;QACxC,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,IAAA,mBAAO,EAAC,GAAG,CAAC,CAAC;YAC3B,MAAM,IAAI,gCAAoB,CAC1B,aAAa,KAAK,gBAAgB,EAClC,SAAS,EACT,SAAS,EACT,KAAK,CACR,CAAC;QACN,CAAC;IACL,CAAC;CACJ;AAlGD,wDAkGC","sourcesContent":["import { once } from 'node:events';\nimport { Request, Response } from 'express';\nimport {\n StreamErrorControl,\n DtoValue,\n RequestStream,\n RouteMetadata,\n StreamDirection,\n StreamEventValidator,\n StreamTransportError,\n StreamProtocolError,\n toError,\n} from '@webpieces/core-util';\nimport { RequestContextHeaders, StreamEventContext } from '@webpieces/core-context';\n\nconst MAX_LINE_BYTES = 1024 * 1024;\n\n/** Stateful line reader that preserves bytes received after the initial request record. */\nclass JsonlRequestReader {\n private readonly iterator: AsyncIterator<Buffer | string>;\n private pending = Buffer.alloc(0);\n private done = false;\n\n constructor(req: Request) {\n this.iterator = req[Symbol.asyncIterator]() as AsyncIterator<Buffer | string>;\n }\n\n async nextLine(): Promise<string | undefined> {\n for (;;) {\n const newline = this.pending.indexOf(10);\n if (newline >= 0) {\n if (newline > MAX_LINE_BYTES)\n throw new StreamProtocolError(`JSONL record exceeds ${MAX_LINE_BYTES} bytes.`);\n const line = this.pending.subarray(0, newline).toString('utf8').replace(/\\r$/, '');\n this.pending = this.pending.subarray(newline + 1);\n if (line === '') continue;\n return line;\n }\n if (this.done) {\n if (this.pending.length === 0) return undefined;\n throw new StreamProtocolError('JSONL request ended mid-record.');\n }\n const chunk = await this.iterator.next();\n this.done = chunk.done === true;\n if (chunk.value !== undefined) {\n const bytes = Buffer.isBuffer(chunk.value) ? chunk.value : Buffer.from(chunk.value);\n this.pending = Buffer.concat([this.pending, bytes]);\n }\n if (this.pending.length > MAX_LINE_BYTES && this.pending.indexOf(10) < 0) {\n throw new StreamTransportError(`JSONL record exceeds ${MAX_LINE_BYTES} bytes.`);\n }\n }\n }\n}\n\n/** Ordered raw-JSONL response writer with an atomic initial-response boundary. */\nexport class JsonlResponseWriter {\n private opened = false;\n private ended = false;\n private pendingWrite: Promise<void> = Promise.resolve();\n private readonly queued: string[] = [];\n private queuedBytes = 0;\n private failure?: Error;\n\n constructor(\n private readonly res: Response,\n private readonly route: RouteMetadata,\n private readonly validator: StreamEventValidator,\n ) {\n res.once('close', (): void => {\n if (!res.writableEnded)\n this.failure = new StreamTransportError('Streaming HTTP peer disconnected.');\n });\n }\n\n readonly stream = {\n event: async (value: DtoValue): Promise<void> => {\n if (this.failure) throw this.failure;\n if (this.ended)\n throw new StreamTransportError('Cannot write after stream termination.');\n if (this.route.streaming?.responseSchema) {\n this.validator.validate(this.route.streaming.responseSchema, value, 'response');\n }\n await this.deliver(`${JSON.stringify(value)}\\n`);\n },\n close: async (): Promise<void> => {\n this.ended = true;\n await this.pendingWrite;\n if (this.opened) this.res.end();\n },\n cancel: async (error?: Error): Promise<void> => this.cancel(error),\n };\n\n async open(initial: DtoValue, headers: Map<string, string>): Promise<void> {\n if (this.route.streaming?.initialResponseSchema) {\n this.validator.validate(\n this.route.streaming.initialResponseSchema,\n initial,\n 'response',\n );\n }\n this.res.status(200);\n this.res.setHeader('Content-Type', 'application/x-webpieces-jsonl; charset=utf-8');\n this.res.setHeader('Cache-Control', 'no-cache, no-transform');\n this.res.setHeader('X-Accel-Buffering', 'no');\n for (const entry of headers) this.res.setHeader(entry[0], entry[1]);\n this.res.flushHeaders();\n this.opened = true;\n this.pendingWrite = this.flushOpening(initial);\n await this.pendingWrite;\n }\n\n async cancel(error?: Error): Promise<void> {\n if (this.failure) return;\n if (!error || this.ended) {\n this.failure = error ?? new StreamTransportError('Local stream cancellation.');\n this.res.destroy(this.failure);\n return;\n }\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- a failed error-control write must reset rather than send an invented remote DTO\n try {\n await this.deliver(new StreamErrorControl().encode(error));\n this.failure = error;\n this.ended = true;\n if (this.opened) this.res.end();\n } catch (err: unknown) {\n const error = toError(err);\n this.failure = error;\n this.res.destroy(error);\n }\n }\n\n private async flushOpening(initial: DtoValue): Promise<void> {\n await this.write(`${JSON.stringify(initial)}\\n`);\n for (const record of this.queued) await this.write(record);\n this.queued.length = 0;\n if (this.ended) this.res.end();\n }\n\n private async deliver(record: string): Promise<void> {\n if (!this.opened) {\n this.queuedBytes += Buffer.byteLength(record);\n if (this.queuedBytes > 64 * 1024)\n throw new StreamTransportError(\n 'Pre-handshake response buffer exceeds 65536 bytes.',\n );\n this.queued.push(record);\n return;\n }\n const delivery = this.pendingWrite.then((): Promise<void> => this.write(record));\n this.pendingWrite = delivery.catch((): void => undefined);\n await delivery;\n }\n\n private async write(record: string): Promise<void> {\n if (this.res.destroyed || this.res.writableEnded) {\n throw new StreamTransportError('Cannot write to a closed streaming HTTP response.');\n }\n if (this.res.write(record)) return;\n await Promise.race([\n once(this.res, 'drain'),\n once(this.res, 'close').then((): never => {\n throw new StreamTransportError('Streaming HTTP peer disconnected during write.');\n }),\n ]);\n }\n}\n\n/** Handles Node-only REQUEST/FULL application/x-webpieces-jsonl routes. */\nexport class JsonlDuplexExpressCall {\n private readonly validator = new StreamEventValidator();\n\n constructor(\n // webpieces-disable no-any-unknown -- controller boundary has contract-erased DTO types\n private readonly clientMethod: (...args: unknown[]) => Promise<unknown>,\n private readonly route: RouteMetadata,\n private readonly headers: RequestContextHeaders,\n ) {}\n\n async execute(req: Request, res: Response): Promise<void> {\n const reader = new JsonlRequestReader(req);\n const initial = this.parseData(await reader.nextLine(), 'initial request');\n const metadata = this.route.streaming!;\n if (metadata.initialRequestSchema) {\n this.validator.validate(metadata.initialRequestSchema, initial, 'request');\n }\n const outbound = new JsonlResponseWriter(res, this.route, this.validator);\n const returned = await this.invoke(initial, outbound);\n const inbound = this.requestStream(returned);\n const initialResponse = inbound.getInitialResponse();\n const events = new StreamEventContext();\n await outbound.open(initialResponse, this.headers.buildResponseHeaders());\n let cancelled = false;\n const cancel = async (): Promise<void> => {\n if (cancelled) return;\n cancelled = true;\n const error = new StreamTransportError('Streaming HTTP peer disconnected.');\n await inbound.cancel(error);\n };\n req.once('aborted', (): void => void cancel());\n res.once('close', (): void => {\n if (!res.writableEnded) void cancel();\n });\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- post-open failures must be written as sideband controls\n try {\n for (;;) {\n const line = await reader.nextLine();\n if (line === undefined) break;\n if (line.charCodeAt(0) === 0x1e) {\n const error = new StreamErrorControl().decode(line);\n await inbound.cancel(error);\n await outbound.cancel(error);\n return;\n }\n const value = this.parseData(line, 'request event');\n if (metadata.requestSchema) {\n this.validator.validate(metadata.requestSchema, value, 'request');\n }\n await events.run((): Promise<void> => inbound.event(value));\n }\n await inbound.close();\n if (metadata.direction === StreamDirection.REQUEST) await outbound.stream.close();\n } catch (err: unknown) {\n const error = toError(err);\n await outbound.cancel(error);\n await inbound.cancel(error);\n }\n }\n\n // webpieces-disable no-any-unknown -- controller return is validated as a typed RequestStream before opening\n private async invoke(initial: DtoValue, outbound: JsonlResponseWriter): Promise<unknown> {\n if (this.route.streaming?.direction === StreamDirection.FULL) {\n return this.clientMethod(initial, outbound.stream);\n }\n return this.clientMethod(initial);\n }\n\n // webpieces-disable no-any-unknown -- runtime guard narrows controller return value\n private requestStream(value: unknown): RequestStream<DtoValue, DtoValue> {\n if (\n typeof value !== 'object' ||\n value === null ||\n typeof Reflect.get(value, 'getInitialResponse') !== 'function' ||\n typeof Reflect.get(value, 'event') !== 'function' ||\n typeof Reflect.get(value, 'close') !== 'function' ||\n typeof Reflect.get(value, 'cancel') !== 'function'\n ) {\n throw new StreamTransportError('Streaming controller did not return a RequestStream.');\n }\n return value as RequestStream<DtoValue, DtoValue>;\n }\n\n private parseData(line: string | undefined, label: string): DtoValue {\n if (line === undefined) throw new StreamTransportError(`Missing ${label} JSONL record.`);\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- JSON.parse is the untrusted JSONL boundary\n try {\n return JSON.parse(line) as DtoValue;\n } catch (err: unknown) {\n const error = toError(err);\n throw new StreamTransportError(\n `Malformed ${label} JSONL record.`,\n undefined,\n undefined,\n error,\n );\n }\n }\n}\n"]}
1
+ {"version":3,"file":"JsonlDuplexExpressCall.js","sourceRoot":"","sources":["../../../../../packages/http/http-server/src/JsonlDuplexExpressCall.ts"],"names":[],"mappings":"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","sourcesContent":["import { once } from 'node:events';\nimport { Request, Response } from 'express';\nimport {\n ClientRole,\n StreamErrorControl,\n DtoValue,\n RequestStream,\n RouteMetadata,\n StreamDirection,\n StreamEventValidator,\n StreamTransportError,\n StreamProtocolError,\n toError,\n} from '@webpieces/core-util';\nimport { RequestContextHeaders, StreamEventContext } from '@webpieces/core-context';\n\nconst MAX_LINE_BYTES = 1024 * 1024;\n\n/** Stateful line reader that preserves bytes received after the initial request record. */\nclass JsonlRequestReader {\n private readonly iterator: AsyncIterator<Buffer | string>;\n private pending = Buffer.alloc(0);\n private done = false;\n\n constructor(req: Request) {\n this.iterator = req[Symbol.asyncIterator]() as AsyncIterator<Buffer | string>;\n }\n\n async nextLine(): Promise<string | undefined> {\n for (;;) {\n const newline = this.pending.indexOf(10);\n if (newline >= 0) {\n if (newline > MAX_LINE_BYTES)\n throw new StreamProtocolError(`JSONL record exceeds ${MAX_LINE_BYTES} bytes.`);\n const line = this.pending.subarray(0, newline).toString('utf8').replace(/\\r$/, '');\n this.pending = this.pending.subarray(newline + 1);\n if (line === '') continue;\n return line;\n }\n if (this.done) {\n if (this.pending.length === 0) return undefined;\n throw new StreamProtocolError('JSONL request ended mid-record.');\n }\n const chunk = await this.iterator.next();\n this.done = chunk.done === true;\n if (chunk.value !== undefined) {\n const bytes = Buffer.isBuffer(chunk.value) ? chunk.value : Buffer.from(chunk.value);\n this.pending = Buffer.concat([this.pending, bytes]);\n }\n if (this.pending.length > MAX_LINE_BYTES && this.pending.indexOf(10) < 0) {\n throw new StreamTransportError(`JSONL record exceeds ${MAX_LINE_BYTES} bytes.`);\n }\n }\n }\n}\n\n/** Ordered raw-JSONL response writer with an atomic initial-response boundary. */\nexport class JsonlResponseWriter {\n private opened = false;\n private ended = false;\n private pendingWrite: Promise<void> = Promise.resolve();\n private readonly queued: string[] = [];\n private queuedBytes = 0;\n private failure?: Error;\n\n constructor(\n private readonly res: Response,\n private readonly route: RouteMetadata,\n private readonly validator: StreamEventValidator,\n ) {\n res.once('close', (): void => {\n if (!res.writableEnded)\n this.failure = new StreamTransportError('Streaming HTTP peer disconnected.');\n });\n }\n\n readonly stream = {\n event: async (value: DtoValue): Promise<void> => {\n if (this.failure) throw this.failure;\n if (this.ended)\n throw new StreamTransportError('Cannot write after stream termination.');\n if (this.route.streaming?.responseSchema) {\n this.validator.validate(this.route.streaming.responseSchema, value, 'response');\n }\n await this.deliver(`${JSON.stringify(value)}\\n`);\n },\n close: async (): Promise<void> => {\n this.ended = true;\n await this.pendingWrite;\n if (this.opened) this.res.end();\n },\n cancel: async (error?: Error): Promise<void> => this.cancel(error),\n };\n\n async open(initial: DtoValue, headers: Map<string, string>): Promise<void> {\n if (this.route.streaming?.initialResponseSchema) {\n this.validator.validate(\n this.route.streaming.initialResponseSchema,\n initial,\n 'response',\n );\n }\n this.res.status(200);\n this.res.setHeader('Content-Type', 'application/x-webpieces-jsonl; charset=utf-8');\n this.res.setHeader('Cache-Control', 'no-cache, no-transform');\n this.res.setHeader('X-Accel-Buffering', 'no');\n for (const entry of headers) this.res.setHeader(entry[0], entry[1]);\n this.res.flushHeaders();\n this.opened = true;\n this.pendingWrite = this.flushOpening(initial);\n await this.pendingWrite;\n }\n\n async cancel(error?: Error): Promise<void> {\n if (this.failure) return;\n if (!error || this.ended) {\n this.failure = error ?? new StreamTransportError('Local stream cancellation.');\n this.res.destroy(this.failure);\n return;\n }\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- a failed error-control write must reset rather than send an invented remote DTO\n try {\n await this.deliver(new StreamErrorControl().encode(error));\n this.failure = error;\n this.ended = true;\n if (this.opened) this.res.end();\n } catch (err: unknown) {\n const error = toError(err);\n this.failure = error;\n this.res.destroy(error);\n }\n }\n\n private async flushOpening(initial: DtoValue): Promise<void> {\n await this.write(`${JSON.stringify(initial)}\\n`);\n for (const record of this.queued) await this.write(record);\n this.queued.length = 0;\n if (this.ended) this.res.end();\n }\n\n private async deliver(record: string): Promise<void> {\n if (!this.opened) {\n this.queuedBytes += Buffer.byteLength(record);\n if (this.queuedBytes > 64 * 1024)\n throw new StreamTransportError(\n 'Pre-handshake response buffer exceeds 65536 bytes.',\n );\n this.queued.push(record);\n return;\n }\n const delivery = this.pendingWrite.then((): Promise<void> => this.write(record));\n this.pendingWrite = delivery.catch((): void => undefined);\n await delivery;\n }\n\n private async write(record: string): Promise<void> {\n if (this.res.destroyed || this.res.writableEnded) {\n throw new StreamTransportError('Cannot write to a closed streaming HTTP response.');\n }\n if (this.res.write(record)) return;\n await Promise.race([\n once(this.res, 'drain'),\n once(this.res, 'close').then((): never => {\n throw new StreamTransportError('Streaming HTTP peer disconnected during write.');\n }),\n ]);\n }\n}\n\n/** Handles Node-only REQUEST/FULL application/x-webpieces-jsonl routes. */\nexport class JsonlDuplexExpressCall {\n private readonly validator = new StreamEventValidator();\n\n constructor(\n // webpieces-disable no-any-unknown -- controller boundary has contract-erased DTO types\n private readonly clientMethod: (...args: unknown[]) => Promise<unknown>,\n private readonly route: RouteMetadata,\n private readonly headers: RequestContextHeaders,\n ) {}\n\n async execute(req: Request, res: Response): Promise<void> {\n const reader = new JsonlRequestReader(req);\n const initial = this.parseData(await reader.nextLine(), 'initial request');\n const metadata = this.route.streaming!;\n if (metadata.initialRequestSchema) {\n this.validator.validate(metadata.initialRequestSchema, initial, 'request');\n }\n const outbound = new JsonlResponseWriter(res, this.route, this.validator);\n const returned = await this.invoke(initial, outbound);\n const inbound = this.requestStream(returned);\n const initialResponse = inbound.getInitialResponse();\n const events = new StreamEventContext();\n await outbound.open(initialResponse, this.headers.buildResponseHeaders());\n let cancelled = false;\n const cancel = async (): Promise<void> => {\n if (cancelled) return;\n cancelled = true;\n const error = new StreamTransportError('Streaming HTTP peer disconnected.');\n await inbound.cancel(error);\n };\n req.once('aborted', (): void => void cancel());\n res.once('close', (): void => {\n if (!res.writableEnded) void cancel();\n });\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- post-open failures must be written as sideband controls\n try {\n for (;;) {\n const line = await reader.nextLine();\n if (line === undefined) break;\n if (line.charCodeAt(0) === 0x1e) {\n // The SERVER is the receiver of a record its caller wrote mid-upload (#1173).\n const error = new StreamErrorControl().decode(line, ClientRole.SERVER);\n await inbound.cancel(error);\n await outbound.cancel(error);\n return;\n }\n const value = this.parseData(line, 'request event');\n if (metadata.requestSchema) {\n this.validator.validate(metadata.requestSchema, value, 'request');\n }\n await events.run((): Promise<void> => inbound.event(value));\n }\n await inbound.close();\n if (metadata.direction === StreamDirection.REQUEST) await outbound.stream.close();\n } catch (err: unknown) {\n const error = toError(err);\n await outbound.cancel(error);\n await inbound.cancel(error);\n }\n }\n\n // webpieces-disable no-any-unknown -- controller return is validated as a typed RequestStream before opening\n private async invoke(initial: DtoValue, outbound: JsonlResponseWriter): Promise<unknown> {\n if (this.route.streaming?.direction === StreamDirection.FULL) {\n return this.clientMethod(initial, outbound.stream);\n }\n return this.clientMethod(initial);\n }\n\n // webpieces-disable no-any-unknown -- runtime guard narrows controller return value\n private requestStream(value: unknown): RequestStream<DtoValue, DtoValue> {\n if (\n typeof value !== 'object' ||\n value === null ||\n typeof Reflect.get(value, 'getInitialResponse') !== 'function' ||\n typeof Reflect.get(value, 'event') !== 'function' ||\n typeof Reflect.get(value, 'close') !== 'function' ||\n typeof Reflect.get(value, 'cancel') !== 'function'\n ) {\n throw new StreamTransportError('Streaming controller did not return a RequestStream.');\n }\n return value as RequestStream<DtoValue, DtoValue>;\n }\n\n private parseData(line: string | undefined, label: string): DtoValue {\n if (line === undefined) throw new StreamTransportError(`Missing ${label} JSONL record.`);\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- JSON.parse is the untrusted JSONL boundary\n try {\n return JSON.parse(line) as DtoValue;\n } catch (err: unknown) {\n const error = toError(err);\n throw new StreamTransportError(\n `Malformed ${label} JSONL record.`,\n undefined,\n undefined,\n error,\n );\n }\n }\n}\n"]}