@oeave/bakery3 0.0.0-stage → 0.2.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.
- package/LICENSE +21 -0
- package/README.md +562 -2
- package/dist/animation-B1h0Ryvj.d.ts +97 -0
- package/dist/bake/index.d.ts +369 -0
- package/dist/bake/index.js +9 -0
- package/dist/bake/index.js.map +1 -0
- package/dist/bake-DZ-CJR6f.d.ts +1364 -0
- package/dist/catalog/index.d.ts +100 -0
- package/dist/catalog/index.js +154 -0
- package/dist/catalog/index.js.map +1 -0
- package/dist/catalog.gen-BM-aNf7n.d.ts +733 -0
- package/dist/chunk-3G5QL4F4.js +145 -0
- package/dist/chunk-3G5QL4F4.js.map +1 -0
- package/dist/chunk-4E5VV4QY.js +12 -0
- package/dist/chunk-4E5VV4QY.js.map +1 -0
- package/dist/chunk-62M6XXNX.js +142 -0
- package/dist/chunk-62M6XXNX.js.map +1 -0
- package/dist/chunk-6FYI6AJM.js +1157 -0
- package/dist/chunk-6FYI6AJM.js.map +1 -0
- package/dist/chunk-6NYR73Y7.js +832 -0
- package/dist/chunk-6NYR73Y7.js.map +1 -0
- package/dist/chunk-APWUCEEB.js +118 -0
- package/dist/chunk-APWUCEEB.js.map +1 -0
- package/dist/chunk-HNMSWQU7.js +1709 -0
- package/dist/chunk-HNMSWQU7.js.map +1 -0
- package/dist/chunk-JFYUDERE.js +1412 -0
- package/dist/chunk-JFYUDERE.js.map +1 -0
- package/dist/chunk-KNUAOILG.js +551 -0
- package/dist/chunk-KNUAOILG.js.map +1 -0
- package/dist/chunk-KZLVTSBI.js +191 -0
- package/dist/chunk-KZLVTSBI.js.map +1 -0
- package/dist/chunk-LAKXC4WR.js +2028 -0
- package/dist/chunk-LAKXC4WR.js.map +1 -0
- package/dist/chunk-NXBAZGNB.js +1107 -0
- package/dist/chunk-NXBAZGNB.js.map +1 -0
- package/dist/chunk-QRCT5UGZ.js +3286 -0
- package/dist/chunk-QRCT5UGZ.js.map +1 -0
- package/dist/chunk-S4AJTLLN.js +23 -0
- package/dist/chunk-S4AJTLLN.js.map +1 -0
- package/dist/chunk-UWBP7B54.js +92 -0
- package/dist/chunk-UWBP7B54.js.map +1 -0
- package/dist/chunk-XK35ANPJ.js +346 -0
- package/dist/chunk-XK35ANPJ.js.map +1 -0
- package/dist/chunk-Z7IYVH22.js +4781 -0
- package/dist/chunk-Z7IYVH22.js.map +1 -0
- package/dist/chunk-ZEBVAIJJ.js +156 -0
- package/dist/chunk-ZEBVAIJJ.js.map +1 -0
- package/dist/devtools/index.d.ts +536 -0
- package/dist/devtools/index.js +15 -0
- package/dist/devtools/index.js.map +1 -0
- package/dist/environments/index.d.ts +93 -0
- package/dist/environments/index.js +382 -0
- package/dist/environments/index.js.map +1 -0
- package/dist/hotspots/index.d.ts +111 -0
- package/dist/hotspots/index.js +285 -0
- package/dist/hotspots/index.js.map +1 -0
- package/dist/index.d.ts +975 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/node/index.cjs +5240 -0
- package/dist/node/index.cjs.map +1 -0
- package/dist/node/index.d.cts +4927 -0
- package/dist/node/index.d.ts +597 -0
- package/dist/node/index.js +1328 -0
- package/dist/node/index.js.map +1 -0
- package/dist/prepare-BtjY4G3q.d.ts +112 -0
- package/dist/presets/index.d.ts +562 -0
- package/dist/presets/index.js +14 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/r3f/index.d.ts +159 -0
- package/dist/r3f/index.js +592 -0
- package/dist/r3f/index.js.map +1 -0
- package/dist/room-FS26KAPQ.js +9 -0
- package/dist/room-FS26KAPQ.js.map +1 -0
- package/dist/rooms.gen-DItzBR9k.d.ts +1462 -0
- package/dist/session-VCIQEO26.js +9 -0
- package/dist/session-VCIQEO26.js.map +1 -0
- package/dist/shapes/index.d.ts +222 -0
- package/dist/shapes/index.js +836 -0
- package/dist/shapes/index.js.map +1 -0
- package/dist/testRun-20OARnQr.d.ts +1139 -0
- package/dist/timeline-ChwgD7bT.d.ts +470 -0
- package/dist/tsl/index.d.ts +165 -0
- package/dist/tsl/index.js +310 -0
- package/dist/tsl/index.js.map +1 -0
- package/package.json +170 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/protocol/asset.ts","../../src/frame.ts","../../src/node/renderBatch.ts","../../src/node/webhook.ts","../../src/node/index.ts"],"names":["s"],"mappings":";;;;;;;;;AAeO,IAAM,kBAAA,GAAqB,uBAAA;AAE3B,SAAS,YAAY,KAAA,EAAiC;AAC3D,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,kBAAA,CAAmB,KAAK,KAAK,CAAA;AACnE;;;ACmBO,IAAM,UAAA,GAAa;AAAA,EACxB,KAAA,EAAO,EAAE,UAAA,EAAY,CAAA,EAAG,cAAc,CAAA,EAAE;AAAA,EACxC,eAAA,EAAiB,EAAE,UAAA,EAAY,EAAA,EAAI,cAAc,EAAA,EAAG;AAAA,EACpD,IAAA,EAAM,EAAE,UAAA,EAAY,EAAA,EAAI,cAAc,CAAA,EAAE;AAAA,EACxC,IAAA,EAAM,EAAE,UAAA,EAAY,GAAA,EAAK,cAAc,CAAA,EAAE;AAAA,EACzC,oBAAA,EAAsB,EAAE,UAAA,EAAY,GAAA,EAAK,cAAc,EAAA,EAAG;AAAA,EAC1D,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAG,cAAc,EAAA;AACtC,CAAA;AAKO,SAAS,QAAQ,IAAA,EAA6B;AACnD,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA;AAClB,IAAA,OAAO,QAAQ,UAAA,GAAa,EAAE,GAAG,UAAA,CAAW,IAAgB,GAAE,GAAI,IAAA;AACpE,EAAA,IACE,QACA,OAAO,IAAA,KAAS,YAChB,OAAQ,IAAA,CAAe,eAAe,QAAA,EACtC;AACA,IAAA,MAAM,EAAE,UAAA,EAAY,YAAA,EAAa,GAAI,IAAA;AACrC,IAAA,OAAO;AAAA,MACL,UAAA;AAAA,MACA,GAAI,YAAA,KAAiB,MAAA,GAAY,EAAE,YAAA,KAAiB;AAAC,KACvD;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,YAAA,CAAa,IAAA,EAAa,EAAA,EAAW,CAAA,EAAkB;AACrE,EAAA,MAAM,MAAA,GAAS,KAAK,YAAA,IAAgB,EAAA;AACpC,EAAA,MAAM,IAAA,GAAO,GAAG,YAAA,IAAgB,EAAA;AAChC,EAAA,OAAO;AAAA,IACL,YAAY,IAAA,CAAK,UAAA,GAAA,CAAc,EAAA,CAAG,UAAA,GAAa,KAAK,UAAA,IAAc,CAAA;AAAA,IAClE,YAAA,EAAc,MAAA,GAAA,CAAU,IAAA,GAAO,MAAA,IAAU;AAAA,GAC3C;AACF;AAGO,SAAS,YAAY,KAAA,EAAoB;AAC9C,EAAA,MAAM,OAAA,GAAW,KAAA,CAAM,UAAA,GAAa,IAAA,CAAK,EAAA,GAAM,GAAA;AAC/C,EAAA,MAAM,SAAA,GAAA,CAAc,KAAA,CAAM,YAAA,IAAgB,EAAA,IAAM,KAAK,EAAA,GAAM,GAAA;AAC3D,EAAA,OAAO;AAAA,IACL,KAAK,GAAA,CAAI,OAAO,CAAA,GAAI,IAAA,CAAK,IAAI,SAAS,CAAA;AAAA,IACtC,IAAA,CAAK,IAAI,SAAS,CAAA;AAAA,IAClB,KAAK,GAAA,CAAI,OAAO,CAAA,GAAI,IAAA,CAAK,IAAI,SAAS;AAAA,GACxC;AACF;AAGO,SAAS,cAAA,CACd,MAAA,EACA,GAAA,EACA,MAAA,EACA,MAAA,EACQ;AACR,EAAA,MAAM,QAAA,GAAY,GAAA,GAAM,IAAA,CAAK,EAAA,GAAM,GAAA;AACnC,EAAA,MAAM,UAAA,GAAa,IAAI,IAAA,CAAK,IAAA,CAAK,KAAK,GAAA,CAAI,QAAA,GAAW,CAAC,CAAA,GAAI,MAAM,CAAA;AAChE,EAAA,OAAQ,MAAA,IAAU,CAAA,GAAI,MAAA,CAAA,GAAW,IAAA,CAAK,GAAA,CAAI,KAAK,GAAA,CAAI,QAAA,EAAU,UAAU,CAAA,GAAI,CAAC,CAAA;AAC9E;AAEO,SAAS,SAAS,MAAA,EAAwB;AAC/C,EAAA,OACE,IAAA,CAAK,KAAA;AAAA,IACH,OAAO,GAAA,CAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,IAC5B,OAAO,GAAA,CAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,IAC5B,OAAO,GAAA,CAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC;AAAA,MAC1B,CAAA,IAAK,GAAA;AAEb;AAEO,SAAS,SAAS,MAAA,EAAsB;AAC7C,EAAA,OAAO;AAAA,IAAA,CACJ,OAAO,GAAA,CAAI,CAAC,IAAI,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,IAAK,CAAA;AAAA,IAAA,CACjC,OAAO,GAAA,CAAI,CAAC,IAAI,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,IAAK,CAAA;AAAA,IAAA,CACjC,OAAO,GAAA,CAAI,CAAC,IAAI,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,IAAK;AAAA,GACpC;AACF;AAOO,SAAS,YAAA,CACd,MAAA,EACA,IAAA,EACA,MAAA,EACY;AACZ,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,IAAO,EAAA;AACxB,EAAA,IAAI,EAAE,GAAA,GAAM,CAAA,IAAK,GAAA,GAAM,GAAA,CAAA;AACrB,IAAA,MAAM,OAAA,CAAQ,IAAA,CAAK,EAAA,EAAI,CAAA,IAAA,EAAO,GAAG,CAAA,4BAAA,CAA8B,CAAA;AACjE,EAAA,MAAM,MAAA,GAAS,SAAS,MAAM,CAAA;AAC9B,EAAA,MAAM,MAAA,GAAS,SAAS,MAAM,CAAA;AAC9B,EAAA,MAAM,WAAW,cAAA,CAAe,MAAA,EAAQ,KAAK,MAAA,EAAQ,IAAA,CAAK,UAAU,IAAI,CAAA;AACxE,EAAA,OAAO,QAAA;AAAA,IACL,MAAA;AAAA,IACA,MAAA;AAAA,IACA,YAAY,IAAI,CAAA;AAAA,IAChB,QAAA;AAAA,IACA,GAAA;AAAA,IACA,MAAA;AAAA,IACA,IAAA,CAAK;AAAA,GACP;AACF;AAGO,SAAS,SACd,MAAA,EACA,MAAA,EACA,WACA,QAAA,EACA,GAAA,EACA,QACA,IAAA,EACY;AACZ,EAAA,MAAM,QAAA,GAAiB;AAAA,IACrB,MAAA,CAAO,CAAC,CAAA,GAAI,SAAA,CAAU,CAAC,CAAA,GAAI,QAAA;AAAA,IAC3B,MAAA,CAAO,CAAC,CAAA,GAAI,SAAA,CAAU,CAAC,CAAA,GAAI,QAAA;AAAA,IAC3B,MAAA,CAAO,CAAC,CAAA,GAAI,SAAA,CAAU,CAAC,CAAA,GAAI;AAAA,GAC7B;AACA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,aAAA;AAAA,IACN,GAAA;AAAA,IACA,MAAA;AAAA,IACA,MAAM,IAAA,CAAK,GAAA,CAAI,IAAA,EAAA,CAAQ,QAAA,GAAW,UAAU,EAAE,CAAA;AAAA,IAC9C,GAAA,EAAA,CAAM,WAAW,MAAA,IAAU,EAAA;AAAA,IAC3B,QAAA;AAAA,IACA,UAAA,EAAY,MAAA,CAAO,QAAA,EAAU,MAAM,CAAA;AAAA,IACnC;AAAA,GACF;AACF;AAyBO,SAAS,MAAA,CAAO,UAAgB,MAAA,EAAoB;AACzD,EAAA,IAAI,IAAI,SAAA,CAAU;AAAA,IAChB,QAAA,CAAS,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA;AAAA,IACtB,QAAA,CAAS,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA;AAAA,IACtB,QAAA,CAAS,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC;AAAA,GACvB,CAAA;AACD,EAAA,IAAI,CAAC,CAAA,EAAG,CAAA,GAAI,CAAC,CAAA,EAAG,GAAG,CAAC,CAAA;AAEpB,EAAA,MAAM,EAAA,GACJ,KAAK,GAAA,CAAI,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,IAAA,IAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,IAAA,GAAO,CAAC,CAAA,EAAG,CAAA,EAAG,EAAE,CAAA,GAAI,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA;AACxE,EAAA,MAAM,CAAA,GAAI,SAAA,CAAU,KAAA,CAAM,EAAA,EAAI,CAAC,CAAC,CAAA,IAAK,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA;AAC7C,EAAA,MAAM,CAAA,GAAI,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AACpB,EAAA,OAAO,YAAA,CAAa,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA;AAC7B;AAEA,SAAS,YAAA,CAAa,CAAA,EAAS,CAAA,EAAS,CAAA,EAAe;AACrD,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,CAAC,CAAA,EACb,GAAA,GAAM,EAAE,CAAC,CAAA,EACT,GAAA,GAAM,CAAA,CAAE,CAAC,CAAA;AACX,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,CAAC,CAAA,EACb,GAAA,GAAM,EAAE,CAAC,CAAA,EACT,GAAA,GAAM,CAAA,CAAE,CAAC,CAAA;AACX,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,CAAC,CAAA,EACb,GAAA,GAAM,EAAE,CAAC,CAAA,EACT,GAAA,GAAM,CAAA,CAAE,CAAC,CAAA;AACX,EAAA,MAAM,KAAA,GAAQ,MAAM,GAAA,GAAM,GAAA;AAC1B,EAAA,IAAI,QAAQ,CAAA,EAAG;AACb,IAAA,MAAMA,EAAAA,GAAI,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAC,CAAA;AACnC,IAAA,OAAO,CAAA,CAAE,GAAA,GAAM,GAAA,IAAOA,EAAAA,EAAAA,CAAI,GAAA,GAAM,GAAA,IAAOA,EAAAA,EAAAA,CAAI,GAAA,GAAM,GAAA,IAAOA,EAAAA,EAAG,IAAA,GAAOA,EAAC,CAAA;AAAA,EACrE;AACA,EAAA,IAAI,GAAA,GAAM,GAAA,IAAO,GAAA,GAAM,GAAA,EAAK;AAC1B,IAAA,MAAMA,KAAI,CAAA,GAAI,IAAA,CAAK,KAAK,CAAA,GAAI,GAAA,GAAM,MAAM,GAAG,CAAA;AAC3C,IAAA,OAAO,CAAC,IAAA,GAAOA,EAAAA,EAAAA,CAAI,GAAA,GAAM,GAAA,IAAOA,EAAAA,EAAAA,CAAI,GAAA,GAAM,GAAA,IAAOA,EAAAA,EAAAA,CAAI,GAAA,GAAM,GAAA,IAAOA,EAAC,CAAA;AAAA,EACrE;AACA,EAAA,IAAI,MAAM,GAAA,EAAK;AACb,IAAA,MAAMA,KAAI,CAAA,GAAI,IAAA,CAAK,KAAK,CAAA,GAAI,GAAA,GAAM,MAAM,GAAG,CAAA;AAC3C,IAAA,OAAO,CAAA,CAAE,GAAA,GAAM,GAAA,IAAOA,EAAAA,EAAG,IAAA,GAAOA,EAAAA,EAAAA,CAAI,GAAA,GAAM,GAAA,IAAOA,EAAAA,EAAAA,CAAI,GAAA,GAAM,GAAA,IAAOA,EAAC,CAAA;AAAA,EACrE;AACA,EAAA,MAAM,IAAI,CAAA,GAAI,IAAA,CAAK,KAAK,CAAA,GAAI,GAAA,GAAM,MAAM,GAAG,CAAA;AAC3C,EAAA,OAAO,CAAA,CAAE,GAAA,GAAM,GAAA,IAAO,CAAA,EAAA,CAAI,GAAA,GAAM,GAAA,IAAO,CAAA,EAAG,IAAA,GAAO,CAAA,EAAA,CAAI,GAAA,GAAM,GAAA,IAAO,CAAC,CAAA;AACrE;AAEA,SAAS,KAAA,CAAM,GAAS,CAAA,EAAe;AACrC,EAAA,OAAO;AAAA,IACL,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,IAAI,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA;AAAA,IACxB,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,IAAI,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA;AAAA,IACxB,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,IAAI,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC;AAAA,GAC1B;AACF;AAEA,SAAS,UAAU,CAAA,EAAsB;AACvC,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,CAAC,CAAA,EAAG,CAAA,CAAE,CAAC,CAAA,EAAG,CAAA,CAAE,CAAC,CAAC,CAAA;AAC1C,EAAA,OAAO,MAAA,GAAS,KAAA,GAAQ,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,MAAA,EAAQ,CAAA,CAAE,CAAC,IAAI,MAAA,EAAQ,CAAA,CAAE,CAAC,CAAA,GAAI,MAAM,CAAA,GAAI,IAAA;AAC1E;AAEA,SAAS,OAAA,CAAQ,IAAY,IAAA,EAA4B;AACvD,EAAA,OAAO,IAAI,YAAA,CAAa;AAAA,IACtB,IAAA,EAAM,gBAAA;AAAA,IACN,OAAA,EAAS,CAAA,QAAA,EAAW,EAAE,CAAA,GAAA,EAAM,IAAI,CAAA,CAAA,CAAA;AAAA,IAChC,IAAA,EAAM;AAAA,GACP,CAAA;AACH;;;AClKA,IAAM,IAAA,GAAO,kCAAA;AACb,IAAM,cAAA,GAAiB,iCAAA;AACvB,IAAM,UAAA,GAAa,EAAA;AAKnB,IAAM,aAAA,GAAgB,CAAA;AACtB,IAAM,aAAA,GAAgB,GAAA;AAEtB,IAAM,WAAA,GAAc,EAAA;AACpB,IAAM,OAAA,GAAU,EAAA;AA0OhB,eAAsB,WAAA,CACpB,IAAA,EACA,KAAA,EACA,OAAA,EACA,EAAE,SAAS,KAAA,EAAO,KAAA,EAAM,GAAwB,EAAC,EAClB;AAC/B,EAAA,aAAA,CAAc,OAAA,CAAQ,KAAA,IAAS,EAAC,EAAG,SAAS,CAAA;AAC5C,EAAA,MAAM,YAAA,GAAe,IAAI,gBAAA,CAAiB,IAAI,CAAA;AAE9C,EAAA,MAAM,KAAA,GAA8B;AAAA,IAClC,GAAG,aAAA,EAAc;AAAA,IACjB,OAAA,EAAS,CAAA;AAAA,IACT,OAAO,EAAC;AAAA,IACR,SAAA,EAAW,CAAA;AAAA,IACX,OAAA,EAAS;AAAA,GACX;AACA,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,IAAI,SAAA,GAAY,CAAA;AAEhB,EAAA,MAAM,GAAA,GAAM,OAAO,OAAA,KAAyC;AAC1D,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AACF,MAAA,IAAI,OAAA,CAAQ,KAAA;AACV,QAAA,aAAA,CAAc,OAAA,CAAQ,KAAA,EAAO,CAAA,SAAA,EAAY,OAAA,CAAQ,EAAE,CAAA,CAAA,CAAG,CAAA;AACxD,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,WAAA,CAAY;AAAA,QACtC,KAAK,OAAA,CAAQ,GAAA;AAAA,QACb,IAAA,EAAM;AAAA,OACP,CAAA;AACD,MAAA,KAAA,GAAQ,MAAM,OAAA,CAAQ,OAAA,EAAS,QAAA,EAAU,OAAA,EAAS,cAAc,KAAK,CAAA;AAAA,IACvE,SAAS,KAAA,EAAO;AAMd,MAAA,IACE,EAAE,KAAA,YAAiB,YAAA,CAAA,IAClB,MAAM,IAAA,KAAS,cAAA,IAAkB,MAAM,IAAA,KAAS,eAAA;AAEjD,QAAA,MAAM,KAAA;AACR,MAAA,SAAA,EAAA;AACA,MAAA,KAAA,CAAM,OAAA,EAAA;AACN,MAAA,IAAI,KAAA,CAAM,MAAM,MAAA,GAAS,UAAA;AACvB,QAAA,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,EAAE,EAAA,EAAI,OAAA,CAAQ,IAAI,GAAA,EAAK,OAAA,CAAQ,GAAA,EAAK,KAAA,EAAO,CAAA;AAC9D,MAAA,IACE,SAAA,IAAa,aAAA,IACb,KAAA,CAAM,OAAA,GAAU,SAAA,GAAY,aAAA;AAE5B,QAAA,MAAM,aAAA,CAAc,OAAO,SAAS,CAAA;AACtC,MAAA,MAAA,CAAO,QAAQ,EAAE,CAAA;AACjB,MAAA;AAAA,IACF;AACA,IAAA,SAAA,EAAA;AAEA,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,QAAA,GAAW,MAAM,KAAA,CAAM,KAAA,CAAM,KAAK,CAAA;AAAA,IACpC,CAAA,MAAO;AACL,MAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,EAAO,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA;AACxC,MAAA,QAAA,GAAW,MAAM,MAAM,KAAA,EAAM;AAAA,IAC/B;AACA,IAAA,KAAA,CAAM,QAAA,EAAA;AACN,IAAA,KAAA,CAAM,UAAU,KAAA,CAAM,MAAA;AACtB,IAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,IAAI,QAAQ,KAAA,EAAO;AACjB,QAAA,KAAA,CAAM,OAAA,EAAA;AACN,QAAA,IAAI,KAAA,CAAM,SAAS,MAAA,GAAS,UAAA;AAC1B,UAAA,KAAA,CAAM,QAAA,CAAS,KAAK,EAAE,GAAA,EAAK,QAAQ,GAAA,EAAK,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,CAAA;AAAA,MAClE,CAAA,MAAA,IAAW,OAAA,CAAQ,OAAA,EAAS,KAAA,CAAM,OAAA,EAAA;AAAA,WAC7B;AACH,QAAA,KAAA,CAAM,aAAa,OAAA,CAAQ,aAAA;AAC3B,QAAA,KAAA,CAAM,WAAW,OAAA,CAAQ,WAAA;AAAA,MAC3B;AAAA,IACF;AACA,IAAA,MAAA,CAAO,QAAQ,EAAE,CAAA;AAAA,EACnB,CAAA;AAEA,EAAA,MAAM,MAAA,GAAS,CAAC,OAAA,KACd,OAAA,CAAQ,UAAA,GAAa;AAAA,IACnB,GAAG,MAAM,QAAA,EAAS;AAAA,IAClB,OAAA;AAAA,IACA,UAAU,KAAA,CAAM,QAAA;AAAA,IAChB,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,SAAS,KAAA,CAAM;AAAA,GAChB,CAAA;AAKH,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,WAAA,IAAe,CAAC,CAAC,CAAC,CAAA;AAC5E,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAmB;AACtC,EAAA,IAAI,OAAA;AACJ,EAAA,WAAA,MAAiB,OAAA,IAAW,QAAQ,QAAA,EAAU;AAC5C,IAAA,IAAI,OAAA,EAAS;AACb,IAAA,IAAI,OAAA,CAAQ,QAAQ,OAAA,EAAS;AAC3B,MAAA,OAAA,GAAU,OAAA,CAAQ,MAAA,CAAO,MAAA,IAAU,UAAA,EAAW;AAC9C,MAAA;AAAA,IACF;AACA,IAAA,eAAA,CAAgB,SAAS,IAAI,CAAA;AAC7B,IAAA,MAAM,OAAO,GAAA,CAAI,OAAO,CAAA,CACrB,KAAA,CAAM,CAAC,KAAA,KAAU;AAChB,MAAA,OAAA,KAAY,KAAA;AAAA,IACd,CAAC,CAAA,CACA,OAAA,CAAQ,MAAM,MAAA,CAAO,MAAA,CAAO,IAAI,CAAC,CAAA;AACpC,IAAA,MAAA,CAAO,IAAI,IAAI,CAAA;AACf,IAAA,IAAI,OAAO,IAAA,IAAQ,KAAA,EAAO,MAAM,OAAA,CAAQ,KAAK,MAAM,CAAA;AAAA,EACrD;AACA,EAAA,MAAM,OAAA,CAAQ,IAAI,MAAM,CAAA;AACxB,EAAA,IAAI,SAAS,MAAM,OAAA;AAEnB,EAAA,KAAA,CAAM,YAAY,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,SAAA,GAAY,GAAG,CAAA,GAAI,GAAA;AACtD,EAAA,KAAA,CAAM,UAAU,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,OAAA,GAAU,GAAG,CAAA,GAAI,GAAA;AAClD,EAAA,OAAO,KAAA;AACT;AAiBA,eAAe,OAAA,CACb,OAAA,EACA,QAAA,EACA,GAAA,EACA,cACA,KAAA,EAC6B;AAC7B,EAAA,MAAM,QAAQ,QAAA,CAAS,KAAA;AACvB,EAAA,IAAI,CAAC,KAAA;AACH,IAAA,MAAM,UAAA,CAAW,SAAS,+CAA+C,CAAA;AAC3E,EAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,IAAA,CAAK,CAAC,KAAA,KAAU,KAAA,CAAM,aAAa,OAAO,CAAA;AACxE,EAAA,IAAI,QAAA,EAAU,MAAM,UAAA,CAAW,OAAA,EAAS,SAAS,OAAO,CAAA;AACxD,EAAA,IAAI,CAAC,KAAA,CAAM,MAAA;AACT,IAAA,MAAM,UAAA;AAAA,MACJ,OAAA;AAAA,MACA;AAAA,KACF;AACF,EAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AAErB,EAAA,MAAM,WAAA,GAAc,WAAW,GAAG,CAAA;AAClC,EAAA,MAAM,eAAA,GAAkB,WAAW,OAAO,CAAA;AAC1C,EAAA,MAAM,SAAS,OAAA,CAAQ,KAAA,IAAS,GAAA,CAAI,KAAA,IAAS,EAAC,EAAG,GAAA;AAAA,IAAI,CAAC,IAAA,KACpD,WAAA,CAAY,IAAA,EAAM,WAAA,EAAa,iBAAiB,KAAK;AAAA,GACvD;AACA,EAAA,IAAI,CAAC,MAAM,MAAA,EAAQ;AACjB,IAAA,MAAM,SAAS,OAAA,CAAQ,MAAA,EAAQ,WAAA,EAAa,eAAA,EAAiB,KAAK,CAAA,IAAK,IAAA;AACvE,IAAA,KAAA,CAAM,IAAA;AAAA,MACJ,WAAA;AAAA,QACE,SAAS,MAAA,GAAS,eAAA;AAAA,QAClB,WAAA;AAAA,QACA,eAAA;AAAA,QACA;AAAA;AACF,KACF;AAAA,EACF;AAEA,EAAA,MAAM,SAAS,EAAE,IAAA,EAAM,GAAG,OAAA,EAAS,CAAA,EAAG,OAAO,CAAA,EAAE;AAC/C,EAAA,KAAA,MAAW,KAAA,IAAS,KAAA,CAAM,MAAA,EAAQ,MAAA,CAAO,MAAM,QAAQ,CAAA,EAAA;AACvD,EAAA,MAAM,OAAA,GAAU,KAAA,EAAO,OAAA,IAAW,GAAA,CAAI,OAAA;AAEtC,EAAA,MAAM,QAA4B,EAAC;AACnC,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,OAAA,GAAU,KAAK,OAAA,IAAW,QAAA;AAChC,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,OAAO,CAAA,CAAE,eAAA;AAC9B,IAAA,MAAM,KAAA,GAAQ,KAAK,IAAA,KAAS,OAAA;AAC5B,IAAA,MAAM,MAAA,GAAqB;AAAA,MACzB,KAAA,EAAO,KAAK,KAAA,IAAS,IAAA;AAAA,MACrB,MAAA,EAAQ,KAAK,MAAA,IAAU,IAAA;AAAA,MACvB,MAAA,EAAQ,IAAA,CAAK,MAAA,KAAW,KAAA,GAAQ,KAAA,GAAQ,KAAA,CAAA;AAAA,MACxC,GAAI,KAAK,YAAA,KAAiB,MAAA,GACtB,EAAE,OAAA,EAAS,IAAA,CAAK,YAAA,EAAa,GAC7B;AAAC,KACP;AACA,IAAA,IAAI,KAAA,KAAU,YAAA,CAAa,MAAA,CAAO,MAAM,CAAA,EAAG;AACzC,MAAA,MAAM,IAAI,YAAA,CAAa;AAAA,QACrB,IAAA,EAAM,gBAAA;AAAA,QACN,OAAA,EAAS,CAAA,MAAA,EAAS,IAAA,CAAK,EAAE,CAAA,KAAA,EAAQ,OAAA,CAAQ,EAAE,CAAA,IAAA,EAAO,KAAA,GAAQ,oBAAA,GAAuB,qBAAqB,CAAA,SAAA,EAAY,OAAO,MAAM,CAAA,EAAA,CAAA;AAAA,QAC/H,GAAA,EAAK,0GAAA;AAAA,QACL,MAAM,CAAA,EAAG,OAAA,CAAQ,EAAE,CAAA,CAAA,EAAI,KAAK,EAAE,CAAA,CAAA;AAAA,QAC9B,IAAA,EAAM,GAAG,IAAI,CAAA,MAAA;AAAA,OACd,CAAA;AAAA,IACH;AACA,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,KAAA,GAAQ,MAAA,CAAO,MAAA;AAErC,IAAA,MAAM,OAAO,IAAA,CAAK,IAAA,GAAO,QAAQ,IAAA,CAAK,IAAA,EAAM,MAAM,CAAA,GAAI,MAAA;AAKtD,IAAA,MAAM,UAAA,GACJ,aAAA,CAAc,MAAA,CAAO,MAAM,CAAA,IAAA,CAC1B,KAAK,UAAA,IAAc,aAAA,MAAmB,aAAA,GACnC,aAAA,GACA,IAAA,CAAK,UAAA;AACX,IAAA,MAAM,WAAA,GAAc,OAChB,cAAA,EAAe,GACf,MAAM,YAAA,CAAa,GAAA,CAAI,IAAA,CAAK,WAAA,EAAa,UAAU,CAAA;AACvD,IAAA,MAAM,KAAA,GAAmB;AAAA,MACvB,gBAAA,EAAkB,MAAA;AAAA,MAClB,WAAA,EAAa,aAAA;AAAA,MACb,mBAAA,EAAqB,IAAA,GAAO,IAAA,CAAK,QAAA,GAAW,CAAA;AAAA,MAC5C,GAAG,IAAA,CAAK;AAAA,KACV;AACA,IAAA,MAAM,OAAO,EAAE,GAAA,EAAK,KAAK,GAAA,EAAK,MAAA,EAAQ,KAAK,MAAA,EAAO;AAElD,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI,SAAA;AACJ,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,MAAM,OAAO,QAAA,CAAS,IAAA,CAAK,MAAO,IAAA,EAAM,OAAA,EAAS,KAAK,EAAE,CAAA;AACxD,MAAA,MAAM,KAAK,QAAA,CAAS,IAAA,CAAK,IAAK,IAAA,EAAM,OAAA,EAAS,KAAK,EAAE,CAAA;AACpD,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,IAAO,EAAE,CAAC,CAAC,CAAA;AACrE,MAAA,MAAM,UAAU,IAAA,CAAK,GAAA,CAAI,WAAA,EAAa,IAAA,CAAK,WAAW,CAAC,CAAA;AACvD,MAAA,MAAM,UAAA,GAAa,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,OAAA,GAAU,GAAG,CAAC,CAAA;AACxD,MAAA,MAAM,YAAsB,EAAC;AAC7B,MAAA,MAAM,cAAwB,EAAC;AAC/B,MAAA,IAAI,KAAA;AACJ,MAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,GAAQ,UAAA,EAAY,KAAA,EAAA,EAAS;AAC/C,QAAA,MAAM,KAAK,YAAA,CAAa,IAAA,EAAM,EAAA,EAAI,KAAA,IAAS,aAAa,CAAA,CAAE,CAAA;AAC1D,QAAA,MAAM,IAAA,GAAO,eAAe,EAAA,EAAI,MAAA,EAAQ,QAAQ,IAAA,EAAM,IAAA,EAAM,KAAK,EAAE,CAAA;AACnE,QAAA,KAAA,KAAU,IAAA;AACV,QAAA,SAAA,CAAU,IAAA,CAAK,GAAG,IAAA,CAAK,QAAQ,CAAA;AAC/B,QAAA,WAAA,CAAY,IAAA,CAAK,GAAG,IAAA,CAAK,UAAU,CAAA;AAAA,MACrC;AACA,MAAA,MAAA,GAAS,KAAA;AACT,MAAA,SAAA,GAAY;AAAA,QACV,GAAA;AAAA,QACA,UAAA;AAAA,QACA,QAAA,EAAU;AAAA,UACR;AAAA,YACE,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,YACzB,QAAA,EAAU,UAAA;AAAA,YACV,IAAA,EAAM,CAAA;AAAA,YACN,MAAA,EAAQ;AAAA,WACV;AAAA,UACA;AAAA,YACE,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,YACzB,QAAA,EAAU,YAAA;AAAA,YACV,IAAA,EAAM,CAAA;AAAA,YACN,MAAA,EAAQ;AAAA;AACV;AACF,OACF;AAAA,IACF,CAAA,MAAA,IAAW,KAAK,MAAA,EAAQ;AACtB,MAAA,MAAA,GAAS,UAAU,IAAA,CAAK,MAAA,EAAQ,OAAO,MAAA,EAAQ,OAAA,EAAS,KAAK,EAAE,CAAA;AAAA,IACjE,CAAA,MAAO;AACL,MAAA,MAAA,GAAS,cAAA;AAAA,QACP,QAAA;AAAA,UACE,IAAA,CAAK,IAAA,KAAS,IAAA,GAAO,MAAA,GAAS,eAAA,CAAA;AAAA,UAC9B,IAAA;AAAA,UACA,OAAA;AAAA,UACA,IAAA,CAAK;AAAA,SACP;AAAA,QACA,MAAA;AAAA,QACA,MAAA;AAAA,QACA,IAAA;AAAA,QACA,IAAA;AAAA,QACA,IAAA,CAAK;AAAA,OACP;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAA0B;AAAA,MAC9B,iBAAiB,kBAAA,CAAmB;AAAA,QAClC,GAAI,IAAA,GAAO,EAAE,MAAM,IAAA,CAAK,IAAA,KAAS,EAAC;AAAA,QAClC,GAAI,SAAA,GAAY,EAAE,SAAA,KAAc;AAAC,OAClC,CAAA;AAAA,MACD,UAAA,EAAY,WAAA;AAAA,MACZ,YAAY,QAAA,CAAS,IAAA;AAAA,MACrB,MAAA;AAAA,MACA,WAAA;AAAA,MACA,KAAA;AAAA,MACA,GAAI,IAAA,GAAO,EAAE,MAAM,IAAA,CAAK,IAAA,KAAS,EAAC;AAAA,MAClC,GAAI,SAAA,GAAY,EAAE,SAAA,KAAc,EAAC;AAAA,MACjC,eAAe,EAAE,KAAA,EAAO,GAAG,MAAA,EAAQ,KAAA,CAAM,QAAQ,MAAA,EAAO;AAAA,MACxD,KAAA,EAAO;AAAA,QACL,SAAA,EAAW,KAAA,CAAM,SAAA,IAAa,IAAA,EAAM,SAAA,IAAa,CAAA,CAAA;AAAA;AAAA;AAAA;AAAA,QAIjD,GAAI,MAAM,UAAA,GACN;AAAA,UACE,SAAA,EAAW,KAAK,UAAA,CAAW,SAAA;AAAA,UAC3B,OAAA,EAAS,IAAA,CAAK,UAAA,CAAW,OAAA,GAAU;AAAA,YAErC;AAAC,OACP;AAAA,MACA,MAAA,EAAQ,EAAE,QAAA,EAAU,SAAA;AAAU,KAChC;AAEA,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,OAAA,CAAQ,EAAE,CAAA,CAAA,EAAI,IAAA,CAAK,EAAE,CAAA,EAAG,OAAA,GAAU,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA;AACnE,IAAA,IAAI,IAAI,MAAA,GAAS,GAAA;AACf,MAAA,MAAM,UAAA;AAAA,QACJ,OAAA;AAAA,QACA,CAAA,SAAA,EAAY,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA,gDAAA;AAAA,OAC9B;AACF,IAAA,KAAA,CAAM,IAAA,CAAK;AAAA,MACT,GAAA;AAAA,MACA,IAAA,EAAM;AAAA,QACJ,QAAA;AAAA,QACA,OAAA;AAAA,QACA,MAAA;AAAA,QACA,GAAI,KAAK,QAAA,GAAW,EAAE,UAAU,IAAA,CAAK,QAAA,KAAa,EAAC;AAAA,QACnD,GAAI,KAAA,GAAQ,EAAE,OAAA,EAAS,KAAA,KAAU;AAAC,OACpC;AAAA,MACA,QAAA,EAAU;AAAA,QACR,GAAG,OAAA,CAAQ,QAAA;AAAA,QACX,SAAS,OAAA,CAAQ,EAAA;AAAA,QACjB,MAAM,IAAA,CAAK,EAAA;AAAA,QACX,MAAM,IAAA,CAAK;AAAA,OACb;AAAA,MACA,GAAI,IAAI,eAAA,KAAoB,MAAA,GACxB,EAAE,OAAA,EAAS,GAAA,CAAI,eAAA,EAAgB,GAC/B;AAAC,KACN,CAAA;AAAA,EACH;AACA,EAAA,OAAO,KAAA;AACT;AAMA,IAAM,YAAA,GAAe;AAAA,EACnB,MAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,cAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA;AAEA,SAAS,WAAW,MAAA,EAAoC;AACtD,EAAA,MAAM,MAAoB,EAAC;AAC3B,EAAA,KAAA,MAAW,GAAA,IAAO,YAAA;AAChB,IAAA,IAAI,MAAA,CAAO,GAAG,CAAA,KAAM,MAAA;AAClB,MAAC,GAAA,CAAgC,GAAG,CAAA,GAAI,MAAA,CAAO,GAAG,CAAA;AACtD,EAAA,OAAO,GAAA;AACT;AAMA,SAAS,OAAA,CACP,QACG,MAAA,EACc;AACjB,EAAA,KAAA,IAAS,IAAI,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AAC3C,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,CAAC,CAAA,GAAI,GAAG,CAAA;AAC7B,IAAA,IAAI,KAAA,KAAU,QAAW,OAAO,KAAA;AAAA,EAClC;AACA,EAAA,OAAO,MAAA;AACT;AAGA,SAAS,OAAO,IAAA,EAAmC;AACjD,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,EAAU,OAAO,EAAE,MAAM,IAAA,EAAK;AAClD,EAAA,IACE,IAAA,IACA,OAAO,IAAA,KAAS,QAAA,IAChB,gBAAgB,IAAA,IAChB,EAAE,MAAA,IAAU,IAAA,CAAA,IACZ,EAAE,MAAA,IAAU,IAAA,CAAA,IACZ,EAAE,YAAY,IAAA,CAAA,EACd;AACA,IAAA,MAAM,EAAE,UAAA,EAAY,YAAA,EAAc,GAAG,MAAK,GAAI,IAAA;AAC9C,IAAA,OAAO;AAAA,MACL,GAAG,IAAA;AAAA,MACH,IAAA,EAAM;AAAA,QACJ,UAAA;AAAA,QACA,GAAI,YAAA,KAAiB,MAAA,GAAY,EAAE,YAAA,KAAiB;AAAC;AACvD,KACF;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,WAAA,CACP,IAAA,EACA,GAAA,EACA,OAAA,EACA,KAAA,EACc;AACd,EAAA,MAAM,GAAA,GAAM,OAAO,IAAI,CAAA;AACvB,EAAA,MAAM,WAAyB,EAAC;AAChC,EAAA,KAAA,MAAW,OAAO,YAAA,EAAc;AAC9B,IAAA,MAAM,KAAA,GAAQ,QAAQ,GAAA,EAAK,GAAA,EAAK,SAAS,UAAA,CAAW,GAAG,GAAG,KAAK,CAAA;AAC/D,IAAA,IAAI,KAAA,KAAU,MAAA,EAAY,QAAA,CAAqC,GAAG,CAAA,GAAI,KAAA;AAAA,EACxE;AACA,EAAA,IAAI,GAAA,CAAI,SAAS,OAAA,EAAS;AACxB,IAAA,OAAO;AAAA,MACL,GAAG,QAAA;AAAA,MACH,IAAA,EAAM,OAAA;AAAA,MACN,EAAA,EAAI,GAAA,CAAI,EAAA,IAAM,CAAA,MAAA,EAAS,QAAA,CAAS,GAAA,CAAI,IAAI,CAAC,CAAA,CAAA,EAAI,QAAA,CAAS,GAAA,CAAI,EAAE,CAAC,CAAA,CAAA;AAAA,MAC7D,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,IAAI,GAAA,CAAI,EAAA;AAAA,MACR,OAAA,EACE,KAAA,EAAO,OAAA,KAAY,MAAA,GACf,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,OAAA,EAAS,GAAA,CAAI,OAAA,IAAW,CAAC,CAAA,GACxC,GAAA,CAAI;AAAA,KACZ;AAAA,EACF;AACA,EAAA,MAAM,KAAA,GAAQ,GAAA;AACd,EAAA,OAAO;AAAA,IACL,GAAG,QAAA;AAAA,IACH,IAAA,EAAM,OAAA;AAAA,IACN,EAAA,EACE,KAAA,CAAM,EAAA,KACL,KAAA,CAAM,MAAA,GACH,KAAA,CAAM,MAAA,GACN,QAAA,CAAS,KAAA,CAAM,IAAA,KAAS,QAAA,CAAS,IAAA,GAAO,SAAS,eAAA,CAAgB,CAAA,CAAA;AAAA,IACvE,GAAI,MAAM,IAAA,KAAS,MAAA,GAAY,EAAE,IAAA,EAAM,KAAA,CAAM,IAAA,EAAK,GAAI,EAAC;AAAA,IACvD,GAAI,MAAM,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,CAAM,MAAA,EAAO,GAAI;AAAC,GAC/D;AACF;AAEA,SAAS,SAAS,IAAA,EAAoB;AACpC,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,EAAU,OAAO,IAAA;AACrC,EAAA,MAAM,KAAK,IAAA,CAAK,YAAA;AAChB,EAAA,OAAO,KAAK,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,UAAU,CAAC,CAAA,EAAG,EAAA,KAAO,MAAA,GAAY,CAAA,GAAA,EAAM,KAAK,KAAA,CAAM,EAAE,CAAC,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA,CAAG,OAAA;AAAA,IACzF,IAAA;AAAA,IACA;AAAA,GACF;AACF;AASA,SAAS,QAAA,CACP,IAAA,EACA,IAAA,EACA,OAAA,EACA,IAAA,EACO;AACP,EAAA,IAAI,SAAS,MAAA,EAAQ;AACnB,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,IAAI,YAAA,CAAa;AAAA,QACrB,IAAA,EAAM,gBAAA;AAAA,QACN,OAAA,EAAS,CAAA,MAAA,EAAS,IAAI,CAAA,KAAA,EAAQ,QAAQ,EAAE,CAAA,oCAAA,CAAA;AAAA,QACxC,GAAA,EAAK,4GAAA;AAAA,QACL,IAAA,EAAM,CAAA,EAAG,OAAA,CAAQ,EAAE,IAAI,IAAI,CAAA,CAAA;AAAA,QAC3B,IAAA,EAAM,GAAG,IAAI,CAAA,OAAA;AAAA,OACd,CAAA;AAAA,IACH;AACA,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AACA,EAAA,MAAM,KAAA,GAAQ,QAAQ,IAAI,CAAA;AAC1B,EAAA,IAAI,OAAO,OAAO,KAAA;AAClB,EAAA,MAAM,IAAI,YAAA,CAAa;AAAA,IACrB,IAAA,EAAM,gBAAA;AAAA,IACN,OAAA,EAAS,CAAA,MAAA,EAAS,IAAI,CAAA,KAAA,EAAQ,QAAQ,EAAE,CAAA,GAAA,EAAM,OAAO,IAAA,KAAS,QAAA,GAAW,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA,gBAAA,CAAA;AAAA,IACpG,GAAA,EAAK,oBAAoB,MAAA,CAAO,IAAA,CAAK,UAAU,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,2GAAA,CAAA;AAAA,IAC3D,IAAA,EAAM,CAAA,EAAG,OAAA,CAAQ,EAAE,IAAI,IAAI,CAAA,CAAA;AAAA,IAC3B,IAAA,EAAM,GAAG,IAAI,CAAA,OAAA;AAAA,GACd,CAAA;AACH;AAEA,SAAS,eACP,KAAA,EACA,MAAA,EACA,MAAA,EACA,IAAA,EACA,MACA,IAAA,EACY;AACZ,EAAA,IAAI,MAAM,OAAO,IAAA,CAAK,OAAO,KAAA,EAAO,MAAA,EAAQ,MAAM,IAAI,CAAA;AACtD,EAAA,OAAO,YAAA;AAAA,IACL,MAAA;AAAA,IACA;AAAA,MACE,EAAA,EAAI,IAAA;AAAA,MACJ,GAAG,KAAA;AAAA,MACH,GAAI,KAAK,GAAA,KAAQ,MAAA,GAAY,EAAE,GAAA,EAAK,IAAA,CAAK,GAAA,EAAI,GAAI,EAAC;AAAA,MAClD,GAAI,KAAK,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAO,GAAI;AAAC,KAC7D;AAAA,IACA;AAAA,GACF;AACF;AAGA,SAAS,SAAA,CACP,IAAA,EACA,KAAA,EACA,MAAA,EACA,SACA,IAAA,EACY;AACZ,EAAA,MAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,SAAS,IAAI,CAAA;AAC/D,EAAA,IAAI,GAAA;AACF,IAAA,OAAO;AAAA,MACL,GAAG,GAAA,CAAI,MAAA;AAAA,MACP,GAAI,IAAI,MAAA,CAAO,IAAA,KAAS,gBAAgB,EAAE,MAAA,KAAW,EAAC;AAAA,MACtD,IAAA,EAAM;AAAA,KACR;AACF,EAAA,MAAM,QAAQ,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAC,MAAA,KAAW,OAAO,IAAI,CAAA;AACvD,EAAA,MAAM,IAAI,YAAA,CAAa;AAAA,IACrB,IAAA,EAAM,cAAA;AAAA,IACN,SAAS,CAAA,MAAA,EAAS,IAAI,MAAM,OAAA,CAAQ,EAAE,iCAAiC,IAAI,CAAA,EAAA,CAAA;AAAA,IAC3E,GAAA,EAAK,KAAA,CAAM,MAAA,GACP,CAAA,iBAAA,EAAoB,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAA,GAChD,sFAAA;AAAA,IACJ,IAAA,EAAM,CAAA,EAAG,OAAA,CAAQ,EAAE,IAAI,IAAI,CAAA,CAAA;AAAA,IAC3B,IAAA,EAAM,GAAG,IAAI,CAAA,OAAA;AAAA,GACd,CAAA;AACH;AAaA,IAAM,mBAAA,GAAwC;AAAA,EAC5C,MAAA,EAAQ,iBAAA;AAAA,EACR,SAAA,EAAW;AACb,CAAA;AAKA,IAAM,aAAA,GAAgB,SAAA;AAGtB,IAAM,mBAAN,MAAuB;AAAA,EAErB,YAA6B,IAAA,EAAiB;AAAjB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAkB;AAAA,EAAlB,IAAA;AAAA,EADZ,MAAA,uBAAa,GAAA,EAA6B;AAAA,EAG3D,MAAM,GAAA,CACJ,MAAA,EACA,UAAA,EAC0B;AAC1B,IAAA,MAAM,cAAc,MAAA,IAAU,mBAAA;AAC9B,IAAA,IAAI,WAAA,CAAY,MAAA,IAAU,WAAA,CAAY,GAAA,EAAK;AACzC,MAAA,MAAM,IAAI,YAAA,CAAa;AAAA,QACrB,IAAA,EAAM,gBAAA;AAAA,QACN,OAAA,EAAS,oDAAA;AAAA,QACT,IAAA,EAAM,GAAG,IAAI,CAAA,MAAA;AAAA,OACd,CAAA;AAAA,IACH;AACA,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI,YAAY,GAAA,EAAK;AAGnB,MAAA,MAAM,MAAM,WAAA,CAAY,GAAA;AACxB,MAAA,IAAI,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA;AACjC,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,OAAA,GAAU,IAAA,CAAK,IAAA,CACZ,WAAA,CAAY,EAAE,GAAA,EAAK,IAAA,EAAM,MAAA,EAAQ,CAAA,CACjC,IAAA,CAAK,CAAC,QAAA,KAAa,SAAS,IAAI,CAAA;AACnC,QAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,GAAA,EAAK,OAAO,CAAA;AAC5B,QAAA,OAAA,CAAQ,MAAM,MAAM,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,MAC7C;AACA,MAAA,IAAA,GAAO,MAAM,OAAA;AAAA,IACf,CAAA,MAAO;AACL,MAAA,MAAM,IAAA,GAAO,YAAY,MAAA,IAAU,iBAAA;AACnC,MAAA,IAAI,EAAE,QAAQ,YAAA,CAAA,EAAe;AAC3B,QAAA,MAAM,IAAI,YAAA,CAAa;AAAA,UACrB,IAAA,EAAM,gBAAA;AAAA,UACN,OAAA,EAAS,mCAAmC,IAAI,CAAA,EAAA,CAAA;AAAA,UAChD,GAAA,EAAK,oBAAoB,MAAA,CAAO,IAAA,CAAK,YAAY,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,UAC7D,IAAA,EAAM,GAAG,IAAI,CAAA,MAAA;AAAA,SACd,CAAA;AAAA,MACH;AACA,MAAA,IAAA,GAAO,CAAA,EAAG,cAAc,CAAA,EAAA,EAAK,eAAe,SAAS,IAAI,CAAA,WAAA,CAAA;AAAA,IAC3D;AACA,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,GAAI,YAAY,SAAA,KAAc,MAAA,GAC1B,EAAE,SAAA,EAAW,WAAA,CAAY,SAAA,EAAU,GACnC,EAAC;AAAA,MACL,GAAI,YAAY,WAAA,GACZ;AAAA,QACE,QAAA,EAAU,CAAC,CAAA,EAAI,WAAA,CAAY,cAAc,IAAA,CAAK,EAAA,GAAM,KAAK,CAAC;AAAA,UAE5D,EAAC;AAAA,MACL,UAAA,EAAY,aAAa,UAAU;AAAA,KACrC;AAAA,EACF;AACF,CAAA;AAEA,SAAS,aACP,UAAA,EAC4C;AAC5C,EAAA,MAAM,SAAS,UAAA,IAAc,aAAA;AAC7B,EAAA,IAAI,MAAA,KAAW,aAAA,EAAe,OAAO,EAAE,MAAM,aAAA,EAAc;AAC3D,EAAA,IAAI,MAAA,KAAW,aAAA,EAAe,OAAO,EAAE,MAAM,aAAA,EAAc;AAC3D,EAAA,IAAI,CAAC,iBAAA,CAAkB,IAAA,CAAK,MAAM,CAAA,EAAG;AACnC,IAAA,MAAM,IAAI,YAAA,CAAa;AAAA,MACrB,IAAA,EAAM,gBAAA;AAAA,MACN,OAAA,EAAS,eAAe,MAAM,CAAA,yDAAA,CAAA;AAAA,MAC9B,IAAA,EAAM,GAAG,IAAI,CAAA,MAAA;AAAA,KACd,CAAA;AAAA,EACH;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,MAAA,EAAO;AACxC;AAGA,SAAS,cAAA,GAAkC;AACzC,EAAA,OAAO,EAAE,UAAA,EAAY,EAAE,IAAA,EAAM,eAAc,EAAE;AAC/C;AAQA,IAAM,WAAA,GAAc;AAAA,EAClB,GAAA,EAAK,IAAA;AAAA,EACL,QAAA,EAAU,GAAA;AAAA,EACV,WAAA,EAAa,GAAA;AAAA,EACb,YAAA,EAAc;AAChB,CAAA;AACA,IAAM,MAAA,GAAS,iBAAA;AAEf,IAAM,WAAA,GAAc,GAAA;AAEpB,IAAM,cAAA,GAAiB,GAAA;AAEvB,IAAM,UAAA,GAAa,IAAA;AAEnB,IAAM,YAAA,GAAe,GAAA;AAWrB,IAAM,sBAAA,GAAyB,CAAA;AAM/B,SAAS,QAAA,CAAS,MAAA,EAAgB,QAAA,EAAkB,MAAA,EAAwB;AAC1E,EAAA,MAAM,IAAA,GAAO,KAAK,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA,EAAG,MAAA,GAAS,QAAQ,CAAC,CAAA;AACrD,EAAA,MAAM,QAAA,GAAW,MAAA,IAAU,CAAA,GAAI,IAAA,GAAO,IAAA,CAAK,KAAK,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,GAAI,MAAM,CAAA;AACvE,EAAA,OAAQ,CAAA,GAAI,QAAA,GAAW,GAAA,GAAO,IAAA,CAAK,EAAA;AACrC;AAEA,SAAS,QAAA,CACP,IAAA,EACA,IAAA,EACA,MAAA,EACwD;AACxD,EAAA,MAAM,YAAY,IAAA,CAAK,GAAA;AAAA,IACrB,OAAO,GAAA,CAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,IAC5B,OAAO,GAAA,CAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC;AAAA,GAC9B;AACA,EAAA,MAAM,SAAS,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC,CAAA;AAC3C,EAAA,MAAM,IAAA,GAAO,CACX,IAAA,KACY;AACZ,IAAA,IAAI,CAAC,MAAM,OAAO,KAAA;AAClB,IAAA,IAAI,SAAA,GAAY,WAAA,CAAY,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA,EAAG,IAAA,CAAK,CAAC,CAAA,EAAG,OAAO,KAAA;AACnE,IAAA,OACE,WACC,IAAA,CAAK,CAAA,IAAK,YAAY,QAAA,GACnB,WAAA,CAAY,cACZ,WAAA,CAAY,YAAA,CAAA;AAAA,EAEpB,CAAA;AACA,EAAA,MAAM,MAAA,GAAS,KAAK,KAAA,IAAS,MAAA;AAC7B,EAAA,IAAI,WAAW,KAAA,IAAU,MAAA,KAAW,UAAU,IAAA,CAAK,IAAA,CAAK,MAAM,IAAI,CAAA;AAChE,IAAA,OAAO,EAAE,GAAA,EAAK,IAAA,CAAK,KAAA,CAAM,GAAA,EAAI;AAC/B,EAAA,IAAI,WAAW,MAAA,IAAU,IAAA,CAAK,gBAAA,CAAiB,MAAM,EAAE,IAAI,CAAA;AACzD,IAAA,OAAO,EAAE,QAAA,EAAU,EAAE,IAAA,EAAM,MAAA,EAAO,EAAG,GAAA,EAAK,gBAAA,CAAiB,MAAM,CAAA,CAAE,IAAA,CAAK,CAAA,EAAE;AAC5E,EAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,GAAA,EAAK,CAAA,EAAE;AAClC;AASA,SAAS,OAAA,CAAQ,MAAiB,MAAA,EAAgB;AAChD,EAAA,MAAM,IAAA,GAAO,YAAA,CAAa,IAAA,CAAK,MAAM,CAAA;AACrC,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,MAAM,IAAI,YAAA,CAAa;AAAA,MACrB,IAAA,EAAM,gBAAA;AAAA,MACN,OAAA,EAAS,CAAA,yBAAA,EAA4B,IAAA,CAAK,MAAM,CAAA,EAAA,CAAA;AAAA,MAChD,GAAA,EAAK,kBAAkB,MAAA,CAAO,IAAA,CAAK,YAAY,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,MAC3D,IAAA,EAAM,GAAG,IAAI,CAAA,MAAA;AAAA,KACd,CAAA;AAAA,EACH;AACA,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,QAAA;AACnC,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,IAAA,EAAM,IAAA,EAAM,MAAM,CAAA;AAC5C,EAAA,MAAM,KAAA,GAAc,CAAC,IAAA,CAAK,KAAA,CAAM,GAAG,QAAA,CAAS,GAAA,EAAK,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA;AAC7D,EAAA,MAAM,IAAA,GAAa;AAAA,IAAA,CAChB,OAAO,GAAA,CAAI,CAAC,IAAI,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,IAAK,CAAA;AAAA,IAClC,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,IAAA,CACX,OAAO,GAAA,CAAI,CAAC,IAAI,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,IAAK;AAAA,GACpC;AACA,EAAA,MAAM,IAAA,GAAa;AAAA,IACjB,OAAO,GAAA,CAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,IAC5B,OAAO,GAAA,CAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,IAC5B,OAAO,GAAA,CAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC;AAAA,GAC9B;AACA,EAAA,MAAM,MAAA,GAAS,SAAS,MAAM,CAAA;AAG9B,EAAA,MAAM,IAAA,GAAa;AAAA,IACjB,IAAA,CAAK,OAAO,QAAA,CAAS,CAAC,IAAI,IAAA,CAAK,MAAA,CAAO,OAAO,CAAC,CAAA;AAAA,IAC9C,IAAA,CAAK,OAAO,QAAA,CAAS,CAAC,IAAI,IAAA,CAAK,MAAA,CAAO,OAAO,CAAC,CAAA;AAAA,IAC9C,IAAA,CAAK,OAAO,QAAA,CAAS,CAAC,IAAI,IAAA,CAAK,MAAA,CAAO,OAAO,CAAC;AAAA,GAChD;AACA,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,EAAG,IAAA,CAAK,CAAC,CAAA,EAAG,IAAA,CAAK,CAAC,CAAC,CAAA;AACrD,EAAA,MAAM,gBAAA,GAAmB,KAAK,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,EAAG,IAAA,CAAK,CAAC,CAAC,CAAA;AACpD,EAAA,MAAM,QAAA,GAAA,CAAa,IAAA,CAAK,WAAA,IAAe,EAAA,IAAM,KAAK,EAAA,GAAM,GAAA;AACxD,EAAA,MAAM,QAAQ,QAAA,GAAW,gBAAA;AACzB,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA;AACxB,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA;AAExB,EAAA,MAAM,QAAQ,CAAC,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,KAA+C;AACpE,IAAA,MAAM,EAAA,GAAK,CAAA,GAAI,KAAA,CAAM,CAAC,CAAA;AACtB,IAAA,MAAM,EAAA,GAAK,CAAA,GAAI,KAAA,CAAM,CAAC,CAAA;AACtB,IAAA,OAAO;AAAA,MACL,IAAA,CAAK,CAAC,CAAA,GAAI,EAAA,GAAK,IAAI,EAAA,GAAK,CAAA;AAAA,MACxB,IAAA,CAAK,CAAC,CAAA,IAAK,CAAA,GAAI,MAAM,CAAC,CAAA,CAAA;AAAA,MACtB,IAAA,CAAK,CAAC,CAAA,GAAI,EAAA,GAAK,IAAI,EAAA,GAAK;AAAA,KAC1B;AAAA,EACF,CAAA;AACA,EAAA,MAAM,SAAS,KAAA,CAAM,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAC,CAAA;AAC9B,EAAA,MAAM,MAAA,GAAkB;AAAA,IACtB,CAAA;AAAA,IACA,CAAA;AAAA,IACA,CAAC,CAAA;AAAA,IACD,CAAA;AAAA,IACA,CAAA;AAAA,IACA,CAAA;AAAA,IACA,CAAA;AAAA,IACA,CAAA;AAAA,IACA,CAAA;AAAA,IACA,CAAA;AAAA,IACA,CAAA;AAAA,IACA,CAAA;AAAA,IACA,OAAO,CAAC,CAAA;AAAA,IACR,OAAO,CAAC,CAAA;AAAA,IACR,OAAO,CAAC,CAAA;AAAA,IACR;AAAA,GACF;AAEA,EAAA,MAAM,IAAA,GAAuB;AAAA,IAC3B,MAAM,IAAA,CAAK,MAAA;AAAA,IACX,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,QAAA;AAAA,IACA,GAAI,SAAS,QAAA,KAAa,MAAA,GAAY,EAAE,QAAA,EAAU,QAAA,CAAS,QAAA,EAAS,GAAI,EAAC;AAAA,IACzE;AAAA,GACF;AACA,EAAA,MAAM,SAAA,GAAmB;AAAA,IACvB,UAAA,EAAa,QAAA,GAAW,GAAA,GAAO,IAAA,CAAK,EAAA;AAAA,IACpC,cAAc,IAAA,CAAK,GAAA;AAAA,MACjB,sBAAA;AAAA,MACC,KAAK,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,EAAG,KAAK,CAAC,CAAC,CAAC,CAAA,GAAI,MAAO,IAAA,CAAK;AAAA;AACnE,GACF;AAKA,EAAA,MAAM,UAAU,CAAC,MAAA,KACd,CAAA,GACC,IAAA,CAAK,MAAM,MAAA,IAAU,CAAA,GAAI,EAAA,GAAK,MAAA,GAAS,OAAO,CAAA,GAAI,IAAA,CAAK,OAAO,MAAA,CAAO,CAAA,GACrE,MACF,IAAA,CAAK,EAAA;AAEP,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,SAAA,EAAW,KAAK,OAAA,CAAQ,SAAA;AAAA,IACxB,YAAY,IAAA,CAAK,UAAA;AAAA,IACjB,QAAA,EAAU,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA;AAAA,IAChC,SAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,MAAA,CACE,KAAA,EACA,MAAA,EACA,IAAA,EACA,IAAA,EACY;AACZ,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,IAAO,OAAA,CAAQ,MAAM,CAAA;AACtC,MAAA,MAAM,MAAA,GAAS,SAAS,MAAM,CAAA;AAC9B,MAAA,MAAM,SAAA,GAAY,YAAY,KAAK,CAAA;AACnC,MAAA,MAAM,MAAA,GAAS,cAAA;AAAA,QACb,MAAA;AAAA,QACA,GAAA;AAAA,QACA,MAAA;AAAA,QACA,KAAK,MAAA,IAAU;AAAA,OACjB;AACA,MAAA,MAAM,cACJ,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,UAAA,GAAa,UAAU,UAAU,CAAA,GAAI,IAAA,IACpD,IAAA,CAAK,KAAK,KAAA,CAAM,YAAA,IAAgB,EAAA,IAAM,SAAA,CAAU,YAAa,CAAA,GAAI,IAAA;AAGnE,MAAA,MAAM,KAAK,SAAA,CAAU,CAAC,IAAI,CAAA,GAAI,SAAA,CAAU,CAAC,CAAA,GAAI,CAAA;AAC7C,MAAA,MAAM,KAAK,SAAA,CAAU,CAAC,IAAI,CAAA,GAAI,SAAA,CAAU,CAAC,CAAA,GAAI,CAAA;AAC7C,MAAA,MAAM,EAAA,GAAK,UAAU,CAAC,CAAA;AACtB,MAAA,MAAM,IAAA,GAAa,CAAC,KAAA,CAAM,CAAC,GAAG,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA,EAAG,KAAA,CAAM,CAAC,CAAC,CAAA;AAC9D,MAAA,MAAM,IAAA,GAAO;AAAA,QACX,IAAA,CAAK,IAAA,CAAK,KAAA,GAAQ,CAAA,GAAI,cAAA;AAAA,QACtB,IAAA,CAAK,IAAA,CAAK,KAAA,GAAQ,CAAA,GAAI;AAAA,OACxB;AACA,MAAA,IAAI,KAAA,GAAQ,QAAA;AACZ,MAAA,IAAI,EAAA,KAAO,CAAA;AACT,QAAA,KAAA,GAAQ,IAAA,CAAK,GAAA;AAAA,UACX,KAAA;AAAA,UAAA,CAAA,CACE,EAAA,GAAK,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA,GAAK,CAAC,IAAA,CAAK,CAAC,CAAA,IAAM,IAAA,CAAK,CAAC,CAAA,IAAK;AAAA,SAChD;AACF,MAAA,IAAI,EAAA,KAAO,CAAA;AACT,QAAA,KAAA,GAAQ,IAAA,CAAK,GAAA;AAAA,UACX,KAAA;AAAA,UAAA,CAAA,CACE,EAAA,GAAK,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA,GAAK,CAAC,IAAA,CAAK,CAAC,CAAA,IAAM,IAAA,CAAK,CAAC,CAAA,IAAK;AAAA,SAChD;AACF,MAAA,IAAI,EAAA,GAAK,CAAA;AACP,QAAA,KAAA,GAAQ,IAAA,CAAK,GAAA;AAAA,UACX,KAAA;AAAA,UAAA,CACC,KAAK,IAAA,CAAK,MAAA,GAAS,cAAA,GAAiB,IAAA,CAAK,CAAC,CAAA,IAAK;AAAA,SAClD;AACF,MAAA,IAAI,EAAA,GAAK,CAAA,EAAG,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,QAAQ,cAAA,GAAiB,IAAA,CAAK,CAAC,CAAA,IAAK,EAAE,CAAA;AAEnE,MAAA,MAAM,SAAS,IAAA,CAAK,GAAA,CAAI,WAAA,GAAc,QAAA,GAAW,GAAG,MAAM,CAAA;AAC1D,MAAA,MAAM,QAAA,GAAW,KAAK,GAAA,CAAI,MAAA,GAAS,KAAK,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,KAAK,CAAC,CAAA;AAG/D,MAAA,MAAM,OAAA,GACJ,WAAW,MAAA,GACP,QAAA,CAAS,UAAU,CAAA,GAAI,UAAA,CAAA,EAAa,QAAA,EAAU,MAAM,CAAA,GACpD,GAAA;AACN,MAAA,OAAO,QAAA;AAAA,QACL,MAAA;AAAA,QACA,MAAA;AAAA,QACA,SAAA;AAAA,QACA,QAAA;AAAA,QACA,KAAK,GAAA,CAAI,YAAA,EAAc,KAAK,GAAA,CAAI,GAAA,EAAK,OAAO,CAAC,CAAA;AAAA,QAC7C,MAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAAA,GACF;AACF;AAIA,SAAS,aAAA,CAAc,OAAe,KAAA,EAAqB;AACzD,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAY;AAC5B,EAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,EAAM,KAAA,KAAU;AAC7B,IAAA,IAAI,CAAC,IAAA,IAAS,OAAO,IAAA,KAAS,QAAA,IAAY,OAAO,IAAA,KAAS,QAAA;AACxD,MAAA,MAAM,OAAA,CAAQ,KAAA,EAAO,KAAA,EAAO,eAAe,CAAA;AAC7C,IAAA,MAAM,GAAA,GAAM,OAAO,IAAI,CAAA;AACvB,IAAA,IAAI,GAAA,CAAI,SAAS,OAAA,EAAS;AACxB,MAAA,IAAI,QAAQ,GAAA,CAAI,IAAI,CAAA,KAAM,IAAA,IAAQ,IAAI,IAAA,KAAS,MAAA;AAC7C,QAAA,MAAM,OAAA,CAAQ,KAAA,EAAO,KAAA,EAAO,sBAAsB,CAAA;AACpD,MAAA,IAAI,QAAQ,GAAA,CAAI,EAAE,CAAA,KAAM,IAAA,IAAQ,IAAI,EAAA,KAAO,MAAA;AACzC,QAAA,MAAM,OAAA,CAAQ,KAAA,EAAO,KAAA,EAAO,oBAAoB,CAAA;AAClD,MAAA,IACE,GAAA,CAAI,YAAY,MAAA,IAChB,EAAE,IAAI,OAAA,GAAU,CAAA,IAAK,IAAI,OAAA,IAAW,WAAA,CAAA;AAEpC,QAAA,MAAM,OAAA;AAAA,UACJ,KAAA;AAAA,UACA,KAAA;AAAA,UACA,+BAA+B,WAAW,CAAA;AAAA,SAC5C;AAAA,IACJ,WAAW,GAAA,CAAI,IAAA,KAAS,MAAA,IAAa,GAAA,CAAI,SAAS,OAAA,EAAS;AACzD,MAAA,MAAM,OAAA;AAAA,QACJ,KAAA;AAAA,QACA,KAAA;AAAA,QACA,CAAA,MAAA,EAAS,MAAA,CAAO,GAAA,CAAI,IAAI,CAAC,CAAA,2BAAA;AAAA,OAC3B;AAAA,IACF,WACG,GAAA,CAAkB,IAAA,KAAS,MAAA,IAC3B,GAAA,CAAkB,WAAW,MAAA,EAC9B;AACA,MAAA,MAAM,OAAA,CAAQ,KAAA,EAAO,KAAA,EAAO,kCAAkC,CAAA;AAAA,IAChE;AACA,IAAA,MAAM,EAAA,GACJ,GAAA,CAAI,EAAA,KACH,GAAA,CAAI,IAAA,KAAS,UACV,CAAA,MAAA,EAAS,QAAA,CAAS,GAAA,CAAI,IAAI,CAAC,CAAA,CAAA,EAAI,SAAS,GAAA,CAAI,EAAE,CAAC,CAAA,CAAA,GAC7C,GAAA,CAAkB,MAAA,KAClB,GAAA,CAAkB,IAAA,KAAS,MAAA,GACzB,QAAA,CAAU,GAAA,CAAkB,IAAK,CAAA,GACjC,MAAA,CAAA,CAAA;AACV,IAAA,IAAI,OAAO,MAAA,EAAW;AACpB,MAAA,IAAI,CAAC,wBAAA,CAAyB,IAAA,CAAK,EAAE,CAAA;AACnC,QAAA,MAAM,OAAA;AAAA,UACJ,KAAA;AAAA,UACA,KAAA;AAAA,UACA,OAAO,EAAE,CAAA,6DAAA;AAAA,SACX;AACF,MAAA,IAAI,GAAA,CAAI,GAAA,CAAI,EAAE,CAAA,EAAG,MAAM,QAAQ,KAAA,EAAO,KAAA,EAAO,CAAA,IAAA,EAAO,EAAE,CAAA,eAAA,CAAiB,CAAA;AACvE,MAAA,GAAA,CAAI,IAAI,EAAE,CAAA;AAAA,IACZ;AAAA,EACF,CAAC,CAAA;AACH;AAEA,SAAS,OAAA,CAAQ,KAAA,EAAe,KAAA,EAAe,IAAA,EAA4B;AACzE,EAAA,OAAO,IAAI,YAAA,CAAa;AAAA,IACtB,IAAA,EAAM,gBAAA;AAAA,IACN,SAAS,CAAA,KAAA,EAAQ,KAAA,GAAQ,CAAC,CAAA,IAAA,EAAO,KAAK,IAAI,IAAI,CAAA,CAAA,CAAA;AAAA,IAC9C,GAAA,EAAK,wHAAA;AAAA,IACL,IAAA,EAAM,GAAG,IAAI,CAAA,MAAA;AAAA,GACd,CAAA;AACH;AAEA,SAAS,eAAA,CAAgB,SAAuB,IAAA,EAAyB;AACvE,EAAA,IACE,CAAC,OAAA,IACD,OAAO,OAAA,CAAQ,OAAO,QAAA,IACtB,CAAC,OAAA,CAAQ,EAAA,IACT,OAAO,OAAA,CAAQ,GAAA,KAAQ,QAAA,IACvB,CAAC,QAAQ,GAAA,EACT;AACA,IAAA,MAAM,IAAI,YAAA,CAAa;AAAA,MACrB,IAAA,EAAM,gBAAA;AAAA,MACN,OAAA,EAAS,0CAAA;AAAA,MACT,GAAA,EAAK,0GAAA;AAAA,MACL,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACA,EAAA,IAAI,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,EAAE,CAAA,EAAG;AACxB,IAAA,MAAM,IAAI,YAAA,CAAa;AAAA,MACrB,IAAA,EAAM,gBAAA;AAAA,MACN,OAAA,EAAS,CAAA,yBAAA,EAA4B,OAAA,CAAQ,EAAE,CAAA,EAAA,CAAA;AAAA,MAC/C,GAAA,EAAK,mEAAA;AAAA,MACL,GAAA,EAAK,sBAAA;AAAA,MACL,MAAM,OAAA,CAAQ,EAAA;AAAA,MACd,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACA,EAAA,IAAA,CAAK,GAAA,CAAI,QAAQ,EAAE,CAAA;AACrB;AAEA,SAAS,UAAA,CAAW,SAAuB,OAAA,EAA+B;AACxE,EAAA,OAAO,IAAI,YAAA,CAAa;AAAA,IACtB,IAAA,EAAM,cAAA;AAAA,IACN,OAAA;AAAA,IACA,MAAM,OAAA,CAAQ,EAAA;AAAA,IACd,IAAA,EAAM,GAAG,IAAI,CAAA,qBAAA;AAAA,GACd,CAAA;AACH;AAEA,SAAS,aAAA,CACP,OACA,SAAA,EACc;AACd,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA;AAC3B,EAAA,OAAO,IAAI,YAAA,CAAa;AAAA,IACtB,IAAA,EAAM,cAAA;AAAA,IACN,OAAA,EAAS,CAAA,EAAG,KAAA,CAAM,OAAO,CAAA,cAAA,EAAiB,SAAS,CAAA,0CAAA,EAA6C,KAAA,CAAM,EAAE,CAAA,EAAA,EAAK,KAAA,CAAM,KAAA,CAAM,OAAO,CAAA,CAAA;AAAA,IAChI,GAAA,EAAK,mJAAA;AAAA,IACL,GAAA,EAAK,6JAAA;AAAA,IACL,IAAA,EAAM,GAAG,IAAI,CAAA,iBAAA;AAAA,GACd,CAAA;AACH;AAEA,SAAS,UAAA,GAAoB;AAC3B,EAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,CAAM,4BAA4B,CAAA;AACpD,EAAA,KAAA,CAAM,IAAA,GAAO,YAAA;AACb,EAAA,OAAO,KAAA;AACT;;;AC3xCA,IAAM,YAAA,GAAe,IAAI,EAAA,GAAK,GAAA;AAO9B,eAAsB,cAAc,KAAA,EAYR;AAC1B,EAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,MAAA,EAAO,GAAI,KAAA;AACpC,EAAA,MAAM,GAAA,GAAM,KAAA,CAAM,GAAA,IAAO,IAAA,CAAK,GAAA,EAAI;AAElC,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,CAAC,MAAA,EAAQ;AACzC,IAAA,MAAM,IAAI,YAAA,CAAa;AAAA,MACrB,IAAA,EAAM,gBAAA;AAAA,MACN,OAAA,EAAS,sCAAA;AAAA,MACT,GAAA,EAAK,0IAAA;AAAA,MACL,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACA,EAAA,IAAI,OAAO,SAAA,KAAc,QAAA,IAAY,CAAC,SAAA,EAAW;AAC/C,IAAA,MAAM,OAAA;AAAA,MACJ;AAAA,KACF;AAAA,EACF;AAIA,EAAA,MAAM,QAAQ,MAAA,CAAO,WAAA;AAAA,IACnB,UAAU,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,CAAC,KAAA,KAAU;AAClC,MAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAC/B,MAAA,OAAO,CAAC,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,KAAK,CAAA,CAAE,IAAA,EAAK,EAAG,KAAA,CAAM,KAAA,CAAM,KAAA,GAAQ,CAAC,CAAA,CAAE,MAAM,CAAA;AAAA,IACrE,CAAC;AAAA,GACH;AACA,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,KAAA,CAAM,CAAC,CAAA;AAChC,EAAA,MAAM,WAAW,KAAA,CAAM,EAAA;AAEvB,EAAA,IAAI,CAAC,SAAA,IAAa,CAAC,QAAA,EAAU;AAC3B,IAAA,MAAM,QAAQ,+DAAqD,CAAA;AAAA,EACrE;AACA,EAAA,IAAI,IAAA,CAAK,GAAA,CAAI,GAAA,GAAM,SAAS,IAAI,YAAA,EAAc;AAC5C,IAAA,MAAM,QAAQ,2DAA2D,CAAA;AAAA,EAC3E;AAEA,EAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,MAAA,CAAO,SAAA;AAAA,IAC9B,KAAA;AAAA,IACA,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,MAAM,CAAA;AAAA,IAC/B,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAU;AAAA,IAChC,KAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AACA,EAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,MAAA,CAAO,IAAA;AAAA,IAC9B,MAAA;AAAA,IACA,GAAA;AAAA,IACA,IAAI,aAAY,CAAE,MAAA,CAAO,GAAG,SAAS,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE;AAAA,GACjD;AAEA,EAAA,IAAI,CAAC,gBAAgB,KAAA,CAAM,IAAI,WAAW,GAAG,CAAC,CAAA,EAAG,QAAQ,CAAA,EAAG;AAC1D,IAAA,MAAM,QAAQ,oCAAoC,CAAA;AAAA,EACpD;AAEA,EAAA,OAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AACxB;AAEA,SAAS,QAAQ,OAAA,EAA+B;AAC9C,EAAA,OAAO,IAAI,YAAA,CAAa;AAAA,IACtB,IAAA,EAAM,cAAA;AAAA,IACN,OAAA;AAAA,IACA,GAAA,EAAK,uFAAA;AAAA,IACL,GAAA,EAAK,mGAAA;AAAA,IACL,IAAA,EAAM;AAAA,GACP,CAAA;AACH;AAMA,SAAS,eAAA,CAAgB,GAAW,CAAA,EAAoB;AACtD,EAAA,IAAI,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,MAAA,EAAQ,OAAO,KAAA;AAClC,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,MAAA,EAAQ,CAAA,EAAA,EAAK,IAAA,IAAQ,CAAA,CAAE,UAAA,CAAW,CAAC,CAAA,GAAI,CAAA,CAAE,WAAW,CAAC,CAAA;AAC3E,EAAA,OAAO,IAAA,KAAS,CAAA;AAClB;AAEA,SAAS,MAAM,KAAA,EAA2B;AACxC,EAAA,IAAI,GAAA,GAAM,EAAA;AACV,EAAA,KAAA,MAAW,IAAA,IAAQ,OAAO,GAAA,IAAO,IAAA,CAAK,SAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAA;AAClE,EAAA,OAAO,GAAA;AACT;;;AC1BO,IAAM,gBAAN,MAAoB;AAAA,EAChB,MAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EAEQ,SAAA;AAAA,EACA,OAAA;AAAA,EACT,SAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWR,WAAA,CAAY,SAAA,EAAmB,OAAA,GAAgC,EAAC,EAAG;AAIjE,IAAA,IAAI,SAAA,IAAa,IAAA,IAAQ,OAAO,SAAA,KAAc,QAAA,EAAU;AACtD,MAAA,MAAM,IAAI,YAAA,CAAa;AAAA,QACrB,IAAA,EAAM,gBAAA;AAAA,QACN,OAAA,EACE,8EAAA;AAAA,QACF,GAAA,EAAK,6DAAA;AAAA,QACL,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,IAAA,CAAK,YAAY,SAAA,IAAa,MAAA;AAC9B,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAKf,IAAA,IAAI,IAAA,CAAK,WAAW,kBAAA,CAAmB,IAAA,CAAK,WAAW,EAAE,MAAA,EAAQ,QAAQ,CAAA;AAEzE,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,MAAA,EAAO;AAGjC,IAAA,MAAM,OAAA,GAAmB,OAAO,MAAA,EAAQ,IAAA,EAAM,IAAA,KAC5C,QAAO,CAAE,OAAA,CAAQ,MAAA,EAAQ,IAAA,EAAM,IAAI,CAAA;AACrC,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,SAAA,CAAU,OAAO,CAAA;AACnC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,UAAA,CAAW,OAAA,EAAS,MAAM,CAAA;AAC7C,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,UAAA,CAAW,MAAM,CAAA;AACpC,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,SAAA,CAAU,MAAM,CAAA;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,MAAA,GAAwB;AAC9B,IAAA,IAAI,IAAA,CAAK,SAAA,EAAW,OAAO,IAAA,CAAK,SAAA;AAChC,IAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AACvB,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,YAAA,CAAa;AAAA,QACrB,IAAA,EAAM,cAAA;AAAA,QACN,OAAA,EACE,qIAAA;AAAA,QACF,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AAIA,IAAA,IAAI,SAAA,CAAU,UAAA,CAAW,QAAQ,CAAA,EAAG;AAClC,MAAA,MAAM,IAAI,YAAA,CAAa;AAAA,QACrB,IAAA,EAAM,cAAA;AAAA,QACN,OAAA,EAAS,4CAAA;AAAA,QACT,GAAA,EAAK,+FAAA;AAAA,QACL,GAAA,EAAK,gGAAA;AAAA,QACL,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,IAAI,CAAC,SAAA,CAAU,UAAA,CAAW,QAAQ,CAAA,EAAG;AACnC,MAAA,MAAM,IAAI,YAAA,CAAa;AAAA,QACrB,IAAA,EAAM,cAAA;AAAA,QACN,OAAA,EACE,kGAAA;AAAA,QACF,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,aAAA,CAAc;AAAA,MACjC,MAAA,EAAQ,SAAA;AAAA,MACR,GAAI,IAAA,CAAK,OAAA,CAAQ,OAAA,GAAU,EAAE,SAAS,IAAA,CAAK,OAAA,CAAQ,OAAA,EAAQ,GAAI,EAAC;AAAA,MAChE,GAAI,IAAA,CAAK,OAAA,CAAQ,KAAA,GAAQ,EAAE,OAAO,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAM,GAAI,EAAC;AAAA,MAC1D,GAAI,IAAA,CAAK,OAAA,CAAQ,KAAA,GAAQ,EAAE,OAAO,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAM,GAAI;AAAC,KAC3D,CAAA;AACD,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BA,MAAM,YAAY,OAAA,EAAsD;AACtE,IAAA,IAAI,EAAE,OAAA,CAAQ,OAAA,GAAU,CAAA,CAAA,EAAI;AAC1B,MAAA,MAAM,IAAI,YAAA,CAAa;AAAA,QACrB,IAAA,EAAM,gBAAA;AAAA,QACN,OAAA,EAAS,gCAAA;AAAA,QACT,GAAA,EAAK,yKAAA;AAAA,QACL,GAAA,EAAK,8GAAA;AAAA,QACL,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,OAAA,CAAQ,OAAO,CAAA;AACxC,IAAA,MAAM,WAAW,MAAM,WAAA,CAAY,KAAK,MAAA,EAAO,EAAG,OAAO,OAAO,CAAA;AAGhE,IAAA,MAAM,MAAM,KAAA,EAAM;AAClB,IAAA,OAAO,IAAI,SAAA,CAAU,KAAA,EAAO,QAAQ,CAAA;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WACJ,OAAA,EAC+B;AAO/B,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,OAAA,CAAQ;AAAA,MAC/B,GAAA,EAAK,OAAA,CAAQ,GAAA,IAAO,QAAA,CAAS,QAAQ,GAAG,CAAA;AAAA,MACxC,IAAA,EAAM,CAAA,EAAG,OAAA,CAAQ,IAAA,IAAQ,QAAQ,GAAG,CAAA,QAAA,CAAA;AAAA,MACpC,GAAI,QAAQ,IAAA,GAAO,EAAE,MAAM,OAAA,CAAQ,IAAA,KAAS;AAAC,KAC9C,CAAA;AACD,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,WAAA,CAAY,IAAA,CAAK,MAAA,EAAO,EAAG,OAAO,OAAA,EAAS;AAAA,QACtD,MAAA,EAAQ;AAAA,OACT,CAAA;AAAA,IACH,CAAA,SAAE;AAEA,MAAA,MAAM,KAAA,CAAM,MAAA,EAAO,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACrC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,SAAA,CACJ,OAAA,EACA,IAAA,GAAuB,EAAC,EACC;AACzB,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,OAAA,CAAQ,OAAA,IAAW,QAAQ,CAAA,CAAE,eAAA;AAClD,IAAA,MAAM,QAAA,GAAW,YAAA;AAAA,MACf;AAAA,QACE,KAAK,OAAA,CAAQ,GAAA;AAAA,QACb,KAAA,EAAO,QAAQ,KAAA,IAAS,IAAA;AAAA,QACxB,MAAA,EAAQ,QAAQ,MAAA,IAAU;AAAA,OAC5B;AAAA,MACA;AAAA,KACF;AACA,IAAA,MAAM,GAAA,GAAiE;AAAA,MACrE,GAAG,OAAA;AAAA,MACH,KAAK,QAAA,CAAS,GAAA;AAAA,MACd,MAAM,QAAA,CAAS,IAAA;AAAA,MACf,SAAS,QAAA,CAAS,OAAA;AAAA,MAClB,QAAA,EAAU,QAAA,CAAS,OAAA,CAAQ,QAAA,EAAU,KAAK,QAAQ,CAAA;AAAA,MAClD,IAAA,EAAM,CAAA,EAAG,OAAA,CAAQ,IAAA,IAAQ,QAAQ,GAAG,CAAA,OAAA;AAAA,KACtC;AACA,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AAGpC,IAAA,MAAM,WAAW,MAAM,WAAA,CAAY,KAAK,MAAA,EAAO,EAAG,OAAO,GAAA,EAAK;AAAA,MAC5D,KAAA,EAAO;AAAA,QACL,SAAS,QAAA,CAAS,OAAA;AAAA,QAClB,SAAS,QAAA,CAAS,OAAA;AAAA,QAClB,OAAO,QAAA,CAAS,KAAA;AAAA,QAChB,QAAQ,QAAA,CAAS,MAAA;AAAA,QACjB,GAAA,EAAK,EAAA;AAAA,QACL,OAAA,EAAS;AAAA;AACX,KACD,CAAA;AACD,IAAA,MAAM,MAAM,KAAA,EAAM;AAClB,IAAA,OAAO,IAAI,SAAA,CAAU,KAAA,EAAO,QAAQ,CAAA;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAAa,EAAA,EAAgC;AACjD,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,EAAO;AAC3B,IAAA,OAAO,IAAI,SAAA,CAAU,IAAI,KAAA,CAAM,MAAA,EAAQ,MAAM,MAAA,CAAO,QAAA,CAAS,EAAE,CAAC,CAAC,CAAA;AAAA,EACnE;AAAA,EAEA,MAAc,QACZ,OAAA,EAIgB;AAChB,IAAA,IAAI,CAAC,QAAQ,GAAA,EAAK;AAChB,MAAA,MAAM,IAAI,YAAA,CAAa;AAAA,QACrB,IAAA,EAAM,gBAAA;AAAA,QACN,OAAA,EAAS,oBAAA;AAAA,QACT,GAAA,EAAK,yHAAA;AAAA,QACL,GAAA,EAAK,4EAAA;AAAA,QACL,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,EAAO;AAC3B,IAAA,OAAO,IAAI,KAAA;AAAA,MACT,MAAA;AAAA,MACA,MAAM,OAAO,SAAA,CAAU;AAAA,QACrB,KAAK,OAAA,CAAQ,GAAA;AAAA,QACb,GAAI,QAAQ,IAAA,GAAO,EAAE,MAAM,OAAA,CAAQ,IAAA,KAAS,EAAC;AAAA,QAC7C,GAAI,QAAQ,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAQ,GAAI,EAAC;AAAA,QACpE,IAAA,EAAM,QAAQ,IAAA,IAAQ,OAAA;AAAA,QACtB,GAAI,QAAQ,WAAA,KAAgB,MAAA,GACxB,EAAE,WAAA,EAAa,OAAA,CAAQ,WAAA,EAAY,GACnC;AAAC,OACN;AAAA,KACH;AAAA,EACF;AACF;AAEA,IAAM,YAAN,MAAgB;AAAA,EACd,YAA6B,MAAA,EAA6B;AAA7B,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAA8B;AAAA,EAA9B,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAa7B,MAAM,MAAA,CACJ,GAAA,EACA,OAAA,GAAsC,EAAC,EACT;AAC9B,IAAA,OAAO,IAAA,CAAK,MAAA,EAAO,CAAE,WAAA,CAAY;AAAA,MAC/B,GAAA;AAAA,MACA,GAAI,QAAQ,IAAA,GAAO,EAAE,MAAM,OAAA,CAAQ,IAAA,KAAS;AAAC,KAC9C,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,OAAO,IAAA,EAA4C;AAGvD,IAAA,IAAI,CAAC,WAAA,CAAY,IAAI,CAAA,EAAG;AACtB,MAAA,MAAM,IAAI,YAAA,CAAa;AAAA,QACrB,IAAA,EAAM,gBAAA;AAAA,QACN,OAAA,EAAS,IAAI,MAAA,CAAO,IAAI,EAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA,iFAAA,CAAA;AAAA,QACtC,GAAA,EAAK,4FAAA;AAAA,QACL,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,OAAO,IAAA,CAAK,QAAO,CAAE,OAAA;AAAA,MACnB,QAAA;AAAA,MACA,cAAc,IAAI,CAAA;AAAA,KACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,SAAA,GAA0C;AAC9C,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,EAAO;AAC3B,IAAA,IAAI,OAAA,GAAU,CAAA;AACd,IAAA,WAAS;AACP,MAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,OAAA;AAAA,QACxB,QAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA,OAAA,IAAW,IAAA,CAAK,OAAA;AAGhB,MAAA,IAAI,CAAC,KAAK,IAAA,IAAQ,IAAA,CAAK,YAAY,CAAA,EAAG,OAAO,EAAE,OAAA,EAAQ;AAAA,IACzD;AAAA,EACF;AACF,CAAA;AAIA,IAAM,YAAN,MAAgB;AAAA,EACd,YAA6B,OAAA,EAAkB;AAAlB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EAAmB;AAAA,EAAnB,OAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAW7B,MAAA,CAAO,OAAA,GAA+B,EAAC,EAA0B;AAC/D,IAAA,OAAO,IAAA,CAAK,OAAA,CAAsB,MAAA,EAAQ,YAAA,EAAc;AAAA,MACtD,gBAAA,EAAkB,QAAQ,gBAAA,IAAoB,GAAA;AAAA,MAC9C,UAAA,EAAY,QAAQ,UAAA,IAAc,CAAA;AAAA,MAClC,OAAA,EAAS,QAAQ,OAAA,IAAW,CAAA;AAAA,MAC5B,GAAI,QAAQ,cAAA,GACR,EAAE,gBAAgB,OAAA,CAAQ,cAAA,KAC1B,EAAC;AAAA,MACL,GAAI,QAAQ,OAAA,GAAU,EAAE,SAAS,OAAA,CAAQ,OAAA,KAAY;AAAC,KACvD,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,OAAO,KAAA,EAA8B;AACnC,IAAA,OAAO,KAAK,OAAA,CAAc,MAAA,EAAQ,mBAAA,EAAqB,EAAE,OAAO,CAAA;AAAA,EAClE;AACF,CAAA;AAEA,IAAM,aAAN,MAAiB;AAAA,EACf,WAAA,CACmB,SACA,MAAA,EACjB;AAFiB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAChB;AAAA,EAFgB,OAAA;AAAA,EACA,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQnB,MAAM,OAAO,IAAA,EAAyC;AACpD,IAAA,OAAO,IAAA,CAAK,MAAA,EAAO,CAAE,YAAA,CAAa,IAAI,CAAA;AAAA,EACxC;AAAA;AAAA,EAGA,IAAI,EAAA,EAAmC;AACrC,IAAA,OAAO,IAAA,CAAK,OAAA,CAAsB,KAAA,EAAO,CAAA,YAAA,EAAe,EAAE,CAAA,CAAE,CAAA;AAAA,EAC9D;AAAA;AAAA,EAGA,OAAO,EAAA,EAAmC;AACxC,IAAA,OAAO,KAAK,OAAA,CAAsB,MAAA,EAAQ,eAAe,EAAE,CAAA,OAAA,CAAA,EAAW,EAAE,CAAA;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,MAAM,EAAA,EAAmC;AAC7C,IAAA,OAAO,IAAA,CAAK,MAAA,EAAO,CAAE,WAAA,CAAY,EAAE,CAAA;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,EAAA,EAAmC;AACxC,IAAA,OAAO,IAAA,CAAK,OAAA,CAAsB,QAAA,EAAU,CAAA,YAAA,EAAe,EAAE,CAAA,CAAE,CAAA;AAAA,EACjE;AAAA;AAAA,EAGA,IAAA,CAAK,OAAA,GAA+C,EAAC,EAGlD;AACD,IAAA,MAAM,KAAA,GAAQ,IAAI,eAAA,EAAgB;AAClC,IAAA,IAAI,OAAA,CAAQ,OAAO,KAAA,CAAM,GAAA,CAAI,SAAS,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAC,CAAA;AAC3D,IAAA,IAAI,QAAQ,MAAA,EAAQ,KAAA,CAAM,GAAA,CAAI,QAAA,EAAU,QAAQ,MAAM,CAAA;AACtD,IAAA,MAAM,SAAS,KAAA,CAAM,QAAA,EAAS,GAAI,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,GAAK,EAAA;AAChD,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAO,CAAA,WAAA,EAAc,MAAM,CAAA,CAAE,CAAA;AAAA,EACnD;AAAA;AAAA,EAGA,SACE,IAAA,EACuB;AACvB,IAAA,OAAO,IAAA,CAAK,OAAA,CAAsB,MAAA,EAAQ,cAAA,EAAgB,IAAI,CAAA;AAAA,EAChE;AACF,CAAA;AAeA,IAAM,aAAN,MAAiB;AAAA,EACf,YAA6B,MAAA,EAA6B;AAA7B,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAA8B;AAAA,EAA9B,MAAA;AAAA;AAAA,EAG7B,MAAM,KAAK,OAAA,EAA2C;AACpD,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,EAAO;AAC3B,IAAA,OAAO,IAAI,KAAA,CAAM,MAAA,EAAQ,MAAM,MAAA,CAAO,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA,EAC1D;AAAA;AAAA,EAGA,MAAM,IAAI,EAAA,EAA4B;AACpC,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,EAAO;AAC3B,IAAA,OAAO,IAAI,KAAA,CAAM,MAAA,EAAQ,MAAM,MAAA,CAAO,QAAA,CAAS,EAAE,CAAC,CAAA;AAAA,EACpD;AACF,CAAA","file":"index.js","sourcesContent":["/**\n * Content-addressed assets.\n *\n * A product scene can be hundreds of megabytes, and the second render of it\n * usually differs from the first by a camera angle. So every immutable blob\n * is named by the SHA-256 of its own bytes and uploaded at most once. The\n * flow is three round trips and no wasted bytes:\n *\n * hash locally -> POST /assets/check -> PUT only what is missing\n *\n * Nothing here knows about a bucket or a region. The control plane signs,\n * the browser puts, the worker reads by hash.\n */\n\n/** `sha256:` + 64 lowercase hex. */\nexport const ASSET_HASH_PATTERN = /^sha256:[0-9a-f]{64}$/;\n\nexport function isAssetHash(value: unknown): value is string {\n return typeof value === 'string' && ASSET_HASH_PATTERN.test(value);\n}\n\nexport type AssetKind =\n 'scene' | 'texture' | 'hdri' | 'ies' | 'geometry' | 'animation';\n\nexport type AssetDescriptor = {\n hash: string;\n kind: AssetKind;\n bytes: number;\n contentType: string;\n /** Diagnostics and the devtools' upload list; never used for addressing. */\n name?: string;\n};\n\n/** Request body for \"which of these do you already have?\". */\nexport type AssetCheckRequest = {\n assets: AssetDescriptor[];\n};\n\n/**\n * The answer, plus a signed PUT for each miss.\n *\n * The presigned URL is a capability, not a credential: one object, one\n * method, one expiry. It lets the browser upload straight to storage without\n * the control plane ever touching the bytes.\n */\nexport type AssetCheckResponse = {\n /** Hashes already in storage. Do not upload these. */\n present: string[];\n /** One signed PUT per hash that is missing. */\n uploads: Array<{\n hash: string;\n url: string;\n /**\n * Headers the signature covers. A presigned PUT is signed over an exact\n * header set, so sending more or fewer than these is a 403. Pass them\n * through verbatim.\n */\n headers?: Record<string, string>;\n expiresAt: number;\n }>;\n};\n\n/**\n * `DELETE /v1/assets/:hash`. Secret key only. The stored file and its\n * record are gone; the next render that needs it uploads it again.\n */\nexport type AssetDeleteResponse = {\n hash: string;\n /** False when the project held no file with this hash: not an error. */\n deleted: boolean;\n};\n\n/**\n * `DELETE /v1/assets`: one page of the project's files per call. Secret key\n * only. Call again while `more` is true.\n */\nexport type AssetsDeleteResponse = {\n /** Files deleted by this call. */\n deleted: number;\n /** Whether the project still holds files after this call. */\n more: boolean;\n};\n","/**\n * Cameras without a scene graph: where to stand to photograph a box.\n *\n * In the browser a camera is an object the developer placed. From a server\n * there is a model's bounds (`GlbFacts.bounds`, read at import) and nothing\n * else, so a view is described the way a photographer would: from which\n * side, how high, how tight. `framedCamera` turns that into the same\n * `CameraSpec` a captured camera becomes.\n *\n * No three.js here: the server entry imports this file.\n */\n\nimport type { CameraSpec, Quat, Vec3 } from './protocol/index.js';\nimport { Bakery3Error } from './errors.js';\n\nexport type Bounds = { min: Vec3; max: Vec3 };\n\n/** Where to look from: degrees around the model from its front (+Z, where glTF says a model faces) toward its right (+X), and degrees above the horizon. */\nexport type Angle = { azimuthDeg: number; elevationDeg?: number };\n\n/** A view framed around the model, whatever its size and wherever it sits. */\nexport type FramedView = Angle & {\n id: string;\n /** Vertical field of view in degrees. Default 30: a product lens, little perspective. */\n fov?: number;\n /** Room around the model, as a share of its size. Default 0.12. */\n margin?: number;\n};\n\n/** A camera declared absolutely, in the model's own coordinates. */\nexport type DeclaredView = {\n id: string;\n position: Vec3;\n target: Vec3;\n fov: number;\n};\n\n/** The framings with names. */\nexport const VIEW_WORDS = {\n front: { azimuthDeg: 0, elevationDeg: 6 },\n 'three-quarter': { azimuthDeg: 35, elevationDeg: 14 },\n side: { azimuthDeg: 90, elevationDeg: 6 },\n back: { azimuthDeg: 180, elevationDeg: 6 },\n 'three-quarter-back': { azimuthDeg: 145, elevationDeg: 14 },\n top: { azimuthDeg: 0, elevationDeg: 88 },\n} as const satisfies Record<string, Omit<FramedView, 'id'>>;\n\nexport type ViewWord = keyof typeof VIEW_WORDS;\n\n/** A word or an angle, as an angle. Anything else is null. */\nexport function angleOf(view: unknown): Angle | null {\n if (typeof view === 'string')\n return view in VIEW_WORDS ? { ...VIEW_WORDS[view as ViewWord] } : null;\n if (\n view &&\n typeof view === 'object' &&\n typeof (view as Angle).azimuthDeg === 'number'\n ) {\n const { azimuthDeg, elevationDeg } = view as Angle;\n return {\n azimuthDeg,\n ...(elevationDeg !== undefined ? { elevationDeg } : {}),\n };\n }\n return null;\n}\n\n/** The angle `t` of the way from `from` to `to`, azimuth as given: 0 to 360 is a full turn, 0 to -90 goes the other way. */\nexport function angleBetween(from: Angle, to: Angle, t: number): Angle {\n const fromEl = from.elevationDeg ?? 12;\n const toEl = to.elevationDeg ?? 12;\n return {\n azimuthDeg: from.azimuthDeg + (to.azimuthDeg - from.azimuthDeg) * t,\n elevationDeg: fromEl + (toEl - fromEl) * t,\n };\n}\n\n/** The unit direction from a model's center toward a camera at this angle. */\nexport function directionOf(angle: Angle): Vec3 {\n const azimuth = (angle.azimuthDeg * Math.PI) / 180;\n const elevation = ((angle.elevationDeg ?? 12) * Math.PI) / 180;\n return [\n Math.sin(azimuth) * Math.cos(elevation),\n Math.sin(elevation),\n Math.cos(azimuth) * Math.cos(elevation),\n ];\n}\n\n/** How far a camera with this lens stands from a sphere of `radius` to fit it, with `margin` to spare. */\nexport function framedDistance(\n radius: number,\n fov: number,\n aspect: number,\n margin: number,\n): number {\n const vertical = (fov * Math.PI) / 180;\n const horizontal = 2 * Math.atan(Math.tan(vertical / 2) * aspect);\n return (radius * (1 + margin)) / Math.sin(Math.min(vertical, horizontal) / 2);\n}\n\nexport function radiusOf(bounds: Bounds): number {\n return (\n Math.hypot(\n bounds.max[0] - bounds.min[0],\n bounds.max[1] - bounds.min[1],\n bounds.max[2] - bounds.min[2],\n ) / 2 || 0.5\n );\n}\n\nexport function centerOf(bounds: Bounds): Vec3 {\n return [\n (bounds.min[0] + bounds.max[0]) / 2,\n (bounds.min[1] + bounds.max[1]) / 2,\n (bounds.min[2] + bounds.max[2]) / 2,\n ];\n}\n\n/**\n * Stand far enough back that the model's bounding sphere fits the narrower\n * of the two fields of view, with `margin` to spare. A sphere, not the box's\n * silhouette: it is a little loose on a tall thin thing and never crops.\n */\nexport function framedCamera(\n bounds: Bounds,\n view: FramedView,\n aspect: number,\n): CameraSpec {\n const fov = view.fov ?? 30;\n if (!(fov > 1 && fov < 120))\n throw badView(view.id, `fov ${fov} is outside 1 to 120 degrees`);\n const center = centerOf(bounds);\n const radius = radiusOf(bounds);\n const distance = framedDistance(radius, fov, aspect, view.margin ?? 0.12);\n return cameraAt(\n center,\n radius,\n directionOf(view),\n distance,\n fov,\n aspect,\n view.id,\n );\n}\n\n/** A camera `distance` along `direction` from `center`, looking back at it. */\nexport function cameraAt(\n center: Vec3,\n radius: number,\n direction: Vec3,\n distance: number,\n fov: number,\n aspect: number,\n name: string,\n): CameraSpec {\n const position: Vec3 = [\n center[0] + direction[0] * distance,\n center[1] + direction[1] * distance,\n center[2] + direction[2] * distance,\n ];\n return {\n type: 'perspective',\n fov,\n aspect,\n near: Math.max(0.001, (distance - radius) / 10),\n far: (distance + radius) * 10,\n position,\n quaternion: lookAt(position, center),\n name,\n };\n}\n\nexport function declaredCamera(view: DeclaredView, aspect: number): CameraSpec {\n const distance = Math.hypot(\n view.position[0] - view.target[0],\n view.position[1] - view.target[1],\n view.position[2] - view.target[2],\n );\n if (!(distance > 0)) throw badView(view.id, 'its position is on its target');\n return {\n type: 'perspective',\n fov: view.fov,\n aspect,\n near: Math.max(0.01, distance / 100),\n far: Math.max(100, distance * 100),\n position: [...view.position] as Vec3,\n quaternion: lookAt(view.position, view.target),\n name: view.id,\n };\n}\n\n/**\n * The rotation of a camera at `position` looking at `target`, +Y up, by\n * three's convention: a camera looks down its local -Z.\n */\nexport function lookAt(position: Vec3, target: Vec3): Quat {\n let z = normalize([\n position[0] - target[0],\n position[1] - target[1],\n position[2] - target[2],\n ]);\n if (!z) z = [0, 0, 1];\n // Straight down (or up): +Y up is degenerate, so face -Z as three does.\n const up: Vec3 =\n Math.abs(z[0]) < 1e-9 && Math.abs(z[2]) < 1e-9 ? [0, 0, -1] : [0, 1, 0];\n const x = normalize(cross(up, z)) ?? [1, 0, 0];\n const y = cross(z, x);\n return quaternionOf(x, y, z);\n}\n\nfunction quaternionOf(x: Vec3, y: Vec3, z: Vec3): Quat {\n const m00 = x[0],\n m10 = x[1],\n m20 = x[2];\n const m01 = y[0],\n m11 = y[1],\n m21 = y[2];\n const m02 = z[0],\n m12 = z[1],\n m22 = z[2];\n const trace = m00 + m11 + m22;\n if (trace > 0) {\n const s = 0.5 / Math.sqrt(trace + 1);\n return [(m21 - m12) * s, (m02 - m20) * s, (m10 - m01) * s, 0.25 / s];\n }\n if (m00 > m11 && m00 > m22) {\n const s = 2 * Math.sqrt(1 + m00 - m11 - m22);\n return [0.25 * s, (m01 + m10) / s, (m02 + m20) / s, (m21 - m12) / s];\n }\n if (m11 > m22) {\n const s = 2 * Math.sqrt(1 + m11 - m00 - m22);\n return [(m01 + m10) / s, 0.25 * s, (m12 + m21) / s, (m02 - m20) / s];\n }\n const s = 2 * Math.sqrt(1 + m22 - m00 - m11);\n return [(m02 + m20) / s, (m12 + m21) / s, 0.25 * s, (m10 - m01) / s];\n}\n\nfunction cross(a: Vec3, b: Vec3): Vec3 {\n return [\n a[1] * b[2] - a[2] * b[1],\n a[2] * b[0] - a[0] * b[2],\n a[0] * b[1] - a[1] * b[0],\n ];\n}\n\nfunction normalize(v: Vec3): Vec3 | null {\n const length = Math.hypot(v[0], v[1], v[2]);\n return length > 1e-12 ? [v[0] / length, v[1] / length, v[2] / length] : null;\n}\n\nfunction badView(id: string, what: string): Bakery3Error {\n return new Bakery3Error({\n code: 'InvalidRequest',\n message: `Camera \"${id}\": ${what}.`,\n docs: 'https://bakery3.com/docs/catalog#angles',\n });\n}\n","/**\n * A catalog from a server: models by URL, shots per product, no browser.\n *\n * import { Bakery3Server } from '@oeave/bakery3/node';\n * const api = new Bakery3Server(process.env.BAKERY3_SECRET_KEY!);\n *\n * const run = await api.renderBatch({\n * key: 'fall-2026',\n * products: [{ id: 'chair-aria', url: 'https://cdn.shop.com/models/chair-aria.glb' }],\n * shots: [\n * 'three-quarter',\n * { kind: 'video', from: 'three-quarter', to: 'three-quarter-back', seconds: 4 },\n * { id: 'low', azimuthDeg: -30, elevationDeg: 4 },\n * ],\n * room: { preset: 'loft_golden' },\n * maxCost: 600,\n * });\n *\n * A shot is a picture or a clip of a product from an angle: degrees around\n * the model from its front and degrees above the horizon, or a word for one.\n * The camera is framed from the model's own bounds, read when the model is\n * imported, so a vase and a sofa both fill the frame from the same word and\n * nothing is asked of the file itself. A clip is the camera carried from one\n * angle to another over `seconds`, one framed camera per frame.\n *\n * Settings come in three layers: the run's, then a product's, then a shot's,\n * the nearer winning. So one `room` at the top is every shot's room, a\n * product that wants the studio instead says `room: null, environment: {…}`,\n * and one shot in it can still be a close-up at 2048² in a jpeg.\n *\n * The model's bytes never pass through this process. Each URL is handed to\n * `POST /v1/assets/import`; the service fetches it once, stores it content\n * addressed like any upload, and answers with the hash and what the GLB says\n * about itself. A model that did not change since the last run is not\n * downloaded again. What this process sends is a few KB of manifest per shot.\n *\n * A manifest built here describes a model, cameras and light. A scene whose\n * look lives in code exists only where that code runs, so it is recorded\n * there, with `renderVariants()` in the page. Both kinds of item can share a\n * batch.\n *\n * No three.js here.\n */\n\nimport {\n protocolVersionFor,\n type AnimationSpec,\n type AssetImportKind,\n type AssetImportResponse,\n type BatchItemOutcome,\n type BatchItemRequest,\n type CameraSpec,\n type ColorSpec,\n type EnvironmentSpec,\n type GlbFacts,\n type Matrix4,\n type OutputSpec,\n type QualityPreset,\n type RenderSpec,\n type RoomPresetSpec,\n type SceneManifest,\n type Vec3,\n} from '../protocol/index.js';\nimport { QUALITY, isClipFormat, isVideoFormat } from '../protocol/index.js';\nimport type { Batch, BatchProgress } from '../batch.js';\nimport { Bakery3Error } from '../errors.js';\nimport {\n VIEW_WORDS,\n angleBetween,\n angleOf,\n cameraAt,\n centerOf,\n directionOf,\n framedCamera,\n framedDistance,\n radiusOf,\n type Angle,\n type Bounds,\n type ViewWord,\n} from '../frame.js';\nimport {\n HDRI_PRESETS,\n PEDESTAL_PRESETS,\n PRESETS_VERSION,\n type HdriPresetName,\n} from '../presets/catalog.gen.js';\nimport {\n ROOM_PRESETS,\n type RoomPresetLighting,\n type RoomPresetName,\n} from '../presets/rooms.gen.js';\nimport { emptyRecorded, type Recorded } from '../set.js';\nimport { SDK_VERSION } from '../version.js';\n\nconst DOCS = 'https://bakery3.com/docs/catalog';\nconst PRESET_LIBRARY = 'https://cdn.bakery3.com/presets';\nconst SKIPS_KEPT = 50;\n/**\n * After this many products, a run where most of them could not be imported\n * is a wrong base URL, not a bad model, and stops.\n */\nconst BREAKER_AFTER = 8;\nconst BREAKER_SHARE = 0.5;\n/** A clip is at most this long, and this many frames a second. */\nconst MAX_SECONDS = 30;\nconst MAX_FPS = 60;\n\n// ---------------------------------------------------------------------------\n// What the developer types\n// ---------------------------------------------------------------------------\n\n/**\n * Where to look from: a word, or degrees. `'room'` is the framing a preset\n * room was published with, from level or above: never looking up at the\n * product.\n */\nexport type View = ViewWord | 'room' | Angle;\n\nexport type BatchEnvironment = {\n /** A studio or a sky from the preset library. */\n preset?: HdriPresetName;\n /**\n * Or an HDRI of your own: a public https URL of a .hdr or .exr, imported\n * like the models.\n */\n url?: string;\n /** How strongly it lights the product. Default 1 (0.6 for the default studio). */\n intensity?: number;\n /** Turn the environment about the vertical, in degrees. */\n rotationDeg?: number;\n};\n\nexport type BatchRoom = {\n /** A room from the preset library. */\n preset: RoomPresetName;\n /** Default: the mode the room was designed under. */\n mode?: RoomPresetLighting;\n /**\n * What the product stands on. `'auto'` (the default) goes by its size: the\n * room's own pedestal for a small thing, the low plinth for a mid-sized\n * one, the floor for furniture and anything that would overhang. `'own'`\n * and `'floor'` say so yourself.\n */\n stand?: 'auto' | 'own' | 'floor';\n /**\n * Where the room's own camera sees the product from, in degrees from the\n * product's front. The room is turned about the product to make it so.\n * Default 30: a three-quarter view from the side the room is open to.\n */\n viewFromDeg?: number;\n};\n\n/**\n * What every shot can say about how it is taken. Set on the run for all of\n * them, on a product for its own, on a shot for that one; the nearest wins.\n */\nexport type ShotSettings = {\n /**\n * A preset room to stand in. `null` says no room, where a wider layer had\n * one.\n */\n room?: BatchRoom | null;\n /**\n * The light and backdrop when there is no room. Default: the\n * `studio_small_03` preset at 0.6.\n */\n environment?: BatchEnvironment;\n /**\n * `'transparent'` (the default, with a traced shadow), a `#rrggbb`, or\n * `'environment'`. A video has no alpha: `'transparent'` is `#f4f4f5` there\n * (a `png-sequence` keeps it).\n */\n background?: 'transparent' | 'environment' | `#${string}`;\n /** Default `'studio'`. */\n quality?: QualityPreset;\n /** Pixels. Default: the quality preset's long edge, square. */\n width?: number;\n height?: number;\n /**\n * `png` (the default), `jpeg` or `webp` for an image; `mp4` (the default),\n * `webm` or `png-sequence` (every frame a PNG with alpha, in one tar) for a\n * video.\n */\n format?: OutputSpec['format'];\n /** JPEG/WebP only, 1 to 100. */\n imageQuality?: number;\n /**\n * Vertical field of view in degrees. Default 30, or the room's own lens in\n * a room.\n */\n fov?: number;\n /**\n * Room around the model, as a share of its size. Default 0.12, or 0.9 in\n * a room.\n */\n margin?: number;\n /** Frames a second, for a video. Default 30, at most 60. */\n fps?: number;\n /** Renderer settings beyond the quality preset. */\n advanced?: RenderSpec['advanced'];\n /**\n * How the pictures are developed. Default: sRGB, ACES filmic, exposure 1\n * (a room's own exposure in a room).\n */\n color?: Partial<ColorSpec>;\n};\n\nexport type ImageShot = ShotSettings & {\n kind?: 'image';\n /** Default: the view's word, or `az35-el14` for degrees. Ends the item's key. */\n id?: string;\n /** Where from. Default `'three-quarter'`, or `'room'` in a room. */\n view?: View;\n /**\n * Instead of a view: a camera inside the model, by its node name, as the\n * file has it.\n */\n camera?: string;\n};\n\nexport type VideoShot = ShotSettings & {\n kind: 'video';\n /** Default `orbit-<from>-<to>`. */\n id?: string;\n /** The camera is carried from here. */\n from: View;\n /**\n * To here, azimuth as written: `{ azimuthDeg: 395 }` from 35 is a full\n * turn.\n */\n to: View;\n /** Default 4. At most 30. */\n seconds?: number;\n};\n\n/** A word or an angle is an image from that view. */\nexport type Shot = ViewWord | 'room' | Angle | ImageShot | VideoShot;\n\nexport type BatchProduct = ShotSettings & {\n /** Starts every shot's key. Stable across re-runs. */\n id: string;\n /** A public https URL of a binary glTF (.glb). */\n url: string;\n /** This product's shots, instead of the run's. */\n shots?: Shot[];\n /** Echoed on every shot of this product, its webhooks and the ledger. */\n metadata?: Record<string, unknown>;\n};\n\nexport type RenderBatchProgress = BatchProgress & {\n /** The product just recorded, or skipped. */\n product: string;\n /** Products recorded so far. */\n products: number;\n /** Shots recorded so far, clips included. */\n images: number;\n /** Products skipped so far. */\n skipped: number;\n};\n\n/** A product left out of a run, with the reason. */\nexport type ProductSkip = { id: string; url: string; error: Bakery3Error };\n\nexport type RenderBatchRecorded = Recorded & {\n /**\n * Products whose model could not be imported or read. The run went on\n * without them.\n */\n skipped: number;\n /** The first of those, with their reasons. */\n skips: ProductSkip[];\n};\n\nexport type RenderBatchOptions = ShotSettings & {\n /** Names the run. The same key re-opens it while it is unfinished. */\n key: string;\n /** A label for the console. Default: the key. */\n name?: string;\n /**\n * An array, a generator, a database cursor. Pulled as it is needed, never\n * collected.\n */\n products: Iterable<BatchProduct> | AsyncIterable<BatchProduct>;\n /**\n * Every product's shots, unless it has its own. Default: one image,\n * `'three-quarter'` (`'room'` in a room).\n */\n shots?: Shot[];\n /**\n * Appended to every key as `@version`. Bump it to trace again what already\n * rendered.\n */\n version?: string;\n /** The ceiling for the whole run, in USD. */\n maxCost: number;\n /** A ceiling per shot, in USD. A shot quoted above it is refused. */\n maxCostPerImage?: number;\n /**\n * `'batch'` (the default) never runs ahead of a person in a configurator;\n * `'normal'` is the API's ordinary lane.\n */\n lane?: 'batch' | 'normal';\n /** Fewer parallel shots than the plan allows, for a gentler budget. */\n maxParallel?: number;\n /** Imports in flight at once. Default 4, at most 16. */\n concurrency?: number;\n /** Called after each product is recorded or skipped. */\n onProgress?: (progress: RenderBatchProgress) => void;\n /**\n * Stops between products. What was recorded stays admitted; call again to\n * go on.\n */\n signal?: AbortSignal;\n};\n\n// ---------------------------------------------------------------------------\n// The recorder\n// ---------------------------------------------------------------------------\n\n/** The slice of the client a recording drives. */\nexport type BatchHost = {\n importAsset(body: {\n url: string;\n kind?: AssetImportKind;\n }): Promise<AssetImportResponse>;\n};\n\nexport type RenderBatchRecording = RenderBatchRecorded & {\n estimated: number;\n maximum: number;\n};\n\nexport type RecordBatchOptions = {\n /** Price, admit nothing. */\n dryRun?: boolean;\n /** Settings that beat every layer: what a test run forces. */\n force?: ShotSettings & { version?: string; seconds?: number };\n};\n\nexport async function recordBatch(\n host: BatchHost,\n batch: Batch,\n options: Omit<RenderBatchOptions, 'maxCost'>,\n { dryRun = false, force }: RecordBatchOptions = {},\n): Promise<RenderBatchRecording> {\n validateShots(options.shots ?? [], 'the run');\n const environments = new EnvironmentCache(host);\n\n const tally: RenderBatchRecording = {\n ...emptyRecorded(),\n skipped: 0,\n skips: [],\n estimated: 0,\n maximum: 0,\n };\n const seen = new Set<string>();\n let attempted = 0;\n\n const one = async (product: BatchProduct): Promise<void> => {\n let items: BatchItemRequest[];\n try {\n if (product.shots)\n validateShots(product.shots, `product \"${product.id}\"`);\n const imported = await host.importAsset({\n url: product.url,\n kind: 'scene',\n });\n items = await itemsOf(product, imported, options, environments, force);\n } catch (error) {\n // One model that will not import, or cannot be used as asked, is that\n // product's problem. A night's run does not stop for it; it is listed,\n // and the rest go on. Anything else is a verdict on the caller (the\n // plan, the key, a shot that is not a shot), would be the same for\n // every product, and stops the run.\n if (\n !(error instanceof Bakery3Error) ||\n (error.code !== 'ImportFailed' && error.code !== 'ImportRefused')\n )\n throw error;\n attempted++;\n tally.skipped++;\n if (tally.skips.length < SKIPS_KEPT)\n tally.skips.push({ id: product.id, url: product.url, error });\n if (\n attempted >= BREAKER_AFTER &&\n tally.skipped / attempted > BREAKER_SHARE\n )\n throw mostlyFailing(tally, attempted);\n report(product.id);\n return;\n }\n attempted++;\n\n let outcomes: BatchItemOutcome[];\n if (dryRun) {\n outcomes = await batch.quote(items);\n } else {\n for (const item of items) batch.add(item);\n outcomes = await batch.flush();\n }\n tally.variants++;\n tally.images += items.length;\n for (const outcome of outcomes) {\n if (outcome.error) {\n tally.refused++;\n if (tally.refusals.length < SKIPS_KEPT)\n tally.refusals.push({ key: outcome.key, error: outcome.error });\n } else if (outcome.adopted) tally.adopted++;\n else {\n tally.estimated += outcome.estimatedCost;\n tally.maximum += outcome.maximumCost;\n }\n }\n report(product.id);\n };\n\n const report = (product: string) =>\n options.onProgress?.({\n ...batch.progress(),\n product,\n products: tally.variants,\n images: tally.images,\n skipped: tally.skipped,\n });\n\n // A window of `concurrency` products in flight, refilled as each settles.\n // The list is pulled only as a slot frees, so a cursor over a million rows\n // holds `concurrency` of them here.\n const limit = Math.max(1, Math.min(16, Math.floor(options.concurrency ?? 4)));\n const flying = new Set<Promise<void>>();\n let failure: unknown;\n for await (const product of options.products) {\n if (failure) break;\n if (options.signal?.aborted) {\n failure = options.signal.reason ?? abortError();\n break;\n }\n validateProduct(product, seen);\n const task = one(product)\n .catch((error) => {\n failure ??= error;\n })\n .finally(() => flying.delete(task));\n flying.add(task);\n if (flying.size >= limit) await Promise.race(flying);\n }\n await Promise.all(flying);\n if (failure) throw failure;\n\n tally.estimated = Math.round(tally.estimated * 1e4) / 1e4;\n tally.maximum = Math.round(tally.maximum * 1e4) / 1e4;\n return tally;\n}\n\n// ---------------------------------------------------------------------------\n// One product's items: one per shot\n// ---------------------------------------------------------------------------\n\n/** A shot with every layer folded in. */\ntype ResolvedShot = ShotSettings & {\n id: string;\n kind: 'image' | 'video';\n view?: View;\n camera?: string;\n from?: View;\n to?: View;\n seconds?: number;\n};\n\nasync function itemsOf(\n product: BatchProduct,\n imported: AssetImportResponse,\n run: Omit<RenderBatchOptions, 'maxCost'>,\n environments: EnvironmentCache,\n force: RecordBatchOptions['force'],\n): Promise<BatchItemRequest[]> {\n const facts = imported.facts;\n if (!facts)\n throw unreadable(product, 'The import returned no facts about the model.');\n const blocking = facts.issues.find((issue) => issue.severity === 'error');\n if (blocking) throw unreadable(product, blocking.message);\n if (!facts.bounds)\n throw unreadable(\n product,\n 'The model has no geometry with bounds, so there is nowhere to point a camera.',\n );\n const bounds = facts.bounds;\n\n const runSettings = settingsOf(run);\n const productSettings = settingsOf(product);\n const shots = (product.shots ?? run.shots ?? []).map((shot) =>\n resolveShot(shot, runSettings, productSettings, force),\n );\n if (!shots.length) {\n const inRoom = layered('room', runSettings, productSettings, force) != null;\n shots.push(\n resolveShot(\n inRoom ? 'room' : 'three-quarter',\n runSettings,\n productSettings,\n force,\n ),\n );\n }\n\n const counts = { info: 0, warning: 0, error: 0 };\n for (const issue of facts.issues) counts[issue.severity]++;\n const version = force?.version ?? run.version;\n\n const items: BatchItemRequest[] = [];\n for (const shot of shots) {\n const quality = shot.quality ?? 'studio';\n const edge = QUALITY[quality].defaultLongEdge;\n const video = shot.kind === 'video';\n const output: OutputSpec = {\n width: shot.width ?? edge,\n height: shot.height ?? edge,\n format: shot.format ?? (video ? 'mp4' : 'png'),\n ...(shot.imageQuality !== undefined\n ? { quality: shot.imageQuality }\n : {}),\n };\n if (video !== isClipFormat(output.format)) {\n throw new Bakery3Error({\n code: 'InvalidRequest',\n message: `Shot \"${shot.id}\" of ${product.id} is ${video ? 'a video in a still' : 'an image in a video'} format (${output.format}).`,\n fix: 'A video is mp4, webm or png-sequence; an image is png, jpeg or webp. Leave `format` out for the default.',\n path: `${product.id}/${shot.id}`,\n docs: `${DOCS}#shots`,\n });\n }\n const aspect = output.width / output.height;\n\n const room = shot.room ? roomFor(shot.room, bounds) : undefined;\n // A video has no alpha, so a transparent background would show the raw\n // studio map behind the product. A video stands on a plain backdrop\n // instead, with its shadow, unless the shot says what it stands on. A\n // png-sequence keeps its alpha, as a still does.\n const background =\n isVideoFormat(output.format) &&\n (shot.background ?? 'transparent') === 'transparent'\n ? CLIP_BACKDROP\n : shot.background;\n const environment = room\n ? roomBackground()\n : await environments.get(shot.environment, background);\n const color: ColorSpec = {\n outputColorSpace: 'srgb',\n toneMapping: 'aces-filmic',\n toneMappingExposure: room ? room.exposure : 1,\n ...shot.color,\n };\n const lens = { fov: shot.fov, margin: shot.margin };\n\n let camera: CameraSpec;\n let animation: AnimationSpec | undefined;\n if (video) {\n const from = angleFor(shot.from!, room, product, shot.id);\n const to = angleFor(shot.to!, room, product, shot.id);\n const fps = Math.min(MAX_FPS, Math.max(1, Math.round(shot.fps ?? 30)));\n const seconds = Math.min(MAX_SECONDS, shot.seconds ?? 4);\n const frameCount = Math.max(2, Math.round(seconds * fps));\n const positions: number[] = [];\n const quaternions: number[] = [];\n let first: CameraSpec | undefined;\n for (let frame = 0; frame < frameCount; frame++) {\n const at = angleBetween(from, to, frame / (frameCount - 1));\n const spec = cameraForAngle(at, bounds, aspect, lens, room, shot.id);\n first ??= spec;\n positions.push(...spec.position);\n quaternions.push(...spec.quaternion);\n }\n camera = first!;\n animation = {\n fps,\n frameCount,\n channels: [\n {\n target: { type: 'camera' },\n property: 'position',\n size: 3,\n values: positions,\n },\n {\n target: { type: 'camera' },\n property: 'quaternion',\n size: 4,\n values: quaternions,\n },\n ],\n };\n } else if (shot.camera) {\n camera = ownCamera(shot.camera, facts, aspect, product, shot.id);\n } else {\n camera = cameraForAngle(\n angleFor(\n shot.view ?? (room ? 'room' : 'three-quarter'),\n room,\n product,\n shot.id,\n ),\n bounds,\n aspect,\n lens,\n room,\n shot.id,\n );\n }\n\n const manifest: SceneManifest = {\n protocolVersion: protocolVersionFor({\n ...(room ? { room: room.spec } : {}),\n ...(animation ? { animation } : {}),\n }),\n sdkVersion: SDK_VERSION,\n sceneAsset: imported.hash,\n camera,\n environment,\n color,\n ...(room ? { room: room.spec } : {}),\n ...(animation ? { animation } : {}),\n compatibility: { score: 1, issues: facts.issues, counts },\n stats: {\n triangles: facts.triangles + (room?.triangles ?? 0),\n // A room is priced by how enclosed and how full it is, measured when\n // it was published; the product adds one object to it. Without a room\n // the shot is an open set, which needs saying nothing.\n ...(room?.complexity\n ? {\n enclosure: room.complexity.enclosure,\n objects: room.complexity.objects + 1,\n }\n : {}),\n },\n source: { renderer: 'catalog' },\n };\n\n const key = `${product.id}/${shot.id}${version ? `@${version}` : ''}`;\n if (key.length > 200)\n throw unreadable(\n product,\n `The key \"${key.slice(0, 40)}…\" is over 200 characters. Use shorter ids.`,\n );\n items.push({\n key,\n spec: {\n manifest,\n quality,\n output,\n ...(shot.advanced ? { advanced: shot.advanced } : {}),\n ...(video ? { preview: false } : {}),\n },\n metadata: {\n ...product.metadata,\n variant: product.id,\n shot: shot.id,\n kind: shot.kind,\n },\n ...(run.maxCostPerImage !== undefined\n ? { maxCost: run.maxCostPerImage }\n : {}),\n });\n }\n return items;\n}\n\n// ---------------------------------------------------------------------------\n// Settings, in layers\n// ---------------------------------------------------------------------------\n\nconst SETTING_KEYS = [\n 'room',\n 'environment',\n 'background',\n 'quality',\n 'width',\n 'height',\n 'format',\n 'imageQuality',\n 'fov',\n 'margin',\n 'fps',\n 'advanced',\n 'color',\n] as const satisfies ReadonlyArray<keyof ShotSettings>;\n\nfunction settingsOf(source: ShotSettings): ShotSettings {\n const out: ShotSettings = {};\n for (const key of SETTING_KEYS)\n if (source[key] !== undefined)\n (out as Record<string, unknown>)[key] = source[key];\n return out;\n}\n\n/**\n * The nearest layer that says anything about `key`, `null` included: a\n * product's `room: null` beats the run's room.\n */\nfunction layered<K extends keyof ShotSettings>(\n key: K,\n ...layers: Array<ShotSettings | undefined>\n): ShotSettings[K] {\n for (let i = layers.length - 1; i >= 0; i--) {\n const value = layers[i]?.[key];\n if (value !== undefined) return value;\n }\n return undefined;\n}\n\n/** A word or a bare angle, as the image shot it stands for. */\nfunction shotOf(shot: Shot): ImageShot | VideoShot {\n if (typeof shot === 'string') return { view: shot };\n if (\n shot &&\n typeof shot === 'object' &&\n 'azimuthDeg' in shot &&\n !('view' in shot) &&\n !('kind' in shot) &&\n !('camera' in shot)\n ) {\n const { azimuthDeg, elevationDeg, ...rest } = shot as Angle & ImageShot;\n return {\n ...rest,\n view: {\n azimuthDeg,\n ...(elevationDeg !== undefined ? { elevationDeg } : {}),\n },\n };\n }\n return shot as ImageShot | VideoShot;\n}\n\nfunction resolveShot(\n shot: Shot,\n run: ShotSettings,\n product: ShotSettings,\n force: RecordBatchOptions['force'],\n): ResolvedShot {\n const own = shotOf(shot);\n const settings: ShotSettings = {};\n for (const key of SETTING_KEYS) {\n const value = layered(key, run, product, settingsOf(own), force);\n if (value !== undefined) (settings as Record<string, unknown>)[key] = value;\n }\n if (own.kind === 'video') {\n return {\n ...settings,\n kind: 'video',\n id: own.id ?? `orbit-${viewName(own.from)}-${viewName(own.to)}`,\n from: own.from,\n to: own.to,\n seconds:\n force?.seconds !== undefined\n ? Math.min(force.seconds, own.seconds ?? 4)\n : own.seconds,\n };\n }\n const image = own as ImageShot;\n return {\n ...settings,\n kind: 'image',\n id:\n image.id ??\n (image.camera\n ? image.camera\n : viewName(image.view ?? (settings.room ? 'room' : 'three-quarter'))),\n ...(image.view !== undefined ? { view: image.view } : {}),\n ...(image.camera !== undefined ? { camera: image.camera } : {}),\n };\n}\n\nfunction viewName(view: View): string {\n if (typeof view === 'string') return view;\n const el = view.elevationDeg;\n return `az${Math.round(view.azimuthDeg)}${el !== undefined ? `-el${Math.round(el)}` : ''}`.replace(\n '--',\n '-neg',\n );\n}\n\n// ---------------------------------------------------------------------------\n// Cameras\n// ---------------------------------------------------------------------------\n\ntype Room = ReturnType<typeof roomFor>;\n\n/** A view as an angle, the room's published direction for `'room'`. */\nfunction angleFor(\n view: View,\n room: Room | undefined,\n product: BatchProduct,\n shot: string,\n): Angle {\n if (view === 'room') {\n if (!room) {\n throw new Bakery3Error({\n code: 'InvalidRequest',\n message: `Shot \"${shot}\" of ${product.id} looks from 'room', but has no room.`,\n fix: \"Set `room: { preset: … }` on the run, the product or the shot, or use a view such as 'three-quarter'.\",\n path: `${product.id}/${shot}`,\n docs: `${DOCS}#angles`,\n });\n }\n return room.published;\n }\n const angle = angleOf(view);\n if (angle) return angle;\n throw new Bakery3Error({\n code: 'InvalidRequest',\n message: `Shot \"${shot}\" of ${product.id}: \"${typeof view === 'string' ? view : JSON.stringify(view)}\" is not a view.`,\n fix: `A view is one of ${Object.keys(VIEW_WORDS).join(', ')}, room, or \\`{ azimuthDeg, elevationDeg? }\\`. For a camera inside the model, use \\`camera: '<node name>'\\`.`,\n path: `${product.id}/${shot}`,\n docs: `${DOCS}#angles`,\n });\n}\n\nfunction cameraForAngle(\n angle: Angle,\n bounds: Bounds,\n aspect: number,\n lens: { fov?: number; margin?: number },\n room: Room | undefined,\n name: string,\n): CameraSpec {\n if (room) return room.camera(angle, aspect, lens, name);\n return framedCamera(\n bounds,\n {\n id: name,\n ...angle,\n ...(lens.fov !== undefined ? { fov: lens.fov } : {}),\n ...(lens.margin !== undefined ? { margin: lens.margin } : {}),\n },\n aspect,\n );\n}\n\n/** A camera the model carries, at the output's aspect. */\nfunction ownCamera(\n name: string,\n facts: GlbFacts,\n aspect: number,\n product: BatchProduct,\n shot: string,\n): CameraSpec {\n const own = facts.cameras.find((camera) => camera.name === name);\n if (own)\n return {\n ...own.camera,\n ...(own.camera.type === 'perspective' ? { aspect } : {}),\n name: shot,\n } as CameraSpec;\n const names = facts.cameras.map((camera) => camera.name);\n throw new Bakery3Error({\n code: 'ImportFailed',\n message: `Shot \"${shot}\": ${product.id}'s model has no camera named \"${name}\".`,\n fix: names.length\n ? `Its cameras are: ${names.slice(0, 8).join(', ')}.`\n : 'It carries no cameras. Use a view instead: an angle is framed from the model itself.',\n path: `${product.id}/${shot}`,\n docs: `${DOCS}#angles`,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Light: an environment, or a room\n// ---------------------------------------------------------------------------\n\n/**\n * What a product stands in when nothing is said. `studio_small_03` at full\n * strength clips a white product to paper (a ceramic vase or a lacquered\n * table top loses its form shading); at 0.6 they keep it and a dark sofa is\n * still well lit. An environment the caller names is used at the strength\n * they give, 1 unless they say.\n */\nconst DEFAULT_ENVIRONMENT: BatchEnvironment = {\n preset: 'studio_small_03',\n intensity: 0.6,\n};\n/**\n * What a clip stands on when nothing is said: a light neutral, the same one\n * a preview is flattened onto.\n */\nconst CLIP_BACKDROP = '#f4f4f5' as const;\n\n/** One import per distinct HDRI URL, however many shots share it. */\nclass EnvironmentCache {\n private readonly hashes = new Map<string, Promise<string>>();\n constructor(private readonly host: BatchHost) {}\n\n async get(\n chosen: BatchEnvironment | undefined,\n background: ShotSettings['background'],\n ): Promise<EnvironmentSpec> {\n const environment = chosen ?? DEFAULT_ENVIRONMENT;\n if (environment.preset && environment.url) {\n throw new Bakery3Error({\n code: 'InvalidRequest',\n message: 'environment takes a `preset` or a `url`, not both.',\n docs: `${DOCS}#light`,\n });\n }\n let hdri: string;\n if (environment.url) {\n // Your own HDRI arrives at the renderer as a hash, like every other\n // asset. Only the preset library is ever named by URL.\n const url = environment.url;\n let pending = this.hashes.get(url);\n if (!pending) {\n pending = this.host\n .importAsset({ url, kind: 'hdri' })\n .then((imported) => imported.hash);\n this.hashes.set(url, pending);\n pending.catch(() => this.hashes.delete(url));\n }\n hdri = await pending;\n } else {\n const name = environment.preset ?? 'studio_small_03';\n if (!(name in HDRI_PRESETS)) {\n throw new Bakery3Error({\n code: 'InvalidRequest',\n message: `There is no environment preset \"${name}\".`,\n fix: `The presets are: ${Object.keys(HDRI_PRESETS).join(', ')}.`,\n docs: `${DOCS}#light`,\n });\n }\n hdri = `${PRESET_LIBRARY}/v${PRESETS_VERSION}/hdri/${name}/render.exr`;\n }\n return {\n hdri,\n ...(environment.intensity !== undefined\n ? { intensity: environment.intensity }\n : {}),\n ...(environment.rotationDeg\n ? {\n rotation: [0, (environment.rotationDeg * Math.PI) / 180, 0] as Vec3,\n }\n : {}),\n background: backgroundOf(background),\n };\n }\n}\n\nfunction backgroundOf(\n background: ShotSettings['background'],\n): NonNullable<EnvironmentSpec['background']> {\n const chosen = background ?? 'transparent';\n if (chosen === 'transparent') return { type: 'transparent' };\n if (chosen === 'environment') return { type: 'environment' };\n if (!/^#[0-9a-f]{6}$/i.test(chosen)) {\n throw new Bakery3Error({\n code: 'InvalidRequest',\n message: `background \"${chosen}\" is not 'transparent', 'environment' or a #rrggbb color.`,\n docs: `${DOCS}#light`,\n });\n }\n return { type: 'color', color: chosen };\n}\n\n/** In a room the room is the background; what no wall covers is transparent. */\nfunction roomBackground(): EnvironmentSpec {\n return { background: { type: 'transparent' } };\n}\n\n/**\n * What a product stands on follows its size, by the rule the rooms were\n * designed around: a small thing on the room's own pedestal, a mid-sized\n * piece on the low wide plinth, furniture and anything that would overhang\n * on the floor. A sofa on a meter-high column is a picture nobody wanted.\n */\nconst STAND_RULES = {\n fit: 0.85,\n tallFrom: 0.6,\n smallHeight: 0.6,\n plinthHeight: 1.0,\n} as const;\nconst PLINTH = 'pedestal_plinth';\n/** Room to see the room in: the product fills about half the frame. */\nconst ROOM_MARGIN = 0.9;\n/** A camera is kept this far inside the walls, the floor and the ceiling. */\nconst WALL_CLEARANCE = 0.3;\n/** The least room left around a product when a wall decides the distance. */\nconst FIT_MARGIN = 0.12;\n/** The widest lens a wall can force. */\nconst MAX_ROOM_FOV = 100;\n/**\n * The lowest the `'room'` view is taken from, in degrees above the product's\n * middle. A room's published camera is the hero shot of its own stand, and\n * three look up at it (living_evening 14 degrees, gallery_day 11,\n * dining_golden 5). Aimed at a real product along that line, the camera\n * stood below the surface a short product stands on, so the stand's top and\n * the product's base were hidden, and a sofa on the floor was shot from\n * near the floor through a wide lens. Level keeps every room's direction and\n * distance and changes only those three.\n */\nconst ROOM_MIN_ELEVATION_DEG = 0;\n\n/**\n * The vertical field of view that fits a sphere of `radius` at `distance`,\n * in the narrower of the two axes.\n */\nfunction fovToFit(radius: number, distance: number, aspect: number): number {\n const half = Math.asin(Math.min(1, radius / distance));\n const vertical = aspect >= 1 ? half : Math.atan(Math.tan(half) / aspect);\n return (2 * vertical * 180) / Math.PI;\n}\n\nfunction standFor(\n room: BatchRoom,\n info: (typeof ROOM_PRESETS)[RoomPresetName],\n bounds: Bounds,\n): { pedestal?: RoomPresetSpec['pedestal']; top: number } {\n const footprint = Math.max(\n bounds.max[0] - bounds.min[0],\n bounds.max[2] - bounds.min[2],\n );\n const height = bounds.max[1] - bounds.min[1];\n const fits = (\n size: { x: number; y: number; z: number } | null | undefined,\n ): boolean => {\n if (!size) return false;\n if (footprint > STAND_RULES.fit * Math.min(size.x, size.z)) return false;\n return (\n height <=\n (size.y >= STAND_RULES.tallFrom\n ? STAND_RULES.smallHeight\n : STAND_RULES.plinthHeight)\n );\n };\n const choice = room.stand ?? 'auto';\n if (choice === 'own' || (choice === 'auto' && fits(info.stand.size)))\n return { top: info.stand.top };\n if (choice === 'auto' && fits(PEDESTAL_PRESETS[PLINTH].size))\n return { pedestal: { type: PLINTH }, top: PEDESTAL_PRESETS[PLINTH].size.y };\n return { pedestal: null, top: 0 };\n}\n\n/**\n * Put the room around the product, since the product cannot be moved into\n * the room: a model by URL has none of the ids a transform is addressed by.\n * The room is turned about its stand so its published camera sees the\n * product from `viewFromDeg`, and placed so the stand's top (or the floor)\n * is under the product's base. What the renderer receives is one matrix.\n */\nfunction roomFor(room: BatchRoom, bounds: Bounds) {\n const info = ROOM_PRESETS[room.preset];\n if (!info) {\n throw new Bakery3Error({\n code: 'InvalidRequest',\n message: `There is no room preset \"${room.preset}\".`,\n fix: `The rooms are: ${Object.keys(ROOM_PRESETS).join(', ')}.`,\n docs: `${DOCS}#light`,\n });\n }\n const lighting = room.mode ?? info.lighting;\n const standing = standFor(room, info, bounds);\n const stand: Vec3 = [info.stand.x, standing.top, info.stand.z];\n const base: Vec3 = [\n (bounds.min[0] + bounds.max[0]) / 2,\n bounds.min[1],\n (bounds.min[2] + bounds.max[2]) / 2,\n ];\n const size: Vec3 = [\n bounds.max[0] - bounds.min[0],\n bounds.max[1] - bounds.min[1],\n bounds.max[2] - bounds.min[2],\n ];\n const radius = radiusOf(bounds);\n\n // The published line, from the stand to the camera, as an angle and a length.\n const line: Vec3 = [\n info.camera.position[0] - info.camera.target[0],\n info.camera.position[1] - info.camera.target[1],\n info.camera.position[2] - info.camera.target[2],\n ];\n const designed = Math.hypot(line[0], line[1], line[2]);\n const publishedAzimuth = Math.atan2(line[0], line[2]);\n const viewFrom = ((room.viewFromDeg ?? 30) * Math.PI) / 180;\n const theta = viewFrom - publishedAzimuth;\n const c = Math.cos(theta);\n const s = Math.sin(theta);\n /** A point in the room's frame, in the product's. */\n const place = ([x, y, z]: readonly [number, number, number]): Vec3 => {\n const dx = x - stand[0];\n const dz = z - stand[2];\n return [\n base[0] + dx * c + dz * s,\n base[1] + (y - stand[1]),\n base[2] - dx * s + dz * c,\n ];\n };\n const origin = place([0, 0, 0]);\n const matrix: Matrix4 = [\n c,\n 0,\n -s,\n 0,\n 0,\n 1,\n 0,\n 0,\n s,\n 0,\n c,\n 0,\n origin[0],\n origin[1],\n origin[2],\n 1,\n ];\n\n const spec: RoomPresetSpec = {\n name: room.preset,\n build: info.build,\n lighting,\n ...(standing.pedestal !== undefined ? { pedestal: standing.pedestal } : {}),\n matrix,\n };\n const published: Angle = {\n azimuthDeg: (viewFrom * 180) / Math.PI,\n elevationDeg: Math.max(\n ROOM_MIN_ELEVATION_DEG,\n (Math.atan2(line[1], Math.hypot(line[0], line[2])) * 180) / Math.PI,\n ),\n };\n /**\n * The room's published camera: a 36 mm horizontal sensor, so the vertical\n * FOV follows the aspect.\n */\n const lensFov = (aspect: number) =>\n (2 *\n Math.atan((aspect >= 1 ? 36 / aspect : 36) / (2 * info.camera.lensMm)) *\n 180) /\n Math.PI;\n\n return {\n spec,\n triangles: info.preview.triangles,\n complexity: info.complexity,\n exposure: info.exposure[lighting],\n published,\n /**\n * A camera in the room from any angle: framed as in the open, from as\n * far as the published camera stood when that is the view, and never\n * behind a wall, the floor or the ceiling.\n */\n camera(\n angle: Angle,\n aspect: number,\n lens: { fov?: number; margin?: number },\n name: string,\n ): CameraSpec {\n const fov = lens.fov ?? lensFov(aspect);\n const center = centerOf(bounds);\n const direction = directionOf(angle);\n const framed = framedDistance(\n radius,\n fov,\n aspect,\n lens.margin ?? ROOM_MARGIN,\n );\n const isPublished =\n Math.abs(angle.azimuthDeg - published.azimuthDeg) < 1e-6 &&\n Math.abs((angle.elevationDeg ?? 12) - published.elevationDeg!) < 1e-6;\n\n // The direction in the room's own frame, to find the wall it meets.\n const rx = direction[0] * c - direction[2] * s;\n const rz = direction[0] * s + direction[2] * c;\n const ry = direction[1];\n const from: Vec3 = [stand[0], stand[1] + size[1] / 2, stand[2]];\n const half = [\n info.size.width / 2 - WALL_CLEARANCE,\n info.size.depth / 2 - WALL_CLEARANCE,\n ];\n let reach = Infinity;\n if (rx !== 0)\n reach = Math.min(\n reach,\n ((rx > 0 ? half[0]! : -half[0]!) - from[0]) / rx,\n );\n if (rz !== 0)\n reach = Math.min(\n reach,\n ((rz > 0 ? half[1]! : -half[1]!) - from[2]) / rz,\n );\n if (ry > 0)\n reach = Math.min(\n reach,\n (info.size.height - WALL_CLEARANCE - from[1]) / ry,\n );\n if (ry < 0) reach = Math.min(reach, (WALL_CLEARANCE - from[1]) / ry);\n\n const wanted = Math.max(isPublished ? designed : 0, framed);\n const distance = Math.max(radius * 1.2, Math.min(wanted, reach));\n // A photographer with their back to the wall takes a wider lens. The\n // product still fits, with a little room, at whatever the walls allow.\n const lensFit =\n distance < framed\n ? fovToFit(radius * (1 + FIT_MARGIN), distance, aspect)\n : fov;\n return cameraAt(\n center,\n radius,\n direction,\n distance,\n Math.min(MAX_ROOM_FOV, Math.max(fov, lensFit)),\n aspect,\n name,\n );\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n\nfunction validateShots(shots: Shot[], where: string): void {\n const ids = new Set<string>();\n shots.forEach((shot, index) => {\n if (!shot || (typeof shot !== 'string' && typeof shot !== 'object'))\n throw badShot(where, index, 'is not a shot');\n const own = shotOf(shot);\n if (own.kind === 'video') {\n if (angleOf(own.from) === null && own.from !== 'room')\n throw badShot(where, index, '`from` is not a view');\n if (angleOf(own.to) === null && own.to !== 'room')\n throw badShot(where, index, '`to` is not a view');\n if (\n own.seconds !== undefined &&\n !(own.seconds > 0 && own.seconds <= MAX_SECONDS)\n )\n throw badShot(\n where,\n index,\n `\\`seconds\\` is outside 0 to ${MAX_SECONDS}`,\n );\n } else if (own.kind !== undefined && own.kind !== 'image') {\n throw badShot(\n where,\n index,\n `kind \"${String(own.kind)}\" is not 'image' or 'video'`,\n );\n } else if (\n (own as ImageShot).view !== undefined &&\n (own as ImageShot).camera !== undefined\n ) {\n throw badShot(where, index, 'has both a `view` and a `camera`');\n }\n const id =\n own.id ??\n (own.kind === 'video'\n ? `orbit-${viewName(own.from)}-${viewName(own.to)}`\n : ((own as ImageShot).camera ??\n ((own as ImageShot).view !== undefined\n ? viewName((own as ImageShot).view!)\n : undefined)));\n if (id !== undefined) {\n if (!/^[A-Za-z0-9_.-]{1,60}$/.test(id))\n throw badShot(\n where,\n index,\n `id \"${id}\" is not 1 to 60 letters, digits, dots, dashes or underscores`,\n );\n if (ids.has(id)) throw badShot(where, index, `id \"${id}\" is used twice`);\n ids.add(id);\n }\n });\n}\n\nfunction badShot(where: string, index: number, what: string): Bakery3Error {\n return new Bakery3Error({\n code: 'InvalidRequest',\n message: `Shot ${index + 1} of ${where} ${what}.`,\n why: 'A shot is a word, `{ view }`, or `{ kind: \"video\", from, to }`, plus settings, and its id ends the picture’s key.',\n docs: `${DOCS}#shots`,\n });\n}\n\nfunction validateProduct(product: BatchProduct, seen: Set<string>): void {\n if (\n !product ||\n typeof product.id !== 'string' ||\n !product.id ||\n typeof product.url !== 'string' ||\n !product.url\n ) {\n throw new Bakery3Error({\n code: 'InvalidRequest',\n message: 'Every product needs an `id` and a `url`.',\n why: 'The id starts every shot’s key: it is what a re-run adopts by and what a failure is reported under.',\n docs: DOCS,\n });\n }\n if (seen.has(product.id)) {\n throw new Bakery3Error({\n code: 'InvalidRequest',\n message: `Two products are called \"${product.id}\".`,\n why: 'The second would be adopted as the first: same key, same picture.',\n fix: 'Make the ids unique.',\n path: product.id,\n docs: DOCS,\n });\n }\n seen.add(product.id);\n}\n\nfunction unreadable(product: BatchProduct, message: string): Bakery3Error {\n return new Bakery3Error({\n code: 'ImportFailed',\n message,\n path: product.id,\n docs: `${DOCS}#what-a-model-can-use`,\n });\n}\n\nfunction mostlyFailing(\n tally: RenderBatchRecorded,\n attempted: number,\n): Bakery3Error {\n const first = tally.skips[0]!;\n return new Bakery3Error({\n code: 'ImportFailed',\n message: `${tally.skipped} of the first ${attempted} models could not be imported. The first: ${first.id}: ${first.error.message}`,\n why: 'One bad model is skipped and listed. Most of them failing is something wrong with all of them: a base URL, a bucket that is not public, a format.',\n fix: 'Open one of the URLs in a private browser window. It has to download a .glb there. What was recorded stays admitted; call again with the same key to go on.',\n docs: `${DOCS}#importing-by-url`,\n });\n}\n\nfunction abortError(): Error {\n const error = new Error('The recording was aborted.');\n error.name = 'AbortError';\n return error;\n}\n","/**\n * Webhook signature verification.\n *\n * A webhook endpoint is a public URL that causes writes in the developer's\n * database. Verifying is not optional, so it is one function with no options\n * and no way to get it subtly wrong.\n *\n * const event = await verifyWebhook({\n * body: await request.text(),\n * signature: request.headers.get('bakery3-signature'),\n * secret: process.env.BAKERY3_WEBHOOK_SECRET!,\n * });\n *\n * Pass the raw body, not a parsed and re-stringified object. Re-serializing\n * JSON changes key order and whitespace and therefore the signature, and it\n * is the single most common reason a correct implementation fails.\n */\n\nimport type { WebhookPayload } from '../protocol/index.js';\nimport { Bakery3Error } from '../errors.js';\n\n/**\n * A signature older than this is refused, so a captured request cannot be\n * replayed later. Five minutes is the usual allowance for clock skew.\n */\nconst TOLERANCE_MS = 5 * 60 * 1000;\n\n/**\n * Verify a webhook request and return its payload. Throws a `Bakery3Error`\n * (`Unauthorized`) when the header is missing, malformed, older than five\n * minutes, or signed with another secret.\n */\nexport async function verifyWebhook(input: {\n /** The request body exactly as received, as text. */\n body: string;\n /**\n * The `bakery3-signature` header. `headers.get()` gives `null` when the\n * request has none, and that is refused like a bad signature.\n */\n signature: string | null | undefined;\n /** The signing secret from your webhook settings. */\n secret: string;\n /** Test seam. Never pass this in production. */\n now?: number;\n}): Promise<WebhookPayload> {\n const { body, signature, secret } = input;\n const now = input.now ?? Date.now();\n\n if (typeof secret !== 'string' || !secret) {\n throw new Bakery3Error({\n code: 'InvalidRequest',\n message: 'verifyWebhook() was given no secret.',\n fix: 'Pass the signing secret from your webhook settings, from a server-only environment variable: secret: process.env.BAKERY3_WEBHOOK_SECRET!',\n docs: 'https://bakery3.com/docs/webhooks',\n });\n }\n if (typeof signature !== 'string' || !signature) {\n throw invalid(\n 'The request has no bakery3-signature header. Pass request.headers.get(\"bakery3-signature\").',\n );\n }\n\n // `t=<ms>,v1=<hex>`: the timestamp is signed together with the body, which\n // is what makes the replay window enforceable.\n const parts = Object.fromEntries(\n signature.split(',').map((piece) => {\n const index = piece.indexOf('=');\n return [piece.slice(0, index).trim(), piece.slice(index + 1).trim()];\n }),\n );\n const timestamp = Number(parts.t);\n const provided = parts.v1;\n\n if (!timestamp || !provided) {\n throw invalid('Signature header is malformed. Expected \"t=…,v1=…\".');\n }\n if (Math.abs(now - timestamp) > TOLERANCE_MS) {\n throw invalid('Signature timestamp is outside the five-minute tolerance.');\n }\n\n const key = await crypto.subtle.importKey(\n 'raw',\n new TextEncoder().encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n const mac = await crypto.subtle.sign(\n 'HMAC',\n key,\n new TextEncoder().encode(`${timestamp}.${body}`),\n );\n\n if (!timingSafeEqual(toHex(new Uint8Array(mac)), provided)) {\n throw invalid('Signature does not match the body.');\n }\n\n return JSON.parse(body) as WebhookPayload;\n}\n\nfunction invalid(message: string): Bakery3Error {\n return new Bakery3Error({\n code: 'Unauthorized',\n message,\n why: 'The request did not carry a valid Bakery3 signature, so it may not have come from us.',\n fix: 'Pass the raw request body (not a re-serialized object) and the secret from your webhook settings.',\n docs: 'https://bakery3.com/docs/webhooks',\n });\n}\n\n/**\n * Constant time in the length-equal case, which is the only case that can\n * leak anything useful: both sides are fixed-length hex digests.\n */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);\n return diff === 0;\n}\n\nfunction toHex(bytes: Uint8Array): string {\n let out = '';\n for (const byte of bytes) out += byte.toString(16).padStart(2, '0');\n return out;\n}\n","/**\n * @oeave/bakery3/node: the server half.\n *\n * The secret key lives here and only here. It never reaches a browser and is\n * never an argument to anything in `@oeave/bakery3`. This module mints the\n * short-lived, narrow token that goes in its place, verifies webhooks, and\n * calls the API with the secret key for the things a browser may not do.\n *\n * import { Bakery3Server } from '@oeave/bakery3/node';\n *\n * const bakery3 = new Bakery3Server(process.env.BAKERY3_SECRET_KEY!);\n *\n * export async function POST() {\n * return Response.json(\n * await bakery3.tokens.create({\n * expiresInSeconds: 300,\n * maxRenders: 1,\n * maxCost: 1,\n * allowedOrigins: ['https://shop.example.com'],\n * })\n * );\n * }\n *\n * That endpoint is the entire server-side integration.\n */\n\nimport type {\n AssetDeleteResponse,\n AssetImportKind,\n AssetImportResponse,\n AssetsDeleteResponse,\n BatchOpenRequest,\n CostEstimate,\n RenderRecord,\n RenderSpec,\n} from '../protocol/index.js';\nimport { QUALITY, isAssetHash } from '../protocol/index.js';\nimport { Bakery3Error } from '../errors.js';\nimport { Bakery3Client, type RetryPolicy } from '../client.js';\nimport { Batch } from '../batch.js';\nimport { RenderSet } from '../set.js';\nimport {\n quoteKey,\n sampleOf,\n testSettings,\n type TestRunOptions,\n} from '../testRun.js';\nimport {\n recordBatch,\n type RenderBatchOptions,\n type RenderBatchRecorded,\n type RenderBatchRecording,\n} from './renderBatch.js';\nimport { warnIfKeyIsExposed } from '../warn.js';\n\nexport type BrowserTokenOptions = {\n /**\n * How long the token lives, in seconds. Default 300. Keep it short: a\n * browser token is a capability handed to a page, and the shorter its life\n * the less a leaked one is worth. Five minutes is plenty, because the\n * browser SDK re-mints on a 401 without the developer writing anything.\n */\n expiresInSeconds?: number;\n /** Hard ceiling on renders this token can start. Default 5. */\n maxRenders?: number;\n /** Hard ceiling on spend across all of them, in USD. Default 2. */\n maxCost?: number;\n /**\n * Origins allowed to spend it. Set this in production: it is what stops a\n * token lifted out of one page's network tab from working anywhere else.\n */\n allowedOrigins?: string[];\n /** Your own user/session id. Shows up in the usage ledger for attribution. */\n subject?: string;\n};\n\nexport type BrowserToken = {\n /** The token itself, a `bk_pt_` string. Hand it to the browser SDK. */\n token: string;\n /** When it stops working, as a Unix timestamp in milliseconds. */\n expiresAt: number;\n /** The project the token renders into. */\n projectId: string;\n};\n\nexport type Bakery3ServerOptions = {\n /** The API's base URL. Only for a self-hosted or test deployment. */\n baseUrl?: string;\n /** A `fetch` to use instead of the global one. */\n fetch?: typeof fetch;\n /** How a 429/503 is waited out. The browser SDK's defaults otherwise. */\n retry?: RetryPolicy;\n};\n\n/** A run's pictures, plus which products were left out and why. */\nexport type RenderBatchRun = RenderSet & {\n readonly recorded: RenderBatchRecorded;\n};\n\nexport class Bakery3Server {\n readonly tokens: TokensApi;\n readonly renders: RendersApi;\n readonly batches: BatchesApi;\n readonly assets: AssetsApi;\n\n private readonly secretKey: string | undefined;\n private readonly options: Bakery3ServerOptions;\n private transport: Bakery3Client | undefined;\n\n /**\n * @param secretKey Your `bk_sk_` key, as a string, from a server-only\n * environment variable. Not the browser SDK's `{ apiKey }` object.\n *\n * The key is checked on the first request, not here. A route module that\n * builds its client at the top level is evaluated by `next build`, often\n * where the server's secrets are not set, and a constructor that threw\n * there would fail the build over a key the build never uses.\n */\n constructor(secretKey: string, options: Bakery3ServerOptions = {}) {\n // The browser SDK takes `{ apiKey }`; this constructor takes the string.\n // Said here, or it would fail as `secretKey.startsWith is not a function`.\n // An object is wrong wherever the code runs, so this one is not deferred.\n if (secretKey != null && typeof secretKey !== 'string') {\n throw new Bakery3Error({\n code: 'InvalidRequest',\n message:\n 'new Bakery3Server() takes the secret key as a string, not an options object.',\n fix: 'new Bakery3Server(process.env.BAKERY3_SECRET_KEY!, options)',\n docs: 'https://bakery3.com/docs/auth',\n });\n }\n this.secretKey = secretKey || undefined;\n this.options = options;\n\n // This module is server-only by design, but nothing stops a bundler from\n // pulling it into a client component, and the failure is silent: the key\n // ships and everything keeps working.\n if (this.secretKey) warnIfKeyIsExposed(this.secretKey, { source: 'node' });\n\n const client = () => this.client();\n // Async, so a key that fails its check rejects the call's promise\n // rather than throwing from it.\n const request: Request = async (method, path, body) =>\n client().request(method, path, body);\n this.tokens = new TokensApi(request);\n this.renders = new RendersApi(request, client);\n this.batches = new BatchesApi(client);\n this.assets = new AssetsApi(client);\n }\n\n /**\n * The same transport the browser SDK uses (one error shape, the same\n * 429/503 backoff) with the secret key as the bearer. It has nothing to\n * re-mint, so a 401 here is a 401. Made on first use, after the key is\n * checked.\n */\n private client(): Bakery3Client {\n if (this.transport) return this.transport;\n const secretKey = this.secretKey;\n if (!secretKey) {\n throw new Bakery3Error({\n code: 'Unauthorized',\n message:\n 'A secret key is required. Create one at https://bakery3.com/keys, then pass it: new Bakery3Server(process.env.BAKERY3_SECRET_KEY!).',\n docs: 'https://bakery3.com/docs/auth',\n });\n }\n // A browser token here is almost always a copy-paste mistake between the\n // two halves of the integration, and it would otherwise fail later with a\n // generic 401 from a route that looks unrelated.\n if (secretKey.startsWith('bk_pt_')) {\n throw new Bakery3Error({\n code: 'Unauthorized',\n message: 'That is a browser token, not a secret key.',\n why: 'Browser tokens (bk_pt_…) are minted by this SDK. Secret keys (bk_sk_…) create them.',\n fix: 'Use your bk_sk_ key from https://bakery3.com/keys, kept in a server-only environment variable.',\n docs: 'https://bakery3.com/docs/auth',\n });\n }\n if (!secretKey.startsWith('bk_sk_')) {\n throw new Bakery3Error({\n code: 'Unauthorized',\n message:\n 'That is not a secret key. Secret keys start with bk_sk_. Create one at https://bakery3.com/keys.',\n docs: 'https://bakery3.com/docs/auth',\n });\n }\n this.transport = new Bakery3Client({\n apiKey: secretKey,\n ...(this.options.baseUrl ? { baseUrl: this.options.baseUrl } : {}),\n ...(this.options.fetch ? { fetch: this.options.fetch } : {}),\n ...(this.options.retry ? { retry: this.options.retry } : {}),\n });\n return this.transport;\n }\n\n /**\n * Render a catalog of models that already sit on a CDN: one call, no\n * browser, and none of the models' bytes through this process. Needs a\n * plan that includes imports (see https://bakery3.com/docs/catalog#plans).\n *\n * const run = await api.renderBatch({\n * key: 'fall-2026',\n * products: [{ id: 'chair-aria', url: 'https://cdn.shop.com/models/chair-aria.glb' }],\n * shots: ['three-quarter', 'front', { kind: 'video', from: 'front', to: 'back', seconds: 4 }],\n * room: { preset: 'loft_golden' },\n * maxCost: 600,\n * });\n * await run.wait(); // or let a webhook tell you, and exit now\n *\n * Resolves once every product is recorded and the run is sealed. The\n * shots render on from there; this process does not have to stay up.\n * A product whose model cannot be imported is skipped and listed in\n * `run.recorded.skips`, and the run goes on. Calling it again with the\n * same `key` resumes a recording that stopped, re-downloads no model that\n * did not change, and adopts every shot that already rendered.\n *\n * What a model by URL cannot carry (node materials, a shader-lit set) is\n * recorded where that code runs; see `renderVariants()` in `@oeave/bakery3`.\n */\n async renderBatch(options: RenderBatchOptions): Promise<RenderBatchRun> {\n if (!(options.maxCost > 0)) {\n throw new Bakery3Error({\n code: 'InvalidRequest',\n message: 'renderBatch() needs a maxCost.',\n why: 'A run is as many renders as products times shots, and a ceiling is what makes that number safe to be wrong about: a page that would cross it is refused, never charged.',\n fix: 'Call quoteBatch() with the same options for the real number, or testBatch() to look at three products first.',\n docs: 'https://bakery3.com/docs/catalog#what-it-will-cost',\n });\n }\n const batch = await this.openRun(options);\n const recorded = await recordBatch(this.client(), batch, options);\n // Sealed only once every product is through. A recording that threw\n // leaves the run open, which is what lets the same call resume it.\n await batch.close();\n return new RenderSet(batch, recorded) as RenderBatchRun;\n }\n\n /**\n * What `renderBatch()` would cost. The models are imported (that is how\n * they are priced); nothing is rendered or charged.\n */\n async quoteBatch(\n options: Omit<RenderBatchOptions, 'maxCost'> & { maxCost?: number },\n ): Promise<RenderBatchRecording> {\n // The route that prices a page belongs to a batch, and a batch is opened\n // under a key. Never the run's own: that batch is the one\n // `renderBatch()` opens with its `maxCost`, and one opened here without\n // a ceiling would be the batch the run then re-opens. A batch of its\n // own, priced and then cancelled, holds nothing and keeps the run's key\n // free.\n const batch = await this.openRun({\n key: options.key && quoteKey(options.key),\n name: `${options.name ?? options.key} (quote)`,\n ...(options.lane ? { lane: options.lane } : {}),\n });\n try {\n return await recordBatch(this.client(), batch, options, {\n dryRun: true,\n });\n } finally {\n // Best effort: a quote batch left open holds nothing either.\n await batch.cancel().catch(() => {});\n }\n }\n\n /**\n * Look before paying: three products (the first, the middle and the last\n * of an array; the first three of anything else), every shot, at preview\n * quality and a small size, in the ordinary lane so they come back in\n * about a minute. A clip is cut to two seconds at twelve frames. Same\n * options as `renderBatch()`. The test run has keys of its own, so the\n * real run never adopts these previews as finished shots.\n *\n * const test = await api.testBatch(options);\n * for (const shot of await test.result()) console.log(shot.variant, shot.shot, shot.url);\n */\n async testBatch(\n options: Omit<RenderBatchOptions, 'maxCost'> & { maxCost?: number },\n test: TestRunOptions = {},\n ): Promise<RenderBatchRun> {\n const edge = QUALITY[options.quality ?? 'studio'].defaultLongEdge;\n const settings = testSettings(\n {\n key: options.key,\n width: options.width ?? edge,\n height: options.height ?? edge,\n },\n test,\n );\n const run: Omit<RenderBatchOptions, 'maxCost'> & { maxCost: number } = {\n ...options,\n key: settings.key,\n lane: settings.lane,\n maxCost: settings.maxCost,\n products: sampleOf(options.products, test.products),\n name: `${options.name ?? options.key} (test)`,\n };\n const batch = await this.openRun(run);\n // Forced over every layer, so a product's or a shot's own 2048² still\n // comes back small.\n const recorded = await recordBatch(this.client(), batch, run, {\n force: {\n version: settings.version,\n quality: settings.quality,\n width: settings.width,\n height: settings.height,\n fps: 12,\n seconds: 2,\n },\n });\n await batch.close();\n return new RenderSet(batch, recorded) as RenderBatchRun;\n }\n\n /**\n * A run by id, from another process, a webhook handler, or tomorrow\n * morning.\n */\n async getRenderSet(id: string): Promise<RenderSet> {\n const client = this.client();\n return new RenderSet(new Batch(client, await client.getBatch(id)));\n }\n\n private async openRun(\n options: Pick<\n RenderBatchOptions,\n 'key' | 'name' | 'lane' | 'maxParallel'\n > & { maxCost?: number },\n ): Promise<Batch> {\n if (!options.key) {\n throw new Bakery3Error({\n code: 'InvalidRequest',\n message: 'A run needs a key.',\n why: 'The key names the run. It is what lets the same call resume a recording that stopped, instead of starting a second one.',\n fix: \"Give it something stable that names this body of work: `key: 'fall-2026'`.\",\n docs: 'https://bakery3.com/docs/catalog',\n });\n }\n const client = this.client();\n return new Batch(\n client,\n await client.openBatch({\n key: options.key,\n ...(options.name ? { name: options.name } : {}),\n ...(options.maxCost !== undefined ? { maxCost: options.maxCost } : {}),\n lane: options.lane ?? 'batch',\n ...(options.maxParallel !== undefined\n ? { maxParallel: options.maxParallel }\n : {}),\n }),\n );\n }\n}\n\nclass AssetsApi {\n constructor(private readonly client: () => Bakery3Client) {}\n\n /**\n * Have the service fetch a public https URL into the project's assets,\n * and say what it found: the hash to put in a manifest, and for a model\n * its triangles, bounds, cameras and anything the renderer cannot read.\n *\n * Secret key only, which is why it is here and not in the browser SDK.\n * What is fetched is fenced on the service's side: https, public\n * addresses only, no credentials, a size limit, and the file must be a\n * model or an HDRI. An unchanged URL is answered without a download\n * (`unchanged: true`).\n */\n async import(\n url: string,\n options: { kind?: AssetImportKind } = {},\n ): Promise<AssetImportResponse> {\n return this.client().importAsset({\n url,\n ...(options.kind ? { kind: options.kind } : {}),\n });\n }\n\n /**\n * Delete one uploaded file from the project now, rather than when\n * retention would. `deleted` is false when the project held no such file,\n * so deleting twice is not an error. The next render that needs the file\n * uploads it again; a render still queued that needs it can fail, and a\n * failed render costs nothing.\n *\n * await api.assets.delete('sha256:9f2b…');\n * // { hash: 'sha256:9f2b…', deleted: true }\n */\n async delete(hash: string): Promise<AssetDeleteResponse> {\n // Checked here and not only by the API: the hash becomes a path, and\n // `../renders/<id>` would be resolved by fetch into another route.\n if (!isAssetHash(hash)) {\n throw new Bakery3Error({\n code: 'InvalidRequest',\n message: `\"${String(hash).slice(0, 80)}\" is not an asset hash. Expected sha256: followed by 64 lowercase hex characters.`,\n fix: 'Pass the hash an import or a manifest gave you, or call assets.deleteAll() for every file.',\n docs: 'https://bakery3.com/docs/uploads#delete-your-uploaded-files',\n });\n }\n return this.client().request<AssetDeleteResponse>(\n 'DELETE',\n `/v1/assets/${hash}`,\n );\n }\n\n /**\n * Delete every uploaded file in the project, a page per request until\n * none is left. Resolves with how many were deleted.\n *\n * await api.assets.deleteAll();\n * // { deleted: 240 }\n */\n async deleteAll(): Promise<{ deleted: number }> {\n const client = this.client();\n let deleted = 0;\n for (;;) {\n const page = await client.request<AssetsDeleteResponse>(\n 'DELETE',\n '/v1/assets',\n );\n deleted += page.deleted;\n // A page that deleted nothing and still says more would loop for\n // ever; the API answers 503 instead, but a loop should not rely on it.\n if (!page.more || page.deleted === 0) return { deleted };\n }\n }\n}\n\ntype Request = <T>(method: string, path: string, body?: unknown) => Promise<T>;\n\nclass TokensApi {\n constructor(private readonly request: Request) {}\n\n /**\n * Mint a browser token.\n *\n * Everything about it is a ceiling rather than a grant: it cannot outlive\n * its expiry, cannot start more renders than `maxRenders`, cannot spend past\n * `maxCost`, cannot be used from an origin outside `allowedOrigins`, and\n * cannot perform a single billing or admin operation. That last one is not\n * a policy: those routes require a `bk_sk_` key and this is not one.\n */\n create(options: BrowserTokenOptions = {}): Promise<BrowserToken> {\n return this.request<BrowserToken>('POST', '/v1/tokens', {\n expiresInSeconds: options.expiresInSeconds ?? 300,\n maxRenders: options.maxRenders ?? 5,\n maxCost: options.maxCost ?? 2,\n ...(options.allowedOrigins\n ? { allowedOrigins: options.allowedOrigins }\n : {}),\n ...(options.subject ? { subject: options.subject } : {}),\n });\n }\n\n /** Revoke a token before its expiry. */\n revoke(token: string): Promise<void> {\n return this.request<void>('POST', '/v1/tokens/revoke', { token });\n }\n}\n\nclass RendersApi {\n constructor(\n private readonly request: Request,\n private readonly client: () => Bakery3Client,\n ) {}\n\n /**\n * Render from a manifest you already have: a batch job, a re-render, a\n * queued webhook. The browser flow is `@oeave/bakery3`; this is the API.\n * Repeated on a 429/503 only when `spec.idempotencyKey` makes that safe.\n */\n async create(spec: RenderSpec): Promise<RenderRecord> {\n return this.client().createRender(spec);\n }\n\n /** A render's record, with its state, cost and result URLs. */\n get(id: string): Promise<RenderRecord> {\n return this.request<RenderRecord>('GET', `/v1/renders/${id}`);\n }\n\n /** Cancel a render that has not finished. Already terminal is a no-op. */\n cancel(id: string): Promise<RenderRecord> {\n return this.request<RenderRecord>('POST', `/v1/renders/${id}/cancel`, {});\n }\n\n /**\n * One more attempt for a render that failed with `attemptsExhausted`.\n * Returns the new render, linked to the old one; a render that is not in\n * that state answers 409.\n */\n async retry(id: string): Promise<RenderRecord> {\n return this.client().retryRender(id);\n }\n\n /**\n * Delete a render now rather than when retention would: the result, the\n * preview, and every signed URL that pointed at them. The record survives\n * as `expired`, so the receipt is still readable. A live render is\n * cancelled first.\n */\n delete(id: string): Promise<RenderRecord> {\n return this.request<RenderRecord>('DELETE', `/v1/renders/${id}`);\n }\n\n /** The project's renders, newest first, a page at a time. */\n list(options: { limit?: number; cursor?: string } = {}): Promise<{\n renders: RenderRecord[];\n cursor: string | null;\n }> {\n const query = new URLSearchParams();\n if (options.limit) query.set('limit', String(options.limit));\n if (options.cursor) query.set('cursor', options.cursor);\n const suffix = query.toString() ? `?${query}` : '';\n return this.request('GET', `/v1/renders${suffix}`);\n }\n\n /** The quote for a spec: a likely cost and a maximum, in USD. */\n estimate(\n spec: Pick<RenderSpec, 'quality' | 'output' | 'advanced'>,\n ): Promise<CostEstimate> {\n return this.request<CostEstimate>('POST', '/v1/estimate', spec);\n }\n}\n\n/**\n * Batches from a server: manifests you already have, added by the hundred\n * and rendered behind one cost ceiling. `renderBatch()` builds on this.\n *\n * const batch = await api.batches.open({ key: 'fall-2026-v3', lane: 'batch', maxCost: 600 });\n * for await (const line of readLines('manifests.jsonl')) {\n * const item = JSON.parse(line);\n * batch.add({ key: item.key, spec: item.spec, metadata: item.metadata });\n * if (batch.buffered >= 100) await batch.flush();\n * }\n * await batch.close();\n * await batch.wait({ onProgress: (p) => console.log(`${p.completed}/${p.total}`) });\n */\nclass BatchesApi {\n constructor(private readonly client: () => Bakery3Client) {}\n\n /** Open, or re-open by key. */\n async open(request: BatchOpenRequest): Promise<Batch> {\n const client = this.client();\n return new Batch(client, await client.openBatch(request));\n }\n\n /** A batch by id, with its latest counts. */\n async get(id: string): Promise<Batch> {\n const client = this.client();\n return new Batch(client, await client.getBatch(id));\n }\n}\n\nexport { Bakery3Error, BatchPageRefused } from '../errors.js';\nexport type { Batch } from '../batch.js';\nexport type { RenderSet } from '../set.js';\nexport type { Recorded, RenderSetFailure, RenderSetImage } from '../set.js';\nexport type { TestRunOptions } from '../testRun.js';\nexport type {\n BatchEnvironment,\n BatchProduct,\n BatchRoom,\n ImageShot,\n ProductSkip,\n RenderBatchOptions,\n RenderBatchProgress,\n RenderBatchRecorded,\n Shot,\n ShotSettings,\n VideoShot,\n View,\n} from './renderBatch.js';\nexport type { Angle, ViewWord } from '../frame.js';\nexport type { BatchProgress, FlushOptions, WaitOptions } from '../batch.js';\nexport type {\n BatchItemRecord,\n BatchItemsPage,\n RetryPolicy,\n} from '../client.js';\nexport { verifyWebhook } from './webhook.js';\nexport type {\n AssetDeleteResponse,\n BatchAddRequest,\n BatchAddResponse,\n BatchExportLine,\n BatchItemOutcome,\n BatchItemRequest,\n BatchOpenRequest,\n BatchRecord,\n CostEstimate,\n FrameSequenceIndex,\n RenderRecord,\n RenderSpec,\n} from '../protocol/index.js';\n"]}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Object3D, Mesh } from 'three';
|
|
2
|
+
import { B as BakeTextureSize, a as BakeQuality, b as BakeAtlas, c as BakeView } from './bake-DZ-CJR6f.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The request half: a live scene becomes a `BakeSpec` plus its assets.
|
|
6
|
+
*
|
|
7
|
+
* `bake()` on the root entry point is a short wrapper over this: prepare,
|
|
8
|
+
* upload the misses, POST `/v1/bakes`, poll. It stays exported on its own so
|
|
9
|
+
* a caller with a bake worker of their own can build the exact request the
|
|
10
|
+
* hosted one takes and post it wherever that worker lives.
|
|
11
|
+
*
|
|
12
|
+
* The capture is the ordinary one: the same graph walk, shader extraction and
|
|
13
|
+
* content-addressed assets as a still. The camera travels with it and is
|
|
14
|
+
* unused by the bake itself, which is what lets you move the viewpoint and
|
|
15
|
+
* still hit the same bake cache entry.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Geometry the viewer does not need, delivered as something lighter with
|
|
20
|
+
* its detail baked on: its color, a normal map for the relief it lost, and
|
|
21
|
+
* the light traced at the real surface. The real objects still cast their
|
|
22
|
+
* shadows and bounce their light in the bake; they are only hidden once it
|
|
23
|
+
* is applied.
|
|
24
|
+
*
|
|
25
|
+
* simplify: [
|
|
26
|
+
* { objects: bookcase, to: 'box' }, // a group: every mesh under it
|
|
27
|
+
* { objects: [palm, monstera], to: 'billboard' },
|
|
28
|
+
* { objects: statue, triangles: 800 }, // to: 'lowpoly' is the default
|
|
29
|
+
* { objects: sofa, to: sofaLowPoly }, // a mesh of your own
|
|
30
|
+
* ]
|
|
31
|
+
*
|
|
32
|
+
* Or on the object itself, which travels with the model:
|
|
33
|
+
*
|
|
34
|
+
* bookcase.userData.bakery3 = { simplify: 'box' };
|
|
35
|
+
*/
|
|
36
|
+
type BakeSimplifyInput = {
|
|
37
|
+
/** What to replace: objects (a group means every mesh under it) or ids. */
|
|
38
|
+
objects: Object3D | string | Array<Object3D | string>;
|
|
39
|
+
/**
|
|
40
|
+
* `'lowpoly'` (default): shrink-wrapped and reduced to `triangles`.
|
|
41
|
+
* `'box'`: the box round them. `'billboard'`: one picture that turns to
|
|
42
|
+
* face the camera, for foliage. `'decimate'`: each object, with fewer
|
|
43
|
+
* triangles and its own materials, for the product itself. Or a mesh of
|
|
44
|
+
* your own to use as the shape: it does not have to be in the scene, and
|
|
45
|
+
* it is never drawn as itself.
|
|
46
|
+
*/
|
|
47
|
+
to?: 'lowpoly' | 'box' | 'billboard' | 'decimate' | Mesh;
|
|
48
|
+
/** `'lowpoly'`: default 1500. `'decimate'`: per object, default 20000. */
|
|
49
|
+
triangles?: number;
|
|
50
|
+
/** The stand-in's texture side. Default `textureSize`. */
|
|
51
|
+
textureSize?: BakeTextureSize;
|
|
52
|
+
/**
|
|
53
|
+
* One stand-in for several entries, where there is no group node to hang
|
|
54
|
+
* it on. Every entry with the same `group` becomes a single stand-in.
|
|
55
|
+
*
|
|
56
|
+
* A row of books is thirty meshes lying under the same carcass as the
|
|
57
|
+
* shelves, and one box around the books is the point; naming the carcass
|
|
58
|
+
* would take the shelves with it. Objects that already share a parent
|
|
59
|
+
* need none of this: pass the parent.
|
|
60
|
+
*/
|
|
61
|
+
group?: string;
|
|
62
|
+
};
|
|
63
|
+
type PrepareBakeSettings = {
|
|
64
|
+
quality?: BakeQuality;
|
|
65
|
+
textureSize?: BakeTextureSize;
|
|
66
|
+
/** Explicit objectIds. Omit and the SDK bakes every candidate that is
|
|
67
|
+
* bakeable and on by default. */
|
|
68
|
+
include?: string[];
|
|
69
|
+
/** Removed from whatever `include` resolved to: the panel's unticked
|
|
70
|
+
* boxes, without the panel having to restate the whole list. */
|
|
71
|
+
exclude?: string[];
|
|
72
|
+
sizes?: Record<string, BakeTextureSize>;
|
|
73
|
+
margin?: number;
|
|
74
|
+
deliverGlb?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Bake everything into one shared lightmap instead of one per object:
|
|
77
|
+
* one download and one texture bind for the whole room. `true` is a 2048²
|
|
78
|
+
* atlas; pass `{ size, weights }` to choose the size and give a hero
|
|
79
|
+
* product more of the map (`weights: { [heroId]: 4 }` is twice the side
|
|
80
|
+
* and four times the area its surface alone would earn). See `BakeAtlas`
|
|
81
|
+
* for how shares are worked out.
|
|
82
|
+
*/
|
|
83
|
+
atlas?: boolean | BakeAtlas;
|
|
84
|
+
/**
|
|
85
|
+
* Where the unwrap hides its seams from.
|
|
86
|
+
*
|
|
87
|
+
* `'camera'` (default): the camera you pass, quantized so that small moves
|
|
88
|
+
* reuse the bake (see view.ts). `'none'`: no viewpoint; seams prefer the
|
|
89
|
+
* underside and hard edges alone, for a scene with no dominant view. Or an
|
|
90
|
+
* explicit position in scene units, sent as given.
|
|
91
|
+
*/
|
|
92
|
+
view?: 'camera' | 'none' | BakeView;
|
|
93
|
+
/** See `BakeSimplifyInput`. Entries here are added to the ones found on
|
|
94
|
+
* objects as `userData.bakery3.simplify`. */
|
|
95
|
+
simplify?: BakeSimplifyInput[];
|
|
96
|
+
/**
|
|
97
|
+
* What to do about a preset room in the scene.
|
|
98
|
+
*
|
|
99
|
+
* `'preset'` (the default) takes an unmodified room's own lightmaps from
|
|
100
|
+
* the library and bakes only your objects, the stand they are on and the
|
|
101
|
+
* shadow they cast: a few seconds where a whole room is minutes. A room
|
|
102
|
+
* you have changed, or a scene with no preset room in it, is baked in full
|
|
103
|
+
* either way. `'full'` bakes the room's surfaces too, which is what you
|
|
104
|
+
* want if you have lit it yourself or the product throws light of its own.
|
|
105
|
+
*
|
|
106
|
+
* The report says which happened (`BakeApplyReport.room`), because a bake
|
|
107
|
+
* that quietly covered less than you asked is not a saving.
|
|
108
|
+
*/
|
|
109
|
+
room?: 'full' | 'preset';
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export type { BakeSimplifyInput as B, PrepareBakeSettings as P };
|