@event-driven-io/emmett-expressjs 0.5.4 → 0.6.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.
Files changed (53) hide show
  1. package/dist/application.js +1 -1
  2. package/dist/application.mjs +1 -1
  3. package/dist/{chunk-YC2DBBXW.js → chunk-2JWQPLZI.js} +2 -2
  4. package/dist/{chunk-P7AA2K4Q.js → chunk-5SQK7LQ2.js} +2 -2
  5. package/dist/{chunk-BPMP6GJ7.mjs → chunk-BHGAXF2A.mjs} +2 -2
  6. package/dist/chunk-DA5J4ET5.js +5 -0
  7. package/dist/chunk-DA5J4ET5.js.map +1 -0
  8. package/dist/{chunk-UT7Q27E5.js → chunk-DLZ3WQUJ.js} +2 -2
  9. package/dist/chunk-DLZ3WQUJ.js.map +1 -0
  10. package/dist/{chunk-TJPUQYKV.mjs → chunk-IMSJF3JS.mjs} +2 -2
  11. package/dist/chunk-KIRBEYFF.mjs +5 -0
  12. package/dist/chunk-KIRBEYFF.mjs.map +1 -0
  13. package/dist/{chunk-Y7SZXFJ2.js → chunk-MEK5AIAJ.js} +2 -2
  14. package/dist/chunk-OAYYW4GF.mjs +2 -0
  15. package/dist/{chunk-3P6L3RAK.mjs.map → chunk-OAYYW4GF.mjs.map} +1 -1
  16. package/dist/{chunk-6MY6WCJR.mjs → chunk-TP4BTDFZ.mjs} +2 -2
  17. package/dist/e2e/decider/api.d.mts +4 -19
  18. package/dist/e2e/decider/api.d.ts +4 -19
  19. package/dist/e2e/decider/api.js +1 -1
  20. package/dist/e2e/decider/api.mjs +1 -1
  21. package/dist/e2e/decider/businessLogic.js +1 -1
  22. package/dist/e2e/decider/businessLogic.mjs +1 -1
  23. package/dist/e2e/decider/shoppingCart.js +1 -1
  24. package/dist/e2e/decider/shoppingCart.mjs +1 -1
  25. package/dist/e2e/testing.js +1 -1
  26. package/dist/e2e/testing.mjs +1 -1
  27. package/dist/etag.js +1 -1
  28. package/dist/etag.mjs +1 -1
  29. package/dist/handler.js +1 -1
  30. package/dist/handler.mjs +1 -1
  31. package/dist/index.js +1 -1
  32. package/dist/index.mjs +1 -1
  33. package/dist/middlewares/problemDetailsMiddleware.js +1 -1
  34. package/dist/middlewares/problemDetailsMiddleware.mjs +1 -1
  35. package/dist/responses.js +1 -1
  36. package/dist/responses.mjs +1 -1
  37. package/dist/testing/apiSpecification.js +1 -1
  38. package/dist/testing/apiSpecification.mjs +1 -1
  39. package/dist/testing/index.js +1 -1
  40. package/dist/testing/index.mjs +1 -1
  41. package/package.json +4 -3
  42. package/dist/chunk-3P6L3RAK.mjs +0 -2
  43. package/dist/chunk-HEPNAXF4.mjs +0 -5
  44. package/dist/chunk-HEPNAXF4.mjs.map +0 -1
  45. package/dist/chunk-UT7Q27E5.js.map +0 -1
  46. package/dist/chunk-ZWOSOI7Z.js +0 -5
  47. package/dist/chunk-ZWOSOI7Z.js.map +0 -1
  48. /package/dist/{chunk-YC2DBBXW.js.map → chunk-2JWQPLZI.js.map} +0 -0
  49. /package/dist/{chunk-P7AA2K4Q.js.map → chunk-5SQK7LQ2.js.map} +0 -0
  50. /package/dist/{chunk-BPMP6GJ7.mjs.map → chunk-BHGAXF2A.mjs.map} +0 -0
  51. /package/dist/{chunk-TJPUQYKV.mjs.map → chunk-IMSJF3JS.mjs.map} +0 -0
  52. /package/dist/{chunk-Y7SZXFJ2.js.map → chunk-MEK5AIAJ.js.map} +0 -0
  53. /package/dist/{chunk-6MY6WCJR.mjs.map → chunk-TP4BTDFZ.mjs.map} +0 -0
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkUT7Q27E5js = require('./chunk-UT7Q27E5.js');require('./chunk-7H3QW2YD.js');require('./chunk-VK264KTU.js');require('./chunk-Y7SZXFJ2.js');require('./chunk-KVWDIWFZ.js');require('./chunk-NDXUB3PP.js');require('./chunk-E4DZPUJH.js');require('./chunk-ZWOSOI7Z.js');exports.getApplication = _chunkUT7Q27E5js.o; exports.startAPI = _chunkUT7Q27E5js.p;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkDLZ3WQUJjs = require('./chunk-DLZ3WQUJ.js');require('./chunk-7H3QW2YD.js');require('./chunk-VK264KTU.js');require('./chunk-MEK5AIAJ.js');require('./chunk-KVWDIWFZ.js');require('./chunk-NDXUB3PP.js');require('./chunk-E4DZPUJH.js');require('./chunk-DA5J4ET5.js');exports.getApplication = _chunkDLZ3WQUJjs.o; exports.startAPI = _chunkDLZ3WQUJjs.p;
2
2
  //# sourceMappingURL=application.js.map
