@fayz-ai/shop 0.14.2 → 0.16.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 (44) hide show
  1. package/dist/{chunk-STRNMFC4.js → chunk-26YK5V6P.js} +35 -6
  2. package/dist/chunk-26YK5V6P.js.map +1 -0
  3. package/dist/{chunk-U6HV3LVP.js → chunk-EUFSFVGS.js} +67 -5
  4. package/dist/chunk-EUFSFVGS.js.map +1 -0
  5. package/dist/{chunk-3GERSY5F.js → chunk-UVQ6UUDN.js} +5 -2
  6. package/dist/chunk-UVQ6UUDN.js.map +1 -0
  7. package/dist/{chunk-2WACO2TG.js → chunk-WWQICATY.js} +3 -3
  8. package/dist/{chunk-2WACO2TG.js.map → chunk-WWQICATY.js.map} +1 -1
  9. package/dist/data/checkout-gateways.d.ts +83 -0
  10. package/dist/data/checkout-gateways.d.ts.map +1 -1
  11. package/dist/data/functions.d.ts +3 -1
  12. package/dist/data/functions.d.ts.map +1 -1
  13. package/dist/data/mock-provider.d.ts +4 -0
  14. package/dist/data/mock-provider.d.ts.map +1 -1
  15. package/dist/data/provider.d.ts +106 -2
  16. package/dist/data/provider.d.ts.map +1 -1
  17. package/dist/data/supabase-provider.d.ts +39 -2
  18. package/dist/data/supabase-provider.d.ts.map +1 -1
  19. package/dist/data/tables.d.ts +51 -0
  20. package/dist/data/tables.d.ts.map +1 -1
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +329 -47
  24. package/dist/index.js.map +1 -1
  25. package/dist/inventory/postgrest-double.d.ts +9 -0
  26. package/dist/inventory/postgrest-double.d.ts.map +1 -1
  27. package/dist/inventory/supabase-stock-store.d.ts.map +1 -1
  28. package/dist/inventory/vocabulary.d.ts.map +1 -1
  29. package/dist/inventory.js +1 -1
  30. package/dist/lib/commerce.d.ts.map +1 -1
  31. package/dist/lib/message-events.d.ts.map +1 -1
  32. package/dist/lib/order-events.d.ts +5 -0
  33. package/dist/lib/order-events.d.ts.map +1 -0
  34. package/dist/mock.js +2 -2
  35. package/dist/rules/adapter.d.ts +3 -0
  36. package/dist/rules/adapter.d.ts.map +1 -1
  37. package/dist/rules.js +2 -2
  38. package/dist/runtime.js +3 -3
  39. package/dist/types.d.ts +96 -1
  40. package/dist/types.d.ts.map +1 -1
  41. package/package.json +4 -4
  42. package/dist/chunk-3GERSY5F.js.map +0 -1
  43. package/dist/chunk-STRNMFC4.js.map +0 -1
  44. package/dist/chunk-U6HV3LVP.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/data/media.ts","../src/lib/variant-matrix.ts","../src/lib/order-events.ts","../src/data/mock-provider.ts"],"names":["store","o"],"mappings":";;;;;;AAaA,IAAM,gBAAA,mBAAmB,IAAI,GAAA,CAAI,CAAC,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,KAAK,CAAC,CAAA;AAC5F,IAAM,gBAAA,mBAAmB,IAAI,GAAA,CAAI,CAAC,KAAA,EAAO,OAAO,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAO,KAAK,CAAC,CAAA;AAErE,SAAS,WAAA,CAAY,MAAc,IAAA,EAAyC;AACjF,EAAA,IAAI,IAAA,EAAM,UAAA,CAAW,QAAQ,CAAA,EAAG,OAAO,OAAA;AACvC,EAAA,IAAI,IAAA,EAAM,UAAA,CAAW,QAAQ,CAAA,EAAG,OAAO,OAAA;AACvC,EAAA,MAAM,GAAA,GAAA,CAAO,KAAK,KAAA,CAAM,GAAG,EAAE,GAAA,EAAI,IAAK,IAAI,WAAA,EAAY;AACtD,EAAA,IAAI,gBAAA,CAAiB,GAAA,CAAI,GAAG,CAAA,EAAG,OAAO,OAAA;AACtC,EAAA,IAAI,gBAAA,CAAiB,GAAA,CAAI,GAAG,CAAA,EAAG,OAAO,OAAA;AACtC,EAAA,OAAO,UAAA;AACT;AAUO,SAAS,cAAc,GAAA,EAA4B;AACxD,EAAA,MAAM,KAAA,GAAQ,yDAAA,CAA0D,IAAA,CAAK,GAAG,CAAA;AAChF,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,IAAI;AACF,IAAA,OAAO,kBAAA,CAAmB,KAAA,CAAM,CAAC,CAAE,CAAA;AAAA,EACrC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAM,CAAC,CAAA;AAAA,EAChB;AACF;AASO,SAAS,cAAc,IAAA,EAAsB;AAClD,EAAA,MAAM,OAAO,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,CAAE,KAAI,IAAK,IAAA;AACtC,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,WAAA,EAAa,EAAE,CAAA;AACrC;AAUO,SAAS,uBAAA,CACd,OACA,WAAA,EACW;AACX,EAAA,MAAM,IAAA,GAAO,aAAA,CAAc,KAAA,CAAM,GAAG,CAAA;AACpC,EAAA,MAAM,IAAA,GAAO,aAAA,CAAc,IAAA,IAAQ,KAAA,CAAM,GAAG,CAAA;AAC5C,EAAA,OAAO;AAAA;AAAA;AAAA,IAGL,EAAA,EAAI,QAAQ,KAAA,CAAM,GAAA;AAAA,IAClB,IAAA;AAAA,IACA,KAAK,KAAA,CAAM,GAAA;AAAA,IACX,IAAA,EAAM,YAAY,IAAI,CAAA;AAAA,IACtB,IAAA,EAAM,CAAA;AAAA,IACN,SAAA,EAAA,CAAY,KAAK,KAAA,CAAM,GAAG,EAAE,GAAA,EAAI,IAAK,IAAI,WAAA,EAAY;AAAA,IACrD,SAAA,EAAW,MAAM,SAAA,IAAa,EAAA;AAAA,IAC9B,SAAA,EAAW;AAAA,MACT,IAAA,EAAM,SAAA;AAAA,MACN,IAAI,KAAA,CAAM,SAAA;AAAA,MACV,KAAA,EAAO,WAAA,EAAa,IAAA,EAAK,IAAK,kBAAA;AAAA,MAC9B,cAAc,KAAA,CAAM,EAAA;AAAA,MACpB,SAAS,KAAA,CAAM;AAAA;AACjB,GACF;AACF;AASO,SAAS,eAAA,CAAgB,UAAuB,OAAA,EAAmC;AACxF,EAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,QAAA,CAAS,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAC,CAAA;AAC9C,EAAA,OAAO,CAAC,GAAG,QAAA,EAAU,GAAG,OAAA,CAAQ,OAAO,CAAC,CAAA,KAAM,CAAC,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,EAAE,CAAC,CAAC,CAAA,CAC3D,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,SAAA,CAAU,aAAA,CAAc,CAAA,CAAE,SAAS,CAAC,CAAA;AAC1D;;;ACpFO,IAAM,gBAAA,GAAmB;AACzB,IAAM,wBAAA,GAA2B;AAgBjC,SAAS,kBAAkB,OAAA,EAAqC;AACrE,EAAA,OAAO,IAAA,CAAK,SAAA;AAAA,IACV,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAChB,MAAK,CACL,GAAA,CAAI,CAAC,GAAA,KAAQ,CAAC,GAAA,EAAK,OAAA,CAAQ,GAAG,CAAC,CAAC;AAAA,GACrC;AACF;AAOO,SAAS,qBAAqB,IAAA,EAAuD;AAC1F,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAY;AAClC,EAAA,MAAM,SAA6B,EAAC;AACpC,EAAA,KAAA,MAAW,QAAQ,IAAA,EAAM;AACvB,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,IAAA,EAAK;AAC5B,IAAA,IAAI,CAAC,IAAA,IAAQ,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA,EAAG;AAClC,IAAA,MAAM,SAAmB,EAAC;AAC1B,IAAA,MAAM,UAAA,uBAAiB,GAAA,EAAY;AACnC,IAAA,KAAA,MAAW,GAAA,IAAO,KAAK,MAAA,EAAQ;AAC7B,MAAA,MAAM,KAAA,GAAQ,IAAI,IAAA,EAAK;AACvB,MAAA,IAAI,CAAC,KAAA,IAAS,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA,EAAG;AACrC,MAAA,UAAA,CAAW,IAAI,KAAK,CAAA;AACpB,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,IACnB;AACA,IAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACzB,IAAA,SAAA,CAAU,IAAI,IAAI,CAAA;AAClB,IAAA,MAAA,CAAO,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,CAAA;AAAA,EAC9B;AACA,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,oBAAoB,IAAA,EAAyD;AAC3F,EAAA,MAAM,KAAA,GAAQ,qBAAqB,IAAI,CAAA;AACvC,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAChC,EAAA,IAAI,IAAA,GAA6B,CAAC,EAAE,CAAA;AACpC,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,OAA6B,EAAC;AACpC,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,KAAA,MAAW,KAAA,IAAS,IAAA,CAAK,MAAA,EAAQ,IAAA,CAAK,IAAA,CAAK,EAAE,GAAG,GAAA,EAAK,CAAC,IAAA,CAAK,IAAI,GAAG,OAAO,CAAA;AAAA,IAC3E;AACA,IAAA,IAAA,GAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,oBAAoB,IAAA,EAAkD;AACpF,EAAA,MAAM,KAAA,GAAQ,qBAAqB,IAAI,CAAA;AACvC,EAAA,IAAI,KAAA,CAAM,SAAS,gBAAA,EAAkB;AACnC,IAAA,OAAO,kCAA+B,gBAAgB,CAAA,4CAAA,CAAA;AAAA,EACxD;AACA,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,MAAA,CAAO,CAAC,GAAA,EAAK,SAAS,GAAA,GAAM,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ,CAAC,CAAA;AACrE,EAAA,IAAI,KAAA,CAAM,MAAA,GAAS,CAAA,IAAK,KAAA,GAAQ,wBAAA,EAA0B;AACxD,IAAA,OAAO,CAAA,4BAAA,EAAyB,KAAK,CAAA,4BAAA,EAA4B,wBAAwB,CAAA,+CAAA,CAAA;AAAA,EAC3F;AACA,EAAA,OAAO,IAAA;AACT;AAwCO,SAAS,iBAAA,CACd,MACA,QAAA,EACmB;AACnB,EAAA,MAAM,MAAA,GAAS,oBAAoB,IAAI,CAAA;AACvC,EAAA,MAAM,aAAa,IAAI,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,iBAAiB,CAAC,CAAA;AAExD,EAAA,MAAM,KAAA,uBAAY,GAAA,EAA4B;AAC9C,EAAA,IAAI,cAAA,GAAwC,IAAA;AAC5C,EAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,IAAA,IAAI,QAAQ,gBAAA,EAAkB;AAC5B,MAAA,cAAA,GAAiB,OAAA;AACjB,MAAA;AAAA,IACF;AACA,IAAA,KAAA,CAAM,GAAA,CAAI,iBAAA,CAAkB,OAAA,CAAQ,OAAO,GAAG,OAAO,CAAA;AAAA,EACvD;AAEA,EAAA,MAAM,IAAA,GAA0B;AAAA,IAC9B,MAAM,EAAC;AAAA,IAAG,QAAQ,EAAC;AAAA,IAAG,YAAY,EAAC;AAAA,IAAG,MAAM,EAAC;AAAA,IAAG,SAAS,EAAC;AAAA,IAAG;AAAA,GAC/D;AAEA,EAAA,KAAA,MAAW,CAAC,QAAA,EAAU,OAAO,CAAA,IAAK,MAAA,CAAO,SAAQ,EAAG;AAClD,IAAA,MAAM,UAAU,KAAA,CAAM,GAAA,CAAI,iBAAA,CAAkB,OAAO,CAAC,CAAA,IAAK,IAAA;AACzD,IAAA,MAAM,GAAA,GAAwB,EAAE,OAAA,EAAS,QAAA,EAAU,OAAA,EAAQ;AAC3D,IAAA,IAAA,CAAK,IAAA,CAAK,KAAK,GAAG,CAAA;AAClB,IAAA,IAAI,CAAC,OAAA,EAAS,IAAA,CAAK,MAAA,CAAO,KAAK,GAAG,CAAA;AAAA,SAAA,IACzB,QAAQ,MAAA,KAAW,UAAA,EAAY,IAAA,CAAK,UAAA,CAAW,KAAK,GAAG,CAAA;AAAA,SAC3D,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA;AAAA,EACzB;AAEA,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,OAAO,CAAA,IAAK,KAAA,EAAO;AAClC,IAAA,IAAI,CAAC,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA,IAAK,OAAA,CAAQ,MAAA,KAAW,QAAA,EAAU,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA;AAAA,EACpF;AAEA,EAAA,OAAO,IAAA;AACT;AAQO,SAAS,sBAAsB,QAAA,EAA8C;AAClF,EAAA,MAAM,SAAS,QAAA,CAAS,MAAA,CAAO,CAAC,OAAA,KAAY,OAAA,CAAQ,WAAW,QAAQ,CAAA;AACvE,EAAA,OAAO,OAAO,MAAA,KAAW,CAAA,IAAK,QAAQ,MAAA,CAAO,CAAC,EAAG,gBAAgB,CAAA;AACnE;AAkBO,SAAS,sBAAsB,IAAA,EAAkC;AACtE,EAAA,MAAM,YAAA,GAAe,KAAK,IAAA,CAAK,MAAA,GAAS,KAAK,UAAA,CAAW,MAAA,GAAS,KAAK,MAAA,CAAO,MAAA;AAC7E,EAAA,OAAO,YAAA,KAAiB,CAAA,IAAK,IAAA,CAAK,cAAA,KAAmB,IAAA;AACvD;AAQO,SAAS,gBAAgB,OAAA,EAAuD;AACrF,EAAA,OAAO,CAAC,GAAG,OAAO,CAAA,CACf,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,QAAA,GAAW,CAAA,CAAE,QAAQ,CAAA,CACtC,IAAI,CAAC,MAAA,MAAY,EAAE,IAAA,EAAM,MAAA,CAAO,IAAA,EAAM,MAAA,EAAQ,CAAC,GAAG,MAAA,CAAO,MAAM,CAAA,EAAE,CAAE,CAAA;AACxE;AAkBA,eAAsB,kBAAA,CACpB,QAAA,EACA,SAAA,EACA,IAAA,EACA,QAAA,EAC4B;AAC5B,EAAA,MAAM,OAAA,GAAU,oBAAoB,IAAI,CAAA;AACxC,EAAA,IAAI,OAAA,EAAS,MAAM,IAAI,KAAA,CAAM,OAAO,CAAA;AACpC,EAAA,IAAI,CAAC,SAAS,kBAAA,IAAsB,CAAC,SAAS,oBAAA,IAAwB,CAAC,SAAS,oBAAA,EAAsB;AACpG,IAAA,MAAM,IAAI,MAAM,4CAAyC,CAAA;AAAA,EAC3D;AAEA,EAAA,MAAM,KAAA,GAAQ,qBAAqB,IAAI,CAAA;AACvC,EAAA,MAAM,IAAA,GAAO,iBAAA,CAAkB,KAAA,EAAO,QAAQ,CAAA;AAE9C,EAAA,MAAM,QAAA,CAAS,kBAAA,CAAmB,SAAA,EAAW,KAAK,CAAA;AAElD,EAAA,KAAA,MAAW,GAAA,IAAO,KAAK,MAAA,EAAQ;AAC7B,IAAA,MAAM,QAAA,CAAS,oBAAA,CAAqB,SAAA,EAAW,EAAE,OAAA,EAAS,IAAI,OAAA,EAAS,QAAA,EAAU,GAAA,CAAI,QAAA,EAAU,CAAA;AAAA,EACjG;AACA,EAAA,KAAA,MAAW,GAAA,IAAO,KAAK,UAAA,EAAY;AACjC,IAAA,MAAM,QAAA,CAAS,oBAAA,CAAqB,GAAA,CAAI,OAAA,CAAS,EAAA,EAAI,EAAE,MAAA,EAAQ,QAAA,EAAU,QAAA,EAAU,GAAA,CAAI,QAAA,EAAU,CAAA;AAAA,EACnG;AACA,EAAA,KAAA,MAAW,GAAA,IAAO,KAAK,IAAA,EAAM;AAC3B,IAAA,IAAI,GAAA,CAAI,OAAA,CAAS,QAAA,KAAa,GAAA,CAAI,QAAA,EAAU;AAC1C,MAAA,MAAM,QAAA,CAAS,qBAAqB,GAAA,CAAI,OAAA,CAAS,IAAI,EAAE,QAAA,EAAU,GAAA,CAAI,QAAA,EAAU,CAAA;AAAA,IACjF;AAAA,EACF;AACA,EAAA,KAAA,MAAW,OAAA,IAAW,KAAK,OAAA,EAAS;AAClC,IAAA,OAAO,QAAA,CAAS,qBAAA,GAAwB,OAAA,CAAQ,EAAE,CAAA,IAChD,QAAA,CAAS,oBAAA,CAAqB,OAAA,CAAQ,EAAA,EAAI,EAAE,MAAA,EAAQ,UAAA,EAAY,CAAA,CAAA;AAAA,EACpE;AAEA,EAAA,MAAM,IAAA,GAAO,KAAK,MAAA,CAAO,MAAA,GAAS,KAAK,UAAA,CAAW,MAAA,GAAS,KAAK,IAAA,CAAK,MAAA;AACrE,EAAA,IAAI,KAAK,cAAA,EAAgB;AACvB,IAAA,IAAI,IAAA,GAAO,CAAA,IAAK,IAAA,CAAK,cAAA,CAAe,WAAW,QAAA,EAAU;AAKvD,MAAA,MAAM,QAAA,CAAS,qBAAqB,IAAA,CAAK,cAAA,CAAe,IAAI,EAAE,MAAA,EAAQ,YAAY,CAAA;AAAA,IACpF,WAAW,IAAA,KAAS,CAAA,IAAK,IAAA,CAAK,cAAA,CAAe,WAAW,UAAA,EAAY;AAClE,MAAA,MAAM,QAAA,CAAS,qBAAqB,IAAA,CAAK,cAAA,CAAe,IAAI,EAAE,MAAA,EAAQ,UAAU,CAAA;AAAA,IAClF;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,wBAAA,CAAyB,SAA6B,IAAA,EAA4C;AAChH,EAAA,MAAM,KAAA,GAAQ,IAAA,EAAM,GAAA,CAAI,CAAC,IAAA,KAAS,IAAA,CAAK,IAAI,CAAA,IAAK,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,IAAA,EAAK;AAC1E,EAAA,OAAO,KAAA,CACJ,OAAO,CAAC,IAAA,KAAS,QAAQ,IAAI,CAAA,IAAK,IAAI,CAAA,CACtC,GAAA,CAAI,CAAC,IAAA,KAAS,CAAA,EAAG,IAAI,CAAA,EAAA,EAAK,OAAA,CAAQ,IAAI,CAAC,CAAA,CAAE,CAAA,CACzC,IAAA,CAAK,QAAK,CAAA;AACf;AChRA,IAAM,KAAA,GAAQ,YAAY,MAAM,CAAA;AAEhC,SAAS,KAAA,CAAM,QAAgB,QAAA,EAA0B;AACvD,EAAA,IAAI;AACF,IAAA,OAAO,IAAI,IAAA,CAAK,YAAA,CAAa,OAAA,EAAS,EAAE,KAAA,EAAO,UAAA,EAAY,QAAA,EAAU,QAAA,IAAY,KAAA,EAAO,CAAA,CAAE,OAAO,MAAM,CAAA;AAAA,EACzG,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,GAAG,QAAQ,CAAA,CAAA,EAAI,MAAA,CAAO,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA;AAAA,EACzC;AACF;AAGO,SAAS,kBAAkB,KAAA,EAAuC;AACvE,EAAA,OAAO;AAAA,IACL,YAAA,EAAc,MAAA,CAAO,KAAA,CAAM,WAAW,CAAA;AAAA,IACtC,WAAA,EAAa,KAAA,CAAM,KAAA,CAAM,KAAA,EAAO,MAAM,QAAQ,CAAA;AAAA,IAC9C,WAAA,EAAA,CAAc,KAAA,CAAM,KAAA,IAAS,EAAC,EAC3B,IAAI,CAAC,CAAA,KAAM,CAAA,EAAG,CAAA,CAAE,QAAQ,CAAA,MAAA,EAAM,EAAE,IAAI,CAAA,QAAA,EAAM,KAAA,CAAM,CAAA,CAAE,KAAA,EAAO,KAAA,CAAM,QAAQ,CAAC,CAAA,CAAE,CAAA,CAC1E,IAAA,CAAK,IAAI,CAAA;AAAA,IACZ,aAAA,EAAe,MAAM,YAAA,IAAgB,EAAA;AAAA;AAAA;AAAA;AAAA,IAIrC,cAAA,EAAgB,MAAM,aAAA,IAAiB,EAAA;AAAA,IACvC,cAAA,EAAgB,KAAA,CAAM,eAAA,EAAiB,KAAA,IAAS;AAAA,GAClD;AACF;AAEO,SAAS,cAAA,CAAe,OAAmE,KAAA,EAAoB;AACpH,EAAA,MAAM,GAAA,GAAM,QAAQ,KAAK,CAAA,CAAA;AACzB,EAAA,IAAI;AACF,IAAA,eAAA,CAAgB,GAAA,EAAK,iBAAA,CAAkB,KAAK,CAAA,EAAG;AAAA,MAC7C,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,SAAS,EAAE,IAAA,EAAM,OAAA,EAAS,EAAA,EAAI,MAAM,EAAA;AAAG,KACxC,CAAA;AAAA,EACH,SAAS,GAAA,EAAK;AAEZ,IAAA,KAAA,CAAM,KAAA,CAAM,CAAA,KAAA,EAAQ,GAAG,CAAA,OAAA,CAAA,EAAW,GAAG,CAAA;AAAA,EACvC;AACF;AC1BA,SAAS,GAAA,GAAM;AAAE,EAAA,OAAO,KAAK,MAAA,EAAO,CAAE,SAAS,EAAE,CAAA,CAAE,MAAM,CAAC,CAAA;AAAE;AAC5D,SAAS,GAAA,GAAM;AAAE,EAAA,OAAA,iBAAO,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAE;AAKjD,IAAM,UAAA,GAAa,0BAAA;AACnB,IAAM,aAAA,GAAgB,6BAAA;AACtB,IAAM,aAAA,GAAgB,6BAAA;AACtB,IAAM,YAAA,GAAe,4BAAA;AAIrB,IAAM,YAAA,GAAe,4BAAA;AACrB,IAAM,qBAAA,GAAwB,qCAAA;AAE9B,IAAM,gBAAA,GAAmC;AAAA,EACvC,EAAE,IAAI,cAAA,EAAgB,QAAA,EAAU,QAAQ,IAAA,EAAM,cAAA,EAAgB,OAAO,aAAA,EAAe,GAAA,EAAK,MAAM,OAAA,EAAS,IAAA,EAAM,UAAU,CAAA,EAAG,SAAA,EAAW,KAAI,EAAG,SAAA,EAAW,KAAI;AAC9J,CAAA;AAEA,SAAS,WAAc,GAAA,EAAkB;AACvC,EAAA,IAAI;AACF,IAAA,IAAI,OAAO,YAAA,KAAiB,WAAA,EAAa,OAAO,EAAC;AACjD,IAAA,MAAM,GAAA,GAAM,YAAA,CAAa,OAAA,CAAQ,GAAG,CAAA;AACpC,IAAA,OAAO,GAAA,GAAO,IAAA,CAAK,KAAA,CAAM,GAAG,IAAY,EAAC;AAAA,EAC3C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAEA,SAAS,KAAA,CAAS,KAAa,KAAA,EAAkB;AAC/C,EAAA,IAAI;AACF,IAAA,IAAI,OAAO,iBAAiB,WAAA,EAAa;AACzC,IAAA,YAAA,CAAa,OAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,EACjD,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAqBA,IAAM,eAAA,GAAkB,+BAAA;AACxB,IAAM,cAAA,GAAiB,8BAAA;AACvB,IAAM,mBAAA,GAAsB,mCAAA;AAC5B,IAAM,mBAAA,GAAsB,mCAAA;AAC5B,IAAM,qBAAA,GAAwB,qCAAA;AAE9B,SAAS,gBAAA,GAA2B;AAClC,EAAA,MAAM,QAAA,GAAW,+BAAA;AACjB,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,KAAK,MAAA,EAAO,GAAI,QAAA,CAAS,MAAM,CAAC,CAAA;AACvE,EAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,IAAA,CAAK,EAAE,MAAA,EAAQ,CAAA,EAAE,EAAG,IAAI,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AAC3D,EAAA,OAAO,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AACzC;AAEA,SAAS,YAAY,IAAA,EAAsB;AACzC,EAAA,OAAO,IAAA,CAAK,aAAY,CAAE,OAAA,CAAQ,eAAe,GAAG,CAAA,CAAE,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA;AAC5E;AAEO,IAAM,mBAAN,MAA+C;AAAA,EAwBpD,YAAY,IAAA,EAAqB;AAvBnC,IAAA,IAAA,CAAQ,WAAA,GAA4B,WAAuB,eAAe,CAAA;AACxE,IAAA,IAAA,CAAQ,SAAA,GAAwB,WAAqB,cAAc,CAAA;AACnE,IAAA,IAAA,CAAQ,cAAA,GAAkC,WAA0B,mBAAmB,CAAA;AACvF,IAAA,IAAA,CAAQ,cAAA,GAAkC,WAA0B,mBAAmB,CAAA;AACvF,IAAA,IAAA,CAAQ,gBAAA,GAAsC,WAA4B,qBAAqB,CAAA;AAI/F,IAAA,IAAA,CAAQ,MAAA,GAAkB,WAAkB,UAAU,CAAA;AACtD,IAAA,IAAA,CAAQ,SAAA,GAA4B,WAAyB,aAAa,CAAA;AAC1E,IAAA,IAAA,CAAQ,SAAA,GAA8B,WAA2B,aAAa,CAAA;AAC9E,IAAA,IAAA,CAAQ,YAA4B,MAAM;AACxC,MAAA,MAAM,MAAA,GAAS,WAAyB,YAAY,CAAA;AACpD,MAAA,OAAO,MAAA,CAAO,SAAS,MAAA,GAAS,gBAAA,CAAiB,IAAI,CAAA,CAAA,MAAM,EAAE,GAAG,CAAA,EAAE,CAAE,CAAA;AAAA,IACtE,CAAA,GAAG;AAGH,IAAA,IAAA,CAAQ,YAAA,uBAAmB,GAAA,EAAyB;AAwmBpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,IAAA,CAAQ,mBAAqG,EAAC;AAjmB5G,IAAA,IAAA,CAAK,QAAA,GAAA,CAAY,MAAM,QAAA,IAAY,aAAA,EAAe,IAAI,CAAA,CAAA,MAAM,EAAE,GAAG,CAAA,EAAE,CAAE,CAAA;AACrE,IAAA,IAAA,CAAK,UAAA,GAAA,CAAc,MAAM,UAAA,IAAc,eAAA,EAAiB,IAAI,CAAA,CAAA,MAAM,EAAE,GAAG,CAAA,EAAE,CAAE,CAAA;AAC3E,IAAA,IAAA,CAAK,SAAA,GAAA,CAAa,MAAM,SAAA,IAAa,cAAA,EAAgB,IAAI,CAAA,CAAA,MAAM,EAAE,GAAG,CAAA,EAAE,CAAE,CAAA;AACxE,IAAA,IAAA,CAAK,cAAc,MAAA,CAAO,WAAA;AAAA,MACxB,MAAA,CAAO,OAAA,CAAQ,IAAA,EAAM,QAAA,KAAa,MAAM,QAAA,GAAW,EAAC,GAAI,aAAA,CAAc,EAAE,GAAA,CAAI,CAAC,CAAC,SAAA,EAAW,GAAG,CAAA,KAAM;AAAA,QAChG,SAAA;AAAA,QACA,EAAE,OAAA,EAAS,GAAA,CAAI,OAAA,CAAQ,IAAI,CAAA,CAAA,MAAM,EAAE,GAAG,CAAA,EAAG,MAAA,EAAQ,CAAC,GAAG,CAAA,CAAE,MAAM,CAAA,EAAE,CAAE,CAAA,EAAG,QAAA,EAAU,GAAA,CAAI,QAAA,CAAS,GAAA,CAAI,CAAA,CAAA,MAAM,EAAE,GAAG,CAAA,EAAG,OAAA,EAAS,EAAE,GAAG,CAAA,CAAE,OAAA,EAAQ,GAAI,CAAA;AAAE,OAC5I;AAAA,KACH;AACA,IAAA,IAAA,CAAK,UAAA,GAAA,CAAc,IAAA,EAAM,UAAA,IAAc,EAAC,EAAG,IAAI,CAAA,CAAA,MAAM,EAAE,GAAG,CAAA,EAAE,CAAE,CAAA;AAC9D,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA,EAAM,QAAA,IAAY,EAAC;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,YAAY,MAAA,EAA6B;AAG/C,IAAA,wBAAA,CAAyB,MAAM,CAAA;AAC/B,IAAA,OAAO,kBAAA,CAAmB,MAAA,EAAQ,CAAC,GAAA,KAAQ;AACzC,MAAA,IAAIA,MAAAA,GAAQ,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,GAAG,CAAA;AACrC,MAAA,IAAI,CAACA,MAAAA,EAAO;AACV,QAAAA,MAAAA,GAAQ,sBAAsB,GAAA,EAAK,EAAE,MAAM,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,EAAG,CAAA;AACjE,QAAA,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,GAAA,EAAKA,MAAK,CAAA;AAAA,MAClC;AACA,MAAA,OAAOA,MAAAA;AAAA,IACT,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA,EAIQ,UAAA,GAAa;AAAE,IAAA,IAAA,CAAK,MAAA,GAAS,WAAkB,UAAU,CAAA;AAAA,EAAE;AAAA,EAC3D,aAAA,GAAgB;AAAE,IAAA,IAAA,CAAK,SAAA,GAAY,WAAyB,aAAa,CAAA;AAAA,EAAE;AAAA,EAC3E,aAAA,GAAgB;AAAE,IAAA,IAAA,CAAK,SAAA,GAAY,WAA2B,aAAa,CAAA;AAAA,EAAE;AAAA,EAC7E,YAAA,GAAe;AACrB,IAAA,MAAM,MAAA,GAAS,WAAyB,YAAY,CAAA;AACpD,IAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,IAAA,CAAK,QAAA,GAAW,MAAA;AAAA,EACrC;AAAA,EACQ,aAAA,GAAgB;AAAE,IAAA,KAAA,CAAM,UAAA,EAAY,KAAK,MAAM,CAAA;AAAA,EAAE;AAAA,EACjD,gBAAA,GAAmB;AAAE,IAAA,KAAA,CAAM,aAAA,EAAe,KAAK,SAAS,CAAA;AAAA,EAAE;AAAA,EAC1D,gBAAA,GAAmB;AAAE,IAAA,KAAA,CAAM,aAAA,EAAe,KAAK,SAAS,CAAA;AAAA,EAAE;AAAA,EAC1D,eAAA,GAAkB;AAAE,IAAA,KAAA,CAAM,YAAA,EAAc,KAAK,QAAQ,CAAA;AAAA,EAAE;AAAA;AAAA;AAAA;AAAA,EAM/D,MAAM,aAAa,IAAA,EAAgD;AACjE,IAAA,IAAI,IAAA,GAAO,CAAC,GAAG,IAAA,CAAK,QAAQ,CAAA;AAC5B,IAAA,IAAI,IAAA,EAAM,QAAQ,IAAA,GAAO,IAAA,CAAK,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,KAAW,IAAA,CAAK,MAAM,CAAA;AAClE,IAAA,IAAI,IAAA,EAAM,YAAY,IAAA,GAAO,IAAA,CAAK,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,UAAA,KAAe,IAAA,CAAK,UAAU,CAAA;AAC9E,IAAA,IAAI,IAAA,EAAM,MAAM,IAAA,GAAO,IAAA,CAAK,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,IAAA,KAAS,IAAA,CAAK,IAAI,CAAA;AAC5D,IAAA,IAAI,MAAM,MAAA,EAAQ;AAChB,MAAA,MAAM,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,WAAA,EAAY;AAClC,MAAA,IAAA,GAAO,IAAA,CAAK,MAAA;AAAA,QAAO,CAAA,CAAA,KACjB,EAAE,IAAA,CAAK,WAAA,GAAc,QAAA,CAAS,CAAC,CAAA,IAAA,CAC9B,CAAA,CAAE,WAAA,IAAe,EAAA,EAAI,aAAY,CAAE,QAAA,CAAS,CAAC,CAAA,IAAA,CAC7C,CAAA,CAAE,OAAO,EAAA,EAAI,WAAA,EAAY,CAAE,QAAA,CAAS,CAAC;AAAA,OACxC;AAAA,IACF;AACA,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,IAAW,YAAA;AACjC,IAAA,MAAM,GAAA,GAAM,IAAA,EAAM,KAAA,KAAU,MAAA,GAAS,EAAA,GAAK,CAAA;AAC1C,IAAA,IAAI,IAAA,EAAM,MAAA,IAAU,CAAC,IAAA,CAAK,OAAA,EAAS;AAKjC,MAAA,MAAM,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,WAAA,EAAY;AAClC,MAAA,MAAM,OAAO,CAAC,CAAA,KACZ,EAAE,IAAA,CAAK,WAAA,GAAc,UAAA,CAAW,CAAC,CAAA,GAAI,CAAA,GAAI,EAAE,IAAA,CAAK,WAAA,GAAc,QAAA,CAAS,CAAC,IAAI,CAAA,GAAI,CAAA;AAClF,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,IAAA,CAAK,CAAC,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA,IAAK,CAAA,CAAE,SAAA,GAAY,EAAE,SAAS,CAAA;AAAA,IACpE,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM;AAClB,QAAA,QAAQ,OAAA;AAAS,UACf,KAAK,MAAA;AAAQ,YAAA,OAAO,CAAA,CAAE,IAAA,CAAK,aAAA,CAAc,CAAA,CAAE,IAAI,CAAA,GAAI,GAAA;AAAA,UACnD,KAAK,OAAA;AAAS,YAAA,OAAA,CAAQ,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,KAAA,IAAS,GAAA;AAAA,UAC3C,KAAK,YAAA;AAAc,YAAA,OAAO,CAAA,CAAE,SAAA,CAAU,aAAA,CAAc,CAAA,CAAE,SAAS,CAAA,GAAI,GAAA;AAAA,UACnE;AAAS,YAAA,OAAA,CAAQ,CAAA,CAAE,SAAA,GAAY,CAAA,CAAE,SAAA,IAAa,GAAA;AAAA;AAChD,MACF,CAAC,CAAA;AAAA,IACH;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,IAAU,CAAA;AAC/B,IAAA,IAAI,MAAA,IAAU,IAAA,EAAM,KAAA,EAAO,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,IAAA,EAAM,KAAA,GAAQ,MAAA,GAAS,IAAA,CAAK,KAAA,GAAQ,MAAS,CAAA;AAClG,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,WAAW,EAAA,EAAY;AAAE,IAAA,OAAO,KAAK,QAAA,CAAS,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,EAAE,CAAA,IAAK,IAAA;AAAA,EAAK;AAAA;AAAA;AAAA,EAInF,MAAM,kBAAA,CAAmB,SAAA,EAAmB,IAAA,EAAkE;AAC5G,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,WAAA,CAAY,SAAS,CAAA;AACtC,IAAA,IAAI,CAAC,KAAK,OAAO,EAAE,SAAS,EAAC,EAAG,QAAA,EAAU,EAAC,EAAE;AAC7C,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAM,EAAE,GAAG,CAAA,EAAG,MAAA,EAAQ,CAAC,GAAG,EAAE,MAAM,CAAA,EAAE,CAAE,CAAA,CAAE,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM,CAAA,CAAE,QAAA,GAAW,CAAA,CAAE,QAAQ,CAAA;AAAA,MACvG,QAAA,EAAU,GAAA,CAAI,QAAA,CACX,MAAA,CAAO,CAAA,CAAA,KAAK,IAAA,EAAM,eAAA,IAAmB,CAAA,CAAE,MAAA,KAAW,QAAQ,CAAA,CAC1D,GAAA,CAAI,QAAM,EAAE,GAAG,CAAA,EAAG,OAAA,EAAS,EAAE,GAAG,CAAA,CAAE,OAAA,IAAU,CAAE,CAAA,CAC9C,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,QAAA,GAAW,EAAE,QAAQ;AAAA,KAC3C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,WAAW,SAAA,EAAsC;AAhP3D,IAAA,IAAA,EAAA;AAiPI,IAAA,CAAA,EAAA,GAAA,IAAA,CAAK,WAAA,EAAL,+BAAgC,EAAE,OAAA,EAAS,EAAC,EAAG,QAAA,EAAU,EAAC,EAAE,CAAA;AAC5D,IAAA,OAAO,IAAA,CAAK,YAAY,SAAS,CAAA;AAAA,EACnC;AAAA,EAEA,MAAM,kBAAA,CAAmB,SAAA,EAAmB,KAAA,EAAuD;AACjG,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,UAAA,CAAW,SAAS,CAAA;AACrC,IAAA,MAAM,QAAA,GAAW,IAAI,GAAA,CAAI,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,CAAC,CAAA,CAAE,IAAA,EAAM,CAAC,CAAC,CAAC,CAAA;AAC1D,IAAA,GAAA,CAAI,OAAA,GAAU,KAAA,CAAM,GAAA,CAAI,CAAC,MAAM,QAAA,MAAc;AAAA,MAC3C,IAAI,QAAA,CAAS,GAAA,CAAI,KAAK,IAAI,CAAA,EAAG,MAAM,GAAA,EAAI;AAAA,MACvC,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,MAAA,EAAQ,CAAC,GAAG,IAAA,CAAK,MAAM,CAAA;AAAA,MACvB;AAAA,KACF,CAAE,CAAA;AACF,IAAA,OAAO,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,MAAM,EAAE,GAAG,CAAA,EAAG,MAAA,EAAQ,CAAC,GAAG,CAAA,CAAE,MAAM,GAAE,CAAE,CAAA;AAAA,EAC/D;AAAA,EAEA,MAAM,oBAAA,CAAqB,SAAA,EAAmB,KAAA,EAA2D;AACvG,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,UAAA,CAAW,SAAS,CAAA;AACrC,IAAA,MAAM,GAAA,GAAM,iBAAA,CAAkB,KAAA,CAAM,OAAO,CAAA;AAC3C,IAAA,MAAM,QAAA,GAAW,IAAI,QAAA,CAAS,IAAA,CAAK,OAAK,iBAAA,CAAkB,CAAA,CAAE,OAAO,CAAA,KAAM,GAAG,CAAA;AAE5E,IAAA,IAAI,QAAA,EAAU,OAAO,IAAA,CAAK,oBAAA,CAAqB,QAAA,CAAS,EAAA,EAAI,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,KAAA,CAAM,MAAA,IAAU,UAAU,CAAA;AAE1G,IAAA,MAAM,OAAA,GAA0B;AAAA,MAC9B,IAAI,GAAA,EAAI;AAAA,MACR,SAAA;AAAA,MACA,OAAA,EAAS,EAAE,GAAG,KAAA,CAAM,OAAA,EAAQ;AAAA,MAC5B,GAAA,EAAK,MAAM,GAAA,IAAO,IAAA;AAAA,MAClB,KAAA,EAAO,MAAM,KAAA,IAAS,IAAA;AAAA,MACtB,cAAA,EAAgB,MAAM,cAAA,IAAkB,IAAA;AAAA,MACxC,cAAA,EAAgB,CAAA;AAAA,MAChB,QAAA,EAAU,KAAA,CAAM,QAAA,IAAY,GAAA,CAAI,QAAA,CAAS,MAAA;AAAA,MACzC,MAAA,EAAQ,MAAM,MAAA,IAAU,QAAA;AAAA,MACxB,OAAA,EAAS,MAAM,OAAA,IAAW,IAAA;AAAA,MAC1B,gBAAA,EAAkB,KAAA;AAAA,MAClB,MAAA,EAAQ,MAAM,MAAA,IAAU,IAAA;AAAA,MACxB,UAAA,EAAY,MAAM,UAAA,IAAc,IAAA;AAAA,MAChC,QAAA,EAAU,MAAM,QAAA,IAAY,IAAA;AAAA,MAC5B,OAAA,EAAS,MAAM,OAAA,IAAW,IAAA;AAAA,MAC1B,QAAA,EAAU,MAAM,QAAA,IAAY;AAAA,KAC9B;AACA,IAAA,GAAA,CAAI,QAAA,CAAS,KAAK,OAAO,CAAA;AAGzB,IAAA,KAAA,MAAW,KAAA,IAAS,IAAI,QAAA,EAAU;AAChC,MAAA,IAAI,MAAM,gBAAA,IAAoB,KAAA,CAAM,MAAA,KAAW,QAAA,QAAgB,MAAA,GAAS,UAAA;AAAA,IAC1E;AACA,IAAA,IAAA,CAAK,wBAAwB,SAAS,CAAA;AACtC,IAAA,OAAO,EAAE,GAAG,OAAA,EAAS,OAAA,EAAS,EAAE,GAAG,OAAA,CAAQ,SAAQ,EAAE;AAAA,EACvD;AAAA,EAEA,MAAM,oBAAA,CAAqB,SAAA,EAAmB,KAAA,EAA2D;AACvG,IAAA,KAAA,MAAW,CAAC,WAAW,GAAG,CAAA,IAAK,OAAO,OAAA,CAAQ,IAAA,CAAK,WAAW,CAAA,EAAG;AAC/D,MAAA,MAAM,UAAU,GAAA,CAAI,QAAA,CAAS,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,SAAS,CAAA;AACzD,MAAA,IAAI,CAAC,OAAA,EAAS;AACd,MAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAChD,QAAA,IAAI,KAAA,KAAU,MAAA,EAAY,OAAA,CAA+C,GAAG,CAAA,GAAI,KAAA;AAAA,MAClF;AACA,MAAA,IAAA,CAAK,wBAAwB,SAAS,CAAA;AACtC,MAAA,OAAO,EAAE,GAAG,OAAA,EAAS,OAAA,EAAS,EAAE,GAAG,OAAA,CAAQ,SAAQ,EAAE;AAAA,IACvD;AACA,IAAA,MAAM,IAAI,MAAM,mBAAmB,CAAA;AAAA,EACrC;AAAA,EAEA,MAAM,sBAAsB,SAAA,EAAkC;AAC5D,IAAA,MAAM,KAAK,oBAAA,CAAqB,SAAA,EAAW,EAAE,MAAA,EAAQ,YAAY,CAAA;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eAAA,CAAgB,SAAA,EAAmB,KAAA,EAAgC;AACvE,IAAA,MAAM,SAAS,IAAA,CAAK,GAAA,CAAI,GAAG,IAAA,CAAK,KAAA,CAAM,KAAK,CAAC,CAAA;AAC5C,IAAA,KAAA,MAAW,CAAC,WAAW,GAAG,CAAA,IAAK,OAAO,OAAA,CAAQ,IAAA,CAAK,WAAW,CAAA,EAAG;AAC/D,MAAA,MAAM,UAAU,GAAA,CAAI,QAAA,CAAS,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,SAAS,CAAA;AACzD,MAAA,IAAI,CAAC,OAAA,EAAS;AACd,MAAA,OAAA,CAAQ,cAAA,GAAiB,MAAA;AACzB,MAAA,IAAA,CAAK,wBAAwB,SAAS,CAAA;AACtC,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAI,MAAM,mBAAmB,CAAA;AAAA,EACrC;AAAA,EAEA,MAAM,mBAAA,CAAoB,SAAA,EAAmB,QAAA,EAAmC;AAC9E,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA;AAClC,IAAA,IAAI,MAAA,IAAU,CAAA,EAAG,MAAM,IAAI,MAAM,mDAAmD,CAAA;AACpF,IAAA,KAAA,MAAW,CAAC,WAAW,GAAG,CAAA,IAAK,OAAO,OAAA,CAAQ,IAAA,CAAK,WAAW,CAAA,EAAG;AAC/D,MAAA,MAAM,UAAU,GAAA,CAAI,QAAA,CAAS,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,SAAS,CAAA;AACzD,MAAA,IAAI,CAAC,OAAA,EAAS;AACd,MAAA,OAAA,CAAQ,cAAA,IAAkB,MAAA;AAC1B,MAAA,IAAA,CAAK,wBAAwB,SAAS,CAAA;AACtC,MAAA,OAAO,OAAA,CAAQ,cAAA;AAAA,IACjB;AACA,IAAA,MAAM,IAAI,MAAM,mBAAmB,CAAA;AAAA,EACrC;AAAA,EAEA,MAAM,mBAAA,CACJ,SAAA,EACA,QAAA,EACA,OAAA,EACiB;AACjB,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA;AAClC,IAAA,IAAI,MAAA,IAAU,CAAA,EAAG,MAAM,IAAI,MAAM,mDAAmD,CAAA;AACpF,IAAA,IAAI,SAAS,SAAA,EAAW,OAAO,KAAK,mBAAA,CAAoB,OAAA,CAAQ,WAAW,MAAM,CAAA;AACjF,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,WAAA,CAAY,SAAS,CAAA,EAAG,QAAA,CAAS,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,KAAW,QAAQ,CAAA,IAAK,EAAC;AAC9F,IAAA,IAAI,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA,CAAK,oBAAoB,QAAA,CAAS,CAAC,CAAA,CAAE,EAAA,EAAI,MAAM,CAAA;AACjF,IAAA,IAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AACvB,MAAA,MAAM,IAAI,MAAM,oFAAyE,CAAA;AAAA,IAC3F;AACA,IAAA,MAAM,UAAU,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,SAAS,CAAA;AAC1D,IAAA,IAAI,CAAC,OAAA,EAAS,MAAM,IAAI,MAAM,mBAAmB,CAAA;AACjD,IAAA,OAAA,CAAQ,iBAAiB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAA,CAAQ,cAAc,CAAA,GAAI,MAAA;AAC/D,IAAA,OAAO,OAAA,CAAQ,cAAA;AAAA,EACjB;AAAA;AAAA,EAGQ,wBAAwB,SAAA,EAAyB;AACvD,IAAA,MAAM,UAAU,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,SAAS,CAAA;AAC1D,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,WAAA,CAAY,SAAS,CAAA;AACtC,IAAA,IAAI,CAAC,OAAA,IAAW,CAAC,GAAA,EAAK;AACtB,IAAA,MAAM,SAAS,GAAA,CAAI,QAAA,CAAS,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,WAAW,QAAQ,CAAA;AAC7D,IAAA,OAAA,CAAQ,cAAA,GAAiB,OAAO,MAAA,CAAO,CAAC,KAAK,CAAA,KAAM,GAAA,GAAM,CAAA,CAAE,cAAA,EAAgB,CAAC,CAAA;AAAA,EAC9E;AAAA,EAEA,MAAM,cAAc,KAAA,EAA6C;AAC/D,IAAA,MAAM,IAAa,EAAE,EAAA,EAAI,KAAI,EAAG,QAAA,EAAU,QAAQ,IAAA,EAAM,KAAA,CAAM,MAAM,IAAA,EAAM,KAAA,CAAM,QAAQ,KAAA,CAAM,IAAA,CAAK,aAAY,CAAE,OAAA,CAAQ,QAAQ,GAAG,CAAA,EAAG,WAAA,EAAa,KAAA,CAAM,eAAe,IAAA,EAAM,KAAA,EAAO,MAAM,KAAA,EAAO,cAAA,EAAgB,MAAM,cAAA,IAAkB,IAAA,EAAM,UAAU,KAAA,CAAM,QAAA,IAAY,OAAO,MAAA,EAAQ,KAAA,CAAM,UAAU,QAAA,EAAU,cAAA,EAAgB,MAAM,cAAA,IAAkB,CAAA,EAAG,GAAA,EAAK,KAAA,CAAM,OAAO,IAAA,EAAM,SAAA,EAAW,MAAM,SAAA,IAAa,CAAA,EAAG,UAAU,KAAA,CAAM,QAAA,IAAY,EAAC,EAAG,MAAA,EAAQ,EAAC,EAAG,UAAA,EAAY,MAAM,UAAA,IAAc,IAAA,EAAM,cAAc,IAAA,EAAM,UAAA,EAAY,KAAA,CAAM,UAAA,IAAc,MAAM,MAAA,EAAQ,KAAA,CAAM,UAAU,IAAA,EAAM,UAAA,EAAY,MAAM,UAAA,IAAc,IAAA,EAAM,UAAU,KAAA,CAAM,QAAA,IAAY,EAAC,EAAG,SAAA,EAAW,KAAI,EAAG,SAAA,EAAW,KAAI,EAAE;AAC7qB,IAAA,IAAA,CAAK,QAAA,CAAS,KAAK,CAAC,CAAA;AAAG,IAAA,OAAO,CAAA;AAAA,EAChC;AAAA,EAEA,MAAM,aAAA,CAAc,EAAA,EAAY,KAAA,EAA6C;AAC3E,IAAA,MAAM,IAAI,IAAA,CAAK,QAAA,CAAS,UAAU,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AAClD,IAAA,IAAI,CAAA,GAAI,CAAA,EAAG,MAAM,IAAI,MAAM,mBAAmB,CAAA;AAC9C,IAAA,IAAA,CAAK,QAAA,CAAS,CAAC,CAAA,GAAI,EAAE,GAAG,IAAA,CAAK,QAAA,CAAS,CAAC,CAAA,EAAG,GAAG,KAAA,EAAO,SAAA,EAAW,KAAI,EAAE;AACrE,IAAA,OAAO,IAAA,CAAK,SAAS,CAAC,CAAA;AAAA,EACxB;AAAA,EAEA,MAAM,cAAc,EAAA,EAAY;AAAE,IAAA,IAAA,CAAK,WAAW,IAAA,CAAK,QAAA,CAAS,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AAAA,EAAE;AAAA,EACzF,MAAM,kBAAA,CAAmB,UAAA,EAAoB,KAAA,EAAoC;AAAE,IAAA,MAAM,IAAI,MAAM,yCAAyC,CAAA;AAAA,EAAE;AAAA,EAE9I,MAAM,mBAAmB,OAAA,EAAiB;AACxC,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,CAAO,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,EAAA,KAAO,OAAO,CAAA,GACtE,EAAE,GAAG,CAAA,EAAG,MAAA,EAAQ,CAAA,CAAE,MAAA,CAAO,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,EAAA,KAAO,OAAO,CAAA,EAAE,GACvD,CAAC,CAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAA,GAAuC;AAC3C,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,OACrC,CAAA,CAAE,MAAA,CAAO,GAAA,CAAI,CAAA,KAAA,KAAS,uBAAA,CAAwB,KAAA,EAAO,CAAA,CAAE,IAAI,CAAC,CAAC,CAAA;AAC/D,IAAA,OAAO,eAAA,CAAgB,QAAA,EAAU,EAAE,CAAA;AAAA,EACrC;AAAA,EAEA,MAAM,qBAAqB,KAAA,EAA2D;AACpF,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,MAAM,KAAK,GAAA,EAAI;AACf,IAAA,MAAM,OAAA,GAA0B;AAAA,MAC9B,IAAI,GAAA,EAAI;AAAA,MACR,QAAA,EAAU,MAAA;AAAA,MACV,SAAA,EAAW,MAAM,SAAA,IAAa,IAAA;AAAA,MAC9B,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,WAAA,EAAa,MAAM,WAAA,IAAe,IAAA;AAAA,MAClC,cAAc,KAAA,CAAM,YAAA;AAAA,MACpB,eAAe,KAAA,CAAM,aAAA;AAAA,MACrB,aAAA,EAAe,MAAM,aAAA,IAAiB,IAAA;AAAA,MACtC,OAAA,EAAS,MAAM,OAAA,IAAW,IAAA;AAAA,MAC1B,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,SAAA,EAAW,MAAM,SAAA,IAAa,IAAA;AAAA,MAC9B,MAAA,EAAQ,KAAA;AAAA,MACR,QAAA,EAAU,KAAA,CAAM,QAAA,IAAY,EAAC;AAAA,MAC7B,SAAA,EAAW,EAAA;AAAA,MACX,SAAA,EAAW;AAAA,KACb;AACA,IAAA,IAAA,CAAK,SAAA,CAAU,QAAQ,OAAO,CAAA;AAC9B,IAAA,IAAA,CAAK,gBAAA,EAAiB;AACtB,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,MAAM,qBAAqB,IAAA,EAA+D;AACxF,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,IAAI,IAAA,GAAO,CAAC,GAAG,IAAA,CAAK,SAAS,CAAA;AAC7B,IAAA,IAAI,IAAA,EAAM,SAAA,EAAW,IAAA,GAAO,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,SAAA,KAAc,IAAA,CAAK,SAAS,CAAA;AAC7E,IAAA,IAAI,MAAM,aAAA,EAAe;AACvB,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,aAAA,CAAc,WAAA,EAAY;AAC7C,MAAA,IAAA,GAAO,IAAA,CAAK,OAAO,CAAC,CAAA,KAAM,EAAE,aAAA,CAAc,WAAA,OAAkB,KAAK,CAAA;AAAA,IACnE;AACA,IAAA,IAAI,IAAA,EAAM,MAAA,EAAQ,IAAA,GAAO,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,KAAW,IAAA,CAAK,MAAM,CAAA;AACpE,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,SAAA,CAAU,aAAA,CAAc,CAAA,CAAE,SAAS,CAAC,CAAA;AAC1D,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,IAAU,CAAA;AAC/B,IAAA,IAAI,MAAA,IAAU,IAAA,EAAM,KAAA,EAAO,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,IAAA,EAAM,KAAA,GAAQ,MAAA,GAAS,IAAA,CAAK,KAAA,GAAQ,MAAS,CAAA;AAClG,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cAAA,GAAiB;AAAE,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,UAAU,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,SAAA,GAAY,CAAA,CAAE,SAAS,CAAA;AAAA,EAAE;AAAA,EAE/F,MAAM,eAAe,KAAA,EAA+C;AAClE,IAAA,MAAM,CAAA,GAAc,EAAE,EAAA,EAAI,GAAA,IAAO,QAAA,EAAU,MAAA,EAAQ,IAAA,EAAM,KAAA,CAAM,MAAM,IAAA,EAAM,KAAA,CAAM,IAAA,IAAQ,KAAA,CAAM,KAAK,WAAA,EAAY,CAAE,OAAA,CAAQ,MAAA,EAAQ,GAAG,CAAA,EAAG,WAAA,EAAa,KAAA,CAAM,WAAA,IAAe,MAAM,QAAA,EAAU,KAAA,CAAM,QAAA,IAAY,IAAA,EAAM,WAAW,KAAA,CAAM,SAAA,IAAa,CAAA,EAAG,SAAA,EAAW,KAAI,EAAE;AACpQ,IAAA,IAAA,CAAK,UAAA,CAAW,KAAK,CAAC,CAAA;AAAG,IAAA,OAAO,CAAA;AAAA,EAClC;AAAA,EAEA,MAAM,cAAA,CAAe,EAAA,EAAY,KAAA,EAA+C;AAC9E,IAAA,MAAM,IAAI,IAAA,CAAK,UAAA,CAAW,UAAU,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AACpD,IAAA,IAAI,CAAA,GAAI,CAAA,EAAG,MAAM,IAAI,MAAM,oBAAoB,CAAA;AAC/C,IAAA,IAAA,CAAK,UAAA,CAAW,CAAC,CAAA,GAAI,EAAE,GAAG,KAAK,UAAA,CAAW,CAAC,CAAA,EAAG,GAAG,KAAA,EAAM;AACvD,IAAA,OAAO,IAAA,CAAK,WAAW,CAAC,CAAA;AAAA,EAC1B;AAAA,EAEA,MAAM,eAAe,EAAA,EAAY;AAAE,IAAA,IAAA,CAAK,aAAa,IAAA,CAAK,UAAA,CAAW,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AAAA,EAAE;AAAA;AAAA;AAAA;AAAA,EAM9F,MAAM,WAAW,IAAA,EAA4C;AAC3D,IAAA,IAAA,CAAK,UAAA,EAAW;AAChB,IAAA,IAAI,IAAA,GAAO,CAAC,GAAG,IAAA,CAAK,MAAM,CAAA;AAC1B,IAAA,IAAI,IAAA,EAAM,QAAQ,IAAA,GAAO,IAAA,CAAK,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,KAAW,IAAA,CAAK,MAAM,CAAA;AAClE,IAAA,IAAI,IAAA,EAAM,iBAAiB,IAAA,GAAO,IAAA,CAAK,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,eAAA,KAAoB,IAAA,CAAK,eAAe,CAAA;AAC7F,IAAA,IAAI,IAAA,EAAM,mBAAmB,IAAA,GAAO,IAAA,CAAK,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,iBAAA,KAAsB,IAAA,CAAK,iBAAiB,CAAA;AACnG,IAAA,IAAI,IAAA,EAAM,YAAY,IAAA,GAAO,IAAA,CAAK,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,UAAA,KAAe,IAAA,CAAK,UAAU,CAAA;AAC9E,IAAA,IAAI,MAAM,aAAA,EAAe;AACvB,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,aAAA,CAAc,WAAA,EAAY;AAC7C,MAAA,IAAA,GAAO,IAAA,CAAK,OAAO,CAAA,CAAA,KAAA,CAAM,CAAA,CAAE,iBAAiB,EAAA,EAAI,WAAA,OAAkB,KAAK,CAAA;AAAA,IACzE;AACA,IAAA,IAAI,MAAM,MAAA,EAAQ;AAChB,MAAA,MAAM,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,WAAA,EAAY;AAClC,MAAA,IAAA,GAAO,IAAA,CAAK,MAAA;AAAA,QAAO,CAAA,CAAA,KAAA,CAChB,EAAE,YAAA,IAAgB,EAAA,EAAI,aAAY,CAAE,QAAA,CAAS,CAAC,CAAA,IAAA,CAC9C,CAAA,CAAE,aAAA,IAAiB,IAAI,WAAA,EAAY,CAAE,SAAS,CAAC,CAAA,IAChD,OAAO,CAAA,CAAE,WAAW,CAAA,CAAE,QAAA,CAAS,CAAC;AAAA,OAClC;AAAA,IACF;AACA,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,SAAA,CAAU,aAAA,CAAc,CAAA,CAAE,SAAS,CAAC,CAAA;AAC1D,IAAA,IAAI,MAAM,KAAA,EAAO,IAAA,GAAO,KAAK,KAAA,CAAM,CAAA,EAAG,KAAK,KAAK,CAAA;AAChD,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,SAAS,EAAA,EAAY;AACzB,IAAA,IAAA,CAAK,UAAA,EAAW;AAChB,IAAA,OAAO,KAAK,MAAA,CAAO,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,EAAE,CAAA,IAAK,IAAA;AAAA,EAC/C;AAAA,EAEA,MAAM,YAAY,KAAA,EAAyC;AACzD,IAAA,IAAA,CAAK,UAAA,EAAW;AAChB,IAAA,MAAM,QAAA,GAAW,KAAA,CAAM,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAA,CAAE,QAAA,GAAW,CAAA,CAAE,SAAA,EAAW,CAAC,CAAA;AAC7E,IAAA,MAAM,aAAA,GAAgB,MAAM,aAAA,IAAiB,CAAA;AAC7C,IAAA,MAAM,aAAA,GAAgB,MAAM,aAAA,IAAiB,CAAA;AAC7C,IAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,CAAA,CAAO,WAAW,aAAA,GAAgB,aAAA,IAAiB,GAAG,CAAA,GAAI,GAAA;AAC7E,IAAA,MAAM,UAAU,GAAA,EAAI;AACpB,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,EAAGC,EAAAA,KAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAGA,EAAAA,CAAE,WAAW,GAAG,GAAI,CAAA;AAC/E,IAAA,MAAM,CAAA,GAAW;AAAA,MACf,EAAA,EAAI,OAAA;AAAA,MACJ,QAAA,EAAU,MAAA;AAAA,MACV,aAAa,SAAA,GAAY,CAAA;AAAA,MACzB,MAAA,EAAQ,MAAA;AAAA,MACR,eAAA,EAAiB,SAAA;AAAA,MACjB,iBAAA,EAAmB,aAAA;AAAA,MACnB,QAAA,EAAU,MAAM,QAAA,IAAY,KAAA;AAAA,MAC5B,QAAA,EAAU,IAAA,CAAK,KAAA,CAAM,QAAA,GAAW,GAAG,CAAA,GAAI,GAAA;AAAA,MACvC,QAAA,EAAU,CAAA;AAAA,MACV,aAAA;AAAA,MACA,aAAA;AAAA,MACA,KAAA;AAAA,MACA,UAAA,EAAY,MAAM,UAAA,IAAc,IAAA;AAAA,MAChC,YAAA,EAAc,MAAM,YAAA,IAAgB,IAAA;AAAA,MACpC,aAAA,EAAe,MAAM,aAAA,IAAiB,IAAA;AAAA,MACtC,YAAA,EAAc,MAAM,YAAA,IAAgB,IAAA;AAAA,MACpC,KAAA,EAAO,MAAM,KAAA,IAAS,IAAA;AAAA,MACtB,eAAA,EAAiB,IAAA;AAAA;AAAA;AAAA,MAGjB,iBAAA,EAAmB,IAAA;AAAA,MACnB,MAAA,EAAQ,IAAA;AAAA,MACR,OAAO,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA,CAAA,MAAM,EAAE,IAAI,GAAA,EAAI,EAAG,OAAA,EAAS,SAAA,EAAW,EAAE,SAAA,IAAa,IAAA,EAAM,MAAM,CAAA,CAAE,IAAA,EAAM,KAAK,CAAA,CAAE,GAAA,IAAO,IAAA,EAAM,QAAA,EAAU,EAAE,QAAA,EAAU,SAAA,EAAW,EAAE,SAAA,EAAW,KAAA,EAAO,KAAK,KAAA,CAAM,CAAA,CAAE,WAAW,CAAA,CAAE,SAAA,GAAY,GAAG,CAAA,GAAI,GAAA,EAAK,UAAU,CAAA,CAAE,QAAA,IAAY,MAAK,CAAE,CAAA;AAAA,MAC3P,WAAW,GAAA,EAAI;AAAA,MACf,WAAW,GAAA;AAAI,KACjB;AACA,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAClB,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,OAAO,CAAA;AAAA,EACT;AAAA,EAEA,MAAM,WAAA,CAAY,EAAA,EAAY,KAAA,EAAyC;AACrE,IAAA,IAAA,CAAK,UAAA,EAAW;AAChB,IAAA,MAAM,IAAI,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AAChD,IAAA,IAAI,CAAA,GAAI,CAAA,EAAG,MAAM,IAAI,MAAM,iBAAiB,CAAA;AAC5C,IAAA,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,GAAI,EAAE,GAAG,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,EAAG,GAAG,KAAA,EAAO,SAAA,EAAW,KAAI,EAAE;AACjE,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,OAAO,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAW,KAAA,EAAwC;AACvD,IAAA,IAAA,CAAK,UAAA,EAAW;AAChB,IAAA,IAAA,CAAK,aAAA,EAAc;AAGnB,IAAA,IAAI,UAAA,GAAa,MAAM,UAAA,IAAc,IAAA;AACrC,IAAA,IAAI,YAAA,GAAe,KAAA,CAAM,QAAA,EAAU,IAAA,EAAM,MAAK,IAAK,IAAA;AACnD,IAAA,MAAM,QAAQ,KAAA,CAAM,QAAA,EAAU,OAAO,IAAA,EAAK,CAAE,aAAY,IAAK,IAAA;AAC7D,IAAA,IAAI,CAAC,cAAc,KAAA,EAAO;AACxB,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,CAAA,CAAA,KAAA,CAAM,EAAE,KAAA,IAAS,EAAA,EAAI,WAAA,EAAY,KAAM,KAAK,CAAA;AACjF,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,UAAA,GAAa,QAAA,CAAS,EAAA;AACtB,QAAA,YAAA,GAAe,YAAA,IAAgB,GAAG,QAAA,CAAS,SAAS,IAAI,QAAA,CAAS,QAAQ,GAAG,IAAA,EAAK;AAAA,MACnF,CAAA,MAAO;AACL,QAAA,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,YAAA,IAAgB,KAAA,EAAO,MAAM,GAAG,CAAA;AAC1D,QAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,cAAA,CAAe,EAAE,SAAA,EAAW,KAAA,IAAS,KAAA,EAAO,QAAA,EAAU,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,EAAG,OAAO,CAAA;AACxG,QAAA,UAAA,GAAa,OAAA,CAAQ,EAAA;AAAA,MACvB;AAAA,IACF;AAKA,IAAA,MAAM,QAAmC,EAAC;AAE1C,IAAA,MAAM,cAA0F,EAAC;AAGjG,IAAA,MAAM,gBAAgC,EAAC;AACvC,IAAA,IAAI,QAAA,GAAW,CAAA;AACf,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,IAAI,KAAK,KAAA,CAAM,KAAA,CAAM,SAAQ,EAAG;AACjD,MAAA,MAAM,OAAA,GAAU,KAAK,QAAA,CAAS,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,KAAK,SAAS,CAAA;AAC/D,MAAA,IAAI,CAAC,OAAA,IAAW,OAAA,CAAQ,MAAA,KAAW,QAAA,EAAU,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,IAAA,CAAK,SAAS,CAAA,CAAE,CAAA;AACrG,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI,KAAK,SAAA,EAAW;AAClB,QAAA,OAAA,GAAU,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,SAAS,GAAG,QAAA,CAAS,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,EAAA,KAAO,IAAA,CAAK,SAAA,IAAa,CAAA,CAAE,WAAW,QAAQ,CAAA;AAC/G,QAAA,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,CAAA,qBAAA,EAAwB,IAAA,CAAK,SAAS,CAAA,CAAE,CAAA;AACtE,QAAA,IAAI,OAAA,CAAQ,cAAA,GAAiB,IAAA,CAAK,QAAA,EAAU,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,OAAA,CAAQ,IAAI,CAAA,CAAE,CAAA;AAAA,MACtG,CAAA,MAAA,IAAW,OAAA,CAAQ,cAAA,GAAiB,IAAA,CAAK,QAAA,EAAU;AACjD,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,OAAA,CAAQ,IAAI,CAAA,CAAE,CAAA;AAAA,MAC1D;AACA,MAAA,MAAM,SAAA,GAAY,OAAA,EAAS,KAAA,IAAS,OAAA,CAAQ,KAAA;AAC5C,MAAA,MAAM,QAAQ,IAAA,CAAK,YAAA,KACb,OAAA,GAAU,MAAA,CAAO,QAAQ,OAAA,CAAQ,OAAO,CAAA,CAAE,IAAA,CAAK,CAAC,CAAC,CAAC,CAAA,EAAG,CAAC,CAAC,CAAA,KAAM,CAAA,CAAE,aAAA,CAAc,CAAC,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAC,GAAG,CAAC,CAAA,KAAM,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA,CAAE,CAAA,CAAE,IAAA,CAAK,QAAK,CAAA,GAAI,EAAA,CAAA;AACnI,MAAA,MAAM,IAAA,GAAO,QAAQ,CAAA,EAAG,OAAA,CAAQ,IAAI,CAAA,EAAA,EAAK,KAAK,MAAM,OAAA,CAAQ,IAAA;AAC5D,MAAA,MAAM,SAAA,GAAY,YAAY,IAAA,CAAK,QAAA;AACnC,MAAA,QAAA,IAAY,SAAA;AACZ,MAAA,WAAA,CAAY,IAAA,CAAK,EAAE,SAAA,EAAW,OAAA,CAAQ,IAAI,UAAA,EAAY,OAAA,CAAQ,UAAA,EAAY,SAAA,EAAW,CAAA;AAIrF,MAAA,aAAA,CAAc,IAAA,CAAK;AAAA,QACjB,IAAI,CAAA,EAAG,KAAK,IAAI,IAAA,CAAK,SAAA,IAAa,QAAQ,EAAE,CAAA,CAAA;AAAA,QAC5C,WAAW,OAAA,CAAQ,EAAA;AAAA,QACnB,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,SAAA;AAAA,QACA,YAAY,OAAA,CAAQ,UAAA;AAAA,QACpB,YAAA,EAAc,OAAO,OAAA,CAAQ,QAAA,EAAU,eAAe,QAAA,GAAW,OAAA,CAAQ,SAAS,UAAA,GAAa;AAAA,OAChG,CAAA;AACD,MAAA,KAAA,CAAM,IAAA,CAAK,EAAE,SAAA,EAAW,OAAA,CAAQ,IAAI,IAAA,EAAM,GAAA,EAAK,OAAA,EAAS,GAAA,IAAO,OAAA,CAAQ,GAAA,IAAO,QAAW,QAAA,EAAU,IAAA,CAAK,UAAU,SAAA,EAAW,QAAA,EAAU,QAAQ,MAAA,CAAO,CAAC,CAAA,EAAG,GAAA,EAAK,CAAA;AAAA,IACjK;AACA,IAAA,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,QAAA,GAAW,GAAG,CAAA,GAAI,GAAA;AAGxC,IAAA,IAAI,gBAAgB,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,aAAA,IAAiB,GAAG,CAAC,CAAA;AACxD,IAAA,IAAI,aAAA,GAAgB,CAAA;AACpB,IAAA,IAAI,WAAA,GAA6B,IAAA;AAWjC,IAAA,MAAM,OAAA,GAAU,MAAM,YAAA,GAAe,CAAC,MAAM,YAAA,CAAa,IAAA,EAAM,CAAA,GAAI,EAAC;AACpE,IAAA,MAAM,IAAA,GAAyB;AAAA,MAC7B,KAAA,EAAO,aAAA;AAAA,MACP,aAAA;AAAA,MACA,UAAU,EAAE,KAAA,EAAO,KAAA,CAAM,QAAA,EAAU,SAAS,IAAA,EAAK;AAAA,MACjD,KAAA,EAAO,OAAA;AAAA,MACP,UAAU,KAAA,CAAM;AAAA,KAClB;AACA,IAAA,MAAM,OAAA,GAAU,MAAM,gBAAA,CAAiB,IAAI,CAAA;AAC3C,IAAA,MAAM,UAAU,uBAAA,CAAwB,IAAA,EAAM,KAAK,UAAA,EAAY,EAAE,SAAS,CAAA;AAE1E,IAAA,IAAI,qBAAA,GAAwB,CAAA;AAC5B,IAAA,IAAI,yBAAA,GAA4B,CAAA;AAChC,IAAA,MAAM,iBAAA,uBAAwB,GAAA,EAAY;AAC1C,IAAA,MAAM,UAAA,uBAAiB,GAAA,EAAY;AACnC,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,iBAAA,CAAkB,GAAA,CAAI,OAAO,WAAW,CAAA;AACxC,MAAA,IAAI,MAAA,CAAO,MAAM,UAAA,CAAW,GAAA,CAAI,OAAO,IAAA,CAAK,IAAA,EAAK,CAAE,WAAA,EAAa,CAAA;AAChE,MAAA,IAAI,MAAA,CAAO,MAAA,KAAW,iBAAA,EAAmB,qBAAA,IAAyB,MAAA,CAAO,MAAA;AAAA,WAAA,IAChE,MAAA,CAAO,MAAA,KAAW,qBAAA,EAAuB,yBAAA,IAA6B,MAAA,CAAO,MAAA;AAAA,WAAA,IAC7E,MAAA,CAAO,WAAW,aAAA,EAAe;AAGxC,QAAA,MAAM,OAAA,GAAU,KAAK,QAAA,CAAS,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,OAAO,SAAS,CAAA;AACjE,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,KAAA,CAAM,IAAA,CAAK,EAAE,SAAA,EAAW,OAAA,CAAQ,IAAI,IAAA,EAAM,OAAA,CAAQ,IAAA,EAAM,GAAA,EAAK,OAAA,CAAQ,GAAA,IAAO,QAAW,QAAA,EAAU,MAAA,CAAO,QAAA,EAAU,SAAA,EAAW,CAAA,EAAG,QAAA,EAAU,QAAQ,MAAA,CAAO,CAAC,CAAA,EAAG,GAAA,EAAK,CAAA;AAAA,QACpK;AAAA,MACF;AAAA,IACF;AAEA,IAAA,KAAA,MAAW,SAAA,IAAa,KAAK,UAAA,EAAY;AACvC,MAAA,IAAI,iBAAA,CAAkB,IAAI,SAAA,CAAU,EAAE,GAAG,SAAA,CAAU,SAAA,GAAA,CAAa,SAAA,CAAU,SAAA,IAAa,CAAA,IAAK,CAAA;AAAA,IAC9F;AACA,IAAA,aAAA,IAAiB,IAAA,CAAK,KAAA,CAAM,qBAAA,GAAwB,GAAG,CAAA,GAAI,GAAA;AAC3D,IAAA,aAAA,GAAgB,IAAA,CAAK,IAAI,CAAA,EAAG,IAAA,CAAK,OAAO,aAAA,GAAgB,yBAAA,IAA6B,GAAG,CAAA,GAAI,GAAG,CAAA;AAC/F,IAAA,IAAI,KAAA,CAAM,YAAA,IAAgB,UAAA,CAAW,GAAA,CAAI,KAAA,CAAM,aAAa,IAAA,EAAK,CAAE,WAAA,EAAa,CAAA,EAAG;AACjF,MAAA,WAAA,GAAc,KAAA,CAAM,YAAA,CAAa,IAAA,EAAK,CAAE,WAAA,EAAY;AAAA,IACtD;AAMA,IAAA,IAAI,KAAA,CAAM,YAAA,IAAgB,CAAC,WAAA,EAAa;AACtC,MAAA,MAAM,IAAA,GAAO,KAAA,CAAM,YAAA,CAAa,IAAA,GAAO,WAAA,EAAY;AACnD,MAAA,MAAM,CAAA,GAAI,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,CAAA,CAAA,KAAA,CAAM,EAAE,IAAA,IAAQ,EAAA,EAAI,WAAA,EAAY,KAAM,IAAI,CAAA;AACxE,MAAA,MAAM,KAAK,GAAA,EAAI;AACf,MAAA,MAAM,QAAA,GAAW,CAAC,CAAA,EAAG,WAAA,IAAe,YAAY,CAAA,CAAE,WAAA;AAClD,MAAA,MAAM,KAAA,GAAQ,CAAC,CAAC,CAAA,IAAK,EAAE,MAAA,KAAW,QAAA,IAAY,CAAA,CAAE,QAAA,IAAY,EAAA,KAAO,CAAC,EAAE,MAAA,IAAU,CAAA,CAAE,UAAU,EAAA,CAAA,KAAQ,CAAA,CAAE,cAAc,IAAA,IAAQ,CAAA,CAAE,SAAA,GAAY,CAAA,CAAE,UAAA,CAAA,IAAe,QAAA;AAC3J,MAAA,IAAI,SAAS,CAAA,EAAG;AACd,QAAA,WAAA,GAAc,CAAA,CAAE,IAAA;AAGhB,QAAA,IAAI,QAAA,GAAW,QAAA;AACf,QAAA,IAAI,CAAA,CAAE,cAAc,UAAA,EAAY;AAC9B,UAAA,QAAA,GAAW,YAAY,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,UAAA,CAAW,SAAS,CAAA,CAAE,SAAS,CAAC,CAAA,CAAE,OAAO,CAAC,CAAA,EAAG,MAAM,CAAA,GAAI,CAAA,CAAE,WAAW,CAAC,CAAA;AAAA,QAC5G,CAAA,MAAA,IAAW,CAAA,CAAE,SAAA,KAAc,YAAA,EAAc;AACvC,UAAA,QAAA,GAAW,YAAY,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,UAAA,IAAc,CAAA,CAAE,YAAY,QAAA,CAAS,CAAA,CAAE,UAAU,CAAC,CAAA,CAAE,OAAO,CAAC,CAAA,EAAG,MAAM,CAAA,GAAI,CAAA,CAAE,WAAW,CAAC,CAAA;AAAA,QAC9H;AACA,QAAA,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,QAAA,GAAW,GAAG,CAAA,GAAI,GAAA;AAGxC,QAAA,IAAI,CAAA,CAAE,SAAS,YAAA,EAAc,aAAA,IAAiB,KAAK,KAAA,CAAM,QAAA,GAAW,CAAA,CAAE,KAAK,CAAA,GAAI,GAAA;AAAA,aAAA,IACtE,CAAA,CAAE,SAAS,cAAA,EAAgB,aAAA,IAAiB,KAAK,GAAA,CAAI,CAAA,CAAE,OAAO,QAAQ,CAAA;AAAA,aAAA,IACtE,CAAA,CAAE,IAAA,KAAS,eAAA,EAAiB,aAAA,GAAgB,CAAA;AAErD,QAAA,CAAA,CAAE,SAAA,IAAa,CAAA;AAAA,MACjB;AAAA,IACF;AACA,IAAA,aAAA,GAAgB,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,aAAA,EAAe,CAAC,CAAA,EAAG,QAAQ,CAAA,GAAI,GAAG,CAAA,GAAI,GAAA;AAGnF,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,WAAA,CAAY;AAAA,MACnC,YAAY,UAAA,IAAc,MAAA;AAAA,MAC1B,cAAc,YAAA,IAAgB,MAAA;AAAA,MAC9B,aAAA,EAAe,KAAA,CAAM,QAAA,EAAU,KAAA,IAAS,MAAA;AAAA,MACxC,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,cAAc,WAAA,IAAe,MAAA;AAAA,MAC7B,aAAA;AAAA,MACA,aAAA;AAAA,MACA;AAAA,KACD,CAAA;AAOD,IAAA,KAAA,MAAW,IAAA,IAAQ,MAAM,KAAA,EAAO;AAC9B,MAAA,MAAM,OAAA,GAAU,KAAK,QAAA,CAAS,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,KAAK,SAAS,CAAA;AAC/D,MAAA,IAAI,CAAC,OAAA,EAAS;AACd,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,SAAA,GACjB,IAAA,CAAK,YAAY,IAAA,CAAK,SAAS,CAAA,EAAG,QAAA,CAAS,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,EAAA,KAAO,IAAA,CAAK,SAAS,CAAA,GAC5E,MAAA;AACJ,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,OAAA,CAAQ,iBAAiB,IAAA,CAAK,GAAA,CAAI,GAAG,OAAA,CAAQ,cAAA,GAAiB,KAAK,QAAQ,CAAA;AAC3E,QAAA,OAAA,CAAQ,cAAA,GAAiB,KAAK,WAAA,CAAY,IAAA,CAAK,SAAS,CAAA,CAAG,QAAA,CACxD,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,WAAW,QAAQ,CAAA,CACjC,OAAO,CAAC,GAAA,EAAK,MAAM,GAAA,GAAM,CAAA,CAAE,gBAAgB,CAAC,CAAA;AAAA,MACjD,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,iBAAiB,IAAA,CAAK,GAAA,CAAI,GAAG,OAAA,CAAQ,cAAA,GAAiB,KAAK,QAAQ,CAAA;AAAA,MAC7E;AAAA,IACF;AAEA,IAAA,cAAA,CAAe,sBAAsB,KAAK,CAAA;AAC1C,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAaA,MAAM,oBAAoB,KAAA,EAAuD;AAC/E,IAAA,MAAM,YAAY,GAAA,EAAI;AACtB,IAAA,IAAA,CAAK,iBAAiB,SAAS,CAAA,GAAI,EAAE,KAAA,EAAO,OAAO,CAAA,EAAE;AAGrD,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,KAAA,MAAW,IAAA,IAAQ,MAAM,KAAA,EAAO;AAC9B,MAAA,MAAM,OAAA,GAAU,KAAK,QAAA,CAAS,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,KAAK,SAAS,CAAA;AAC/D,MAAA,IAAI,CAAC,OAAA,EAAS;AACd,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,SAAA,GACjB,IAAA,CAAK,YAAY,IAAA,CAAK,SAAS,CAAA,EAAG,QAAA,CAAS,KAAK,CAAA,CAAA,KAAK,CAAA,CAAE,EAAA,KAAO,IAAA,CAAK,SAAS,CAAA,GAC5E,MAAA;AACJ,MAAA,KAAA,IAAA,CAAU,OAAA,EAAS,KAAA,IAAS,OAAA,CAAQ,KAAA,IAAS,IAAA,CAAK,QAAA;AAAA,IACpD;AACA,IAAA,OAAO;AAAA,MACL,SAAA;AAAA,MACA,KAAA,EAAO,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,GAAG,CAAA,GAAI,GAAA;AAAA,MACjC,KAAA,EAAO,MAAA;AAAA,MACP,MAAA,EAAQ;AAAA;AAAA;AAAA,QAGN,KAAK,CAAA,gCAAA,EAAmC,SAAS,qBAAqB,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,cAAA,CAAA;AAAA,QACtF,YAAA,EAAc,IAAA;AAAA;AAAA;AAAA,QAGd,SAAA,EAAW,IAAA;AAAA,QACX,SAAA,EAAW,IAAI,IAAA,CAAK,IAAA,CAAK,KAAI,GAAI,EAAA,GAAK,GAAM,CAAA,CAAE,WAAA;AAAY;AAC5D,KACF;AAAA,EACF;AAAA,EAEA,MAAM,sBAAsB,SAAA,EAAgD;AAC1E,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,gBAAA,CAAiB,SAAS,CAAA;AAC/C,IAAA,IAAI,CAAC,OAAA,EAAS,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,QAAQ,0CAAA,EAAqC;AACtF,IAAA,IAAI,OAAA,CAAQ,SAAS,OAAO,EAAE,OAAO,MAAA,EAAQ,OAAA,EAAS,QAAQ,OAAA,EAAQ;AACtE,IAAA,OAAA,CAAQ,KAAA,IAAS,CAAA;AACjB,IAAA,IAAI,QAAQ,KAAA,GAAQ,CAAA,EAAG,OAAO,EAAE,OAAO,MAAA,EAAO;AAC9C,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,UAAA,CAAW;AAAA,MAClC,KAAA,EAAO,QAAQ,KAAA,CAAM,KAAA;AAAA,MACrB,QAAA,EAAU,QAAQ,KAAA,CAAM,QAAA;AAAA,MACxB,YAAA,EAAc,OAAA,CAAQ,KAAA,CAAM,YAAA,IAAgB,MAAA;AAAA,MAC5C,eAAA,EAAiB,QAAQ,KAAA,CAAM;AAAA,KACb,CAAA;AAGpB,IAAA,MAAM,KAAK,WAAA,CAAY,KAAA,CAAM,IAAI,EAAE,eAAA,EAAiB,QAAQ,CAAA;AAC5D,IAAA,OAAA,CAAQ,UAAU,KAAA,CAAM,EAAA;AACxB,IAAA,OAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,OAAA,EAAS,MAAM,EAAA,EAAG;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cAAc,IAAA,EAA6B;AAC/C,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,IAAI,IAAA,GAAO,CAAC,GAAG,IAAA,CAAK,SAAS,CAAA;AAC7B,IAAA,IAAI,IAAA,EAAM,QAAQ,IAAA,GAAO,IAAA,CAAK,OAAO,CAAA,CAAA,KAAK,CAAA,EAAG,CAAA,CAAE,SAAS,CAAA,CAAA,EAAI,CAAA,CAAE,QAAQ,CAAA,CAAA,EAAI,CAAA,CAAE,KAAK,CAAA,CAAA,CAAG,WAAA,EAAY,CAAE,SAAS,IAAA,CAAK,MAAA,CAAQ,WAAA,EAAa,CAAC,CAAA;AACtI,IAAA,IAAI,MAAM,KAAA,EAAO,IAAA,GAAO,KAAK,KAAA,CAAM,CAAA,EAAG,KAAK,KAAK,CAAA;AAChD,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,YAAY,EAAA,EAAY;AAC5B,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,OAAO,KAAK,SAAA,CAAU,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,EAAE,CAAA,IAAK,IAAA;AAAA,EAClD;AAAA,EAEA,MAAM,eAAe,KAAA,EAAmD;AACtE,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,MAAM,IAAkB,EAAE,EAAA,EAAI,GAAA,EAAI,EAAG,UAAU,MAAA,EAAQ,SAAA,EAAW,KAAA,CAAM,SAAA,EAAW,UAAU,KAAA,CAAM,QAAA,IAAY,IAAI,KAAA,EAAO,KAAA,CAAM,SAAS,IAAA,EAAM,KAAA,EAAO,KAAA,CAAM,KAAA,IAAS,MAAM,QAAA,EAAU,KAAA,CAAM,YAAY,IAAA,EAAM,KAAA,EAAO,MAAM,KAAA,IAAS,IAAA,EAAM,WAAA,EAAa,CAAA,EAAG,YAAY,CAAA,EAAG,SAAA,EAAW,KAAI,EAAG,SAAA,EAAW,KAAI,EAAE;AAC3S,IAAA,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AACrB,IAAA,IAAA,CAAK,gBAAA,EAAiB;AACtB,IAAA,OAAO,CAAA;AAAA,EACT;AAAA,EAEA,MAAM,cAAA,CAAe,EAAA,EAAY,KAAA,EAAmD;AAClF,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,MAAM,IAAI,IAAA,CAAK,SAAA,CAAU,UAAU,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AACnD,IAAA,IAAI,CAAA,GAAI,CAAA,EAAG,MAAM,IAAI,MAAM,oBAAoB,CAAA;AAC/C,IAAA,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,GAAI,EAAE,GAAG,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,EAAG,GAAG,KAAA,EAAO,SAAA,EAAW,KAAI,EAAE;AACvE,IAAA,IAAA,CAAK,gBAAA,EAAiB;AACtB,IAAA,OAAO,IAAA,CAAK,UAAU,CAAC,CAAA;AAAA,EACzB;AAAA,EAEA,MAAM,eAAe,EAAA,EAAY;AAC/B,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,IAAA,CAAK,YAAY,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AACvD,IAAA,IAAA,CAAK,gBAAA,EAAiB;AAAA,EACxB;AAAA,EAEA,MAAM,gBAAgB,KAAA,EAAoD;AACxE,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,IAAA,GAAO,WAAA,EAAY;AAC7C,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,CAAA,CAAA,KAAA,CAAM,EAAE,KAAA,IAAS,EAAA,EAAI,WAAA,EAAY,KAAM,KAAK,CAAA;AACjF,IAAA,IAAI,UAAU,OAAO,QAAA;AACrB,IAAA,MAAM,CAAC,KAAA,EAAO,GAAG,IAAI,CAAA,GAAA,CAAK,KAAA,CAAM,IAAA,EAAM,IAAA,EAAK,IAAK,KAAA,EAAO,KAAA,CAAM,KAAK,CAAA;AAClE,IAAA,OAAO,IAAA,CAAK,cAAA,CAAe,EAAE,SAAA,EAAW,KAAA,IAAS,KAAA,EAAO,QAAA,EAAU,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,EAAG,KAAA,EAAO,CAAA;AAAA,EAC3F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,mBAAmB,KAAA,EAA6D;AACpF,IAAA,MAAM,UAAA,GAA0B;AAAA,MAC9B,GAAG,IAAA,CAAK,UAAA;AAAA,MACR,GAAG,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,mBAAmB,EAAE,MAAA,CAAO,CAAC,CAAA,KAAsB,CAAA,KAAM,IAAI;AAAA,KACrF;AACA,IAAA,MAAM,OAAA,GAAU,MAAM,gBAAA,CAAiB,KAAA,CAAM,IAAI,CAAA;AACjD,IAAA,OAAO,wBAAwB,KAAA,CAAM,IAAA,EAAM,UAAA,EAAY,EAAE,SAAS,CAAA;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cAAc,IAAA,EAA6B;AAC/C,IAAA,IAAI,IAAA,GAAO,CAAC,GAAG,IAAA,CAAK,SAAS,CAAA;AAC7B,IAAA,IAAI,IAAA,EAAM,QAAQ,IAAA,GAAO,IAAA,CAAK,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,KAAW,IAAA,CAAK,MAAM,CAAA;AAClE,IAAA,IAAI,IAAA,EAAM,MAAM,IAAA,GAAO,IAAA,CAAK,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,IAAA,KAAS,IAAA,CAAK,IAAI,CAAA;AAC5D,IAAA,IAAI,IAAA,EAAM,MAAA,EAAQ,IAAA,GAAO,IAAA,CAAK,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,KAAA,CAAM,WAAA,GAAc,QAAA,CAAS,IAAA,CAAK,MAAA,CAAQ,WAAA,EAAa,CAAC,CAAA;AACpG,IAAA,IAAI,MAAM,KAAA,EAAO,IAAA,GAAO,KAAK,KAAA,CAAM,CAAA,EAAG,KAAK,KAAK,CAAA;AAChD,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,YAAY,EAAA,EAAY;AAAE,IAAA,OAAO,KAAK,SAAA,CAAU,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,EAAE,CAAA,IAAK,IAAA;AAAA,EAAK;AAAA,EAErF,MAAM,eAAe,KAAA,EAA+C;AAClE,IAAA,MAAM,CAAA,GAAc,EAAE,EAAA,EAAI,GAAA,IAAO,QAAA,EAAU,MAAA,EAAQ,KAAA,EAAO,KAAA,CAAM,KAAA,EAAO,IAAA,EAAM,KAAA,CAAM,IAAA,IAAQ,MAAM,IAAA,EAAM,KAAA,CAAM,IAAA,EAAM,MAAA,EAAQ,KAAA,CAAM,MAAA,IAAU,MAAA,EAAQ,KAAA,EAAO,MAAM,KAAA,EAAO,UAAA,EAAY,KAAA,CAAM,UAAA,IAAc,MAAM,eAAA,EAAiB,KAAA,CAAM,eAAA,IAAmB,KAAA,EAAO,aAAa,KAAA,CAAM,WAAA,IAAe,IAAA,EAAM,SAAA,EAAW,KAAA,CAAM,SAAA,IAAa,KAAA,EAAO,UAAA,EAAY,MAAM,UAAA,IAAc,EAAC,EAAG,WAAA,EAAa,KAAA,CAAM,WAAA,IAAe,EAAC,EAAG,UAAU,KAAA,CAAM,QAAA,IAAY,GAAA,EAAI,EAAG,MAAA,EAAQ,KAAA,CAAM,MAAA,IAAU,IAAA,EAAM,QAAQ,KAAA,CAAM,MAAA,IAAU,QAAA,EAAU,SAAA,EAAW,GAAG,SAAA,EAAW,GAAA,EAAI,EAAG,SAAA,EAAW,KAAI,EAAE;AACziB,IAAA,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAG,IAAA,OAAO,CAAA;AAAA,EACjC;AAAA,EAEA,MAAM,cAAA,CAAe,EAAA,EAAY,KAAA,EAA+C;AAC9E,IAAA,MAAM,IAAI,IAAA,CAAK,SAAA,CAAU,UAAU,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AACnD,IAAA,IAAI,CAAA,GAAI,CAAA,EAAG,MAAM,IAAI,MAAM,oBAAoB,CAAA;AAC/C,IAAA,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,GAAI,EAAE,GAAG,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,EAAG,GAAG,KAAA,EAAO,SAAA,EAAW,KAAI,EAAE;AACvE,IAAA,OAAO,IAAA,CAAK,UAAU,CAAC,CAAA;AAAA,EACzB;AAAA,EAEA,MAAM,eAAe,EAAA,EAAY;AAAE,IAAA,IAAA,CAAK,YAAY,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AAAA,EAAE;AAAA;AAAA;AAAA;AAAA,EAM5F,MAAM,iBAAA,GAA6C;AACjD,IAAA,IAAA,CAAK,YAAA,EAAa;AAClB,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,QAAA,GAAW,CAAA,CAAE,QAAQ,CAAA;AAAA,EAClE;AAAA,EAEA,MAAM,mBAAmB,KAAA,EAAuD;AAC9E,IAAA,IAAA,CAAK,YAAA,EAAa;AAClB,IAAA,MAAM,CAAA,GAAkB,EAAE,EAAA,EAAI,GAAA,IAAO,QAAA,EAAU,MAAA,EAAQ,IAAA,EAAM,KAAA,CAAM,IAAA,EAAM,KAAA,EAAO,KAAA,CAAM,KAAA,EAAO,KAAK,KAAA,CAAM,GAAA,IAAO,IAAA,EAAM,OAAA,EAAS,KAAA,CAAM,OAAA,IAAW,IAAA,EAAM,QAAA,EAAU,MAAM,QAAA,IAAY,IAAA,CAAK,QAAA,CAAS,MAAA,EAAQ,SAAA,EAAW,GAAA,EAAI,EAAG,SAAA,EAAW,KAAI,EAAE;AAC1O,IAAA,IAAA,CAAK,QAAA,CAAS,KAAK,CAAC,CAAA;AAAG,IAAA,IAAA,CAAK,eAAA,EAAgB;AAAG,IAAA,OAAO,CAAA;AAAA,EACxD;AAAA,EAEA,MAAM,kBAAA,CAAmB,EAAA,EAAY,KAAA,EAAuD;AAC1F,IAAA,IAAA,CAAK,YAAA,EAAa;AAClB,IAAA,MAAM,IAAI,IAAA,CAAK,QAAA,CAAS,UAAU,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AAClD,IAAA,IAAI,CAAA,GAAI,CAAA,EAAG,MAAM,IAAI,MAAM,yBAAyB,CAAA;AACpD,IAAA,IAAA,CAAK,QAAA,CAAS,CAAC,CAAA,GAAI,EAAE,GAAG,IAAA,CAAK,QAAA,CAAS,CAAC,CAAA,EAAG,GAAG,KAAA,EAAO,SAAA,EAAW,KAAI,EAAE;AACrE,IAAA,IAAA,CAAK,eAAA,EAAgB;AAAG,IAAA,OAAO,IAAA,CAAK,SAAS,CAAC,CAAA;AAAA,EAChD;AAAA,EAEA,MAAM,mBAAmB,EAAA,EAA2B;AAClD,IAAA,IAAA,CAAK,YAAA,EAAa;AAClB,IAAA,IAAA,CAAK,WAAW,IAAA,CAAK,QAAA,CAAS,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AACrD,IAAA,IAAA,CAAK,eAAA,EAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,gBAAA,GAAkD;AACtD,IAAA,OAAO,UAAA,CAA0B,YAAY,CAAA,CAAE,CAAC,CAAA,IAAK,IAAA;AAAA,EACvD;AAAA,EAEA,MAAM,oBAAoB,KAAA,EAAyD;AACjF,IAAA,MAAM,IAAA,GAAsB,EAAE,GAAI,MAAM,IAAA,CAAK,kBAAiB,IAAK,EAAC,EAAI,GAAG,KAAA,EAAM;AACjF,IAAA,KAAA,CAAM,YAAA,EAAc,CAAC,IAAI,CAAC,CAAA;AAC1B,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA,EAIA,MAAM,sBAAA,GAAwD;AAC5D,IAAA,OAAO,KAAK,gBAAA,EAAiB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAA,GAAwC;AAC5C,IAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,OAAA,EAAS,KAAA,EAAM;AAAA,EAC1C;AAAA,EAEA,MAAM,mBAAA,GAAwD;AAC5D,IAAA,OAAO,UAAA,CAA6B,qBAAqB,CAAA,CAAE,CAAC,CAAA,IAAK,IAAA;AAAA,EACnE;AAAA,EAEA,MAAM,uBAAuB,KAAA,EAA+D;AAC1F,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,mBAAA,EAAoB;AAC/C,IAAA,MAAM,IAAA,GAAyB;AAAA,MAC7B,QAAA,EAAU,KAAA,CAAM,QAAA,IAAY,OAAA,EAAS,QAAA,IAAY,CAAA;AAAA,MACjD,WAAW,KAAA,CAAM,SAAA,KAAc,SAAY,KAAA,CAAM,SAAA,GAAY,SAAS,SAAA,IAAa,IAAA;AAAA,MACnF,QAAA,EAAU,KAAA,CAAM,QAAA,IAAY,OAAA,EAAS,QAAA,IAAY;AAAA,KACnD;AACA,IAAA,KAAA,CAAM,qBAAA,EAAuB,CAAC,IAAI,CAAC,CAAA;AACnC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,iBAAA,CAAkB,MAAA,EAAgB,OAAA,EAA6D;AACnG,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,MAAM,CAAA,CAAE,KAAK,OAAO,CAAA;AAAA,EAC9C;AAAA,EAEA,MAAM,eAAA,CAAgB,MAAA,EAAgB,EAAA,EAA0C;AAC9E,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,MAAM,CAAA,CAAE,IAAI,EAAE,CAAA;AAAA,EACxC;AAAA,EAEA,MAAM,qBAAA,CAAsB,MAAA,EAAgB,IAAA,EAA4C;AACtF,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,MAAM,CAAA,CAAE,UAAU,IAAI,CAAA;AAAA,EAChD;AAAA,EAEA,MAAM,kBAAA,CAAmB,MAAA,EAAgB,KAAA,EAAiD;AACxF,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,MAAM,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,EAC9C;AAAA,EAEA,MAAM,kBAAA,CAAmB,MAAA,EAAgB,EAAA,EAAY,KAAA,EAA0D;AAC7G,IAAA,OAAO,KAAK,WAAA,CAAY,MAAM,CAAA,CAAE,MAAA,CAAO,IAAI,KAAK,CAAA;AAAA,EAClD;AAAA,EAEA,MAAM,kBAAA,CAAmB,MAAA,EAAgB,EAAA,EAA2B;AAClE,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,MAAM,CAAA,CAAE,OAAO,EAAE,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA,EAKF,MAAM,eAAA,GAAyC;AAC3C,IAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,WAAW,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,SAAA,GAAY,CAAA,CAAE,SAAS,CAAA;AAAA,EACvE;AAAA,EAEA,MAAM,cAAc,EAAA,EAAwC;AAC1D,IAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,IAAA,OAAO,KAAK,WAAA,CAAY,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,EAAE,CAAA,IAAK,IAAA;AAAA,EACpD;AAAA,EAEA,MAAM,iBAAiB,KAAA,EAAmD;AACxE,IAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,IAAA,MAAM,CAAA,GAAgB;AAAA,MACpB,IAAI,GAAA,EAAI;AAAA,MAAG,QAAA,EAAU,MAAA;AAAA,MACrB,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,QAAQ,KAAA,CAAM,MAAA,EAAQ,MAAK,IAAK,WAAA,CAAY,MAAM,KAAK,CAAA;AAAA,MACvD,WAAA,EAAa,MAAM,WAAA,IAAe,IAAA;AAAA,MAClC,QAAA,EAAU,MAAM,QAAA,IAAY,IAAA;AAAA,MAC5B,QAAA,EAAU,MAAM,QAAA,IAAY,IAAA;AAAA,MAC5B,cAAA,EAAgB,MAAM,cAAA,IAAkB,IAAA;AAAA,MACxC,SAAA,EAAW,MAAM,SAAA,IAAa,IAAA;AAAA,MAC9B,SAAA,EAAW,KAAA,CAAM,SAAA,IAAa,IAAA,CAAK,WAAA,CAAY,MAAA;AAAA,MAC/C,UAAA,EAAY,KAAA,CAAM,UAAA,IAAc,EAAC;AAAA,MACjC,WAAW,GAAA,EAAI;AAAA,MAAG,WAAW,GAAA;AAAI,KACnC;AACA,IAAA,IAAA,CAAK,WAAA,CAAY,KAAK,CAAC,CAAA;AAAG,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAAG,IAAA,OAAO,CAAA;AAAA,EAC9D;AAAA,EAEA,MAAM,gBAAA,CAAiB,EAAA,EAAY,KAAA,EAAmD;AACpF,IAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,IAAA,MAAM,IAAI,IAAA,CAAK,WAAA,CAAY,UAAU,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AACrD,IAAA,IAAI,CAAA,GAAI,CAAA,EAAG,MAAM,IAAI,MAAM,sBAAsB,CAAA;AACjD,IAAA,IAAA,CAAK,WAAA,CAAY,CAAC,CAAA,GAAI,EAAE,GAAG,IAAA,CAAK,WAAA,CAAY,CAAC,CAAA,EAAG,GAAG,KAAA,EAAO,SAAA,EAAW,KAAI,EAAE;AAC3E,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAAG,IAAA,OAAO,IAAA,CAAK,YAAY,CAAC,CAAA;AAAA,EACtD;AAAA,EAEA,MAAM,iBAAiB,EAAA,EAA2B;AAChD,IAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,IAAA,IAAA,CAAK,cAAc,IAAA,CAAK,WAAA,CAAY,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AAC3D,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,EAC1B;AAAA,EAEA,MAAM,kBAAA,GAA+C;AACnD,IAAA,MAAM,MAAA,GAAS,WAA0B,mBAAmB,CAAA;AAC5D,IAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,IAAA,CAAK,cAAA,GAAiB,MAAA;AACzC,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,cAAc,EAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,IAAA,CAAK,aAAA,CAAc,CAAA,CAAE,IAAA,EAAM,OAAO,CAAC,CAAA;AAAA,EACtF;AAAA,EAEA,MAAM,oBAAoB,KAAA,EAAyD;AACjF,IAAA,MAAM,KAAK,kBAAA,EAAmB;AAC9B,IAAA,MAAM,CAAA,GAAmB;AAAA,MACvB,IAAI,GAAA,EAAI;AAAA,MAAG,QAAA,EAAU,MAAA;AAAA,MACrB,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,WAAA,EAAa,MAAM,WAAA,IAAe,IAAA;AAAA,MAClC,KAAA,EAAO,MAAM,KAAA,IAAS,IAAA;AAAA,MACtB,WAAA,EAAa,KAAA,CAAM,WAAA,IAAe,EAAC;AAAA,MACnC,WAAW,GAAA,EAAI;AAAA,MAAG,WAAW,GAAA;AAAI,KACnC;AACA,IAAA,IAAA,CAAK,cAAA,CAAe,KAAK,CAAC,CAAA;AAAG,IAAA,KAAA,CAAM,mBAAA,EAAqB,KAAK,cAAc,CAAA;AAAG,IAAA,OAAO,CAAA;AAAA,EACvF;AAAA,EAEA,MAAM,mBAAA,CAAoB,EAAA,EAAY,KAAA,EAAyD;AAC7F,IAAA,MAAM,KAAK,kBAAA,EAAmB;AAC9B,IAAA,MAAM,IAAI,IAAA,CAAK,cAAA,CAAe,UAAU,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AACxD,IAAA,IAAI,CAAA,GAAI,CAAA,EAAG,MAAM,IAAI,MAAM,0BAA0B,CAAA;AACrD,IAAA,IAAA,CAAK,cAAA,CAAe,CAAC,CAAA,GAAI,EAAE,GAAG,IAAA,CAAK,cAAA,CAAe,CAAC,CAAA,EAAG,GAAG,KAAA,EAAO,SAAA,EAAW,KAAI,EAAE;AACjF,IAAA,KAAA,CAAM,mBAAA,EAAqB,KAAK,cAAc,CAAA;AAAG,IAAA,OAAO,IAAA,CAAK,eAAe,CAAC,CAAA;AAAA,EAC/E;AAAA,EAEA,MAAM,oBAAoB,EAAA,EAA2B;AACnD,IAAA,MAAM,KAAK,kBAAA,EAAmB;AAE9B,IAAA,IAAA,CAAK,iBAAiB,IAAA,CAAK,cAAA,CAAe,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AACjE,IAAA,KAAA,CAAM,mBAAA,EAAqB,KAAK,cAAc,CAAA;AAAA,EAChD;AAAA,EAEA,MAAM,oBAAA,GAAmD;AACvD,IAAA,MAAM,MAAA,GAAS,WAA4B,qBAAqB,CAAA;AAChE,IAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,IAAA,CAAK,gBAAA,GAAmB,MAAA;AAC3C,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,gBAAgB,EAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,IAAA,CAAK,aAAA,CAAc,CAAA,CAAE,IAAA,EAAM,OAAO,CAAC,CAAA;AAAA,EACxF;AAAA,EAEA,MAAM,sBAAsB,KAAA,EAA6D;AACvF,IAAA,MAAM,KAAK,oBAAA,EAAqB;AAChC,IAAA,MAAM,CAAA,GAAqB;AAAA,MACzB,IAAI,GAAA,EAAI;AAAA,MAAG,QAAA,EAAU,MAAA;AAAA,MACrB,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,WAAA,EAAa,MAAM,WAAA,IAAe,IAAA;AAAA,MAClC,SAAA,EAAW,MAAM,SAAA,IAAa,IAAA;AAAA,MAC9B,SAAA,EAAW,MAAM,SAAA,IAAa,IAAA;AAAA,MAC9B,QAAA,EAAU,MAAM,QAAA,IAAY,IAAA;AAAA,MAC5B,QAAA,EAAU,MAAM,QAAA,IAAY,IAAA;AAAA,MAC5B,WAAA,EAAa,MAAM,WAAA,IAAe,IAAA;AAAA,MAClC,YAAA,EAAc,MAAM,YAAA,IAAgB,IAAA;AAAA,MACpC,WAAW,GAAA,EAAI;AAAA,MAAG,WAAW,GAAA;AAAI,KACnC;AACA,IAAA,IAAA,CAAK,gBAAA,CAAiB,KAAK,CAAC,CAAA;AAAG,IAAA,KAAA,CAAM,qBAAA,EAAuB,KAAK,gBAAgB,CAAA;AAAG,IAAA,OAAO,CAAA;AAAA,EAC7F;AAAA,EAEA,MAAM,qBAAA,CAAsB,EAAA,EAAY,KAAA,EAA6D;AACnG,IAAA,MAAM,KAAK,oBAAA,EAAqB;AAChC,IAAA,MAAM,IAAI,IAAA,CAAK,gBAAA,CAAiB,UAAU,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AAC1D,IAAA,IAAI,CAAA,GAAI,CAAA,EAAG,MAAM,IAAI,MAAM,4BAA4B,CAAA;AACvD,IAAA,IAAA,CAAK,gBAAA,CAAiB,CAAC,CAAA,GAAI,EAAE,GAAG,IAAA,CAAK,gBAAA,CAAiB,CAAC,CAAA,EAAG,GAAG,KAAA,EAAO,SAAA,EAAW,KAAI,EAAE;AACrF,IAAA,KAAA,CAAM,qBAAA,EAAuB,KAAK,gBAAgB,CAAA;AAAG,IAAA,OAAO,IAAA,CAAK,iBAAiB,CAAC,CAAA;AAAA,EACrF;AAAA,EAEA,MAAM,sBAAsB,EAAA,EAA2B;AACrD,IAAA,MAAM,KAAK,oBAAA,EAAqB;AAChC,IAAA,IAAA,CAAK,mBAAmB,IAAA,CAAK,gBAAA,CAAiB,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AACrE,IAAA,KAAA,CAAM,qBAAA,EAAuB,KAAK,gBAAgB,CAAA;AAAA,EACpD;AAAA,EAEA,MAAM,aAAA,GAAqC;AACzC,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,SAAS,EAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,SAAA,CAAU,aAAA,CAAc,CAAA,CAAE,SAAS,CAAC,CAAA;AAAA,EAClF;AAAA,EAEA,MAAM,eAAe,KAAA,EAA+C;AAClE,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,KAAA,CAAM,cAAc,CAAA,IAAK,CAAA;AAC/C,IAAA,MAAM,CAAA,GAAc;AAAA,MAClB,IAAI,GAAA,EAAI;AAAA,MAAG,QAAA,EAAU,MAAA;AAAA,MACrB,OAAO,KAAA,CAAM,IAAA,EAAM,MAAK,IAAK,gBAAA,IAAoB,WAAA,EAAY;AAAA;AAAA;AAAA,MAG7D,cAAA,EAAgB,MAAA;AAAA,MAAQ,OAAA,EAAS,MAAA;AAAA,MACjC,QAAA,EAAU,MAAM,QAAA,IAAY,KAAA;AAAA,MAC5B,MAAA,EAAQ,MAAM,MAAA,IAAU,QAAA;AAAA,MACxB,SAAA,EAAW,MAAM,SAAA,IAAa,IAAA;AAAA,MAC9B,UAAA,EAAY,MAAM,UAAA,IAAc,IAAA;AAAA,MAChC,aAAA,EAAe,MAAM,aAAA,IAAiB,IAAA;AAAA,MACtC,IAAA,EAAM,MAAM,IAAA,IAAQ,IAAA;AAAA,MACpB,WAAW,GAAA,EAAI;AAAA,MAAG,WAAW,GAAA;AAAI,KACnC;AACA,IAAA,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAG,IAAA,IAAA,CAAK,gBAAA,EAAiB;AAAG,IAAA,OAAO,CAAA;AAAA,EAC1D;AAAA,EAEA,MAAM,cAAA,CAAe,EAAA,EAAY,KAAA,EAA+C;AAC9E,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,MAAM,IAAI,IAAA,CAAK,SAAA,CAAU,UAAU,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AACnD,IAAA,IAAI,CAAA,GAAI,CAAA,EAAG,MAAM,IAAI,MAAM,qBAAqB,CAAA;AAChD,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,IAAA,KAAS,MAAA,GAAY,KAAA,CAAM,IAAA,CAAK,IAAA,EAAK,CAAE,WAAA,EAAY,GAAI,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,CAAE,IAAA;AAC5F,IAAA,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,GAAI,EAAE,GAAG,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,EAAG,GAAG,KAAA,EAAO,IAAA,EAAM,SAAA,EAAW,KAAI,EAAE;AAC7E,IAAA,IAAA,CAAK,gBAAA,EAAiB;AAAG,IAAA,OAAO,IAAA,CAAK,UAAU,CAAC,CAAA;AAAA,EAClD;AAAA,EAEA,MAAM,eAAe,EAAA,EAA2B;AAC9C,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,IAAA,CAAK,YAAY,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA;AACvD,IAAA,IAAA,CAAK,gBAAA,EAAiB;AAAA,EACxB;AAAA,EAEA,MAAM,kBAAA,GAA+C;AACnD,IAAA,IAAA,CAAK,kBAAA,EAAmB;AACxB,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,cAAc,CAAA;AAAA,EAChC;AAAA,EAEA,MAAM,oBAAoB,KAAA,EAAyD;AACjF,IAAA,IAAA,CAAK,kBAAA,EAAmB;AACxB,IAAA,MAAM,CAAA,GAAI,KAAK,cAAA,CAAe,SAAA,CAAU,OAAK,CAAA,CAAE,KAAA,KAAU,MAAM,KAAK,CAAA;AACpE,IAAA,MAAM,OAAsB,CAAA,IAAK,CAAA,GAAI,IAAA,CAAK,cAAA,CAAe,CAAC,CAAA,GAAI;AAAA,MAC5D,IAAI,GAAA,EAAI;AAAA,MAAG,QAAA,EAAU,MAAA;AAAA,MAAQ,OAAO,KAAA,CAAM,KAAA;AAAA,MAC1C,OAAA,EAAS,KAAA;AAAA,MAAO,OAAA,EAAS,IAAA;AAAA,MAAM,IAAA,EAAM,IAAA;AAAA,MAAM,WAAW,GAAA;AAAI,KAC5D;AACA,IAAA,MAAM,IAAA,GAAsB,EAAE,GAAG,IAAA,EAAM,GAAG,KAAA,EAAO,SAAA,EAAW,KAAI,EAAE;AAClE,IAAA,IAAI,CAAA,IAAK,CAAA,EAAG,IAAA,CAAK,cAAA,CAAe,CAAC,CAAA,GAAI,IAAA;AAAA,SAChC,IAAA,CAAK,cAAA,CAAe,IAAA,CAAK,IAAI,CAAA;AAClC,IAAA,KAAA,CAAM,mBAAA,EAAqB,KAAK,cAAc,CAAA;AAC9C,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEM,eAAA,GAAkB;AACtB,IAAA,MAAM,MAAA,GAAS,WAAuB,eAAe,CAAA;AACrD,IAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,IAAA,CAAK,WAAA,GAAc,MAAA;AAAA,EACxC;AAAA,EAEQ,kBAAA,GAAqB;AAAE,IAAA,KAAA,CAAM,eAAA,EAAiB,KAAK,WAAW,CAAA;AAAA,EAAE;AAAA,EAEhE,aAAA,GAAgB;AACtB,IAAA,MAAM,MAAA,GAAS,WAAqB,cAAc,CAAA;AAClD,IAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,IAAA,CAAK,SAAA,GAAY,MAAA;AAAA,EACtC;AAAA,EAEQ,gBAAA,GAAmB;AAAE,IAAA,KAAA,CAAM,cAAA,EAAgB,KAAK,SAAS,CAAA;AAAA,EAAE;AAAA,EAE3D,kBAAA,GAAqB;AAC3B,IAAA,MAAM,MAAA,GAAS,WAA0B,mBAAmB,CAAA;AAC5D,IAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,IAAA,CAAK,cAAA,GAAiB,MAAA;AAAA,EAC3C;AACF;AAEO,SAAS,uBAAuB,IAAA,EAAmC;AACxE,EAAA,OAAO,IAAI,iBAAiB,IAAI,CAAA;AAClC","file":"chunk-EUFSFVGS.js","sourcesContent":["import type { MediaFile, ProductImage } from '../types'\n\n// ---------------------------------------------------------------------------\n// The media library's shared vocabulary.\n//\n// A file in the library arrives from one of two places: the bucket, which knows\n// what exists, and the record that owns it, which is the only thing that knows\n// what the file is FOR. Both have to land as the same shape with the same\n// identity — the storage path — or one photo shows up as two cards.\n//\n// These are the pure pieces. The providers do the I/O.\n// ---------------------------------------------------------------------------\n\nconst IMAGE_EXTENSIONS = new Set(['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'avif', 'bmp'])\nconst VIDEO_EXTENSIONS = new Set(['mp4', 'mov', 'webm', 'm4v', 'avi', 'mkv'])\n\nexport function mediaKindOf(name: string, mime?: string | null): MediaFile['kind'] {\n if (mime?.startsWith('image/')) return 'image'\n if (mime?.startsWith('video/')) return 'video'\n const ext = (name.split('.').pop() ?? '').toLowerCase()\n if (IMAGE_EXTENSIONS.has(ext)) return 'image'\n if (VIDEO_EXTENSIONS.has(ext)) return 'video'\n return 'document'\n}\n\n/**\n * `…/object/public/{bucket}/{path}` → `{path}`.\n *\n * The path is a file's identity in the library, so the bucket entry and the row\n * that attaches it to a product collapse into one card. Returns null for a URL\n * that did not come from this storage — an image pasted in by hand, say, which\n * has no path to be identified by.\n */\nexport function storagePathOf(url: string): string | null {\n const match = /\\/object\\/(?:public|sign|authenticated)\\/[^/]+\\/([^?]+)/.exec(url)\n if (!match) return null\n try {\n return decodeURIComponent(match[1]!)\n } catch {\n return match[1]!\n }\n}\n\n/**\n * The name a merchant should read.\n *\n * Every upload is stored as `{timestamp}-{original}` so two photos with the same\n * filename can coexist; showing that prefix back would be showing them our\n * bookkeeping.\n */\nexport function displayNameOf(path: string): string {\n const base = path.split('/').pop() ?? path\n return base.replace(/^\\d{10,}-/, '')\n}\n\n/**\n * A product photo as a library file.\n *\n * Same shape as anything uploaded straight to the library, plus the record it\n * belongs to — the only way the library can send a merchant to the screen where\n * the photo is actually managed. `size` is 0 because the row does not carry one:\n * storage does, and a photo is two folders deeper than a bounded walk reaches.\n */\nexport function productImageToMediaFile(\n image: ProductImage,\n productName?: string | null,\n): MediaFile {\n const path = storagePathOf(image.url)\n const name = displayNameOf(path ?? image.url)\n return {\n // Fall back to the URL as identity: an image row that points outside our\n // bucket still belongs in the library, it just cannot be deleted by path.\n id: path ?? image.url,\n name,\n url: image.url,\n kind: mediaKindOf(name),\n size: 0,\n extension: (name.split('.').pop() ?? '').toUpperCase(),\n createdAt: image.createdAt ?? '',\n reference: {\n type: 'product',\n id: image.productId,\n label: productName?.trim() || 'Produto sem nome',\n attachmentId: image.id,\n isCover: image.isPrimary,\n },\n }\n}\n\n/**\n * The library as one list: what a record owns first, then whatever is loose in\n * the bucket, newest first, one card per path.\n *\n * Attached files win the dedupe on purpose — the same file described by a record\n * is strictly more useful than the same file described by nothing.\n */\nexport function mergeMediaFiles(attached: MediaFile[], library: MediaFile[]): MediaFile[] {\n const seen = new Set(attached.map((f) => f.id))\n return [...attached, ...library.filter((f) => !seen.has(f.id))]\n .sort((a, b) => b.createdAt.localeCompare(a.createdAt))\n}\n","import type { ShopProvider } from '../data/provider'\nimport type { ProductOption, ProductVariant } from '../types'\n\n// ---------------------------------------------------------------------------\n// The variant matrix — the arithmetic between \"the axes the merchant declared\"\n// and \"the rows that exist in plg_shop_product_variants\".\n//\n// Lives in @fayz-ai/shop rather than in the admin screen because the two hard\n// rules it encodes are DATA rules, not layout: the jsonb key normalisation that\n// 0028's UNIQUE (product_id, options) actually compares on, and 0037's default\n// variant, which must survive every edit the matrix makes and is invisible to\n// the merchant while it does. A screen that re-derived either would be a second\n// opinion about what the database already decided.\n// ---------------------------------------------------------------------------\n\n/** Shopify's ceiling, carried so a future connector never has to reject a product it can't map. */\nexport const MAX_VARIANT_AXES = 3\nexport const MAX_VARIANT_COMBINATIONS = 100\n\n/** An axis as the editor holds it: no id yet, values not yet cleaned. */\nexport interface VariantAxisInput {\n name: string\n values: string[]\n}\n\nexport type VariantCombination = Record<string, string>\n\n/**\n * The canonical string for a combination. Sorted by key because 0028 stores\n * `options` as jsonb, which normalises key order on write — so\n * {\"Cor\":\"Azul\",\"Tamanho\":\"P\"} and {\"Tamanho\":\"P\",\"Cor\":\"Azul\"} are ONE row to\n * the UNIQUE index, and anything comparing them in TypeScript has to agree.\n */\nexport function variantOptionsKey(options: VariantCombination): string {\n return JSON.stringify(\n Object.keys(options)\n .sort()\n .map((key) => [key, options[key]]),\n )\n}\n\n/**\n * Trim, drop the blanks, dedupe the values. An axis with no name or no value is\n * removed outright: it cannot contribute a combination, and keeping it would\n * multiply the matrix by zero.\n */\nexport function normalizeVariantAxes(axes: readonly VariantAxisInput[]): VariantAxisInput[] {\n const seenNames = new Set<string>()\n const result: VariantAxisInput[] = []\n for (const axis of axes) {\n const name = axis.name.trim()\n if (!name || seenNames.has(name)) continue\n const values: string[] = []\n const seenValues = new Set<string>()\n for (const raw of axis.values) {\n const value = raw.trim()\n if (!value || seenValues.has(value)) continue\n seenValues.add(value)\n values.push(value)\n }\n if (values.length === 0) continue\n seenNames.add(name)\n result.push({ name, values })\n }\n return result\n}\n\n/**\n * The cartesian product, LAST axis varying fastest — P/Cru, P/Azul, M/Cru… That\n * is the order Shopify lists variants in and the order a merchant reads a size\n * chart in; deriving it any other way makes the grid look shuffled.\n */\nexport function variantCombinations(axes: readonly VariantAxisInput[]): VariantCombination[] {\n const clean = normalizeVariantAxes(axes)\n if (clean.length === 0) return []\n let rows: VariantCombination[] = [{}]\n for (const axis of clean) {\n const next: VariantCombination[] = []\n for (const row of rows) {\n for (const value of axis.values) next.push({ ...row, [axis.name]: value })\n }\n rows = next\n }\n return rows\n}\n\n/** Why the axes cannot be saved, or null. Both limits are Shopify's. */\nexport function validateVariantAxes(axes: readonly VariantAxisInput[]): string | null {\n const clean = normalizeVariantAxes(axes)\n if (clean.length > MAX_VARIANT_AXES) {\n return `Um produto aceita no máximo ${MAX_VARIANT_AXES} opções (ex.: Tamanho, Cor, Material).`\n }\n const total = clean.reduce((acc, axis) => acc * axis.values.length, 1)\n if (clean.length > 0 && total > MAX_VARIANT_COMBINATIONS) {\n return `Essas opções gerariam ${total} variantes, e o limite é ${MAX_VARIANT_COMBINATIONS}. Reduza os valores ou separe em dois produtos.`\n }\n return null\n}\n\n/** One cell of the matrix: a combination and the row that carries it, if any. */\nexport interface VariantMatrixRow {\n options: VariantCombination\n /** Grid order, written back to `position` so the DB reads in the same order. */\n position: number\n variant: ProductVariant | null\n}\n\nexport interface VariantMatrixPlan {\n /** The whole matrix, in grid order. */\n rows: VariantMatrixRow[]\n /** Combinations with no row at all — INSERT. */\n create: VariantMatrixRow[]\n /** Combinations whose row exists but is archived — UPDATE back to active,\n * because 0028's UNIQUE (product_id, options) refuses a second row and a\n * DELETE would take the archived row's stock balances with it (0034 CASCADEs). */\n reactivate: VariantMatrixRow[]\n /** Active rows the axes still describe. Nothing to do but reposition. */\n keep: VariantMatrixRow[]\n /** Active rows the axes no longer describe — ARCHIVE, never delete, for the\n * same reason 0037 §4 archives the default variant. */\n archive: ProductVariant[]\n /**\n * The default variant (0037), if the product has one. It is NEVER in any of\n * the lists above: it carries no options, so the matrix can neither describe\n * it nor orphan it. Its lifecycle is reconciled separately — see\n * applyVariantMatrix.\n */\n defaultVariant: ProductVariant | null\n}\n\n/**\n * What has to happen to make the variant rows match the axes.\n *\n * `existing` must include ARCHIVED rows. A merchant who removes \"GG\" and puts\n * it back an hour later is not creating a new SKU — and INSERTing one would hit\n * 0028's UNIQUE (product_id, options) rather than gracefully doing anything.\n */\nexport function planVariantMatrix(\n axes: readonly VariantAxisInput[],\n existing: readonly ProductVariant[],\n): VariantMatrixPlan {\n const wanted = variantCombinations(axes)\n const wantedKeys = new Set(wanted.map(variantOptionsKey))\n\n const byKey = new Map<string, ProductVariant>()\n let defaultVariant: ProductVariant | null = null\n for (const variant of existing) {\n if (variant.isDefaultVariant) {\n defaultVariant = variant\n continue\n }\n byKey.set(variantOptionsKey(variant.options), variant)\n }\n\n const plan: VariantMatrixPlan = {\n rows: [], create: [], reactivate: [], keep: [], archive: [], defaultVariant,\n }\n\n for (const [position, options] of wanted.entries()) {\n const variant = byKey.get(variantOptionsKey(options)) ?? null\n const row: VariantMatrixRow = { options, position, variant }\n plan.rows.push(row)\n if (!variant) plan.create.push(row)\n else if (variant.status === 'archived') plan.reactivate.push(row)\n else plan.keep.push(row)\n }\n\n for (const [key, variant] of byKey) {\n if (!wantedKeys.has(key) && variant.status === 'active') plan.archive.push(variant)\n }\n\n return plan\n}\n\n/**\n * Whether the product is option-less as far as the merchant is concerned: one\n * variant, and it is 0037's placeholder. The admin shows the empty state for\n * this, never a one-row grid — 0037 is explicit that the default variant MUST\n * BE INVISIBLE (no picker, no admin column, no options label).\n */\nexport function hasOnlyDefaultVariant(variants: readonly ProductVariant[]): boolean {\n const active = variants.filter((variant) => variant.status === 'active')\n return active.length === 1 && Boolean(active[0]!.isDefaultVariant)\n}\n\n/**\n * Whether applying the plan would leave the product with NOTHING ACTIVE to\n * sell, and no default variant to fall back on.\n *\n * FOUND BY READING 0039, NOT BY USING THE SCREEN, and the failure is silent:\n * with every real variant archived and 0037's default archived too (§4 archived\n * it the moment the first real variant appeared), shop_place_order's resolution\n * pass finds no default, falls through to the DEPRECATED product-scalar leg,\n * and 0028's sync trigger then recomputes plg_shop_products.inventory_count as\n * the sum of ZERO active variants. The merchant deletes an option and the\n * product goes permanently sold out, with no error anywhere.\n *\n * applyVariantMatrix closes the case where the default row EXISTS (it revives\n * it). This predicate is the residue: a product that predates 0037's backfill\n * has no such row, and no client can mint one — 0047 is what fixes that.\n */\nexport function leavesNothingSellable(plan: VariantMatrixPlan): boolean {\n const willHaveReal = plan.keep.length + plan.reactivate.length + plan.create.length\n return willHaveReal === 0 && plan.defaultVariant === null\n}\n\n/**\n * The axes a variant set implies, position-ordered — what the editor opens\n * with. Taken from `options` rows rather than derived from the variants: 0028\n * makes the ORDER of the values meaningful (\"P before M before G is not\n * alphabetical and not arbitrary, so it cannot be derived\").\n */\nexport function axesFromOptions(options: readonly ProductOption[]): VariantAxisInput[] {\n return [...options]\n .sort((a, b) => a.position - b.position)\n .map((option) => ({ name: option.name, values: [...option.values] }))\n}\n\n/**\n * Save the axes and reconcile the variant rows to them, INCLUDING 0037's\n * default variant. The whole rule lives here rather than in the screen because\n * every step of it is a database invariant, and a second screen that\n * re-implemented four of the five steps would be right until the day it wasn't.\n *\n * Order is load-bearing:\n * 1. axes first, so a variant referring to a value the axes no longer declare\n * is never visible even for one render;\n * 2. INSERT the new combinations — which is also what fires 0037 §4 and\n * archives the default variant, so we never do that by hand on this path;\n * 3. revive the archived combinations (an UPDATE, which fires NO trigger —\n * hence step 5);\n * 4. archive what the axes dropped;\n * 5. reconcile the default variant in whichever direction is now true.\n */\nexport async function applyVariantMatrix(\n provider: ShopProvider,\n productId: string,\n axes: readonly VariantAxisInput[],\n existing: readonly ProductVariant[],\n): Promise<VariantMatrixPlan> {\n const refusal = validateVariantAxes(axes)\n if (refusal) throw new Error(refusal)\n if (!provider.saveProductOptions || !provider.createProductVariant || !provider.updateProductVariant) {\n throw new Error('Este provider não administra variantes.')\n }\n\n const clean = normalizeVariantAxes(axes)\n const plan = planVariantMatrix(clean, existing)\n\n await provider.saveProductOptions(productId, clean)\n\n for (const row of plan.create) {\n await provider.createProductVariant(productId, { options: row.options, position: row.position })\n }\n for (const row of plan.reactivate) {\n await provider.updateProductVariant(row.variant!.id, { status: 'active', position: row.position })\n }\n for (const row of plan.keep) {\n if (row.variant!.position !== row.position) {\n await provider.updateProductVariant(row.variant!.id, { position: row.position })\n }\n }\n for (const variant of plan.archive) {\n await (provider.archiveProductVariant?.(variant.id) ??\n provider.updateProductVariant(variant.id, { status: 'archived' }))\n }\n\n const real = plan.create.length + plan.reactivate.length + plan.keep.length\n if (plan.defaultVariant) {\n if (real > 0 && plan.defaultVariant.status === 'active') {\n // The revive-only path: step 3 is an UPDATE and 0037 §4 is an AFTER\n // INSERT trigger, so nothing retired the default for us. Leaving it active\n // beside real variants is the unnamed combination an empty selection\n // resolves to — the overselling 0028 exists to prevent.\n await provider.updateProductVariant(plan.defaultVariant.id, { status: 'archived' })\n } else if (real === 0 && plan.defaultVariant.status === 'archived') {\n await provider.updateProductVariant(plan.defaultVariant.id, { status: 'active' })\n }\n }\n\n return plan\n}\n\n/** The merchant-facing label for a combination: \"Tamanho: P · Cor: Azul\". */\nexport function formatVariantCombination(options: VariantCombination, axes?: readonly VariantAxisInput[]): string {\n const order = axes?.map((axis) => axis.name) ?? Object.keys(options).sort()\n return order\n .filter((name) => options[name] != null)\n .map((name) => `${name}: ${options[name]}`)\n .join(' · ')\n}\n","import { createDebug, emitDomainEvent } from '@fayz-ai/core'\nimport type { Order } from '../types'\n\n// ---------------------------------------------------------------------------\n// The shop's domain-event EMITTER — the half message-events.ts always assumed.\n//\n// message-events declares what `shop.order_confirmation` says; nothing ever\n// SAID it: the automations list showed the event, and no order ever fired it.\n// The provider calls this after `shop_place_order` succeeds, so any app that\n// completes a checkout through the shop provider emits.\n//\n// Reach, honestly: the event leaves THIS browser. In the admin the platform\n// bridge forwards it and automations run; a standalone storefront only reaches\n// the platform if it runs the bridge too. The durable fix for buyer-side\n// orders is a server-side emitter (pool trigger → platform ingress) — tracked,\n// not built here.\n// ---------------------------------------------------------------------------\n\nconst debug = createDebug('shop')\n\nfunction money(amount: number, currency: string): string {\n try {\n return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: currency || 'BRL' }).format(amount)\n } catch {\n return `${currency} ${amount.toFixed(2)}`\n }\n}\n\n/** The payload promised by ORDER_FIELDS in message-events — same names. */\nexport function orderEventPayload(order: Order): Record<string, unknown> {\n return {\n order_number: String(order.orderNumber),\n order_total: money(order.total, order.currency),\n order_items: (order.items ?? [])\n .map((i) => `${i.quantity} × ${i.name} — ${money(i.total, order.currency)}`)\n .join('\\n'),\n customer_name: order.customerName ?? '',\n // The addresses of the notification, not template text: the automation\n // reads its recipient from here (recipientField), and an order without\n // them is a notification that cannot be delivered.\n customer_email: order.customerEmail ?? '',\n customer_phone: order.shippingAddress?.phone ?? '',\n }\n}\n\nexport function emitOrderEvent(event: 'order_confirmation' | 'order_shipped' | 'order_delivered', order: Order): void {\n const key = `shop.${event}`\n try {\n emitDomainEvent(key, orderEventPayload(order), {\n tenantId: order.tenantId,\n subject: { type: 'order', id: order.id },\n })\n } catch (err) {\n // A notification must never undo a sale.\n debug.error(`emit ${key} failed`, err)\n }\n}\n","import type { ShopProvider } from './provider'\nimport type {\n Product, ProductImage, ProductOption, ProductOptionInput, ProductVariant, ProductVariantSet,\n CreateProductVariantInput, UpdateProductVariantInput,\n Category, Order, ShopCustomer, Discount, ProductEnquiry,\n CreateProductInput, UpdateProductInput, ListProductsOptions,\n CreateProductEnquiryInput, ListProductEnquiriesOptions,\n CreateCategoryInput, UpdateCategoryInput,\n CreateOrderInput, UpdateOrderInput, ListOrdersOptions, PlaceOrderInput,\n CreateCustomerInput, UpdateCustomerInput, ListCustomersOptions, ResolveCustomerInput,\n CreateDiscountInput, UpdateDiscountInput, ListDiscountsOptions,\n SalesChannel, CreateSalesChannelInput, UpdateSalesChannelInput,\n ShippingSettings, UpdateShippingSettingsInput, StoreSettings, UpdateStoreSettingsInput,\n DeliveryCheck,\n CheckoutSessionInput, CheckoutSession, CheckoutSettlement,\n Collection, CreateCollectionInput, UpdateCollectionInput, CustomerGroup, CreateCustomerGroupInput, UpdateCustomerGroupInput, CustomerSegment, CreateCustomerSegmentInput, UpdateCustomerSegmentInput, GiftCard, CreateGiftCardInput, UpdateGiftCardInput, EmailTemplate, UpsertEmailTemplateInput, MediaFile,\n} from '../types'\nimport { mergeMediaFiles, productImageToMediaFile } from './media'\nimport { MOCK_PRODUCTS, MOCK_CATEGORIES, MOCK_DISCOUNTS, MOCK_VARIANTS } from './mock-catalog'\nimport { variantOptionsKey } from '../lib/variant-matrix'\nimport { emitOrderEvent } from '../lib/order-events'\nimport { resolveEntityDeclaration } from '@fayz-ai/core'\nimport { resolveEntityStore } from '../entities/entity-store'\nimport type { EntityRecord, EntityRecordInput, EntityStore, ListEntityRecordsOptions } from '../entities/entity-store'\nimport { createMockEntityStore } from '../entities/mock-entity-store'\nimport { discountToPromotion } from '../rules/adapter'\nimport { buildRuleContext } from '../rules/context'\nimport { computePromotionActions } from '../rules/evaluator'\nimport type { ComputeAction, Promotion, RuleCartItem, RuleCartSnapshot } from '../rules/rule-types'\n\nfunction uid() { return Math.random().toString(36).slice(2) }\nfunction now() { return new Date().toISOString() }\n\n// Orders/customers persist to localStorage so \"my purchases\" survives a page\n// reload. Products/categories/discounts always reseed from the catalog —\n// the storefront sees a deterministic catalog on every load.\nconst ORDERS_KEY = 'fayz.shop.mock.orders.v1'\nconst CUSTOMERS_KEY = 'fayz.shop.mock.customers.v1'\nconst ENQUIRIES_KEY = 'fayz.shop.mock.enquiries.v1'\nconst CHANNELS_KEY = 'fayz.shop.mock.channels.v1'\n// Store policy + delivery fallback persist too, and for the same reason: a\n// settings screen whose toggles reset on reload is indistinguishable from the\n// broken one this replaces, mock backend or not.\nconst SETTINGS_KEY = 'fayz.shop.mock.settings.v1'\nconst SHIPPING_SETTINGS_KEY = 'fayz.shop.mock.shipping-settings.v1'\n\nconst DEFAULT_CHANNELS: SalesChannel[] = [\n { id: 'online-store', tenantId: 'mock', kind: 'online_store', label: 'Loja Online', url: null, enabled: true, position: 0, createdAt: now(), updatedAt: now() },\n]\n\nfunction loadStored<T>(key: string): T[] {\n try {\n if (typeof localStorage === 'undefined') return []\n const raw = localStorage.getItem(key)\n return raw ? (JSON.parse(raw) as T[]) : []\n } catch {\n return []\n }\n}\n\nfunction store<T>(key: string, value: T[]): void {\n try {\n if (typeof localStorage === 'undefined') return\n localStorage.setItem(key, JSON.stringify(value))\n } catch {\n /* quota/serialization failures are non-fatal in mock mode */\n }\n}\n\nexport interface MockShopSeed {\n products?: Product[]\n categories?: Category[]\n discounts?: Discount[]\n /** Option axes + variants per product id (spine M5, mirrors 0028). Absent\n * with the default catalog → the MOCK_VARIANTS fixtures; absent with a\n * custom product seed → no variants (a store's own catalog stays as\n * declared). */\n variants?: Record<string, ProductVariantSet>\n /** Rule-engine promotions (spine M6) — the serializable Promotion shape the\n * Store Document's `promotions` section carries. Evaluated by\n * evaluatePromotions alongside the legacy discounts (adapter-translated). */\n promotions?: Promotion[]\n /** Custom entity records, keyed by defineEntity key. Each seed's `data` is\n * validated against the declaration when the entity's store is built. */\n entities?: Record<string, Array<{ id?: string; slug?: string | null; data: Record<string, unknown> }>>\n}\n\n// Entidades resgatadas da onda de 04-ago.\nconst COLLECTIONS_KEY = 'fayz.shop.mock.collections.v1'\nconst GIFT_CARDS_KEY = 'fayz.shop.mock.gift-cards.v1'\nconst EMAIL_TEMPLATES_KEY = 'fayz.shop.mock.email-templates.v1'\nconst CUSTOMER_GROUPS_KEY = 'fayz.shop.mock.customer-groups.v1'\nconst CUSTOMER_SEGMENTS_KEY = 'fayz.shop.mock.customer-segments.v1'\n\nfunction mockGiftCardCode(): string {\n const alphabet = 'ABCDEFGHJKLMNPQRTUVWXY2346789'\n const pick = () => alphabet[Math.floor(Math.random() * alphabet.length)]\n const block = () => Array.from({ length: 4 }, pick).join('')\n return `${block()}-${block()}-${block()}`\n}\n\nfunction mockSlugify(name: string): string {\n return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '')\n}\n\nexport class MockShopProvider implements ShopProvider {\nprivate collections: Collection[] = loadStored<Collection>(COLLECTIONS_KEY)\n private giftCards: GiftCard[] = loadStored<GiftCard>(GIFT_CARDS_KEY)\n private emailTemplates: EmailTemplate[] = loadStored<EmailTemplate>(EMAIL_TEMPLATES_KEY)\n private customerGroups: CustomerGroup[] = loadStored<CustomerGroup>(CUSTOMER_GROUPS_KEY)\n private customerSegments: CustomerSegment[] = loadStored<CustomerSegment>(CUSTOMER_SEGMENTS_KEY)\n private products: Product[]\n private categories: Category[]\n private discounts: Discount[]\n private orders: Order[] = loadStored<Order>(ORDERS_KEY)\n private customers: ShopCustomer[] = loadStored<ShopCustomer>(CUSTOMERS_KEY)\n private enquiries: ProductEnquiry[] = loadStored<ProductEnquiry>(ENQUIRIES_KEY)\n private channels: SalesChannel[] = (() => {\n const stored = loadStored<SalesChannel>(CHANNELS_KEY)\n return stored.length ? stored : DEFAULT_CHANNELS.map(c => ({ ...c }))\n })()\n\n private entitySeed: NonNullable<MockShopSeed['entities']>\n private entityStores = new Map<string, EntityStore>()\n\n private promotions: Promotion[]\n\n private variantSets: Record<string, ProductVariantSet>\n\n constructor(seed?: MockShopSeed) {\n this.products = (seed?.products ?? MOCK_PRODUCTS).map(p => ({ ...p }))\n this.categories = (seed?.categories ?? MOCK_CATEGORIES).map(c => ({ ...c }))\n this.discounts = (seed?.discounts ?? MOCK_DISCOUNTS).map(d => ({ ...d }))\n this.variantSets = Object.fromEntries(\n Object.entries(seed?.variants ?? (seed?.products ? {} : MOCK_VARIANTS)).map(([productId, set]) => [\n productId,\n { options: set.options.map(o => ({ ...o, values: [...o.values] })), variants: set.variants.map(v => ({ ...v, options: { ...v.options } })) },\n ]),\n )\n this.promotions = (seed?.promotions ?? []).map(p => ({ ...p }))\n this.entitySeed = seed?.entities ?? {}\n }\n\n /** The I5 indirection: a promoted (registered) store wins; otherwise the\n * entity gets a lazily-built in-memory store seeded from the mock seed.\n * Lazy on purpose — the seed is validated against the declaration, which\n * the app may register after constructing the provider. */\n private entityStore(entity: string): EntityStore {\n // The I2 gate first: an unknown entity must name the declared set even for\n // reads the lazy store would otherwise satisfy with an empty list.\n resolveEntityDeclaration(entity)\n return resolveEntityStore(entity, (key) => {\n let store = this.entityStores.get(key)\n if (!store) {\n store = createMockEntityStore(key, { seed: this.entitySeed[key] })\n this.entityStores.set(key, store)\n }\n return store\n })\n }\n\n // Re-read before mutating: HMR can re-instantiate the provider mid-session\n // and a stale in-memory copy must not clobber persisted records.\n private syncOrders() { this.orders = loadStored<Order>(ORDERS_KEY) }\n private syncCustomers() { this.customers = loadStored<ShopCustomer>(CUSTOMERS_KEY) }\n private syncEnquiries() { this.enquiries = loadStored<ProductEnquiry>(ENQUIRIES_KEY) }\n private syncChannels() {\n const stored = loadStored<SalesChannel>(CHANNELS_KEY)\n if (stored.length) this.channels = stored\n }\n private persistOrders() { store(ORDERS_KEY, this.orders) }\n private persistCustomers() { store(CUSTOMERS_KEY, this.customers) }\n private persistEnquiries() { store(ENQUIRIES_KEY, this.enquiries) }\n private persistChannels() { store(CHANNELS_KEY, this.channels) }\n\n // ---------------------------------------------------------------------------\n // Products\n // ---------------------------------------------------------------------------\n\n async listProducts(opts?: ListProductsOptions): Promise<Product[]> {\n let list = [...this.products]\n if (opts?.status) list = list.filter(p => p.status === opts.status)\n if (opts?.categoryId) list = list.filter(p => p.categoryId === opts.categoryId)\n if (opts?.slug) list = list.filter(p => p.slug === opts.slug)\n if (opts?.search) {\n const q = opts.search.toLowerCase()\n list = list.filter(p =>\n p.name.toLowerCase().includes(q) ||\n (p.description ?? '').toLowerCase().includes(q) ||\n (p.sku ?? '').toLowerCase().includes(q),\n )\n }\n const orderBy = opts?.orderBy ?? 'sort_order'\n const dir = opts?.order === 'desc' ? -1 : 1\n if (opts?.search && !opts.orderBy) {\n // A term matched in the NAME must outrank one matched in the description,\n // otherwise \"caneta\" answers with whatever the catalogue happens to list\n // first among the products that merely mention a pen. Only when the caller\n // asked for a specific order does that order win.\n const q = opts.search.toLowerCase()\n const rank = (p: Product) =>\n p.name.toLowerCase().startsWith(q) ? 0 : p.name.toLowerCase().includes(q) ? 1 : 2\n list.sort((a, b) => rank(a) - rank(b) || a.sortOrder - b.sortOrder)\n } else {\n list.sort((a, b) => {\n switch (orderBy) {\n case 'name': return a.name.localeCompare(b.name) * dir\n case 'price': return (a.price - b.price) * dir\n case 'created_at': return a.createdAt.localeCompare(b.createdAt) * dir\n default: return (a.sortOrder - b.sortOrder) * dir\n }\n })\n }\n const offset = opts?.offset ?? 0\n if (offset || opts?.limit) list = list.slice(offset, opts?.limit ? offset + opts.limit : undefined)\n return list\n }\n\n async getProduct(id: string) { return this.products.find(p => p.id === id) ?? null }\n\n /** Option axes + variants (spine M5) — active variants only, like the 0028\n * storefront RLS. Answers empty sets for a variantless product. */\n async getProductVariants(productId: string, opts?: { includeArchived?: boolean }): Promise<ProductVariantSet> {\n const set = this.variantSets[productId]\n if (!set) return { options: [], variants: [] }\n return {\n options: set.options.map(o => ({ ...o, values: [...o.values] })).sort((a, b) => a.position - b.position),\n variants: set.variants\n .filter(v => opts?.includeArchived || v.status === 'active')\n .map(v => ({ ...v, options: { ...v.options } }))\n .sort((a, b) => a.position - b.position),\n }\n }\n\n // --- The variant admin ------------------------------------------------------\n // Modelled on the SQL rather than on convenience: 0028's UNIQUE\n // (product_id, options), 0037's default-variant triggers and 0036's mirror all\n // have a counterpart here, so a test that passes against this mock is\n // asserting the real semantics and not a friendlier imitation of them.\n\n private variantSet(productId: string): ProductVariantSet {\n this.variantSets[productId] ??= { options: [], variants: [] }\n return this.variantSets[productId]!\n }\n\n async saveProductOptions(productId: string, input: ProductOptionInput[]): Promise<ProductOption[]> {\n const set = this.variantSet(productId)\n const existing = new Map(set.options.map(o => [o.name, o]))\n set.options = input.map((axis, position) => ({\n id: existing.get(axis.name)?.id ?? uid(),\n name: axis.name,\n values: [...axis.values],\n position,\n }))\n return set.options.map(o => ({ ...o, values: [...o.values] }))\n }\n\n async createProductVariant(productId: string, input: CreateProductVariantInput): Promise<ProductVariant> {\n const set = this.variantSet(productId)\n const key = variantOptionsKey(input.options)\n const existing = set.variants.find(v => variantOptionsKey(v.options) === key)\n // 0028's UNIQUE (product_id, options): the row is revived, never doubled.\n if (existing) return this.updateProductVariant(existing.id, { ...input, status: input.status ?? 'active' })\n\n const variant: ProductVariant = {\n id: uid(),\n productId,\n options: { ...input.options },\n sku: input.sku ?? null,\n price: input.price ?? null,\n compareAtPrice: input.compareAtPrice ?? null,\n inventoryCount: 0,\n position: input.position ?? set.variants.length,\n status: input.status ?? 'active',\n imageId: input.imageId ?? null,\n isDefaultVariant: false,\n weight: input.weight ?? null,\n weightUnit: input.weightUnit ?? null,\n heightCm: input.heightCm ?? null,\n widthCm: input.widthCm ?? null,\n lengthCm: input.lengthCm ?? null,\n }\n set.variants.push(variant)\n // 0037 §4: the first real variant retires the default one. ARCHIVED, not\n // deleted — the balance rows belong to stock the merchant still owns.\n for (const other of set.variants) {\n if (other.isDefaultVariant && other.status === 'active') other.status = 'archived'\n }\n this.syncProductFromVariants(productId)\n return { ...variant, options: { ...variant.options } }\n }\n\n async updateProductVariant(variantId: string, input: UpdateProductVariantInput): Promise<ProductVariant> {\n for (const [productId, set] of Object.entries(this.variantSets)) {\n const variant = set.variants.find(v => v.id === variantId)\n if (!variant) continue\n for (const [key, value] of Object.entries(input)) {\n if (value !== undefined) (variant as unknown as Record<string, unknown>)[key] = value\n }\n this.syncProductFromVariants(productId)\n return { ...variant, options: { ...variant.options } }\n }\n throw new Error('Variant not found')\n }\n\n async archiveProductVariant(variantId: string): Promise<void> {\n await this.updateProductVariant(variantId, { status: 'archived' })\n }\n\n /**\n * The 0034→0036 path, compressed: the merchant states a count, the difference\n * is what gets recorded, and inventory_count is the mirror that follows. The\n * ledger itself is MockStockStore's business — what matters here is that no\n * caller ever assigns to inventoryCount.\n */\n async setVariantStock(variantId: string, count: number): Promise<number> {\n const target = Math.max(0, Math.trunc(count))\n for (const [productId, set] of Object.entries(this.variantSets)) {\n const variant = set.variants.find(v => v.id === variantId)\n if (!variant) continue\n variant.inventoryCount = target\n this.syncProductFromVariants(productId)\n return target\n }\n throw new Error('Variant not found')\n }\n\n async receiveVariantStock(variantId: string, quantity: number): Promise<number> {\n const amount = Math.trunc(quantity)\n if (amount <= 0) throw new Error('A quantidade recebida precisa ser maior que zero.')\n for (const [productId, set] of Object.entries(this.variantSets)) {\n const variant = set.variants.find(v => v.id === variantId)\n if (!variant) continue\n variant.inventoryCount += amount\n this.syncProductFromVariants(productId)\n return variant.inventoryCount\n }\n throw new Error('Variant not found')\n }\n\n async receiveProductStock(\n productId: string,\n quantity: number,\n options?: { variantId?: string | null },\n ): Promise<number> {\n const amount = Math.trunc(quantity)\n if (amount <= 0) throw new Error('A quantidade recebida precisa ser maior que zero.')\n if (options?.variantId) return this.receiveVariantStock(options.variantId, amount)\n const variants = this.variantSets[productId]?.variants.filter(v => v.status === 'active') ?? []\n if (variants.length === 1) return this.receiveVariantStock(variants[0].id, amount)\n if (variants.length > 1) {\n throw new Error('Este produto tem mais de uma variação — escolha qual recebeu a entrada.')\n }\n const product = this.products.find(p => p.id === productId)\n if (!product) throw new Error('Product not found')\n product.inventoryCount = Math.max(0, product.inventoryCount) + amount\n return product.inventoryCount\n }\n\n /** 0028's sync trigger: the product row is the SUM of active variant stock. */\n private syncProductFromVariants(productId: string): void {\n const product = this.products.find(p => p.id === productId)\n const set = this.variantSets[productId]\n if (!product || !set) return\n const active = set.variants.filter(v => v.status === 'active')\n product.inventoryCount = active.reduce((sum, v) => sum + v.inventoryCount, 0)\n }\n\n async createProduct(input: CreateProductInput): Promise<Product> {\n const p: Product = { id: uid(), tenantId: 'mock', name: input.name, slug: input.slug ?? input.name.toLowerCase().replace(/\\s+/g, '-'), description: input.description ?? null, price: input.price, compareAtPrice: input.compareAtPrice ?? null, currency: input.currency ?? 'BRL', status: input.status ?? 'active', inventoryCount: input.inventoryCount ?? 0, sku: input.sku ?? null, sortOrder: input.sortOrder ?? 0, metadata: input.metadata ?? {}, images: [], categoryId: input.categoryId ?? null, categoryName: null, isPhysical: input.isPhysical ?? true, weight: input.weight ?? null, weightUnit: input.weightUnit ?? 'kg', handling: input.handling ?? [], createdAt: now(), updatedAt: now() }\n this.products.push(p); return p\n }\n\n async updateProduct(id: string, input: UpdateProductInput): Promise<Product> {\n const i = this.products.findIndex(p => p.id === id)\n if (i < 0) throw new Error('Product not found')\n this.products[i] = { ...this.products[i], ...input, updatedAt: now() }\n return this.products[i]\n }\n\n async deleteProduct(id: string) { this.products = this.products.filter(p => p.id !== id) }\n async uploadProductImage(_productId: string, _file: File): Promise<ProductImage> { throw new Error('Image upload not available in mock mode') }\n\n async deleteProductImage(imageId: string) {\n this.products = this.products.map(p => p.images.some(i => i.id === imageId)\n ? { ...p, images: p.images.filter(i => i.id !== imageId) }\n : p)\n }\n\n /** The media library, mock-side: no bucket to walk, so the catalogue's own\n * photos ARE the library. Uploading has nowhere to go, which is why\n * uploadMediaFile stays unimplemented and the screen hides its button. */\n async listMediaFiles(): Promise<MediaFile[]> {\n const attached = this.products.flatMap(p =>\n p.images.map(image => productImageToMediaFile(image, p.name)))\n return mergeMediaFiles(attached, [])\n }\n\n async createProductEnquiry(input: CreateProductEnquiryInput): Promise<ProductEnquiry> {\n this.syncEnquiries()\n const ts = now()\n const enquiry: ProductEnquiry = {\n id: uid(),\n tenantId: 'mock',\n productId: input.productId ?? null,\n productName: input.productName,\n productSlug: input.productSlug ?? null,\n customerName: input.customerName,\n customerEmail: input.customerEmail,\n customerPhone: input.customerPhone ?? null,\n subject: input.subject ?? null,\n message: input.message,\n sourceUrl: input.sourceUrl ?? null,\n status: 'new',\n metadata: input.metadata ?? {},\n createdAt: ts,\n updatedAt: ts,\n }\n this.enquiries.unshift(enquiry)\n this.persistEnquiries()\n return enquiry\n }\n\n async listProductEnquiries(opts?: ListProductEnquiriesOptions): Promise<ProductEnquiry[]> {\n this.syncEnquiries()\n let list = [...this.enquiries]\n if (opts?.productId) list = list.filter((e) => e.productId === opts.productId)\n if (opts?.customerEmail) {\n const email = opts.customerEmail.toLowerCase()\n list = list.filter((e) => e.customerEmail.toLowerCase() === email)\n }\n if (opts?.status) list = list.filter((e) => e.status === opts.status)\n list.sort((a, b) => b.createdAt.localeCompare(a.createdAt))\n const offset = opts?.offset ?? 0\n if (offset || opts?.limit) list = list.slice(offset, opts?.limit ? offset + opts.limit : undefined)\n return list\n }\n\n // ---------------------------------------------------------------------------\n // Categories\n // ---------------------------------------------------------------------------\n\n async listCategories() { return [...this.categories].sort((a, b) => a.sortOrder - b.sortOrder) }\n\n async createCategory(input: CreateCategoryInput): Promise<Category> {\n const c: Category = { id: uid(), tenantId: 'mock', name: input.name, slug: input.slug ?? input.name.toLowerCase().replace(/\\s+/g, '-'), description: input.description ?? null, parentId: input.parentId ?? null, sortOrder: input.sortOrder ?? 0, createdAt: now() }\n this.categories.push(c); return c\n }\n\n async updateCategory(id: string, input: UpdateCategoryInput): Promise<Category> {\n const i = this.categories.findIndex(c => c.id === id)\n if (i < 0) throw new Error('Category not found')\n this.categories[i] = { ...this.categories[i], ...input }\n return this.categories[i]\n }\n\n async deleteCategory(id: string) { this.categories = this.categories.filter(c => c.id !== id) }\n\n // ---------------------------------------------------------------------------\n // Orders\n // ---------------------------------------------------------------------------\n\n async listOrders(opts?: ListOrdersOptions): Promise<Order[]> {\n this.syncOrders()\n let list = [...this.orders]\n if (opts?.status) list = list.filter(o => o.status === opts.status)\n if (opts?.financialStatus) list = list.filter(o => o.financialStatus === opts.financialStatus)\n if (opts?.fulfillmentStatus) list = list.filter(o => o.fulfillmentStatus === opts.fulfillmentStatus)\n if (opts?.customerId) list = list.filter(o => o.customerId === opts.customerId)\n if (opts?.customerEmail) {\n const email = opts.customerEmail.toLowerCase()\n list = list.filter(o => (o.customerEmail ?? '').toLowerCase() === email)\n }\n if (opts?.search) {\n const q = opts.search.toLowerCase()\n list = list.filter(o =>\n (o.customerName ?? '').toLowerCase().includes(q) ||\n (o.customerEmail ?? '').toLowerCase().includes(q) ||\n String(o.orderNumber).includes(q),\n )\n }\n list.sort((a, b) => b.createdAt.localeCompare(a.createdAt))\n if (opts?.limit) list = list.slice(0, opts.limit)\n return list\n }\n\n async getOrder(id: string) {\n this.syncOrders()\n return this.orders.find(o => o.id === id) ?? null\n }\n\n async createOrder(input: CreateOrderInput): Promise<Order> {\n this.syncOrders()\n const subtotal = input.items.reduce((s, i) => s + i.quantity * i.unitPrice, 0)\n const discountTotal = input.discountTotal ?? 0\n const shippingTotal = input.shippingTotal ?? 0\n const total = Math.round((subtotal - discountTotal + shippingTotal) * 100) / 100\n const orderId = uid()\n const maxNumber = this.orders.reduce((m, o) => Math.max(m, o.orderNumber), 1000)\n const o: Order = {\n id: orderId,\n tenantId: 'mock',\n orderNumber: maxNumber + 1,\n status: 'open',\n financialStatus: 'pending',\n fulfillmentStatus: 'unfulfilled',\n currency: input.currency ?? 'BRL',\n subtotal: Math.round(subtotal * 100) / 100,\n taxTotal: 0,\n discountTotal,\n shippingTotal,\n total,\n customerId: input.customerId ?? null,\n customerName: input.customerName ?? null,\n customerEmail: input.customerEmail ?? null,\n discountCode: input.discountCode ?? null,\n notes: input.notes ?? null,\n shippingAddress: null,\n // CreateOrderInput has no payment method — that is a PlaceOrderInput\n // concern; the mock records none rather than inventing one.\n paymentMethodKind: null,\n paidAt: null,\n items: input.items.map(i => ({ id: uid(), orderId, productId: i.productId ?? null, name: i.name, sku: i.sku ?? null, quantity: i.quantity, unitPrice: i.unitPrice, total: Math.round(i.quantity * i.unitPrice * 100) / 100, imageUrl: i.imageUrl ?? null })),\n createdAt: now(),\n updatedAt: now(),\n }\n this.orders.push(o)\n this.persistOrders()\n return o\n }\n\n async updateOrder(id: string, input: UpdateOrderInput): Promise<Order> {\n this.syncOrders()\n const i = this.orders.findIndex(o => o.id === id)\n if (i < 0) throw new Error('Order not found')\n this.orders[i] = { ...this.orders[i], ...input, updatedAt: now() }\n this.persistOrders()\n return this.orders[i]\n }\n\n // Trusted placement (mock parity with the shop_place_order RPC): re-reads\n // prices + stock from the catalog, EVALUATES THE DECLARED PROMOTIONS through\n // the rule engine, validates the legacy discount code, decrements inventory.\n // The browser-supplied prices and totals are never used.\n async placeOrder(input: PlaceOrderInput): Promise<Order> {\n this.syncOrders()\n this.syncCustomers()\n\n // Resolve / create the customer (find-or-create by email).\n let customerId = input.customerId ?? null\n let customerName = input.customer?.name?.trim() || null\n const email = input.customer?.email?.trim().toLowerCase() || null\n if (!customerId && email) {\n const existing = this.customers.find(c => (c.email ?? '').toLowerCase() === email)\n if (existing) {\n customerId = existing.id\n customerName = customerName ?? `${existing.firstName} ${existing.lastName}`.trim()\n } else {\n const [first, ...rest] = (customerName ?? email).split(' ')\n const created = await this.createCustomer({ firstName: first || email, lastName: rest.join(' '), email })\n customerId = created.id\n }\n }\n\n // Re-read price + guard stock from the catalog (never trust the client).\n // Variant lines (spine M5, mirroring 0029): the VARIANT is the priced and\n // stock-checked unit; its options derive the label the shopper sees.\n const items: CreateOrderInput['items'] = []\n // Per-line facts for coupon scoping (productId, categoryId, line total).\n const lineDetails: Array<{ productId: string; categoryId: string | null; lineTotal: number }> = []\n // The SAME lines as a rule-engine snapshot (M6). Built here, from the\n // re-read catalog prices, so the engine can never be fed client numbers.\n const snapshotItems: RuleCartItem[] = []\n let subtotal = 0\n for (const [index, line] of input.items.entries()) {\n const product = this.products.find(p => p.id === line.productId)\n if (!product || product.status !== 'active') throw new Error(`Product unavailable: ${line.productId}`)\n let variant: ProductVariant | undefined\n if (line.variantId) {\n variant = this.variantSets[line.productId]?.variants.find(v => v.id === line.variantId && v.status === 'active')\n if (!variant) throw new Error(`Variant unavailable: ${line.variantId}`)\n if (variant.inventoryCount < line.quantity) throw new Error(`Insufficient stock for ${product.name}`)\n } else if (product.inventoryCount < line.quantity) {\n throw new Error(`Insufficient stock for ${product.name}`)\n }\n const unitPrice = variant?.price ?? product.price\n const label = line.optionsLabel\n || (variant ? Object.entries(variant.options).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}: ${v}`).join(' · ') : '')\n const name = label ? `${product.name} (${label})` : product.name\n const lineTotal = unitPrice * line.quantity\n subtotal += lineTotal\n lineDetails.push({ productId: product.id, categoryId: product.categoryId, lineTotal })\n // Line identity must be UNIQUE (the engine splits `across` allocations\n // per line id); the index guarantees it even for two lines of the same\n // product bought under different variants.\n snapshotItems.push({\n id: `${index}:${line.variantId ?? product.id}`,\n productId: product.id,\n quantity: line.quantity,\n unitPrice,\n categoryId: product.categoryId,\n collectionId: typeof product.metadata?.collection === 'string' ? product.metadata.collection : null,\n })\n items.push({ productId: product.id, name, sku: variant?.sku ?? product.sku ?? undefined, quantity: line.quantity, unitPrice, imageUrl: product.images[0]?.url })\n }\n subtotal = Math.round(subtotal * 100) / 100\n\n // Validate + apply the discount server-side.\n let shippingTotal = Math.max(input.shippingTotal ?? 0, 0)\n let discountTotal = 0\n let appliedCode: string | null = null\n\n // --- The rule engine on the ORDER path (spine M6) -----------------------\n // Declared `promotions` are evaluated here, not only in the cart preview:\n // without this a store that carries ONLY new-style promotions placed every\n // order with discountTotal 0 — the promotion was advertised, previewed and\n // then silently dropped at the till.\n //\n // Only the DECLARED promotions ride this path. Legacy `discounts` keep\n // their own (unchanged) code below; running them through the adapter here\n // as well would count the same coupon twice.\n const entered = input.discountCode ? [input.discountCode.trim()] : []\n const cart: RuleCartSnapshot = {\n items: snapshotItems,\n shippingTotal,\n customer: { email: input.customer?.email ?? null },\n codes: entered,\n currency: input.currency,\n }\n const context = await buildRuleContext(cart)\n const actions = computePromotionActions(cart, this.promotions, { context })\n\n let promotionItemDiscount = 0\n let promotionShippingDiscount = 0\n const firedPromotionIds = new Set<string>()\n const firedCodes = new Set<string>()\n for (const action of actions) {\n firedPromotionIds.add(action.promotionId)\n if (action.code) firedCodes.add(action.code.trim().toUpperCase())\n if (action.action === 'addItemDiscount') promotionItemDiscount += action.amount\n else if (action.action === 'addShippingDiscount') promotionShippingDiscount += action.amount\n else if (action.action === 'addFreeItem') {\n // The grant is a real order line at price 0 — otherwise the shopper is\n // promised a free product the order never records.\n const granted = this.products.find(p => p.id === action.productId)\n if (granted) {\n items.push({ productId: granted.id, name: granted.name, sku: granted.sku ?? undefined, quantity: action.quantity, unitPrice: 0, imageUrl: granted.images[0]?.url })\n }\n }\n }\n // Usage limits are enforced against the same counter the legacy path uses.\n for (const promotion of this.promotions) {\n if (firedPromotionIds.has(promotion.id)) promotion.timesUsed = (promotion.timesUsed ?? 0) + 1\n }\n discountTotal += Math.round(promotionItemDiscount * 100) / 100\n shippingTotal = Math.max(0, Math.round((shippingTotal - promotionShippingDiscount) * 100) / 100)\n if (input.discountCode && firedCodes.has(input.discountCode.trim().toUpperCase())) {\n appliedCode = input.discountCode.trim().toUpperCase()\n }\n\n // --- Legacy `discounts` coupons (unchanged) -----------------------------\n // Skipped only when a declared promotion already consumed this exact code,\n // so a store that migrated one coupon to the rule model is not charged the\n // discount twice.\n if (input.discountCode && !appliedCode) {\n const code = input.discountCode.trim().toLowerCase()\n const d = this.discounts.find(x => (x.code ?? '').toLowerCase() === code)\n const ts = now()\n const meetsMin = !d?.minSubtotal || subtotal >= d.minSubtotal\n const valid = !!d && d.status === 'active' && d.startsAt <= ts && (!d.endsAt || d.endsAt >= ts) && (d.usageLimit == null || d.timesUsed < d.usageLimit) && meetsMin\n if (valid && d) {\n appliedCode = d.code\n // Eligible subtotal = the part of the cart the coupon is scoped to.\n // applies_to='all' → whole subtotal (unchanged for legacy coupons).\n let eligible = subtotal\n if (d.appliesTo === 'products') {\n eligible = lineDetails.filter(l => d.productIds.includes(l.productId)).reduce((s, l) => s + l.lineTotal, 0)\n } else if (d.appliesTo === 'categories') {\n eligible = lineDetails.filter(l => l.categoryId && d.categoryIds.includes(l.categoryId)).reduce((s, l) => s + l.lineTotal, 0)\n }\n eligible = Math.round(eligible * 100) / 100\n // `+=`, not `=`: an automatic rule-engine promotion may already have\n // contributed above, and a legacy coupon must not erase it.\n if (d.type === 'percentage') discountTotal += Math.round(eligible * d.value) / 100\n else if (d.type === 'fixed_amount') discountTotal += Math.min(d.value, eligible)\n else if (d.type === 'free_shipping') shippingTotal = 0\n // buy_x_get_y unsupported in v1: code recorded, no monetary effect\n d.timesUsed += 1\n }\n }\n discountTotal = Math.round(Math.min(Math.max(discountTotal, 0), subtotal) * 100) / 100\n\n // Persist via createOrder (recomputes total from these trusted values).\n const order = await this.createOrder({\n customerId: customerId ?? undefined,\n customerName: customerName ?? undefined,\n customerEmail: input.customer?.email ?? undefined,\n currency: input.currency,\n notes: input.notes,\n discountCode: appliedCode ?? undefined,\n discountTotal,\n shippingTotal,\n items,\n })\n\n // Decrement inventory (in-memory; the mock catalog reseeds on reload).\n // A variant line decrements the VARIANT counter, and the product mirror is\n // recomputed as the sum of active variant stock — the same rule 0028's\n // sync trigger enforces on live data, so both providers report identical\n // numbers after a sale.\n for (const line of input.items) {\n const product = this.products.find(p => p.id === line.productId)\n if (!product) continue\n const variant = line.variantId\n ? this.variantSets[line.productId]?.variants.find(v => v.id === line.variantId)\n : undefined\n if (variant) {\n variant.inventoryCount = Math.max(0, variant.inventoryCount - line.quantity)\n product.inventoryCount = this.variantSets[line.productId]!.variants\n .filter(v => v.status === 'active')\n .reduce((sum, v) => sum + v.inventoryCount, 0)\n } else {\n product.inventoryCount = Math.max(0, product.inventoryCount - line.quantity)\n }\n }\n\n emitOrderEvent('order_confirmation', order)\n return order\n }\n\n // ---------------------------------------------------------------------------\n // Checkout sessions\n //\n // Mirrors the live inversion: the session holds the cart, and the ORDER is\n // only written when the settle says the money is in. Here the \"provider\" is a\n // clock — the second poll pays — which is what lets the four-step checkout be\n // walked end to end without an acquirer, in demo stores and in the e2e suite.\n // ---------------------------------------------------------------------------\n\n private checkoutSessions: Record<string, { input: CheckoutSessionInput; polls: number; orderId?: string }> = {}\n\n async openCheckoutSession(input: CheckoutSessionInput): Promise<CheckoutSession> {\n const sessionId = uid()\n this.checkoutSessions[sessionId] = { input, polls: 0 }\n // Re-priced from the catalog, exactly like placeOrder — the browser's\n // numbers never reach the charge, in the mock either.\n let total = 0\n for (const line of input.items) {\n const product = this.products.find(p => p.id === line.productId)\n if (!product) continue\n const variant = line.variantId\n ? this.variantSets[line.productId]?.variants.find(v => v.id === line.variantId)\n : undefined\n total += (variant?.price ?? product.price) * line.quantity\n }\n return {\n sessionId,\n total: Math.round(total * 100) / 100,\n state: 'open',\n charge: {\n // Shaped like a real EMV payload so the copy button and the layout are\n // exercised, not a placeholder that fits in one line.\n emv: `00020126580014BR.GOV.BCB.PIX0136${sessionId}520400005303986540${total.toFixed(2)}5802BR6304MOCK`,\n qrcodeBase64: null,\n // No image either way in the mock: the copy-and-paste code is what pays,\n // and a fabricated QR would be a square that scans to nothing.\n qrcodeUrl: null,\n expiresAt: new Date(Date.now() + 30 * 60_000).toISOString(),\n },\n }\n }\n\n async settleCheckoutSession(sessionId: string): Promise<CheckoutSettlement> {\n const session = this.checkoutSessions[sessionId]\n if (!session) return { state: 'expired', reason: 'Sessão de checkout não encontrada.' }\n if (session.orderId) return { state: 'paid', orderId: session.orderId }\n session.polls += 1\n if (session.polls < 2) return { state: 'open' }\n const order = await this.placeOrder({\n items: session.input.items,\n customer: session.input.customer,\n discountCode: session.input.discountCode ?? undefined,\n shippingAddress: session.input.shippingAddress,\n } as PlaceOrderInput)\n // Paid on arrival: the mock only reaches here because the charge settled,\n // so an order left `pending` would contradict the very state we return.\n await this.updateOrder(order.id, { financialStatus: 'paid' })\n session.orderId = order.id\n return { state: 'paid', orderId: order.id }\n }\n\n // ---------------------------------------------------------------------------\n // Customers\n // ---------------------------------------------------------------------------\n\n async listCustomers(opts?: ListCustomersOptions) {\n this.syncCustomers()\n let list = [...this.customers]\n if (opts?.search) list = list.filter(c => `${c.firstName} ${c.lastName} ${c.email}`.toLowerCase().includes(opts.search!.toLowerCase()))\n if (opts?.limit) list = list.slice(0, opts.limit)\n return list\n }\n\n async getCustomer(id: string) {\n this.syncCustomers()\n return this.customers.find(c => c.id === id) ?? null\n }\n\n async createCustomer(input: CreateCustomerInput): Promise<ShopCustomer> {\n this.syncCustomers()\n const c: ShopCustomer = { id: uid(), tenantId: 'mock', firstName: input.firstName, lastName: input.lastName ?? '', email: input.email ?? null, phone: input.phone ?? null, document: input.document ?? null, notes: input.notes ?? null, ordersCount: 0, totalSpent: 0, createdAt: now(), updatedAt: now() }\n this.customers.push(c)\n this.persistCustomers()\n return c\n }\n\n async updateCustomer(id: string, input: UpdateCustomerInput): Promise<ShopCustomer> {\n this.syncCustomers()\n const i = this.customers.findIndex(c => c.id === id)\n if (i < 0) throw new Error('Customer not found')\n this.customers[i] = { ...this.customers[i], ...input, updatedAt: now() }\n this.persistCustomers()\n return this.customers[i]\n }\n\n async deleteCustomer(id: string) {\n this.syncCustomers()\n this.customers = this.customers.filter(c => c.id !== id)\n this.persistCustomers()\n }\n\n async resolveCustomer(input: ResolveCustomerInput): Promise<ShopCustomer> {\n this.syncCustomers()\n const email = input.email.trim().toLowerCase()\n const existing = this.customers.find(c => (c.email ?? '').toLowerCase() === email)\n if (existing) return existing\n const [first, ...rest] = (input.name?.trim() || email).split(/\\s+/)\n return this.createCustomer({ firstName: first || email, lastName: rest.join(' '), email })\n }\n\n // ---------------------------------------------------------------------------\n // Promotions (spine M6) — the mock provider IS the reference evaluator, so\n // tests and pilot fixtures exercise the rule engine without a database.\n // Seeded promotions ride as-is; legacy discounts ride through the adapter\n // (a percent code = one eligibility rule on code + percentage method).\n // ---------------------------------------------------------------------------\n\n async evaluatePromotions(input: { cart: RuleCartSnapshot }): Promise<ComputeAction[]> {\n const promotions: Promotion[] = [\n ...this.promotions,\n ...this.discounts.map(discountToPromotion).filter((p): p is Promotion => p !== null),\n ]\n const context = await buildRuleContext(input.cart)\n return computePromotionActions(input.cart, promotions, { context })\n }\n\n // ---------------------------------------------------------------------------\n // Discounts\n // ---------------------------------------------------------------------------\n\n async listDiscounts(opts?: ListDiscountsOptions) {\n let list = [...this.discounts]\n if (opts?.status) list = list.filter(d => d.status === opts.status)\n if (opts?.type) list = list.filter(d => d.type === opts.type)\n if (opts?.search) list = list.filter(d => d.title.toLowerCase().includes(opts.search!.toLowerCase()))\n if (opts?.limit) list = list.slice(0, opts.limit)\n return list\n }\n\n async getDiscount(id: string) { return this.discounts.find(d => d.id === id) ?? null }\n\n async createDiscount(input: CreateDiscountInput): Promise<Discount> {\n const d: Discount = { id: uid(), tenantId: 'mock', title: input.title, code: input.code ?? null, type: input.type, method: input.method ?? 'code', value: input.value, usageLimit: input.usageLimit ?? null, oncePerCustomer: input.oncePerCustomer ?? false, minSubtotal: input.minSubtotal ?? null, appliesTo: input.appliesTo ?? 'all', productIds: input.productIds ?? [], categoryIds: input.categoryIds ?? [], startsAt: input.startsAt ?? now(), endsAt: input.endsAt ?? null, status: input.status ?? 'active', timesUsed: 0, createdAt: now(), updatedAt: now() }\n this.discounts.push(d); return d\n }\n\n async updateDiscount(id: string, input: UpdateDiscountInput): Promise<Discount> {\n const i = this.discounts.findIndex(d => d.id === id)\n if (i < 0) throw new Error('Discount not found')\n this.discounts[i] = { ...this.discounts[i], ...input, updatedAt: now() }\n return this.discounts[i]\n }\n\n async deleteDiscount(id: string) { this.discounts = this.discounts.filter(d => d.id !== id) }\n\n // ---------------------------------------------------------------------------\n // Sales channels\n // ---------------------------------------------------------------------------\n\n async listSalesChannels(): Promise<SalesChannel[]> {\n this.syncChannels()\n return [...this.channels].sort((a, b) => a.position - b.position)\n }\n\n async createSalesChannel(input: CreateSalesChannelInput): Promise<SalesChannel> {\n this.syncChannels()\n const c: SalesChannel = { id: uid(), tenantId: 'mock', kind: input.kind, label: input.label, url: input.url ?? null, enabled: input.enabled ?? true, position: input.position ?? this.channels.length, createdAt: now(), updatedAt: now() }\n this.channels.push(c); this.persistChannels(); return c\n }\n\n async updateSalesChannel(id: string, input: UpdateSalesChannelInput): Promise<SalesChannel> {\n this.syncChannels()\n const i = this.channels.findIndex(c => c.id === id)\n if (i < 0) throw new Error('Sales channel not found')\n this.channels[i] = { ...this.channels[i], ...input, updatedAt: now() }\n this.persistChannels(); return this.channels[i]\n }\n\n async deleteSalesChannel(id: string): Promise<void> {\n this.syncChannels()\n this.channels = this.channels.filter(c => c.id !== id)\n this.persistChannels()\n }\n\n // ---------------------------------------------------------------------------\n // Store policy + delivery fallback\n //\n // A single object behind a list-shaped store helper, so the same loadStored /\n // store pair serves it. Absent = null, NOT an object of defaults: \"nothing\n // decided\" is a state the callers are written to handle, and manufacturing\n // defaults here would hide the one case the live provider really has.\n // ---------------------------------------------------------------------------\n\n async getStoreSettings(): Promise<StoreSettings | null> {\n return loadStored<StoreSettings>(SETTINGS_KEY)[0] ?? null\n }\n\n async updateStoreSettings(input: UpdateStoreSettingsInput): Promise<StoreSettings> {\n const next: StoreSettings = { ...(await this.getStoreSettings() ?? {}), ...input }\n store(SETTINGS_KEY, [next])\n return next\n }\n\n /** In mock mode there is no publication gate to fail, so the shopper's read\n * and the merchant's are the same row. */\n async getPublicStoreSettings(): Promise<StoreSettings | null> {\n return this.getStoreSettings()\n }\n\n /**\n * Mock mode has no delivery zones at all, so nothing is refused and no zone is\n * the store's own. Answered rather than omitted so a screen developed against\n * the mock sees the same shape it will see live — an absent method would make\n * the caller take its \"provider cannot check\" branch and never exercise this.\n */\n async checkDelivery(): Promise<DeliveryCheck> {\n return { refused: false, ownZone: false }\n }\n\n async getShippingSettings(): Promise<ShippingSettings | null> {\n return loadStored<ShippingSettings>(SHIPPING_SETTINGS_KEY)[0] ?? null\n }\n\n async updateShippingSettings(input: UpdateShippingSettingsInput): Promise<ShippingSettings> {\n const current = await this.getShippingSettings()\n const next: ShippingSettings = {\n flatRate: input.flatRate ?? current?.flatRate ?? 0,\n freeAbove: input.freeAbove !== undefined ? input.freeAbove : current?.freeAbove ?? null,\n currency: input.currency ?? current?.currency ?? 'BRL',\n }\n store(SHIPPING_SETTINGS_KEY, [next])\n return next\n }\n\n // ---------------------------------------------------------------------------\n // Custom entities (spine M4) — same EntityStore port as the live provider.\n // ---------------------------------------------------------------------------\n\n async listEntityRecords(entity: string, options?: ListEntityRecordsOptions): Promise<EntityRecord[]> {\n return this.entityStore(entity).list(options)\n }\n\n async getEntityRecord(entity: string, id: string): Promise<EntityRecord | null> {\n return this.entityStore(entity).get(id)\n }\n\n async getEntityRecordBySlug(entity: string, slug: string): Promise<EntityRecord | null> {\n return this.entityStore(entity).getBySlug(slug)\n }\n\n async createEntityRecord(entity: string, input: EntityRecordInput): Promise<EntityRecord> {\n return this.entityStore(entity).create(input)\n }\n\n async updateEntityRecord(entity: string, id: string, input: Partial<EntityRecordInput>): Promise<EntityRecord> {\n return this.entityStore(entity).update(id, input)\n }\n\n async deleteEntityRecord(entity: string, id: string): Promise<void> {\n return this.entityStore(entity).delete(id)\n }\n\n // Coleções, grupos/segmentos, vale-presente e e-mails — paridade com o\n // provider Supabase. Mídia não entra: é storage, não tem mock honesto.\n\nasync listCollections(): Promise<Collection[]> {\n this.syncCollections()\n return [...this.collections].sort((a, b) => a.sortOrder - b.sortOrder)\n }\n\n async getCollection(id: string): Promise<Collection | null> {\n this.syncCollections()\n return this.collections.find(c => c.id === id) ?? null\n }\n\n async createCollection(input: CreateCollectionInput): Promise<Collection> {\n this.syncCollections()\n const c: Collection = {\n id: uid(), tenantId: 'mock',\n title: input.title,\n handle: input.handle?.trim() || mockSlugify(input.title),\n description: input.description ?? null,\n imageUrl: input.imageUrl ?? null,\n seoTitle: input.seoTitle ?? null,\n seoDescription: input.seoDescription ?? null,\n published: input.published ?? true,\n sortOrder: input.sortOrder ?? this.collections.length,\n productIds: input.productIds ?? [],\n createdAt: now(), updatedAt: now(),\n }\n this.collections.push(c); this.persistCollections(); return c\n }\n\n async updateCollection(id: string, input: UpdateCollectionInput): Promise<Collection> {\n this.syncCollections()\n const i = this.collections.findIndex(c => c.id === id)\n if (i < 0) throw new Error('Collection not found')\n this.collections[i] = { ...this.collections[i], ...input, updatedAt: now() }\n this.persistCollections(); return this.collections[i]\n }\n\n async deleteCollection(id: string): Promise<void> {\n this.syncCollections()\n this.collections = this.collections.filter(c => c.id !== id)\n this.persistCollections()\n }\n\n async listCustomerGroups(): Promise<CustomerGroup[]> {\n const stored = loadStored<CustomerGroup>(CUSTOMER_GROUPS_KEY)\n if (stored.length) this.customerGroups = stored\n return [...this.customerGroups].sort((a, b) => a.name.localeCompare(b.name, 'pt-BR'))\n }\n\n async createCustomerGroup(input: CreateCustomerGroupInput): Promise<CustomerGroup> {\n await this.listCustomerGroups()\n const g: CustomerGroup = {\n id: uid(), tenantId: 'mock',\n name: input.name,\n description: input.description ?? null,\n color: input.color ?? null,\n customerIds: input.customerIds ?? [],\n createdAt: now(), updatedAt: now(),\n }\n this.customerGroups.push(g); store(CUSTOMER_GROUPS_KEY, this.customerGroups); return g\n }\n\n async updateCustomerGroup(id: string, input: UpdateCustomerGroupInput): Promise<CustomerGroup> {\n await this.listCustomerGroups()\n const i = this.customerGroups.findIndex(g => g.id === id)\n if (i < 0) throw new Error('Customer group not found')\n this.customerGroups[i] = { ...this.customerGroups[i], ...input, updatedAt: now() }\n store(CUSTOMER_GROUPS_KEY, this.customerGroups); return this.customerGroups[i]\n }\n\n async deleteCustomerGroup(id: string): Promise<void> {\n await this.listCustomerGroups()\n // Only the grouping goes: the customers in it are untouched.\n this.customerGroups = this.customerGroups.filter(g => g.id !== id)\n store(CUSTOMER_GROUPS_KEY, this.customerGroups)\n }\n\n async listCustomerSegments(): Promise<CustomerSegment[]> {\n const stored = loadStored<CustomerSegment>(CUSTOMER_SEGMENTS_KEY)\n if (stored.length) this.customerSegments = stored\n return [...this.customerSegments].sort((a, b) => a.name.localeCompare(b.name, 'pt-BR'))\n }\n\n async createCustomerSegment(input: CreateCustomerSegmentInput): Promise<CustomerSegment> {\n await this.listCustomerSegments()\n const s: CustomerSegment = {\n id: uid(), tenantId: 'mock',\n name: input.name,\n description: input.description ?? null,\n minOrders: input.minOrders ?? null,\n maxOrders: input.maxOrders ?? null,\n minSpent: input.minSpent ?? null,\n maxSpent: input.maxSpent ?? null,\n joinedAfter: input.joinedAfter ?? null,\n joinedBefore: input.joinedBefore ?? null,\n createdAt: now(), updatedAt: now(),\n }\n this.customerSegments.push(s); store(CUSTOMER_SEGMENTS_KEY, this.customerSegments); return s\n }\n\n async updateCustomerSegment(id: string, input: UpdateCustomerSegmentInput): Promise<CustomerSegment> {\n await this.listCustomerSegments()\n const i = this.customerSegments.findIndex(s => s.id === id)\n if (i < 0) throw new Error('Customer segment not found')\n this.customerSegments[i] = { ...this.customerSegments[i], ...input, updatedAt: now() }\n store(CUSTOMER_SEGMENTS_KEY, this.customerSegments); return this.customerSegments[i]\n }\n\n async deleteCustomerSegment(id: string): Promise<void> {\n await this.listCustomerSegments()\n this.customerSegments = this.customerSegments.filter(s => s.id !== id)\n store(CUSTOMER_SEGMENTS_KEY, this.customerSegments)\n }\n\n async listGiftCards(): Promise<GiftCard[]> {\n this.syncGiftCards()\n return [...this.giftCards].sort((a, b) => b.createdAt.localeCompare(a.createdAt))\n }\n\n async createGiftCard(input: CreateGiftCardInput): Promise<GiftCard> {\n this.syncGiftCards()\n const amount = Number(input.initialBalance) || 0\n const g: GiftCard = {\n id: uid(), tenantId: 'mock',\n code: (input.code?.trim() || mockGiftCardCode()).toUpperCase(),\n // Same rule the supabase provider enforces: a new card is worth its face\n // value, and only redemption moves the remaining balance.\n initialBalance: amount, balance: amount,\n currency: input.currency ?? 'BRL',\n status: input.status ?? 'active',\n expiresAt: input.expiresAt ?? null,\n customerId: input.customerId ?? null,\n customerEmail: input.customerEmail ?? null,\n note: input.note ?? null,\n createdAt: now(), updatedAt: now(),\n }\n this.giftCards.push(g); this.persistGiftCards(); return g\n }\n\n async updateGiftCard(id: string, input: UpdateGiftCardInput): Promise<GiftCard> {\n this.syncGiftCards()\n const i = this.giftCards.findIndex(g => g.id === id)\n if (i < 0) throw new Error('Gift card not found')\n const code = input.code !== undefined ? input.code.trim().toUpperCase() : this.giftCards[i].code\n this.giftCards[i] = { ...this.giftCards[i], ...input, code, updatedAt: now() }\n this.persistGiftCards(); return this.giftCards[i]\n }\n\n async deleteGiftCard(id: string): Promise<void> {\n this.syncGiftCards()\n this.giftCards = this.giftCards.filter(g => g.id !== id)\n this.persistGiftCards()\n }\n\n async listEmailTemplates(): Promise<EmailTemplate[]> {\n this.syncEmailTemplates()\n return [...this.emailTemplates]\n }\n\n async upsertEmailTemplate(input: UpsertEmailTemplateInput): Promise<EmailTemplate> {\n this.syncEmailTemplates()\n const i = this.emailTemplates.findIndex(t => t.event === input.event)\n const base: EmailTemplate = i >= 0 ? this.emailTemplates[i] : {\n id: uid(), tenantId: 'mock', event: input.event,\n enabled: false, subject: null, body: null, updatedAt: now(),\n }\n const next: EmailTemplate = { ...base, ...input, updatedAt: now() }\n if (i >= 0) this.emailTemplates[i] = next\n else this.emailTemplates.push(next)\n store(EMAIL_TEMPLATES_KEY, this.emailTemplates)\n return next\n }\n\nprivate syncCollections() {\n const stored = loadStored<Collection>(COLLECTIONS_KEY)\n if (stored.length) this.collections = stored\n }\n\n private persistCollections() { store(COLLECTIONS_KEY, this.collections) }\n\n private syncGiftCards() {\n const stored = loadStored<GiftCard>(GIFT_CARDS_KEY)\n if (stored.length) this.giftCards = stored\n }\n\n private persistGiftCards() { store(GIFT_CARDS_KEY, this.giftCards) }\n\n private syncEmailTemplates() {\n const stored = loadStored<EmailTemplate>(EMAIL_TEMPLATES_KEY)\n if (stored.length) this.emailTemplates = stored\n }\n}\n\nexport function createMockShopProvider(seed?: MockShopSeed): ShopProvider {\n return new MockShopProvider(seed)\n}\n"]}
@@ -457,6 +457,9 @@ function previewCouponPercent(promotions, code, cart = { items: [] }, options =
457
457
  if (reason === "inactive") return { valid: false, percent: 0, reason: "not_found" };
458
458
  if (reason !== null) return { valid: false, percent: 0, reason };
459
459
  const method = promotion.applicationMethod;
460
+ if (method.targetType === "shipping" && method.type === "percentage" && method.value >= 100) {
461
+ return { valid: true, percent: 0, freeShipping: true };
462
+ }
460
463
  if (method.type !== "percentage" || method.targetType !== "order" || method.buyRulesMinQuantity != null) {
461
464
  return { valid: false, percent: 0, reason: "unsupported" };
462
465
  }
@@ -522,5 +525,5 @@ function clearRuleContextProviders() {
522
525
  }
523
526
 
524
527
  export { APPLICATION_METHOD_ALLOCATIONS, APPLICATION_METHOD_TARGET_TYPES, APPLICATION_METHOD_TYPES, CORE_RULE_ATTRIBUTES, ITEM_PATH_PREFIX, PROMOTION_STATUSES, PROMOTION_TYPES, RULE_ATTRIBUTE_FIELD_TYPES, RULE_OPERATORS, actionsDiscountTotal, buildRuleContext, cartSubtotal, clearRuleAttributes, clearRuleContextProviders, computePromotionActions, defineRuleContextProvider, discountToPromotion, hasRuleAttribute, isItemScopedAttribute, listRuleAttributeKeys, listRuleAttributes, matchRuleValues, orderPromotions, previewCouponPercent, promotionGateReason, registerCoreRuleAttributes, registerRuleAttribute, resolveRuleAttribute, roundCents, ruleAttributeRegistry, ruleContextRegistry, rulesMatchCart, splitProportionally, storefrontDiscountToPromotion, validateRuleContextResult };
525
- //# sourceMappingURL=chunk-3GERSY5F.js.map
526
- //# sourceMappingURL=chunk-3GERSY5F.js.map
528
+ //# sourceMappingURL=chunk-UVQ6UUDN.js.map
529
+ //# sourceMappingURL=chunk-UVQ6UUDN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/rules/rule-types.ts","../src/rules/attributes.ts","../src/rules/evaluator.ts","../src/rules/adapter.ts","../src/rules/context.ts"],"names":["Registry"],"mappings":"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","file":"chunk-UVQ6UUDN.js","sourcesContent":["// ---------------------------------------------------------------------------\n// The rule model (spine §3 L2, milestone M6) — ONE rule engine, as data.\n//\n// Adopted nearly verbatim from Medusa's promotion module because it is correct\n// (spine I8): `rule(attribute, operator)` with values in a child table, three\n// rule sets (eligibility / target / buy), and an application_method whose six\n// integers and two rule sets express buy-N-get-M, tiered, BOGO, percentage and\n// fixed across `each | across | once`. \"Buy 3 pay 2\" is pure data, zero code —\n// see evaluator.test.ts (the acceptance test).\n//\n// Everything in this module is SERIALIZABLE AND ENGINE-INDEPENDENT (spine I11):\n// the portable artifact is the rule schema, never the evaluator. A promotion\n// here survives JSON round-tripping, rides in the Store Document's\n// `promotions` section, and is evaluated identically by the TypeScript\n// reference implementation (evaluator.ts) and the SQL function\n// (migrations/0033) — the TS implementation is the spec, the SQL mirrors it.\n//\n// This is a LEAF module: types and enum vocabularies only, so the storefront\n// validator, the document section, and the evaluator can all import it\n// without dragging in providers.\n// ---------------------------------------------------------------------------\n\n/** The 7 rule operators. This is the closed set — widening it is a model\n * change (TS union + DB CHECK + SQL evaluator), not an insert. */\nexport const RULE_OPERATORS = ['gte', 'lte', 'gt', 'lt', 'eq', 'ne', 'in'] as const\nexport type RuleOperator = (typeof RULE_OPERATORS)[number]\n\n/** A rule value is a JSON scalar. The DB stores each in its own\n * plg_shop_rule_values row (values-in-a-child-table, per the model). */\nexport type RuleValue = string | number | boolean\n\n/**\n * One rule: `attribute` names a row of the rule_attribute VOCABULARY (I9 —\n * never a free-form dotted path; an unknown attribute is an I2 hard error\n * naming the valid set), `operator` is one of the 7, `values` is the child\n * list (a single-element list for scalar operators).\n */\nexport interface PromotionRule {\n attribute: string\n operator: RuleOperator\n values: RuleValue[]\n}\n\nexport const APPLICATION_METHOD_TYPES = ['percentage', 'fixed'] as const\nexport type ApplicationMethodType = (typeof APPLICATION_METHOD_TYPES)[number]\n\nexport const APPLICATION_METHOD_TARGET_TYPES = ['order', 'items', 'shipping'] as const\nexport type ApplicationMethodTargetType = (typeof APPLICATION_METHOD_TARGET_TYPES)[number]\n\nexport const APPLICATION_METHOD_ALLOCATIONS = ['each', 'across', 'once'] as const\nexport type ApplicationMethodAllocation = (typeof APPLICATION_METHOD_ALLOCATIONS)[number]\n\n/**\n * HOW an eligible promotion applies. The six numbers + two rule sets that make\n * buy-N-pay-M pure data:\n *\n * - `type` percentage (value = percentage points) or fixed (value = amount).\n * - `targetType` order (spread across all items) | items | shipping.\n * - `allocation` (items only):\n * each — per unit of each eligible line, `maxQuantity` units per line;\n * across — one amount over the eligible subtotal, split proportionally;\n * once — one unit of the cheapest eligible line, once.\n * - `buyRulesMinQuantity` + `buyRules` — what must be in the cart, and how\n * many, for the promotion to fire (buyget). The promotion applies\n * floor(matched buy quantity / buyRulesMinQuantity) times.\n * - `applyToQuantity` — how many target units each firing discounts.\n * - `targetRules` — which items the discount lands on. A buyget whose target\n * is not in the cart but is pinned to one product id emits addFreeItem.\n */\nexport interface ApplicationMethod {\n type: ApplicationMethodType\n value: number\n targetType: ApplicationMethodTargetType\n allocation?: ApplicationMethodAllocation\n /** Unit cap: per line for `each`; total discounted/free units for buyget. */\n maxQuantity?: number | null\n /** Buyget: target units discounted per firing. */\n applyToQuantity?: number | null\n /** Buyget: matched buy quantity required per firing. Null/absent = standard. */\n buyRulesMinQuantity?: number | null\n /** What gets discounted (the `target` pivot). Absent = every item. */\n targetRules?: PromotionRule[]\n /** What must be bought (the `buy` pivot). Item-scoped attributes only. */\n buyRules?: PromotionRule[]\n}\n\nexport const PROMOTION_TYPES = ['standard', 'buyget'] as const\nexport type PromotionType = (typeof PROMOTION_TYPES)[number]\n\nexport const PROMOTION_STATUSES = ['draft', 'active', 'inactive'] as const\nexport type PromotionStatus = (typeof PROMOTION_STATUSES)[number]\n\n/**\n * A promotion: eligibility rules (the `eligibility` pivot) + one application\n * method. `code` promotions fire only when the shopper entered the code\n * (cart.codes); `isAutomatic` promotions fire whenever eligible.\n */\nexport interface Promotion {\n id: string\n /** Coupon code. Null/absent = automatic-only. Matched case-insensitively. */\n code?: string | null\n isAutomatic?: boolean\n /** Derivable (buyRulesMinQuantity ⇒ buyget) but stored for the admin UI. */\n type?: PromotionType\n status?: PromotionStatus\n campaignId?: string | null\n /** Does this promotion apply at all? (the `eligibility` pivot). AND across\n * rules; a rule's values are OR. Absent/empty = always eligible. */\n rules?: PromotionRule[]\n applicationMethod: ApplicationMethod\n startsAt?: string | null\n endsAt?: string | null\n usageLimit?: number | null\n timesUsed?: number\n}\n\n/** A campaign groups promotions for reporting/budgets. Parent row only in M6;\n * budget enforcement is a later milestone. */\nexport interface Campaign {\n id: string\n name: string\n startsAt?: string | null\n endsAt?: string | null\n}\n\n// --- The cart snapshot the engine evaluates against ---------------------------\n\n/** One cart line as the engine sees it. Prices are authoritative-catalog\n * prices; the engine never trusts a client-computed total. */\nexport interface RuleCartItem {\n /** Line identity actions refer back to. Defaults to productId. */\n id?: string\n productId: string\n quantity: number\n unitPrice: number\n categoryId?: string | null\n collectionId?: string | null\n}\n\n/**\n * The evaluation input. Serializable on purpose: the SAME snapshot shape is\n * the TS evaluator's input and the SQL function's `p_cart` jsonb, so the\n * preview a shopper sees and the revalidation place_order runs read one\n * contract.\n */\nexport interface RuleCartSnapshot {\n items: RuleCartItem[]\n /** Quoted shipping — what a shipping-target promotion discounts. */\n shippingTotal?: number | null\n /** Shipping region/zone identifier (the shipping.region attribute). */\n region?: string | null\n customer?: { email?: string | null; tags?: string[] }\n /** Promotion codes the shopper entered (the code attribute; case-insensitive). */\n codes?: string[]\n currency?: string\n}\n\n// --- Compute actions (the engine's output) ------------------------------------\n\n/** Discount one cart line by an absolute amount (already allocation-resolved). */\nexport interface AddItemDiscountAction {\n action: 'addItemDiscount'\n promotionId: string\n code?: string | null\n itemId: string\n amount: number\n}\n\n/** Discount the shipping total by an absolute amount. */\nexport interface AddShippingDiscountAction {\n action: 'addShippingDiscount'\n promotionId: string\n code?: string | null\n amount: number\n}\n\n/** Add `quantity` free units of a product the buyget promotion grants but the\n * cart does not contain. The cart applies it by adding the line at price 0. */\nexport interface AddFreeItemAction {\n action: 'addFreeItem'\n promotionId: string\n code?: string | null\n productId: string\n quantity: number\n}\n\n/**\n * The ordered action list computePromotionActions returns. Deterministic:\n * buyget promotions first (they consume target units), then by specificity\n * (total rules count DESC), then id — so replaying the same cart against the\n * same promotions always yields byte-identical actions.\n */\nexport type ComputeAction = AddItemDiscountAction | AddShippingDiscountAction | AddFreeItemAction\n\n/** Sum of a cart's line totals, cents-rounded — the number `cart.subtotal`\n * rules compare against. */\nexport function cartSubtotal(cart: RuleCartSnapshot): number {\n return roundCents(cart.items.reduce((sum, item) => sum + item.unitPrice * item.quantity, 0))\n}\n\n/** Cents rounding, the house money convention (commerce.ts round2). */\nexport function roundCents(value: number): number {\n return Math.round(value * 100) / 100\n}\n","import { Registry } from '@fayz-ai/core'\nimport type { RegistryMeta } from '@fayz-ai/core'\nimport { RULE_OPERATORS } from './rule-types'\nimport type { RuleOperator } from './rule-types'\n\n// ---------------------------------------------------------------------------\n// The rule attribute VOCABULARY — data, not a hardcoded list (spine I9).\n//\n// Medusa's promotion engine accepts any dotted path, its admin whitelist is a\n// literal array in the API layer, and the real bound is a hardcoded 50-entry\n// field list that silently decides which rules can ever match — a rule on an\n// unknown attribute evaluates against `undefined` and just fails. The fix is\n// to publish `rule_attribute(key, path, label, field_type, value_source,\n// operators[])` as ROWS: the admin form renders itself from the same data the\n// AI reads (describeStore), validateStore checks documents against it, the\n// evaluator refuses attributes outside it (I2, never a silent non-match), and\n// WIDENING the vocabulary is an insert — defineRuleContextProvider for code,\n// a plain INSERT for SQL.\n//\n// The TS registry here and the plg_shop_rule_attributes seed rows (migration\n// 0032) carry the SAME core vocabulary; migrations.test.ts cross-checks the\n// two so they cannot drift.\n// ---------------------------------------------------------------------------\n\nexport const RULE_ATTRIBUTE_FIELD_TYPES = ['text', 'number', 'boolean'] as const\nexport type RuleAttributeFieldType = (typeof RULE_ATTRIBUTE_FIELD_TYPES)[number]\n\n/**\n * One vocabulary row.\n *\n * `path` locates the value in the evaluation context built from the cart\n * snapshot. Paths under `items.` are ITEM-scoped: they evaluate per cart line\n * (scoping target/buy rules to lines; for eligibility, \"some line matches\").\n * Every other path is CART-scoped, walked from the snapshot root. A context\n * provider's attributes resolve by KEY from the provided context instead.\n *\n * `value_source` names the id list an admin form offers as values\n * ('products', 'categories', …) — a UI hint, never an evaluation input.\n */\nexport interface RuleAttribute {\n key: string\n path: string\n label: string\n fieldType: RuleAttributeFieldType\n /** Where an admin form fetches candidate values. Null = free entry. */\n valueSource?: string | null\n /** The operators this attribute supports — a subset of the 7. */\n operators: readonly RuleOperator[]\n}\n\nconst ID_OPERATORS: readonly RuleOperator[] = ['eq', 'ne', 'in']\nconst NUMBER_OPERATORS: readonly RuleOperator[] = ['gte', 'lte', 'gt', 'lt', 'eq', 'ne']\n\n/** Prefix that marks an attribute path as item-scoped. */\nexport const ITEM_PATH_PREFIX = 'items.'\n\n/**\n * The core vocabulary — what every Fayz-backed store starts with, mirrored as\n * the plg_shop_rule_attributes seed rows in migration 0032.\n */\nexport const CORE_RULE_ATTRIBUTES: readonly RuleAttribute[] = [\n {\n key: 'code',\n path: 'codes',\n label: 'Cupom informado',\n fieldType: 'text',\n valueSource: null,\n operators: ['eq', 'in'],\n },\n {\n key: 'cart.subtotal',\n path: 'subtotal',\n label: 'Subtotal do carrinho',\n fieldType: 'number',\n valueSource: null,\n operators: NUMBER_OPERATORS,\n },\n {\n key: 'item.quantity',\n path: 'items.quantity',\n label: 'Quantidade do item',\n fieldType: 'number',\n valueSource: null,\n operators: NUMBER_OPERATORS,\n },\n {\n key: 'product.id',\n path: 'items.product_id',\n label: 'Produto',\n fieldType: 'text',\n valueSource: 'products',\n operators: ID_OPERATORS,\n },\n {\n key: 'product.category_id',\n path: 'items.category_id',\n label: 'Categoria do produto',\n fieldType: 'text',\n valueSource: 'categories',\n operators: ID_OPERATORS,\n },\n {\n key: 'product.collection_id',\n path: 'items.collection_id',\n label: 'Coleção do produto',\n fieldType: 'text',\n valueSource: 'collections',\n operators: ID_OPERATORS,\n },\n {\n key: 'customer.email',\n path: 'customer.email',\n label: 'E-mail do cliente',\n fieldType: 'text',\n valueSource: null,\n operators: ID_OPERATORS,\n },\n {\n key: 'customer.tag',\n path: 'customer.tags',\n label: 'Tag do cliente',\n fieldType: 'text',\n valueSource: 'customer_tags',\n operators: ['eq', 'ne', 'in'],\n },\n {\n key: 'shipping.region',\n path: 'shipping.region',\n label: 'Região de entrega',\n fieldType: 'text',\n valueSource: 'regions',\n operators: ID_OPERATORS,\n },\n]\n\n// --- The registry -------------------------------------------------------------\n// Uniform Registry<T> meta envelope (M1), same as blocks/loaders/handles, so\n// `describeRuleAttributes()` feeds describeStore through the same parser every\n// other registry uses.\n\nexport const ruleAttributeRegistry = new Registry<RuleAttribute>('ruleAttribute')\n\nlet coreRegistered = false\n\n/** Idempotent — mirrors registerStorefrontBlocks: consumers call before reads. */\nexport function registerCoreRuleAttributes(): void {\n if (coreRegistered && ruleAttributeRegistry.has('code')) return\n for (const attribute of CORE_RULE_ATTRIBUTES) {\n ruleAttributeRegistry.register(attribute.key, attribute, {\n title: attribute.label,\n description: `Rule attribute (${attribute.fieldType}) — operators: ${attribute.operators.join(', ')}`,\n source: 'sdk',\n })\n }\n coreRegistered = true\n}\n\nexport interface RegisterRuleAttributeOptions {\n meta?: RegistryMeta\n /** Re-registering an existing key is an error unless the caller owns it\n * (module re-evaluation under HMR re-registers the same declaration). */\n replace?: boolean\n}\n\n/**\n * Widen the vocabulary with one attribute. Duplicate keys are an I2 hard\n * error naming the taken set — two providers silently fighting over one key\n * would make rules mean different things on different renders.\n */\nexport function registerRuleAttribute(attribute: RuleAttribute, options: RegisterRuleAttributeOptions = {}): void {\n registerCoreRuleAttributes()\n if (!attribute.key) throw new Error('registerRuleAttribute: attribute.key is required')\n if (!RULE_ATTRIBUTE_FIELD_TYPES.includes(attribute.fieldType)) {\n throw new Error(\n `registerRuleAttribute: \"${attribute.key}\" has unknown fieldType \"${attribute.fieldType}\". ` +\n `Valid field types: ${RULE_ATTRIBUTE_FIELD_TYPES.join(', ')}`,\n )\n }\n for (const op of attribute.operators) {\n if (!RULE_OPERATORS.includes(op)) {\n throw new Error(\n `registerRuleAttribute: \"${attribute.key}\" declares unknown operator \"${op}\". ` +\n `Valid operators: ${RULE_OPERATORS.join(', ')}`,\n )\n }\n }\n if (ruleAttributeRegistry.has(attribute.key) && !options.replace) {\n throw new Error(\n `registerRuleAttribute: attribute \"${attribute.key}\" is already registered. ` +\n `Registered attributes: ${listRuleAttributeKeys().join(', ')}`,\n )\n }\n ruleAttributeRegistry.register(attribute.key, attribute, {\n title: attribute.label,\n description: `Rule attribute (${attribute.fieldType}) — operators: ${attribute.operators.join(', ')}`,\n source: 'app',\n ...options.meta,\n })\n}\n\n/** The attribute for a key, or an I2 hard error naming the valid set — the\n * only lookup the evaluator and the validators may use. */\nexport function resolveRuleAttribute(key: string): RuleAttribute {\n registerCoreRuleAttributes()\n const attribute = ruleAttributeRegistry.get(key)\n if (!attribute) {\n throw new Error(`Unknown rule attribute \"${key}\". Registered attributes: ${listRuleAttributeKeys().join(', ')}`)\n }\n return attribute\n}\n\nexport function hasRuleAttribute(key: string): boolean {\n registerCoreRuleAttributes()\n return ruleAttributeRegistry.has(key)\n}\n\n/** Every attribute key, sorted — the valid set I2 errors name. */\nexport function listRuleAttributeKeys(): string[] {\n registerCoreRuleAttributes()\n return ruleAttributeRegistry.ids().sort()\n}\n\n/** Every vocabulary row, sorted by key — what describeStore publishes and the\n * admin promotion form renders itself from. */\nexport function listRuleAttributes(): RuleAttribute[] {\n registerCoreRuleAttributes()\n return ruleAttributeRegistry\n .list()\n .map((entry) => entry.value)\n .sort((a, b) => a.key.localeCompare(b.key))\n}\n\n/** True when the attribute evaluates per cart line. */\nexport function isItemScopedAttribute(attribute: RuleAttribute): boolean {\n return attribute.path.startsWith(ITEM_PATH_PREFIX)\n}\n\n/** Test seam — suites that widen the vocabulary must not leak into the next.\n * Core attributes re-register on the next read. */\nexport function clearRuleAttributes(): void {\n ruleAttributeRegistry.clear()\n coreRegistered = false\n}\n","import { isItemScopedAttribute, resolveRuleAttribute } from './attributes'\nimport type { RuleAttribute } from './attributes'\nimport type { RuleContext } from './context'\nimport {\n cartSubtotal,\n roundCents,\n} from './rule-types'\nimport type {\n ApplicationMethod,\n ComputeAction,\n Promotion,\n PromotionRule,\n RuleCartItem,\n RuleCartSnapshot,\n RuleValue,\n} from './rule-types'\n\n// ---------------------------------------------------------------------------\n// computePromotionActions — the TypeScript REFERENCE implementation of the\n// rule engine (spine §3 L2, M6). Pure: (cart snapshot, promotions, context) →\n// ordered actions. No provider, no clock (injected), no I/O — which is what\n// makes it exhaustively unit-testable and runnable in the storefront preview,\n// the mock provider and (later) a server, unchanged.\n//\n// THIS FILE IS THE SPEC. The SQL function shop_compute_promotion_actions\n// (packages/shop/migrations/0033_rule_engine_eval.sql) mirrors these\n// semantics for the trust boundary — place_order revalidates server-side so\n// the browser can never set what it pays. Change semantics HERE first, with\n// tests, then re-emit the SQL to match.\n//\n// Semantics, precisely:\n// - A promotion is eligible when its status/date/usage gates pass, its code\n// (if any) was entered, and ALL eligibility rules match (a rule's values\n// are OR; item-scoped eligibility rules match when SOME line matches).\n// - Unknown rule attributes are an I2 hard error naming the valid set —\n// never a silent non-match (the Medusa failure I9 exists to end).\n// - Buyget (buyRulesMinQuantity ≥ 1): the promotion fires\n// floor(matched buy qty / buyRulesMinQuantity) times, discounting\n// applyToQuantity target units per firing, cheapest-eligible-units first,\n// capped by maxQuantity. A target pinned to one product id that is absent\n// from the cart becomes addFreeItem instead.\n// - Standard: percentage|fixed over order (spread proportionally) | items\n// (each: per-unit per line, maxQuantity units per line; across: one amount\n// split proportionally over the eligible subtotal; once: one unit of the\n// cheapest eligible line) | shipping.\n// - Output order is deterministic: buyget before standard (they consume\n// units), then total rules count DESC (specific before generic), then id.\n// ---------------------------------------------------------------------------\n\nexport interface EvaluateOptions {\n /** Extra attribute values, keyed by attribute KEY — the validated output of\n * buildRuleContext (context providers). Wins over snapshot resolution. */\n context?: RuleContext\n /** ISO timestamp the date-window gates compare against. Default: now. */\n now?: string\n}\n\n// --- Attribute resolution -----------------------------------------------------\n\n/** items.* path suffix → RuleCartItem field. The vocabulary speaks the wire's\n * snake_case (it is also the SQL function's vocabulary); the TS snapshot is\n * camelCase. */\nconst ITEM_FIELDS: Record<string, keyof RuleCartItem> = {\n quantity: 'quantity',\n unit_price: 'unitPrice',\n product_id: 'productId',\n category_id: 'categoryId',\n collection_id: 'collectionId',\n}\n\nfunction itemValue(item: RuleCartItem, attribute: RuleAttribute): unknown {\n const field = ITEM_FIELDS[attribute.path.slice('items.'.length)]\n return field ? item[field] : undefined\n}\n\n/** Cart-scoped resolution: context (by key) wins, then a dot-walk of the\n * snapshot-derived root. Returns a flat list — array values (codes, tags)\n * flatten so `eq` means membership. */\nfunction cartValues(cart: RuleCartSnapshot, attribute: RuleAttribute, context: RuleContext): unknown[] {\n if (attribute.key in context) return flatten(context[attribute.key])\n const root: Record<string, unknown> = {\n subtotal: cartSubtotal(cart),\n codes: (cart.codes ?? []).map((code) => code.trim().toUpperCase()),\n customer: { email: cart.customer?.email ?? null, tags: cart.customer?.tags ?? [] },\n shipping: { region: cart.region ?? null, total: cart.shippingTotal ?? null },\n }\n let value: unknown = root\n for (const segment of attribute.path.split('.')) {\n if (value === null || typeof value !== 'object') return []\n value = (value as Record<string, unknown>)[segment]\n }\n return flatten(value)\n}\n\nfunction flatten(value: unknown): unknown[] {\n if (value === null || value === undefined) return []\n return Array.isArray(value) ? value.filter((v) => v !== null && v !== undefined) : [value]\n}\n\n// --- Operator matching --------------------------------------------------------\n\nfunction scalarEq(a: unknown, b: RuleValue): boolean {\n if (typeof a === 'string' && typeof b === 'string') return a.toUpperCase() === b.toUpperCase()\n return a === b\n}\n\nfunction numeric(op: (a: number, b: number) => boolean, values: unknown[], ruleValues: RuleValue[]): boolean {\n const bound = Number(ruleValues[0])\n if (!Number.isFinite(bound)) return false\n return values.some((value) => {\n const n = Number(value)\n return Number.isFinite(n) && op(n, bound)\n })\n}\n\n/** One rule against a flat value list. Values are OR; `ne` is a negative and\n * therefore holds only when NO value equals any rule value. */\nexport function matchRuleValues(rule: PromotionRule, values: unknown[]): boolean {\n switch (rule.operator) {\n case 'eq':\n case 'in':\n return values.some((value) => rule.values.some((rv) => scalarEq(value, rv)))\n case 'ne':\n return !values.some((value) => rule.values.some((rv) => scalarEq(value, rv)))\n case 'gt':\n return numeric((a, b) => a > b, values, rule.values)\n case 'gte':\n return numeric((a, b) => a >= b, values, rule.values)\n case 'lt':\n return numeric((a, b) => a < b, values, rule.values)\n case 'lte':\n return numeric((a, b) => a <= b, values, rule.values)\n }\n}\n\nfunction ruleMatchesCart(rule: PromotionRule, cart: RuleCartSnapshot, context: RuleContext): boolean {\n const attribute = resolveRuleAttribute(rule.attribute)\n if (isItemScopedAttribute(attribute) && !(attribute.key in context)) {\n // Item-scoped at cart level: \"some line matches\".\n return cart.items.some((item) => matchRuleValues(rule, flatten(itemValue(item, attribute))))\n }\n return matchRuleValues(rule, cartValues(cart, attribute, context))\n}\n\nfunction ruleMatchesItem(rule: PromotionRule, item: RuleCartItem, cart: RuleCartSnapshot, context: RuleContext): boolean {\n const attribute = resolveRuleAttribute(rule.attribute)\n if (isItemScopedAttribute(attribute) && !(attribute.key in context)) {\n return matchRuleValues(rule, flatten(itemValue(item, attribute)))\n }\n // A cart-scoped rule inside a target/buy set gates the whole set.\n return matchRuleValues(rule, cartValues(cart, attribute, context))\n}\n\n/** ALL rules match (AND). Empty/absent = match. */\nexport function rulesMatchCart(rules: PromotionRule[] | undefined, cart: RuleCartSnapshot, context: RuleContext = {}): boolean {\n return (rules ?? []).every((rule) => ruleMatchesCart(rule, cart, context))\n}\n\nfunction itemsMatching(rules: PromotionRule[] | undefined, cart: RuleCartSnapshot, context: RuleContext): RuleCartItem[] {\n const list = rules ?? []\n return cart.items.filter((item) => list.every((rule) => ruleMatchesItem(rule, item, cart, context)))\n}\n\n// --- Eligibility gates --------------------------------------------------------\n\nexport type PromotionGateReason =\n | 'inactive'\n | 'not_started'\n | 'expired'\n | 'usage_limit'\n | 'code_not_entered'\n | 'rules_not_matched'\n\n/**\n * Why a promotion does NOT fire against this cart, or null when it does.\n * Shared by the evaluator and the coupon-surface adapter so a rejected code\n * reports the same machine-readable reason everywhere.\n */\nexport function promotionGateReason(\n promotion: Promotion,\n cart: RuleCartSnapshot,\n options: EvaluateOptions = {},\n): PromotionGateReason | null {\n const now = options.now ?? new Date().toISOString()\n if (promotion.status !== undefined && promotion.status !== 'active') return 'inactive'\n if (promotion.startsAt && promotion.startsAt > now) return 'not_started'\n if (promotion.endsAt && promotion.endsAt < now) return 'expired'\n if (promotion.usageLimit != null && (promotion.timesUsed ?? 0) >= promotion.usageLimit) return 'usage_limit'\n if (promotion.code) {\n const entered = (cart.codes ?? []).map((code) => code.trim().toUpperCase())\n if (!entered.includes(promotion.code.trim().toUpperCase())) return 'code_not_entered'\n } else if (promotion.isAutomatic === false) {\n // No code AND not automatic: nothing can ever trigger it.\n return 'code_not_entered'\n }\n if (!rulesMatchCart(promotion.rules, cart, options.context ?? {})) return 'rules_not_matched'\n return null\n}\n\n// --- Money helpers ------------------------------------------------------------\n\nfunction clampPercent(value: number): number {\n return Math.min(Math.max(value, 0), 100)\n}\n\n/** Split `total` across weights, in cents, largest-remainder — the parts sum\n * to exactly `total` so a spread discount never loses or invents a cent. */\nexport function splitProportionally(total: number, weights: number[]): number[] {\n const sum = weights.reduce((acc, weight) => acc + weight, 0)\n if (sum <= 0 || total <= 0) return weights.map(() => 0)\n const cents = Math.round(total * 100)\n const raw = weights.map((weight) => (cents * weight) / sum)\n const floors = raw.map(Math.floor)\n let remainder = cents - floors.reduce((acc, value) => acc + value, 0)\n const order = raw\n .map((value, index) => ({ index, frac: value - Math.floor(value) }))\n .sort((a, b) => b.frac - a.frac || a.index - b.index)\n for (const { index } of order) {\n if (remainder <= 0) break\n floors[index] += 1\n remainder -= 1\n }\n return floors.map((value) => value / 100)\n}\n\n// --- Per-promotion application ------------------------------------------------\n\ninterface ItemLike {\n item: RuleCartItem\n id: string\n}\n\nfunction lineId(item: RuleCartItem): string {\n return item.id ?? item.productId\n}\n\nfunction unitDiscount(method: ApplicationMethod, unitPrice: number): number {\n if (method.type === 'percentage') return roundCents((unitPrice * clampPercent(method.value)) / 100)\n return Math.min(method.value, unitPrice)\n}\n\nfunction isBuyget(promotion: Promotion): boolean {\n const min = promotion.applicationMethod.buyRulesMinQuantity\n return promotion.type === 'buyget' || (min != null && min >= 1)\n}\n\nfunction applyBuyget(promotion: Promotion, cart: RuleCartSnapshot, context: RuleContext): ComputeAction[] {\n const method = promotion.applicationMethod\n const min = method.buyRulesMinQuantity ?? 1\n const per = method.applyToQuantity ?? 1\n const buyQty = itemsMatching(method.buyRules, cart, context).reduce((sum, item) => sum + item.quantity, 0)\n const times = Math.floor(buyQty / Math.max(min, 1))\n if (times <= 0 || per <= 0) return []\n\n let grantUnits = times * per\n if (method.maxQuantity != null) grantUnits = Math.min(grantUnits, method.maxQuantity)\n if (grantUnits <= 0) return []\n\n // Cheapest eligible units first — the shopper pays for the dearer ones.\n const targets: ItemLike[] = itemsMatching(method.targetRules, cart, context)\n .map((item) => ({ item, id: lineId(item) }))\n .sort((a, b) => a.item.unitPrice - b.item.unitPrice || a.id.localeCompare(b.id))\n\n if (targets.length === 0) {\n // Nothing to discount in the cart. A target pinned to exactly one product\n // id is a grant of something addable — the free-item case.\n const pins = (method.targetRules ?? [])\n .filter((rule) => rule.attribute === 'product.id' && (rule.operator === 'eq' || rule.operator === 'in'))\n .flatMap((rule) => rule.values)\n if (pins.length === 1 && typeof pins[0] === 'string') {\n return [{\n action: 'addFreeItem',\n promotionId: promotion.id,\n code: promotion.code ?? null,\n productId: pins[0],\n quantity: grantUnits,\n }]\n }\n return []\n }\n\n const actions: ComputeAction[] = []\n let remaining = grantUnits\n for (const target of targets) {\n if (remaining <= 0) break\n const units = Math.min(target.item.quantity, remaining)\n const amount = roundCents(unitDiscount(method, target.item.unitPrice) * units)\n remaining -= units\n if (amount <= 0) continue\n actions.push({\n action: 'addItemDiscount',\n promotionId: promotion.id,\n code: promotion.code ?? null,\n itemId: target.id,\n amount,\n })\n }\n return actions\n}\n\nfunction applyStandard(promotion: Promotion, cart: RuleCartSnapshot, context: RuleContext): ComputeAction[] {\n const method = promotion.applicationMethod\n const code = promotion.code ?? null\n\n if (method.targetType === 'shipping') {\n const shipping = cart.shippingTotal ?? 0\n if (shipping <= 0) return []\n const amount =\n method.type === 'percentage'\n ? roundCents((shipping * clampPercent(method.value)) / 100)\n : roundCents(Math.min(method.value, shipping))\n if (amount <= 0) return []\n return [{ action: 'addShippingDiscount', promotionId: promotion.id, code, amount }]\n }\n\n const eligible: ItemLike[] =\n method.targetType === 'order'\n ? cart.items.map((item) => ({ item, id: lineId(item) }))\n : itemsMatching(method.targetRules, cart, context).map((item) => ({ item, id: lineId(item) }))\n if (eligible.length === 0) return []\n\n const lineTotals = eligible.map(({ item }) => roundCents(item.unitPrice * item.quantity))\n const eligibleTotal = roundCents(lineTotals.reduce((sum, value) => sum + value, 0))\n const emit = (amounts: number[]): ComputeAction[] =>\n amounts.flatMap((amount, index) =>\n amount > 0\n ? [{ action: 'addItemDiscount' as const, promotionId: promotion.id, code, itemId: eligible[index].id, amount }]\n : [],\n )\n\n const allocation = method.targetType === 'order' ? 'across' : (method.allocation ?? 'across')\n\n if (allocation === 'each') {\n return emit(\n eligible.map(({ item }) => {\n const units = method.maxQuantity != null ? Math.min(item.quantity, method.maxQuantity) : item.quantity\n return roundCents(unitDiscount(method, item.unitPrice) * units)\n }),\n )\n }\n\n if (allocation === 'once') {\n // One unit of the cheapest eligible line, once.\n let cheapest = 0\n for (let i = 1; i < eligible.length; i++) {\n if (eligible[i].item.unitPrice < eligible[cheapest].item.unitPrice) cheapest = i\n }\n const amounts = eligible.map(() => 0)\n amounts[cheapest] = unitDiscount(method, eligible[cheapest].item.unitPrice)\n return emit(amounts)\n }\n\n // across (and order): one amount over the eligible subtotal, split\n // proportionally so the parts sum exactly.\n const total =\n method.type === 'percentage'\n ? roundCents((eligibleTotal * clampPercent(method.value)) / 100)\n : roundCents(Math.min(method.value, eligibleTotal))\n return emit(splitProportionally(total, lineTotals))\n}\n\n// --- Ordering -----------------------------------------------------------------\n\nfunction totalRulesCount(promotion: Promotion): number {\n return (\n (promotion.rules?.length ?? 0) +\n (promotion.applicationMethod.targetRules?.length ?? 0) +\n (promotion.applicationMethod.buyRules?.length ?? 0)\n )\n}\n\n/** Deterministic evaluation order: buyget first, specific before generic, id\n * as the final tiebreak. Exported so the SQL mirror's ORDER BY has a named\n * TS counterpart to test against. */\nexport function orderPromotions(promotions: Promotion[]): Promotion[] {\n return [...promotions].sort((a, b) => {\n const buyget = Number(isBuyget(b)) - Number(isBuyget(a))\n if (buyget !== 0) return buyget\n const specificity = totalRulesCount(b) - totalRulesCount(a)\n if (specificity !== 0) return specificity\n return a.id.localeCompare(b.id)\n })\n}\n\n// --- The engine ---------------------------------------------------------------\n\n/**\n * Evaluate promotions against a cart snapshot → the ordered compute-actions\n * the cart applies. Pure and deterministic (inject `now` for date gates).\n */\nexport function computePromotionActions(\n cart: RuleCartSnapshot,\n promotions: Promotion[],\n options: EvaluateOptions = {},\n): ComputeAction[] {\n const context = options.context ?? {}\n const actions: ComputeAction[] = []\n for (const promotion of orderPromotions(promotions)) {\n if (promotionGateReason(promotion, cart, options) !== null) continue\n actions.push(\n ...(isBuyget(promotion)\n ? applyBuyget(promotion, cart, context)\n : applyStandard(promotion, cart, context)),\n )\n }\n return actions\n}\n\n/** Total item+shipping discount an action list carries — the preview number a\n * cart shows. Free items carry no amount (they enter the cart at price 0). */\nexport function actionsDiscountTotal(actions: ComputeAction[]): number {\n return roundCents(\n actions.reduce((sum, action) => sum + ('amount' in action ? action.amount : 0), 0),\n )\n}\n","import { promotionGateReason } from './evaluator'\nimport type { EvaluateOptions } from './evaluator'\nimport type { Discount } from '../types'\nimport type { ApplicationMethod, Promotion, PromotionRule, RuleCartSnapshot } from './rule-types'\n\n// ---------------------------------------------------------------------------\n// The legacy-coupon adapter — how the EXISTING discount surface keeps working\n// while its internals retire onto the rule engine (M6 deliverable: \"a percent\n// code = promotion with one eligibility rule on code + percentage application\n// method\").\n//\n// Nothing here invents semantics: every plg_shop_discounts row (and every\n// StorefrontDiscountConfig `{code, percent}` entry) is EXPRESSIBLE in the rule\n// model, so the adapter is a pure translation:\n//\n// code → eligibility rule {code eq CODE} (method 'code')\n// minSubtotal → eligibility rule {cart.subtotal gte N}\n// percentage → applicationMethod {type percentage, value}\n// fixed_amount → applicationMethod {type fixed, value}\n// free_shipping → applicationMethod {type percentage, value 100, target shipping}\n// appliesTo products/categories → target rules {product.id/category_id in [...]}\n//\n// `buy_x_get_y` is the one legacy type that CANNOT ride: the legacy row has no\n// fields for X or Y (which is itself the evidence the old model was too\n// small). The adapter returns null for it; a store that wants buyget writes a\n// real promotion, where buy-3-pay-2 is six integers of data.\n//\n// `oncePerCustomer` does not translate either — it is a usage constraint on\n// (promotion, customer), not a cart predicate, and stays enforced where it\n// always was: server-side in shop_place_order.\n// ---------------------------------------------------------------------------\n\n/** The storefront config shape (`config.discounts` entries). */\nexport interface StorefrontPercentCode {\n code: string\n percent: number\n title?: string\n}\n\n/** `{code, percent}` — the simplest promotion there is. */\nexport function storefrontDiscountToPromotion(discount: StorefrontPercentCode): Promotion {\n const code = discount.code.trim().toUpperCase()\n return {\n id: `config-discount:${code}`,\n code,\n type: 'standard',\n status: 'active',\n rules: [{ attribute: 'code', operator: 'eq', values: [code] }],\n applicationMethod: { type: 'percentage', value: discount.percent, targetType: 'order' },\n }\n}\n\n/**\n * A provider Discount row as a Promotion, or null for the untranslatable\n * legacy `buy_x_get_y` (see header). Pure; tested against the existing\n * coupon fixtures in adapter.test.ts.\n */\nexport function discountToPromotion(discount: Discount): Promotion | null {\n if (discount.type === 'buy_x_get_y') return null\n\n const rules: PromotionRule[] = []\n const code = discount.code ? discount.code.trim().toUpperCase() : null\n if (discount.method !== 'automatic' && code) {\n rules.push({ attribute: 'code', operator: 'eq', values: [code] })\n }\n if (discount.minSubtotal != null) {\n rules.push({ attribute: 'cart.subtotal', operator: 'gte', values: [discount.minSubtotal] })\n }\n\n let targetRules: PromotionRule[] | undefined\n if (discount.appliesTo === 'products' && discount.productIds.length > 0) {\n targetRules = [{ attribute: 'product.id', operator: 'in', values: [...discount.productIds] }]\n } else if (discount.appliesTo === 'categories' && discount.categoryIds.length > 0) {\n targetRules = [{ attribute: 'product.category_id', operator: 'in', values: [...discount.categoryIds] }]\n }\n\n let applicationMethod: ApplicationMethod\n if (discount.type === 'free_shipping') {\n applicationMethod = { type: 'percentage', value: 100, targetType: 'shipping' }\n } else {\n applicationMethod = {\n type: discount.type === 'percentage' ? 'percentage' : 'fixed',\n value: discount.value,\n // A scoped legacy coupon discounts its eligible lines; an unscoped one\n // is order-wide. Same split 0027 makes in shop_place_order.\n targetType: targetRules ? 'items' : 'order',\n ...(targetRules ? { allocation: 'across' as const, targetRules } : {}),\n }\n }\n\n return {\n id: `discount:${discount.id}`,\n code,\n isAutomatic: discount.method === 'automatic',\n type: 'standard',\n status: discount.status === 'active' ? 'active' : 'inactive',\n rules,\n applicationMethod,\n startsAt: discount.startsAt || null,\n endsAt: discount.endsAt || null,\n usageLimit: discount.usageLimit,\n timesUsed: discount.timesUsed,\n }\n}\n\n// --- The percent-preview surface ----------------------------------------------\n\nexport interface CouponPreview {\n valid: boolean\n /** Percentage points, when the promotion is an order-wide percentage — the\n * only shape the client-side percent cart model can preview. */\n percent: number\n /** The promotion zeroes freight instead of discounting the subtotal (a\n * legacy `free_shipping` coupon, or any 100%-of-shipping method). */\n freeShipping?: boolean\n /** Machine-readable reason when invalid — the useDiscountValidator message\n * vocabulary: not_found | not_started | expired | usage_limit | inactive |\n * rules_not_matched | unsupported. */\n reason?: string\n}\n\n/**\n * The client-side coupon preview, engine-backed: find the promotion carrying\n * the code, gate it through the SAME eligibility path the evaluator runs, and\n * report the percent when (and only when) it is an order-wide percentage —\n * anything richer is previewed as compute-actions and always revalidated\n * server-side at place_order.\n */\nexport function previewCouponPercent(\n promotions: Promotion[],\n code: string,\n cart: RuleCartSnapshot = { items: [] },\n options: EvaluateOptions = {},\n): CouponPreview {\n const normalized = code.trim().toUpperCase()\n if (!normalized) return { valid: false, percent: 0, reason: 'not_found' }\n const promotion = promotions.find((p) => (p.code ?? '').trim().toUpperCase() === normalized)\n if (!promotion) return { valid: false, percent: 0, reason: 'not_found' }\n\n const reason = promotionGateReason(promotion, { ...cart, codes: [normalized] }, options)\n if (reason === 'inactive') return { valid: false, percent: 0, reason: 'not_found' }\n if (reason !== null) return { valid: false, percent: 0, reason }\n\n const method = promotion.applicationMethod\n // Freight, not subtotal: the cart previews it as a flag, and the eligibility\n // gate above already decided the coupon applies to this cart.\n if (method.targetType === 'shipping' && method.type === 'percentage' && method.value >= 100) {\n return { valid: true, percent: 0, freeShipping: true }\n }\n if (method.type !== 'percentage' || method.targetType !== 'order' || method.buyRulesMinQuantity != null) {\n return { valid: false, percent: 0, reason: 'unsupported' }\n }\n return { valid: true, percent: method.value }\n}\n","import { Registry } from '@fayz-ai/core'\nimport type { RegistryMeta } from '@fayz-ai/core'\nimport { registerRuleAttribute, ruleAttributeRegistry } from './attributes'\nimport type { RuleAttribute, RuleAttributeFieldType } from './attributes'\nimport type { RuleCartSnapshot } from './rule-types'\n\n// ---------------------------------------------------------------------------\n// Context providers — how the vocabulary WIDENS (spine I9, the fix over\n// Medusa).\n//\n// A context provider is ~15 lines of validated code (Medusa's\n// setPromotionContext shape) after which every rule referencing the new\n// attribute is pure data. Two deliberate fixes over the original:\n//\n// 1. The result is VALIDATED against the provider's own declaration — never\n// z.record(z.any()). A provider may only return the attribute keys it\n// declared, each value type-checked against the declared field type.\n// A violation is an I2 hard error naming the declared set, because a\n// context value of the wrong shape makes every rule on it silently\n// non-matching — the exact failure mode I9 exists to end.\n//\n// 2. Registration REGISTERS THE ATTRIBUTES BACK into the vocabulary registry,\n// so the admin form, validateStore and describeStore discover them the\n// moment the provider exists. In Medusa the context can carry attributes\n// the admin whitelist has never heard of; here the two cannot diverge\n// because they are one write.\n//\n// Registry on the uniform meta envelope, same as blocks/loaders (M1).\n// ---------------------------------------------------------------------------\n\n/** What a provider contributes: one context value per declared attribute key.\n * A value may be a scalar of the declared field type or an array of them\n * (e.g. customer tags); null/undefined mean \"no value\" and are dropped. */\nexport type RuleContext = Record<string, unknown>\n\nexport interface RuleContextAttributeInput extends Omit<RuleAttribute, 'path'> {\n /** Optional — context attributes resolve by KEY from the provided context,\n * so the path is display metadata only. Defaults to `context.<key>`. */\n path?: string\n}\n\nexport interface RuleContextProvider {\n /** Attributes this provider contributes — registered into the vocabulary. */\n attributes: readonly RuleContextAttributeInput[]\n /** Compute the context values for one evaluation. Pure of side effects. */\n resolve(cart: RuleCartSnapshot): Promise<RuleContext> | RuleContext\n}\n\nexport const ruleContextRegistry = new Registry<RuleContextProvider>('ruleContext')\n\n/**\n * Register a context provider. Its attributes enter the vocabulary\n * immediately (duplicate keys are the I2 hard error registerRuleAttribute\n * throws), so discovery and evaluation can never disagree about what exists.\n */\nexport function defineRuleContextProvider(\n id: string,\n provider: RuleContextProvider,\n meta: RegistryMeta = {},\n): void {\n if (!id) throw new Error('defineRuleContextProvider: id is required')\n if (!provider.attributes.length) {\n throw new Error(`defineRuleContextProvider: \"${id}\" declares no attributes — a provider that contributes nothing cannot widen the vocabulary`)\n }\n const replacing = ruleContextRegistry.has(id)\n for (const input of provider.attributes) {\n registerRuleAttribute(\n { ...input, path: input.path ?? `context.${input.key}` },\n { meta: { source: 'app', ...meta }, replace: replacing },\n )\n }\n ruleContextRegistry.register(id, provider, {\n description: `Rule context provider — contributes: ${provider.attributes.map((a) => a.key).join(', ')}`,\n source: 'app',\n ...meta,\n })\n}\n\nfunction typeOk(value: unknown, fieldType: RuleAttributeFieldType): boolean {\n if (fieldType === 'number') return typeof value === 'number' && Number.isFinite(value)\n if (fieldType === 'boolean') return typeof value === 'boolean'\n return typeof value === 'string'\n}\n\n/**\n * Validate one provider's resolved context against its declaration (I2):\n * unknown keys name the declared set; wrong-typed values name the expected\n * type. Returns only the declared, typed, non-null entries.\n */\nexport function validateRuleContextResult(id: string, provider: RuleContextProvider, result: RuleContext): RuleContext {\n const declared = new Map(provider.attributes.map((attribute) => [attribute.key, attribute]))\n const validated: RuleContext = {}\n for (const [key, value] of Object.entries(result)) {\n const attribute = declared.get(key)\n if (!attribute) {\n throw new Error(\n `Rule context provider \"${id}\" returned undeclared attribute \"${key}\". ` +\n `Declared attributes: ${[...declared.keys()].sort().join(', ')}`,\n )\n }\n if (value === null || value === undefined) continue\n const values = Array.isArray(value) ? value : [value]\n for (const entry of values) {\n if (!typeOk(entry, attribute.fieldType)) {\n throw new Error(\n `Rule context provider \"${id}\" returned ${JSON.stringify(entry)} for \"${key}\", ` +\n `which is declared as ${attribute.fieldType}`,\n )\n }\n }\n validated[key] = value\n }\n return validated\n}\n\n/**\n * Run every registered provider against the cart and merge the validated\n * results into one context record, keyed by attribute key — the `context`\n * input of computePromotionActions. Key collisions cannot happen here: the\n * vocabulary registry already refused the second registration.\n */\nexport async function buildRuleContext(cart: RuleCartSnapshot): Promise<RuleContext> {\n const context: RuleContext = {}\n for (const entry of ruleContextRegistry.list()) {\n const result = await entry.value.resolve(cart)\n Object.assign(context, validateRuleContextResult(entry.id, entry.value, result))\n }\n return context\n}\n\n/** Test seam. Clearing providers does not un-register their vocabulary rows —\n * pair with clearRuleAttributes() in suite teardown. */\nexport function clearRuleContextProviders(): void {\n ruleContextRegistry.clear()\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { createMockShopProvider } from './chunk-U6HV3LVP.js';
1
+ import { createMockShopProvider } from './chunk-EUFSFVGS.js';
2
2
 
3
3
  // src/lib/runtime.ts
4
4
  var provider = null;
@@ -17,5 +17,5 @@ function resetShopProvider() {
17
17
  }
18
18
 
19
19
  export { getShopProvider, resetShopProvider, setShopProvider };
20
- //# sourceMappingURL=chunk-2WACO2TG.js.map
21
- //# sourceMappingURL=chunk-2WACO2TG.js.map
20
+ //# sourceMappingURL=chunk-WWQICATY.js.map
21
+ //# sourceMappingURL=chunk-WWQICATY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/runtime.ts"],"names":[],"mappings":";;;AAGA,IAAI,QAAA,GAAgC,IAAA;AACpC,IAAI,YAAA,GAAoC,IAAA;AAEjC,SAAS,eAAA,GAAgC;AAC9C,EAAA,IAAI,UAAU,OAAO,QAAA;AACrB,EAAA,IAAI,CAAC,YAAA,EAAc,YAAA,GAAe,sBAAA,EAAuB;AACzD,EAAA,OAAO,YAAA;AACT;AAEO,SAAS,gBAAgB,YAAA,EAAkC;AAChE,EAAA,QAAA,GAAW,YAAA;AACb;AAEO,SAAS,iBAAA,GAA0B;AACxC,EAAA,QAAA,GAAW,IAAA;AACX,EAAA,YAAA,GAAe,IAAA;AACjB","file":"chunk-2WACO2TG.js","sourcesContent":["import type { ShopProvider } from '../data/provider'\nimport { createMockShopProvider } from '../data/mock-provider'\n\nlet provider: ShopProvider | null = null\nlet mockFallback: ShopProvider | null = null\n\nexport function getShopProvider(): ShopProvider {\n if (provider) return provider\n if (!mockFallback) mockFallback = createMockShopProvider()\n return mockFallback\n}\n\nexport function setShopProvider(nextProvider: ShopProvider): void {\n provider = nextProvider\n}\n\nexport function resetShopProvider(): void {\n provider = null\n mockFallback = null\n}\n"]}
1
+ {"version":3,"sources":["../src/lib/runtime.ts"],"names":[],"mappings":";;;AAGA,IAAI,QAAA,GAAgC,IAAA;AACpC,IAAI,YAAA,GAAoC,IAAA;AAEjC,SAAS,eAAA,GAAgC;AAC9C,EAAA,IAAI,UAAU,OAAO,QAAA;AACrB,EAAA,IAAI,CAAC,YAAA,EAAc,YAAA,GAAe,sBAAA,EAAuB;AACzD,EAAA,OAAO,YAAA;AACT;AAEO,SAAS,gBAAgB,YAAA,EAAkC;AAChE,EAAA,QAAA,GAAW,YAAA;AACb;AAEO,SAAS,iBAAA,GAA0B;AACxC,EAAA,QAAA,GAAW,IAAA;AACX,EAAA,YAAA,GAAe,IAAA;AACjB","file":"chunk-WWQICATY.js","sourcesContent":["import type { ShopProvider } from '../data/provider'\nimport { createMockShopProvider } from '../data/mock-provider'\n\nlet provider: ShopProvider | null = null\nlet mockFallback: ShopProvider | null = null\n\nexport function getShopProvider(): ShopProvider {\n if (provider) return provider\n if (!mockFallback) mockFallback = createMockShopProvider()\n return mockFallback\n}\n\nexport function setShopProvider(nextProvider: ShopProvider): void {\n provider = nextProvider\n}\n\nexport function resetShopProvider(): void {\n provider = null\n mockFallback = null\n}\n"]}