@@ -1,2 +1,2 @@
1
- import{o as a,p as b}from"./chunk-3P6L3RAK.mjs";import"./chunk-HKEQAT6F.mjs";import"./chunk-2IUXL747.mjs";import"./chunk-TJPUQYKV.mjs";import"./chunk-42BDHECF.mjs";import"./chunk-3ECNKSAE.mjs";import"./chunk-GEU24YU2.mjs";import"./chunk-HEPNAXF4.mjs";export{a as getApplication,b as startAPI};
1
+ import{o as a,p as b}from"./chunk-OAYYW4GF.mjs";import"./chunk-HKEQAT6F.mjs";import"./chunk-2IUXL747.mjs";import"./chunk-IMSJF3JS.mjs";import"./chunk-42BDHECF.mjs";import"./chunk-3ECNKSAE.mjs";import"./chunk-GEU24YU2.mjs";import"./chunk-KIRBEYFF.mjs";export{a as getApplication,b as startAPI};
2
2
  //# sourceMappingURL=application.mjs.map
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _chunkP7AA2K4Qjs = require('./chunk-P7AA2K4Q.js');var _chunkZWOSOI7Zjs = require('./chunk-ZWOSOI7Z.js');var S=(p=>(p.CART_ALREADY_EXISTS="CART_ALREADY_EXISTS",p.CART_IS_ALREADY_CLOSED="CART_IS_ALREADY_CLOSED",p.PRODUCT_ITEM_NOT_FOUND="PRODUCT_ITEM_NOT_FOUND",p.CART_IS_EMPTY="CART_IS_EMPTY",p.UNKNOWN_EVENT_TYPE="UNKNOWN_EVENT_TYPE",p.UNKNOWN_COMMAND_TYPE="UNKNOWN_COMMAND_TYPE",p))(S||{}),I= exports.b =(o,{productId:t,quantity:r,unitPrice:n})=>{if((_nullishCoalesce(_optionalChain([o, 'access', _ => _.find, 'call', _2 => _2(i=>i.productId===t&&i.unitPrice==n), 'optionalAccess', _3 => _3.quantity]), () => (0)))<r)throw new (0, _chunkZWOSOI7Zjs.d)("PRODUCT_ITEM_NOT_FOUND")},g= exports.c =({type:o,data:t},r)=>{switch(o){case"OpenShoppingCart":{if(r.status!=="Empty")throw new (0, _chunkZWOSOI7Zjs.d)("CART_ALREADY_EXISTS");return{type:"ShoppingCartOpened",data:{shoppingCartId:t.shoppingCartId,clientId:t.clientId,openedAt:t.now}}}case"AddProductItemToShoppingCart":{if(r.status!=="Pending")throw new (0, _chunkZWOSOI7Zjs.d)("CART_IS_ALREADY_CLOSED");return{type:"ProductItemAddedToShoppingCart",data:{shoppingCartId:t.shoppingCartId,productItem:t.productItem}}}case"RemoveProductItemFromShoppingCart":{if(r.status!=="Pending")throw new (0, _chunkZWOSOI7Zjs.d)("CART_IS_ALREADY_CLOSED");return I(r.productItems,t.productItem),{type:"ProductItemRemovedFromShoppingCart",data:{shoppingCartId:t.shoppingCartId,productItem:t.productItem}}}case"ConfirmShoppingCart":{if(r.status!=="Pending")throw new (0, _chunkZWOSOI7Zjs.d)("CART_IS_ALREADY_CLOSED");if(r.productItems.length===0)throw new (0, _chunkZWOSOI7Zjs.d)("CART_IS_EMPTY");return{type:"ShoppingCartConfirmed",data:{shoppingCartId:t.shoppingCartId,confirmedAt:t.now}}}case"CancelShoppingCart":{if(r.status!=="Pending")throw new (0, _chunkZWOSOI7Zjs.d)("CART_IS_ALREADY_CLOSED");return{type:"ShoppingCartCanceled",data:{shoppingCartId:t.shoppingCartId,canceledAt:t.now}}}default:{let n=t;throw new (0, _chunkZWOSOI7Zjs.c)("UNKNOWN_COMMAND_TYPE")}}},u= exports.d ={decide:g,evolve:_chunkP7AA2K4Qjs.c,getInitialState:()=>_chunkP7AA2K4Qjs.b};exports.a = S; exports.b = I; exports.c = g; exports.d = u;
2
- //# sourceMappingURL=chunk-YC2DBBXW.js.map
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _chunk5SQK7LQ2js = require('./chunk-5SQK7LQ2.js');var _chunkDA5J4ET5js = require('./chunk-DA5J4ET5.js');var S=(p=>(p.CART_ALREADY_EXISTS="CART_ALREADY_EXISTS",p.CART_IS_ALREADY_CLOSED="CART_IS_ALREADY_CLOSED",p.PRODUCT_ITEM_NOT_FOUND="PRODUCT_ITEM_NOT_FOUND",p.CART_IS_EMPTY="CART_IS_EMPTY",p.UNKNOWN_EVENT_TYPE="UNKNOWN_EVENT_TYPE",p.UNKNOWN_COMMAND_TYPE="UNKNOWN_COMMAND_TYPE",p))(S||{}),I= exports.b =(o,{productId:t,quantity:r,unitPrice:n})=>{if((_nullishCoalesce(_optionalChain([o, 'access', _ => _.find, 'call', _2 => _2(i=>i.productId===t&&i.unitPrice==n), 'optionalAccess', _3 => _3.quantity]), () => (0)))<r)throw new (0, _chunkDA5J4ET5js.d)("PRODUCT_ITEM_NOT_FOUND")},g= exports.c =({type:o,data:t},r)=>{switch(o){case"OpenShoppingCart":{if(r.status!=="Empty")throw new (0, _chunkDA5J4ET5js.d)("CART_ALREADY_EXISTS");return{type:"ShoppingCartOpened",data:{shoppingCartId:t.shoppingCartId,clientId:t.clientId,openedAt:t.now}}}case"AddProductItemToShoppingCart":{if(r.status!=="Pending")throw new (0, _chunkDA5J4ET5js.d)("CART_IS_ALREADY_CLOSED");return{type:"ProductItemAddedToShoppingCart",data:{shoppingCartId:t.shoppingCartId,productItem:t.productItem}}}case"RemoveProductItemFromShoppingCart":{if(r.status!=="Pending")throw new (0, _chunkDA5J4ET5js.d)("CART_IS_ALREADY_CLOSED");return I(r.productItems,t.productItem),{type:"ProductItemRemovedFromShoppingCart",data:{shoppingCartId:t.shoppingCartId,productItem:t.productItem}}}case"ConfirmShoppingCart":{if(r.status!=="Pending")throw new (0, _chunkDA5J4ET5js.d)("CART_IS_ALREADY_CLOSED");if(r.productItems.length===0)throw new (0, _chunkDA5J4ET5js.d)("CART_IS_EMPTY");return{type:"ShoppingCartConfirmed",data:{shoppingCartId:t.shoppingCartId,confirmedAt:t.now}}}case"CancelShoppingCart":{if(r.status!=="Pending")throw new (0, _chunkDA5J4ET5js.d)("CART_IS_ALREADY_CLOSED");return{type:"ShoppingCartCanceled",data:{shoppingCartId:t.shoppingCartId,canceledAt:t.now}}}default:{let n=t;throw new (0, _chunkDA5J4ET5js.c)("UNKNOWN_COMMAND_TYPE")}}},u= exports.d ={decide:g,evolve:_chunk5SQK7LQ2js.c,getInitialState:()=>_chunk5SQK7LQ2js.b};exports.a = S; exports.b = I; exports.c = g; exports.d = u;
2
+ //# sourceMappingURL=chunk-2JWQPLZI.js.map
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkZWOSOI7Zjs = require('./chunk-ZWOSOI7Z.js');var o=(n=>(n.Empty="Empty",n.Pending="Pending",n.Confirmed="Confirmed",n.Canceled="Canceled",n))(o||{}),c= exports.b ={status:"Empty"},a= exports.c =(e,{type:i,data:r})=>{switch(i){case"ShoppingCartOpened":return{id:r.shoppingCartId,clientId:r.clientId,openedAt:r.openedAt,productItems:[],status:"Pending"};case"ProductItemAddedToShoppingCart":{if(e.status!=="Pending")return e;let{productItems:d}=e,{productItem:n}=r;return{...e,productItems:_chunkZWOSOI7Zjs.a.call(void 0, d,n,t=>t.productId===n.productId&&t.unitPrice===n.unitPrice,t=>({...t,quantity:t.quantity+n.quantity}),()=>n)}}case"ProductItemRemovedFromShoppingCart":{if(e.status!=="Pending")return e;let{productItems:d}=e,{productItem:n}=r;return{...e,productItems:_chunkZWOSOI7Zjs.a.call(void 0, d,n,t=>t.productId===n.productId&&t.unitPrice===n.unitPrice,t=>({...t,quantity:t.quantity-n.quantity}))}}case"ShoppingCartConfirmed":return e.status!=="Pending"?e:{...e,status:"Confirmed",confirmedAt:r.confirmedAt};case"ShoppingCartCanceled":return e.status!=="Pending"?e:{...e,status:"Canceled",canceledAt:r.canceledAt}}},s= exports.d =e=>e.reduce(a,c),u= exports.e =(t=>(t.CART_IS_ALREADY_CLOSED="CART_IS_ALREADY_CLOSED",t.PRODUCT_ITEM_NOT_FOUND="PRODUCT_ITEM_NOT_FOUND",t.CART_IS_EMPTY="CART_IS_EMPTY",t.UNKNOWN_EVENT_TYPE="UNKNOWN_EVENT_TYPE",t.UNKNOWN_COMMAND_TYPE="UNKNOWN_COMMAND_TYPE",t))(u||{});exports.a = o; exports.b = c; exports.c = a; exports.d = s; exports.e = u;
2
- //# sourceMappingURL=chunk-P7AA2K4Q.js.map
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkDA5J4ET5js = require('./chunk-DA5J4ET5.js');var o=(n=>(n.Empty="Empty",n.Pending="Pending",n.Confirmed="Confirmed",n.Canceled="Canceled",n))(o||{}),c= exports.b ={status:"Empty"},a= exports.c =(e,{type:i,data:r})=>{switch(i){case"ShoppingCartOpened":return{id:r.shoppingCartId,clientId:r.clientId,openedAt:r.openedAt,productItems:[],status:"Pending"};case"ProductItemAddedToShoppingCart":{if(e.status!=="Pending")return e;let{productItems:d}=e,{productItem:n}=r;return{...e,productItems:_chunkDA5J4ET5js.a.call(void 0, d,n,t=>t.productId===n.productId&&t.unitPrice===n.unitPrice,t=>({...t,quantity:t.quantity+n.quantity}),()=>n)}}case"ProductItemRemovedFromShoppingCart":{if(e.status!=="Pending")return e;let{productItems:d}=e,{productItem:n}=r;return{...e,productItems:_chunkDA5J4ET5js.a.call(void 0, d,n,t=>t.productId===n.productId&&t.unitPrice===n.unitPrice,t=>({...t,quantity:t.quantity-n.quantity}))}}case"ShoppingCartConfirmed":return e.status!=="Pending"?e:{...e,status:"Confirmed",confirmedAt:r.confirmedAt};case"ShoppingCartCanceled":return e.status!=="Pending"?e:{...e,status:"Canceled",canceledAt:r.canceledAt}}},s= exports.d =e=>e.reduce(a,c),u= exports.e =(t=>(t.CART_IS_ALREADY_CLOSED="CART_IS_ALREADY_CLOSED",t.PRODUCT_ITEM_NOT_FOUND="PRODUCT_ITEM_NOT_FOUND",t.CART_IS_EMPTY="CART_IS_EMPTY",t.UNKNOWN_EVENT_TYPE="UNKNOWN_EVENT_TYPE",t.UNKNOWN_COMMAND_TYPE="UNKNOWN_COMMAND_TYPE",t))(u||{});exports.a = o; exports.b = c; exports.c = a; exports.d = s; exports.e = u;
2
+ //# sourceMappingURL=chunk-5SQK7LQ2.js.map
@@ -1,2 +1,2 @@
1
- import{a as p}from"./chunk-HEPNAXF4.mjs";var o=(n=>(n.Empty="Empty",n.Pending="Pending",n.Confirmed="Confirmed",n.Canceled="Canceled",n))(o||{}),c={status:"Empty"},a=(e,{type:i,data:r})=>{switch(i){case"ShoppingCartOpened":return{id:r.shoppingCartId,clientId:r.clientId,openedAt:r.openedAt,productItems:[],status:"Pending"};case"ProductItemAddedToShoppingCart":{if(e.status!=="Pending")return e;let{productItems:d}=e,{productItem:n}=r;return{...e,productItems:p(d,n,t=>t.productId===n.productId&&t.unitPrice===n.unitPrice,t=>({...t,quantity:t.quantity+n.quantity}),()=>n)}}case"ProductItemRemovedFromShoppingCart":{if(e.status!=="Pending")return e;let{productItems:d}=e,{productItem:n}=r;return{...e,productItems:p(d,n,t=>t.productId===n.productId&&t.unitPrice===n.unitPrice,t=>({...t,quantity:t.quantity-n.quantity}))}}case"ShoppingCartConfirmed":return e.status!=="Pending"?e:{...e,status:"Confirmed",confirmedAt:r.confirmedAt};case"ShoppingCartCanceled":return e.status!=="Pending"?e:{...e,status:"Canceled",canceledAt:r.canceledAt}}},s=e=>e.reduce(a,c),u=(t=>(t.CART_IS_ALREADY_CLOSED="CART_IS_ALREADY_CLOSED",t.PRODUCT_ITEM_NOT_FOUND="PRODUCT_ITEM_NOT_FOUND",t.CART_IS_EMPTY="CART_IS_EMPTY",t.UNKNOWN_EVENT_TYPE="UNKNOWN_EVENT_TYPE",t.UNKNOWN_COMMAND_TYPE="UNKNOWN_COMMAND_TYPE",t))(u||{});export{o as a,c as b,a as c,s as d,u as e};
2
- //# sourceMappingURL=chunk-BPMP6GJ7.mjs.map
1
+ import{a as p}from"./chunk-KIRBEYFF.mjs";var o=(n=>(n.Empty="Empty",n.Pending="Pending",n.Confirmed="Confirmed",n.Canceled="Canceled",n))(o||{}),c={status:"Empty"},a=(e,{type:i,data:r})=>{switch(i){case"ShoppingCartOpened":return{id:r.shoppingCartId,clientId:r.clientId,openedAt:r.openedAt,productItems:[],status:"Pending"};case"ProductItemAddedToShoppingCart":{if(e.status!=="Pending")return e;let{productItems:d}=e,{productItem:n}=r;return{...e,productItems:p(d,n,t=>t.productId===n.productId&&t.unitPrice===n.unitPrice,t=>({...t,quantity:t.quantity+n.quantity}),()=>n)}}case"ProductItemRemovedFromShoppingCart":{if(e.status!=="Pending")return e;let{productItems:d}=e,{productItem:n}=r;return{...e,productItems:p(d,n,t=>t.productId===n.productId&&t.unitPrice===n.unitPrice,t=>({...t,quantity:t.quantity-n.quantity}))}}case"ShoppingCartConfirmed":return e.status!=="Pending"?e:{...e,status:"Confirmed",confirmedAt:r.confirmedAt};case"ShoppingCartCanceled":return e.status!=="Pending"?e:{...e,status:"Canceled",canceledAt:r.canceledAt}}},s=e=>e.reduce(a,c),u=(t=>(t.CART_IS_ALREADY_CLOSED="CART_IS_ALREADY_CLOSED",t.PRODUCT_ITEM_NOT_FOUND="PRODUCT_ITEM_NOT_FOUND",t.CART_IS_EMPTY="CART_IS_EMPTY",t.UNKNOWN_EVENT_TYPE="UNKNOWN_EVENT_TYPE",t.UNKNOWN_COMMAND_TYPE="UNKNOWN_COMMAND_TYPE",t))(u||{});export{o as a,c as b,a as c,s as d,u as e};
2
+ //# sourceMappingURL=chunk-BHGAXF2A.mjs.map
@@ -0,0 +1,5 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var b=(t,e,o,r,a=()=>{})=>{let n=!1,i=t.map(s=>o(s)?(n=!0,r(s)):s).filter(s=>s!==void 0).map(s=>{if(!s)throw Error("That should not happen");return s});return!n&&a()!==void 0?[...t,e]:i};var c=(t,e)=>{let o=t,r=e;return Object.keys(r).every(a=>typeof r[a]=="object"?c(o[a],r[a]):r[a]===o[a])},A= exports.b =(t,e)=>{if(!c(t,e))throw Error(`subObj:
2
+ ${JSON.stringify(e)}
3
+ is not subset of
4
+ ${JSON.stringify(t)}`)};var u=class y extends Error{constructor(e){let o=e&&typeof e=="object"&&"errorCode"in e?e.errorCode:l(e)?e:500,r=e&&typeof e=="object"&&"message"in e?e.message:g(e)?e:`Error with status code '${o}' ocurred during Emmett processing`;super(r),this.errorCode=o,Object.setPrototypeOf(this,y.prototype)}};var p=class v extends u{constructor(e){super({errorCode:400,message:_nullishCoalesce(e, () => ("Validation Error ocurred during Emmett processing"))}),Object.setPrototypeOf(this,v.prototype)}},T= exports.d =class N extends u{constructor(e){super({errorCode:403,message:_nullishCoalesce(e, () => ("Illegal State ocurred during Emmett processing"))}),Object.setPrototypeOf(this,N.prototype)}};var x=(t=>(t.NOT_A_NONEMPTY_STRING="NOT_A_NONEMPTY_STRING",t.NOT_A_POSITIVE_NUMBER="NOT_A_POSITIVE_NUMBER",t.NOT_AN_UNSIGNED_BIGINT="NOT_AN_UNSIGNED_BIGINT",t))(x||{}),l= exports.e =t=>typeof t=="number"&&t===t,g=t=>typeof t=="string",_= exports.f =t=>{if(!g(t)||t.length===0)throw new p("NOT_A_NONEMPTY_STRING");return t},C= exports.g =t=>{if(!l(t)||t<=0)throw new p("NOT_A_POSITIVE_NUMBER");return t},P= exports.h =t=>{let e=BigInt(t);if(e<0)throw new p("NOT_AN_UNSIGNED_BIGINT");return e};var S="STREAM_DOES_NOT_EXIST",f="NO_CONCURRENCY_CHECK";var I=(t,e,o=r=>r)=>async(r,a,n,i)=>{let s=o(a),m=await r.aggregateStream(s,{evolve:t,getInitialState:e,read:{expectedStreamVersion:_nullishCoalesce(_optionalChain([i, 'optionalAccess', _2 => _2.expectedStreamVersion]), () => (f))}}),E=_nullishCoalesce(_optionalChain([m, 'optionalAccess', _3 => _3.state]), () => (e())),O=_optionalChain([m, 'optionalAccess', _4 => _4.currentStreamVersion]),d=n(E),h=Array.isArray(d)?d:[d],w=_nullishCoalesce(_nullishCoalesce(_optionalChain([i, 'optionalAccess', _5 => _5.expectedStreamVersion]), () => (O)), () => (S));return{...await r.appendToStream(s,h,{expectedStreamVersion:w}),newState:h.reduce(t,E)}};var k=({decide:t,evolve:e,getInitialState:o},r=a=>a)=>async(a,n,i,s)=>I(e,o,r)(a,n,m=>t(i,m),s);var _assert = require('assert'); var _assert2 = _interopRequireDefault(_assert);var _crypto = require('crypto');var _test = require('test');exports.a = b; exports.b = A; exports.c = u; exports.d = T; exports.e = l; exports.f = _; exports.g = C; exports.h = P; exports.i = S; exports.j = k;
5
+ //# sourceMappingURL=chunk-DA5J4ET5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../emmett/src/utils/merge.ts","../../emmett/src/testing/assertions.ts","../../emmett/src/errors/index.ts","../../emmett/src/validation/index.ts","../../emmett/src/eventStore/expectedVersion.ts","../../emmett/src/commandHandling/handleCommand.ts","../../emmett/src/commandHandling/handleCommandWithDecider.ts","../../emmett/src/testing/deciderSpecification.ts","../../emmett/src/testing/features.ts","../../emmett/src/eventStore/inMemoryEventStore.ts"],"names":["merge","array","item","where","onExisting","onNotFound","wasFound","result","p","isSubset","superObj","subObj","sup","sub","ele","assertMatches","actual","expected","EmmettError","_EmmettError","options","errorCode","isNumber","message","isString","ValidationError","_ValidationError","IllegalStateError","_IllegalStateError","ValidationErrors","val","assertNotEmptyString","value","assertPositiveNumber","assertUnsignedBigInt","number","STREAM_DOES_NOT_EXIST","NO_CONCURRENCY_CHECK","CommandHandler","evolve","getInitialState","mapToStreamId","id","eventStore","handle","streamName","aggregationResult","state","currentStreamVersion","newEvents","expectedStreamVersion","DeciderCommandHandler","decide","command","assert","randomUUID","after","before","describe","it"],"mappings":"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","sourcesContent":["export const merge = <T>(\n array: T[],\n item: T,\n where: (current: T) => boolean,\n onExisting: (current: T) => T,\n onNotFound: () => T | undefined = () => undefined,\n) => {\n let wasFound = false;\n\n const result = array\n // merge the existing item if matches condition\n .map((p: T) => {\n if (!where(p)) return p;\n\n wasFound = true;\n return onExisting(p);\n })\n // filter out item if undefined was returned\n // for cases of removal\n .filter((p) => p !== undefined)\n // make TypeScript happy\n .map((p) => {\n if (!p) throw Error('That should not happen');\n\n return p;\n });\n\n // if item was not found and onNotFound action is defined\n // try to generate new item\n if (!wasFound) {\n const result = onNotFound();\n\n if (result !== undefined) return [...array, item];\n }\n\n return result;\n};\n","export const isSubset = (superObj: unknown, subObj: unknown): boolean => {\n const sup = superObj as Record<string, unknown>;\n const sub = subObj as Record<string, unknown>;\n\n return Object.keys(sub).every((ele: string) => {\n if (typeof sub[ele] == 'object') {\n return isSubset(\n sup[ele] as Record<string, unknown>,\n sub[ele] as Record<string, unknown>,\n );\n }\n return sub[ele] === sup[ele];\n });\n};\n\nexport const assertMatches = (actual: unknown, expected: unknown) => {\n if (!isSubset(actual, expected))\n throw Error(\n `subObj:\\n${JSON.stringify(expected)}\\nis not subset of\\n${JSON.stringify(actual)}`,\n );\n};\n","import { isNumber, isString } from '../validation';\n\nexport class EmmettError extends Error {\n public errorCode: number;\n\n constructor(\n options?: { errorCode: number; message?: string } | string | number,\n ) {\n const errorCode =\n options && typeof options === 'object' && 'errorCode' in options\n ? options.errorCode\n : isNumber(options)\n ? options\n : 500;\n const message =\n options && typeof options === 'object' && 'message' in options\n ? options.message\n : isString(options)\n ? options\n : `Error with status code '${errorCode}' ocurred during Emmett processing`;\n\n super(message);\n this.errorCode = errorCode;\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, EmmettError.prototype);\n }\n}\n\nexport class ConcurrencyError extends EmmettError {\n constructor(\n public current: string | undefined,\n public expected: string,\n message?: string,\n ) {\n super({\n errorCode: 412,\n message:\n message ??\n `Expected version ${expected.toString()} does not match current ${current?.toString()}`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ConcurrencyError.prototype);\n }\n}\n\nexport class ValidationError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: 400,\n message: message ?? `Validation Error ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\nexport class IllegalStateError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: 403,\n message: message ?? `Illegal State ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, IllegalStateError.prototype);\n }\n}\n\nexport class NotFoundError extends EmmettError {\n constructor(options?: { id: string; type: string; message?: string }) {\n super({\n errorCode: 404,\n message:\n options?.message ??\n (options?.id\n ? options.type\n ? `${options.type} with ${options.id} was not found during Emmett processing`\n : `State with ${options.id} was not found during Emmett processing`\n : options?.type\n ? `${options.type} was not found during Emmett processing`\n : 'State was not found during Emmett processing'),\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, NotFoundError.prototype);\n }\n}\n","import { ValidationError } from '../errors';\n\nexport const enum ValidationErrors {\n NOT_A_NONEMPTY_STRING = 'NOT_A_NONEMPTY_STRING',\n NOT_A_POSITIVE_NUMBER = 'NOT_A_POSITIVE_NUMBER',\n NOT_AN_UNSIGNED_BIGINT = 'NOT_AN_UNSIGNED_BIGINT',\n}\n\nexport const isNumber = (val: unknown): val is number =>\n typeof val === 'number' && val === val;\n\nexport const isString = (val: unknown): val is string =>\n typeof val === 'string';\n\nexport const assertNotEmptyString = (value: unknown): string => {\n if (!isString(value) || value.length === 0) {\n throw new ValidationError(ValidationErrors.NOT_A_NONEMPTY_STRING);\n }\n return value;\n};\n\nexport const assertPositiveNumber = (value: unknown): number => {\n if (!isNumber(value) || value <= 0) {\n throw new ValidationError(ValidationErrors.NOT_A_POSITIVE_NUMBER);\n }\n return value;\n};\n\nexport const assertUnsignedBigInt = (value: string): bigint => {\n const number = BigInt(value);\n if (number < 0) {\n throw new ValidationError(ValidationErrors.NOT_AN_UNSIGNED_BIGINT);\n }\n return number;\n};\n","import { ConcurrencyError } from '../errors';\nimport type { Flavour } from '../typing';\nimport type { DefaultStreamVersionType } from './eventStore';\n\nexport type ExpectedStreamVersion<VersionType = DefaultStreamVersionType> =\n | ExpectedStreamVersionWithValue<VersionType>\n | ExpectedStreamVersionGeneral;\n\nexport type ExpectedStreamVersionWithValue<\n VersionType = DefaultStreamVersionType,\n> = Flavour<VersionType, 'StreamVersion'>;\n\nexport type ExpectedStreamVersionGeneral = Flavour<\n 'STREAM_EXISTS' | 'STREAM_DOES_NOT_EXIST' | 'NO_CONCURRENCY_CHECK',\n 'StreamVersion'\n>;\n\nexport const STREAM_EXISTS = 'STREAM_EXISTS' as ExpectedStreamVersionGeneral;\nexport const STREAM_DOES_NOT_EXIST =\n 'STREAM_DOES_NOT_EXIST' as ExpectedStreamVersionGeneral;\nexport const NO_CONCURRENCY_CHECK =\n 'NO_CONCURRENCY_CHECK' as ExpectedStreamVersionGeneral;\n\nexport const matchesExpectedVersion = <\n StreamVersion = DefaultStreamVersionType,\n>(\n current: StreamVersion | undefined,\n expected: ExpectedStreamVersion<StreamVersion>,\n): boolean => {\n if (expected === NO_CONCURRENCY_CHECK) return true;\n\n if (expected == STREAM_DOES_NOT_EXIST) return current === undefined;\n\n if (expected == STREAM_EXISTS) return current !== undefined;\n\n return current === expected;\n};\n\nexport const assertExpectedVersionMatchesCurrent = <\n StreamVersion = DefaultStreamVersionType,\n>(\n current: StreamVersion | undefined,\n expected: ExpectedStreamVersion<StreamVersion> | undefined,\n): void => {\n expected ??= NO_CONCURRENCY_CHECK;\n\n if (!matchesExpectedVersion(current, expected))\n throw new ExpectedVersionConflictError(current, expected);\n};\n\nexport class ExpectedVersionConflictError<\n VersionType = DefaultStreamVersionType,\n> extends ConcurrencyError {\n constructor(\n current: VersionType | undefined,\n expected: ExpectedStreamVersion<VersionType>,\n ) {\n super(current?.toString(), expected?.toString());\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ExpectedVersionConflictError.prototype);\n }\n}\n","import {\n NO_CONCURRENCY_CHECK,\n STREAM_DOES_NOT_EXIST,\n type AppendToStreamResult,\n type DefaultStreamVersionType,\n type EventStore,\n type ExpectedStreamVersion,\n} from '../eventStore';\nimport type { Event } from '../typing';\n\n// #region command-handler\nexport type CommandHandlerResult<\n State,\n StreamVersion = DefaultStreamVersionType,\n> = AppendToStreamResult<StreamVersion> & { newState: State };\n\nexport const CommandHandler =\n <State, StreamEvent extends Event, StreamVersion = DefaultStreamVersionType>(\n evolve: (state: State, event: StreamEvent) => State,\n getInitialState: () => State,\n mapToStreamId: (id: string) => string = (id) => id,\n ) =>\n async (\n eventStore: EventStore<StreamVersion>,\n id: string,\n handle: (state: State) => StreamEvent | StreamEvent[],\n options?: {\n expectedStreamVersion?: ExpectedStreamVersion<StreamVersion>;\n },\n ): Promise<CommandHandlerResult<State, StreamVersion>> => {\n const streamName = mapToStreamId(id);\n\n // 1. Aggregate the stream\n const aggregationResult = await eventStore.aggregateStream<\n State,\n StreamEvent\n >(streamName, {\n evolve,\n getInitialState,\n read: {\n // expected stream version is passed to fail fast\n // if stream is in the wrong state\n expectedStreamVersion:\n options?.expectedStreamVersion ?? NO_CONCURRENCY_CHECK,\n },\n });\n\n // 2. Use the aggregate state or the initial one (when e.g. stream does not exist)\n const state = aggregationResult?.state ?? getInitialState();\n const currentStreamVersion = aggregationResult?.currentStreamVersion;\n\n // 3. Run business logic\n const result = handle(state);\n\n const newEvents = Array.isArray(result) ? result : [result];\n\n // Either use:\n // - provided expected stream version,\n // - current stream version got from stream aggregation,\n // - or expect stream not to exists otherwise.\n const expectedStreamVersion: ExpectedStreamVersion<StreamVersion> =\n options?.expectedStreamVersion ??\n currentStreamVersion ??\n STREAM_DOES_NOT_EXIST;\n\n // 4. Append result to the stream\n const appendResult = await eventStore.appendToStream(\n streamName,\n newEvents,\n {\n expectedStreamVersion,\n },\n );\n\n // 5. Return result with updated state\n return { ...appendResult, newState: newEvents.reduce(evolve, state) };\n };\n// #endregion command-handler\n","import type {\n DefaultStreamVersionType,\n EventStore,\n ExpectedStreamVersion,\n} from '../eventStore';\nimport type { Command, Event } from '../typing';\nimport type { Decider } from '../typing/decider';\nimport { CommandHandler } from './handleCommand';\n\n// #region command-handler\nexport const DeciderCommandHandler =\n <\n State,\n CommandType extends Command,\n StreamEvent extends Event,\n StreamVersion = DefaultStreamVersionType,\n >(\n {\n decide,\n evolve,\n getInitialState,\n }: Decider<State, CommandType, StreamEvent>,\n mapToStreamId: (id: string) => string = (id) => id,\n ) =>\n async (\n eventStore: EventStore<StreamVersion>,\n id: string,\n command: CommandType,\n options?: {\n expectedStreamVersion?: ExpectedStreamVersion<StreamVersion>;\n },\n ) =>\n CommandHandler<State, StreamEvent, StreamVersion>(\n evolve,\n getInitialState,\n mapToStreamId,\n )(eventStore, id, (state) => decide(command, state), options);\n// #endregion command-handler\n","import assert from 'assert';\n\nexport type DeciderSpecfication<Command, Event> = (\n givenEvents: Event | Event[],\n) => {\n when: (command: Command) => {\n then: (expectedEvents: Event | Event[]) => void;\n thenThrows: <Error>(assert: (error: Error) => boolean) => void;\n };\n};\n\nexport const DeciderSpecification = {\n for: <Command, Event, State>(decider: {\n decide: (command: Command, state: State) => Event | Event[];\n evolve: (state: State, event: Event) => State;\n initialState: () => State;\n }): DeciderSpecfication<Command, Event> => {\n {\n return (givenEvents: Event | Event[]) => {\n return {\n when: (command: Command) => {\n const handle = () => {\n const existingEvents = Array.isArray(givenEvents)\n ? givenEvents\n : [givenEvents];\n\n const currentState = existingEvents.reduce<State>(\n decider.evolve,\n decider.initialState(),\n );\n\n return decider.decide(command, currentState);\n };\n\n return {\n then: (expectedEvents: Event | Event[]): void => {\n const resultEvents = handle();\n\n const resultEventsArray = Array.isArray(resultEvents)\n ? resultEvents\n : [resultEvents];\n\n const expectedEventsArray = Array.isArray(expectedEvents)\n ? expectedEvents\n : [expectedEvents];\n\n assert.deepEqual(resultEventsArray, expectedEventsArray);\n },\n thenThrows: <Error>(check?: (error: Error) => boolean): void => {\n try {\n handle();\n assert.fail('Handler did not fail as expected');\n } catch (error) {\n if (check) assert.ok(check(error as Error));\n }\n },\n };\n },\n };\n };\n }\n },\n};\n","/* eslint-disable @typescript-eslint/no-floating-promises */\nimport assert from 'node:assert';\nimport { randomUUID } from 'node:crypto';\nimport { after, before, describe, it } from 'node:test';\nimport type { EventStore } from '../eventStore';\nimport {\n evolve,\n getInitialState,\n type PricedProductItem,\n type ShoppingCartEvent,\n} from './shoppingCart.domain';\n\ntype TestOptions = {\n getInitialIndex: () => bigint;\n teardownHook?: () => Promise<void>;\n};\n\nexport type EventStoreFactory = () => Promise<EventStore<bigint>>;\n\nexport async function testAggregateStream(\n eventStoreFactory: EventStoreFactory,\n options: TestOptions = {\n getInitialIndex: () => 1n,\n },\n) {\n return describe('aggregateStream', () => {\n let eventStore: EventStore<bigint>;\n\n before(async () => {\n eventStore = await eventStoreFactory();\n });\n\n after(async () => {\n const teardownHook = options.teardownHook;\n if (teardownHook) await teardownHook();\n });\n\n it('When called with `to` allows time traveling', async () => {\n // Given\n const productItem: PricedProductItem = {\n productId: '123',\n quantity: 10,\n price: 3,\n };\n const discount = 10;\n const shoppingCartId = randomUUID();\n\n await eventStore.appendToStream<ShoppingCartEvent>(shoppingCartId, [\n { type: 'ProductItemAdded', data: { productItem } },\n ]);\n await eventStore.appendToStream<ShoppingCartEvent>(shoppingCartId, [\n { type: 'ProductItemAdded', data: { productItem } },\n ]);\n await eventStore.appendToStream<ShoppingCartEvent>(shoppingCartId, [\n { type: 'DiscountApplied', data: { percent: discount } },\n ]);\n\n // when\n const resultAt1 = await eventStore.aggregateStream(shoppingCartId, {\n evolve,\n getInitialState,\n read: { to: 1n },\n });\n const resultAt2 = await eventStore.aggregateStream(shoppingCartId, {\n evolve,\n getInitialState,\n read: { to: 2n },\n });\n const resultAt3 = await eventStore.aggregateStream(shoppingCartId, {\n evolve,\n getInitialState,\n read: { to: 3n },\n });\n\n // then\n assert.ok(resultAt1);\n assert.ok(resultAt2);\n assert.ok(resultAt3);\n\n assert.equal(resultAt1.currentStreamVersion, options.getInitialIndex());\n assert.deepEqual(resultAt1.state, {\n productItems: [productItem],\n totalAmount: 30,\n });\n\n assert.equal(\n resultAt2.currentStreamVersion,\n options.getInitialIndex() + 1n,\n );\n assert.deepEqual(resultAt2.state, {\n productItems: [productItem, productItem],\n totalAmount: 60,\n });\n\n assert.equal(\n resultAt3.currentStreamVersion,\n options.getInitialIndex() + 2n,\n );\n assert.deepEqual(resultAt3.state, {\n productItems: [productItem, productItem],\n totalAmount: 54,\n });\n });\n });\n}\n","import { randomUUID } from 'crypto';\nimport type { Event } from '../typing';\nimport {\n type AggregateStreamOptions,\n type AggregateStreamResult,\n type AppendToStreamOptions,\n type AppendToStreamResult,\n type EventStore,\n type ReadStreamOptions,\n type ReadStreamResult,\n} from './eventStore';\nimport { assertExpectedVersionMatchesCurrent } from './expectedVersion';\n\nexport type EventMetadata = Readonly<{\n eventId: string;\n streamPosition: number;\n logPosition: bigint;\n}>;\n\nexport type EventEnvelope<E extends Event = Event> = {\n event: E;\n metadata: EventMetadata;\n};\n\nexport type EventHandler<E extends Event = Event> = (\n eventEnvelope: EventEnvelope<E>,\n) => void;\n\nexport const getInMemoryEventStore = (): EventStore => {\n const streams = new Map<string, EventEnvelope[]>();\n\n const getAllEventsCount = () => {\n return Array.from<EventEnvelope[]>(streams.values())\n .map((s) => s.length)\n .reduce((p, c) => p + c, 0);\n };\n\n return {\n async aggregateStream<State, EventType extends Event>(\n streamName: string,\n options: AggregateStreamOptions<State, EventType>,\n ): Promise<AggregateStreamResult<State> | null> {\n const { evolve, getInitialState, read } = options;\n\n const result = await this.readStream<EventType>(streamName, read);\n\n if (!result) return null;\n\n const events = result?.events ?? [];\n\n return {\n currentStreamVersion: BigInt(events.length),\n state: events.reduce(evolve, getInitialState()),\n };\n },\n\n readStream: <EventType extends Event>(\n streamName: string,\n options?: ReadStreamOptions,\n ): Promise<ReadStreamResult<EventType>> => {\n const events = streams.get(streamName);\n const currentStreamVersion = events ? BigInt(events.length) : undefined;\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n options?.expectedStreamVersion,\n );\n\n const from = Number(options && 'from' in options ? options.from : 0);\n const to = Number(\n options && 'to' in options\n ? options.to\n : options && 'maxCount' in options && options.maxCount\n ? options.from + options.maxCount\n : events?.length ?? 1,\n );\n\n const resultEvents =\n events && events.length > 0\n ? events.map((e) => e.event as EventType).slice(from, to)\n : [];\n\n const result: ReadStreamResult<EventType> =\n events && events.length > 0\n ? {\n currentStreamVersion: currentStreamVersion!,\n events: resultEvents,\n }\n : null;\n\n return Promise.resolve(result);\n },\n\n appendToStream: <EventType extends Event>(\n streamName: string,\n events: EventType[],\n options?: AppendToStreamOptions,\n ): Promise<AppendToStreamResult> => {\n const currentEvents = streams.get(streamName) ?? [];\n const currentStreamVersion =\n currentEvents.length > 0 ? BigInt(currentEvents.length) : undefined;\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n options?.expectedStreamVersion,\n );\n\n const eventEnvelopes: EventEnvelope[] = events.map((event, index) => {\n return {\n event,\n metadata: {\n eventId: randomUUID(),\n streamPosition: currentEvents.length + index + 1,\n logPosition: BigInt(getAllEventsCount() + index + 1),\n },\n };\n });\n\n const positionOfLastEventInTheStream = BigInt(\n eventEnvelopes.slice(-1)[0]!.metadata.streamPosition,\n );\n\n streams.set(streamName, [...currentEvents, ...eventEnvelopes]);\n\n const result: AppendToStreamResult = {\n nextExpectedStreamVersion: positionOfLastEventInTheStream,\n };\n\n return Promise.resolve(result);\n },\n };\n};\n"]}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }var _chunkNDXUB3PPjs = require('./chunk-NDXUB3PP.js');var _chunkZWOSOI7Zjs = require('./chunk-ZWOSOI7Z.js');var _express = require('express'); var _express2 = _interopRequireDefault(_express);require('express-async-errors');var _http = require('http'); var _http2 = _interopRequireDefault(_http);var _httpproblemdetails = require('http-problem-details');var u=e=>(t,o,s,i)=>{let p;e&&(p=e(t,o)),p=_nullishCoalesce(p, () => (P(t))),_chunkNDXUB3PPjs.f.call(void 0, s,p.status,{problem:p})},P= exports.n =e=>{let t=500;return e instanceof _chunkZWOSOI7Zjs.c&&(t=e.errorCode),new (0, _httpproblemdetails.ProblemDocument)({detail:e.message,status:t})};var v=e=>{let t=_express2.default.call(void 0, ),{apis:o,mapError:s,enableDefaultExpressEtag:i,disableJsonMiddleware:p,disableUrlEncodingMiddleware:b,disableProblemDetailsMiddleware:x}=e,m=_express.Router.call(void 0, );t.set("etag",_nullishCoalesce(i, () => (!1))),p||t.use(_express2.default.json()),b||t.use(_express2.default.urlencoded({extended:!0}));for(let H of o)H(m);return t.use(m),x||t.use(u(s)),t},N= exports.p =(e,t={port:3e3})=>{let{port:o}=t,s=_http2.default.createServer(e);return s.on("listening",()=>{console.info("server up listening")}),s.listen(o)};var K=e=>async(t,o,s)=>(await Promise.resolve(e(t)))(o),k= exports.b =e=>t=>{_chunkNDXUB3PPjs.e.call(void 0, t,200,e)},z= exports.c =e=>t=>{_chunkNDXUB3PPjs.c.call(void 0, t,e)},G= exports.d =e=>t=>{_chunkNDXUB3PPjs.d.call(void 0, t,e)},L= exports.e =e=>E(204,e),E= exports.f =(e,t)=>o=>{_chunkNDXUB3PPjs.e.call(void 0, o,e,t)},Q= exports.g =e=>n(400,e),V= exports.h =e=>n(403,e),X= exports.i =e=>n(404,e),Y= exports.j =e=>n(409,e),Z= exports.k =e=>n(412,e),n= exports.l =(e,t)=>o=>{_chunkNDXUB3PPjs.f.call(void 0, o,e,t)};exports.a = K; exports.b = k; exports.c = z; exports.d = G; exports.e = L; exports.f = E; exports.g = Q; exports.h = V; exports.i = X; exports.j = Y; exports.k = Z; exports.l = n; exports.m = u; exports.n = P; exports.o = v; exports.p = N;
2
- //# sourceMappingURL=chunk-UT7Q27E5.js.map
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }var _chunkNDXUB3PPjs = require('./chunk-NDXUB3PP.js');var _chunkDA5J4ET5js = require('./chunk-DA5J4ET5.js');var _express = require('express'); var _express2 = _interopRequireDefault(_express);require('express-async-errors');var _http = require('http'); var _http2 = _interopRequireDefault(_http);var _httpproblemdetails = require('http-problem-details');var u=e=>(t,o,s,i)=>{let p;e&&(p=e(t,o)),p=_nullishCoalesce(p, () => (P(t))),_chunkNDXUB3PPjs.f.call(void 0, s,p.status,{problem:p})},P= exports.n =e=>{let t=500;return"errorCode"in e&&_chunkDA5J4ET5js.e.call(void 0, e.errorCode)&&e.errorCode>=100&&e.errorCode<600&&(t=e.errorCode),new (0, _httpproblemdetails.ProblemDocument)({detail:e.message,status:t})};var N=e=>{let t=_express2.default.call(void 0, ),{apis:o,mapError:s,enableDefaultExpressEtag:i,disableJsonMiddleware:p,disableUrlEncodingMiddleware:b,disableProblemDetailsMiddleware:x}=e,d=_express.Router.call(void 0, );t.set("etag",_nullishCoalesce(i, () => (!1))),p||t.use(_express2.default.json()),b||t.use(_express2.default.urlencoded({extended:!0}));for(let H of o)H(d);return t.use(d),x||t.use(u(s)),t},v= exports.p =(e,t={port:3e3})=>{let{port:o}=t,s=_http2.default.createServer(e);return s.on("listening",()=>{console.info("server up listening")}),s.listen(o)};var K=e=>async(t,o,s)=>(await Promise.resolve(e(t)))(o),k= exports.b =e=>t=>{_chunkNDXUB3PPjs.e.call(void 0, t,200,e)},z= exports.c =e=>t=>{_chunkNDXUB3PPjs.c.call(void 0, t,e)},G= exports.d =e=>t=>{_chunkNDXUB3PPjs.d.call(void 0, t,e)},L= exports.e =e=>A(204,e),A= exports.f =(e,t)=>o=>{_chunkNDXUB3PPjs.e.call(void 0, o,e,t)},Q= exports.g =e=>n(400,e),V= exports.h =e=>n(403,e),X= exports.i =e=>n(404,e),Y= exports.j =e=>n(409,e),Z= exports.k =e=>n(412,e),n= exports.l =(e,t)=>o=>{_chunkNDXUB3PPjs.f.call(void 0, o,e,t)};exports.a = K; exports.b = k; exports.c = z; exports.d = G; exports.e = L; exports.f = A; exports.g = Q; exports.h = V; exports.i = X; exports.j = Y; exports.k = Z; exports.l = n; exports.m = u; exports.n = P; exports.o = N; exports.p = v;
2
+ //# sourceMappingURL=chunk-DLZ3WQUJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/handler.ts","../src/index.ts","../src/application.ts","../src/middlewares/problemDetailsMiddleware.ts"],"names":["express","Router","http","ProblemDocument","problemDetailsMiddleware","mapError","error","request","response","_next","problemDetails","defaulErrorToProblemDetailsMapping","sendProblem","statusCode","i","getApplication","options","app","apis","enableDefaultExpressEtag","disableJsonMiddleware","disableUrlEncodingMiddleware","disableProblemDetailsMiddleware","router","api","startAPI","port","server","on","handle","OK","send","Created","sendCreated","Accepted","sendAccepted","NoContent","HttpResponse","BadRequest","HttpProblem","Forbidden","NotFound","Conflict","PreconditionFailed"],"mappings":"qGAAA,MAA+D,UCA/D,MAAO,uBCAP,OAAOA,GAAW,UAAAC,MAAgC,UAClD,MAAO,uBACP,OAAOC,MAAU,OCAjB,OAAS,mBAAAC,MAAuB,uBAGzB,IAAMC,EACVC,GACD,CACEC,EACAC,EACAC,EACAC,IACS,CACT,IAAIC,EAEAL,IAAUK,EAAiBL,EAASC,EAAOC,CAAO,GAEtDG,EACEA,GAAkBC,EAAmCL,CAAK,EAE5DM,EAAYJ,EAAUE,EAAe,OAAQ,CAAE,QAASA,CAAe,CAAC,CAC1E,EAEWC,EACXL,GACoB,CACpB,IAAIO,EAAa,IAEjB,MACE,cAAeP,GACfQ,EAASR,EAAM,SAAS,GACxBA,EAAM,WAAa,KACnBA,EAAM,UAAY,MAElBO,EAAaP,EAAM,WAGd,IAAIH,EAAgB,CACzB,OAAQG,EAAM,QACd,OAAQO,CACV,CAAC,CACH,EDtBO,IAAME,EAAkBC,GAAgC,CAC7D,IAAMC,EAAmBjB,EAAQ,EAE3B,CACJ,KAAAkB,EACA,SAAAb,EACA,yBAAAc,EACA,sBAAAC,EACA,6BAAAC,EACA,gCAAAC,CACF,EAAIN,EAEEO,EAAStB,EAAO,EAItBgB,EAAI,IAAI,OAAQE,GAA4B,EAAK,EAG5CC,GAAuBH,EAAI,IAAIjB,EAAQ,KAAK,CAAC,EAG7CqB,GACHJ,EAAI,IACFjB,EAAQ,WAAW,CACjB,SAAU,EACZ,CAAC,CACH,EAEF,QAAWwB,KAAON,EAChBM,EAAID,CAAM,EAEZ,OAAAN,EAAI,IAAIM,CAAM,EAGTD,GACHL,EAAI,IAAIb,EAAyBC,CAAQ,CAAC,EAErCY,CACT,EAMaQ,EAAW,CACtBR,EACAD,EAA2B,CAAE,KAAM,GAAK,IACrC,CACH,GAAM,CAAE,KAAAU,CAAK,EAAIV,EACXW,EAASzB,EAAK,aAAae,CAAG,EAEpC,OAAAU,EAAO,GAAG,YAAa,IAAM,CAC3B,QAAQ,KAAK,qBAAqB,CACpC,CAAC,EAEMA,EAAO,OAAOD,CAAI,CAC3B,EFxDO,IAAME,EACmBC,GAC9B,MACEtB,EACAC,EACAC,KAEoB,MAAM,QAAQ,QAAQoB,EAAOtB,CAAO,CAAC,GAEtCC,CAAQ,EAIlBsB,EACVd,GACAR,GAAuB,CACtBuB,EAAKvB,EAAU,IAAKQ,CAAO,CAC7B,EAEWgB,EACVhB,GACAR,GAAuB,CACtByB,EAAYzB,EAAUQ,CAAO,CAC/B,EAEWkB,EACVlB,GACAR,GAAuB,CACtB2B,EAAa3B,EAAUQ,CAAO,CAChC,EAEWoB,EACXpB,GACiBqB,EAAa,IAAKrB,CAAO,EAE/BqB,EACX,CAACxB,EAAoBG,IACpBR,GAAuB,CACtBuB,EAAKvB,EAAUK,EAAYG,CAAO,CACpC,EAMWsB,EACXtB,GACiBuB,EAAY,IAAKvB,CAAO,EAE9BwB,EAAaxB,GACxBuB,EAAY,IAAKvB,CAAO,EAEbyB,EAAYzB,GACvBuB,EAAY,IAAKvB,CAAO,EAEb0B,EAAY1B,GACvBuB,EAAY,IAAKvB,CAAO,EAEb2B,EACX3B,GACiBuB,EAAY,IAAKvB,CAAO,EAE9BuB,EACX,CAAC1B,EAAoBG,IACpBR,GAAuB,CACtBI,EAAYJ,EAAUK,EAAYG,CAAO,CAC3C","sourcesContent":["import { type NextFunction, type Request, type Response } from 'express';\nimport {\n send,\n sendAccepted,\n sendCreated,\n sendProblem,\n type AcceptedHttpResponseOptions,\n type CreatedHttpResponseOptions,\n type HttpProblemResponseOptions,\n type HttpResponseOptions,\n type NoContentHttpResponseOptions,\n} from '.';\n\n// #region httpresponse-on\nexport type HttpResponse = (response: Response) => void;\n\nexport type HttpHandler<RequestType extends Request> = (\n request: RequestType,\n) => Promise<HttpResponse> | HttpResponse;\n\nexport const on =\n <RequestType extends Request>(handle: HttpHandler<RequestType>) =>\n async (\n request: RequestType,\n response: Response,\n _next: NextFunction,\n ): Promise<void> => {\n const setResponse = await Promise.resolve(handle(request));\n\n return setResponse(response);\n };\n// #endregion httpresponse-on\n\nexport const OK =\n (options?: HttpResponseOptions): HttpResponse =>\n (response: Response) => {\n send(response, 200, options);\n };\n\nexport const Created =\n (options: CreatedHttpResponseOptions): HttpResponse =>\n (response: Response) => {\n sendCreated(response, options);\n };\n\nexport const Accepted =\n (options: AcceptedHttpResponseOptions): HttpResponse =>\n (response: Response) => {\n sendAccepted(response, options);\n };\n\nexport const NoContent = (\n options?: NoContentHttpResponseOptions,\n): HttpResponse => HttpResponse(204, options);\n\nexport const HttpResponse =\n (statusCode: number, options?: HttpResponseOptions): HttpResponse =>\n (response: Response) => {\n send(response, statusCode, options);\n };\n\n/////////////////////\n// ERRORS\n/////////////////////\n\nexport const BadRequest = (\n options?: HttpProblemResponseOptions,\n): HttpResponse => HttpProblem(400, options);\n\nexport const Forbidden = (options?: HttpProblemResponseOptions): HttpResponse =>\n HttpProblem(403, options);\n\nexport const NotFound = (options?: HttpProblemResponseOptions): HttpResponse =>\n HttpProblem(404, options);\n\nexport const Conflict = (options?: HttpProblemResponseOptions): HttpResponse =>\n HttpProblem(409, options);\n\nexport const PreconditionFailed = (\n options: HttpProblemResponseOptions,\n): HttpResponse => HttpProblem(412, options);\n\nexport const HttpProblem =\n (statusCode: number, options?: HttpProblemResponseOptions): HttpResponse =>\n (response: Response) => {\n sendProblem(response, statusCode, options);\n };\n","import 'express-async-errors';\n\nexport * from './application';\nexport * from './etag';\nexport * from './handler';\nexport * from './responses';\nexport * from './testing';\n","import express, { Router, type Application } from 'express';\nimport 'express-async-errors';\nimport http from 'http';\nimport { problemDetailsMiddleware } from './middlewares/problemDetailsMiddleware';\nimport type { ErrorToProblemDetailsMapping } from './responses';\n\n// #region web-api-setup\nexport type WebApiSetup = (router: Router) => void;\n// #endregion web-api-setup\n\nexport type ApplicationOptions = {\n apis: WebApiSetup[];\n mapError?: ErrorToProblemDetailsMapping;\n enableDefaultExpressEtag?: boolean;\n disableJsonMiddleware?: boolean;\n disableUrlEncodingMiddleware?: boolean;\n disableProblemDetailsMiddleware?: boolean;\n};\n\nexport const getApplication = (options: ApplicationOptions) => {\n const app: Application = express();\n\n const {\n apis,\n mapError,\n enableDefaultExpressEtag,\n disableJsonMiddleware,\n disableUrlEncodingMiddleware,\n disableProblemDetailsMiddleware,\n } = options;\n\n const router = Router();\n\n // disabling default etag behaviour\n // to use etags in if-match and if-not-match headers\n app.set('etag', enableDefaultExpressEtag ?? false);\n\n // add json middleware\n if (!disableJsonMiddleware) app.use(express.json());\n\n // enable url encoded urls and bodies\n if (!disableUrlEncodingMiddleware)\n app.use(\n express.urlencoded({\n extended: true,\n }),\n );\n\n for (const api of apis) {\n api(router);\n }\n app.use(router);\n\n // add problem details middleware\n if (!disableProblemDetailsMiddleware)\n app.use(problemDetailsMiddleware(mapError));\n\n return app;\n};\n\nexport type StartApiOptions = {\n port?: number;\n};\n\nexport const startAPI = (\n app: Application,\n options: StartApiOptions = { port: 3000 },\n) => {\n const { port } = options;\n const server = http.createServer(app);\n\n server.on('listening', () => {\n console.info('server up listening');\n });\n\n return server.listen(port);\n};\n","import { isNumber } from '@event-driven-io/emmett';\nimport type { NextFunction, Request, Response } from 'express';\nimport { ProblemDocument } from 'http-problem-details';\nimport { sendProblem, type ErrorToProblemDetailsMapping } from '..';\n\nexport const problemDetailsMiddleware =\n (mapError?: ErrorToProblemDetailsMapping) =>\n (\n error: Error,\n request: Request,\n response: Response,\n _next: NextFunction,\n ): void => {\n let problemDetails: ProblemDocument | undefined;\n\n if (mapError) problemDetails = mapError(error, request);\n\n problemDetails =\n problemDetails ?? defaulErrorToProblemDetailsMapping(error);\n\n sendProblem(response, problemDetails.status, { problem: problemDetails });\n };\n\nexport const defaulErrorToProblemDetailsMapping = (\n error: Error,\n): ProblemDocument => {\n let statusCode = 500;\n\n if (\n 'errorCode' in error &&\n isNumber(error.errorCode) &&\n error.errorCode >= 100 &&\n error.errorCode < 600\n ) {\n statusCode = error.errorCode;\n }\n\n return new ProblemDocument({\n detail: error.message,\n status: statusCode,\n });\n};\n"]}
@@ -1,2 +1,2 @@
1
- import{a as c}from"./chunk-42BDHECF.mjs";import{b as a}from"./chunk-HEPNAXF4.mjs";import"express";import v from"node:assert/strict";import f from"supertest";var b=(t,e)=>[t,e],h=(t,e)=>[t,e],R=(t,e)=>[t,e],d=(t,e)=>r=>{let{body:s,headers:o}=e??{};v.equal(r.statusCode,t),s&&a(r.body,s),o&&a(r.headers,o)},w=(t,e)=>d(t,e?{body:e}:void 0),V={for:(t,e)=>(...r)=>{let s=c(t()),o=e(s);return{when:E=>{let y=async()=>{for(let[n,p]of r)await s.setup(n,p);return E(f(o))};return{then:async n=>{let p=await y();if(typeof n=="function")n(p)===!1&&v.fail();else if(Array.isArray(n)){let[i,...m]=n;typeof i=="function"&&i(p)===!1&&v.fail();let T=typeof i=="function"?m:n;a(Array.from(s.appendedEvents.values()),T)}}}}}}};export{b as a,h as b,R as c,d,w as e,V as f};
2
- //# sourceMappingURL=chunk-TJPUQYKV.mjs.map
1
+ import{a as c}from"./chunk-42BDHECF.mjs";import{b as a}from"./chunk-KIRBEYFF.mjs";import"express";import v from"node:assert/strict";import f from"supertest";var b=(t,e)=>[t,e],h=(t,e)=>[t,e],R=(t,e)=>[t,e],d=(t,e)=>r=>{let{body:s,headers:o}=e??{};v.equal(r.statusCode,t),s&&a(r.body,s),o&&a(r.headers,o)},w=(t,e)=>d(t,e?{body:e}:void 0),V={for:(t,e)=>(...r)=>{let s=c(t()),o=e(s);return{when:E=>{let y=async()=>{for(let[n,p]of r)await s.setup(n,p);return E(f(o))};return{then:async n=>{let p=await y();if(typeof n=="function")n(p)===!1&&v.fail();else if(Array.isArray(n)){let[i,...m]=n;typeof i=="function"&&i(p)===!1&&v.fail();let T=typeof i=="function"?m:n;a(Array.from(s.appendedEvents.values()),T)}}}}}}};export{b as a,h as b,R as c,d,w as e,V as f};
2
+ //# sourceMappingURL=chunk-IMSJF3JS.mjs.map
@@ -0,0 +1,5 @@
1
+ var b=(t,e,o,r,a=()=>{})=>{let n=!1,i=t.map(s=>o(s)?(n=!0,r(s)):s).filter(s=>s!==void 0).map(s=>{if(!s)throw Error("That should not happen");return s});return!n&&a()!==void 0?[...t,e]:i};var c=(t,e)=>{let o=t,r=e;return Object.keys(r).every(a=>typeof r[a]=="object"?c(o[a],r[a]):r[a]===o[a])},A=(t,e)=>{if(!c(t,e))throw Error(`subObj:
2
+ ${JSON.stringify(e)}
3
+ is not subset of
4
+ ${JSON.stringify(t)}`)};var u=class y extends Error{errorCode;constructor(e){let o=e&&typeof e=="object"&&"errorCode"in e?e.errorCode:l(e)?e:500,r=e&&typeof e=="object"&&"message"in e?e.message:g(e)?e:`Error with status code '${o}' ocurred during Emmett processing`;super(r),this.errorCode=o,Object.setPrototypeOf(this,y.prototype)}};var p=class v extends u{constructor(e){super({errorCode:400,message:e??"Validation Error ocurred during Emmett processing"}),Object.setPrototypeOf(this,v.prototype)}},T=class N extends u{constructor(e){super({errorCode:403,message:e??"Illegal State ocurred during Emmett processing"}),Object.setPrototypeOf(this,N.prototype)}};var x=(t=>(t.NOT_A_NONEMPTY_STRING="NOT_A_NONEMPTY_STRING",t.NOT_A_POSITIVE_NUMBER="NOT_A_POSITIVE_NUMBER",t.NOT_AN_UNSIGNED_BIGINT="NOT_AN_UNSIGNED_BIGINT",t))(x||{}),l=t=>typeof t=="number"&&t===t,g=t=>typeof t=="string",_=t=>{if(!g(t)||t.length===0)throw new p("NOT_A_NONEMPTY_STRING");return t},C=t=>{if(!l(t)||t<=0)throw new p("NOT_A_POSITIVE_NUMBER");return t},P=t=>{let e=BigInt(t);if(e<0)throw new p("NOT_AN_UNSIGNED_BIGINT");return e};var S="STREAM_DOES_NOT_EXIST",f="NO_CONCURRENCY_CHECK";var I=(t,e,o=r=>r)=>async(r,a,n,i)=>{let s=o(a),m=await r.aggregateStream(s,{evolve:t,getInitialState:e,read:{expectedStreamVersion:i?.expectedStreamVersion??f}}),E=m?.state??e(),O=m?.currentStreamVersion,d=n(E),h=Array.isArray(d)?d:[d],w=i?.expectedStreamVersion??O??S;return{...await r.appendToStream(s,h,{expectedStreamVersion:w}),newState:h.reduce(t,E)}};var k=({decide:t,evolve:e,getInitialState:o},r=a=>a)=>async(a,n,i,s)=>I(e,o,r)(a,n,m=>t(i,m),s);import L from"assert";import et from"node:assert";import{randomUUID as at}from"node:crypto";import{after as ot,before as nt,describe as it,it as mt}from"node:test";import{randomUUID as lt}from"crypto";export{b as a,A as b,u as c,T as d,l as e,_ as f,C as g,P as h,S as i,k as j};
5
+ //# sourceMappingURL=chunk-KIRBEYFF.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../emmett/src/utils/merge.ts","../../emmett/src/testing/assertions.ts","../../emmett/src/errors/index.ts","../../emmett/src/validation/index.ts","../../emmett/src/eventStore/expectedVersion.ts","../../emmett/src/commandHandling/handleCommand.ts","../../emmett/src/commandHandling/handleCommandWithDecider.ts","../../emmett/src/testing/deciderSpecification.ts","../../emmett/src/testing/features.ts","../../emmett/src/eventStore/inMemoryEventStore.ts"],"sourcesContent":["export const merge = <T>(\n array: T[],\n item: T,\n where: (current: T) => boolean,\n onExisting: (current: T) => T,\n onNotFound: () => T | undefined = () => undefined,\n) => {\n let wasFound = false;\n\n const result = array\n // merge the existing item if matches condition\n .map((p: T) => {\n if (!where(p)) return p;\n\n wasFound = true;\n return onExisting(p);\n })\n // filter out item if undefined was returned\n // for cases of removal\n .filter((p) => p !== undefined)\n // make TypeScript happy\n .map((p) => {\n if (!p) throw Error('That should not happen');\n\n return p;\n });\n\n // if item was not found and onNotFound action is defined\n // try to generate new item\n if (!wasFound) {\n const result = onNotFound();\n\n if (result !== undefined) return [...array, item];\n }\n\n return result;\n};\n","export const isSubset = (superObj: unknown, subObj: unknown): boolean => {\n const sup = superObj as Record<string, unknown>;\n const sub = subObj as Record<string, unknown>;\n\n return Object.keys(sub).every((ele: string) => {\n if (typeof sub[ele] == 'object') {\n return isSubset(\n sup[ele] as Record<string, unknown>,\n sub[ele] as Record<string, unknown>,\n );\n }\n return sub[ele] === sup[ele];\n });\n};\n\nexport const assertMatches = (actual: unknown, expected: unknown) => {\n if (!isSubset(actual, expected))\n throw Error(\n `subObj:\\n${JSON.stringify(expected)}\\nis not subset of\\n${JSON.stringify(actual)}`,\n );\n};\n","import { isNumber, isString } from '../validation';\n\nexport class EmmettError extends Error {\n public errorCode: number;\n\n constructor(\n options?: { errorCode: number; message?: string } | string | number,\n ) {\n const errorCode =\n options && typeof options === 'object' && 'errorCode' in options\n ? options.errorCode\n : isNumber(options)\n ? options\n : 500;\n const message =\n options && typeof options === 'object' && 'message' in options\n ? options.message\n : isString(options)\n ? options\n : `Error with status code '${errorCode}' ocurred during Emmett processing`;\n\n super(message);\n this.errorCode = errorCode;\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, EmmettError.prototype);\n }\n}\n\nexport class ConcurrencyError extends EmmettError {\n constructor(\n public current: string | undefined,\n public expected: string,\n message?: string,\n ) {\n super({\n errorCode: 412,\n message:\n message ??\n `Expected version ${expected.toString()} does not match current ${current?.toString()}`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ConcurrencyError.prototype);\n }\n}\n\nexport class ValidationError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: 400,\n message: message ?? `Validation Error ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\nexport class IllegalStateError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: 403,\n message: message ?? `Illegal State ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, IllegalStateError.prototype);\n }\n}\n\nexport class NotFoundError extends EmmettError {\n constructor(options?: { id: string; type: string; message?: string }) {\n super({\n errorCode: 404,\n message:\n options?.message ??\n (options?.id\n ? options.type\n ? `${options.type} with ${options.id} was not found during Emmett processing`\n : `State with ${options.id} was not found during Emmett processing`\n : options?.type\n ? `${options.type} was not found during Emmett processing`\n : 'State was not found during Emmett processing'),\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, NotFoundError.prototype);\n }\n}\n","import { ValidationError } from '../errors';\n\nexport const enum ValidationErrors {\n NOT_A_NONEMPTY_STRING = 'NOT_A_NONEMPTY_STRING',\n NOT_A_POSITIVE_NUMBER = 'NOT_A_POSITIVE_NUMBER',\n NOT_AN_UNSIGNED_BIGINT = 'NOT_AN_UNSIGNED_BIGINT',\n}\n\nexport const isNumber = (val: unknown): val is number =>\n typeof val === 'number' && val === val;\n\nexport const isString = (val: unknown): val is string =>\n typeof val === 'string';\n\nexport const assertNotEmptyString = (value: unknown): string => {\n if (!isString(value) || value.length === 0) {\n throw new ValidationError(ValidationErrors.NOT_A_NONEMPTY_STRING);\n }\n return value;\n};\n\nexport const assertPositiveNumber = (value: unknown): number => {\n if (!isNumber(value) || value <= 0) {\n throw new ValidationError(ValidationErrors.NOT_A_POSITIVE_NUMBER);\n }\n return value;\n};\n\nexport const assertUnsignedBigInt = (value: string): bigint => {\n const number = BigInt(value);\n if (number < 0) {\n throw new ValidationError(ValidationErrors.NOT_AN_UNSIGNED_BIGINT);\n }\n return number;\n};\n","import { ConcurrencyError } from '../errors';\nimport type { Flavour } from '../typing';\nimport type { DefaultStreamVersionType } from './eventStore';\n\nexport type ExpectedStreamVersion<VersionType = DefaultStreamVersionType> =\n | ExpectedStreamVersionWithValue<VersionType>\n | ExpectedStreamVersionGeneral;\n\nexport type ExpectedStreamVersionWithValue<\n VersionType = DefaultStreamVersionType,\n> = Flavour<VersionType, 'StreamVersion'>;\n\nexport type ExpectedStreamVersionGeneral = Flavour<\n 'STREAM_EXISTS' | 'STREAM_DOES_NOT_EXIST' | 'NO_CONCURRENCY_CHECK',\n 'StreamVersion'\n>;\n\nexport const STREAM_EXISTS = 'STREAM_EXISTS' as ExpectedStreamVersionGeneral;\nexport const STREAM_DOES_NOT_EXIST =\n 'STREAM_DOES_NOT_EXIST' as ExpectedStreamVersionGeneral;\nexport const NO_CONCURRENCY_CHECK =\n 'NO_CONCURRENCY_CHECK' as ExpectedStreamVersionGeneral;\n\nexport const matchesExpectedVersion = <\n StreamVersion = DefaultStreamVersionType,\n>(\n current: StreamVersion | undefined,\n expected: ExpectedStreamVersion<StreamVersion>,\n): boolean => {\n if (expected === NO_CONCURRENCY_CHECK) return true;\n\n if (expected == STREAM_DOES_NOT_EXIST) return current === undefined;\n\n if (expected == STREAM_EXISTS) return current !== undefined;\n\n return current === expected;\n};\n\nexport const assertExpectedVersionMatchesCurrent = <\n StreamVersion = DefaultStreamVersionType,\n>(\n current: StreamVersion | undefined,\n expected: ExpectedStreamVersion<StreamVersion> | undefined,\n): void => {\n expected ??= NO_CONCURRENCY_CHECK;\n\n if (!matchesExpectedVersion(current, expected))\n throw new ExpectedVersionConflictError(current, expected);\n};\n\nexport class ExpectedVersionConflictError<\n VersionType = DefaultStreamVersionType,\n> extends ConcurrencyError {\n constructor(\n current: VersionType | undefined,\n expected: ExpectedStreamVersion<VersionType>,\n ) {\n super(current?.toString(), expected?.toString());\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ExpectedVersionConflictError.prototype);\n }\n}\n","import {\n NO_CONCURRENCY_CHECK,\n STREAM_DOES_NOT_EXIST,\n type AppendToStreamResult,\n type DefaultStreamVersionType,\n type EventStore,\n type ExpectedStreamVersion,\n} from '../eventStore';\nimport type { Event } from '../typing';\n\n// #region command-handler\nexport type CommandHandlerResult<\n State,\n StreamVersion = DefaultStreamVersionType,\n> = AppendToStreamResult<StreamVersion> & { newState: State };\n\nexport const CommandHandler =\n <State, StreamEvent extends Event, StreamVersion = DefaultStreamVersionType>(\n evolve: (state: State, event: StreamEvent) => State,\n getInitialState: () => State,\n mapToStreamId: (id: string) => string = (id) => id,\n ) =>\n async (\n eventStore: EventStore<StreamVersion>,\n id: string,\n handle: (state: State) => StreamEvent | StreamEvent[],\n options?: {\n expectedStreamVersion?: ExpectedStreamVersion<StreamVersion>;\n },\n ): Promise<CommandHandlerResult<State, StreamVersion>> => {\n const streamName = mapToStreamId(id);\n\n // 1. Aggregate the stream\n const aggregationResult = await eventStore.aggregateStream<\n State,\n StreamEvent\n >(streamName, {\n evolve,\n getInitialState,\n read: {\n // expected stream version is passed to fail fast\n // if stream is in the wrong state\n expectedStreamVersion:\n options?.expectedStreamVersion ?? NO_CONCURRENCY_CHECK,\n },\n });\n\n // 2. Use the aggregate state or the initial one (when e.g. stream does not exist)\n const state = aggregationResult?.state ?? getInitialState();\n const currentStreamVersion = aggregationResult?.currentStreamVersion;\n\n // 3. Run business logic\n const result = handle(state);\n\n const newEvents = Array.isArray(result) ? result : [result];\n\n // Either use:\n // - provided expected stream version,\n // - current stream version got from stream aggregation,\n // - or expect stream not to exists otherwise.\n const expectedStreamVersion: ExpectedStreamVersion<StreamVersion> =\n options?.expectedStreamVersion ??\n currentStreamVersion ??\n STREAM_DOES_NOT_EXIST;\n\n // 4. Append result to the stream\n const appendResult = await eventStore.appendToStream(\n streamName,\n newEvents,\n {\n expectedStreamVersion,\n },\n );\n\n // 5. Return result with updated state\n return { ...appendResult, newState: newEvents.reduce(evolve, state) };\n };\n// #endregion command-handler\n","import type {\n DefaultStreamVersionType,\n EventStore,\n ExpectedStreamVersion,\n} from '../eventStore';\nimport type { Command, Event } from '../typing';\nimport type { Decider } from '../typing/decider';\nimport { CommandHandler } from './handleCommand';\n\n// #region command-handler\nexport const DeciderCommandHandler =\n <\n State,\n CommandType extends Command,\n StreamEvent extends Event,\n StreamVersion = DefaultStreamVersionType,\n >(\n {\n decide,\n evolve,\n getInitialState,\n }: Decider<State, CommandType, StreamEvent>,\n mapToStreamId: (id: string) => string = (id) => id,\n ) =>\n async (\n eventStore: EventStore<StreamVersion>,\n id: string,\n command: CommandType,\n options?: {\n expectedStreamVersion?: ExpectedStreamVersion<StreamVersion>;\n },\n ) =>\n CommandHandler<State, StreamEvent, StreamVersion>(\n evolve,\n getInitialState,\n mapToStreamId,\n )(eventStore, id, (state) => decide(command, state), options);\n// #endregion command-handler\n","import assert from 'assert';\n\nexport type DeciderSpecfication<Command, Event> = (\n givenEvents: Event | Event[],\n) => {\n when: (command: Command) => {\n then: (expectedEvents: Event | Event[]) => void;\n thenThrows: <Error>(assert: (error: Error) => boolean) => void;\n };\n};\n\nexport const DeciderSpecification = {\n for: <Command, Event, State>(decider: {\n decide: (command: Command, state: State) => Event | Event[];\n evolve: (state: State, event: Event) => State;\n initialState: () => State;\n }): DeciderSpecfication<Command, Event> => {\n {\n return (givenEvents: Event | Event[]) => {\n return {\n when: (command: Command) => {\n const handle = () => {\n const existingEvents = Array.isArray(givenEvents)\n ? givenEvents\n : [givenEvents];\n\n const currentState = existingEvents.reduce<State>(\n decider.evolve,\n decider.initialState(),\n );\n\n return decider.decide(command, currentState);\n };\n\n return {\n then: (expectedEvents: Event | Event[]): void => {\n const resultEvents = handle();\n\n const resultEventsArray = Array.isArray(resultEvents)\n ? resultEvents\n : [resultEvents];\n\n const expectedEventsArray = Array.isArray(expectedEvents)\n ? expectedEvents\n : [expectedEvents];\n\n assert.deepEqual(resultEventsArray, expectedEventsArray);\n },\n thenThrows: <Error>(check?: (error: Error) => boolean): void => {\n try {\n handle();\n assert.fail('Handler did not fail as expected');\n } catch (error) {\n if (check) assert.ok(check(error as Error));\n }\n },\n };\n },\n };\n };\n }\n },\n};\n","/* eslint-disable @typescript-eslint/no-floating-promises */\nimport assert from 'node:assert';\nimport { randomUUID } from 'node:crypto';\nimport { after, before, describe, it } from 'node:test';\nimport type { EventStore } from '../eventStore';\nimport {\n evolve,\n getInitialState,\n type PricedProductItem,\n type ShoppingCartEvent,\n} from './shoppingCart.domain';\n\ntype TestOptions = {\n getInitialIndex: () => bigint;\n teardownHook?: () => Promise<void>;\n};\n\nexport type EventStoreFactory = () => Promise<EventStore<bigint>>;\n\nexport async function testAggregateStream(\n eventStoreFactory: EventStoreFactory,\n options: TestOptions = {\n getInitialIndex: () => 1n,\n },\n) {\n return describe('aggregateStream', () => {\n let eventStore: EventStore<bigint>;\n\n before(async () => {\n eventStore = await eventStoreFactory();\n });\n\n after(async () => {\n const teardownHook = options.teardownHook;\n if (teardownHook) await teardownHook();\n });\n\n it('When called with `to` allows time traveling', async () => {\n // Given\n const productItem: PricedProductItem = {\n productId: '123',\n quantity: 10,\n price: 3,\n };\n const discount = 10;\n const shoppingCartId = randomUUID();\n\n await eventStore.appendToStream<ShoppingCartEvent>(shoppingCartId, [\n { type: 'ProductItemAdded', data: { productItem } },\n ]);\n await eventStore.appendToStream<ShoppingCartEvent>(shoppingCartId, [\n { type: 'ProductItemAdded', data: { productItem } },\n ]);\n await eventStore.appendToStream<ShoppingCartEvent>(shoppingCartId, [\n { type: 'DiscountApplied', data: { percent: discount } },\n ]);\n\n // when\n const resultAt1 = await eventStore.aggregateStream(shoppingCartId, {\n evolve,\n getInitialState,\n read: { to: 1n },\n });\n const resultAt2 = await eventStore.aggregateStream(shoppingCartId, {\n evolve,\n getInitialState,\n read: { to: 2n },\n });\n const resultAt3 = await eventStore.aggregateStream(shoppingCartId, {\n evolve,\n getInitialState,\n read: { to: 3n },\n });\n\n // then\n assert.ok(resultAt1);\n assert.ok(resultAt2);\n assert.ok(resultAt3);\n\n assert.equal(resultAt1.currentStreamVersion, options.getInitialIndex());\n assert.deepEqual(resultAt1.state, {\n productItems: [productItem],\n totalAmount: 30,\n });\n\n assert.equal(\n resultAt2.currentStreamVersion,\n options.getInitialIndex() + 1n,\n );\n assert.deepEqual(resultAt2.state, {\n productItems: [productItem, productItem],\n totalAmount: 60,\n });\n\n assert.equal(\n resultAt3.currentStreamVersion,\n options.getInitialIndex() + 2n,\n );\n assert.deepEqual(resultAt3.state, {\n productItems: [productItem, productItem],\n totalAmount: 54,\n });\n });\n });\n}\n","import { randomUUID } from 'crypto';\nimport type { Event } from '../typing';\nimport {\n type AggregateStreamOptions,\n type AggregateStreamResult,\n type AppendToStreamOptions,\n type AppendToStreamResult,\n type EventStore,\n type ReadStreamOptions,\n type ReadStreamResult,\n} from './eventStore';\nimport { assertExpectedVersionMatchesCurrent } from './expectedVersion';\n\nexport type EventMetadata = Readonly<{\n eventId: string;\n streamPosition: number;\n logPosition: bigint;\n}>;\n\nexport type EventEnvelope<E extends Event = Event> = {\n event: E;\n metadata: EventMetadata;\n};\n\nexport type EventHandler<E extends Event = Event> = (\n eventEnvelope: EventEnvelope<E>,\n) => void;\n\nexport const getInMemoryEventStore = (): EventStore => {\n const streams = new Map<string, EventEnvelope[]>();\n\n const getAllEventsCount = () => {\n return Array.from<EventEnvelope[]>(streams.values())\n .map((s) => s.length)\n .reduce((p, c) => p + c, 0);\n };\n\n return {\n async aggregateStream<State, EventType extends Event>(\n streamName: string,\n options: AggregateStreamOptions<State, EventType>,\n ): Promise<AggregateStreamResult<State> | null> {\n const { evolve, getInitialState, read } = options;\n\n const result = await this.readStream<EventType>(streamName, read);\n\n if (!result) return null;\n\n const events = result?.events ?? [];\n\n return {\n currentStreamVersion: BigInt(events.length),\n state: events.reduce(evolve, getInitialState()),\n };\n },\n\n readStream: <EventType extends Event>(\n streamName: string,\n options?: ReadStreamOptions,\n ): Promise<ReadStreamResult<EventType>> => {\n const events = streams.get(streamName);\n const currentStreamVersion = events ? BigInt(events.length) : undefined;\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n options?.expectedStreamVersion,\n );\n\n const from = Number(options && 'from' in options ? options.from : 0);\n const to = Number(\n options && 'to' in options\n ? options.to\n : options && 'maxCount' in options && options.maxCount\n ? options.from + options.maxCount\n : events?.length ?? 1,\n );\n\n const resultEvents =\n events && events.length > 0\n ? events.map((e) => e.event as EventType).slice(from, to)\n : [];\n\n const result: ReadStreamResult<EventType> =\n events && events.length > 0\n ? {\n currentStreamVersion: currentStreamVersion!,\n events: resultEvents,\n }\n : null;\n\n return Promise.resolve(result);\n },\n\n appendToStream: <EventType extends Event>(\n streamName: string,\n events: EventType[],\n options?: AppendToStreamOptions,\n ): Promise<AppendToStreamResult> => {\n const currentEvents = streams.get(streamName) ?? [];\n const currentStreamVersion =\n currentEvents.length > 0 ? BigInt(currentEvents.length) : undefined;\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n options?.expectedStreamVersion,\n );\n\n const eventEnvelopes: EventEnvelope[] = events.map((event, index) => {\n return {\n event,\n metadata: {\n eventId: randomUUID(),\n streamPosition: currentEvents.length + index + 1,\n logPosition: BigInt(getAllEventsCount() + index + 1),\n },\n };\n });\n\n const positionOfLastEventInTheStream = BigInt(\n eventEnvelopes.slice(-1)[0]!.metadata.streamPosition,\n );\n\n streams.set(streamName, [...currentEvents, ...eventEnvelopes]);\n\n const result: AppendToStreamResult = {\n nextExpectedStreamVersion: positionOfLastEventInTheStream,\n };\n\n return Promise.resolve(result);\n },\n };\n};\n"],"mappings":"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","names":["merge","array","item","where","onExisting","onNotFound","wasFound","result","p","isSubset","superObj","subObj","sup","sub","ele","assertMatches","actual","expected","EmmettError","_EmmettError","options","errorCode","isNumber","message","isString","ValidationError","_ValidationError","EmmettError","message","IllegalStateError","_IllegalStateError","ValidationErrors","isNumber","val","isString","assertNotEmptyString","value","ValidationError","assertPositiveNumber","assertUnsignedBigInt","number","STREAM_DOES_NOT_EXIST","NO_CONCURRENCY_CHECK","CommandHandler","evolve","getInitialState","mapToStreamId","id","eventStore","handle","options","streamName","aggregationResult","NO_CONCURRENCY_CHECK","state","currentStreamVersion","result","newEvents","expectedStreamVersion","STREAM_DOES_NOT_EXIST","DeciderCommandHandler","decide","evolve","getInitialState","mapToStreamId","id","eventStore","command","options","CommandHandler","state","assert","assert","randomUUID","after","before","describe","it","randomUUID"]}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }var _chunkKVWDIWFZjs = require('./chunk-KVWDIWFZ.js');var _chunkZWOSOI7Zjs = require('./chunk-ZWOSOI7Z.js');require('express');var _strict = require('assert/strict'); var _strict2 = _interopRequireDefault(_strict);var _supertest = require('supertest'); var _supertest2 = _interopRequireDefault(_supertest);var b=(t,e)=>[t,e],h= exports.b =(t,e)=>[t,e],R= exports.c =(t,e)=>[t,e],d= exports.d =(t,e)=>r=>{let{body:s,headers:o}=_nullishCoalesce(e, () => ({}));_strict2.default.equal(r.statusCode,t),s&&_chunkZWOSOI7Zjs.b.call(void 0, r.body,s),o&&_chunkZWOSOI7Zjs.b.call(void 0, r.headers,o)},w= exports.e =(t,e)=>d(t,e?{body:e}:void 0),V= exports.f ={for:(t,e)=>(...r)=>{let s=_chunkKVWDIWFZjs.a.call(void 0, t()),o=e(s);return{when:E=>{let y=async()=>{for(let[n,p]of r)await s.setup(n,p);return E(_supertest2.default.call(void 0, o))};return{then:async n=>{let p=await y();if(typeof n=="function")n(p)===!1&&_strict2.default.fail();else if(Array.isArray(n)){let[i,...m]=n;typeof i=="function"&&i(p)===!1&&_strict2.default.fail();let T=typeof i=="function"?m:n;_chunkZWOSOI7Zjs.b.call(void 0, Array.from(s.appendedEvents.values()),T)}}}}}}};exports.a = b; exports.b = h; exports.c = R; exports.d = d; exports.e = w; exports.f = V;
2
- //# sourceMappingURL=chunk-Y7SZXFJ2.js.map
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }var _chunkKVWDIWFZjs = require('./chunk-KVWDIWFZ.js');var _chunkDA5J4ET5js = require('./chunk-DA5J4ET5.js');require('express');var _strict = require('assert/strict'); var _strict2 = _interopRequireDefault(_strict);var _supertest = require('supertest'); var _supertest2 = _interopRequireDefault(_supertest);var b=(t,e)=>[t,e],h= exports.b =(t,e)=>[t,e],R= exports.c =(t,e)=>[t,e],d= exports.d =(t,e)=>r=>{let{body:s,headers:o}=_nullishCoalesce(e, () => ({}));_strict2.default.equal(r.statusCode,t),s&&_chunkDA5J4ET5js.b.call(void 0, r.body,s),o&&_chunkDA5J4ET5js.b.call(void 0, r.headers,o)},w= exports.e =(t,e)=>d(t,e?{body:e}:void 0),V= exports.f ={for:(t,e)=>(...r)=>{let s=_chunkKVWDIWFZjs.a.call(void 0, t()),o=e(s);return{when:E=>{let y=async()=>{for(let[n,p]of r)await s.setup(n,p);return E(_supertest2.default.call(void 0, o))};return{then:async n=>{let p=await y();if(typeof n=="function")n(p)===!1&&_strict2.default.fail();else if(Array.isArray(n)){let[i,...m]=n;typeof i=="function"&&i(p)===!1&&_strict2.default.fail();let T=typeof i=="function"?m:n;_chunkDA5J4ET5js.b.call(void 0, Array.from(s.appendedEvents.values()),T)}}}}}}};exports.a = b; exports.b = h; exports.c = R; exports.d = d; exports.e = w; exports.f = V;
2
+ //# sourceMappingURL=chunk-MEK5AIAJ.js.map
@@ -0,0 +1,2 @@
1
+ import{c as R,d as c,e as l,f as r}from"./chunk-3ECNKSAE.mjs";import{e as m}from"./chunk-KIRBEYFF.mjs";import"express";import"express-async-errors";import a,{Router as y}from"express";import"express-async-errors";import O from"http";import{ProblemDocument as f}from"http-problem-details";var u=e=>(t,o,s,i)=>{let p;e&&(p=e(t,o)),p=p??P(t),r(s,p.status,{problem:p})},P=e=>{let t=500;return"errorCode"in e&&m(e.errorCode)&&e.errorCode>=100&&e.errorCode<600&&(t=e.errorCode),new f({detail:e.message,status:t})};var N=e=>{let t=a(),{apis:o,mapError:s,enableDefaultExpressEtag:i,disableJsonMiddleware:p,disableUrlEncodingMiddleware:b,disableProblemDetailsMiddleware:x}=e,d=y();t.set("etag",i??!1),p||t.use(a.json()),b||t.use(a.urlencoded({extended:!0}));for(let H of o)H(d);return t.use(d),x||t.use(u(s)),t},v=(e,t={port:3e3})=>{let{port:o}=t,s=O.createServer(e);return s.on("listening",()=>{console.info("server up listening")}),s.listen(o)};var K=e=>async(t,o,s)=>(await Promise.resolve(e(t)))(o),k=e=>t=>{l(t,200,e)},z=e=>t=>{R(t,e)},G=e=>t=>{c(t,e)},L=e=>A(204,e),A=(e,t)=>o=>{l(o,e,t)},Q=e=>n(400,e),V=e=>n(403,e),X=e=>n(404,e),Y=e=>n(409,e),Z=e=>n(412,e),n=(e,t)=>o=>{r(o,e,t)};export{K as a,k as b,z as c,G as d,L as e,A as f,Q as g,V as h,X as i,Y as j,Z as k,n as l,u as m,P as n,N as o,v as p};
2
+ //# sourceMappingURL=chunk-OAYYW4GF.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/handler.ts","../src/index.ts","../src/application.ts","../src/middlewares/problemDetailsMiddleware.ts"],"sourcesContent":["import { type NextFunction, type Request, type Response } from 'express';\nimport {\n send,\n sendAccepted,\n sendCreated,\n sendProblem,\n type AcceptedHttpResponseOptions,\n type CreatedHttpResponseOptions,\n type HttpProblemResponseOptions,\n type HttpResponseOptions,\n type NoContentHttpResponseOptions,\n} from '.';\n\n// #region httpresponse-on\nexport type HttpResponse = (response: Response) => void;\n\nexport type HttpHandler<RequestType extends Request> = (\n request: RequestType,\n) => Promise<HttpResponse> | HttpResponse;\n\nexport const on =\n <RequestType extends Request>(handle: HttpHandler<RequestType>) =>\n async (\n request: RequestType,\n response: Response,\n _next: NextFunction,\n ): Promise<void> => {\n const setResponse = await Promise.resolve(handle(request));\n\n return setResponse(response);\n };\n// #endregion httpresponse-on\n\nexport const OK =\n (options?: HttpResponseOptions): HttpResponse =>\n (response: Response) => {\n send(response, 200, options);\n };\n\nexport const Created =\n (options: CreatedHttpResponseOptions): HttpResponse =>\n (response: Response) => {\n sendCreated(response, options);\n };\n\nexport const Accepted =\n (options: AcceptedHttpResponseOptions): HttpResponse =>\n (response: Response) => {\n sendAccepted(response, options);\n };\n\nexport const NoContent = (\n options?: NoContentHttpResponseOptions,\n): HttpResponse => HttpResponse(204, options);\n\nexport const HttpResponse =\n (statusCode: number, options?: HttpResponseOptions): HttpResponse =>\n (response: Response) => {\n send(response, statusCode, options);\n };\n\n/////////////////////\n// ERRORS\n/////////////////////\n\nexport const BadRequest = (\n options?: HttpProblemResponseOptions,\n): HttpResponse => HttpProblem(400, options);\n\nexport const Forbidden = (options?: HttpProblemResponseOptions): HttpResponse =>\n HttpProblem(403, options);\n\nexport const NotFound = (options?: HttpProblemResponseOptions): HttpResponse =>\n HttpProblem(404, options);\n\nexport const Conflict = (options?: HttpProblemResponseOptions): HttpResponse =>\n HttpProblem(409, options);\n\nexport const PreconditionFailed = (\n options: HttpProblemResponseOptions,\n): HttpResponse => HttpProblem(412, options);\n\nexport const HttpProblem =\n (statusCode: number, options?: HttpProblemResponseOptions): HttpResponse =>\n (response: Response) => {\n sendProblem(response, statusCode, options);\n };\n","import 'express-async-errors';\n\nexport * from './application';\nexport * from './etag';\nexport * from './handler';\nexport * from './responses';\nexport * from './testing';\n","import express, { Router, type Application } from 'express';\nimport 'express-async-errors';\nimport http from 'http';\nimport { problemDetailsMiddleware } from './middlewares/problemDetailsMiddleware';\nimport type { ErrorToProblemDetailsMapping } from './responses';\n\n// #region web-api-setup\nexport type WebApiSetup = (router: Router) => void;\n// #endregion web-api-setup\n\nexport type ApplicationOptions = {\n apis: WebApiSetup[];\n mapError?: ErrorToProblemDetailsMapping;\n enableDefaultExpressEtag?: boolean;\n disableJsonMiddleware?: boolean;\n disableUrlEncodingMiddleware?: boolean;\n disableProblemDetailsMiddleware?: boolean;\n};\n\nexport const getApplication = (options: ApplicationOptions) => {\n const app: Application = express();\n\n const {\n apis,\n mapError,\n enableDefaultExpressEtag,\n disableJsonMiddleware,\n disableUrlEncodingMiddleware,\n disableProblemDetailsMiddleware,\n } = options;\n\n const router = Router();\n\n // disabling default etag behaviour\n // to use etags in if-match and if-not-match headers\n app.set('etag', enableDefaultExpressEtag ?? false);\n\n // add json middleware\n if (!disableJsonMiddleware) app.use(express.json());\n\n // enable url encoded urls and bodies\n if (!disableUrlEncodingMiddleware)\n app.use(\n express.urlencoded({\n extended: true,\n }),\n );\n\n for (const api of apis) {\n api(router);\n }\n app.use(router);\n\n // add problem details middleware\n if (!disableProblemDetailsMiddleware)\n app.use(problemDetailsMiddleware(mapError));\n\n return app;\n};\n\nexport type StartApiOptions = {\n port?: number;\n};\n\nexport const startAPI = (\n app: Application,\n options: StartApiOptions = { port: 3000 },\n) => {\n const { port } = options;\n const server = http.createServer(app);\n\n server.on('listening', () => {\n console.info('server up listening');\n });\n\n return server.listen(port);\n};\n","import { EmmettError } from '@event-driven-io/emmett';\nimport type { NextFunction, Request, Response } from 'express';\nimport { ProblemDocument } from 'http-problem-details';\nimport { sendProblem, type ErrorToProblemDetailsMapping } from '..';\n\nexport const problemDetailsMiddleware =\n (mapError?: ErrorToProblemDetailsMapping) =>\n (\n error: Error,\n request: Request,\n response: Response,\n _next: NextFunction,\n ): void => {\n let problemDetails: ProblemDocument | undefined;\n\n if (mapError) problemDetails = mapError(error, request);\n\n problemDetails =\n problemDetails ?? defaulErrorToProblemDetailsMapping(error);\n\n sendProblem(response, problemDetails.status, { problem: problemDetails });\n };\n\nexport const defaulErrorToProblemDetailsMapping = (\n error: Error,\n): ProblemDocument => {\n let statusCode = 500;\n\n if (error instanceof EmmettError) {\n statusCode = error.errorCode;\n }\n\n return new ProblemDocument({\n detail: error.message,\n status: statusCode,\n });\n};\n"],"mappings":"uGAAA,MAA+D,UCA/D,MAAO,uBCAP,OAAOA,GAAW,UAAAC,MAAgC,UAClD,MAAO,uBACP,OAAOC,MAAU,OCAjB,OAAS,mBAAAC,MAAuB,uBAGzB,IAAMC,EACVC,GACD,CACEC,EACAC,EACAC,EACAC,IACS,CACT,IAAIC,EAEAL,IAAUK,EAAiBL,EAASC,EAAOC,CAAO,GAEtDG,EACEA,GAAkBC,EAAmCL,CAAK,EAE5DM,EAAYJ,EAAUE,EAAe,OAAQ,CAAE,QAASA,CAAe,CAAC,CAC1E,EAEWC,EACXL,GACoB,CACpB,IAAIO,EAAa,IAEjB,OAAIP,aAAiBQ,IACnBD,EAAaP,EAAM,WAGd,IAAIS,EAAgB,CACzB,OAAQT,EAAM,QACd,OAAQO,CACV,CAAC,CACH,EDjBO,IAAMG,EAAkBC,GAAgC,CAC7D,IAAMC,EAAmBC,EAAQ,EAE3B,CACJ,KAAAC,EACA,SAAAC,EACA,yBAAAC,EACA,sBAAAC,EACA,6BAAAC,EACA,gCAAAC,CACF,EAAIR,EAEES,EAASC,EAAO,EAItBT,EAAI,IAAI,OAAQI,GAA4B,EAAK,EAG5CC,GAAuBL,EAAI,IAAIC,EAAQ,KAAK,CAAC,EAG7CK,GACHN,EAAI,IACFC,EAAQ,WAAW,CACjB,SAAU,EACZ,CAAC,CACH,EAEF,QAAWS,KAAOR,EAChBQ,EAAIF,CAAM,EAEZ,OAAAR,EAAI,IAAIQ,CAAM,EAGTD,GACHP,EAAI,IAAIW,EAAyBR,CAAQ,CAAC,EAErCH,CACT,EAMaY,EAAW,CACtBZ,EACAD,EAA2B,CAAE,KAAM,GAAK,IACrC,CACH,GAAM,CAAE,KAAAc,CAAK,EAAId,EACXe,EAASC,EAAK,aAAaf,CAAG,EAEpC,OAAAc,EAAO,GAAG,YAAa,IAAM,CAC3B,QAAQ,KAAK,qBAAqB,CACpC,CAAC,EAEMA,EAAO,OAAOD,CAAI,CAC3B,EFxDO,IAAMG,EACmBC,GAC9B,MACEC,EACAC,EACAC,KAEoB,MAAM,QAAQ,QAAQH,EAAOC,CAAO,CAAC,GAEtCC,CAAQ,EAIlBE,EACVC,GACAH,GAAuB,CACtBI,EAAKJ,EAAU,IAAKG,CAAO,CAC7B,EAEWE,EACVF,GACAH,GAAuB,CACtBM,EAAYN,EAAUG,CAAO,CAC/B,EAEWI,EACVJ,GACAH,GAAuB,CACtBQ,EAAaR,EAAUG,CAAO,CAChC,EAEWM,EACXN,GACiBO,EAAa,IAAKP,CAAO,EAE/BO,EACX,CAACC,EAAoBR,IACpBH,GAAuB,CACtBI,EAAKJ,EAAUW,EAAYR,CAAO,CACpC,EAMWS,EACXT,GACiBU,EAAY,IAAKV,CAAO,EAE9BW,EAAaX,GACxBU,EAAY,IAAKV,CAAO,EAEbY,EAAYZ,GACvBU,EAAY,IAAKV,CAAO,EAEba,EAAYb,GACvBU,EAAY,IAAKV,CAAO,EAEbc,EACXd,GACiBU,EAAY,IAAKV,CAAO,EAE9BU,EACX,CAACF,EAAoBR,IACpBH,GAAuB,CACtBkB,EAAYlB,EAAUW,EAAYR,CAAO,CAC3C","names":["express","Router","http","ProblemDocument","problemDetailsMiddleware","mapError","error","request","response","_next","problemDetails","defaulErrorToProblemDetailsMapping","sendProblem","statusCode","s","ProblemDocument","getApplication","options","app","express","apis","mapError","enableDefaultExpressEtag","disableJsonMiddleware","disableUrlEncodingMiddleware","disableProblemDetailsMiddleware","router","Router","api","problemDetailsMiddleware","startAPI","port","server","http","on","handle","request","response","_next","OK","options","send","Created","sendCreated","Accepted","sendAccepted","NoContent","HttpResponse","statusCode","BadRequest","HttpProblem","Forbidden","NotFound","Conflict","PreconditionFailed","sendProblem"]}
1
+ {"version":3,"sources":["../src/handler.ts","../src/index.ts","../src/application.ts","../src/middlewares/problemDetailsMiddleware.ts"],"sourcesContent":["import { type NextFunction, type Request, type Response } from 'express';\nimport {\n send,\n sendAccepted,\n sendCreated,\n sendProblem,\n type AcceptedHttpResponseOptions,\n type CreatedHttpResponseOptions,\n type HttpProblemResponseOptions,\n type HttpResponseOptions,\n type NoContentHttpResponseOptions,\n} from '.';\n\n// #region httpresponse-on\nexport type HttpResponse = (response: Response) => void;\n\nexport type HttpHandler<RequestType extends Request> = (\n request: RequestType,\n) => Promise<HttpResponse> | HttpResponse;\n\nexport const on =\n <RequestType extends Request>(handle: HttpHandler<RequestType>) =>\n async (\n request: RequestType,\n response: Response,\n _next: NextFunction,\n ): Promise<void> => {\n const setResponse = await Promise.resolve(handle(request));\n\n return setResponse(response);\n };\n// #endregion httpresponse-on\n\nexport const OK =\n (options?: HttpResponseOptions): HttpResponse =>\n (response: Response) => {\n send(response, 200, options);\n };\n\nexport const Created =\n (options: CreatedHttpResponseOptions): HttpResponse =>\n (response: Response) => {\n sendCreated(response, options);\n };\n\nexport const Accepted =\n (options: AcceptedHttpResponseOptions): HttpResponse =>\n (response: Response) => {\n sendAccepted(response, options);\n };\n\nexport const NoContent = (\n options?: NoContentHttpResponseOptions,\n): HttpResponse => HttpResponse(204, options);\n\nexport const HttpResponse =\n (statusCode: number, options?: HttpResponseOptions): HttpResponse =>\n (response: Response) => {\n send(response, statusCode, options);\n };\n\n/////////////////////\n// ERRORS\n/////////////////////\n\nexport const BadRequest = (\n options?: HttpProblemResponseOptions,\n): HttpResponse => HttpProblem(400, options);\n\nexport const Forbidden = (options?: HttpProblemResponseOptions): HttpResponse =>\n HttpProblem(403, options);\n\nexport const NotFound = (options?: HttpProblemResponseOptions): HttpResponse =>\n HttpProblem(404, options);\n\nexport const Conflict = (options?: HttpProblemResponseOptions): HttpResponse =>\n HttpProblem(409, options);\n\nexport const PreconditionFailed = (\n options: HttpProblemResponseOptions,\n): HttpResponse => HttpProblem(412, options);\n\nexport const HttpProblem =\n (statusCode: number, options?: HttpProblemResponseOptions): HttpResponse =>\n (response: Response) => {\n sendProblem(response, statusCode, options);\n };\n","import 'express-async-errors';\n\nexport * from './application';\nexport * from './etag';\nexport * from './handler';\nexport * from './responses';\nexport * from './testing';\n","import express, { Router, type Application } from 'express';\nimport 'express-async-errors';\nimport http from 'http';\nimport { problemDetailsMiddleware } from './middlewares/problemDetailsMiddleware';\nimport type { ErrorToProblemDetailsMapping } from './responses';\n\n// #region web-api-setup\nexport type WebApiSetup = (router: Router) => void;\n// #endregion web-api-setup\n\nexport type ApplicationOptions = {\n apis: WebApiSetup[];\n mapError?: ErrorToProblemDetailsMapping;\n enableDefaultExpressEtag?: boolean;\n disableJsonMiddleware?: boolean;\n disableUrlEncodingMiddleware?: boolean;\n disableProblemDetailsMiddleware?: boolean;\n};\n\nexport const getApplication = (options: ApplicationOptions) => {\n const app: Application = express();\n\n const {\n apis,\n mapError,\n enableDefaultExpressEtag,\n disableJsonMiddleware,\n disableUrlEncodingMiddleware,\n disableProblemDetailsMiddleware,\n } = options;\n\n const router = Router();\n\n // disabling default etag behaviour\n // to use etags in if-match and if-not-match headers\n app.set('etag', enableDefaultExpressEtag ?? false);\n\n // add json middleware\n if (!disableJsonMiddleware) app.use(express.json());\n\n // enable url encoded urls and bodies\n if (!disableUrlEncodingMiddleware)\n app.use(\n express.urlencoded({\n extended: true,\n }),\n );\n\n for (const api of apis) {\n api(router);\n }\n app.use(router);\n\n // add problem details middleware\n if (!disableProblemDetailsMiddleware)\n app.use(problemDetailsMiddleware(mapError));\n\n return app;\n};\n\nexport type StartApiOptions = {\n port?: number;\n};\n\nexport const startAPI = (\n app: Application,\n options: StartApiOptions = { port: 3000 },\n) => {\n const { port } = options;\n const server = http.createServer(app);\n\n server.on('listening', () => {\n console.info('server up listening');\n });\n\n return server.listen(port);\n};\n","import { isNumber } from '@event-driven-io/emmett';\nimport type { NextFunction, Request, Response } from 'express';\nimport { ProblemDocument } from 'http-problem-details';\nimport { sendProblem, type ErrorToProblemDetailsMapping } from '..';\n\nexport const problemDetailsMiddleware =\n (mapError?: ErrorToProblemDetailsMapping) =>\n (\n error: Error,\n request: Request,\n response: Response,\n _next: NextFunction,\n ): void => {\n let problemDetails: ProblemDocument | undefined;\n\n if (mapError) problemDetails = mapError(error, request);\n\n problemDetails =\n problemDetails ?? defaulErrorToProblemDetailsMapping(error);\n\n sendProblem(response, problemDetails.status, { problem: problemDetails });\n };\n\nexport const defaulErrorToProblemDetailsMapping = (\n error: Error,\n): ProblemDocument => {\n let statusCode = 500;\n\n if (\n 'errorCode' in error &&\n isNumber(error.errorCode) &&\n error.errorCode >= 100 &&\n error.errorCode < 600\n ) {\n statusCode = error.errorCode;\n }\n\n return new ProblemDocument({\n detail: error.message,\n status: statusCode,\n });\n};\n"],"mappings":"uGAAA,MAA+D,UCA/D,MAAO,uBCAP,OAAOA,GAAW,UAAAC,MAAgC,UAClD,MAAO,uBACP,OAAOC,MAAU,OCAjB,OAAS,mBAAAC,MAAuB,uBAGzB,IAAMC,EACVC,GACD,CACEC,EACAC,EACAC,EACAC,IACS,CACT,IAAIC,EAEAL,IAAUK,EAAiBL,EAASC,EAAOC,CAAO,GAEtDG,EACEA,GAAkBC,EAAmCL,CAAK,EAE5DM,EAAYJ,EAAUE,EAAe,OAAQ,CAAE,QAASA,CAAe,CAAC,CAC1E,EAEWC,EACXL,GACoB,CACpB,IAAIO,EAAa,IAEjB,MACE,cAAeP,GACfQ,EAASR,EAAM,SAAS,GACxBA,EAAM,WAAa,KACnBA,EAAM,UAAY,MAElBO,EAAaP,EAAM,WAGd,IAAIS,EAAgB,CACzB,OAAQT,EAAM,QACd,OAAQO,CACV,CAAC,CACH,EDtBO,IAAMG,EAAkBC,GAAgC,CAC7D,IAAMC,EAAmBC,EAAQ,EAE3B,CACJ,KAAAC,EACA,SAAAC,EACA,yBAAAC,EACA,sBAAAC,EACA,6BAAAC,EACA,gCAAAC,CACF,EAAIR,EAEES,EAASC,EAAO,EAItBT,EAAI,IAAI,OAAQI,GAA4B,EAAK,EAG5CC,GAAuBL,EAAI,IAAIC,EAAQ,KAAK,CAAC,EAG7CK,GACHN,EAAI,IACFC,EAAQ,WAAW,CACjB,SAAU,EACZ,CAAC,CACH,EAEF,QAAWS,KAAOR,EAChBQ,EAAIF,CAAM,EAEZ,OAAAR,EAAI,IAAIQ,CAAM,EAGTD,GACHP,EAAI,IAAIW,EAAyBR,CAAQ,CAAC,EAErCH,CACT,EAMaY,EAAW,CACtBZ,EACAD,EAA2B,CAAE,KAAM,GAAK,IACrC,CACH,GAAM,CAAE,KAAAc,CAAK,EAAId,EACXe,EAASC,EAAK,aAAaf,CAAG,EAEpC,OAAAc,EAAO,GAAG,YAAa,IAAM,CAC3B,QAAQ,KAAK,qBAAqB,CACpC,CAAC,EAEMA,EAAO,OAAOD,CAAI,CAC3B,EFxDO,IAAMG,EACmBC,GAC9B,MACEC,EACAC,EACAC,KAEoB,MAAM,QAAQ,QAAQH,EAAOC,CAAO,CAAC,GAEtCC,CAAQ,EAIlBE,EACVC,GACAH,GAAuB,CACtBI,EAAKJ,EAAU,IAAKG,CAAO,CAC7B,EAEWE,EACVF,GACAH,GAAuB,CACtBM,EAAYN,EAAUG,CAAO,CAC/B,EAEWI,EACVJ,GACAH,GAAuB,CACtBQ,EAAaR,EAAUG,CAAO,CAChC,EAEWM,EACXN,GACiBO,EAAa,IAAKP,CAAO,EAE/BO,EACX,CAACC,EAAoBR,IACpBH,GAAuB,CACtBI,EAAKJ,EAAUW,EAAYR,CAAO,CACpC,EAMWS,EACXT,GACiBU,EAAY,IAAKV,CAAO,EAE9BW,EAAaX,GACxBU,EAAY,IAAKV,CAAO,EAEbY,EAAYZ,GACvBU,EAAY,IAAKV,CAAO,EAEba,EAAYb,GACvBU,EAAY,IAAKV,CAAO,EAEbc,EACXd,GACiBU,EAAY,IAAKV,CAAO,EAE9BU,EACX,CAACF,EAAoBR,IACpBH,GAAuB,CACtBkB,EAAYlB,EAAUW,EAAYR,CAAO,CAC3C","names":["express","Router","http","ProblemDocument","problemDetailsMiddleware","mapError","error","request","response","_next","problemDetails","defaulErrorToProblemDetailsMapping","sendProblem","statusCode","i","ProblemDocument","getApplication","options","app","express","apis","mapError","enableDefaultExpressEtag","disableJsonMiddleware","disableUrlEncodingMiddleware","disableProblemDetailsMiddleware","router","Router","api","problemDetailsMiddleware","startAPI","port","server","http","on","handle","request","response","_next","OK","options","send","Created","sendCreated","Accepted","sendAccepted","NoContent","HttpResponse","statusCode","BadRequest","HttpProblem","Forbidden","NotFound","Conflict","PreconditionFailed","sendProblem"]}
@@ -1,2 +1,2 @@
1
- import{b as C,c as d}from"./chunk-BPMP6GJ7.mjs";import{c as a,d as e}from"./chunk-HEPNAXF4.mjs";var S=(p=>(p.CART_ALREADY_EXISTS="CART_ALREADY_EXISTS",p.CART_IS_ALREADY_CLOSED="CART_IS_ALREADY_CLOSED",p.PRODUCT_ITEM_NOT_FOUND="PRODUCT_ITEM_NOT_FOUND",p.CART_IS_EMPTY="CART_IS_EMPTY",p.UNKNOWN_EVENT_TYPE="UNKNOWN_EVENT_TYPE",p.UNKNOWN_COMMAND_TYPE="UNKNOWN_COMMAND_TYPE",p))(S||{}),I=(o,{productId:t,quantity:r,unitPrice:n})=>{if((o.find(i=>i.productId===t&&i.unitPrice==n)?.quantity??0)<r)throw new e("PRODUCT_ITEM_NOT_FOUND")},g=({type:o,data:t},r)=>{switch(o){case"OpenShoppingCart":{if(r.status!=="Empty")throw new e("CART_ALREADY_EXISTS");return{type:"ShoppingCartOpened",data:{shoppingCartId:t.shoppingCartId,clientId:t.clientId,openedAt:t.now}}}case"AddProductItemToShoppingCart":{if(r.status!=="Pending")throw new e("CART_IS_ALREADY_CLOSED");return{type:"ProductItemAddedToShoppingCart",data:{shoppingCartId:t.shoppingCartId,productItem:t.productItem}}}case"RemoveProductItemFromShoppingCart":{if(r.status!=="Pending")throw new e("CART_IS_ALREADY_CLOSED");return I(r.productItems,t.productItem),{type:"ProductItemRemovedFromShoppingCart",data:{shoppingCartId:t.shoppingCartId,productItem:t.productItem}}}case"ConfirmShoppingCart":{if(r.status!=="Pending")throw new e("CART_IS_ALREADY_CLOSED");if(r.productItems.length===0)throw new e("CART_IS_EMPTY");return{type:"ShoppingCartConfirmed",data:{shoppingCartId:t.shoppingCartId,confirmedAt:t.now}}}case"CancelShoppingCart":{if(r.status!=="Pending")throw new e("CART_IS_ALREADY_CLOSED");return{type:"ShoppingCartCanceled",data:{shoppingCartId:t.shoppingCartId,canceledAt:t.now}}}default:{let n=t;throw new a("UNKNOWN_COMMAND_TYPE")}}},u={decide:g,evolve:d,getInitialState:()=>C};export{S as a,I as b,g as c,u as d};
2
- //# sourceMappingURL=chunk-6MY6WCJR.mjs.map
1
+ import{b as C,c as d}from"./chunk-BHGAXF2A.mjs";import{c as a,d as e}from"./chunk-KIRBEYFF.mjs";var S=(p=>(p.CART_ALREADY_EXISTS="CART_ALREADY_EXISTS",p.CART_IS_ALREADY_CLOSED="CART_IS_ALREADY_CLOSED",p.PRODUCT_ITEM_NOT_FOUND="PRODUCT_ITEM_NOT_FOUND",p.CART_IS_EMPTY="CART_IS_EMPTY",p.UNKNOWN_EVENT_TYPE="UNKNOWN_EVENT_TYPE",p.UNKNOWN_COMMAND_TYPE="UNKNOWN_COMMAND_TYPE",p))(S||{}),I=(o,{productId:t,quantity:r,unitPrice:n})=>{if((o.find(i=>i.productId===t&&i.unitPrice==n)?.quantity??0)<r)throw new e("PRODUCT_ITEM_NOT_FOUND")},g=({type:o,data:t},r)=>{switch(o){case"OpenShoppingCart":{if(r.status!=="Empty")throw new e("CART_ALREADY_EXISTS");return{type:"ShoppingCartOpened",data:{shoppingCartId:t.shoppingCartId,clientId:t.clientId,openedAt:t.now}}}case"AddProductItemToShoppingCart":{if(r.status!=="Pending")throw new e("CART_IS_ALREADY_CLOSED");return{type:"ProductItemAddedToShoppingCart",data:{shoppingCartId:t.shoppingCartId,productItem:t.productItem}}}case"RemoveProductItemFromShoppingCart":{if(r.status!=="Pending")throw new e("CART_IS_ALREADY_CLOSED");return I(r.productItems,t.productItem),{type:"ProductItemRemovedFromShoppingCart",data:{shoppingCartId:t.shoppingCartId,productItem:t.productItem}}}case"ConfirmShoppingCart":{if(r.status!=="Pending")throw new e("CART_IS_ALREADY_CLOSED");if(r.productItems.length===0)throw new e("CART_IS_EMPTY");return{type:"ShoppingCartConfirmed",data:{shoppingCartId:t.shoppingCartId,confirmedAt:t.now}}}case"CancelShoppingCart":{if(r.status!=="Pending")throw new e("CART_IS_ALREADY_CLOSED");return{type:"ShoppingCartCanceled",data:{shoppingCartId:t.shoppingCartId,canceledAt:t.now}}}default:{let n=t;throw new a("UNKNOWN_COMMAND_TYPE")}}},u={decide:g,evolve:d,getInitialState:()=>C};export{S as a,I as b,g as c,u as d};
2
+ //# sourceMappingURL=chunk-TP4BTDFZ.mjs.map
@@ -1,27 +1,12 @@
1
1
  import { ShoppingCart } from './shoppingCart.mjs';
2
- import { ShoppingCartCommand } from './businessLogic.mjs';
2
+ import * as _event_driven_io_emmett from '@event-driven-io/emmett';
3
3
  import { EventStore } from '@event-driven-io/emmett';
4
+ import { ShoppingCartCommand } from './businessLogic.mjs';
4
5
  import { Router } from 'express';
5
6
 
6
- type Flavour<K, T> = K & {
7
- readonly __brand?: T;
8
- };
9
-
10
- type ExpectedStreamVersion<VersionType = DefaultStreamVersionType> = ExpectedStreamVersionWithValue<VersionType> | ExpectedStreamVersionGeneral;
11
- type ExpectedStreamVersionWithValue<VersionType = DefaultStreamVersionType> = Flavour<VersionType, 'StreamVersion'>;
12
- type ExpectedStreamVersionGeneral = Flavour<'STREAM_EXISTS' | 'STREAM_DOES_NOT_EXIST' | 'NO_CONCURRENCY_CHECK', 'StreamVersion'>;
13
- type DefaultStreamVersionType = bigint;
14
- type AppendToStreamResult<StreamVersion = DefaultStreamVersionType> = {
15
- nextExpectedStreamVersion: StreamVersion;
16
- };
17
-
18
- type CommandHandlerResult<State, StreamVersion = DefaultStreamVersionType> = AppendToStreamResult<StreamVersion> & {
19
- newState: State;
20
- };
21
-
22
7
  declare const handle: (eventStore: EventStore<bigint>, id: string, command: ShoppingCartCommand, options?: {
23
- expectedStreamVersion?: ExpectedStreamVersion<bigint> | undefined;
24
- } | undefined) => Promise<CommandHandlerResult<ShoppingCart, bigint>>;
8
+ expectedStreamVersion?: _event_driven_io_emmett.ExpectedStreamVersion<bigint> | undefined;
9
+ } | undefined) => Promise<_event_driven_io_emmett.CommandHandlerResult<ShoppingCart, bigint>>;
25
10
  declare const shoppingCartApi: (eventStore: EventStore) => (router: Router) => void;
26
11
 
27
12
  export { handle, shoppingCartApi };
@@ -1,27 +1,12 @@
1
1
  import { ShoppingCart } from './shoppingCart.js';
2
- import { ShoppingCartCommand } from './businessLogic.js';
2
+ import * as _event_driven_io_emmett from '@event-driven-io/emmett';
3
3
  import { EventStore } from '@event-driven-io/emmett';
4
+ import { ShoppingCartCommand } from './businessLogic.js';
4
5
  import { Router } from 'express';
5
6
 
6
- type Flavour<K, T> = K & {
7
- readonly __brand?: T;
8
- };
9
-
10
- type ExpectedStreamVersion<VersionType = DefaultStreamVersionType> = ExpectedStreamVersionWithValue<VersionType> | ExpectedStreamVersionGeneral;
11
- type ExpectedStreamVersionWithValue<VersionType = DefaultStreamVersionType> = Flavour<VersionType, 'StreamVersion'>;
12
- type ExpectedStreamVersionGeneral = Flavour<'STREAM_EXISTS' | 'STREAM_DOES_NOT_EXIST' | 'NO_CONCURRENCY_CHECK', 'StreamVersion'>;
13
- type DefaultStreamVersionType = bigint;
14
- type AppendToStreamResult<StreamVersion = DefaultStreamVersionType> = {
15
- nextExpectedStreamVersion: StreamVersion;
16
- };
17
-
18
- type CommandHandlerResult<State, StreamVersion = DefaultStreamVersionType> = AppendToStreamResult<StreamVersion> & {
19
- newState: State;
20
- };
21
-
22
7
  declare const handle: (eventStore: EventStore<bigint>, id: string, command: ShoppingCartCommand, options?: {
23
- expectedStreamVersion?: ExpectedStreamVersion<bigint> | undefined;
24
- } | undefined) => Promise<CommandHandlerResult<ShoppingCart, bigint>>;
8
+ expectedStreamVersion?: _event_driven_io_emmett.ExpectedStreamVersion<bigint> | undefined;
9
+ } | undefined) => Promise<_event_driven_io_emmett.CommandHandlerResult<ShoppingCart, bigint>>;
25
10
  declare const shoppingCartApi: (eventStore: EventStore) => (router: Router) => void;
26
11
 
27
12
  export { handle, shoppingCartApi };
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkYC2DBBXWjs = require('../../chunk-YC2DBBXW.js');require('../../chunk-P7AA2K4Q.js');var _chunkUT7Q27E5js = require('../../chunk-UT7Q27E5.js');require('../../chunk-7H3QW2YD.js');require('../../chunk-VK264KTU.js');require('../../chunk-Y7SZXFJ2.js');require('../../chunk-KVWDIWFZ.js');require('../../chunk-NDXUB3PP.js');var _chunkE4DZPUJHjs = require('../../chunk-E4DZPUJH.js');var _chunkZWOSOI7Zjs = require('../../chunk-ZWOSOI7Z.js');require('express');var u=_chunkZWOSOI7Zjs.i.call(void 0, _chunkYC2DBBXWjs.d),P=o=>100,T= exports.shoppingCartApi =o=>i=>{i.post("/clients/:clientId/shopping-carts/",_chunkUT7Q27E5js.a.call(void 0, async t=>{let e=_chunkZWOSOI7Zjs.e.call(void 0, t.params.clientId),r=e,d=await u(o,r,{type:"OpenShoppingCart",data:{clientId:e,shoppingCartId:r,now:new Date}},{expectedStreamVersion:_chunkZWOSOI7Zjs.h});return _chunkUT7Q27E5js.c.call(void 0, {createdId:r,eTag:_chunkE4DZPUJHjs.f.call(void 0, d.nextExpectedStreamVersion)})})),i.post("/clients/:clientId/shopping-carts/:shoppingCartId/product-items",_chunkUT7Q27E5js.a.call(void 0, async t=>{let e=_chunkZWOSOI7Zjs.e.call(void 0, t.params.shoppingCartId),r={productId:_chunkZWOSOI7Zjs.e.call(void 0, t.body.productId),quantity:_chunkZWOSOI7Zjs.f.call(void 0, t.body.quantity)},d=P(r.productId),C=await u(o,e,{type:"AddProductItemToShoppingCart",data:{shoppingCartId:e,productItem:{...r,unitPrice:d}}},{expectedStreamVersion:_chunkZWOSOI7Zjs.g.call(void 0, _chunkE4DZPUJHjs.j.call(void 0, t))});return _chunkUT7Q27E5js.e.call(void 0, {eTag:_chunkE4DZPUJHjs.f.call(void 0, C.nextExpectedStreamVersion)})})),i.delete("/clients/:clientId/shopping-carts/:shoppingCartId/product-items",_chunkUT7Q27E5js.a.call(void 0, async t=>{let e=_chunkZWOSOI7Zjs.e.call(void 0, t.params.shoppingCartId),r={productId:_chunkZWOSOI7Zjs.e.call(void 0, t.query.productId),quantity:_chunkZWOSOI7Zjs.f.call(void 0, Number(t.query.quantity)),unitPrice:_chunkZWOSOI7Zjs.f.call(void 0, Number(t.query.unitPrice))},d=await u(o,e,{type:"RemoveProductItemFromShoppingCart",data:{shoppingCartId:e,productItem:r}},{expectedStreamVersion:_chunkZWOSOI7Zjs.g.call(void 0, _chunkE4DZPUJHjs.j.call(void 0, t))});return _chunkUT7Q27E5js.e.call(void 0, {eTag:_chunkE4DZPUJHjs.f.call(void 0, d.nextExpectedStreamVersion)})})),i.post("/clients/:clientId/shopping-carts/:shoppingCartId/confirm",_chunkUT7Q27E5js.a.call(void 0, async t=>{let e=_chunkZWOSOI7Zjs.e.call(void 0, t.params.shoppingCartId),r=await u(o,e,{type:"ConfirmShoppingCart",data:{shoppingCartId:e,now:new Date}},{expectedStreamVersion:_chunkZWOSOI7Zjs.g.call(void 0, _chunkE4DZPUJHjs.j.call(void 0, t))});return _chunkUT7Q27E5js.e.call(void 0, {eTag:_chunkE4DZPUJHjs.f.call(void 0, r.nextExpectedStreamVersion)})})),i.delete("/clients/:clientId/shopping-carts/:shoppingCartId",_chunkUT7Q27E5js.a.call(void 0, async t=>{let e=_chunkZWOSOI7Zjs.e.call(void 0, t.params.shoppingCartId),r=await u(o,e,{type:"CancelShoppingCart",data:{shoppingCartId:e,now:new Date}},{expectedStreamVersion:_chunkZWOSOI7Zjs.g.call(void 0, _chunkE4DZPUJHjs.j.call(void 0, t))});return _chunkUT7Q27E5js.e.call(void 0, {eTag:_chunkE4DZPUJHjs.f.call(void 0, r.nextExpectedStreamVersion)})}))};exports.handle = u; exports.shoppingCartApi = T;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunk2JWQPLZIjs = require('../../chunk-2JWQPLZI.js');require('../../chunk-5SQK7LQ2.js');var _chunkDLZ3WQUJjs = require('../../chunk-DLZ3WQUJ.js');require('../../chunk-7H3QW2YD.js');require('../../chunk-VK264KTU.js');require('../../chunk-MEK5AIAJ.js');require('../../chunk-KVWDIWFZ.js');require('../../chunk-NDXUB3PP.js');var _chunkE4DZPUJHjs = require('../../chunk-E4DZPUJH.js');var _chunkDA5J4ET5js = require('../../chunk-DA5J4ET5.js');require('express');var u=_chunkDA5J4ET5js.j.call(void 0, _chunk2JWQPLZIjs.d),P=o=>100,T= exports.shoppingCartApi =o=>i=>{i.post("/clients/:clientId/shopping-carts/",_chunkDLZ3WQUJjs.a.call(void 0, async t=>{let e=_chunkDA5J4ET5js.f.call(void 0, t.params.clientId),r=e,d=await u(o,r,{type:"OpenShoppingCart",data:{clientId:e,shoppingCartId:r,now:new Date}},{expectedStreamVersion:_chunkDA5J4ET5js.i});return _chunkDLZ3WQUJjs.c.call(void 0, {createdId:r,eTag:_chunkE4DZPUJHjs.f.call(void 0, d.nextExpectedStreamVersion)})})),i.post("/clients/:clientId/shopping-carts/:shoppingCartId/product-items",_chunkDLZ3WQUJjs.a.call(void 0, async t=>{let e=_chunkDA5J4ET5js.f.call(void 0, t.params.shoppingCartId),r={productId:_chunkDA5J4ET5js.f.call(void 0, t.body.productId),quantity:_chunkDA5J4ET5js.g.call(void 0, t.body.quantity)},d=P(r.productId),C=await u(o,e,{type:"AddProductItemToShoppingCart",data:{shoppingCartId:e,productItem:{...r,unitPrice:d}}},{expectedStreamVersion:_chunkDA5J4ET5js.h.call(void 0, _chunkE4DZPUJHjs.j.call(void 0, t))});return _chunkDLZ3WQUJjs.e.call(void 0, {eTag:_chunkE4DZPUJHjs.f.call(void 0, C.nextExpectedStreamVersion)})})),i.delete("/clients/:clientId/shopping-carts/:shoppingCartId/product-items",_chunkDLZ3WQUJjs.a.call(void 0, async t=>{let e=_chunkDA5J4ET5js.f.call(void 0, t.params.shoppingCartId),r={productId:_chunkDA5J4ET5js.f.call(void 0, t.query.productId),quantity:_chunkDA5J4ET5js.g.call(void 0, Number(t.query.quantity)),unitPrice:_chunkDA5J4ET5js.g.call(void 0, Number(t.query.unitPrice))},d=await u(o,e,{type:"RemoveProductItemFromShoppingCart",data:{shoppingCartId:e,productItem:r}},{expectedStreamVersion:_chunkDA5J4ET5js.h.call(void 0, _chunkE4DZPUJHjs.j.call(void 0, t))});return _chunkDLZ3WQUJjs.e.call(void 0, {eTag:_chunkE4DZPUJHjs.f.call(void 0, d.nextExpectedStreamVersion)})})),i.post("/clients/:clientId/shopping-carts/:shoppingCartId/confirm",_chunkDLZ3WQUJjs.a.call(void 0, async t=>{let e=_chunkDA5J4ET5js.f.call(void 0, t.params.shoppingCartId),r=await u(o,e,{type:"ConfirmShoppingCart",data:{shoppingCartId:e,now:new Date}},{expectedStreamVersion:_chunkDA5J4ET5js.h.call(void 0, _chunkE4DZPUJHjs.j.call(void 0, t))});return _chunkDLZ3WQUJjs.e.call(void 0, {eTag:_chunkE4DZPUJHjs.f.call(void 0, r.nextExpectedStreamVersion)})})),i.delete("/clients/:clientId/shopping-carts/:shoppingCartId",_chunkDLZ3WQUJjs.a.call(void 0, async t=>{let e=_chunkDA5J4ET5js.f.call(void 0, t.params.shoppingCartId),r=await u(o,e,{type:"CancelShoppingCart",data:{shoppingCartId:e,now:new Date}},{expectedStreamVersion:_chunkDA5J4ET5js.h.call(void 0, _chunkE4DZPUJHjs.j.call(void 0, t))});return _chunkDLZ3WQUJjs.e.call(void 0, {eTag:_chunkE4DZPUJHjs.f.call(void 0, r.nextExpectedStreamVersion)})}))};exports.handle = u; exports.shoppingCartApi = T;
2
2
  //# sourceMappingURL=api.js.map
@@ -1,2 +1,2 @@
1
- import{d as l}from"../../chunk-6MY6WCJR.mjs";import"../../chunk-BPMP6GJ7.mjs";import{a as p,c as h,e as m}from"../../chunk-3P6L3RAK.mjs";import"../../chunk-HKEQAT6F.mjs";import"../../chunk-2IUXL747.mjs";import"../../chunk-TJPUQYKV.mjs";import"../../chunk-42BDHECF.mjs";import"../../chunk-3ECNKSAE.mjs";import{f as a,j as c}from"../../chunk-GEU24YU2.mjs";import{e as n,f as I,g as s,h as g,i as y}from"../../chunk-HEPNAXF4.mjs";import"express";var u=y(l),P=o=>100,T=o=>i=>{i.post("/clients/:clientId/shopping-carts/",p(async t=>{let e=n(t.params.clientId),r=e,d=await u(o,r,{type:"OpenShoppingCart",data:{clientId:e,shoppingCartId:r,now:new Date}},{expectedStreamVersion:g});return h({createdId:r,eTag:a(d.nextExpectedStreamVersion)})})),i.post("/clients/:clientId/shopping-carts/:shoppingCartId/product-items",p(async t=>{let e=n(t.params.shoppingCartId),r={productId:n(t.body.productId),quantity:I(t.body.quantity)},d=P(r.productId),C=await u(o,e,{type:"AddProductItemToShoppingCart",data:{shoppingCartId:e,productItem:{...r,unitPrice:d}}},{expectedStreamVersion:s(c(t))});return m({eTag:a(C.nextExpectedStreamVersion)})})),i.delete("/clients/:clientId/shopping-carts/:shoppingCartId/product-items",p(async t=>{let e=n(t.params.shoppingCartId),r={productId:n(t.query.productId),quantity:I(Number(t.query.quantity)),unitPrice:I(Number(t.query.unitPrice))},d=await u(o,e,{type:"RemoveProductItemFromShoppingCart",data:{shoppingCartId:e,productItem:r}},{expectedStreamVersion:s(c(t))});return m({eTag:a(d.nextExpectedStreamVersion)})})),i.post("/clients/:clientId/shopping-carts/:shoppingCartId/confirm",p(async t=>{let e=n(t.params.shoppingCartId),r=await u(o,e,{type:"ConfirmShoppingCart",data:{shoppingCartId:e,now:new Date}},{expectedStreamVersion:s(c(t))});return m({eTag:a(r.nextExpectedStreamVersion)})})),i.delete("/clients/:clientId/shopping-carts/:shoppingCartId",p(async t=>{let e=n(t.params.shoppingCartId),r=await u(o,e,{type:"CancelShoppingCart",data:{shoppingCartId:e,now:new Date}},{expectedStreamVersion:s(c(t))});return m({eTag:a(r.nextExpectedStreamVersion)})}))};export{u as handle,T as shoppingCartApi};
1
+ import{d as l}from"../../chunk-TP4BTDFZ.mjs";import"../../chunk-BHGAXF2A.mjs";import{a as p,c as h,e as m}from"../../chunk-OAYYW4GF.mjs";import"../../chunk-HKEQAT6F.mjs";import"../../chunk-2IUXL747.mjs";import"../../chunk-IMSJF3JS.mjs";import"../../chunk-42BDHECF.mjs";import"../../chunk-3ECNKSAE.mjs";import{f as a,j as c}from"../../chunk-GEU24YU2.mjs";import{f as n,g as I,h as s,i as g,j as y}from"../../chunk-KIRBEYFF.mjs";import"express";var u=y(l),P=o=>100,T=o=>i=>{i.post("/clients/:clientId/shopping-carts/",p(async t=>{let e=n(t.params.clientId),r=e,d=await u(o,r,{type:"OpenShoppingCart",data:{clientId:e,shoppingCartId:r,now:new Date}},{expectedStreamVersion:g});return h({createdId:r,eTag:a(d.nextExpectedStreamVersion)})})),i.post("/clients/:clientId/shopping-carts/:shoppingCartId/product-items",p(async t=>{let e=n(t.params.shoppingCartId),r={productId:n(t.body.productId),quantity:I(t.body.quantity)},d=P(r.productId),C=await u(o,e,{type:"AddProductItemToShoppingCart",data:{shoppingCartId:e,productItem:{...r,unitPrice:d}}},{expectedStreamVersion:s(c(t))});return m({eTag:a(C.nextExpectedStreamVersion)})})),i.delete("/clients/:clientId/shopping-carts/:shoppingCartId/product-items",p(async t=>{let e=n(t.params.shoppingCartId),r={productId:n(t.query.productId),quantity:I(Number(t.query.quantity)),unitPrice:I(Number(t.query.unitPrice))},d=await u(o,e,{type:"RemoveProductItemFromShoppingCart",data:{shoppingCartId:e,productItem:r}},{expectedStreamVersion:s(c(t))});return m({eTag:a(d.nextExpectedStreamVersion)})})),i.post("/clients/:clientId/shopping-carts/:shoppingCartId/confirm",p(async t=>{let e=n(t.params.shoppingCartId),r=await u(o,e,{type:"ConfirmShoppingCart",data:{shoppingCartId:e,now:new Date}},{expectedStreamVersion:s(c(t))});return m({eTag:a(r.nextExpectedStreamVersion)})})),i.delete("/clients/:clientId/shopping-carts/:shoppingCartId",p(async t=>{let e=n(t.params.shoppingCartId),r=await u(o,e,{type:"CancelShoppingCart",data:{shoppingCartId:e,now:new Date}},{expectedStreamVersion:s(c(t))});return m({eTag:a(r.nextExpectedStreamVersion)})}))};export{u as handle,T as shoppingCartApi};
2
2
  //# sourceMappingURL=api.mjs.map
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkYC2DBBXWjs = require('../../chunk-YC2DBBXW.js');require('../../chunk-P7AA2K4Q.js');require('../../chunk-ZWOSOI7Z.js');exports.ShoppingCartErrors = _chunkYC2DBBXWjs.a; exports.assertProductItemExists = _chunkYC2DBBXWjs.b; exports.decide = _chunkYC2DBBXWjs.c; exports.decider = _chunkYC2DBBXWjs.d;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunk2JWQPLZIjs = require('../../chunk-2JWQPLZI.js');require('../../chunk-5SQK7LQ2.js');require('../../chunk-DA5J4ET5.js');exports.ShoppingCartErrors = _chunk2JWQPLZIjs.a; exports.assertProductItemExists = _chunk2JWQPLZIjs.b; exports.decide = _chunk2JWQPLZIjs.c; exports.decider = _chunk2JWQPLZIjs.d;
2
2
  //# sourceMappingURL=businessLogic.js.map
@@ -1,2 +1,2 @@
1
- import{a,b,c,d}from"../../chunk-6MY6WCJR.mjs";import"../../chunk-BPMP6GJ7.mjs";import"../../chunk-HEPNAXF4.mjs";export{a as ShoppingCartErrors,b as assertProductItemExists,c as decide,d as decider};
1
+ import{a,b,c,d}from"../../chunk-TP4BTDFZ.mjs";import"../../chunk-BHGAXF2A.mjs";import"../../chunk-KIRBEYFF.mjs";export{a as ShoppingCartErrors,b as assertProductItemExists,c as decide,d as decider};
2
2
  //# sourceMappingURL=businessLogic.mjs.map
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkP7AA2K4Qjs = require('../../chunk-P7AA2K4Q.js');require('../../chunk-ZWOSOI7Z.js');exports.ShoppingCartErrors = _chunkP7AA2K4Qjs.e; exports.ShoppingCartStatus = _chunkP7AA2K4Qjs.a; exports.emptyShoppingCart = _chunkP7AA2K4Qjs.b; exports.evolve = _chunkP7AA2K4Qjs.c; exports.getShoppingCart = _chunkP7AA2K4Qjs.d;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunk5SQK7LQ2js = require('../../chunk-5SQK7LQ2.js');require('../../chunk-DA5J4ET5.js');exports.ShoppingCartErrors = _chunk5SQK7LQ2js.e; exports.ShoppingCartStatus = _chunk5SQK7LQ2js.a; exports.emptyShoppingCart = _chunk5SQK7LQ2js.b; exports.evolve = _chunk5SQK7LQ2js.c; exports.getShoppingCart = _chunk5SQK7LQ2js.d;
2
2
  //# sourceMappingURL=shoppingCart.js.map
@@ -1,2 +1,2 @@
1
- import{a,b,c,d,e}from"../../chunk-BPMP6GJ7.mjs";import"../../chunk-HEPNAXF4.mjs";export{e as ShoppingCartErrors,a as ShoppingCartStatus,b as emptyShoppingCart,c as evolve,d as getShoppingCart};
1
+ import{a,b,c,d,e}from"../../chunk-BHGAXF2A.mjs";import"../../chunk-KIRBEYFF.mjs";export{e as ShoppingCartErrors,a as ShoppingCartStatus,b as emptyShoppingCart,c as evolve,d as getShoppingCart};
2
2
  //# sourceMappingURL=shoppingCart.mjs.map
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _chunkE4DZPUJHjs = require('../chunk-E4DZPUJH.js');var _chunkZWOSOI7Zjs = require('../chunk-ZWOSOI7Z.js');var _strict = require('assert/strict'); var _strict2 = _interopRequireDefault(_strict);require('supertest');var g=t=>{let s=t.headers.etag;_strict2.default.ok(s),_strict2.default.match(s,/W\/"\d+.*"/);let e=_chunkE4DZPUJHjs.e.call(void 0, s);return _chunkZWOSOI7Zjs.g.call(void 0, e)},x= exports.runTwice =t=>({expect:async e=>{let{first:a,second:c}=e,p=await a(t());return await c(t()),p}}),R= exports.statuses =(t,s)=>({first:e=>e.expect(t),second:e=>e.expect(s)});exports.expectNextRevisionInResponseEtag = g; exports.runTwice = x; exports.statuses = R;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _chunkE4DZPUJHjs = require('../chunk-E4DZPUJH.js');var _chunkDA5J4ET5js = require('../chunk-DA5J4ET5.js');var _strict = require('assert/strict'); var _strict2 = _interopRequireDefault(_strict);require('supertest');var g=t=>{let s=t.headers.etag;_strict2.default.ok(s),_strict2.default.match(s,/W\/"\d+.*"/);let e=_chunkE4DZPUJHjs.e.call(void 0, s);return _chunkDA5J4ET5js.h.call(void 0, e)},x= exports.runTwice =t=>({expect:async e=>{let{first:a,second:c}=e,p=await a(t());return await c(t()),p}}),R= exports.statuses =(t,s)=>({first:e=>e.expect(t),second:e=>e.expect(s)});exports.expectNextRevisionInResponseEtag = g; exports.runTwice = x; exports.statuses = R;
2
2
  //# sourceMappingURL=testing.js.map
@@ -1,2 +1,2 @@
1
- import{e as r}from"../chunk-GEU24YU2.mjs";import{g as o}from"../chunk-HEPNAXF4.mjs";import n from"node:assert/strict";import"supertest";var g=t=>{let s=t.headers.etag;n.ok(s),n.match(s,/W\/"\d+.*"/);let e=r(s);return o(e)},x=t=>({expect:async e=>{let{first:a,second:c}=e,p=await a(t());return await c(t()),p}}),R=(t,s)=>({first:e=>e.expect(t),second:e=>e.expect(s)});export{g as expectNextRevisionInResponseEtag,x as runTwice,R as statuses};
1
+ import{e as r}from"../chunk-GEU24YU2.mjs";import{h as o}from"../chunk-KIRBEYFF.mjs";import n from"node:assert/strict";import"supertest";var g=t=>{let s=t.headers.etag;n.ok(s),n.match(s,/W\/"\d+.*"/);let e=r(s);return o(e)},x=t=>({expect:async e=>{let{first:a,second:c}=e,p=await a(t());return await c(t()),p}}),R=(t,s)=>({first:e=>e.expect(t),second:e=>e.expect(s)});export{g as expectNextRevisionInResponseEtag,x as runTwice,R as statuses};
2
2
  //# sourceMappingURL=testing.mjs.map
package/dist/etag.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkE4DZPUJHjs = require('./chunk-E4DZPUJH.js');require('./chunk-ZWOSOI7Z.js');exports.ETagErrors = _chunkE4DZPUJHjs.c; exports.HeaderNames = _chunkE4DZPUJHjs.a; exports.WeakETagRegex = _chunkE4DZPUJHjs.b; exports.getETagFromIfMatch = _chunkE4DZPUJHjs.g; exports.getETagFromIfNotMatch = _chunkE4DZPUJHjs.h; exports.getETagValueFromIfMatch = _chunkE4DZPUJHjs.j; exports.getWeakETagValue = _chunkE4DZPUJHjs.e; exports.isWeakETag = _chunkE4DZPUJHjs.d; exports.setETag = _chunkE4DZPUJHjs.i; exports.toWeakETag = _chunkE4DZPUJHjs.f;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkE4DZPUJHjs = require('./chunk-E4DZPUJH.js');require('./chunk-DA5J4ET5.js');exports.ETagErrors = _chunkE4DZPUJHjs.c; exports.HeaderNames = _chunkE4DZPUJHjs.a; exports.WeakETagRegex = _chunkE4DZPUJHjs.b; exports.getETagFromIfMatch = _chunkE4DZPUJHjs.g; exports.getETagFromIfNotMatch = _chunkE4DZPUJHjs.h; exports.getETagValueFromIfMatch = _chunkE4DZPUJHjs.j; exports.getWeakETagValue = _chunkE4DZPUJHjs.e; exports.isWeakETag = _chunkE4DZPUJHjs.d; exports.setETag = _chunkE4DZPUJHjs.i; exports.toWeakETag = _chunkE4DZPUJHjs.f;
2
2
  //# sourceMappingURL=etag.js.map
package/dist/etag.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{a,b,c,d,e,f,g,h,i,j}from"./chunk-GEU24YU2.mjs";import"./chunk-HEPNAXF4.mjs";export{c as ETagErrors,a as HeaderNames,b as WeakETagRegex,g as getETagFromIfMatch,h as getETagFromIfNotMatch,j as getETagValueFromIfMatch,e as getWeakETagValue,d as isWeakETag,i as setETag,f as toWeakETag};
1
+ import{a,b,c,d,e,f,g,h,i,j}from"./chunk-GEU24YU2.mjs";import"./chunk-KIRBEYFF.mjs";export{c as ETagErrors,a as HeaderNames,b as WeakETagRegex,g as getETagFromIfMatch,h as getETagFromIfNotMatch,j as getETagValueFromIfMatch,e as getWeakETagValue,d as isWeakETag,i as setETag,f as toWeakETag};
2
2
  //# sourceMappingURL=etag.mjs.map
package/dist/handler.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkUT7Q27E5js = require('./chunk-UT7Q27E5.js');require('./chunk-7H3QW2YD.js');require('./chunk-VK264KTU.js');require('./chunk-Y7SZXFJ2.js');require('./chunk-KVWDIWFZ.js');require('./chunk-NDXUB3PP.js');require('./chunk-E4DZPUJH.js');require('./chunk-ZWOSOI7Z.js');exports.Accepted = _chunkUT7Q27E5js.d; exports.BadRequest = _chunkUT7Q27E5js.g; exports.Conflict = _chunkUT7Q27E5js.j; exports.Created = _chunkUT7Q27E5js.c; exports.Forbidden = _chunkUT7Q27E5js.h; exports.HttpProblem = _chunkUT7Q27E5js.l; exports.HttpResponse = _chunkUT7Q27E5js.f; exports.NoContent = _chunkUT7Q27E5js.e; exports.NotFound = _chunkUT7Q27E5js.i; exports.OK = _chunkUT7Q27E5js.b; exports.PreconditionFailed = _chunkUT7Q27E5js.k; exports.on = _chunkUT7Q27E5js.a;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkDLZ3WQUJjs = require('./chunk-DLZ3WQUJ.js');require('./chunk-7H3QW2YD.js');require('./chunk-VK264KTU.js');require('./chunk-MEK5AIAJ.js');require('./chunk-KVWDIWFZ.js');require('./chunk-NDXUB3PP.js');require('./chunk-E4DZPUJH.js');require('./chunk-DA5J4ET5.js');exports.Accepted = _chunkDLZ3WQUJjs.d; exports.BadRequest = _chunkDLZ3WQUJjs.g; exports.Conflict = _chunkDLZ3WQUJjs.j; exports.Created = _chunkDLZ3WQUJjs.c; exports.Forbidden = _chunkDLZ3WQUJjs.h; exports.HttpProblem = _chunkDLZ3WQUJjs.l; exports.HttpResponse = _chunkDLZ3WQUJjs.f; exports.NoContent = _chunkDLZ3WQUJjs.e; exports.NotFound = _chunkDLZ3WQUJjs.i; exports.OK = _chunkDLZ3WQUJjs.b; exports.PreconditionFailed = _chunkDLZ3WQUJjs.k; exports.on = _chunkDLZ3WQUJjs.a;
2
2
  //# sourceMappingURL=handler.js.map
package/dist/handler.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{a,b,c,d,e,f,g,h,i,j,k,l}from"./chunk-3P6L3RAK.mjs";import"./chunk-HKEQAT6F.mjs";import"./chunk-2IUXL747.mjs";import"./chunk-TJPUQYKV.mjs";import"./chunk-42BDHECF.mjs";import"./chunk-3ECNKSAE.mjs";import"./chunk-GEU24YU2.mjs";import"./chunk-HEPNAXF4.mjs";export{d as Accepted,g as BadRequest,j as Conflict,c as Created,h as Forbidden,l as HttpProblem,f as HttpResponse,e as NoContent,i as NotFound,b as OK,k as PreconditionFailed,a as on};
1
+ import{a,b,c,d,e,f,g,h,i,j,k,l}from"./chunk-OAYYW4GF.mjs";import"./chunk-HKEQAT6F.mjs";import"./chunk-2IUXL747.mjs";import"./chunk-IMSJF3JS.mjs";import"./chunk-42BDHECF.mjs";import"./chunk-3ECNKSAE.mjs";import"./chunk-GEU24YU2.mjs";import"./chunk-KIRBEYFF.mjs";export{d as Accepted,g as BadRequest,j as Conflict,c as Created,h as Forbidden,l as HttpProblem,f as HttpResponse,e as NoContent,i as NotFound,b as OK,k as PreconditionFailed,a as on};
2
2
  //# sourceMappingURL=handler.mjs.map
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkUT7Q27E5js = require('./chunk-UT7Q27E5.js');require('./chunk-7H3QW2YD.js');var _chunkVK264KTUjs = require('./chunk-VK264KTU.js');var _chunkY7SZXFJ2js = require('./chunk-Y7SZXFJ2.js');require('./chunk-KVWDIWFZ.js');var _chunkNDXUB3PPjs = require('./chunk-NDXUB3PP.js');var _chunkE4DZPUJHjs = require('./chunk-E4DZPUJH.js');require('./chunk-ZWOSOI7Z.js');exports.Accepted = _chunkUT7Q27E5js.d; exports.ApiE2ESpecification = _chunkVK264KTUjs.a; exports.ApiSpecification = _chunkY7SZXFJ2js.f; exports.BadRequest = _chunkUT7Q27E5js.g; exports.Conflict = _chunkUT7Q27E5js.j; exports.Created = _chunkUT7Q27E5js.c; exports.DefaultHttpProblemResponseOptions = _chunkNDXUB3PPjs.b; exports.DefaultHttpResponseOptions = _chunkNDXUB3PPjs.a; exports.ETagErrors = _chunkE4DZPUJHjs.c; exports.Forbidden = _chunkUT7Q27E5js.h; exports.HeaderNames = _chunkE4DZPUJHjs.a; exports.HttpProblem = _chunkUT7Q27E5js.l; exports.HttpResponse = _chunkUT7Q27E5js.f; exports.NoContent = _chunkUT7Q27E5js.e; exports.NotFound = _chunkUT7Q27E5js.i; exports.OK = _chunkUT7Q27E5js.b; exports.PreconditionFailed = _chunkUT7Q27E5js.k; exports.WeakETagRegex = _chunkE4DZPUJHjs.b; exports.existingStream = _chunkY7SZXFJ2js.a; exports.expect = _chunkY7SZXFJ2js.b; exports.expectError = _chunkY7SZXFJ2js.e; exports.expectNewEvents = _chunkY7SZXFJ2js.c; exports.expectResponse = _chunkY7SZXFJ2js.d; exports.getApplication = _chunkUT7Q27E5js.o; exports.getETagFromIfMatch = _chunkE4DZPUJHjs.g; exports.getETagFromIfNotMatch = _chunkE4DZPUJHjs.h; exports.getETagValueFromIfMatch = _chunkE4DZPUJHjs.j; exports.getWeakETagValue = _chunkE4DZPUJHjs.e; exports.isWeakETag = _chunkE4DZPUJHjs.d; exports.on = _chunkUT7Q27E5js.a; exports.send = _chunkNDXUB3PPjs.e; exports.sendAccepted = _chunkNDXUB3PPjs.d; exports.sendCreated = _chunkNDXUB3PPjs.c; exports.sendProblem = _chunkNDXUB3PPjs.f; exports.setETag = _chunkE4DZPUJHjs.i; exports.startAPI = _chunkUT7Q27E5js.p; exports.toWeakETag = _chunkE4DZPUJHjs.f;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkDLZ3WQUJjs = require('./chunk-DLZ3WQUJ.js');require('./chunk-7H3QW2YD.js');var _chunkVK264KTUjs = require('./chunk-VK264KTU.js');var _chunkMEK5AIAJjs = require('./chunk-MEK5AIAJ.js');require('./chunk-KVWDIWFZ.js');var _chunkNDXUB3PPjs = require('./chunk-NDXUB3PP.js');var _chunkE4DZPUJHjs = require('./chunk-E4DZPUJH.js');require('./chunk-DA5J4ET5.js');exports.Accepted = _chunkDLZ3WQUJjs.d; exports.ApiE2ESpecification = _chunkVK264KTUjs.a; exports.ApiSpecification = _chunkMEK5AIAJjs.f; exports.BadRequest = _chunkDLZ3WQUJjs.g; exports.Conflict = _chunkDLZ3WQUJjs.j; exports.Created = _chunkDLZ3WQUJjs.c; exports.DefaultHttpProblemResponseOptions = _chunkNDXUB3PPjs.b; exports.DefaultHttpResponseOptions = _chunkNDXUB3PPjs.a; exports.ETagErrors = _chunkE4DZPUJHjs.c; exports.Forbidden = _chunkDLZ3WQUJjs.h; exports.HeaderNames = _chunkE4DZPUJHjs.a; exports.HttpProblem = _chunkDLZ3WQUJjs.l; exports.HttpResponse = _chunkDLZ3WQUJjs.f; exports.NoContent = _chunkDLZ3WQUJjs.e; exports.NotFound = _chunkDLZ3WQUJjs.i; exports.OK = _chunkDLZ3WQUJjs.b; exports.PreconditionFailed = _chunkDLZ3WQUJjs.k; exports.WeakETagRegex = _chunkE4DZPUJHjs.b; exports.existingStream = _chunkMEK5AIAJjs.a; exports.expect = _chunkMEK5AIAJjs.b; exports.expectError = _chunkMEK5AIAJjs.e; exports.expectNewEvents = _chunkMEK5AIAJjs.c; exports.expectResponse = _chunkMEK5AIAJjs.d; exports.getApplication = _chunkDLZ3WQUJjs.o; exports.getETagFromIfMatch = _chunkE4DZPUJHjs.g; exports.getETagFromIfNotMatch = _chunkE4DZPUJHjs.h; exports.getETagValueFromIfMatch = _chunkE4DZPUJHjs.j; exports.getWeakETagValue = _chunkE4DZPUJHjs.e; exports.isWeakETag = _chunkE4DZPUJHjs.d; exports.on = _chunkDLZ3WQUJjs.a; exports.send = _chunkNDXUB3PPjs.e; exports.sendAccepted = _chunkNDXUB3PPjs.d; exports.sendCreated = _chunkNDXUB3PPjs.c; exports.sendProblem = _chunkNDXUB3PPjs.f; exports.setETag = _chunkE4DZPUJHjs.i; exports.startAPI = _chunkDLZ3WQUJjs.p; exports.toWeakETag = _chunkE4DZPUJHjs.f;
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{a as k,b as l,c as m,d as n,e as o,f as p,g as q,h as r,i as s,j as t,k as u,l as v,o as J,p as K}from"./chunk-3P6L3RAK.mjs";import"./chunk-HKEQAT6F.mjs";import{a as C}from"./chunk-2IUXL747.mjs";import{a as D,b as E,c as F,d as G,e as H,f as I}from"./chunk-TJPUQYKV.mjs";import"./chunk-42BDHECF.mjs";import{a as w,b as x,c as y,d as z,e as A,f as B}from"./chunk-3ECNKSAE.mjs";import{a,b,c,d,e,f,g,h,i,j}from"./chunk-GEU24YU2.mjs";import"./chunk-HEPNAXF4.mjs";export{n as Accepted,C as ApiE2ESpecification,I as ApiSpecification,q as BadRequest,t as Conflict,m as Created,x as DefaultHttpProblemResponseOptions,w as DefaultHttpResponseOptions,c as ETagErrors,r as Forbidden,a as HeaderNames,v as HttpProblem,p as HttpResponse,o as NoContent,s as NotFound,l as OK,u as PreconditionFailed,b as WeakETagRegex,D as existingStream,E as expect,H as expectError,F as expectNewEvents,G as expectResponse,J as getApplication,g as getETagFromIfMatch,h as getETagFromIfNotMatch,j as getETagValueFromIfMatch,e as getWeakETagValue,d as isWeakETag,k as on,A as send,z as sendAccepted,y as sendCreated,B as sendProblem,i as setETag,K as startAPI,f as toWeakETag};
1
+ import{a as k,b as l,c as m,d as n,e as o,f as p,g as q,h as r,i as s,j as t,k as u,l as v,o as J,p as K}from"./chunk-OAYYW4GF.mjs";import"./chunk-HKEQAT6F.mjs";import{a as C}from"./chunk-2IUXL747.mjs";import{a as D,b as E,c as F,d as G,e as H,f as I}from"./chunk-IMSJF3JS.mjs";import"./chunk-42BDHECF.mjs";import{a as w,b as x,c as y,d as z,e as A,f as B}from"./chunk-3ECNKSAE.mjs";import{a,b,c,d,e,f,g,h,i,j}from"./chunk-GEU24YU2.mjs";import"./chunk-KIRBEYFF.mjs";export{n as Accepted,C as ApiE2ESpecification,I as ApiSpecification,q as BadRequest,t as Conflict,m as Created,x as DefaultHttpProblemResponseOptions,w as DefaultHttpResponseOptions,c as ETagErrors,r as Forbidden,a as HeaderNames,v as HttpProblem,p as HttpResponse,o as NoContent,s as NotFound,l as OK,u as PreconditionFailed,b as WeakETagRegex,D as existingStream,E as expect,H as expectError,F as expectNewEvents,G as expectResponse,J as getApplication,g as getETagFromIfMatch,h as getETagFromIfNotMatch,j as getETagValueFromIfMatch,e as getWeakETagValue,d as isWeakETag,k as on,A as send,z as sendAccepted,y as sendCreated,B as sendProblem,i as setETag,K as startAPI,f as toWeakETag};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkUT7Q27E5js = require('../chunk-UT7Q27E5.js');require('../chunk-7H3QW2YD.js');require('../chunk-VK264KTU.js');require('../chunk-Y7SZXFJ2.js');require('../chunk-KVWDIWFZ.js');require('../chunk-NDXUB3PP.js');require('../chunk-E4DZPUJH.js');require('../chunk-ZWOSOI7Z.js');exports.defaulErrorToProblemDetailsMapping = _chunkUT7Q27E5js.n; exports.problemDetailsMiddleware = _chunkUT7Q27E5js.m;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkDLZ3WQUJjs = require('../chunk-DLZ3WQUJ.js');require('../chunk-7H3QW2YD.js');require('../chunk-VK264KTU.js');require('../chunk-MEK5AIAJ.js');require('../chunk-KVWDIWFZ.js');require('../chunk-NDXUB3PP.js');require('../chunk-E4DZPUJH.js');require('../chunk-DA5J4ET5.js');exports.defaulErrorToProblemDetailsMapping = _chunkDLZ3WQUJjs.n; exports.problemDetailsMiddleware = _chunkDLZ3WQUJjs.m;
2
2
  //# sourceMappingURL=problemDetailsMiddleware.js.map
@@ -1,2 +1,2 @@
1
- import{m as a,n as b}from"../chunk-3P6L3RAK.mjs";import"../chunk-HKEQAT6F.mjs";import"../chunk-2IUXL747.mjs";import"../chunk-TJPUQYKV.mjs";import"../chunk-42BDHECF.mjs";import"../chunk-3ECNKSAE.mjs";import"../chunk-GEU24YU2.mjs";import"../chunk-HEPNAXF4.mjs";export{b as defaulErrorToProblemDetailsMapping,a as problemDetailsMiddleware};
1
+ import{m as a,n as b}from"../chunk-OAYYW4GF.mjs";import"../chunk-HKEQAT6F.mjs";import"../chunk-2IUXL747.mjs";import"../chunk-IMSJF3JS.mjs";import"../chunk-42BDHECF.mjs";import"../chunk-3ECNKSAE.mjs";import"../chunk-GEU24YU2.mjs";import"../chunk-KIRBEYFF.mjs";export{b as defaulErrorToProblemDetailsMapping,a as problemDetailsMiddleware};
2
2
  //# sourceMappingURL=problemDetailsMiddleware.mjs.map
package/dist/responses.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkNDXUB3PPjs = require('./chunk-NDXUB3PP.js');require('./chunk-E4DZPUJH.js');require('./chunk-ZWOSOI7Z.js');exports.DefaultHttpProblemResponseOptions = _chunkNDXUB3PPjs.b; exports.DefaultHttpResponseOptions = _chunkNDXUB3PPjs.a; exports.send = _chunkNDXUB3PPjs.e; exports.sendAccepted = _chunkNDXUB3PPjs.d; exports.sendCreated = _chunkNDXUB3PPjs.c; exports.sendProblem = _chunkNDXUB3PPjs.f;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkNDXUB3PPjs = require('./chunk-NDXUB3PP.js');require('./chunk-E4DZPUJH.js');require('./chunk-DA5J4ET5.js');exports.DefaultHttpProblemResponseOptions = _chunkNDXUB3PPjs.b; exports.DefaultHttpResponseOptions = _chunkNDXUB3PPjs.a; exports.send = _chunkNDXUB3PPjs.e; exports.sendAccepted = _chunkNDXUB3PPjs.d; exports.sendCreated = _chunkNDXUB3PPjs.c; exports.sendProblem = _chunkNDXUB3PPjs.f;
2
2
  //# sourceMappingURL=responses.js.map
@@ -1,2 +1,2 @@
1
- import{a,b,c,d,e,f}from"./chunk-3ECNKSAE.mjs";import"./chunk-GEU24YU2.mjs";import"./chunk-HEPNAXF4.mjs";export{b as DefaultHttpProblemResponseOptions,a as DefaultHttpResponseOptions,e as send,d as sendAccepted,c as sendCreated,f as sendProblem};
1
+ import{a,b,c,d,e,f}from"./chunk-3ECNKSAE.mjs";import"./chunk-GEU24YU2.mjs";import"./chunk-KIRBEYFF.mjs";export{b as DefaultHttpProblemResponseOptions,a as DefaultHttpResponseOptions,e as send,d as sendAccepted,c as sendCreated,f as sendProblem};
2
2
  //# sourceMappingURL=responses.mjs.map
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkY7SZXFJ2js = require('../chunk-Y7SZXFJ2.js');require('../chunk-KVWDIWFZ.js');require('../chunk-ZWOSOI7Z.js');exports.ApiSpecification = _chunkY7SZXFJ2js.f; exports.existingStream = _chunkY7SZXFJ2js.a; exports.expect = _chunkY7SZXFJ2js.b; exports.expectError = _chunkY7SZXFJ2js.e; exports.expectNewEvents = _chunkY7SZXFJ2js.c; exports.expectResponse = _chunkY7SZXFJ2js.d;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkMEK5AIAJjs = require('../chunk-MEK5AIAJ.js');require('../chunk-KVWDIWFZ.js');require('../chunk-DA5J4ET5.js');exports.ApiSpecification = _chunkMEK5AIAJjs.f; exports.existingStream = _chunkMEK5AIAJjs.a; exports.expect = _chunkMEK5AIAJjs.b; exports.expectError = _chunkMEK5AIAJjs.e; exports.expectNewEvents = _chunkMEK5AIAJjs.c; exports.expectResponse = _chunkMEK5AIAJjs.d;
2
2
  //# sourceMappingURL=apiSpecification.js.map
@@ -1,2 +1,2 @@
1
- import{a,b,c,d,e,f}from"../chunk-TJPUQYKV.mjs";import"../chunk-42BDHECF.mjs";import"../chunk-HEPNAXF4.mjs";export{f as ApiSpecification,a as existingStream,b as expect,e as expectError,c as expectNewEvents,d as expectResponse};
1
+ import{a,b,c,d,e,f}from"../chunk-IMSJF3JS.mjs";import"../chunk-42BDHECF.mjs";import"../chunk-KIRBEYFF.mjs";export{f as ApiSpecification,a as existingStream,b as expect,e as expectError,c as expectNewEvents,d as expectResponse};
2
2
  //# sourceMappingURL=apiSpecification.mjs.map
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});require('../chunk-7H3QW2YD.js');var _chunkVK264KTUjs = require('../chunk-VK264KTU.js');var _chunkY7SZXFJ2js = require('../chunk-Y7SZXFJ2.js');require('../chunk-KVWDIWFZ.js');require('../chunk-ZWOSOI7Z.js');exports.ApiE2ESpecification = _chunkVK264KTUjs.a; exports.ApiSpecification = _chunkY7SZXFJ2js.f; exports.existingStream = _chunkY7SZXFJ2js.a; exports.expect = _chunkY7SZXFJ2js.b; exports.expectError = _chunkY7SZXFJ2js.e; exports.expectNewEvents = _chunkY7SZXFJ2js.c; exports.expectResponse = _chunkY7SZXFJ2js.d;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});require('../chunk-7H3QW2YD.js');var _chunkVK264KTUjs = require('../chunk-VK264KTU.js');var _chunkMEK5AIAJjs = require('../chunk-MEK5AIAJ.js');require('../chunk-KVWDIWFZ.js');require('../chunk-DA5J4ET5.js');exports.ApiE2ESpecification = _chunkVK264KTUjs.a; exports.ApiSpecification = _chunkMEK5AIAJjs.f; exports.existingStream = _chunkMEK5AIAJjs.a; exports.expect = _chunkMEK5AIAJjs.b; exports.expectError = _chunkMEK5AIAJjs.e; exports.expectNewEvents = _chunkMEK5AIAJjs.c; exports.expectResponse = _chunkMEK5AIAJjs.d;
2
2
  //# sourceMappingURL=index.js.map
@@ -1,2 +1,2 @@
1
- import"../chunk-HKEQAT6F.mjs";import{a}from"../chunk-2IUXL747.mjs";import{a as b,b as c,c as d,d as e,e as f,f as g}from"../chunk-TJPUQYKV.mjs";import"../chunk-42BDHECF.mjs";import"../chunk-HEPNAXF4.mjs";export{a as ApiE2ESpecification,g as ApiSpecification,b as existingStream,c as expect,f as expectError,d as expectNewEvents,e as expectResponse};
1
+ import"../chunk-HKEQAT6F.mjs";import{a}from"../chunk-2IUXL747.mjs";import{a as b,b as c,c as d,d as e,e as f,f as g}from"../chunk-IMSJF3JS.mjs";import"../chunk-42BDHECF.mjs";import"../chunk-KIRBEYFF.mjs";export{a as ApiE2ESpecification,g as ApiSpecification,b as existingStream,c as expect,f as expectError,d as expectNewEvents,e as expectResponse};
2
2
  //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@event-driven-io/emmett-expressjs",
3
- "version": "0.5.4",
3
+ "version": "0.6.0",
4
4
  "description": "Emmett - Event Sourcing development made simple",
5
5
  "scripts": {
6
6
  "build": "tsup",
@@ -48,9 +48,10 @@
48
48
  "dependencies": {},
49
49
  "devDependencies": {},
50
50
  "peerDependencies": {
51
- "express": "4.18.2",
52
- "@event-driven-io/emmett": "0.5.4",
51
+ "@event-driven-io/emmett": "0.6.0",
52
+ "@types/express": "4.17.21",
53
53
  "@types/supertest": "6.0.2",
54
+ "express": "4.19.2",
54
55
  "express-async-errors": "3.1.1",
55
56
  "http-problem-details": "0.1.5",
56
57
  "supertest": "6.3.4"
@@ -1,2 +0,0 @@
1
- import{c as R,d as c,e as l,f as r}from"./chunk-3ECNKSAE.mjs";import{c as d}from"./chunk-HEPNAXF4.mjs";import"express";import"express-async-errors";import a,{Router as y}from"express";import"express-async-errors";import O from"http";import{ProblemDocument as f}from"http-problem-details";var u=e=>(t,o,s,i)=>{let p;e&&(p=e(t,o)),p=p??P(t),r(s,p.status,{problem:p})},P=e=>{let t=500;return e instanceof d&&(t=e.errorCode),new f({detail:e.message,status:t})};var v=e=>{let t=a(),{apis:o,mapError:s,enableDefaultExpressEtag:i,disableJsonMiddleware:p,disableUrlEncodingMiddleware:b,disableProblemDetailsMiddleware:x}=e,m=y();t.set("etag",i??!1),p||t.use(a.json()),b||t.use(a.urlencoded({extended:!0}));for(let H of o)H(m);return t.use(m),x||t.use(u(s)),t},N=(e,t={port:3e3})=>{let{port:o}=t,s=O.createServer(e);return s.on("listening",()=>{console.info("server up listening")}),s.listen(o)};var K=e=>async(t,o,s)=>(await Promise.resolve(e(t)))(o),k=e=>t=>{l(t,200,e)},z=e=>t=>{R(t,e)},G=e=>t=>{c(t,e)},L=e=>E(204,e),E=(e,t)=>o=>{l(o,e,t)},Q=e=>n(400,e),V=e=>n(403,e),X=e=>n(404,e),Y=e=>n(409,e),Z=e=>n(412,e),n=(e,t)=>o=>{r(o,e,t)};export{K as a,k as b,z as c,G as d,L as e,E as f,Q as g,V as h,X as i,Y as j,Z as k,n as l,u as m,P as n,v as o,N as p};
2
- //# sourceMappingURL=chunk-3P6L3RAK.mjs.map
@@ -1,5 +0,0 @@
1
- var b=(e,t,o,r,a=()=>{})=>{let i=!1,n=e.map(s=>o(s)?(i=!0,r(s)):s).filter(s=>s!==void 0).map(s=>{if(!s)throw Error("That should not happen");return s});return!i&&a()!==void 0?[...e,t]:n};var c=(e,t)=>{let o=e,r=t;return Object.keys(r).every(a=>typeof r[a]=="object"?c(o[a],r[a]):r[a]===o[a])},_=(e,t)=>{if(!c(e,t))throw Error(`subObj:
2
- ${JSON.stringify(t)}
3
- is not subset of
4
- ${JSON.stringify(e)}`)};var u=class y extends Error{errorCode;constructor(t){let o=t&&typeof t=="object"&&"errorCode"in t?t.errorCode:l(t)?t:500,r=t&&typeof t=="object"&&"message"in t?t.message:g(t)?t:`Error with status code '${o}' ocurred during Emmett processing`;super(r),this.errorCode=o,Object.setPrototypeOf(this,y.prototype)}};var p=class v extends u{constructor(t){super({errorCode:400,message:t??"Validation Error ocurred during Emmett processing"}),Object.setPrototypeOf(this,v.prototype)}},C=class O extends u{constructor(t){super({errorCode:403,message:t??"Illegal State ocurred during Emmett processing"}),Object.setPrototypeOf(this,O.prototype)}};var x=(e=>(e.NOT_A_NONEMPTY_STRING="NOT_A_NONEMPTY_STRING",e.NOT_A_POSITIVE_NUMBER="NOT_A_POSITIVE_NUMBER",e.NOT_AN_UNSIGNED_BIGINT="NOT_AN_UNSIGNED_BIGINT",e))(x||{}),l=e=>typeof e=="number"&&e===e,g=e=>typeof e=="string",w=e=>{if(!g(e)||e.length===0)throw new p("NOT_A_NONEMPTY_STRING");return e},A=e=>{if(!l(e)||e<=0)throw new p("NOT_A_POSITIVE_NUMBER");return e},P=e=>{let t=BigInt(e);if(t<0)throw new p("NOT_AN_UNSIGNED_BIGINT");return t};var S="STREAM_DOES_NOT_EXIST",f="NO_CONCURRENCY_CHECK";var E=(e,t,o=r=>r)=>async(r,a,i,n)=>{let s=o(a),m=await r.aggregateStream(s,{evolve:e,getInitialState:t,read:{expectedStreamVersion:n?.expectedStreamVersion??f}}),h=m?.state??t(),I=m?.currentStreamVersion,d=i(h),N=Array.isArray(d)?d:[d],T=n?.expectedStreamVersion??I??S;return{...await r.appendToStream(s,N,{expectedStreamVersion:T}),newState:N.reduce(e,h)}};var k=({decide:e,evolve:t,getInitialState:o},r=a=>a)=>async(a,i,n,s)=>E(t,o,r)(a,i,m=>e(n,m),s);import z from"assert";import{randomUUID as Z}from"crypto";export{b as a,_ as b,u as c,C as d,w as e,A as f,P as g,S as h,k as i};
5
- //# sourceMappingURL=chunk-HEPNAXF4.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../emmett/src/utils/merge.ts","../../emmett/src/testing/assertions.ts","../../emmett/src/errors/index.ts","../../emmett/src/validation/index.ts","../../emmett/src/eventStore/expectedVersion.ts","../../emmett/src/commandHandling/handleCommand.ts","../../emmett/src/commandHandling/handleCommandWithDecider.ts","../../emmett/src/testing/deciderSpecification.ts","../../emmett/src/eventStore/inMemoryEventStore.ts"],"sourcesContent":["export const merge = <T>(\n array: T[],\n item: T,\n where: (current: T) => boolean,\n onExisting: (current: T) => T,\n onNotFound: () => T | undefined = () => undefined,\n) => {\n let wasFound = false;\n\n const result = array\n // merge the existing item if matches condition\n .map((p: T) => {\n if (!where(p)) return p;\n\n wasFound = true;\n return onExisting(p);\n })\n // filter out item if undefined was returned\n // for cases of removal\n .filter((p) => p !== undefined)\n // make TypeScript happy\n .map((p) => {\n if (!p) throw Error('That should not happen');\n\n return p;\n });\n\n // if item was not found and onNotFound action is defined\n // try to generate new item\n if (!wasFound) {\n const result = onNotFound();\n\n if (result !== undefined) return [...array, item];\n }\n\n return result;\n};\n","export const isSubset = (superObj: unknown, subObj: unknown): boolean => {\n const sup = superObj as Record<string, unknown>;\n const sub = subObj as Record<string, unknown>;\n\n return Object.keys(sub).every((ele: string) => {\n if (typeof sub[ele] == 'object') {\n return isSubset(\n sup[ele] as Record<string, unknown>,\n sub[ele] as Record<string, unknown>,\n );\n }\n return sub[ele] === sup[ele];\n });\n};\n\nexport const assertMatches = (actual: unknown, expected: unknown) => {\n if (!isSubset(actual, expected))\n throw Error(\n `subObj:\\n${JSON.stringify(expected)}\\nis not subset of\\n${JSON.stringify(actual)}`,\n );\n};\n","import { isNumber, isString } from '../validation';\n\nexport class EmmettError extends Error {\n public errorCode: number;\n\n constructor(\n options?: { errorCode: number; message?: string } | string | number,\n ) {\n const errorCode =\n options && typeof options === 'object' && 'errorCode' in options\n ? options.errorCode\n : isNumber(options)\n ? options\n : 500;\n const message =\n options && typeof options === 'object' && 'message' in options\n ? options.message\n : isString(options)\n ? options\n : `Error with status code '${errorCode}' ocurred during Emmett processing`;\n\n super(message);\n this.errorCode = errorCode;\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, EmmettError.prototype);\n }\n}\n\nexport class ConcurrencyError extends EmmettError {\n constructor(\n public current: string | undefined,\n public expected: string,\n message?: string,\n ) {\n super({\n errorCode: 412,\n message:\n message ??\n `Expected version ${expected.toString()} does not match current ${current?.toString()}`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ConcurrencyError.prototype);\n }\n}\n\nexport class ValidationError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: 400,\n message: message ?? `Validation Error ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\nexport class IllegalStateError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: 403,\n message: message ?? `Illegal State ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, IllegalStateError.prototype);\n }\n}\n\nexport class NotFoundError extends EmmettError {\n constructor(options?: { id: string; type: string; message?: string }) {\n super({\n errorCode: 404,\n message:\n options?.message ??\n (options?.id\n ? options.type\n ? `${options.type} with ${options.id} was not found during Emmett processing`\n : `State with ${options.id} was not found during Emmett processing`\n : options?.type\n ? `${options.type} was not found during Emmett processing`\n : 'State was not found during Emmett processing'),\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, NotFoundError.prototype);\n }\n}\n","import { ValidationError } from '../errors';\n\nexport const enum ValidationErrors {\n NOT_A_NONEMPTY_STRING = 'NOT_A_NONEMPTY_STRING',\n NOT_A_POSITIVE_NUMBER = 'NOT_A_POSITIVE_NUMBER',\n NOT_AN_UNSIGNED_BIGINT = 'NOT_AN_UNSIGNED_BIGINT',\n}\n\nexport const isNumber = (val: unknown): val is number =>\n typeof val === 'number' && val === val;\n\nexport const isString = (val: unknown): val is string =>\n typeof val === 'string';\n\nexport const assertNotEmptyString = (value: unknown): string => {\n if (!isString(value) || value.length === 0) {\n throw new ValidationError(ValidationErrors.NOT_A_NONEMPTY_STRING);\n }\n return value;\n};\n\nexport const assertPositiveNumber = (value: unknown): number => {\n if (!isNumber(value) || value <= 0) {\n throw new ValidationError(ValidationErrors.NOT_A_POSITIVE_NUMBER);\n }\n return value;\n};\n\nexport const assertUnsignedBigInt = (value: string): bigint => {\n const number = BigInt(value);\n if (number < 0) {\n throw new ValidationError(ValidationErrors.NOT_AN_UNSIGNED_BIGINT);\n }\n return number;\n};\n","import { ConcurrencyError } from '../errors';\nimport type { Flavour } from '../typing';\nimport type { DefaultStreamVersionType } from './eventStore';\n\nexport type ExpectedStreamVersion<VersionType = DefaultStreamVersionType> =\n | ExpectedStreamVersionWithValue<VersionType>\n | ExpectedStreamVersionGeneral;\n\nexport type ExpectedStreamVersionWithValue<\n VersionType = DefaultStreamVersionType,\n> = Flavour<VersionType, 'StreamVersion'>;\n\nexport type ExpectedStreamVersionGeneral = Flavour<\n 'STREAM_EXISTS' | 'STREAM_DOES_NOT_EXIST' | 'NO_CONCURRENCY_CHECK',\n 'StreamVersion'\n>;\n\nexport const STREAM_EXISTS = 'STREAM_EXISTS' as ExpectedStreamVersionGeneral;\nexport const STREAM_DOES_NOT_EXIST =\n 'STREAM_DOES_NOT_EXIST' as ExpectedStreamVersionGeneral;\nexport const NO_CONCURRENCY_CHECK =\n 'NO_CONCURRENCY_CHECK' as ExpectedStreamVersionGeneral;\n\nexport const matchesExpectedVersion = <\n StreamVersion = DefaultStreamVersionType,\n>(\n current: StreamVersion | undefined,\n expected: ExpectedStreamVersion<StreamVersion>,\n): boolean => {\n if (expected === NO_CONCURRENCY_CHECK) return true;\n\n if (expected == STREAM_DOES_NOT_EXIST) return current === undefined;\n\n if (expected == STREAM_EXISTS) return current !== undefined;\n\n return current === expected;\n};\n\nexport const assertExpectedVersionMatchesCurrent = <\n StreamVersion = DefaultStreamVersionType,\n>(\n current: StreamVersion | undefined,\n expected: ExpectedStreamVersion<StreamVersion> | undefined,\n): void => {\n expected ??= NO_CONCURRENCY_CHECK;\n\n if (!matchesExpectedVersion(current, expected))\n throw new ExpectedVersionConflictError(current, expected);\n};\n\nexport class ExpectedVersionConflictError<\n VersionType = DefaultStreamVersionType,\n> extends ConcurrencyError {\n constructor(\n current: VersionType | undefined,\n expected: ExpectedStreamVersion<VersionType>,\n ) {\n super(current?.toString(), expected?.toString());\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ExpectedVersionConflictError.prototype);\n }\n}\n","import {\n NO_CONCURRENCY_CHECK,\n STREAM_DOES_NOT_EXIST,\n type AppendToStreamResult,\n type DefaultStreamVersionType,\n type EventStore,\n type ExpectedStreamVersion,\n} from '../eventStore';\nimport type { Event } from '../typing';\n\n// #region command-handler\nexport type CommandHandlerResult<\n State,\n StreamVersion = DefaultStreamVersionType,\n> = AppendToStreamResult<StreamVersion> & { newState: State };\n\nexport const CommandHandler =\n <State, StreamEvent extends Event, StreamVersion = DefaultStreamVersionType>(\n evolve: (state: State, event: StreamEvent) => State,\n getInitialState: () => State,\n mapToStreamId: (id: string) => string = (id) => id,\n ) =>\n async (\n eventStore: EventStore<StreamVersion>,\n id: string,\n handle: (state: State) => StreamEvent | StreamEvent[],\n options?: {\n expectedStreamVersion?: ExpectedStreamVersion<StreamVersion>;\n },\n ): Promise<CommandHandlerResult<State, StreamVersion>> => {\n const streamName = mapToStreamId(id);\n\n // 1. Aggregate the stream\n const aggregationResult = await eventStore.aggregateStream<\n State,\n StreamEvent\n >(streamName, {\n evolve,\n getInitialState,\n read: {\n // expected stream version is passed to fail fast\n // if stream is in the wrong state\n expectedStreamVersion:\n options?.expectedStreamVersion ?? NO_CONCURRENCY_CHECK,\n },\n });\n\n // 2. Use the aggregate state or the initial one (when e.g. stream does not exist)\n const state = aggregationResult?.state ?? getInitialState();\n const currentStreamVersion = aggregationResult?.currentStreamVersion;\n\n // 3. Run business logic\n const result = handle(state);\n\n const newEvents = Array.isArray(result) ? result : [result];\n\n // Either use:\n // - provided expected stream version,\n // - current stream version got from stream aggregation,\n // - or expect stream not to exists otherwise.\n const expectedStreamVersion: ExpectedStreamVersion<StreamVersion> =\n options?.expectedStreamVersion ??\n currentStreamVersion ??\n STREAM_DOES_NOT_EXIST;\n\n // 4. Append result to the stream\n const appendResult = await eventStore.appendToStream(\n streamName,\n newEvents,\n {\n expectedStreamVersion,\n },\n );\n\n // 5. Return result with updated state\n return { ...appendResult, newState: newEvents.reduce(evolve, state) };\n };\n// #endregion command-handler\n","import type {\n DefaultStreamVersionType,\n EventStore,\n ExpectedStreamVersion,\n} from '../eventStore';\nimport type { Command, Event } from '../typing';\nimport type { Decider } from '../typing/decider';\nimport { CommandHandler } from './handleCommand';\n\n// #region command-handler\nexport const DeciderCommandHandler =\n <\n State,\n CommandType extends Command,\n StreamEvent extends Event,\n StreamVersion = DefaultStreamVersionType,\n >(\n {\n decide,\n evolve,\n getInitialState,\n }: Decider<State, CommandType, StreamEvent>,\n mapToStreamId: (id: string) => string = (id) => id,\n ) =>\n async (\n eventStore: EventStore<StreamVersion>,\n id: string,\n command: CommandType,\n options?: {\n expectedStreamVersion?: ExpectedStreamVersion<StreamVersion>;\n },\n ) =>\n CommandHandler<State, StreamEvent, StreamVersion>(\n evolve,\n getInitialState,\n mapToStreamId,\n )(eventStore, id, (state) => decide(command, state), options);\n// #endregion command-handler\n","import assert from 'assert';\n\nexport type DeciderSpecfication<Command, Event> = (\n givenEvents: Event | Event[],\n) => {\n when: (command: Command) => {\n then: (expectedEvents: Event | Event[]) => void;\n thenThrows: <Error>(assert: (error: Error) => boolean) => void;\n };\n};\n\nexport const DeciderSpecification = {\n for: <Command, Event, State>(decider: {\n decide: (command: Command, state: State) => Event | Event[];\n evolve: (state: State, event: Event) => State;\n initialState: () => State;\n }): DeciderSpecfication<Command, Event> => {\n {\n return (givenEvents: Event | Event[]) => {\n return {\n when: (command: Command) => {\n const handle = () => {\n const existingEvents = Array.isArray(givenEvents)\n ? givenEvents\n : [givenEvents];\n\n const currentState = existingEvents.reduce<State>(\n decider.evolve,\n decider.initialState(),\n );\n\n return decider.decide(command, currentState);\n };\n\n return {\n then: (expectedEvents: Event | Event[]): void => {\n const resultEvents = handle();\n\n const resultEventsArray = Array.isArray(resultEvents)\n ? resultEvents\n : [resultEvents];\n\n const expectedEventsArray = Array.isArray(expectedEvents)\n ? expectedEvents\n : [expectedEvents];\n\n assert.deepEqual(resultEventsArray, expectedEventsArray);\n },\n thenThrows: <Error>(check?: (error: Error) => boolean): void => {\n try {\n handle();\n assert.fail('Handler did not fail as expected');\n } catch (error) {\n if (check) assert.ok(check(error as Error));\n }\n },\n };\n },\n };\n };\n }\n },\n};\n","import { randomUUID } from 'crypto';\nimport type { Event } from '../typing';\nimport {\n type AggregateStreamOptions,\n type AggregateStreamResult,\n type AppendToStreamOptions,\n type AppendToStreamResult,\n type EventStore,\n type ReadStreamOptions,\n type ReadStreamResult,\n} from './eventStore';\nimport { assertExpectedVersionMatchesCurrent } from './expectedVersion';\n\nexport type EventMetadata = Readonly<{\n eventId: string;\n streamPosition: number;\n logPosition: bigint;\n}>;\n\nexport type EventEnvelope<E extends Event = Event> = {\n event: E;\n metadata: EventMetadata;\n};\n\nexport type EventHandler<E extends Event = Event> = (\n eventEnvelope: EventEnvelope<E>,\n) => void;\n\nexport const getInMemoryEventStore = (): EventStore => {\n const streams = new Map<string, EventEnvelope[]>();\n\n const getAllEventsCount = () => {\n return Array.from<EventEnvelope[]>(streams.values())\n .map((s) => s.length)\n .reduce((p, c) => p + c, 0);\n };\n\n return {\n async aggregateStream<State, EventType extends Event>(\n streamName: string,\n options: AggregateStreamOptions<State, EventType>,\n ): Promise<AggregateStreamResult<State> | null> {\n const { evolve, getInitialState, read } = options;\n\n const result = await this.readStream<EventType>(streamName, read);\n\n if (!result) return null;\n\n const events = result?.events ?? [];\n\n return {\n currentStreamVersion: BigInt(events.length),\n state: events.reduce(evolve, getInitialState()),\n };\n },\n\n readStream: <EventType extends Event>(\n streamName: string,\n options?: ReadStreamOptions,\n ): Promise<ReadStreamResult<EventType>> => {\n const events = streams.get(streamName);\n const currentStreamVersion = events ? BigInt(events.length) : undefined;\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n options?.expectedStreamVersion,\n );\n\n const from = Number(options && 'from' in options ? options.from : 0);\n const to = Number(\n options && 'to' in options\n ? options.to\n : options && 'maxCount' in options && options.maxCount\n ? options.from + options.maxCount\n : events?.length ?? 1,\n );\n\n const resultEvents =\n events && events.length > 0\n ? events.map((e) => e.event as EventType).slice(from, to)\n : [];\n\n const result: ReadStreamResult<EventType> =\n events && events.length > 0\n ? {\n currentStreamVersion: currentStreamVersion!,\n events: resultEvents,\n }\n : null;\n\n return Promise.resolve(result);\n },\n\n appendToStream: <EventType extends Event>(\n streamName: string,\n events: EventType[],\n options?: AppendToStreamOptions,\n ): Promise<AppendToStreamResult> => {\n const currentEvents = streams.get(streamName) ?? [];\n const currentStreamVersion =\n currentEvents.length > 0 ? BigInt(currentEvents.length) : undefined;\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n options?.expectedStreamVersion,\n );\n\n const eventEnvelopes: EventEnvelope[] = events.map((event, index) => {\n return {\n event,\n metadata: {\n eventId: randomUUID(),\n streamPosition: currentEvents.length + index + 1,\n logPosition: BigInt(getAllEventsCount() + index + 1),\n },\n };\n });\n\n const positionOfLastEventInTheStream = BigInt(\n eventEnvelopes.slice(-1)[0]!.metadata.streamPosition,\n );\n\n streams.set(streamName, [...currentEvents, ...eventEnvelopes]);\n\n const result: AppendToStreamResult = {\n nextExpectedStreamVersion: positionOfLastEventInTheStream,\n };\n\n return Promise.resolve(result);\n },\n };\n};\n"],"mappings":"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","names":["merge","array","item","where","onExisting","onNotFound","wasFound","result","p","isSubset","superObj","subObj","sup","sub","ele","assertMatches","actual","expected","EmmettError","_EmmettError","options","errorCode","isNumber","message","isString","ValidationError","_ValidationError","EmmettError","message","IllegalStateError","_IllegalStateError","ValidationErrors","isNumber","val","isString","assertNotEmptyString","value","ValidationError","assertPositiveNumber","assertUnsignedBigInt","number","STREAM_DOES_NOT_EXIST","NO_CONCURRENCY_CHECK","CommandHandler","evolve","getInitialState","mapToStreamId","id","eventStore","handle","options","streamName","aggregationResult","NO_CONCURRENCY_CHECK","state","currentStreamVersion","result","newEvents","expectedStreamVersion","STREAM_DOES_NOT_EXIST","DeciderCommandHandler","decide","evolve","getInitialState","mapToStreamId","id","eventStore","command","options","CommandHandler","state","assert","randomUUID"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/handler.ts","../src/index.ts","../src/application.ts","../src/middlewares/problemDetailsMiddleware.ts"],"names":["express","Router","http","ProblemDocument","problemDetailsMiddleware","mapError","error","request","response","_next","problemDetails","defaulErrorToProblemDetailsMapping","sendProblem","statusCode","s","getApplication","options","app","apis","enableDefaultExpressEtag","disableJsonMiddleware","disableUrlEncodingMiddleware","disableProblemDetailsMiddleware","router","api","startAPI","port","server","on","handle","OK","send","Created","sendCreated","Accepted","sendAccepted","NoContent","HttpResponse","BadRequest","HttpProblem","Forbidden","NotFound","Conflict","PreconditionFailed"],"mappings":"qGAAA,MAA+D,UCA/D,MAAO,uBCAP,OAAOA,GAAW,UAAAC,MAAgC,UAClD,MAAO,uBACP,OAAOC,MAAU,OCAjB,OAAS,mBAAAC,MAAuB,uBAGzB,IAAMC,EACVC,GACD,CACEC,EACAC,EACAC,EACAC,IACS,CACT,IAAIC,EAEAL,IAAUK,EAAiBL,EAASC,EAAOC,CAAO,GAEtDG,EACEA,GAAkBC,EAAmCL,CAAK,EAE5DM,EAAYJ,EAAUE,EAAe,OAAQ,CAAE,QAASA,CAAe,CAAC,CAC1E,EAEWC,EACXL,GACoB,CACpB,IAAIO,EAAa,IAEjB,OAAIP,aAAiBQ,IACnBD,EAAaP,EAAM,WAGd,IAAIH,EAAgB,CACzB,OAAQG,EAAM,QACd,OAAQO,CACV,CAAC,CACH,EDjBO,IAAME,EAAkBC,GAAgC,CAC7D,IAAMC,EAAmBjB,EAAQ,EAE3B,CACJ,KAAAkB,EACA,SAAAb,EACA,yBAAAc,EACA,sBAAAC,EACA,6BAAAC,EACA,gCAAAC,CACF,EAAIN,EAEEO,EAAStB,EAAO,EAItBgB,EAAI,IAAI,OAAQE,GAA4B,EAAK,EAG5CC,GAAuBH,EAAI,IAAIjB,EAAQ,KAAK,CAAC,EAG7CqB,GACHJ,EAAI,IACFjB,EAAQ,WAAW,CACjB,SAAU,EACZ,CAAC,CACH,EAEF,QAAWwB,KAAON,EAChBM,EAAID,CAAM,EAEZ,OAAAN,EAAI,IAAIM,CAAM,EAGTD,GACHL,EAAI,IAAIb,EAAyBC,CAAQ,CAAC,EAErCY,CACT,EAMaQ,EAAW,CACtBR,EACAD,EAA2B,CAAE,KAAM,GAAK,IACrC,CACH,GAAM,CAAE,KAAAU,CAAK,EAAIV,EACXW,EAASzB,EAAK,aAAae,CAAG,EAEpC,OAAAU,EAAO,GAAG,YAAa,IAAM,CAC3B,QAAQ,KAAK,qBAAqB,CACpC,CAAC,EAEMA,EAAO,OAAOD,CAAI,CAC3B,EFxDO,IAAME,EACmBC,GAC9B,MACEtB,EACAC,EACAC,KAEoB,MAAM,QAAQ,QAAQoB,EAAOtB,CAAO,CAAC,GAEtCC,CAAQ,EAIlBsB,EACVd,GACAR,GAAuB,CACtBuB,EAAKvB,EAAU,IAAKQ,CAAO,CAC7B,EAEWgB,EACVhB,GACAR,GAAuB,CACtByB,EAAYzB,EAAUQ,CAAO,CAC/B,EAEWkB,EACVlB,GACAR,GAAuB,CACtB2B,EAAa3B,EAAUQ,CAAO,CAChC,EAEWoB,EACXpB,GACiBqB,EAAa,IAAKrB,CAAO,EAE/BqB,EACX,CAACxB,EAAoBG,IACpBR,GAAuB,CACtBuB,EAAKvB,EAAUK,EAAYG,CAAO,CACpC,EAMWsB,EACXtB,GACiBuB,EAAY,IAAKvB,CAAO,EAE9BwB,EAAaxB,GACxBuB,EAAY,IAAKvB,CAAO,EAEbyB,EAAYzB,GACvBuB,EAAY,IAAKvB,CAAO,EAEb0B,EAAY1B,GACvBuB,EAAY,IAAKvB,CAAO,EAEb2B,EACX3B,GACiBuB,EAAY,IAAKvB,CAAO,EAE9BuB,EACX,CAAC1B,EAAoBG,IACpBR,GAAuB,CACtBI,EAAYJ,EAAUK,EAAYG,CAAO,CAC3C","sourcesContent":["import { type NextFunction, type Request, type Response } from 'express';\nimport {\n send,\n sendAccepted,\n sendCreated,\n sendProblem,\n type AcceptedHttpResponseOptions,\n type CreatedHttpResponseOptions,\n type HttpProblemResponseOptions,\n type HttpResponseOptions,\n type NoContentHttpResponseOptions,\n} from '.';\n\n// #region httpresponse-on\nexport type HttpResponse = (response: Response) => void;\n\nexport type HttpHandler<RequestType extends Request> = (\n request: RequestType,\n) => Promise<HttpResponse> | HttpResponse;\n\nexport const on =\n <RequestType extends Request>(handle: HttpHandler<RequestType>) =>\n async (\n request: RequestType,\n response: Response,\n _next: NextFunction,\n ): Promise<void> => {\n const setResponse = await Promise.resolve(handle(request));\n\n return setResponse(response);\n };\n// #endregion httpresponse-on\n\nexport const OK =\n (options?: HttpResponseOptions): HttpResponse =>\n (response: Response) => {\n send(response, 200, options);\n };\n\nexport const Created =\n (options: CreatedHttpResponseOptions): HttpResponse =>\n (response: Response) => {\n sendCreated(response, options);\n };\n\nexport const Accepted =\n (options: AcceptedHttpResponseOptions): HttpResponse =>\n (response: Response) => {\n sendAccepted(response, options);\n };\n\nexport const NoContent = (\n options?: NoContentHttpResponseOptions,\n): HttpResponse => HttpResponse(204, options);\n\nexport const HttpResponse =\n (statusCode: number, options?: HttpResponseOptions): HttpResponse =>\n (response: Response) => {\n send(response, statusCode, options);\n };\n\n/////////////////////\n// ERRORS\n/////////////////////\n\nexport const BadRequest = (\n options?: HttpProblemResponseOptions,\n): HttpResponse => HttpProblem(400, options);\n\nexport const Forbidden = (options?: HttpProblemResponseOptions): HttpResponse =>\n HttpProblem(403, options);\n\nexport const NotFound = (options?: HttpProblemResponseOptions): HttpResponse =>\n HttpProblem(404, options);\n\nexport const Conflict = (options?: HttpProblemResponseOptions): HttpResponse =>\n HttpProblem(409, options);\n\nexport const PreconditionFailed = (\n options: HttpProblemResponseOptions,\n): HttpResponse => HttpProblem(412, options);\n\nexport const HttpProblem =\n (statusCode: number, options?: HttpProblemResponseOptions): HttpResponse =>\n (response: Response) => {\n sendProblem(response, statusCode, options);\n };\n","import 'express-async-errors';\n\nexport * from './application';\nexport * from './etag';\nexport * from './handler';\nexport * from './responses';\nexport * from './testing';\n","import express, { Router, type Application } from 'express';\nimport 'express-async-errors';\nimport http from 'http';\nimport { problemDetailsMiddleware } from './middlewares/problemDetailsMiddleware';\nimport type { ErrorToProblemDetailsMapping } from './responses';\n\n// #region web-api-setup\nexport type WebApiSetup = (router: Router) => void;\n// #endregion web-api-setup\n\nexport type ApplicationOptions = {\n apis: WebApiSetup[];\n mapError?: ErrorToProblemDetailsMapping;\n enableDefaultExpressEtag?: boolean;\n disableJsonMiddleware?: boolean;\n disableUrlEncodingMiddleware?: boolean;\n disableProblemDetailsMiddleware?: boolean;\n};\n\nexport const getApplication = (options: ApplicationOptions) => {\n const app: Application = express();\n\n const {\n apis,\n mapError,\n enableDefaultExpressEtag,\n disableJsonMiddleware,\n disableUrlEncodingMiddleware,\n disableProblemDetailsMiddleware,\n } = options;\n\n const router = Router();\n\n // disabling default etag behaviour\n // to use etags in if-match and if-not-match headers\n app.set('etag', enableDefaultExpressEtag ?? false);\n\n // add json middleware\n if (!disableJsonMiddleware) app.use(express.json());\n\n // enable url encoded urls and bodies\n if (!disableUrlEncodingMiddleware)\n app.use(\n express.urlencoded({\n extended: true,\n }),\n );\n\n for (const api of apis) {\n api(router);\n }\n app.use(router);\n\n // add problem details middleware\n if (!disableProblemDetailsMiddleware)\n app.use(problemDetailsMiddleware(mapError));\n\n return app;\n};\n\nexport type StartApiOptions = {\n port?: number;\n};\n\nexport const startAPI = (\n app: Application,\n options: StartApiOptions = { port: 3000 },\n) => {\n const { port } = options;\n const server = http.createServer(app);\n\n server.on('listening', () => {\n console.info('server up listening');\n });\n\n return server.listen(port);\n};\n","import { EmmettError } from '@event-driven-io/emmett';\nimport type { NextFunction, Request, Response } from 'express';\nimport { ProblemDocument } from 'http-problem-details';\nimport { sendProblem, type ErrorToProblemDetailsMapping } from '..';\n\nexport const problemDetailsMiddleware =\n (mapError?: ErrorToProblemDetailsMapping) =>\n (\n error: Error,\n request: Request,\n response: Response,\n _next: NextFunction,\n ): void => {\n let problemDetails: ProblemDocument | undefined;\n\n if (mapError) problemDetails = mapError(error, request);\n\n problemDetails =\n problemDetails ?? defaulErrorToProblemDetailsMapping(error);\n\n sendProblem(response, problemDetails.status, { problem: problemDetails });\n };\n\nexport const defaulErrorToProblemDetailsMapping = (\n error: Error,\n): ProblemDocument => {\n let statusCode = 500;\n\n if (error instanceof EmmettError) {\n statusCode = error.errorCode;\n }\n\n return new ProblemDocument({\n detail: error.message,\n status: statusCode,\n });\n};\n"]}
@@ -1,5 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var b=(e,t,o,r,a=()=>{})=>{let i=!1,n=e.map(s=>o(s)?(i=!0,r(s)):s).filter(s=>s!==void 0).map(s=>{if(!s)throw Error("That should not happen");return s});return!i&&a()!==void 0?[...e,t]:n};var c=(e,t)=>{let o=e,r=t;return Object.keys(r).every(a=>typeof r[a]=="object"?c(o[a],r[a]):r[a]===o[a])},_= exports.b =(e,t)=>{if(!c(e,t))throw Error(`subObj:
2
- ${JSON.stringify(t)}
3
- is not subset of
4
- ${JSON.stringify(e)}`)};var u=class y extends Error{constructor(t){let o=t&&typeof t=="object"&&"errorCode"in t?t.errorCode:l(t)?t:500,r=t&&typeof t=="object"&&"message"in t?t.message:g(t)?t:`Error with status code '${o}' ocurred during Emmett processing`;super(r),this.errorCode=o,Object.setPrototypeOf(this,y.prototype)}};var p=class v extends u{constructor(t){super({errorCode:400,message:_nullishCoalesce(t, () => ("Validation Error ocurred during Emmett processing"))}),Object.setPrototypeOf(this,v.prototype)}},C= exports.d =class O extends u{constructor(t){super({errorCode:403,message:_nullishCoalesce(t, () => ("Illegal State ocurred during Emmett processing"))}),Object.setPrototypeOf(this,O.prototype)}};var x=(e=>(e.NOT_A_NONEMPTY_STRING="NOT_A_NONEMPTY_STRING",e.NOT_A_POSITIVE_NUMBER="NOT_A_POSITIVE_NUMBER",e.NOT_AN_UNSIGNED_BIGINT="NOT_AN_UNSIGNED_BIGINT",e))(x||{}),l=e=>typeof e=="number"&&e===e,g=e=>typeof e=="string",w= exports.e =e=>{if(!g(e)||e.length===0)throw new p("NOT_A_NONEMPTY_STRING");return e},A= exports.f =e=>{if(!l(e)||e<=0)throw new p("NOT_A_POSITIVE_NUMBER");return e},P= exports.g =e=>{let t=BigInt(e);if(t<0)throw new p("NOT_AN_UNSIGNED_BIGINT");return t};var S="STREAM_DOES_NOT_EXIST",f="NO_CONCURRENCY_CHECK";var E=(e,t,o=r=>r)=>async(r,a,i,n)=>{let s=o(a),m=await r.aggregateStream(s,{evolve:e,getInitialState:t,read:{expectedStreamVersion:_nullishCoalesce(_optionalChain([n, 'optionalAccess', _2 => _2.expectedStreamVersion]), () => (f))}}),h=_nullishCoalesce(_optionalChain([m, 'optionalAccess', _3 => _3.state]), () => (t())),I=_optionalChain([m, 'optionalAccess', _4 => _4.currentStreamVersion]),d=i(h),N=Array.isArray(d)?d:[d],T=_nullishCoalesce(_nullishCoalesce(_optionalChain([n, 'optionalAccess', _5 => _5.expectedStreamVersion]), () => (I)), () => (S));return{...await r.appendToStream(s,N,{expectedStreamVersion:T}),newState:N.reduce(e,h)}};var k=({decide:e,evolve:t,getInitialState:o},r=a=>a)=>async(a,i,n,s)=>E(t,o,r)(a,i,m=>e(n,m),s);var _assert = require('assert'); var _assert2 = _interopRequireDefault(_assert);var _crypto = require('crypto');exports.a = b; exports.b = _; exports.c = u; exports.d = C; exports.e = w; exports.f = A; exports.g = P; exports.h = S; exports.i = k;
5
- //# sourceMappingURL=chunk-ZWOSOI7Z.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../emmett/src/utils/merge.ts","../../emmett/src/testing/assertions.ts","../../emmett/src/errors/index.ts","../../emmett/src/validation/index.ts","../../emmett/src/eventStore/expectedVersion.ts","../../emmett/src/commandHandling/handleCommand.ts","../../emmett/src/commandHandling/handleCommandWithDecider.ts","../../emmett/src/testing/deciderSpecification.ts","../../emmett/src/eventStore/inMemoryEventStore.ts"],"names":["merge","array","item","where","onExisting","onNotFound","wasFound","result","p","isSubset","superObj","subObj","sup","sub","ele","assertMatches","actual","expected","EmmettError","_EmmettError","options","errorCode","isNumber","message","isString","ValidationError","_ValidationError","IllegalStateError","_IllegalStateError","ValidationErrors","val","assertNotEmptyString","value","assertPositiveNumber","assertUnsignedBigInt","number","STREAM_DOES_NOT_EXIST","NO_CONCURRENCY_CHECK","CommandHandler","evolve","getInitialState","mapToStreamId","id","eventStore","handle","streamName","aggregationResult","state","currentStreamVersion","newEvents","expectedStreamVersion","DeciderCommandHandler","decide","command","assert","randomUUID"],"mappings":"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","sourcesContent":["export const merge = <T>(\n array: T[],\n item: T,\n where: (current: T) => boolean,\n onExisting: (current: T) => T,\n onNotFound: () => T | undefined = () => undefined,\n) => {\n let wasFound = false;\n\n const result = array\n // merge the existing item if matches condition\n .map((p: T) => {\n if (!where(p)) return p;\n\n wasFound = true;\n return onExisting(p);\n })\n // filter out item if undefined was returned\n // for cases of removal\n .filter((p) => p !== undefined)\n // make TypeScript happy\n .map((p) => {\n if (!p) throw Error('That should not happen');\n\n return p;\n });\n\n // if item was not found and onNotFound action is defined\n // try to generate new item\n if (!wasFound) {\n const result = onNotFound();\n\n if (result !== undefined) return [...array, item];\n }\n\n return result;\n};\n","export const isSubset = (superObj: unknown, subObj: unknown): boolean => {\n const sup = superObj as Record<string, unknown>;\n const sub = subObj as Record<string, unknown>;\n\n return Object.keys(sub).every((ele: string) => {\n if (typeof sub[ele] == 'object') {\n return isSubset(\n sup[ele] as Record<string, unknown>,\n sub[ele] as Record<string, unknown>,\n );\n }\n return sub[ele] === sup[ele];\n });\n};\n\nexport const assertMatches = (actual: unknown, expected: unknown) => {\n if (!isSubset(actual, expected))\n throw Error(\n `subObj:\\n${JSON.stringify(expected)}\\nis not subset of\\n${JSON.stringify(actual)}`,\n );\n};\n","import { isNumber, isString } from '../validation';\n\nexport class EmmettError extends Error {\n public errorCode: number;\n\n constructor(\n options?: { errorCode: number; message?: string } | string | number,\n ) {\n const errorCode =\n options && typeof options === 'object' && 'errorCode' in options\n ? options.errorCode\n : isNumber(options)\n ? options\n : 500;\n const message =\n options && typeof options === 'object' && 'message' in options\n ? options.message\n : isString(options)\n ? options\n : `Error with status code '${errorCode}' ocurred during Emmett processing`;\n\n super(message);\n this.errorCode = errorCode;\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, EmmettError.prototype);\n }\n}\n\nexport class ConcurrencyError extends EmmettError {\n constructor(\n public current: string | undefined,\n public expected: string,\n message?: string,\n ) {\n super({\n errorCode: 412,\n message:\n message ??\n `Expected version ${expected.toString()} does not match current ${current?.toString()}`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ConcurrencyError.prototype);\n }\n}\n\nexport class ValidationError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: 400,\n message: message ?? `Validation Error ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\nexport class IllegalStateError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: 403,\n message: message ?? `Illegal State ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, IllegalStateError.prototype);\n }\n}\n\nexport class NotFoundError extends EmmettError {\n constructor(options?: { id: string; type: string; message?: string }) {\n super({\n errorCode: 404,\n message:\n options?.message ??\n (options?.id\n ? options.type\n ? `${options.type} with ${options.id} was not found during Emmett processing`\n : `State with ${options.id} was not found during Emmett processing`\n : options?.type\n ? `${options.type} was not found during Emmett processing`\n : 'State was not found during Emmett processing'),\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, NotFoundError.prototype);\n }\n}\n","import { ValidationError } from '../errors';\n\nexport const enum ValidationErrors {\n NOT_A_NONEMPTY_STRING = 'NOT_A_NONEMPTY_STRING',\n NOT_A_POSITIVE_NUMBER = 'NOT_A_POSITIVE_NUMBER',\n NOT_AN_UNSIGNED_BIGINT = 'NOT_AN_UNSIGNED_BIGINT',\n}\n\nexport const isNumber = (val: unknown): val is number =>\n typeof val === 'number' && val === val;\n\nexport const isString = (val: unknown): val is string =>\n typeof val === 'string';\n\nexport const assertNotEmptyString = (value: unknown): string => {\n if (!isString(value) || value.length === 0) {\n throw new ValidationError(ValidationErrors.NOT_A_NONEMPTY_STRING);\n }\n return value;\n};\n\nexport const assertPositiveNumber = (value: unknown): number => {\n if (!isNumber(value) || value <= 0) {\n throw new ValidationError(ValidationErrors.NOT_A_POSITIVE_NUMBER);\n }\n return value;\n};\n\nexport const assertUnsignedBigInt = (value: string): bigint => {\n const number = BigInt(value);\n if (number < 0) {\n throw new ValidationError(ValidationErrors.NOT_AN_UNSIGNED_BIGINT);\n }\n return number;\n};\n","import { ConcurrencyError } from '../errors';\nimport type { Flavour } from '../typing';\nimport type { DefaultStreamVersionType } from './eventStore';\n\nexport type ExpectedStreamVersion<VersionType = DefaultStreamVersionType> =\n | ExpectedStreamVersionWithValue<VersionType>\n | ExpectedStreamVersionGeneral;\n\nexport type ExpectedStreamVersionWithValue<\n VersionType = DefaultStreamVersionType,\n> = Flavour<VersionType, 'StreamVersion'>;\n\nexport type ExpectedStreamVersionGeneral = Flavour<\n 'STREAM_EXISTS' | 'STREAM_DOES_NOT_EXIST' | 'NO_CONCURRENCY_CHECK',\n 'StreamVersion'\n>;\n\nexport const STREAM_EXISTS = 'STREAM_EXISTS' as ExpectedStreamVersionGeneral;\nexport const STREAM_DOES_NOT_EXIST =\n 'STREAM_DOES_NOT_EXIST' as ExpectedStreamVersionGeneral;\nexport const NO_CONCURRENCY_CHECK =\n 'NO_CONCURRENCY_CHECK' as ExpectedStreamVersionGeneral;\n\nexport const matchesExpectedVersion = <\n StreamVersion = DefaultStreamVersionType,\n>(\n current: StreamVersion | undefined,\n expected: ExpectedStreamVersion<StreamVersion>,\n): boolean => {\n if (expected === NO_CONCURRENCY_CHECK) return true;\n\n if (expected == STREAM_DOES_NOT_EXIST) return current === undefined;\n\n if (expected == STREAM_EXISTS) return current !== undefined;\n\n return current === expected;\n};\n\nexport const assertExpectedVersionMatchesCurrent = <\n StreamVersion = DefaultStreamVersionType,\n>(\n current: StreamVersion | undefined,\n expected: ExpectedStreamVersion<StreamVersion> | undefined,\n): void => {\n expected ??= NO_CONCURRENCY_CHECK;\n\n if (!matchesExpectedVersion(current, expected))\n throw new ExpectedVersionConflictError(current, expected);\n};\n\nexport class ExpectedVersionConflictError<\n VersionType = DefaultStreamVersionType,\n> extends ConcurrencyError {\n constructor(\n current: VersionType | undefined,\n expected: ExpectedStreamVersion<VersionType>,\n ) {\n super(current?.toString(), expected?.toString());\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ExpectedVersionConflictError.prototype);\n }\n}\n","import {\n NO_CONCURRENCY_CHECK,\n STREAM_DOES_NOT_EXIST,\n type AppendToStreamResult,\n type DefaultStreamVersionType,\n type EventStore,\n type ExpectedStreamVersion,\n} from '../eventStore';\nimport type { Event } from '../typing';\n\n// #region command-handler\nexport type CommandHandlerResult<\n State,\n StreamVersion = DefaultStreamVersionType,\n> = AppendToStreamResult<StreamVersion> & { newState: State };\n\nexport const CommandHandler =\n <State, StreamEvent extends Event, StreamVersion = DefaultStreamVersionType>(\n evolve: (state: State, event: StreamEvent) => State,\n getInitialState: () => State,\n mapToStreamId: (id: string) => string = (id) => id,\n ) =>\n async (\n eventStore: EventStore<StreamVersion>,\n id: string,\n handle: (state: State) => StreamEvent | StreamEvent[],\n options?: {\n expectedStreamVersion?: ExpectedStreamVersion<StreamVersion>;\n },\n ): Promise<CommandHandlerResult<State, StreamVersion>> => {\n const streamName = mapToStreamId(id);\n\n // 1. Aggregate the stream\n const aggregationResult = await eventStore.aggregateStream<\n State,\n StreamEvent\n >(streamName, {\n evolve,\n getInitialState,\n read: {\n // expected stream version is passed to fail fast\n // if stream is in the wrong state\n expectedStreamVersion:\n options?.expectedStreamVersion ?? NO_CONCURRENCY_CHECK,\n },\n });\n\n // 2. Use the aggregate state or the initial one (when e.g. stream does not exist)\n const state = aggregationResult?.state ?? getInitialState();\n const currentStreamVersion = aggregationResult?.currentStreamVersion;\n\n // 3. Run business logic\n const result = handle(state);\n\n const newEvents = Array.isArray(result) ? result : [result];\n\n // Either use:\n // - provided expected stream version,\n // - current stream version got from stream aggregation,\n // - or expect stream not to exists otherwise.\n const expectedStreamVersion: ExpectedStreamVersion<StreamVersion> =\n options?.expectedStreamVersion ??\n currentStreamVersion ??\n STREAM_DOES_NOT_EXIST;\n\n // 4. Append result to the stream\n const appendResult = await eventStore.appendToStream(\n streamName,\n newEvents,\n {\n expectedStreamVersion,\n },\n );\n\n // 5. Return result with updated state\n return { ...appendResult, newState: newEvents.reduce(evolve, state) };\n };\n// #endregion command-handler\n","import type {\n DefaultStreamVersionType,\n EventStore,\n ExpectedStreamVersion,\n} from '../eventStore';\nimport type { Command, Event } from '../typing';\nimport type { Decider } from '../typing/decider';\nimport { CommandHandler } from './handleCommand';\n\n// #region command-handler\nexport const DeciderCommandHandler =\n <\n State,\n CommandType extends Command,\n StreamEvent extends Event,\n StreamVersion = DefaultStreamVersionType,\n >(\n {\n decide,\n evolve,\n getInitialState,\n }: Decider<State, CommandType, StreamEvent>,\n mapToStreamId: (id: string) => string = (id) => id,\n ) =>\n async (\n eventStore: EventStore<StreamVersion>,\n id: string,\n command: CommandType,\n options?: {\n expectedStreamVersion?: ExpectedStreamVersion<StreamVersion>;\n },\n ) =>\n CommandHandler<State, StreamEvent, StreamVersion>(\n evolve,\n getInitialState,\n mapToStreamId,\n )(eventStore, id, (state) => decide(command, state), options);\n// #endregion command-handler\n","import assert from 'assert';\n\nexport type DeciderSpecfication<Command, Event> = (\n givenEvents: Event | Event[],\n) => {\n when: (command: Command) => {\n then: (expectedEvents: Event | Event[]) => void;\n thenThrows: <Error>(assert: (error: Error) => boolean) => void;\n };\n};\n\nexport const DeciderSpecification = {\n for: <Command, Event, State>(decider: {\n decide: (command: Command, state: State) => Event | Event[];\n evolve: (state: State, event: Event) => State;\n initialState: () => State;\n }): DeciderSpecfication<Command, Event> => {\n {\n return (givenEvents: Event | Event[]) => {\n return {\n when: (command: Command) => {\n const handle = () => {\n const existingEvents = Array.isArray(givenEvents)\n ? givenEvents\n : [givenEvents];\n\n const currentState = existingEvents.reduce<State>(\n decider.evolve,\n decider.initialState(),\n );\n\n return decider.decide(command, currentState);\n };\n\n return {\n then: (expectedEvents: Event | Event[]): void => {\n const resultEvents = handle();\n\n const resultEventsArray = Array.isArray(resultEvents)\n ? resultEvents\n : [resultEvents];\n\n const expectedEventsArray = Array.isArray(expectedEvents)\n ? expectedEvents\n : [expectedEvents];\n\n assert.deepEqual(resultEventsArray, expectedEventsArray);\n },\n thenThrows: <Error>(check?: (error: Error) => boolean): void => {\n try {\n handle();\n assert.fail('Handler did not fail as expected');\n } catch (error) {\n if (check) assert.ok(check(error as Error));\n }\n },\n };\n },\n };\n };\n }\n },\n};\n","import { randomUUID } from 'crypto';\nimport type { Event } from '../typing';\nimport {\n type AggregateStreamOptions,\n type AggregateStreamResult,\n type AppendToStreamOptions,\n type AppendToStreamResult,\n type EventStore,\n type ReadStreamOptions,\n type ReadStreamResult,\n} from './eventStore';\nimport { assertExpectedVersionMatchesCurrent } from './expectedVersion';\n\nexport type EventMetadata = Readonly<{\n eventId: string;\n streamPosition: number;\n logPosition: bigint;\n}>;\n\nexport type EventEnvelope<E extends Event = Event> = {\n event: E;\n metadata: EventMetadata;\n};\n\nexport type EventHandler<E extends Event = Event> = (\n eventEnvelope: EventEnvelope<E>,\n) => void;\n\nexport const getInMemoryEventStore = (): EventStore => {\n const streams = new Map<string, EventEnvelope[]>();\n\n const getAllEventsCount = () => {\n return Array.from<EventEnvelope[]>(streams.values())\n .map((s) => s.length)\n .reduce((p, c) => p + c, 0);\n };\n\n return {\n async aggregateStream<State, EventType extends Event>(\n streamName: string,\n options: AggregateStreamOptions<State, EventType>,\n ): Promise<AggregateStreamResult<State> | null> {\n const { evolve, getInitialState, read } = options;\n\n const result = await this.readStream<EventType>(streamName, read);\n\n if (!result) return null;\n\n const events = result?.events ?? [];\n\n return {\n currentStreamVersion: BigInt(events.length),\n state: events.reduce(evolve, getInitialState()),\n };\n },\n\n readStream: <EventType extends Event>(\n streamName: string,\n options?: ReadStreamOptions,\n ): Promise<ReadStreamResult<EventType>> => {\n const events = streams.get(streamName);\n const currentStreamVersion = events ? BigInt(events.length) : undefined;\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n options?.expectedStreamVersion,\n );\n\n const from = Number(options && 'from' in options ? options.from : 0);\n const to = Number(\n options && 'to' in options\n ? options.to\n : options && 'maxCount' in options && options.maxCount\n ? options.from + options.maxCount\n : events?.length ?? 1,\n );\n\n const resultEvents =\n events && events.length > 0\n ? events.map((e) => e.event as EventType).slice(from, to)\n : [];\n\n const result: ReadStreamResult<EventType> =\n events && events.length > 0\n ? {\n currentStreamVersion: currentStreamVersion!,\n events: resultEvents,\n }\n : null;\n\n return Promise.resolve(result);\n },\n\n appendToStream: <EventType extends Event>(\n streamName: string,\n events: EventType[],\n options?: AppendToStreamOptions,\n ): Promise<AppendToStreamResult> => {\n const currentEvents = streams.get(streamName) ?? [];\n const currentStreamVersion =\n currentEvents.length > 0 ? BigInt(currentEvents.length) : undefined;\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n options?.expectedStreamVersion,\n );\n\n const eventEnvelopes: EventEnvelope[] = events.map((event, index) => {\n return {\n event,\n metadata: {\n eventId: randomUUID(),\n streamPosition: currentEvents.length + index + 1,\n logPosition: BigInt(getAllEventsCount() + index + 1),\n },\n };\n });\n\n const positionOfLastEventInTheStream = BigInt(\n eventEnvelopes.slice(-1)[0]!.metadata.streamPosition,\n );\n\n streams.set(streamName, [...currentEvents, ...eventEnvelopes]);\n\n const result: AppendToStreamResult = {\n nextExpectedStreamVersion: positionOfLastEventInTheStream,\n };\n\n return Promise.resolve(result);\n },\n };\n};\n"]}