@vue-skuilder/platform-ui 0.2.24 → 0.2.26
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/dist/assets/{About-BpF64SeZ.js → About-Cbh4d2en.js} +2 -2
- package/dist/assets/{About-BpF64SeZ.js.map → About-Cbh4d2en.js.map} +1 -1
- package/dist/assets/{AdminDashboard-BpbXoTgh.js → AdminDashboard-1P0YrINL.js} +2 -2
- package/dist/assets/{AdminDashboard-BpbXoTgh.js.map → AdminDashboard-1P0YrINL.js.map} +1 -1
- package/dist/assets/{ClassroomCtrlPanel-B224_mhy.js → ClassroomCtrlPanel-qTZ4-_Qj.js} +2 -2
- package/dist/assets/{ClassroomCtrlPanel-B224_mhy.js.map → ClassroomCtrlPanel-qTZ4-_Qj.js.map} +1 -1
- package/dist/assets/{Classrooms-BCfInF-a.js → Classrooms-Bs9idBBc.js} +3 -3
- package/dist/assets/{Classrooms-BCfInF-a.js.map → Classrooms-Bs9idBBc.js.map} +1 -1
- package/dist/assets/{CourseRouter-Bzg7X5kl.js → CourseRouter-COWEp3J8.js} +2 -2
- package/dist/assets/{CourseRouter-Bzg7X5kl.js.map → CourseRouter-COWEp3J8.js.map} +1 -1
- package/dist/assets/CourseWare-BTFRjgBR-BtoyyUaA.js +3 -0
- package/dist/assets/{CourseWare-BTFRjgBR-Dxg0h8E2.js.map → CourseWare-BTFRjgBR-BtoyyUaA.js.map} +1 -1
- package/dist/assets/{Courses-BofXy-aW.js → Courses-BGeDUa_B.js} +3 -3
- package/dist/assets/{Courses-BofXy-aW.js.map → Courses-BGeDUa_B.js.map} +1 -1
- package/dist/assets/{EloModeration-B6Hw_tBP.js → EloModeration-LGJdnlkx.js} +2 -2
- package/dist/assets/{EloModeration-B6Hw_tBP.js.map → EloModeration-LGJdnlkx.js.map} +1 -1
- package/dist/assets/{JoinCode-CZPavfrz.js → JoinCode-DBoEGv_S.js} +2 -2
- package/dist/assets/{JoinCode-CZPavfrz.js.map → JoinCode-DBoEGv_S.js.map} +1 -1
- package/dist/assets/{MarkdownRenderer-kStoDRNE-CwICngq1.js → MarkdownRenderer-kStoDRNE-HDBFbDeD.js} +2 -2
- package/dist/assets/{MarkdownRenderer-kStoDRNE-CwICngq1.js.map → MarkdownRenderer-kStoDRNE-HDBFbDeD.js.map} +1 -1
- package/dist/assets/MarkdownRenderer-kStoDRNE-HqRzdAdp.js +1 -0
- package/dist/assets/{NewCourseDialog-DDLWdnzs.js → NewCourseDialog-CCbEI3IK.js} +2 -2
- package/dist/assets/{NewCourseDialog-DDLWdnzs.js.map → NewCourseDialog-CCbEI3IK.js.map} +1 -1
- package/dist/assets/{ReleaseNotes-BZGVYO7V.js → ReleaseNotes-CWB3FnDP.js} +2 -2
- package/dist/assets/{ReleaseNotes-BZGVYO7V.js.map → ReleaseNotes-CWB3FnDP.js.map} +1 -1
- package/dist/assets/{RequestPasswordReset-Cv2U8l2g.js → RequestPasswordReset-DIhIj9-T.js} +2 -2
- package/dist/assets/{RequestPasswordReset-Cv2U8l2g.js.map → RequestPasswordReset-DIhIj9-T.js.map} +1 -1
- package/dist/assets/{ResetPassword-Cq2ZwWPS.js → ResetPassword-C9wTg7N2.js} +2 -2
- package/dist/assets/{ResetPassword-Cq2ZwWPS.js.map → ResetPassword-C9wTg7N2.js.map} +1 -1
- package/dist/assets/{Study-CPMb-XdT.js → Study-C48aaEsD.js} +2 -2
- package/dist/assets/{Study-CPMb-XdT.js.map → Study-C48aaEsD.js.map} +1 -1
- package/dist/assets/{TagInformation-B4zvmBwR.js → TagInformation-5WJk5HUd.js} +2 -2
- package/dist/assets/{TagInformation-B4zvmBwR.js.map → TagInformation-5WJk5HUd.js.map} +1 -1
- package/dist/assets/{User-husKeJRJ.js → User-Bz1YIJpG.js} +2 -2
- package/dist/assets/{User-husKeJRJ.js.map → User-Bz1YIJpG.js.map} +1 -1
- package/dist/assets/{UserStats-B_-PVqRz.js → UserStats-BgHdylqF.js} +2 -2
- package/dist/assets/{UserStats-B_-PVqRz.js.map → UserStats-BgHdylqF.js.map} +1 -1
- package/dist/assets/{VerifyEmail-9ZWpiPE5.js → VerifyEmail-tn7DWjZd.js} +2 -2
- package/dist/assets/{VerifyEmail-9ZWpiPE5.js.map → VerifyEmail-tn7DWjZd.js.map} +1 -1
- package/dist/assets/{chess-E2uOAyQS-COCon4Zz.js → chess-E2uOAyQS-CjZFFUEU.js} +3 -3
- package/dist/assets/{chess-E2uOAyQS-COCon4Zz.js.map → chess-E2uOAyQS-CjZFFUEU.js.map} +1 -1
- package/dist/assets/chess-Lfm7Fsvs-ByO95MLa.js +1 -0
- package/dist/assets/{common-ui.es-yyDL5WUq.js → common-ui.es-DUw6dWa3.js} +10 -10
- package/dist/assets/common-ui.es-DUw6dWa3.js.map +1 -0
- package/dist/assets/common-ui.es-Tx9PvNRU.js +1 -0
- package/dist/assets/{dist-BFWCBAj7.js → dist-BfByiGsi.js} +4 -4
- package/dist/assets/{dist-BFWCBAj7.js.map → dist-BfByiGsi.js.map} +1 -1
- package/dist/assets/dist-BxvCddLN.js +1 -0
- package/dist/assets/{dist-CG_VzJ5d.js → dist-DO_oB9R-.js} +58 -57
- package/dist/assets/dist-DO_oB9R-.js.map +1 -0
- package/dist/assets/dist-DrrQdNqf.js +1 -0
- package/dist/assets/{dist-leWgtXBf.js → dist-l4NOxAbA.js} +3 -3
- package/dist/assets/dist-l4NOxAbA.js.map +1 -0
- package/dist/assets/edit-ui.es-DPNX25r_.js +36 -0
- package/dist/assets/{edit-ui.es-B_2n06Oi.js.map → edit-ui.es-DPNX25r_.js.map} +1 -1
- package/dist/assets/edit-ui.es-iOIjLjuM.js +1 -0
- package/dist/assets/{french-Dk7YG8Td-C94Hkiug.js → french-Dk7YG8Td-BzAgKluD.js} +2 -2
- package/dist/assets/{french-Dk7YG8Td-C94Hkiug.js.map → french-Dk7YG8Td-BzAgKluD.js.map} +1 -1
- package/dist/assets/french-evUMlbbq-BgQA34eY.js +1 -0
- package/dist/assets/{index-BQFSPscM.css → index-NFrxkZjT.css} +1 -1
- package/dist/assets/{index-D7SxgwYb.js → index-RjJYO_8m.js} +4 -4
- package/dist/assets/{index-D7SxgwYb.js.map → index-RjJYO_8m.js.map} +1 -1
- package/dist/assets/{math-B4HbgYf6-DBLreBi2.js → math-B4HbgYf6-CTDueFZl.js} +5 -5
- package/dist/assets/{math-B4HbgYf6-DBLreBi2.js.map → math-B4HbgYf6-CTDueFZl.js.map} +1 -1
- package/dist/assets/math-DYni7rRl-DkNo_HJe.js +1 -0
- package/dist/assets/piano-BN5Btq91-CYAp2K4e.js +1 -0
- package/dist/assets/piano-DF1g6yaX-DQqyYFu3.js +2 -0
- package/dist/assets/{piano-DF1g6yaX-oYVxyoaj.js.map → piano-DF1g6yaX-DQqyYFu3.js.map} +1 -1
- package/dist/assets/{pitch-CgGJFkZ1-D21Bc5mk.js → pitch-CgGJFkZ1-DHFd5oC5.js} +2 -2
- package/dist/assets/{pitch-CgGJFkZ1-D21Bc5mk.js.map → pitch-CgGJFkZ1-DHFd5oC5.js.map} +1 -1
- package/dist/assets/pitch-Dn0iNqiS-Bop5wffu.js +1 -0
- package/dist/assets/{server-CIZiVq-K.js → server-ChswrlW3.js} +2 -2
- package/dist/assets/{server-CIZiVq-K.js.map → server-ChswrlW3.js.map} +1 -1
- package/dist/assets/{sightsing-BFQ7HRig-D14v58C-.js → sightsing-BFQ7HRig-Cz0hvcK-.js} +3 -3
- package/dist/assets/{sightsing-BFQ7HRig-D14v58C-.js.map → sightsing-BFQ7HRig-Cz0hvcK-.js.map} +1 -1
- package/dist/assets/sightsing-CJX3k0Fd-DuH2QH0h.js +1 -0
- package/dist/assets/{typing-BevtfWlp-DpsEfl6-.js → typing-BevtfWlp-CEwlkfpM.js} +2 -2
- package/dist/assets/{typing-BevtfWlp-DpsEfl6-.js.map → typing-BevtfWlp-CEwlkfpM.js.map} +1 -1
- package/dist/assets/typing-k-ojjO7G-DXwGpkBj.js +1 -0
- package/dist/assets/{word-work-BOnRlZgd-CagAkKsF.js → word-work-BOnRlZgd-hq7vSIPY.js} +2 -2
- package/dist/assets/{word-work-BOnRlZgd-CagAkKsF.js.map → word-work-BOnRlZgd-hq7vSIPY.js.map} +1 -1
- package/dist/assets/word-work-Dd6tIKrt-CYXO9v7a.js +1 -0
- package/dist/index.html +6 -6
- package/dist/sw.js +1 -1
- package/dist/sw.js.map +1 -1
- package/package.json +7 -7
- package/dist/assets/CourseWare-BTFRjgBR-Dxg0h8E2.js +0 -3
- package/dist/assets/MarkdownRenderer-kStoDRNE-Cdfc9yXz.js +0 -1
- package/dist/assets/chess-Lfm7Fsvs-SecdR1IX.js +0 -1
- package/dist/assets/common-ui.es-Bkhr3DWA.js +0 -1
- package/dist/assets/common-ui.es-yyDL5WUq.js.map +0 -1
- package/dist/assets/dist-BRPOqMYr.js +0 -1
- package/dist/assets/dist-BYxQfFzk.js +0 -1
- package/dist/assets/dist-CG_VzJ5d.js.map +0 -1
- package/dist/assets/dist-leWgtXBf.js.map +0 -1
- package/dist/assets/edit-ui.es-B_2n06Oi.js +0 -36
- package/dist/assets/edit-ui.es-BiLWpW2o.js +0 -1
- package/dist/assets/french-evUMlbbq-DTqj5k5M.js +0 -1
- package/dist/assets/math-DYni7rRl-C-q3S77b.js +0 -1
- package/dist/assets/piano-BN5Btq91-BNaIdA_w.js +0 -1
- package/dist/assets/piano-DF1g6yaX-oYVxyoaj.js +0 -2
- package/dist/assets/pitch-Dn0iNqiS-iGo6N2ya.js +0 -1
- package/dist/assets/sightsing-CJX3k0Fd-DwaChJyk.js +0 -1
- package/dist/assets/typing-k-ojjO7G-DrC0GBAS.js +0 -1
- package/dist/assets/word-work-Dd6tIKrt-CDvI3FpH.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{i as __name,s as __toESM,t as __commonJSMin}from"./chunk-D6hFPZc3.js";import{C as NameSpacer,E as hooks,T as Status,_ as isCourseElo,b as isTaggedPerformance,g as blankCourseElo,h as adjustCourseScoresPerTag,l as require___vite_browser_external,m as adjustCourseScores,o as hasActiveFilter,p as EloToNumber,r as displayableDataToViewData,t as toZodJSON,v as toCourseElo,x as prepareNote55,y as _defineProperty}from"./dist-leWgtXBf.js";var require_spark_md5=__commonJSMin(((e,t)=>{(function(n){if(typeof e==`object`)t.exports=n();else if(typeof define==`function`&&define.amd)define(n);else{var r;try{r=window}catch{r=self}r.SparkMD5=n()}})(function(e){var t=[`0`,`1`,`2`,`3`,`4`,`5`,`6`,`7`,`8`,`9`,`a`,`b`,`c`,`d`,`e`,`f`];function md5cycle(e,t){var n=e[0],r=e[1],a=e[2],o=e[3];n+=(r&a|~r&o)+t[0]-680876936|0,n=(n<<7|n>>>25)+r|0,o+=(n&r|~n&a)+t[1]-389564586|0,o=(o<<12|o>>>20)+n|0,a+=(o&n|~o&r)+t[2]+606105819|0,a=(a<<17|a>>>15)+o|0,r+=(a&o|~a&n)+t[3]-1044525330|0,r=(r<<22|r>>>10)+a|0,n+=(r&a|~r&o)+t[4]-176418897|0,n=(n<<7|n>>>25)+r|0,o+=(n&r|~n&a)+t[5]+1200080426|0,o=(o<<12|o>>>20)+n|0,a+=(o&n|~o&r)+t[6]-1473231341|0,a=(a<<17|a>>>15)+o|0,r+=(a&o|~a&n)+t[7]-45705983|0,r=(r<<22|r>>>10)+a|0,n+=(r&a|~r&o)+t[8]+1770035416|0,n=(n<<7|n>>>25)+r|0,o+=(n&r|~n&a)+t[9]-1958414417|0,o=(o<<12|o>>>20)+n|0,a+=(o&n|~o&r)+t[10]-42063|0,a=(a<<17|a>>>15)+o|0,r+=(a&o|~a&n)+t[11]-1990404162|0,r=(r<<22|r>>>10)+a|0,n+=(r&a|~r&o)+t[12]+1804603682|0,n=(n<<7|n>>>25)+r|0,o+=(n&r|~n&a)+t[13]-40341101|0,o=(o<<12|o>>>20)+n|0,a+=(o&n|~o&r)+t[14]-1502002290|0,a=(a<<17|a>>>15)+o|0,r+=(a&o|~a&n)+t[15]+1236535329|0,r=(r<<22|r>>>10)+a|0,n+=(r&o|a&~o)+t[1]-165796510|0,n=(n<<5|n>>>27)+r|0,o+=(n&a|r&~a)+t[6]-1069501632|0,o=(o<<9|o>>>23)+n|0,a+=(o&r|n&~r)+t[11]+643717713|0,a=(a<<14|a>>>18)+o|0,r+=(a&n|o&~n)+t[0]-373897302|0,r=(r<<20|r>>>12)+a|0,n+=(r&o|a&~o)+t[5]-701558691|0,n=(n<<5|n>>>27)+r|0,o+=(n&a|r&~a)+t[10]+38016083|0,o=(o<<9|o>>>23)+n|0,a+=(o&r|n&~r)+t[15]-660478335|0,a=(a<<14|a>>>18)+o|0,r+=(a&n|o&~n)+t[4]-405537848|0,r=(r<<20|r>>>12)+a|0,n+=(r&o|a&~o)+t[9]+568446438|0,n=(n<<5|n>>>27)+r|0,o+=(n&a|r&~a)+t[14]-1019803690|0,o=(o<<9|o>>>23)+n|0,a+=(o&r|n&~r)+t[3]-187363961|0,a=(a<<14|a>>>18)+o|0,r+=(a&n|o&~n)+t[8]+1163531501|0,r=(r<<20|r>>>12)+a|0,n+=(r&o|a&~o)+t[13]-1444681467|0,n=(n<<5|n>>>27)+r|0,o+=(n&a|r&~a)+t[2]-51403784|0,o=(o<<9|o>>>23)+n|0,a+=(o&r|n&~r)+t[7]+1735328473|0,a=(a<<14|a>>>18)+o|0,r+=(a&n|o&~n)+t[12]-1926607734|0,r=(r<<20|r>>>12)+a|0,n+=(r^a^o)+t[5]-378558|0,n=(n<<4|n>>>28)+r|0,o+=(n^r^a)+t[8]-2022574463|0,o=(o<<11|o>>>21)+n|0,a+=(o^n^r)+t[11]+1839030562|0,a=(a<<16|a>>>16)+o|0,r+=(a^o^n)+t[14]-35309556|0,r=(r<<23|r>>>9)+a|0,n+=(r^a^o)+t[1]-1530992060|0,n=(n<<4|n>>>28)+r|0,o+=(n^r^a)+t[4]+1272893353|0,o=(o<<11|o>>>21)+n|0,a+=(o^n^r)+t[7]-155497632|0,a=(a<<16|a>>>16)+o|0,r+=(a^o^n)+t[10]-1094730640|0,r=(r<<23|r>>>9)+a|0,n+=(r^a^o)+t[13]+681279174|0,n=(n<<4|n>>>28)+r|0,o+=(n^r^a)+t[0]-358537222|0,o=(o<<11|o>>>21)+n|0,a+=(o^n^r)+t[3]-722521979|0,a=(a<<16|a>>>16)+o|0,r+=(a^o^n)+t[6]+76029189|0,r=(r<<23|r>>>9)+a|0,n+=(r^a^o)+t[9]-640364487|0,n=(n<<4|n>>>28)+r|0,o+=(n^r^a)+t[12]-421815835|0,o=(o<<11|o>>>21)+n|0,a+=(o^n^r)+t[15]+530742520|0,a=(a<<16|a>>>16)+o|0,r+=(a^o^n)+t[2]-995338651|0,r=(r<<23|r>>>9)+a|0,n+=(a^(r|~o))+t[0]-198630844|0,n=(n<<6|n>>>26)+r|0,o+=(r^(n|~a))+t[7]+1126891415|0,o=(o<<10|o>>>22)+n|0,a+=(n^(o|~r))+t[14]-1416354905|0,a=(a<<15|a>>>17)+o|0,r+=(o^(a|~n))+t[5]-57434055|0,r=(r<<21|r>>>11)+a|0,n+=(a^(r|~o))+t[12]+1700485571|0,n=(n<<6|n>>>26)+r|0,o+=(r^(n|~a))+t[3]-1894986606|0,o=(o<<10|o>>>22)+n|0,a+=(n^(o|~r))+t[10]-1051523|0,a=(a<<15|a>>>17)+o|0,r+=(o^(a|~n))+t[1]-2054922799|0,r=(r<<21|r>>>11)+a|0,n+=(a^(r|~o))+t[8]+1873313359|0,n=(n<<6|n>>>26)+r|0,o+=(r^(n|~a))+t[15]-30611744|0,o=(o<<10|o>>>22)+n|0,a+=(n^(o|~r))+t[6]-1560198380|0,a=(a<<15|a>>>17)+o|0,r+=(o^(a|~n))+t[13]+1309151649|0,r=(r<<21|r>>>11)+a|0,n+=(a^(r|~o))+t[4]-145523070|0,n=(n<<6|n>>>26)+r|0,o+=(r^(n|~a))+t[11]-1120210379|0,o=(o<<10|o>>>22)+n|0,a+=(n^(o|~r))+t[2]+718787259|0,a=(a<<15|a>>>17)+o|0,r+=(o^(a|~n))+t[9]-343485551|0,r=(r<<21|r>>>11)+a|0,e[0]=n+e[0]|0,e[1]=r+e[1]|0,e[2]=a+e[2]|0,e[3]=o+e[3]|0}function md5blk(e){var t=[],n;for(n=0;n<64;n+=4)t[n>>2]=e.charCodeAt(n)+(e.charCodeAt(n+1)<<8)+(e.charCodeAt(n+2)<<16)+(e.charCodeAt(n+3)<<24);return t}function md5blk_array(e){var t=[],n;for(n=0;n<64;n+=4)t[n>>2]=e[n]+(e[n+1]<<8)+(e[n+2]<<16)+(e[n+3]<<24);return t}function md51(e){var t=e.length,n=[1732584193,-271733879,-1732584194,271733878],r,a,o,s,c,l;for(r=64;r<=t;r+=64)md5cycle(n,md5blk(e.substring(r-64,r)));for(e=e.substring(r-64),a=e.length,o=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],r=0;r<a;r+=1)o[r>>2]|=e.charCodeAt(r)<<(r%4<<3);if(o[r>>2]|=128<<(r%4<<3),r>55)for(md5cycle(n,o),r=0;r<16;r+=1)o[r]=0;return s=t*8,s=s.toString(16).match(/(.*?)(.{0,8})$/),c=parseInt(s[2],16),l=parseInt(s[1],16)||0,o[14]=c,o[15]=l,md5cycle(n,o),n}function md51_array(e){var t=e.length,n=[1732584193,-271733879,-1732584194,271733878],r,a,o,s,c,l;for(r=64;r<=t;r+=64)md5cycle(n,md5blk_array(e.subarray(r-64,r)));for(e=r-64<t?e.subarray(r-64):new Uint8Array,a=e.length,o=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],r=0;r<a;r+=1)o[r>>2]|=e[r]<<(r%4<<3);if(o[r>>2]|=128<<(r%4<<3),r>55)for(md5cycle(n,o),r=0;r<16;r+=1)o[r]=0;return s=t*8,s=s.toString(16).match(/(.*?)(.{0,8})$/),c=parseInt(s[2],16),l=parseInt(s[1],16)||0,o[14]=c,o[15]=l,md5cycle(n,o),n}function rhex(e){var n=``,r;for(r=0;r<4;r+=1)n+=t[e>>r*8+4&15]+t[e>>r*8&15];return n}function hex(e){var t;for(t=0;t<e.length;t+=1)e[t]=rhex(e[t]);return e.join(``)}hex(md51(`hello`)),typeof ArrayBuffer<`u`&&!ArrayBuffer.prototype.slice&&(function(){function clamp(e,t){return e=e|0||0,e<0?Math.max(e+t,0):Math.min(e,t)}ArrayBuffer.prototype.slice=function(t,n){var r=this.byteLength,a=clamp(t,r),o=r,s,c,l,u;return n!==e&&(o=clamp(n,r)),a>o?new ArrayBuffer(0):(s=o-a,c=new ArrayBuffer(s),l=new Uint8Array(c),u=new Uint8Array(this,a,s),l.set(u),c)}})();function toUtf8(e){return/[\u0080-\uFFFF]/.test(e)&&(e=unescape(encodeURIComponent(e))),e}function utf8Str2ArrayBuffer(e,t){var n=e.length,r=new ArrayBuffer(n),a=new Uint8Array(r),o;for(o=0;o<n;o+=1)a[o]=e.charCodeAt(o);return t?a:r}function arrayBuffer2Utf8Str(e){return String.fromCharCode.apply(null,new Uint8Array(e))}function concatenateArrayBuffers(e,t,n){var r=new Uint8Array(e.byteLength+t.byteLength);return r.set(new Uint8Array(e)),r.set(new Uint8Array(t),e.byteLength),n?r:r.buffer}function hexToBinaryString(e){var t=[],n=e.length,r;for(r=0;r<n-1;r+=2)t.push(parseInt(e.substr(r,2),16));return String.fromCharCode.apply(String,t)}function SparkMD5(){this.reset()}return SparkMD5.prototype.append=function(e){return this.appendBinary(toUtf8(e)),this},SparkMD5.prototype.appendBinary=function(e){this._buff+=e,this._length+=e.length;var t=this._buff.length,n;for(n=64;n<=t;n+=64)md5cycle(this._hash,md5blk(this._buff.substring(n-64,n)));return this._buff=this._buff.substring(n-64),this},SparkMD5.prototype.end=function(e){var t=this._buff,n=t.length,r,a=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],o;for(r=0;r<n;r+=1)a[r>>2]|=t.charCodeAt(r)<<(r%4<<3);return this._finish(a,n),o=hex(this._hash),e&&(o=hexToBinaryString(o)),this.reset(),o},SparkMD5.prototype.reset=function(){return this._buff=``,this._length=0,this._hash=[1732584193,-271733879,-1732584194,271733878],this},SparkMD5.prototype.getState=function(){return{buff:this._buff,length:this._length,hash:this._hash.slice()}},SparkMD5.prototype.setState=function(e){return this._buff=e.buff,this._length=e.length,this._hash=e.hash,this},SparkMD5.prototype.destroy=function(){delete this._hash,delete this._buff,delete this._length},SparkMD5.prototype._finish=function(e,t){var n=t,r,a,o;if(e[n>>2]|=128<<(n%4<<3),n>55)for(md5cycle(this._hash,e),n=0;n<16;n+=1)e[n]=0;r=this._length*8,r=r.toString(16).match(/(.*?)(.{0,8})$/),a=parseInt(r[2],16),o=parseInt(r[1],16)||0,e[14]=a,e[15]=o,md5cycle(this._hash,e)},SparkMD5.hash=function(e,t){return SparkMD5.hashBinary(toUtf8(e),t)},SparkMD5.hashBinary=function(e,t){var n=hex(md51(e));return t?hexToBinaryString(n):n},SparkMD5.ArrayBuffer=function(){this.reset()},SparkMD5.ArrayBuffer.prototype.append=function(e){var t=concatenateArrayBuffers(this._buff.buffer,e,!0),n=t.length,r;for(this._length+=e.byteLength,r=64;r<=n;r+=64)md5cycle(this._hash,md5blk_array(t.subarray(r-64,r)));return this._buff=r-64<n?new Uint8Array(t.buffer.slice(r-64)):new Uint8Array,this},SparkMD5.ArrayBuffer.prototype.end=function(e){var t=this._buff,n=t.length,r=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],a,o;for(a=0;a<n;a+=1)r[a>>2]|=t[a]<<(a%4<<3);return this._finish(r,n),o=hex(this._hash),e&&(o=hexToBinaryString(o)),this.reset(),o},SparkMD5.ArrayBuffer.prototype.reset=function(){return this._buff=new Uint8Array,this._length=0,this._hash=[1732584193,-271733879,-1732584194,271733878],this},SparkMD5.ArrayBuffer.prototype.getState=function(){var e=SparkMD5.prototype.getState.call(this);return e.buff=arrayBuffer2Utf8Str(e.buff),e},SparkMD5.ArrayBuffer.prototype.setState=function(e){return e.buff=utf8Str2ArrayBuffer(e.buff,!0),SparkMD5.prototype.setState.call(this,e)},SparkMD5.ArrayBuffer.prototype.destroy=SparkMD5.prototype.destroy,SparkMD5.ArrayBuffer.prototype._finish=SparkMD5.prototype._finish,SparkMD5.ArrayBuffer.hash=function(e,t){var n=hex(md51_array(new Uint8Array(e)));return t?hexToBinaryString(n):n},SparkMD5})})),getRandomValues$1,rnds8$1=new Uint8Array(16);function rng$1(){if(!getRandomValues$1&&(getRandomValues$1=typeof crypto<`u`&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||typeof msCrypto<`u`&&typeof msCrypto.getRandomValues==`function`&&msCrypto.getRandomValues.bind(msCrypto),!getRandomValues$1))throw Error(`crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported`);return getRandomValues$1(rnds8$1)}__name(rng$1,`rng`);var regex_default=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function validate$1(e){return typeof e==`string`&®ex_default.test(e)}__name(validate$1,`validate`);for(var byteToHex$1=[],i=0;i<256;++i)byteToHex$1.push((i+256).toString(16).substr(1));function stringify$2(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0,n=(byteToHex$1[e[t+0]]+byteToHex$1[e[t+1]]+byteToHex$1[e[t+2]]+byteToHex$1[e[t+3]]+`-`+byteToHex$1[e[t+4]]+byteToHex$1[e[t+5]]+`-`+byteToHex$1[e[t+6]]+byteToHex$1[e[t+7]]+`-`+byteToHex$1[e[t+8]]+byteToHex$1[e[t+9]]+`-`+byteToHex$1[e[t+10]]+byteToHex$1[e[t+11]]+byteToHex$1[e[t+12]]+byteToHex$1[e[t+13]]+byteToHex$1[e[t+14]]+byteToHex$1[e[t+15]]).toLowerCase();if(!validate$1(n))throw TypeError(`Stringified UUID is invalid`);return n}__name(stringify$2,`stringify`);function v4$1(e,t,n){e=e||{};var r=e.random||(e.rng||rng$1)();if(r[6]=r[6]&15|64,r[8]=r[8]&63|128,t){n=n||0;for(var a=0;a<16;++a)t[n+a]=r[a];return t}return stringify$2(r)}__name(v4$1,`v4`);var require_vuvuzela=__commonJSMin((e=>{e.stringify=function stringify(e){var t=[];t.push({obj:e});for(var n=``,r,a,o,s,c,l,u,d,p,m,g;r=t.pop();)if(a=r.obj,o=r.prefix||``,s=r.val||``,n+=o,s)n+=s;else if(typeof a!=`object`)n+=a===void 0?null:JSON.stringify(a);else if(a===null)n+=`null`;else if(Array.isArray(a)){for(t.push({val:`]`}),c=a.length-1;c>=0;c--)l=c===0?``:`,`,t.push({obj:a[c],prefix:l});t.push({val:`[`})}else{for(d in u=[],a)a.hasOwnProperty(d)&&u.push(d);for(t.push({val:`}`}),c=u.length-1;c>=0;c--)p=u[c],m=a[p],g=c>0?`,`:``,g+=JSON.stringify(p)+`:`,t.push({obj:m,prefix:g});t.push({val:`{`})}return n};function pop(e,t,n){var r=n[n.length-1];e===r.element&&(n.pop(),r=n[n.length-1]);var a=r.element,o=r.index;if(Array.isArray(a))a.push(e);else if(o===t.length-2){var s=t.pop();a[s]=e}else t.push(e)}e.parse=function(e){for(var t=[],n=[],r=0,a,o,s,c,l,u,d,p,m;;){if(a=e[r++],a===`}`||a===`]`||a===void 0){if(t.length===1)return t.pop();pop(t.pop(),t,n);continue}switch(a){case` `:case` `:case`
|
|
1
|
+
import{i as __name,s as __toESM,t as __commonJSMin}from"./chunk-D6hFPZc3.js";import{D as hooks,E as Status,S as prepareNote55,_ as isCourseElo,b as _defineProperty,g as blankCourseElo,h as adjustCourseScoresPerTag,l as require___vite_browser_external,m as adjustCourseScores,o as hasActiveFilter,p as EloToNumber,r as displayableDataToViewData,t as toZodJSON,v as pushTagPresentation,w as NameSpacer,x as isTaggedPerformance,y as toCourseElo}from"./dist-l4NOxAbA.js";var require_spark_md5=__commonJSMin(((e,t)=>{(function(n){if(typeof e==`object`)t.exports=n();else if(typeof define==`function`&&define.amd)define(n);else{var r;try{r=window}catch{r=self}r.SparkMD5=n()}})(function(e){var t=[`0`,`1`,`2`,`3`,`4`,`5`,`6`,`7`,`8`,`9`,`a`,`b`,`c`,`d`,`e`,`f`];function md5cycle(e,t){var n=e[0],r=e[1],a=e[2],o=e[3];n+=(r&a|~r&o)+t[0]-680876936|0,n=(n<<7|n>>>25)+r|0,o+=(n&r|~n&a)+t[1]-389564586|0,o=(o<<12|o>>>20)+n|0,a+=(o&n|~o&r)+t[2]+606105819|0,a=(a<<17|a>>>15)+o|0,r+=(a&o|~a&n)+t[3]-1044525330|0,r=(r<<22|r>>>10)+a|0,n+=(r&a|~r&o)+t[4]-176418897|0,n=(n<<7|n>>>25)+r|0,o+=(n&r|~n&a)+t[5]+1200080426|0,o=(o<<12|o>>>20)+n|0,a+=(o&n|~o&r)+t[6]-1473231341|0,a=(a<<17|a>>>15)+o|0,r+=(a&o|~a&n)+t[7]-45705983|0,r=(r<<22|r>>>10)+a|0,n+=(r&a|~r&o)+t[8]+1770035416|0,n=(n<<7|n>>>25)+r|0,o+=(n&r|~n&a)+t[9]-1958414417|0,o=(o<<12|o>>>20)+n|0,a+=(o&n|~o&r)+t[10]-42063|0,a=(a<<17|a>>>15)+o|0,r+=(a&o|~a&n)+t[11]-1990404162|0,r=(r<<22|r>>>10)+a|0,n+=(r&a|~r&o)+t[12]+1804603682|0,n=(n<<7|n>>>25)+r|0,o+=(n&r|~n&a)+t[13]-40341101|0,o=(o<<12|o>>>20)+n|0,a+=(o&n|~o&r)+t[14]-1502002290|0,a=(a<<17|a>>>15)+o|0,r+=(a&o|~a&n)+t[15]+1236535329|0,r=(r<<22|r>>>10)+a|0,n+=(r&o|a&~o)+t[1]-165796510|0,n=(n<<5|n>>>27)+r|0,o+=(n&a|r&~a)+t[6]-1069501632|0,o=(o<<9|o>>>23)+n|0,a+=(o&r|n&~r)+t[11]+643717713|0,a=(a<<14|a>>>18)+o|0,r+=(a&n|o&~n)+t[0]-373897302|0,r=(r<<20|r>>>12)+a|0,n+=(r&o|a&~o)+t[5]-701558691|0,n=(n<<5|n>>>27)+r|0,o+=(n&a|r&~a)+t[10]+38016083|0,o=(o<<9|o>>>23)+n|0,a+=(o&r|n&~r)+t[15]-660478335|0,a=(a<<14|a>>>18)+o|0,r+=(a&n|o&~n)+t[4]-405537848|0,r=(r<<20|r>>>12)+a|0,n+=(r&o|a&~o)+t[9]+568446438|0,n=(n<<5|n>>>27)+r|0,o+=(n&a|r&~a)+t[14]-1019803690|0,o=(o<<9|o>>>23)+n|0,a+=(o&r|n&~r)+t[3]-187363961|0,a=(a<<14|a>>>18)+o|0,r+=(a&n|o&~n)+t[8]+1163531501|0,r=(r<<20|r>>>12)+a|0,n+=(r&o|a&~o)+t[13]-1444681467|0,n=(n<<5|n>>>27)+r|0,o+=(n&a|r&~a)+t[2]-51403784|0,o=(o<<9|o>>>23)+n|0,a+=(o&r|n&~r)+t[7]+1735328473|0,a=(a<<14|a>>>18)+o|0,r+=(a&n|o&~n)+t[12]-1926607734|0,r=(r<<20|r>>>12)+a|0,n+=(r^a^o)+t[5]-378558|0,n=(n<<4|n>>>28)+r|0,o+=(n^r^a)+t[8]-2022574463|0,o=(o<<11|o>>>21)+n|0,a+=(o^n^r)+t[11]+1839030562|0,a=(a<<16|a>>>16)+o|0,r+=(a^o^n)+t[14]-35309556|0,r=(r<<23|r>>>9)+a|0,n+=(r^a^o)+t[1]-1530992060|0,n=(n<<4|n>>>28)+r|0,o+=(n^r^a)+t[4]+1272893353|0,o=(o<<11|o>>>21)+n|0,a+=(o^n^r)+t[7]-155497632|0,a=(a<<16|a>>>16)+o|0,r+=(a^o^n)+t[10]-1094730640|0,r=(r<<23|r>>>9)+a|0,n+=(r^a^o)+t[13]+681279174|0,n=(n<<4|n>>>28)+r|0,o+=(n^r^a)+t[0]-358537222|0,o=(o<<11|o>>>21)+n|0,a+=(o^n^r)+t[3]-722521979|0,a=(a<<16|a>>>16)+o|0,r+=(a^o^n)+t[6]+76029189|0,r=(r<<23|r>>>9)+a|0,n+=(r^a^o)+t[9]-640364487|0,n=(n<<4|n>>>28)+r|0,o+=(n^r^a)+t[12]-421815835|0,o=(o<<11|o>>>21)+n|0,a+=(o^n^r)+t[15]+530742520|0,a=(a<<16|a>>>16)+o|0,r+=(a^o^n)+t[2]-995338651|0,r=(r<<23|r>>>9)+a|0,n+=(a^(r|~o))+t[0]-198630844|0,n=(n<<6|n>>>26)+r|0,o+=(r^(n|~a))+t[7]+1126891415|0,o=(o<<10|o>>>22)+n|0,a+=(n^(o|~r))+t[14]-1416354905|0,a=(a<<15|a>>>17)+o|0,r+=(o^(a|~n))+t[5]-57434055|0,r=(r<<21|r>>>11)+a|0,n+=(a^(r|~o))+t[12]+1700485571|0,n=(n<<6|n>>>26)+r|0,o+=(r^(n|~a))+t[3]-1894986606|0,o=(o<<10|o>>>22)+n|0,a+=(n^(o|~r))+t[10]-1051523|0,a=(a<<15|a>>>17)+o|0,r+=(o^(a|~n))+t[1]-2054922799|0,r=(r<<21|r>>>11)+a|0,n+=(a^(r|~o))+t[8]+1873313359|0,n=(n<<6|n>>>26)+r|0,o+=(r^(n|~a))+t[15]-30611744|0,o=(o<<10|o>>>22)+n|0,a+=(n^(o|~r))+t[6]-1560198380|0,a=(a<<15|a>>>17)+o|0,r+=(o^(a|~n))+t[13]+1309151649|0,r=(r<<21|r>>>11)+a|0,n+=(a^(r|~o))+t[4]-145523070|0,n=(n<<6|n>>>26)+r|0,o+=(r^(n|~a))+t[11]-1120210379|0,o=(o<<10|o>>>22)+n|0,a+=(n^(o|~r))+t[2]+718787259|0,a=(a<<15|a>>>17)+o|0,r+=(o^(a|~n))+t[9]-343485551|0,r=(r<<21|r>>>11)+a|0,e[0]=n+e[0]|0,e[1]=r+e[1]|0,e[2]=a+e[2]|0,e[3]=o+e[3]|0}function md5blk(e){var t=[],n;for(n=0;n<64;n+=4)t[n>>2]=e.charCodeAt(n)+(e.charCodeAt(n+1)<<8)+(e.charCodeAt(n+2)<<16)+(e.charCodeAt(n+3)<<24);return t}function md5blk_array(e){var t=[],n;for(n=0;n<64;n+=4)t[n>>2]=e[n]+(e[n+1]<<8)+(e[n+2]<<16)+(e[n+3]<<24);return t}function md51(e){var t=e.length,n=[1732584193,-271733879,-1732584194,271733878],r,a,o,s,c,l;for(r=64;r<=t;r+=64)md5cycle(n,md5blk(e.substring(r-64,r)));for(e=e.substring(r-64),a=e.length,o=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],r=0;r<a;r+=1)o[r>>2]|=e.charCodeAt(r)<<(r%4<<3);if(o[r>>2]|=128<<(r%4<<3),r>55)for(md5cycle(n,o),r=0;r<16;r+=1)o[r]=0;return s=t*8,s=s.toString(16).match(/(.*?)(.{0,8})$/),c=parseInt(s[2],16),l=parseInt(s[1],16)||0,o[14]=c,o[15]=l,md5cycle(n,o),n}function md51_array(e){var t=e.length,n=[1732584193,-271733879,-1732584194,271733878],r,a,o,s,c,l;for(r=64;r<=t;r+=64)md5cycle(n,md5blk_array(e.subarray(r-64,r)));for(e=r-64<t?e.subarray(r-64):new Uint8Array,a=e.length,o=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],r=0;r<a;r+=1)o[r>>2]|=e[r]<<(r%4<<3);if(o[r>>2]|=128<<(r%4<<3),r>55)for(md5cycle(n,o),r=0;r<16;r+=1)o[r]=0;return s=t*8,s=s.toString(16).match(/(.*?)(.{0,8})$/),c=parseInt(s[2],16),l=parseInt(s[1],16)||0,o[14]=c,o[15]=l,md5cycle(n,o),n}function rhex(e){var n=``,r;for(r=0;r<4;r+=1)n+=t[e>>r*8+4&15]+t[e>>r*8&15];return n}function hex(e){var t;for(t=0;t<e.length;t+=1)e[t]=rhex(e[t]);return e.join(``)}hex(md51(`hello`)),typeof ArrayBuffer<`u`&&!ArrayBuffer.prototype.slice&&(function(){function clamp(e,t){return e=e|0||0,e<0?Math.max(e+t,0):Math.min(e,t)}ArrayBuffer.prototype.slice=function(t,n){var r=this.byteLength,a=clamp(t,r),o=r,s,c,l,u;return n!==e&&(o=clamp(n,r)),a>o?new ArrayBuffer(0):(s=o-a,c=new ArrayBuffer(s),l=new Uint8Array(c),u=new Uint8Array(this,a,s),l.set(u),c)}})();function toUtf8(e){return/[\u0080-\uFFFF]/.test(e)&&(e=unescape(encodeURIComponent(e))),e}function utf8Str2ArrayBuffer(e,t){var n=e.length,r=new ArrayBuffer(n),a=new Uint8Array(r),o;for(o=0;o<n;o+=1)a[o]=e.charCodeAt(o);return t?a:r}function arrayBuffer2Utf8Str(e){return String.fromCharCode.apply(null,new Uint8Array(e))}function concatenateArrayBuffers(e,t,n){var r=new Uint8Array(e.byteLength+t.byteLength);return r.set(new Uint8Array(e)),r.set(new Uint8Array(t),e.byteLength),n?r:r.buffer}function hexToBinaryString(e){var t=[],n=e.length,r;for(r=0;r<n-1;r+=2)t.push(parseInt(e.substr(r,2),16));return String.fromCharCode.apply(String,t)}function SparkMD5(){this.reset()}return SparkMD5.prototype.append=function(e){return this.appendBinary(toUtf8(e)),this},SparkMD5.prototype.appendBinary=function(e){this._buff+=e,this._length+=e.length;var t=this._buff.length,n;for(n=64;n<=t;n+=64)md5cycle(this._hash,md5blk(this._buff.substring(n-64,n)));return this._buff=this._buff.substring(n-64),this},SparkMD5.prototype.end=function(e){var t=this._buff,n=t.length,r,a=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],o;for(r=0;r<n;r+=1)a[r>>2]|=t.charCodeAt(r)<<(r%4<<3);return this._finish(a,n),o=hex(this._hash),e&&(o=hexToBinaryString(o)),this.reset(),o},SparkMD5.prototype.reset=function(){return this._buff=``,this._length=0,this._hash=[1732584193,-271733879,-1732584194,271733878],this},SparkMD5.prototype.getState=function(){return{buff:this._buff,length:this._length,hash:this._hash.slice()}},SparkMD5.prototype.setState=function(e){return this._buff=e.buff,this._length=e.length,this._hash=e.hash,this},SparkMD5.prototype.destroy=function(){delete this._hash,delete this._buff,delete this._length},SparkMD5.prototype._finish=function(e,t){var n=t,r,a,o;if(e[n>>2]|=128<<(n%4<<3),n>55)for(md5cycle(this._hash,e),n=0;n<16;n+=1)e[n]=0;r=this._length*8,r=r.toString(16).match(/(.*?)(.{0,8})$/),a=parseInt(r[2],16),o=parseInt(r[1],16)||0,e[14]=a,e[15]=o,md5cycle(this._hash,e)},SparkMD5.hash=function(e,t){return SparkMD5.hashBinary(toUtf8(e),t)},SparkMD5.hashBinary=function(e,t){var n=hex(md51(e));return t?hexToBinaryString(n):n},SparkMD5.ArrayBuffer=function(){this.reset()},SparkMD5.ArrayBuffer.prototype.append=function(e){var t=concatenateArrayBuffers(this._buff.buffer,e,!0),n=t.length,r;for(this._length+=e.byteLength,r=64;r<=n;r+=64)md5cycle(this._hash,md5blk_array(t.subarray(r-64,r)));return this._buff=r-64<n?new Uint8Array(t.buffer.slice(r-64)):new Uint8Array,this},SparkMD5.ArrayBuffer.prototype.end=function(e){var t=this._buff,n=t.length,r=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],a,o;for(a=0;a<n;a+=1)r[a>>2]|=t[a]<<(a%4<<3);return this._finish(r,n),o=hex(this._hash),e&&(o=hexToBinaryString(o)),this.reset(),o},SparkMD5.ArrayBuffer.prototype.reset=function(){return this._buff=new Uint8Array,this._length=0,this._hash=[1732584193,-271733879,-1732584194,271733878],this},SparkMD5.ArrayBuffer.prototype.getState=function(){var e=SparkMD5.prototype.getState.call(this);return e.buff=arrayBuffer2Utf8Str(e.buff),e},SparkMD5.ArrayBuffer.prototype.setState=function(e){return e.buff=utf8Str2ArrayBuffer(e.buff,!0),SparkMD5.prototype.setState.call(this,e)},SparkMD5.ArrayBuffer.prototype.destroy=SparkMD5.prototype.destroy,SparkMD5.ArrayBuffer.prototype._finish=SparkMD5.prototype._finish,SparkMD5.ArrayBuffer.hash=function(e,t){var n=hex(md51_array(new Uint8Array(e)));return t?hexToBinaryString(n):n},SparkMD5})})),getRandomValues$1,rnds8$1=new Uint8Array(16);function rng$1(){if(!getRandomValues$1&&(getRandomValues$1=typeof crypto<`u`&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||typeof msCrypto<`u`&&typeof msCrypto.getRandomValues==`function`&&msCrypto.getRandomValues.bind(msCrypto),!getRandomValues$1))throw Error(`crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported`);return getRandomValues$1(rnds8$1)}__name(rng$1,`rng`);var regex_default=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function validate$1(e){return typeof e==`string`&®ex_default.test(e)}__name(validate$1,`validate`);for(var byteToHex$1=[],i=0;i<256;++i)byteToHex$1.push((i+256).toString(16).substr(1));function stringify$2(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0,n=(byteToHex$1[e[t+0]]+byteToHex$1[e[t+1]]+byteToHex$1[e[t+2]]+byteToHex$1[e[t+3]]+`-`+byteToHex$1[e[t+4]]+byteToHex$1[e[t+5]]+`-`+byteToHex$1[e[t+6]]+byteToHex$1[e[t+7]]+`-`+byteToHex$1[e[t+8]]+byteToHex$1[e[t+9]]+`-`+byteToHex$1[e[t+10]]+byteToHex$1[e[t+11]]+byteToHex$1[e[t+12]]+byteToHex$1[e[t+13]]+byteToHex$1[e[t+14]]+byteToHex$1[e[t+15]]).toLowerCase();if(!validate$1(n))throw TypeError(`Stringified UUID is invalid`);return n}__name(stringify$2,`stringify`);function v4$1(e,t,n){e=e||{};var r=e.random||(e.rng||rng$1)();if(r[6]=r[6]&15|64,r[8]=r[8]&63|128,t){n=n||0;for(var a=0;a<16;++a)t[n+a]=r[a];return t}return stringify$2(r)}__name(v4$1,`v4`);var require_vuvuzela=__commonJSMin((e=>{e.stringify=function stringify(e){var t=[];t.push({obj:e});for(var n=``,r,a,o,s,c,l,u,d,p,m,g;r=t.pop();)if(a=r.obj,o=r.prefix||``,s=r.val||``,n+=o,s)n+=s;else if(typeof a!=`object`)n+=a===void 0?null:JSON.stringify(a);else if(a===null)n+=`null`;else if(Array.isArray(a)){for(t.push({val:`]`}),c=a.length-1;c>=0;c--)l=c===0?``:`,`,t.push({obj:a[c],prefix:l});t.push({val:`[`})}else{for(d in u=[],a)a.hasOwnProperty(d)&&u.push(d);for(t.push({val:`}`}),c=u.length-1;c>=0;c--)p=u[c],m=a[p],g=c>0?`,`:``,g+=JSON.stringify(p)+`:`,t.push({obj:m,prefix:g});t.push({val:`{`})}return n};function pop(e,t,n){var r=n[n.length-1];e===r.element&&(n.pop(),r=n[n.length-1]);var a=r.element,o=r.index;if(Array.isArray(a))a.push(e);else if(o===t.length-2){var s=t.pop();a[s]=e}else t.push(e)}e.parse=function(e){for(var t=[],n=[],r=0,a,o,s,c,l,u,d,p,m;;){if(a=e[r++],a===`}`||a===`]`||a===void 0){if(t.length===1)return t.pop();pop(t.pop(),t,n);continue}switch(a){case` `:case` `:case`
|
|
2
2
|
`:case`:`:case`,`:break;case`n`:r+=3,pop(null,t,n);break;case`t`:r+=3,pop(!0,t,n);break;case`f`:r+=4,pop(!1,t,n);break;case`0`:case`1`:case`2`:case`3`:case`4`:case`5`:case`6`:case`7`:case`8`:case`9`:case`-`:for(o=``,r--;;)if(s=e[r++],/[\d\.\-e\+]/.test(s))o+=s;else{r--;break}pop(parseFloat(o),t,n);break;case`"`:for(c=``,l=void 0,u=0;d=e[r++],d!==`"`||l===`\\`&&u%2==1;)c+=d,l=d,l===`\\`?u++:u=0;pop(JSON.parse(`"`+c+`"`),t,n);break;case`[`:p={element:[],index:t.length},t.push(p.element),n.push(p);break;case`{`:m={element:{},index:t.length},t.push(m.element),n.push(m);break;default:throw Error(`unexpectedly reached end of input: `+a)}}}})),require_events=__commonJSMin(((e,t)=>{var n=typeof Reflect==`object`?Reflect:null,r=n&&typeof n.apply==`function`?n.apply:function ReflectApply(e,t,n){return Function.prototype.apply.call(e,t,n)},a=n&&typeof n.ownKeys==`function`?n.ownKeys:Object.getOwnPropertySymbols?function ReflectOwnKeys(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function ReflectOwnKeys(e){return Object.getOwnPropertyNames(e)};function ProcessEmitWarning(e){console&&console.warn&&console.warn(e)}var o=Number.isNaN||function NumberIsNaN(e){return e!==e};function EventEmitter(){EventEmitter.init.call(this)}t.exports=EventEmitter,t.exports.once=once,EventEmitter.EventEmitter=EventEmitter,EventEmitter.prototype._events=void 0,EventEmitter.prototype._eventsCount=0,EventEmitter.prototype._maxListeners=void 0;var s=10;function checkListener(e){if(typeof e!=`function`)throw TypeError(`The "listener" argument must be of type Function. Received type `+typeof e)}Object.defineProperty(EventEmitter,`defaultMaxListeners`,{enumerable:!0,get:function(){return s},set:function(e){if(typeof e!=`number`||e<0||o(e))throw RangeError(`The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received `+e+`.`);s=e}}),EventEmitter.init=function(){(this._events===void 0||this._events===Object.getPrototypeOf(this)._events)&&(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},EventEmitter.prototype.setMaxListeners=function setMaxListeners(e){if(typeof e!=`number`||e<0||o(e))throw RangeError(`The value of "n" is out of range. It must be a non-negative number. Received `+e+`.`);return this._maxListeners=e,this};function _getMaxListeners(e){return e._maxListeners===void 0?EventEmitter.defaultMaxListeners:e._maxListeners}EventEmitter.prototype.getMaxListeners=function getMaxListeners(){return _getMaxListeners(this)},EventEmitter.prototype.emit=function emit(e){for(var t=[],n=1;n<arguments.length;n++)t.push(arguments[n]);var a=e===`error`,o=this._events;if(o!==void 0)a=a&&o.error===void 0;else if(!a)return!1;if(a){var s;if(t.length>0&&(s=t[0]),s instanceof Error)throw s;var c=Error(`Unhandled error.`+(s?` (`+s.message+`)`:``));throw c.context=s,c}var l=o[e];if(l===void 0)return!1;if(typeof l==`function`)r(l,this,t);else for(var u=l.length,d=arrayClone(l,u),n=0;n<u;++n)r(d[n],this,t);return!0};function _addListener(e,t,n,r){var a,o,s;if(checkListener(n),o=e._events,o===void 0?(o=e._events=Object.create(null),e._eventsCount=0):(o.newListener!==void 0&&(e.emit(`newListener`,t,n.listener?n.listener:n),o=e._events),s=o[t]),s===void 0)s=o[t]=n,++e._eventsCount;else if(typeof s==`function`?s=o[t]=r?[n,s]:[s,n]:r?s.unshift(n):s.push(n),a=_getMaxListeners(e),a>0&&s.length>a&&!s.warned){s.warned=!0;var c=Error(`Possible EventEmitter memory leak detected. `+s.length+` `+String(t)+` listeners added. Use emitter.setMaxListeners() to increase limit`);c.name=`MaxListenersExceededWarning`,c.emitter=e,c.type=t,c.count=s.length,ProcessEmitWarning(c)}return e}EventEmitter.prototype.addListener=function addListener(e,t){return _addListener(this,e,t,!1)},EventEmitter.prototype.on=EventEmitter.prototype.addListener,EventEmitter.prototype.prependListener=function prependListener(e,t){return _addListener(this,e,t,!0)};function onceWrapper(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,arguments.length===0?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function _onceWrap(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},a=onceWrapper.bind(r);return a.listener=n,r.wrapFn=a,a}EventEmitter.prototype.once=function once(e,t){return checkListener(t),this.on(e,_onceWrap(this,e,t)),this},EventEmitter.prototype.prependOnceListener=function prependOnceListener(e,t){return checkListener(t),this.prependListener(e,_onceWrap(this,e,t)),this},EventEmitter.prototype.removeListener=function removeListener(e,t){var n,r,a,o,s;if(checkListener(t),r=this._events,r===void 0||(n=r[e],n===void 0))return this;if(n===t||n.listener===t)--this._eventsCount===0?this._events=Object.create(null):(delete r[e],r.removeListener&&this.emit(`removeListener`,e,n.listener||t));else if(typeof n!=`function`){for(a=-1,o=n.length-1;o>=0;o--)if(n[o]===t||n[o].listener===t){s=n[o].listener,a=o;break}if(a<0)return this;a===0?n.shift():spliceOne(n,a),n.length===1&&(r[e]=n[0]),r.removeListener!==void 0&&this.emit(`removeListener`,e,s||t)}return this},EventEmitter.prototype.off=EventEmitter.prototype.removeListener,EventEmitter.prototype.removeAllListeners=function removeAllListeners(e){var t,n=this._events,r;if(n===void 0)return this;if(n.removeListener===void 0)return arguments.length===0?(this._events=Object.create(null),this._eventsCount=0):n[e]!==void 0&&(--this._eventsCount===0?this._events=Object.create(null):delete n[e]),this;if(arguments.length===0){var a=Object.keys(n),o;for(r=0;r<a.length;++r)o=a[r],o!==`removeListener`&&this.removeAllListeners(o);return this.removeAllListeners(`removeListener`),this._events=Object.create(null),this._eventsCount=0,this}if(t=n[e],typeof t==`function`)this.removeListener(e,t);else if(t!==void 0)for(r=t.length-1;r>=0;r--)this.removeListener(e,t[r]);return this};function _listeners(e,t,n){var r=e._events;if(r===void 0)return[];var a=r[t];return a===void 0?[]:typeof a==`function`?n?[a.listener||a]:[a]:n?unwrapListeners(a):arrayClone(a,a.length)}EventEmitter.prototype.listeners=function listeners(e){return _listeners(this,e,!0)},EventEmitter.prototype.rawListeners=function rawListeners(e){return _listeners(this,e,!1)},EventEmitter.listenerCount=function(e,t){return typeof e.listenerCount==`function`?e.listenerCount(t):listenerCount.call(e,t)},EventEmitter.prototype.listenerCount=listenerCount;function listenerCount(e){var t=this._events;if(t!==void 0){var n=t[e];if(typeof n==`function`)return 1;if(n!==void 0)return n.length}return 0}EventEmitter.prototype.eventNames=function eventNames(){return this._eventsCount>0?a(this._events):[]};function arrayClone(e,t){for(var n=Array(t),r=0;r<t;++r)n[r]=e[r];return n}function spliceOne(e,t){for(;t+1<e.length;t++)e[t]=e[t+1];e.pop()}function unwrapListeners(e){for(var t=Array(e.length),n=0;n<t.length;++n)t[n]=e[n].listener||e[n];return t}function once(e,t){return new Promise(function(n,r){function errorListener(n){e.removeListener(t,resolver),r(n)}function resolver(){typeof e.removeListener==`function`&&e.removeListener(`error`,errorListener),n([].slice.call(arguments))}eventTargetAgnosticAddListener(e,t,resolver,{once:!0}),t!==`error`&&addErrorHandlerIfEventEmitter(e,errorListener,{once:!0})})}function addErrorHandlerIfEventEmitter(e,t,n){typeof e.on==`function`&&eventTargetAgnosticAddListener(e,`error`,t,n)}function eventTargetAgnosticAddListener(e,t,n,r){if(typeof e.on==`function`)r.once?e.once(t,n):e.on(t,n);else if(typeof e.addEventListener==`function`)e.addEventListener(t,function wrapListener(a){r.once&&e.removeEventListener(t,wrapListener),n(a)});else throw TypeError(`The "emitter" argument must be of type EventEmitter. Received type `+typeof e)}})),import_spark_md5=__toESM(require_spark_md5()),import_vuvuzela=__toESM(require_vuvuzela()),import_events=__toESM(require_events());function isBinaryObject$1(e){return typeof ArrayBuffer<`u`&&e instanceof ArrayBuffer||typeof Blob<`u`&&e instanceof Blob}__name(isBinaryObject$1,`isBinaryObject`);function cloneBinaryObject$1(e){return e instanceof ArrayBuffer?e.slice(0):e.slice(0,e.size,e.type)}__name(cloneBinaryObject$1,`cloneBinaryObject`);var funcToString$1=Function.prototype.toString,objectCtorString$1=funcToString$1.call(Object);function isPlainObject$1(e){var t=Object.getPrototypeOf(e);if(t===null)return!0;var n=t.constructor;return typeof n==`function`&&n instanceof n&&funcToString$1.call(n)==objectCtorString$1}__name(isPlainObject$1,`isPlainObject`);function clone$1(e){var t,n,r;if(!e||typeof e!=`object`)return e;if(Array.isArray(e)){for(t=[],n=0,r=e.length;n<r;n++)t[n]=clone$1(e[n]);return t}if(e instanceof Date&&isFinite(e))return e.toISOString();if(isBinaryObject$1(e))return cloneBinaryObject$1(e);if(!isPlainObject$1(e))return e;for(n in t={},e)if(Object.prototype.hasOwnProperty.call(e,n)){var a=clone$1(e[n]);a!==void 0&&(t[n]=a)}return t}__name(clone$1,`clone`);function once(e){var t=!1;return function(...n){if(t)throw Error(`once called more than once`);t=!0,e.apply(this,n)}}function toPromise(e){return function(...t){t=clone$1(t);var n=this,r=typeof t[t.length-1]==`function`?t.pop():!1,a=new Promise(function(r,a){var o;try{var s=once(function(e,t){e?a(e):r(t)});t.push(s),o=e.apply(n,t),o&&typeof o.then==`function`&&r(o)}catch(e){a(e)}});return r&&a.then(function(e){r(null,e)},r),a}}function logApiCall(e,t,n){if(e.constructor.listeners(`debug`).length){for(var r=[`api`,e.name,t],a=0;a<n.length-1;a++)r.push(n[a]);e.constructor.emit(`debug`,r);var o=n[n.length-1];n[n.length-1]=function(n,r){var a=[`api`,e.name,t];a=a.concat(n?[`error`,n]:[`success`,r]),e.constructor.emit(`debug`,a),o(n,r)}}}function adapterFun(e,t){return toPromise(function(...n){if(this._closed)return Promise.reject(Error(`database is closed`));if(this._destroyed)return Promise.reject(Error(`database is destroyed`));var r=this;return logApiCall(r,e,n),this.taskqueue.isReady?t.apply(this,n):new Promise(function(t,a){r.taskqueue.addTask(function(o){o?a(o):t(r[e].apply(r,n))})})})}function pick$1(e,t){for(var n={},r=0,a=t.length;r<a;r++){var o=t[r];o in e&&(n[o]=e[o])}return n}__name(pick$1,`pick`);var MAX_NUM_CONCURRENT_REQUESTS=6;function identityFunction(e){return e}function formatResultForOpenRevsGet(e){return[{ok:e}]}function bulkGet(e,t,n){var r=t.docs,a=new Map;r.forEach(function(e){a.has(e.id)?a.get(e.id).push(e):a.set(e.id,[e])});var o=a.size,s=0,c=Array(o);function collapseResultsAndFinish(){var e=[];c.forEach(function(t){t.docs.forEach(function(n){e.push({id:t.id,docs:[n]})})}),n(null,{results:e})}function checkDone(){++s===o&&collapseResultsAndFinish()}function gotResult(e,t,n){c[e]={id:t,docs:n},checkDone()}var l=[];a.forEach(function(e,t){l.push(t)});var u=0;function nextBatch(){if(!(u>=l.length)){var e=Math.min(u+MAX_NUM_CONCURRENT_REQUESTS,l.length),t=l.slice(u,e);processBatch(t,u),u+=t.length}}function processBatch(n,r){n.forEach(function(n,o){var s=r+o,c=a.get(n),l=pick$1(c[0],[`atts_since`,`attachments`]);l.open_revs=c.map(function(e){return e.rev}),l.open_revs=l.open_revs.filter(identityFunction);var u=identityFunction;l.open_revs.length===0&&(delete l.open_revs,u=formatResultForOpenRevsGet),[`revs`,`attachments`,`binary`,`ajax`,`latest`].forEach(function(e){e in t&&(l[e]=t[e])}),e.get(n,l,function(e,t){gotResult(s,n,e?[{error:e}]:u(t)),nextBatch()})})}nextBatch()}var hasLocal$1;try{localStorage.setItem(`_pouch_check_localstorage`,1),hasLocal$1=!!localStorage.getItem(`_pouch_check_localstorage`)}catch{hasLocal$1=!1}function hasLocalStorage(){return hasLocal$1}var nextTick$1=typeof queueMicrotask==`function`?queueMicrotask:function nextTick(e){Promise.resolve().then(e)},Changes=class extends import_events.default{constructor(){super(),this._listeners={},hasLocalStorage()&&addEventListener(`storage`,e=>{this.emit(e.key)})}addListener(e,t,n,r){if(this._listeners[t])return;var a=!1,o=this;function eventFunction(){if(!o._listeners[t])return;if(a){a=`waiting`;return}a=!0;var e=pick$1(r,[`style`,`include_docs`,`attachments`,`conflicts`,`filter`,`doc_ids`,`view`,`since`,`query_params`,`binary`,`return_docs`]);function onError(){a=!1}n.changes(e).on(`change`,function(e){e.seq>r.since&&!r.cancelled&&(r.since=e.seq,r.onChange(e))}).on(`complete`,function(){a===`waiting`&&nextTick$1(eventFunction),a=!1}).on(`error`,onError)}this._listeners[t]=eventFunction,this.on(e,eventFunction)}removeListener(e,t){t in this._listeners&&(super.removeListener(e,this._listeners[t]),delete this._listeners[t])}notifyLocalWindows(e){hasLocalStorage()&&(localStorage[e]=localStorage[e]===`a`?`b`:`a`)}notify(e){this.emit(e),this.notifyLocalWindows(e)}};function guardedConsole$1(e){if(typeof console<`u`&&typeof console[e]==`function`){var t=Array.prototype.slice.call(arguments,1);console[e].apply(console,t)}}__name(guardedConsole$1,`guardedConsole`);function randomNumber(e,t){var n=6e5;e=parseInt(e,10)||0,t=parseInt(t,10),t!==t||t<=e?t=(e||1)<<1:t+=1,t>n&&(e=n>>1,t=n);var r=Math.random();return~~((t-e)*r+e)}function defaultBackOff(e){var t=0;return e||(t=2e3),randomNumber(e,t)}function explainError(e,t){guardedConsole$1(`info`,`The above `+e+` is totally normal. `+t)}var PouchError$1=class extends Error{static{__name(this,`PouchError`)}constructor(e,t,n){super(),this.status=e,this.name=t,this.message=n,this.error=!0}toString(){return JSON.stringify({status:this.status,name:this.name,message:this.message,reason:this.reason})}};new PouchError$1(401,`unauthorized`,`Name or password is incorrect.`);var MISSING_BULK_DOCS$1=new PouchError$1(400,`bad_request`,`Missing JSON list of 'docs'`),MISSING_DOC$1=new PouchError$1(404,`not_found`,`missing`),REV_CONFLICT$1=new PouchError$1(409,`conflict`,`Document update conflict`),INVALID_ID$1=new PouchError$1(400,`bad_request`,`_id field must contain a string`),MISSING_ID$1=new PouchError$1(412,`missing_id`,`_id is required for puts`),RESERVED_ID$1=new PouchError$1(400,`bad_request`,`Only reserved document ids may start with underscore.`);new PouchError$1(412,`precondition_failed`,`Database not open`);var UNKNOWN_ERROR$1=new PouchError$1(500,`unknown_error`,`Database encountered an unknown error`),BAD_ARG$1=new PouchError$1(500,`badarg`,`Some query argument is invalid`);new PouchError$1(400,`invalid_request`,`Request was invalid`);var QUERY_PARSE_ERROR$1=new PouchError$1(400,`query_parse_error`,`Some query parameter is invalid`),DOC_VALIDATION$1=new PouchError$1(500,`doc_validation`,`Bad special document member`),BAD_REQUEST$1=new PouchError$1(400,`bad_request`,`Something wrong with the request`),NOT_AN_OBJECT$1=new PouchError$1(400,`bad_request`,`Document must be a JSON object`);new PouchError$1(404,`not_found`,`Database not found`);var IDB_ERROR$1=new PouchError$1(500,`indexed_db_went_bad`,`unknown`);new PouchError$1(500,`web_sql_went_bad`,`unknown`),new PouchError$1(500,`levelDB_went_went_bad`,`unknown`),new PouchError$1(403,`forbidden`,`Forbidden by design doc validate_doc_update function`);var INVALID_REV$1=new PouchError$1(400,`bad_request`,`Invalid rev format`);new PouchError$1(412,`file_exists`,`The database could not be created, the file already exists.`);var MISSING_STUB$1=new PouchError$1(412,`missing_stub`,`A pre-existing attachment stub wasn't found`);new PouchError$1(413,`invalid_url`,`Provided URL is invalid`);function createError$1(e,t){function CustomPouchError(t){for(var n=Object.getOwnPropertyNames(e),r=0,a=n.length;r<a;r++)typeof e[n[r]]!=`function`&&(this[n[r]]=e[n[r]]);this.stack===void 0&&(this.stack=Error().stack),t!==void 0&&(this.reason=t)}return CustomPouchError.prototype=PouchError$1.prototype,new CustomPouchError(t)}__name(createError$1,`createError`);function generateErrorFromResponse$1(e){if(typeof e!=`object`){var t=e;e=UNKNOWN_ERROR$1,e.data=t}return`error`in e&&e.error===`conflict`&&(e.name=`conflict`,e.status=409),`name`in e||(e.name=e.error||`unknown`),`status`in e||(e.status=500),`message`in e||(e.message=e.message||e.reason),`stack`in e||(e.stack=Error().stack),e}__name(generateErrorFromResponse$1,`generateErrorFromResponse`);function tryFilter(e,t,n){try{return!e(t,n)}catch(e){return createError$1(BAD_REQUEST$1,`Filter function threw: `+e.toString())}}function filterChange(e){var t={},n=e.filter&&typeof e.filter==`function`;return t.query=e.query_params,function filter(r){r.doc||(r.doc={});var a=n&&tryFilter(e.filter,r.doc,t);if(typeof a==`object`)return a;if(a)return!1;if(!e.include_docs)delete r.doc;else if(!e.attachments)for(var o in r.doc._attachments)Object.prototype.hasOwnProperty.call(r.doc._attachments,o)&&(r.doc._attachments[o].stub=!0);return!0}}function invalidIdError(e){var t;if(e?typeof e==`string`?/^_/.test(e)&&!/^_(design|local)/.test(e)&&(t=createError$1(RESERVED_ID$1)):t=createError$1(INVALID_ID$1):t=createError$1(MISSING_ID$1),t)throw t}function isRemote$1(e){return typeof e._remote==`boolean`?e._remote:typeof e.type==`function`?(guardedConsole$1(`warn`,`db.type() is deprecated and will be removed in a future version of PouchDB`),e.type()===`http`):!1}__name(isRemote$1,`isRemote`);function listenerCount(e,t){return`listenerCount`in e?e.listenerCount(t):import_events.default.listenerCount(e,t)}function parseDesignDocFunctionName(e){if(!e)return null;var t=e.split(`/`);return t.length===2?t:t.length===1?[e,e]:null}function normalizeDesignDocFunctionName(e){var t=parseDesignDocFunctionName(e);return t?t.join(`/`):null}var keys=[`source`,`protocol`,`authority`,`userInfo`,`user`,`password`,`host`,`port`,`relative`,`path`,`directory`,`file`,`query`,`anchor`],qName=`queryKey`,qParser=/(?:^|&)([^&=]*)=?([^&]*)/g,parser=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;function parseUri(e){for(var t=parser.exec(e),n={},r=14;r--;){var a=keys[r],o=t[r]||``;n[a]=[`user`,`password`].indexOf(a)===-1?o:decodeURIComponent(o)}return n[qName]={},n[keys[12]].replace(qParser,function(e,t,r){t&&(n[qName][t]=r)}),n}function scopeEval(e,t){var n=[],r=[];for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(n.push(a),r.push(t[a]));return n.push(e),Function.apply(null,n).apply(null,r)}function upsert$1(e,t,n){return e.get(t).catch(function(e){if(e.status!==404)throw e;return{}}).then(function(r){var a=r._rev,o=n(r);return o?(o._id=t,o._rev=a,tryAndPut$1(e,o,n)):{updated:!1,rev:a}})}__name(upsert$1,`upsert`);function tryAndPut$1(e,t,n){return e.put(t).then(function(e){return{updated:!0,rev:e.rev}},function(r){if(r.status!==409)throw r;return upsert$1(e,t._id,n)})}__name(tryAndPut$1,`tryAndPut`);var thisAtob$1=__name(function(e){return atob(e)},`thisAtob`),thisBtoa=function(e){return btoa(e)};function createBlob$1(e,t){e=e||[],t=t||{};try{return new Blob(e,t)}catch(a){if(a.name!==`TypeError`)throw a;for(var n=new(typeof BlobBuilder<`u`?BlobBuilder:typeof MSBlobBuilder<`u`?MSBlobBuilder:typeof MozBlobBuilder<`u`?MozBlobBuilder:WebKitBlobBuilder),r=0;r<e.length;r+=1)n.append(e[r]);return n.getBlob(t.type)}}__name(createBlob$1,`createBlob`);function binaryStringToArrayBuffer$1(e){for(var t=e.length,n=new ArrayBuffer(t),r=new Uint8Array(n),a=0;a<t;a++)r[a]=e.charCodeAt(a);return n}__name(binaryStringToArrayBuffer$1,`binaryStringToArrayBuffer`);function binStringToBluffer$1(e,t){return createBlob$1([binaryStringToArrayBuffer$1(e)],{type:t})}__name(binStringToBluffer$1,`binStringToBluffer`);function b64ToBluffer$1(e,t){return binStringToBluffer$1(thisAtob$1(e),t)}__name(b64ToBluffer$1,`b64ToBluffer`);function arrayBufferToBinaryString(e){for(var t=``,n=new Uint8Array(e),r=n.byteLength,a=0;a<r;a++)t+=String.fromCharCode(n[a]);return t}function readAsBinaryString(e,t){var n=new FileReader,r=typeof n.readAsBinaryString==`function`;n.onloadend=function(e){var n=e.target.result||``;if(r)return t(n);t(arrayBufferToBinaryString(n))},r?n.readAsBinaryString(e):n.readAsArrayBuffer(e)}function blobToBinaryString(e,t){readAsBinaryString(e,function(e){t(e)})}function blobToBase64(e,t){blobToBinaryString(e,function(e){t(thisBtoa(e))})}function readAsArrayBuffer(e,t){var n=new FileReader;n.onloadend=function(e){t(e.target.result||new ArrayBuffer(0))},n.readAsArrayBuffer(e)}var setImmediateShim$1=self.setImmediate||self.setTimeout,MD5_CHUNK_SIZE=32768;function rawToBase64(e){return thisBtoa(e)}function appendBlob(e,t,n,r,a){(n>0||r<t.size)&&(t=t.slice(n,r)),readAsArrayBuffer(t,function(t){e.append(t),a()})}function appendString(e,t,n,r,a){(n>0||r<t.length)&&(t=t.substring(n,r)),e.appendBinary(t),a()}function binaryMd5(e,t){var n=typeof e==`string`,r=n?e.length:e.size,a=Math.min(MD5_CHUNK_SIZE,r),o=Math.ceil(r/a),s=0,c=n?new import_spark_md5.default:new import_spark_md5.default.ArrayBuffer,l=n?appendString:appendBlob;function next(){setImmediateShim$1(loadNextChunk)}function done(){t(rawToBase64(c.end(!0))),c.destroy()}function loadNextChunk(){var t=s*a,n=t+a;s++,s<o?l(c,e,t,n,next):l(c,e,t,n,done)}loadNextChunk()}function stringMd5$1(e){return import_spark_md5.default.hash(e)}__name(stringMd5$1,`stringMd5`);function rev(e,t){if(!t)return v4$1().replace(/-/g,``).toLowerCase();var n=Object.assign({},e);return delete n._rev_tree,stringMd5$1(JSON.stringify(n))}var uuid=v4$1;function winningRev(e){for(var t,n,r,a=e.rev_tree.slice(),o;o=a.pop();){var s=o.ids,c=s[2],l=o.pos;if(c.length){for(var u=0,d=c.length;u<d;u++)a.push({pos:l+1,ids:c[u]});continue}var p=!!s[1].deleted,m=s[0];(!t||(r===p?n===l?t<m:n<l:r))&&(t=m,n=l,r=p)}return n+`-`+t}function traverseRevTree(e,t){for(var n=e.slice(),r;r=n.pop();)for(var a=r.pos,o=r.ids,s=o[2],c=t(s.length===0,a,o[0],r.ctx,o[1]),l=0,u=s.length;l<u;l++)n.push({pos:a+1,ids:s[l],ctx:c})}function sortByPos(e,t){return e.pos-t.pos}function collectLeaves(e){var t=[];traverseRevTree(e,function(e,n,r,a,o){e&&t.push({rev:n+`-`+r,pos:n,opts:o})}),t.sort(sortByPos).reverse();for(var n=0,r=t.length;n<r;n++)delete t[n].pos;return t}function collectConflicts(e){for(var t=winningRev(e),n=collectLeaves(e.rev_tree),r=[],a=0,o=n.length;a<o;a++){var s=n[a];s.rev!==t&&!s.opts.deleted&&r.push(s.rev)}return r}function compactTree(e){var t=[];return traverseRevTree(e.rev_tree,function(e,n,r,a,o){o.status===`available`&&!e&&(t.push(n+`-`+r),o.status=`missing`)}),t}function findPathToLeaf(e,t){let n=[],r=e.slice(),a;for(;a=r.pop();){let{pos:e,ids:o}=a,s=`${e}-${o[0]}`,c=o[2];if(n.push(s),s===t){if(c.length!==0)throw Error(`The requested revision is not a leaf`);return n.reverse()}(c.length===0||c.length>1)&&(n=[]);for(let t=0,n=c.length;t<n;t++)r.push({pos:e+1,ids:c[t]})}if(n.length===0)throw Error(`The requested revision does not exist`);return n.reverse()}function rootToLeaf(e){for(var t=[],n=e.slice(),r;r=n.pop();){var a=r.pos,o=r.ids,s=o[0],c=o[1],l=o[2],u=l.length===0,d=r.history?r.history.slice():[];d.push({id:s,opts:c}),u&&t.push({pos:a+1-d.length,ids:d});for(var p=0,m=l.length;p<m;p++)n.push({pos:a+1,ids:l[p],history:d})}return t.reverse()}function sortByPos$1(e,t){return e.pos-t.pos}function binarySearch(e,t,n){for(var r=0,a=e.length,o;r<a;)o=r+a>>>1,n(e[o],t)<0?r=o+1:a=o;return r}function insertSorted(e,t,n){var r=binarySearch(e,t,n);e.splice(r,0,t)}function pathToTree(e,t){for(var n,r,a=t,o=e.length;a<o;a++){var s=e[a],c=[s.id,s.opts,[]];r?(r[2].push(c),r=c):n=r=c}return n}function compareTree(e,t){return e[0]<t[0]?-1:1}function mergeTree(e,t){for(var n=[{tree1:e,tree2:t}],r=!1;n.length>0;){var a=n.pop(),o=a.tree1,s=a.tree2;(o[1].status||s[1].status)&&(o[1].status=o[1].status===`available`||s[1].status===`available`?`available`:`missing`);for(var c=0;c<s[2].length;c++){if(!o[2][0]){r=`new_leaf`,o[2][0]=s[2][c];continue}for(var l=!1,u=0;u<o[2].length;u++)o[2][u][0]===s[2][c][0]&&(n.push({tree1:o[2][u],tree2:s[2][c]}),l=!0);l||(r=`new_branch`,insertSorted(o[2],s[2][c],compareTree))}}return{conflicts:r,tree:e}}function doMerge(e,t,n){var r=[],a=!1,o=!1,s;if(!e.length)return{tree:[t],conflicts:`new_leaf`};for(var c=0,l=e.length;c<l;c++){var u=e[c];if(u.pos===t.pos&&u.ids[0]===t.ids[0])s=mergeTree(u.ids,t.ids),r.push({pos:u.pos,ids:s.tree}),a=a||s.conflicts,o=!0;else if(n!==!0){var d=u.pos<t.pos?u:t,p=u.pos<t.pos?t:u,m=p.pos-d.pos,g=[],_=[];for(_.push({ids:d.ids,diff:m,parent:null,parentIdx:null});_.length>0;){var v=_.pop();if(v.diff===0){v.ids[0]===p.ids[0]&&g.push(v);continue}for(var y=v.ids[2],b=0,x=y.length;b<x;b++)_.push({ids:y[b],diff:v.diff-1,parent:v.ids,parentIdx:b})}var S=g[0];S?(s=mergeTree(S.ids,p.ids),S.parent[2][S.parentIdx]=s.tree,r.push({pos:d.pos,ids:d.ids}),a=a||s.conflicts,o=!0):r.push(u)}else r.push(u)}return o||r.push(t),r.sort(sortByPos$1),{tree:r,conflicts:a||`internal_node`}}function stem(e,t){for(var n=rootToLeaf(e),r,a,o=0,s=n.length;o<s;o++){var c=n[o],l=c.ids,u;if(l.length>t){r||(r={});var d=l.length-t;u={pos:c.pos+d,ids:pathToTree(l,d)};for(var p=0;p<d;p++){var m=c.pos+p+`-`+l[p].id;r[m]=!0}}else u={pos:c.pos,ids:pathToTree(l,0)};a=a?doMerge(a,u,!0).tree:[u]}return r&&traverseRevTree(a,function(e,t,n){delete r[t+`-`+n]}),{tree:a,revs:r?Object.keys(r):[]}}function merge(e,t,n){var r=doMerge(e,t),a=stem(r.tree,n);return{tree:a.tree,stemmedRevs:a.revs,conflicts:r.conflicts}}function revExists(e,t){for(var n=e.slice(),r=t.split(`-`),a=parseInt(r[0],10),o=r[1],s;s=n.pop();){if(s.pos===a&&s.ids[0]===o)return!0;for(var c=s.ids[2],l=0,u=c.length;l<u;l++)n.push({pos:s.pos+1,ids:c[l]})}return!1}function getTrees(e){return e.ids}function isDeleted(e,t){t||(t=winningRev(e));for(var n=t.substring(t.indexOf(`-`)+1),r=e.rev_tree.map(getTrees),a;a=r.pop();){if(a[0]===n)return!!a[1].deleted;r=r.concat(a[2])}}function isLocalId(e){return typeof e==`string`&&e.startsWith(`_local/`)}function latest(e,t){for(var n=t.rev_tree.slice(),r;r=n.pop();){var a=r.pos,o=r.ids,s=o[0],c=o[1],l=o[2],u=l.length===0,d=r.history?r.history.slice():[];if(d.push({id:s,pos:a,opts:c}),u)for(var p=0,m=d.length;p<m;p++){var g=d[p];if(g.pos+`-`+g.id===e)return a+`-`+s}for(var _=0,v=l.length;_<v;_++)n.push({pos:a+1,ids:l[_],history:d})}throw Error(`Unable to resolve latest revision for id `+t.id+`, rev `+e)}function tryCatchInChangeListener(e,t,n,r){try{e.emit(`change`,t,n,r)}catch(e){guardedConsole$1(`error`,`Error in .on("change", function):`,e)}}function processChange(e,t,n){var r=[{rev:e._rev}];n.style===`all_docs`&&(r=collectLeaves(t.rev_tree).map(function(e){return{rev:e.rev}}));var a={id:t.id,changes:r,doc:e};return isDeleted(t,e._rev)&&(a.deleted=!0),n.conflicts&&(a.doc._conflicts=collectConflicts(t),a.doc._conflicts.length||delete a.doc._conflicts),a}var Changes$1=class extends import_events.default{constructor(e,t,n){super(),this.db=e,t=t?clone$1(t):{};var r=t.complete=once((t,n)=>{t?listenerCount(this,`error`)>0&&this.emit(`error`,t):this.emit(`complete`,n),this.removeAllListeners(),e.removeListener(`destroyed`,onDestroy)});n&&(this.on(`complete`,function(e){n(null,e)}),this.on(`error`,n));let onDestroy=()=>{this.cancel()};e.once(`destroyed`,onDestroy),t.onChange=(e,t,n)=>{this.isCancelled||tryCatchInChangeListener(this,e,t,n)};var a=new Promise(function(e,n){t.complete=function(t,r){t?n(t):e(r)}});this.once(`cancel`,function(){e.removeListener(`destroyed`,onDestroy),t.complete(null,{status:`cancelled`})}),this.then=a.then.bind(a),this.catch=a.catch.bind(a),this.then(function(e){r(null,e)},r),e.taskqueue.isReady?this.validateChanges(t):e.taskqueue.addTask(e=>{e?t.complete(e):this.isCancelled?this.emit(`cancel`):this.validateChanges(t)})}cancel(){this.isCancelled=!0,this.db.taskqueue.isReady&&this.emit(`cancel`)}validateChanges(e){var t=e.complete;PouchDB._changesFilterPlugin?PouchDB._changesFilterPlugin.validate(e,n=>{if(n)return t(n);this.doChanges(e)}):this.doChanges(e)}doChanges(e){var t=e.complete;if(e=clone$1(e),`live`in e&&!(`continuous`in e)&&(e.continuous=e.live),e.processChange=processChange,e.since===`latest`&&(e.since=`now`),e.since||(e.since=0),e.since===`now`){this.db.info().then(n=>{if(this.isCancelled){t(null,{status:`cancelled`});return}e.since=n.update_seq,this.doChanges(e)},t);return}if(PouchDB._changesFilterPlugin){if(PouchDB._changesFilterPlugin.normalize(e),PouchDB._changesFilterPlugin.shouldFilter(this,e))return PouchDB._changesFilterPlugin.filter(this,e)}else [`doc_ids`,`filter`,`selector`,`view`].forEach(function(t){t in e&&guardedConsole$1(`warn`,`The "`+t+`" option was passed in to changes/replicate, but pouchdb-changes-filter plugin is not installed, so it was ignored. Please install the plugin to enable filtering.`)});`descending`in e||(e.descending=!1),e.limit=e.limit===0?1:e.limit,e.complete=t;var n=this.db._changes(e);if(n&&typeof n.cancel==`function`){let e=this.cancel;this.cancel=(...t)=>{n.cancel(),e.apply(this,t)}}}};function yankError(e,t){return function(n,r){n||r[0]&&r[0].error?(n=n||r[0],n.docId=t,e(n)):e(null,r.length?r[0]:r)}}function cleanDocs(e){for(var t=0;t<e.length;t++){var n=e[t];if(n._deleted)delete n._attachments;else if(n._attachments)for(var r=Object.keys(n._attachments),a=0;a<r.length;a++){var o=r[a];n._attachments[o]=pick$1(n._attachments[o],[`data`,`digest`,`content_type`,`length`,`revpos`,`stub`])}}}function compareByIdThenRev(e,t){return e._id===t._id?(e._revisions?e._revisions.start:0)-(t._revisions?t._revisions.start:0):e._id<t._id?-1:1}function computeHeight(e){var t={},n=[];return traverseRevTree(e,function(e,r,a,o){var s=r+`-`+a;return e&&(t[s]=0),o!==void 0&&n.push({from:o,to:s}),s}),n.reverse(),n.forEach(function(e){t[e.from]===void 0?t[e.from]=1+t[e.to]:t[e.from]=Math.min(t[e.from],1+t[e.to])}),t}function allDocsKeysParse(e){var t=`limit`in e?e.keys.slice(e.skip,e.limit+e.skip):e.skip>0?e.keys.slice(e.skip):e.keys;e.keys=t,e.skip=0,delete e.limit,e.descending&&(t.reverse(),e.descending=!1)}function doNextCompaction(e){var t=e._compactionQueue[0],n=t.opts,r=t.callback;e.get(`_local/compaction`).catch(function(){return!1}).then(function(t){t&&t.last_seq&&(n.last_seq=t.last_seq),e._compact(n,function(t,n){t?r(t):r(null,n),nextTick$1(function(){e._compactionQueue.shift(),e._compactionQueue.length&&doNextCompaction(e)})})})}function appendPurgeSeq(e,t,n){return e.get(`_local/purges`).then(function(e){let r=e.purgeSeq+1;return e.purges.push({docId:t,rev:n,purgeSeq:r}),e.purges.length>self.purged_infos_limit&&e.purges.splice(0,e.purges.length-self.purged_infos_limit),e.purgeSeq=r,e}).catch(function(e){if(e.status!==404)throw e;return{_id:`_local/purges`,purges:[{docId:t,rev:n,purgeSeq:0}],purgeSeq:0}}).then(function(t){return e.put(t)})}function attachmentNameError(e){return e.charAt(0)===`_`?e+` is not a valid attachment name, attachment names cannot start with '_'`:!1}function isNotSingleDoc(e){return typeof e!=`object`||!e||Array.isArray(e)}var validRevRegex=/^\d+-[^-]*$/;function isValidRev(e){return typeof e==`string`&&validRevRegex.test(e)}var AbstractPouchDB=class extends import_events.default{_setup(){this.post=adapterFun(`post`,function(e,t,n){if(typeof t==`function`&&(n=t,t={}),isNotSingleDoc(e))return n(createError$1(NOT_AN_OBJECT$1));this.bulkDocs({docs:[e]},t,yankError(n,e._id))}).bind(this),this.put=adapterFun(`put`,function(e,t,n){if(typeof t==`function`&&(n=t,t={}),isNotSingleDoc(e))return n(createError$1(NOT_AN_OBJECT$1));if(invalidIdError(e._id),`_rev`in e&&!isValidRev(e._rev))return n(createError$1(INVALID_REV$1));if(isLocalId(e._id)&&typeof this._putLocal==`function`)return e._deleted?this._removeLocal(e,n):this._putLocal(e,n);let putDoc=n=>{typeof this._put==`function`&&t.new_edits!==!1?this._put(e,t,n):this.bulkDocs({docs:[e]},t,yankError(n,e._id))};t.force&&e._rev?(transformForceOptionToNewEditsOption(),putDoc(function(t){var r=t?null:{ok:!0,id:e._id,rev:e._rev};n(t,r)})):putDoc(n);function transformForceOptionToNewEditsOption(){var n=e._rev.split(`-`),r=n[1],a=parseInt(n[0],10)+1,o=rev();e._revisions={start:a,ids:[o,r]},e._rev=a+`-`+o,t.new_edits=!1}}).bind(this),this.putAttachment=adapterFun(`putAttachment`,function(e,t,n,r,a){var o=this;typeof a==`function`&&(a=r,r=n,n=null),a===void 0&&(a=r,r=n,n=null),a||guardedConsole$1(`warn`,`Attachment`,t,`on document`,e,`is missing content_type`);function createAttachment(e){var n=`_rev`in e?parseInt(e._rev,10):0;return e._attachments=e._attachments||{},e._attachments[t]={content_type:a,data:r,revpos:++n},o.put(e)}return o.get(e).then(function(e){if(e._rev!==n)throw createError$1(REV_CONFLICT$1);return createAttachment(e)},function(t){if(t.reason===MISSING_DOC$1.message)return createAttachment({_id:e});throw t})}).bind(this),this.removeAttachment=adapterFun(`removeAttachment`,function(e,t,n,r){this.get(e,(e,a)=>{if(e){r(e);return}if(a._rev!==n){r(createError$1(REV_CONFLICT$1));return}if(!a._attachments)return r();delete a._attachments[t],Object.keys(a._attachments).length===0&&delete a._attachments,this.put(a,r)})}).bind(this),this.remove=adapterFun(`remove`,function(e,t,n,r){var a;typeof t==`string`?(a={_id:e,_rev:t},typeof n==`function`&&(r=n,n={})):(a=e,typeof t==`function`?(r=t,n={}):(r=n,n=t)),n=n||{},n.was_delete=!0;var o={_id:a._id,_rev:a._rev||n.rev};if(o._deleted=!0,isLocalId(o._id)&&typeof this._removeLocal==`function`)return this._removeLocal(a,r);this.bulkDocs({docs:[o]},n,yankError(r,o._id))}).bind(this),this.revsDiff=adapterFun(`revsDiff`,function(e,t,n){typeof t==`function`&&(n=t,t={});var r=Object.keys(e);if(!r.length)return n(null,{});var a=0,o=new Map;function addToMissing(e,t){o.has(e)||o.set(e,{missing:[]}),o.get(e).missing.push(t)}function processDoc(t,n){var r=e[t].slice(0);traverseRevTree(n,function(e,n,a,o,s){var c=n+`-`+a,l=r.indexOf(c);l!==-1&&(r.splice(l,1),s.status!==`available`&&addToMissing(t,c))}),r.forEach(function(e){addToMissing(t,e)})}r.forEach(function(t){this._getRevisionTree(t,function(s,c){if(s&&s.status===404&&s.message===`missing`)o.set(t,{missing:e[t]});else if(s)return n(s);else processDoc(t,c);if(++a===r.length){var l={};return o.forEach(function(e,t){l[t]=e}),n(null,l)}})},this)}).bind(this),this.bulkGet=adapterFun(`bulkGet`,function(e,t){bulkGet(this,e,t)}).bind(this),this.compactDocument=adapterFun(`compactDocument`,function(e,t,n){this._getRevisionTree(e,(r,a)=>{if(r)return n(r);var o=computeHeight(a),s=[],c=[];Object.keys(o).forEach(function(e){o[e]>t&&s.push(e)}),traverseRevTree(a,function(e,t,n,r,a){var o=t+`-`+n;a.status===`available`&&s.indexOf(o)!==-1&&c.push(o)}),this._doCompaction(e,c,n)})}).bind(this),this.compact=adapterFun(`compact`,function(e,t){typeof e==`function`&&(t=e,e={}),e=e||{},this._compactionQueue=this._compactionQueue||[],this._compactionQueue.push({opts:e,callback:t}),this._compactionQueue.length===1&&doNextCompaction(this)}).bind(this),this.get=adapterFun(`get`,function(e,t,n){if(typeof t==`function`&&(n=t,t={}),t=t||{},typeof e!=`string`)return n(createError$1(INVALID_ID$1));if(isLocalId(e)&&typeof this._getLocal==`function`)return this._getLocal(e,n);var r=[];let finishOpenRevs=()=>{var a=[],o=r.length;if(!o)return n(null,a);r.forEach(r=>{this.get(e,{rev:r,revs:t.revs,latest:t.latest,attachments:t.attachments,binary:t.binary},function(e,t){if(e)a.push({missing:r});else{for(var s,c=0,l=a.length;c<l;c++)if(a[c].ok&&a[c].ok._rev===t._rev){s=!0;break}s||a.push({ok:t})}o--,o||n(null,a)})})};if(t.open_revs){if(t.open_revs===`all`)this._getRevisionTree(e,function(e,t){if(e)return n(e);r=collectLeaves(t).map(function(e){return e.rev}),finishOpenRevs()});else if(Array.isArray(t.open_revs)){r=t.open_revs;for(var a=0;a<r.length;a++){var o=r[a];if(!isValidRev(o))return n(createError$1(INVALID_REV$1))}finishOpenRevs()}else return n(createError$1(UNKNOWN_ERROR$1,`function_clause`));return}return this._get(e,t,(r,a)=>{if(r)return r.docId=e,n(r);var o=a.doc,s=a.metadata,c=a.ctx;if(t.conflicts){var l=collectConflicts(s);l.length&&(o._conflicts=l)}if(isDeleted(s,o._rev)&&(o._deleted=!0),t.revs||t.revs_info){for(var u=o._rev.split(`-`),d=parseInt(u[0],10),p=u[1],m=rootToLeaf(s.rev_tree),g=null,_=0;_<m.length;_++){var v=m[_];let e=v.ids.findIndex(e=>e.id===p);(e===d-1||!g&&e!==-1)&&(g=v)}if(!g)return r=Error(`invalid rev tree`),r.docId=e,n(r);let a=o._rev.split(`-`)[1],c=g.ids.findIndex(e=>e.id===a)+1;var y=g.ids.length-c;if(g.ids.splice(c,y),g.ids.reverse(),t.revs&&(o._revisions={start:g.pos+g.ids.length-1,ids:g.ids.map(function(e){return e.id})}),t.revs_info){var b=g.pos+g.ids.length;o._revs_info=g.ids.map(function(e){return b--,{rev:b+`-`+e.id,status:e.opts.status}})}}if(t.attachments&&o._attachments){var x=o._attachments,S=Object.keys(x).length;if(S===0)return n(null,o);Object.keys(x).forEach(e=>{this._getAttachment(o._id,e,x[e],{binary:t.binary,metadata:s,ctx:c},function(t,r){var a=o._attachments[e];a.data=r,delete a.stub,delete a.length,--S||n(null,o)})})}else{if(o._attachments)for(var C in o._attachments)Object.prototype.hasOwnProperty.call(o._attachments,C)&&(o._attachments[C].stub=!0);n(null,o)}})}).bind(this),this.getAttachment=adapterFun(`getAttachment`,function(e,t,n,r){n instanceof Function&&(r=n,n={}),this._get(e,n,(a,o)=>{if(a)return r(a);if(o.doc._attachments&&o.doc._attachments[t])n.ctx=o.ctx,n.binary=!0,n.metadata=o.metadata,this._getAttachment(e,t,o.doc._attachments[t],n,r);else return r(createError$1(MISSING_DOC$1))})}).bind(this),this.allDocs=adapterFun(`allDocs`,function(e,t){if(typeof e==`function`&&(t=e,e={}),e.skip=e.skip===void 0?0:e.skip,e.start_key&&(e.startkey=e.start_key),e.end_key&&(e.endkey=e.end_key),`keys`in e){if(!Array.isArray(e.keys))return t(TypeError(`options.keys must be an array`));var n=[`startkey`,`endkey`,`key`].filter(function(t){return t in e})[0];if(n){t(createError$1(QUERY_PARSE_ERROR$1,"Query parameter `"+n+"` is not compatible with multi-get"));return}if(!isRemote$1(this)&&(allDocsKeysParse(e),e.keys.length===0))return this._allDocs({limit:0},t)}return this._allDocs(e,t)}).bind(this),this.close=adapterFun(`close`,function(e){return this._closed=!0,this.emit(`closed`),this._close(e)}).bind(this),this.info=adapterFun(`info`,function(e){this._info((t,n)=>{if(t)return e(t);n.db_name=n.db_name||this.name,n.auto_compaction=!!(this.auto_compaction&&!isRemote$1(this)),n.adapter=this.adapter,e(null,n)})}).bind(this),this.id=adapterFun(`id`,function(e){return this._id(e)}).bind(this),this.bulkDocs=adapterFun(`bulkDocs`,function(e,t,n){if(typeof t==`function`&&(n=t,t={}),t=t||{},Array.isArray(e)&&(e={docs:e}),!e||!e.docs||!Array.isArray(e.docs))return n(createError$1(MISSING_BULK_DOCS$1));for(var r=0;r<e.docs.length;++r){let t=e.docs[r];if(isNotSingleDoc(t))return n(createError$1(NOT_AN_OBJECT$1));if(`_rev`in t&&!isValidRev(t._rev))return n(createError$1(INVALID_REV$1))}var a;if(e.docs.forEach(function(e){e._attachments&&Object.keys(e._attachments).forEach(function(t){a=a||attachmentNameError(t),e._attachments[t].content_type||guardedConsole$1(`warn`,`Attachment`,t,`on document`,e._id,`is missing content_type`)})}),a)return n(createError$1(BAD_REQUEST$1,a));`new_edits`in t||(`new_edits`in e?t.new_edits=e.new_edits:t.new_edits=!0);var o=this;!t.new_edits&&!isRemote$1(o)&&e.docs.sort(compareByIdThenRev),cleanDocs(e.docs);var s=e.docs.map(function(e){return e._id});this._bulkDocs(e,t,function(e,r){if(e)return n(e);if(t.new_edits||(r=r.filter(function(e){return e.error})),!isRemote$1(o))for(var a=0,c=r.length;a<c;a++)r[a].id=r[a].id||s[a];n(null,r)})}).bind(this),this.registerDependentDatabase=adapterFun(`registerDependentDatabase`,function(e,t){var n=clone$1(this.__opts);this.__opts.view_adapter&&(n.adapter=this.__opts.view_adapter);var r=new this.constructor(e,n);function diffFun(t){return t.dependentDbs=t.dependentDbs||{},t.dependentDbs[e]?!1:(t.dependentDbs[e]=!0,t)}upsert$1(this,`_local/_pouch_dependentDbs`,diffFun).then(function(){t(null,{db:r})}).catch(t)}).bind(this),this.destroy=adapterFun(`destroy`,function(e,t){typeof e==`function`&&(t=e,e={});var n=`use_prefix`in this?this.use_prefix:!0;let destroyDb=()=>{this._destroy(e,(e,n)=>{if(e)return t(e);this._destroyed=!0,this.emit(`destroyed`),t(null,n||{ok:!0})})};if(isRemote$1(this))return destroyDb();this.get(`_local/_pouch_dependentDbs`,(e,r)=>{if(e)return e.status===404?destroyDb():t(e);var a=r.dependentDbs,o=this.constructor,s=Object.keys(a).map(e=>new o(n?e.replace(RegExp(`^`+o.prefix),``):e,this.__opts).destroy());Promise.all(s).then(destroyDb,t)})}).bind(this)}_compact(e,t){var n={return_docs:!1,last_seq:e.last_seq||0,since:e.last_seq||0},r=[],a,o=0;let onChange=e=>{this.activeTasks.update(a,{completed_items:++o}),r.push(this.compactDocument(e.id,0))},onError=e=>{this.activeTasks.remove(a,e),t(e)},onComplete=e=>{var n=e.last_seq;Promise.all(r).then(()=>upsert$1(this,`_local/compaction`,e=>!e.last_seq||e.last_seq<n?(e.last_seq=n,e):!1)).then(()=>{this.activeTasks.remove(a),t(null,{ok:!0})}).catch(onError)};this.info().then(e=>{a=this.activeTasks.add({name:`database_compaction`,total_items:e.update_seq-n.last_seq}),this.changes(n).on(`change`,onChange).on(`complete`,onComplete).on(`error`,onError)})}changes(e,t){return typeof e==`function`&&(t=e,e={}),e=e||{},e.return_docs=`return_docs`in e?e.return_docs:!e.live,new Changes$1(this,e,t)}type(){return typeof this._type==`function`?this._type():this.adapter}};AbstractPouchDB.prototype.purge=adapterFun(`_purge`,function(e,t,n){if(this._purge===void 0)return n(createError$1(UNKNOWN_ERROR$1,`Purge is not implemented in the `+this.adapter+` adapter.`));var r=this;r._getRevisionTree(e,(a,o)=>{if(a)return n(a);if(!o)return n(createError$1(MISSING_DOC$1));let s;try{s=findPathToLeaf(o,t)}catch(e){return n(e.message||e)}r._purge(e,s,(a,o)=>{if(a)return n(a);appendPurgeSeq(r,e,t).then(function(){return n(null,o)})})})});var TaskQueue$1=class{static{__name(this,`TaskQueue`)}constructor(){this.isReady=!1,this.failed=!1,this.queue=[]}execute(){var e;if(this.failed)for(;e=this.queue.shift();)e(this.failed);else for(;e=this.queue.shift();)e()}fail(e){this.failed=e,this.execute()}ready(e){this.isReady=!0,this.db=e,this.execute()}addTask(e){this.queue.push(e),this.failed&&this.execute()}};function parseAdapter(e,t){var n=e.match(/([a-z-]*):\/\/(.*)/);if(n)return{name:/https?/.test(n[1])?n[1]+`://`+n[2]:n[2],adapter:n[1]};var r=PouchDB.adapters,a=PouchDB.preferredAdapters,o=PouchDB.prefix,s=t.adapter;if(!s)for(var c=0;c<a.length;++c){if(s=a[c],s===`idb`&&`websql`in r&&hasLocalStorage()&&localStorage[`_pouch__websqldb_`+o+e]){guardedConsole$1(`log`,`PouchDB is downgrading "`+e+`" to WebSQL to avoid data loss, because it was already opened with WebSQL.`);continue}break}var l=r[s];return{name:!(l&&`use_prefix`in l)||l.use_prefix?o+e:e,adapter:s}}function inherits(e,t){e.prototype=Object.create(t.prototype,{constructor:{value:e}})}function createClass(e,t){let klass=function(...e){if(!(this instanceof klass))return new klass(...e);t.apply(this,e)};return inherits(klass,e),klass}function prepareForDestruction(e){function onDestroyed(t){e.removeListener(`closed`,onClosed),t||e.constructor.emit(`destroyed`,e.name)}function onClosed(){e.removeListener(`destroyed`,onDestroyed),e.constructor.emit(`unref`,e)}e.once(`destroyed`,onDestroyed),e.once(`closed`,onClosed),e.constructor.emit(`ref`,e)}var PouchInternal=class extends AbstractPouchDB{constructor(e,t){super(),this._setup(e,t)}_setup(e,t){if(super._setup(),t=t||{},e&&typeof e==`object`&&(t=e,e=t.name,delete t.name),t.deterministic_revs===void 0&&(t.deterministic_revs=!0),this.__opts=t=clone$1(t),this.auto_compaction=t.auto_compaction,this.purged_infos_limit=t.purged_infos_limit||1e3,this.prefix=PouchDB.prefix,typeof e!=`string`)throw Error(`Missing/invalid DB name`);var n=parseAdapter((t.prefix||``)+e,t);if(t.name=n.name,t.adapter=t.adapter||n.adapter,this.name=e,this._adapter=t.adapter,PouchDB.emit(`debug`,[`adapter`,`Picked adapter: `,t.adapter]),!PouchDB.adapters[t.adapter]||!PouchDB.adapters[t.adapter].valid())throw Error(`Invalid Adapter: `+t.adapter);if(t.view_adapter&&(!PouchDB.adapters[t.view_adapter]||!PouchDB.adapters[t.view_adapter].valid()))throw Error(`Invalid View Adapter: `+t.view_adapter);this.taskqueue=new TaskQueue$1,this.adapter=t.adapter,PouchDB.adapters[t.adapter].call(this,t,e=>{if(e)return this.taskqueue.fail(e);prepareForDestruction(this),this.emit(`created`,this),PouchDB.emit(`created`,this.name),this.taskqueue.ready(this)})}},PouchDB=createClass(PouchInternal,function(e,t){PouchInternal.prototype._setup.call(this,e,t)}),f$1=fetch,h$1=Headers,ActiveTasks=class{constructor(){this.tasks={}}list(){return Object.values(this.tasks)}add(e){let t=v4$1();return this.tasks[t]={id:t,name:e.name,total_items:e.total_items,created_at:new Date().toJSON()},t}get(e){return this.tasks[e]}remove(e,t){return delete this.tasks[e],this.tasks}update(e,t){let n=this.tasks[e];if(n!==void 0){let r={id:n.id,name:n.name,created_at:n.created_at,total_items:t.total_items||n.total_items,completed_items:t.completed_items||n.completed_items,updated_at:new Date().toJSON()};this.tasks[e]=r}return this.tasks}};PouchDB.adapters={},PouchDB.preferredAdapters=[],PouchDB.prefix=`_pouch_`;var eventEmitter=new import_events.default;function setUpEventEmitter(e){Object.keys(import_events.default.prototype).forEach(function(t){typeof import_events.default.prototype[t]==`function`&&(e[t]=eventEmitter[t].bind(eventEmitter))});var t=e._destructionListeners=new Map;e.on(`ref`,function onConstructorRef(e){t.has(e.name)||t.set(e.name,[]),t.get(e.name).push(e)}),e.on(`unref`,function onConstructorUnref(e){if(t.has(e.name)){var n=t.get(e.name),r=n.indexOf(e);r<0||(n.splice(r,1),n.length>1?t.set(e.name,n):t.delete(e.name))}}),e.on(`destroyed`,function onConstructorDestroyed(e){if(t.has(e)){var n=t.get(e);t.delete(e),n.forEach(function(e){e.emit(`destroyed`,!0)})}})}setUpEventEmitter(PouchDB),PouchDB.adapter=function(e,t,n){t.valid()&&(PouchDB.adapters[e]=t,n&&PouchDB.preferredAdapters.push(e))},PouchDB.plugin=function(e){if(typeof e==`function`)e(PouchDB);else if(typeof e!=`object`||Object.keys(e).length===0)throw Error(`Invalid plugin: got "`+e+`", expected an object or a function`);else Object.keys(e).forEach(function(t){PouchDB.prototype[t]=e[t]});return this.__defaults&&(PouchDB.__defaults=Object.assign({},this.__defaults)),PouchDB},PouchDB.defaults=function(e){let t=createClass(PouchDB,function(e,n){n=n||{},e&&typeof e==`object`&&(n=e,e=n.name,delete n.name),n=Object.assign({},t.__defaults,n),PouchDB.call(this,e,n)});return t.preferredAdapters=PouchDB.preferredAdapters.slice(),Object.keys(PouchDB).forEach(function(e){e in t||(t[e]=PouchDB[e])}),t.__defaults=Object.assign({},this.__defaults,e),t},PouchDB.fetch=function(e,t){return f$1(e,t)},PouchDB.prototype.activeTasks=PouchDB.activeTasks=new ActiveTasks;var version=`9.0.0`;function getFieldFromDoc$1(e,t){for(var n=e,r=0,a=t.length;r<a;r++){var o=t[r];if(n=n[o],!n)break}return n}__name(getFieldFromDoc$1,`getFieldFromDoc`);function compare$1(e,t){return e<t?-1:e>t?1:0}__name(compare$1,`compare`);function parseField$1(e){for(var t=[],n=``,r=0,a=e.length;r<a;r++){var o=e[r];r>0&&e[r-1]===`\\`&&(o===`$`||o===`.`)?n=n.substring(0,n.length-1)+o:o===`.`?(t.push(n),n=``):n+=o}return t.push(n),t}__name(parseField$1,`parseField`);var combinationFields$1=[`$or`,`$nor`,`$not`];function isCombinationalField$1(e){return combinationFields$1.indexOf(e)>-1}__name(isCombinationalField$1,`isCombinationalField`);function getKey$1(e){return Object.keys(e)[0]}__name(getKey$1,`getKey`);function getValue$1(e){return e[getKey$1(e)]}__name(getValue$1,`getValue`);function mergeAndedSelectors$1(e){var t={},n={$or:!0,$nor:!0};return e.forEach(function(e){Object.keys(e).forEach(function(r){var a=e[r];if(typeof a!=`object`&&(a={$eq:a}),isCombinationalField$1(r))if(a instanceof Array){if(n[r]){n[r]=!1,t[r]=a;return}var o=[];t[r].forEach(function(e){Object.keys(a).forEach(function(t){var n=a[t],r=Math.max(Object.keys(e).length,Object.keys(n).length),s=mergeAndedSelectors$1([e,n]);Object.keys(s).length<=r||o.push(s)})}),t[r]=o}else t[r]=mergeAndedSelectors$1([a]);else{var s=t[r]=t[r]||{};Object.keys(a).forEach(function(e){var t=a[e];if(e===`$gt`||e===`$gte`)return mergeGtGte$1(e,t,s);if(e===`$lt`||e===`$lte`)return mergeLtLte$1(e,t,s);if(e===`$ne`)return mergeNe$1(t,s);if(e===`$eq`)return mergeEq$1(t,s);if(e===`$regex`)return mergeRegex$1(t,s);s[e]=t})}})}),t}__name(mergeAndedSelectors$1,`mergeAndedSelectors`);function mergeGtGte$1(e,t,n){n.$eq===void 0&&(n.$gte===void 0?n.$gt===void 0?n[e]=t:e===`$gte`?t>n.$gt&&(delete n.$gt,n.$gte=t):t>n.$gt&&(n.$gt=t):e===`$gte`?t>n.$gte&&(n.$gte=t):t>=n.$gte&&(delete n.$gte,n.$gt=t))}__name(mergeGtGte$1,`mergeGtGte`);function mergeLtLte$1(e,t,n){n.$eq===void 0&&(n.$lte===void 0?n.$lt===void 0?n[e]=t:e===`$lte`?t<n.$lt&&(delete n.$lt,n.$lte=t):t<n.$lt&&(n.$lt=t):e===`$lte`?t<n.$lte&&(n.$lte=t):t<=n.$lte&&(delete n.$lte,n.$lt=t))}__name(mergeLtLte$1,`mergeLtLte`);function mergeNe$1(e,t){`$ne`in t?t.$ne.push(e):t.$ne=[e]}__name(mergeNe$1,`mergeNe`);function mergeEq$1(e,t){delete t.$gt,delete t.$gte,delete t.$lt,delete t.$lte,delete t.$ne,t.$eq=e}__name(mergeEq$1,`mergeEq`);function mergeRegex$1(e,t){`$regex`in t?t.$regex.push(e):t.$regex=[e]}__name(mergeRegex$1,`mergeRegex`);function mergeAndedSelectorsNested$1(e){for(var t in e){if(Array.isArray(e))for(var n in e)e[n].$and&&(e[n]=mergeAndedSelectors$1(e[n].$and));var r=e[t];typeof r==`object`&&mergeAndedSelectorsNested$1(r)}return e}__name(mergeAndedSelectorsNested$1,`mergeAndedSelectorsNested`);function isAndInSelector$1(e,t){for(var n in e){n===`$and`&&(t=!0);var r=e[n];typeof r==`object`&&(t=isAndInSelector$1(r,t))}return t}__name(isAndInSelector$1,`isAndInSelector`);function massageSelector$1(e){var t=clone$1(e);isAndInSelector$1(t,!1)&&(t=mergeAndedSelectorsNested$1(t),`$and`in t&&(t=mergeAndedSelectors$1(t.$and))),[`$or`,`$nor`].forEach(function(e){e in t&&t[e].forEach(function(e){for(var t=Object.keys(e),n=0;n<t.length;n++){var r=t[n],a=e[r];(typeof a!=`object`||!a)&&(e[r]={$eq:a})}})}),`$not`in t&&(t.$not=mergeAndedSelectors$1([t.$not]));for(var n=Object.keys(t),r=0;r<n.length;r++){var a=n[r],o=t[a];(typeof o!=`object`||!o)&&(o={$eq:o}),t[a]=o}return normalizeArrayOperators$1(t),t}__name(massageSelector$1,`massageSelector`);function normalizeArrayOperators$1(e){Object.keys(e).forEach(function(t){var n=e[t];Array.isArray(n)?n.forEach(function(e){e&&typeof e==`object`&&normalizeArrayOperators$1(e)}):t===`$ne`?e.$ne=[n]:t===`$regex`?e.$regex=[n]:n&&typeof n==`object`&&normalizeArrayOperators$1(n)})}__name(normalizeArrayOperators$1,`normalizeArrayOperators`);function pad$1(e,t,n){for(var r=``,a=n-e.length;r.length<a;)r+=t;return r}__name(pad$1,`pad`);function padLeft$1(e,t,n){return pad$1(e,t,n)+e}__name(padLeft$1,`padLeft`);var MIN_MAGNITUDE$1=-324,MAGNITUDE_DIGITS$1=3,SEP$1=``;function collate$1(e,t){if(e===t)return 0;e=normalizeKey$1(e),t=normalizeKey$1(t);var n=collationIndex$1(e),r=collationIndex$1(t);if(n-r!==0)return n-r;switch(typeof e){case`number`:return e-t;case`boolean`:return e<t?-1:1;case`string`:return stringCollate$1(e,t)}return Array.isArray(e)?arrayCollate$1(e,t):objectCollate$1(e,t)}__name(collate$1,`collate`);function normalizeKey$1(e){switch(typeof e){case`undefined`:return null;case`number`:return e===1/0||e===-1/0||isNaN(e)?null:e;case`object`:var t=e;if(Array.isArray(e)){var n=e.length;e=Array(n);for(var r=0;r<n;r++)e[r]=normalizeKey$1(t[r])}else if(e instanceof Date)return e.toJSON();else if(e!==null){for(var a in e={},t)if(Object.prototype.hasOwnProperty.call(t,a)){var o=t[a];o!==void 0&&(e[a]=normalizeKey$1(o))}}}return e}__name(normalizeKey$1,`normalizeKey`);function indexify$1(e){if(e!==null)switch(typeof e){case`boolean`:return e?1:0;case`number`:return numToIndexableString$1(e);case`string`:return e.replace(/\u0002/g,``).replace(/\u0001/g,``).replace(/\u0000/g,``);case`object`:var t=Array.isArray(e),n=t?e:Object.keys(e),r=-1,a=n.length,o=``;if(t)for(;++r<a;)o+=toIndexableString$1(n[r]);else for(;++r<a;){var s=n[r];o+=toIndexableString$1(s)+toIndexableString$1(e[s])}return o}return``}__name(indexify$1,`indexify`);function toIndexableString$1(e){return e=normalizeKey$1(e),collationIndex$1(e)+SEP$1+indexify$1(e)+`\0`}__name(toIndexableString$1,`toIndexableString`);function parseNumber$1(e,t){var n=t,r;if(e[t]===`1`)r=0,t++;else{var a=e[t]===`0`;t++;var o=``,s=e.substring(t,t+MAGNITUDE_DIGITS$1),c=parseInt(s,10)+MIN_MAGNITUDE$1;for(a&&(c=-c),t+=MAGNITUDE_DIGITS$1;;){var l=e[t];if(l===`\0`)break;o+=l,t++}o=o.split(`.`),r=o.length===1?parseInt(o,10):parseFloat(o[0]+`.`+o[1]),a&&(r-=10),c!==0&&(r=parseFloat(r+`e`+c))}return{num:r,length:t-n}}__name(parseNumber$1,`parseNumber`);function pop$1(e,t){var n=e.pop();if(t.length){var r=t[t.length-1];n===r.element&&(t.pop(),r=t[t.length-1]);var a=r.element,o=r.index;if(Array.isArray(a))a.push(n);else if(o===e.length-2){var s=e.pop();a[s]=n}else e.push(n)}}__name(pop$1,`pop`);function parseIndexableString$1(e){for(var t=[],n=[],r=0;;){var a=e[r++];if(a===`\0`){if(t.length===1)return t.pop();pop$1(t,n);continue}switch(a){case`1`:t.push(null);break;case`2`:t.push(e[r]===`1`),r++;break;case`3`:var o=parseNumber$1(e,r);t.push(o.num),r+=o.length;break;case`4`:for(var s=``;;){var c=e[r];if(c===`\0`)break;s+=c,r++}s=s.replace(/\u0001\u0001/g,`\0`).replace(/\u0001\u0002/g,``).replace(/\u0002\u0002/g,``),t.push(s);break;case`5`:var l={element:[],index:t.length};t.push(l.element),n.push(l);break;case`6`:var u={element:{},index:t.length};t.push(u.element),n.push(u);break;default:throw Error(`bad collationIndex or unexpectedly reached end of input: `+a)}}}__name(parseIndexableString$1,`parseIndexableString`);function arrayCollate$1(e,t){for(var n=Math.min(e.length,t.length),r=0;r<n;r++){var a=collate$1(e[r],t[r]);if(a!==0)return a}return e.length===t.length?0:e.length>t.length?1:-1}__name(arrayCollate$1,`arrayCollate`);function stringCollate$1(e,t){return e===t?0:e>t?1:-1}__name(stringCollate$1,`stringCollate`);function objectCollate$1(e,t){for(var n=Object.keys(e),r=Object.keys(t),a=Math.min(n.length,r.length),o=0;o<a;o++){var s=collate$1(n[o],r[o]);if(s!==0||(s=collate$1(e[n[o]],t[r[o]]),s!==0))return s}return n.length===r.length?0:n.length>r.length?1:-1}__name(objectCollate$1,`objectCollate`);function collationIndex$1(e){var t=[`boolean`,`number`,`string`,`object`].indexOf(typeof e);if(~t)return e===null?1:Array.isArray(e)?5:t<3?t+2:t+3;if(Array.isArray(e))return 5}__name(collationIndex$1,`collationIndex`);function numToIndexableString$1(e){if(e===0)return`1`;var t=e.toExponential().split(/e\+?/),n=parseInt(t[1],10),r=e<0,a=r?`0`:`2`,o=padLeft$1(((r?-n:n)-MIN_MAGNITUDE$1).toString(),`0`,MAGNITUDE_DIGITS$1);a+=SEP$1+o;var s=Math.abs(parseFloat(t[0]));r&&(s=10-s);var c=s.toFixed(20);return c=c.replace(/\.?0+$/,``),a+=SEP$1+c,a}__name(numToIndexableString$1,`numToIndexableString`);function createFieldSorter$1(e){function getFieldValuesAsArray(t){return e.map(function(e){return getFieldFromDoc$1(t,parseField$1(getKey$1(e)))})}return function(e,t){var n=collate$1(getFieldValuesAsArray(e.doc),getFieldValuesAsArray(t.doc));return n===0?compare$1(e.doc._id,t.doc._id):n}}__name(createFieldSorter$1,`createFieldSorter`);function filterInMemoryFields$1(e,t,n){if(e=e.filter(function(e){return rowFilter$1(e.doc,t.selector,n)}),t.sort){var r=createFieldSorter$1(t.sort);e=e.sort(r),typeof t.sort[0]!=`string`&&getValue$1(t.sort[0])===`desc`&&(e=e.reverse())}if(`limit`in t||`skip`in t){var a=t.skip||0,o=(`limit`in t?t.limit:e.length)+a;e=e.slice(a,o)}return e}__name(filterInMemoryFields$1,`filterInMemoryFields`);function rowFilter$1(e,t,n){return n.every(function(n){var r=t[n],a=parseField$1(n),o=getFieldFromDoc$1(e,a);return isCombinationalField$1(n)?matchCominationalSelector$1(n,r,e):matchSelector$1(r,e,a,o)})}__name(rowFilter$1,`rowFilter`);function matchSelector$1(e,t,n,r){return e?typeof e==`object`?Object.keys(e).every(function(a){var o=e[a];if(a.indexOf(`$`)===0)return match$1(a,t,o,n,r);var s=parseField$1(a);if(r===void 0&&typeof o!=`object`&&s.length>0)return!1;var c=getFieldFromDoc$1(r,s);return typeof o==`object`?matchSelector$1(o,t,n,c):match$1(`$eq`,t,o,s,c)}):e===r:!0}__name(matchSelector$1,`matchSelector`);function matchCominationalSelector$1(e,t,n){return e===`$or`?t.some(function(e){return rowFilter$1(n,e,Object.keys(e))}):e===`$not`?!rowFilter$1(n,t,Object.keys(t)):!t.find(function(e){return rowFilter$1(n,e,Object.keys(e))})}__name(matchCominationalSelector$1,`matchCominationalSelector`);function match$1(e,t,n,r,a){if(!matchers$1[e])throw Error(`unknown operator "`+e+`" - should be one of $eq, $lte, $lt, $gt, $gte, $exists, $ne, $in, $nin, $size, $mod, $regex, $elemMatch, $type, $allMatch or $all`);return matchers$1[e](t,n,r,a)}__name(match$1,`match`);function fieldExists$1(e){return e!=null}__name(fieldExists$1,`fieldExists`);function fieldIsNotUndefined$1(e){return e!==void 0}__name(fieldIsNotUndefined$1,`fieldIsNotUndefined`);function modField$1(e,t){if(typeof e!=`number`||parseInt(e,10)!==e)return!1;var n=t[0],r=t[1];return e%n===r}__name(modField$1,`modField`);function arrayContainsValue$1(e,t){return t.some(function(t){return e instanceof Array?e.some(function(e){return collate$1(t,e)===0}):collate$1(t,e)===0})}__name(arrayContainsValue$1,`arrayContainsValue`);function arrayContainsAllValues$1(e,t){return t.every(function(t){return e.some(function(e){return collate$1(t,e)===0})})}__name(arrayContainsAllValues$1,`arrayContainsAllValues`);function arraySize$1(e,t){return e.length===t}__name(arraySize$1,`arraySize`);function regexMatch$1(e,t){return new RegExp(t).test(e)}__name(regexMatch$1,`regexMatch`);function typeMatch$1(e,t){switch(t){case`null`:return e===null;case`boolean`:return typeof e==`boolean`;case`number`:return typeof e==`number`;case`string`:return typeof e==`string`;case`array`:return e instanceof Array;case`object`:return{}.toString.call(e)===`[object Object]`}}__name(typeMatch$1,`typeMatch`);var matchers$1={$elemMatch:function(e,t,n,r){return!Array.isArray(r)||r.length===0?!1:typeof r[0]==`object`&&r[0]!==null?r.some(function(e){return rowFilter$1(e,t,Object.keys(t))}):r.some(function(r){return matchSelector$1(t,e,n,r)})},$allMatch:function(e,t,n,r){return!Array.isArray(r)||r.length===0?!1:typeof r[0]==`object`&&r[0]!==null?r.every(function(e){return rowFilter$1(e,t,Object.keys(t))}):r.every(function(r){return matchSelector$1(t,e,n,r)})},$eq:function(e,t,n,r){return fieldIsNotUndefined$1(r)&&collate$1(r,t)===0},$gte:function(e,t,n,r){return fieldIsNotUndefined$1(r)&&collate$1(r,t)>=0},$gt:function(e,t,n,r){return fieldIsNotUndefined$1(r)&&collate$1(r,t)>0},$lte:function(e,t,n,r){return fieldIsNotUndefined$1(r)&&collate$1(r,t)<=0},$lt:function(e,t,n,r){return fieldIsNotUndefined$1(r)&&collate$1(r,t)<0},$exists:function(e,t,n,r){return t?fieldIsNotUndefined$1(r):!fieldIsNotUndefined$1(r)},$mod:function(e,t,n,r){return fieldExists$1(r)&&modField$1(r,t)},$ne:function(e,t,n,r){return t.every(function(e){return collate$1(r,e)!==0})},$in:function(e,t,n,r){return fieldExists$1(r)&&arrayContainsValue$1(r,t)},$nin:function(e,t,n,r){return fieldExists$1(r)&&!arrayContainsValue$1(r,t)},$size:function(e,t,n,r){return fieldExists$1(r)&&Array.isArray(r)&&arraySize$1(r,t)},$all:function(e,t,n,r){return Array.isArray(r)&&arrayContainsAllValues$1(r,t)},$regex:function(e,t,n,r){return fieldExists$1(r)&&typeof r==`string`&&t.every(function(e){return regexMatch$1(r,e)})},$type:function(e,t,n,r){return typeMatch$1(r,t)}};function matchesSelector$1(e,t){if(typeof t!=`object`)throw Error(`Selector error: expected a JSON object`);t=massageSelector$1(t);var n=filterInMemoryFields$1([{doc:e}],{selector:t},Object.keys(t));return n&&n.length===1}__name(matchesSelector$1,`matchesSelector`);function evalFilter(e){return scopeEval(`"use strict";
|
|
3
3
|
return `+e+`;`,{})}function evalView(e){return scopeEval([`return function(doc) {`,` "use strict";`,` var emitted = false;`,` var emit = function (a, b) {`,` emitted = true;`,` };`,` var view = `+e+`;`,` view(doc);`,` if (emitted) {`,` return true;`,` }`,`};`].join(`
|
|
4
4
|
`),{})}function validate(e,t){if(e.selector&&e.filter&&e.filter!==`_selector`){var n=typeof e.filter==`string`?e.filter:`function`;return t(Error(`selector invalid for filter "`+n+`"`))}t()}function normalize(e){e.view&&!e.filter&&(e.filter=`_view`),e.selector&&!e.filter&&(e.filter=`_selector`),e.filter&&typeof e.filter==`string`&&(e.filter===`_view`?e.view=normalizeDesignDocFunctionName(e.view):e.filter=normalizeDesignDocFunctionName(e.filter))}function shouldFilter(e,t){return t.filter&&typeof t.filter==`string`&&!t.doc_ids&&!isRemote$1(e.db)}function filter(e,t){var n=t.complete;if(t.filter===`_view`){if(!t.view||typeof t.view!=`string`)return n(createError$1(BAD_REQUEST$1,"`view` filter parameter not found or invalid."));var r=parseDesignDocFunctionName(t.view);e.db.get(`_design/`+r[0],function(a,o){if(e.isCancelled)return n(null,{status:`cancelled`});if(a)return n(generateErrorFromResponse$1(a));var s=o&&o.views&&o.views[r[1]]&&o.views[r[1]].map;if(!s)return n(createError$1(MISSING_DOC$1,o.views?`missing json key: `+r[1]:`missing json key: views`));t.filter=evalView(s),e.doChanges(t)})}else if(t.selector)t.filter=function(e){return matchesSelector$1(e,t.selector)},e.doChanges(t);else{var a=parseDesignDocFunctionName(t.filter);e.db.get(`_design/`+a[0],function(r,o){if(e.isCancelled)return n(null,{status:`cancelled`});if(r)return n(generateErrorFromResponse$1(r));var s=o&&o.filters&&o.filters[a[1]];if(!s)return n(createError$1(MISSING_DOC$1,o&&o.filters?`missing json key: `+a[1]:`missing json key: filters`));t.filter=evalFilter(s),e.doChanges(t)})}}function applyChangesFilterPlugin(e){e._changesFilterPlugin={validate,normalize,shouldFilter,filter}}PouchDB.plugin(applyChangesFilterPlugin),PouchDB.version=version;function checkBlobSupport(e,t,n){return new Promise(function(r){var a=createBlob$1([``]);let o;if(typeof n==`function`){let r=n(a);o=e.objectStore(t).put(r)}else{let r=n;o=e.objectStore(t).put(a,r)}o.onsuccess=function(){var e=navigator.userAgent.match(/Chrome\/(\d+)/);r(navigator.userAgent.match(/Edge\//)||!e||parseInt(e[1],10)>=43)},o.onerror=e.onabort=function(e){e.preventDefault(),e.stopPropagation(),r(!1)}}).catch(function(){return!1})}function toObject(e){return e.reduce(function(e,t){return e[t]=!0,e},{})}var reservedWords=toObject([`_id`,`_rev`,`_access`,`_attachments`,`_deleted`,`_revisions`,`_revs_info`,`_conflicts`,`_deleted_conflicts`,`_local_seq`,`_rev_tree`,`_replication_id`,`_replication_state`,`_replication_state_time`,`_replication_state_reason`,`_replication_stats`,`_removed`]),dataWords=toObject([`_access`,`_attachments`,`_replication_id`,`_replication_state`,`_replication_state_time`,`_replication_state_reason`,`_replication_stats`]);function parseRevisionInfo(e){if(!/^\d+-/.test(e))return createError$1(INVALID_REV$1);var t=e.indexOf(`-`),n=e.substring(0,t),r=e.substring(t+1);return{prefix:parseInt(n,10),id:r}}function makeRevTreeFromRevisions(e,t){for(var n=e.start-e.ids.length+1,r=e.ids,a=[r[0],t,[]],o=1,s=r.length;o<s;o++)a=[r[o],{status:`missing`},[a]];return[{pos:n,ids:a}]}function parseDoc(e,t,n){n||(n={deterministic_revs:!0});var r,a,o,s={status:`available`};if(e._deleted&&(s.deleted=!0),t)if(e._id||(e._id=uuid()),a=rev(e,n.deterministic_revs),e._rev){if(o=parseRevisionInfo(e._rev),o.error)return o;e._rev_tree=[{pos:o.prefix,ids:[o.id,{status:`missing`},[[a,s,[]]]]}],r=o.prefix+1}else e._rev_tree=[{pos:1,ids:[a,s,[]]}],r=1;else if(e._revisions&&(e._rev_tree=makeRevTreeFromRevisions(e._revisions,s),r=e._revisions.start,a=e._revisions.ids[0]),!e._rev_tree){if(o=parseRevisionInfo(e._rev),o.error)return o;r=o.prefix,a=o.id,e._rev_tree=[{pos:r,ids:[a,s,[]]}]}invalidIdError(e._id),e._rev=r+`-`+a;var c={metadata:{},data:{}};for(var l in e)if(Object.prototype.hasOwnProperty.call(e,l)){var u=l[0]===`_`;if(u&&!reservedWords[l]){var d=createError$1(DOC_VALIDATION$1,l);throw d.message=DOC_VALIDATION$1.message+`: `+l,d}else u&&!dataWords[l]?c.metadata[l.slice(1)]=e[l]:c.data[l]=e[l]}return c}function parseBase64(e){try{return thisAtob$1(e)}catch{return{error:createError$1(BAD_ARG$1,`Attachment is not a valid base64 string`)}}}function preprocessString(e,t,n){var r=parseBase64(e.data);if(r.error)return n(r.error);e.length=r.length,t===`blob`?e.data=binStringToBluffer$1(r,e.content_type):t===`base64`?e.data=thisBtoa(r):e.data=r,binaryMd5(r,function(t){e.digest=`md5-`+t,n()})}function preprocessBlob(e,t,n){binaryMd5(e.data,function(r){e.digest=`md5-`+r,e.length=e.data.size||e.data.length||0,t===`binary`?blobToBinaryString(e.data,function(t){e.data=t,n()}):t===`base64`?blobToBase64(e.data,function(t){e.data=t,n()}):n()})}function preprocessAttachment(e,t,n){if(e.stub)return n();typeof e.data==`string`?preprocessString(e,t,n):preprocessBlob(e,t,n)}function preprocessAttachments(e,t,n){if(!e.length)return n();var r=0,a;e.forEach(function(e){var n=e.data&&e.data._attachments?Object.keys(e.data._attachments):[],r=0;if(!n.length)return done();function processedAttachment(e){a=e,r++,r===n.length&&done()}for(var o in e.data._attachments)Object.prototype.hasOwnProperty.call(e.data._attachments,o)&&preprocessAttachment(e.data._attachments[o],t,processedAttachment)});function done(){r++,e.length===r&&(a?n(a):n())}}function updateDoc(e,t,n,r,a,o,s,c){if(revExists(t.rev_tree,n.metadata.rev)&&!c)return r[a]=n,o();var l=t.winningRev||winningRev(t),u=`deleted`in t?t.deleted:isDeleted(t,l),d=`deleted`in n.metadata?n.metadata.deleted:isDeleted(n.metadata),p=/^1-/.test(n.metadata.rev);if(u&&!d&&c&&p){var m=n.data;m._rev=l,m._id=n.metadata.id,n=parseDoc(m,c)}var g=merge(t.rev_tree,n.metadata.rev_tree[0],e);if(c&&(u&&d&&g.conflicts!==`new_leaf`||!u&&g.conflicts!==`new_leaf`||u&&!d&&g.conflicts===`new_branch`))return r[a]=createError$1(REV_CONFLICT$1),o();var _=n.metadata.rev;n.metadata.rev_tree=g.tree,n.stemmedRevs=g.stemmedRevs||[],t.rev_map&&(n.metadata.rev_map=t.rev_map);var v=winningRev(n.metadata),y=isDeleted(n.metadata,v),b=u===y?0:u<y?-1:1,x=_===v?y:isDeleted(n.metadata,_);s(n,v,y,x,!0,b,a,o)}function rootIsMissing(e){return e.metadata.rev_tree[0].ids[1].status===`missing`}function processDocs(e,t,n,r,a,o,s,c,l){e=e||1e3;function insertDoc(e,t,n){var r=winningRev(e.metadata),a=isDeleted(e.metadata,r);if(`was_delete`in c&&a)return o[t]=createError$1(MISSING_DOC$1,`deleted`),n();if(u&&rootIsMissing(e))return o[t]=createError$1(REV_CONFLICT$1),n();s(e,r,a,a,!1,a?0:1,t,n)}var u=c.new_edits,d=new Map,p=0,m=t.length;function checkAllDocsDone(){++p===m&&l&&l()}t.forEach(function(e,t){if(e._id&&isLocalId(e._id)){n[e._deleted?`_removeLocal`:`_putLocal`](e,{ctx:a},function(e,n){o[t]=e||n,checkAllDocsDone()});return}var r=e.metadata.id;d.has(r)?(m--,d.get(r).push([e,t])):d.set(r,[[e,t]])}),d.forEach(function(t,n){var a=0;function docWritten(){++a<t.length?nextDoc():checkAllDocsDone()}function nextDoc(){var c=t[a],l=c[0],d=c[1];if(r.has(n))updateDoc(e,r.get(n),l,o,d,docWritten,s,u);else{var p=merge([],l.metadata.rev_tree[0],e);l.metadata.rev_tree=p.tree,l.stemmedRevs=p.stemmedRevs||[],insertDoc(l,d,docWritten)}}nextDoc()})}var ADAPTER_VERSION=5,DOC_STORE=`document-store`,BY_SEQ_STORE=`by-sequence`,ATTACH_STORE=`attach-store`,ATTACH_AND_SEQ_STORE=`attach-seq-store`,META_STORE=`meta-store`,LOCAL_STORE=`local-store`,DETECT_BLOB_SUPPORT_STORE=`detect-blob-support`;function safeJsonParse(e){try{return JSON.parse(e)}catch{return import_vuvuzela.parse(e)}}function safeJsonStringify(e){try{return JSON.stringify(e)}catch{return import_vuvuzela.stringify(e)}}function idbError(e){return function(t){var n=`unknown_error`;t.target&&t.target.error&&(n=t.target.error.name||t.target.error.message),e(createError$1(IDB_ERROR$1,n,t.type))}}function encodeMetadata(e,t,n){return{data:safeJsonStringify(e),winningRev:t,deletedOrLocal:n?`1`:`0`,seq:e.seq,id:e.id}}function decodeMetadata(e){if(!e)return null;var t=safeJsonParse(e.data);return t.winningRev=e.winningRev,t.deleted=e.deletedOrLocal===`1`,t.seq=e.seq,t}function decodeDoc(e){if(!e)return e;var t=e._doc_id_rev.lastIndexOf(`:`);return e._id=e._doc_id_rev.substring(0,t-1),e._rev=e._doc_id_rev.substring(t+1),delete e._doc_id_rev,e}function readBlobData(e,t,n,r){n?r(e?typeof e==`string`?b64ToBluffer$1(e,t):e:createBlob$1([``],{type:t})):e?typeof e==`string`?r(e):readAsBinaryString(e,function(e){r(thisBtoa(e))}):r(``)}function fetchAttachmentsIfNecessary(e,t,n,r){var a=Object.keys(e._attachments||{});if(!a.length)return r&&r();var o=0;function checkDone(){++o===a.length&&r&&r()}function fetchAttachment(e,t){var r=e._attachments[t],a=r.digest,o=n.objectStore(ATTACH_STORE).get(a);o.onsuccess=function(e){r.body=e.target.result.body,checkDone()}}a.forEach(function(n){t.attachments&&t.include_docs?fetchAttachment(e,n):(e._attachments[n].stub=!0,checkDone())})}function postProcessAttachments(e,t){return Promise.all(e.map(function(e){if(e.doc&&e.doc._attachments){var n=Object.keys(e.doc._attachments);return Promise.all(n.map(function(n){var r=e.doc._attachments[n];if(`body`in r){var a=r.body,o=r.content_type;return new Promise(function(s){readBlobData(a,o,t,function(t){e.doc._attachments[n]=Object.assign(pick$1(r,[`digest`,`content_type`]),{data:t}),s()})})}}))}}))}function compactRevs(e,t,n){var r=[],a=n.objectStore(BY_SEQ_STORE),o=n.objectStore(ATTACH_STORE),s=n.objectStore(ATTACH_AND_SEQ_STORE),c=e.length;function checkDone(){c--,c||deleteOrphanedAttachments()}function deleteOrphanedAttachments(){r.length&&r.forEach(function(e){var t=s.index(`digestSeq`).count(IDBKeyRange.bound(e+`::`,e+`::`,!1,!1));t.onsuccess=function(t){t.target.result||o.delete(e)}})}e.forEach(function(e){var n=a.index(`_doc_id_rev`),o=t+`::`+e;n.getKey(o).onsuccess=function(e){var t=e.target.result;if(typeof t!=`number`)return checkDone();a.delete(t);var n=s.index(`seq`).openCursor(IDBKeyRange.only(t));n.onsuccess=function(e){var t=e.target.result;if(t){var n=t.value.digestSeq.split(`::`)[0];r.push(n),s.delete(t.primaryKey),t.continue()}else checkDone()}}})}function openTransactionSafely(e,t,n){try{return{txn:e.transaction(t,n)}}catch(e){return{error:e}}}var changesHandler=new Changes;function idbBulkDocs(e,t,n,r,a,o){for(var s=t.docs,c,l,u,d,p,m,g,_,v=0,y=s.length;v<y;v++){var b=s[v];b._id&&isLocalId(b._id)||(b=s[v]=parseDoc(b,n.new_edits,e),b.error&&!g&&(g=b))}if(g)return o(g);var x=!1,S=0,C=Array(s.length),w=new Map,T=!1;preprocessAttachments(s,r._meta.blobSupport?`blob`:`base64`,function(e){if(e)return o(e);startTransaction()});function startTransaction(){var e=openTransactionSafely(a,[DOC_STORE,BY_SEQ_STORE,ATTACH_STORE,LOCAL_STORE,ATTACH_AND_SEQ_STORE,META_STORE],`readwrite`);if(e.error)return o(e.error);c=e.txn,c.onabort=idbError(o),c.ontimeout=idbError(o),c.oncomplete=complete,l=c.objectStore(DOC_STORE),u=c.objectStore(BY_SEQ_STORE),d=c.objectStore(ATTACH_STORE),p=c.objectStore(ATTACH_AND_SEQ_STORE),m=c.objectStore(META_STORE),m.get(META_STORE).onsuccess=function(e){_=e.target.result,updateDocCountIfReady()},verifyAttachments(function(e){if(e)return T=!0,o(e);fetchExistingDocs()})}function onAllDocsProcessed(){x=!0,updateDocCountIfReady()}function idbProcessDocs(){processDocs(e.revs_limit,s,r,w,c,C,writeDoc,n,onAllDocsProcessed)}function updateDocCountIfReady(){!_||!x||(_.docCount+=S,m.put(_))}function fetchExistingDocs(){if(!s.length)return;var e=0;function checkDone(){++e===s.length&&idbProcessDocs()}function readMetadata(e){var t=decodeMetadata(e.target.result);t&&w.set(t.id,t),checkDone()}for(var t=0,n=s.length;t<n;t++){var r=s[t];if(r._id&&isLocalId(r._id)){checkDone();continue}var a=l.get(r.metadata.id);a.onsuccess=readMetadata}}function complete(){T||(changesHandler.notify(r._meta.name),o(null,C))}function verifyAttachment(e,t){var n=d.get(e);n.onsuccess=function(n){if(n.target.result)t();else{var r=createError$1(MISSING_STUB$1,`unknown stub attachment with digest `+e);r.status=412,t(r)}}}function verifyAttachments(e){var t=[];if(s.forEach(function(e){e.data&&e.data._attachments&&Object.keys(e.data._attachments).forEach(function(n){var r=e.data._attachments[n];r.stub&&t.push(r.digest)})}),!t.length)return e();var n=0,r;function checkDone(){++n===t.length&&e(r)}t.forEach(function(e){verifyAttachment(e,function(e){e&&!r&&(r=e),checkDone()})})}function writeDoc(e,t,n,r,a,o,s,c){e.metadata.winningRev=t,e.metadata.deleted=n;var l=e.data;if(l._id=e.metadata.id,l._rev=e.metadata.rev,r&&(l._deleted=!0),l._attachments&&Object.keys(l._attachments).length)return writeAttachments(e,t,n,a,s,c);S+=o,updateDocCountIfReady(),finishDoc(e,t,n,a,s,c)}function finishDoc(e,t,n,a,o,s){var d=e.data,p=e.metadata;d._doc_id_rev=p.id+`::`+p.rev,delete d._id,delete d._rev;function afterPutDoc(o){var s=e.stemmedRevs||[];a&&r.auto_compaction&&(s=s.concat(compactTree(e.metadata))),s&&s.length&&compactRevs(s,e.metadata.id,c),p.seq=o.target.result;var u=encodeMetadata(p,t,n),d=l.put(u);d.onsuccess=afterPutMetadata}function afterPutDocError(e){e.preventDefault(),e.stopPropagation();var t=u.index(`_doc_id_rev`).getKey(d._doc_id_rev);t.onsuccess=function(e){var t=u.put(d,e.target.result);t.onsuccess=afterPutDoc}}function afterPutMetadata(){C[o]={ok:!0,id:p.id,rev:p.rev},w.set(e.metadata.id,e.metadata),insertAttachmentMappings(e,p.seq,s)}var m=u.put(d);m.onsuccess=afterPutDoc,m.onerror=afterPutDocError}function writeAttachments(e,t,n,r,a,o){var s=e.data,c=0,l=Object.keys(s._attachments);function collectResults(){c===l.length&&finishDoc(e,t,n,r,a,o)}function attachmentSaved(){c++,collectResults()}l.forEach(function(n){var r=e.data._attachments[n];if(r.stub)c++,collectResults();else{var a=r.data;delete r.data,r.revpos=parseInt(t,10);var o=r.digest;saveAttachment(o,a,attachmentSaved)}})}function insertAttachmentMappings(e,t,n){var r=0,a=Object.keys(e.data._attachments||{});if(!a.length)return n();function checkDone(){++r===a.length&&n()}function add(n){var r=e.data._attachments[n].digest,a=p.put({seq:t,digestSeq:r+`::`+t});a.onsuccess=checkDone,a.onerror=function(e){e.preventDefault(),e.stopPropagation(),checkDone()}}for(var o=0;o<a.length;o++)add(a[o])}function saveAttachment(e,t,n){var r=d.count(e);r.onsuccess=function(r){if(r.target.result)return n();var a={digest:e,body:t},o=d.put(a);o.onsuccess=n}}}function runBatchedCursor(e,t,n,r,a){r===-1&&(r=1e3);var o=typeof e.getAll==`function`&&typeof e.getAllKeys==`function`&&r>1&&!n,s,c,l;function onGetAll(e){c=e.target.result,s&&a(s,c,l)}function onGetAllKeys(e){s=e.target.result,c&&a(s,c,l)}function continuePseudoCursor(){if(!s.length)return a();var n=s[s.length-1],o;if(t&&t.upper)try{o=IDBKeyRange.bound(n,t.upper,!0,t.upperOpen)}catch(e){if(e.name===`DataError`&&e.code===0)return a()}else o=IDBKeyRange.lowerBound(n,!0);t=o,s=null,c=null,e.getAll(t,r).onsuccess=onGetAll,e.getAllKeys(t,r).onsuccess=onGetAllKeys}function onCursor(e){var t=e.target.result;if(!t)return a();a([t.key],[t.value],t)}o?(l={continue:continuePseudoCursor},e.getAll(t,r).onsuccess=onGetAll,e.getAllKeys(t,r).onsuccess=onGetAllKeys):n?e.openCursor(t,`prev`).onsuccess=onCursor:e.openCursor(t).onsuccess=onCursor}function getAll(e,t,n){if(typeof e.getAll==`function`){e.getAll(t).onsuccess=n;return}var r=[];function onCursor(e){var t=e.target.result;t?(r.push(t.value),t.continue()):n({target:{result:r}})}e.openCursor(t).onsuccess=onCursor}function allDocsKeys(e,t,n){var r=Array(e.length),a=0;e.forEach(function(o,s){t.get(o).onsuccess=function(t){t.target.result?r[s]=t.target.result:r[s]={key:o,error:`not_found`},a++,a===e.length&&n(e,r,{})}})}function createKeyRange(e,t,n,r,a){try{if(e&&t)return a?IDBKeyRange.bound(t,e,!n,!1):IDBKeyRange.bound(e,t,!1,!n);if(e)return a?IDBKeyRange.upperBound(e):IDBKeyRange.lowerBound(e);if(t)return a?IDBKeyRange.lowerBound(t,!n):IDBKeyRange.upperBound(t,!n);if(r)return IDBKeyRange.only(r)}catch(e){return{error:e}}return null}function idbAllDocs(e,t,n){var r=`startkey`in e?e.startkey:!1,a=`endkey`in e?e.endkey:!1,o=`key`in e?e.key:!1,s=`keys`in e?e.keys:!1,c=e.skip||0,l=typeof e.limit==`number`?e.limit:-1,u=e.inclusive_end!==!1,d,p;if(!s&&(d=createKeyRange(r,a,u,o,e.descending),p=d&&d.error,p&&!(p.name===`DataError`&&p.code===0)))return n(createError$1(IDB_ERROR$1,p.name,p.message));var m=[DOC_STORE,BY_SEQ_STORE,META_STORE];e.attachments&&m.push(ATTACH_STORE);var g=openTransactionSafely(t,m,`readonly`);if(g.error)return n(g.error);var _=g.txn;_.oncomplete=onTxnComplete,_.onabort=idbError(n);var v=_.objectStore(DOC_STORE),y=_.objectStore(BY_SEQ_STORE),b=_.objectStore(META_STORE),x=y.index(`_doc_id_rev`),S=[],C,w;b.get(META_STORE).onsuccess=function(e){C=e.target.result.docCount},e.update_seq&&(y.openKeyCursor(null,`prev`).onsuccess=e=>{var t=e.target.result;t&&t.key&&(w=t.key)});function fetchDocAsynchronously(t,n,r){var a=t.id+`::`+r;x.get(a).onsuccess=function onGetDoc(r){if(n.doc=decodeDoc(r.target.result)||{},e.conflicts){var a=collectConflicts(t);a.length&&(n.doc._conflicts=a)}fetchAttachmentsIfNecessary(n.doc,e,_)}}function allDocsInner(t,n){var r={id:n.id,key:n.id,value:{rev:t}};n.deleted?s&&(S.push(r),r.value.deleted=!0,r.doc=null):c--<=0&&(S.push(r),e.include_docs&&fetchDocAsynchronously(n,r,t))}function processBatch(e){for(var t=0,n=e.length;t<n&&S.length!==l;t++){var r=e[t];if(r.error&&s){S.push(r);continue}var a=decodeMetadata(r),o=a.winningRev;allDocsInner(o,a)}}function onBatch(e,t,n){n&&(processBatch(t),S.length<l&&n.continue())}function onGetAll(t){var n=t.target.result;e.descending&&(n=n.reverse()),processBatch(n)}function onResultsReady(){var t={total_rows:C,offset:e.skip,rows:S};e.update_seq&&w!==void 0&&(t.update_seq=w),n(null,t)}function onTxnComplete(){e.attachments?postProcessAttachments(S,e.binary).then(onResultsReady):onResultsReady()}if(!(p||l===0)){if(s)return allDocsKeys(s,v,onBatch);if(l===-1)return getAll(v,d,onGetAll);runBatchedCursor(v,d,e.descending,l+c,onBatch)}}function countDocs(e,t){var n=e.objectStore(DOC_STORE).index(`deletedOrLocal`);n.count(IDBKeyRange.only(`0`)).onsuccess=function(e){t(e.target.result)}}var running=!1,queue=[];function tryCode(e,t,n,r){try{e(t,n)}catch(e){r.emit(`error`,e)}}function applyNext(){running||!queue.length||(running=!0,queue.shift()())}function enqueueTask(e,t,n){queue.push(function runAction(){e(function runCallback(e,r){tryCode(t,e,r,n),running=!1,nextTick$1(function runNext(){applyNext(n)})})}),applyNext()}function changes(e,t,n,r){if(e=clone$1(e),e.continuous){var a=n+`:`+uuid();return changesHandler.addListener(n,a,t,e),changesHandler.notify(n),{cancel:function(){changesHandler.removeListener(n,a)}}}var o=e.doc_ids&&new Set(e.doc_ids);e.since=e.since||0;var s=e.since,c=`limit`in e?e.limit:-1;c===0&&(c=1);var l=[],u=0,d=filterChange(e),p=new Map,m,g,_,v;function onBatch(t,n,r){if(!r||!t.length)return;var a=Array(t.length),o=Array(t.length);function processMetadataAndWinningDoc(t,n){var r=e.processChange(n,t,e);s=r.seq=t.seq;var a=d(r);return typeof a==`object`?Promise.reject(a):a?(u++,e.return_docs&&l.push(r),e.attachments&&e.include_docs?new Promise(function(t){fetchAttachmentsIfNecessary(n,e,m,function(){postProcessAttachments([r],e.binary).then(function(){t(r)})})}):Promise.resolve(r)):Promise.resolve()}function onBatchDone(){for(var t=[],n=0,s=a.length;n<s&&u!==c;n++){var l=a[n];if(l){var d=o[n];t.push(processMetadataAndWinningDoc(d,l))}}Promise.all(t).then(function(t){for(var n=0,r=t.length;n<r;n++)t[n]&&e.onChange(t[n])}).catch(e.complete),u!==c&&r.continue()}var p=0;n.forEach(function(e,n){var r=decodeDoc(e),s=t[n];fetchWinningDocAndMetadata(r,s,function(e,r){o[n]=e,a[n]=r,++p===t.length&&onBatchDone()})})}function onGetMetadata(e,t,n,r){if(n.seq!==t)return r();if(n.winningRev===e._rev)return r(n,e);var a=e._id+`::`+n.winningRev,o=v.get(a);o.onsuccess=function(e){r(n,decodeDoc(e.target.result))}}function fetchWinningDocAndMetadata(e,t,n){if(o&&!o.has(e._id))return n();var r=p.get(e._id);if(r)return onGetMetadata(e,t,r,n);_.get(e._id).onsuccess=function(a){r=decodeMetadata(a.target.result),p.set(e._id,r),onGetMetadata(e,t,r,n)}}function finish(){e.complete(null,{results:l,last_seq:s})}function onTxnComplete(){!e.continuous&&e.attachments?postProcessAttachments(l).then(finish):finish()}var y=[DOC_STORE,BY_SEQ_STORE];e.attachments&&y.push(ATTACH_STORE);var b=openTransactionSafely(r,y,`readonly`);if(b.error)return e.complete(b.error);m=b.txn,m.onabort=idbError(e.complete),m.oncomplete=onTxnComplete,g=m.objectStore(BY_SEQ_STORE),_=m.objectStore(DOC_STORE),v=g.index(`_doc_id_rev`);var x=e.since&&!e.descending?IDBKeyRange.lowerBound(e.since,!0):null;runBatchedCursor(g,x,e.descending,c,onBatch)}var cachedDBs=new Map,blobSupportPromise,openReqList=new Map;function IdbPouch(e,t){var n=this;enqueueTask(function(t){init(n,e,t)},t,n.constructor)}function init(e,t,n){var r=t.name,a=null,o=null;e._meta=null;function enrichCallbackError(e){return function(t,n){t&&t instanceof Error&&!t.reason&&o&&(t.reason=o),e(t,n)}}function createSchema(e){var t=e.createObjectStore(DOC_STORE,{keyPath:`id`});e.createObjectStore(BY_SEQ_STORE,{autoIncrement:!0}).createIndex(`_doc_id_rev`,`_doc_id_rev`,{unique:!0}),e.createObjectStore(ATTACH_STORE,{keyPath:`digest`}),e.createObjectStore(META_STORE,{keyPath:`id`,autoIncrement:!1}),e.createObjectStore(DETECT_BLOB_SUPPORT_STORE),t.createIndex(`deletedOrLocal`,`deletedOrLocal`,{unique:!1}),e.createObjectStore(LOCAL_STORE,{keyPath:`_id`});var n=e.createObjectStore(ATTACH_AND_SEQ_STORE,{autoIncrement:!0});n.createIndex(`seq`,`seq`),n.createIndex(`digestSeq`,`digestSeq`,{unique:!0})}function addDeletedOrLocalIndex(e,t){var n=e.objectStore(DOC_STORE);n.createIndex(`deletedOrLocal`,`deletedOrLocal`,{unique:!1}),n.openCursor().onsuccess=function(e){var r=e.target.result;if(r){var a=r.value;a.deletedOrLocal=isDeleted(a)?`1`:`0`,n.put(a),r.continue()}else t()}}function createLocalStoreSchema(e){e.createObjectStore(LOCAL_STORE,{keyPath:`_id`}).createIndex(`_doc_id_rev`,`_doc_id_rev`,{unique:!0})}function migrateLocalStore(e,t){var n=e.objectStore(LOCAL_STORE),r=e.objectStore(DOC_STORE),a=e.objectStore(BY_SEQ_STORE),o=r.openCursor();o.onsuccess=function(e){var o=e.target.result;if(o){var s=o.value,c=s.id,l=isLocalId(c),u=winningRev(s);if(l){var d=c+`::`+u,p=c+`::`,m=c+`::~`,g=a.index(`_doc_id_rev`),_=IDBKeyRange.bound(p,m,!1,!1),v=g.openCursor(_);v.onsuccess=function(e){if(v=e.target.result,!v)r.delete(o.primaryKey),o.continue();else{var t=v.value;t._doc_id_rev===d&&n.put(t),a.delete(v.primaryKey),v.continue()}}}else o.continue()}else t&&t()}}function addAttachAndSeqStore(e){var t=e.createObjectStore(ATTACH_AND_SEQ_STORE,{autoIncrement:!0});t.createIndex(`seq`,`seq`),t.createIndex(`digestSeq`,`digestSeq`,{unique:!0})}function migrateAttsAndSeqs(e,t){var n=e.objectStore(BY_SEQ_STORE),r=e.objectStore(ATTACH_STORE),a=e.objectStore(ATTACH_AND_SEQ_STORE),o=r.count();o.onsuccess=function(e){if(!e.target.result)return t();n.openCursor().onsuccess=function(e){var n=e.target.result;if(!n)return t();for(var r=n.value,o=n.primaryKey,s=Object.keys(r._attachments||{}),c={},l=0;l<s.length;l++){var u=r._attachments[s[l]];c[u.digest]=!0}var d=Object.keys(c);for(l=0;l<d.length;l++){var p=d[l];a.put({seq:o,digestSeq:p+`::`+o})}n.continue()}}}function migrateMetadata(e){function decodeMetadataCompat(e){return e.data?decodeMetadata(e):(e.deleted=e.deletedOrLocal===`1`,e)}var t=e.objectStore(BY_SEQ_STORE),n=e.objectStore(DOC_STORE),r=n.openCursor();r.onsuccess=function(e){var r=e.target.result;if(!r)return;var a=decodeMetadataCompat(r.value);a.winningRev=a.winningRev||winningRev(a);function fetchMetadataSeq(){var e=a.id+`::`,n=a.id+`::`,r=t.index(`_doc_id_rev`).openCursor(IDBKeyRange.bound(e,n)),o=0;r.onsuccess=function(e){var t=e.target.result;if(!t)return a.seq=o,onGetMetadataSeq();var n=t.primaryKey;n>o&&(o=n),t.continue()}}function onGetMetadataSeq(){var e=encodeMetadata(a,a.winningRev,a.deleted),t=n.put(e);t.onsuccess=function(){r.continue()}}if(a.seq)return onGetMetadataSeq();fetchMetadataSeq()}}e._remote=!1,e.type=function(){return`idb`},e._id=toPromise(function(t){t(null,e._meta.instanceId)}),e._bulkDocs=function idb_bulkDocs(n,r,o){idbBulkDocs(t,n,r,e,a,enrichCallbackError(o))},e._get=function idb_get(e,t,n){var r,o,s,c=t.ctx;if(!c){var l=openTransactionSafely(a,[DOC_STORE,BY_SEQ_STORE,ATTACH_STORE],`readonly`);if(l.error)return n(l.error);c=l.txn}function finish(){n(s,{doc:r,metadata:o,ctx:c})}c.objectStore(DOC_STORE).get(e).onsuccess=function(e){if(o=decodeMetadata(e.target.result),!o)return s=createError$1(MISSING_DOC$1,`missing`),finish();var n;if(t.rev)n=t.latest?latest(t.rev,o):t.rev;else if(n=o.winningRev,isDeleted(o))return s=createError$1(MISSING_DOC$1,`deleted`),finish();var a=c.objectStore(BY_SEQ_STORE),l=o.id+`::`+n;a.index(`_doc_id_rev`).get(l).onsuccess=function(e){if(r=e.target.result,r&&(r=decodeDoc(r)),!r)return s=createError$1(MISSING_DOC$1,`missing`),finish();finish()}}},e._getAttachment=function(e,t,n,r,o){var s;if(r.ctx)s=r.ctx;else{var c=openTransactionSafely(a,[DOC_STORE,BY_SEQ_STORE,ATTACH_STORE],`readonly`);if(c.error)return o(c.error);s=c.txn}var l=n.digest,u=n.content_type;s.objectStore(ATTACH_STORE).get(l).onsuccess=function(e){var t=e.target.result.body;readBlobData(t,u,r.binary,function(e){o(null,e)})}},e._info=function idb_info(t){var n,r,o=openTransactionSafely(a,[META_STORE,BY_SEQ_STORE],`readonly`);if(o.error)return t(o.error);var s=o.txn;s.objectStore(META_STORE).get(META_STORE).onsuccess=function(e){r=e.target.result.docCount},s.objectStore(BY_SEQ_STORE).openKeyCursor(null,`prev`).onsuccess=function(e){var t=e.target.result;n=t?t.key:0},s.oncomplete=function(){t(null,{doc_count:r,update_seq:n,idb_attachment_format:e._meta.blobSupport?`binary`:`base64`})}},e._allDocs=function idb_allDocs(e,t){idbAllDocs(e,a,enrichCallbackError(t))},e._changes=function idbChanges(t){return changes(t,e,r,a)},e._close=function(e){a.close(),cachedDBs.delete(r),e()},e._getRevisionTree=function(e,t){var n=openTransactionSafely(a,[DOC_STORE],`readonly`);if(n.error)return t(n.error);var r=n.txn.objectStore(DOC_STORE).get(e);r.onsuccess=function(e){var n=decodeMetadata(e.target.result);n?t(null,n.rev_tree):t(createError$1(MISSING_DOC$1))}},e._doCompaction=function(e,t,n){var r=openTransactionSafely(a,[DOC_STORE,BY_SEQ_STORE,ATTACH_STORE,ATTACH_AND_SEQ_STORE],`readwrite`);if(r.error)return n(r.error);var o=r.txn,s=o.objectStore(DOC_STORE);s.get(e).onsuccess=function(n){var r=decodeMetadata(n.target.result);traverseRevTree(r.rev_tree,function(e,n,r,a,o){var s=n+`-`+r;t.indexOf(s)!==-1&&(o.status=`missing`)}),compactRevs(t,e,o);var a=r.winningRev,s=r.deleted;o.objectStore(DOC_STORE).put(encodeMetadata(r,a,s))},o.onabort=idbError(n),o.oncomplete=function(){n()}},e._getLocal=function(e,t){var n=openTransactionSafely(a,[LOCAL_STORE],`readonly`);if(n.error)return t(n.error);var r=n.txn.objectStore(LOCAL_STORE).get(e);r.onerror=idbError(t),r.onsuccess=function(e){var n=e.target.result;n?(delete n._doc_id_rev,t(null,n)):t(createError$1(MISSING_DOC$1))}},e._putLocal=function(e,t,n){typeof t==`function`&&(n=t,t={}),delete e._revisions;var r=e._rev,o=e._id;r?e._rev=`0-`+(parseInt(r.split(`-`)[1],10)+1):e._rev=`0-1`;var s=t.ctx,c;if(!s){var l=openTransactionSafely(a,[LOCAL_STORE],`readwrite`);if(l.error)return n(l.error);s=l.txn,s.onerror=idbError(n),s.oncomplete=function(){c&&n(null,c)}}var u=s.objectStore(LOCAL_STORE),d;r?(d=u.get(o),d.onsuccess=function(a){var o=a.target.result;if(!o||o._rev!==r)n(createError$1(REV_CONFLICT$1));else{var s=u.put(e);s.onsuccess=function(){c={ok:!0,id:e._id,rev:e._rev},t.ctx&&n(null,c)}}}):(d=u.add(e),d.onerror=function(e){n(createError$1(REV_CONFLICT$1)),e.preventDefault(),e.stopPropagation()},d.onsuccess=function(){c={ok:!0,id:e._id,rev:e._rev},t.ctx&&n(null,c)})},e._removeLocal=function(e,t,n){typeof t==`function`&&(n=t,t={});var r=t.ctx;if(!r){var o=openTransactionSafely(a,[LOCAL_STORE],`readwrite`);if(o.error)return n(o.error);r=o.txn,r.oncomplete=function(){s&&n(null,s)}}var s,c=e._id,l=r.objectStore(LOCAL_STORE),u=l.get(c);u.onerror=idbError(n),u.onsuccess=function(r){var a=r.target.result;!a||a._rev!==e._rev?n(createError$1(MISSING_DOC$1)):(l.delete(c),s={ok:!0,id:c,rev:`0-0`},t.ctx&&n(null,s))}},e._destroy=function(e,t){changesHandler.removeAllListeners(r);var n=openReqList.get(r);n&&n.result&&(n.result.close(),cachedDBs.delete(r));var a=indexedDB.deleteDatabase(r);a.onsuccess=function(){openReqList.delete(r),hasLocalStorage()&&r in localStorage&&delete localStorage[r],t(null,{ok:!0})},a.onerror=idbError(t)};var s=cachedDBs.get(r);if(s)return a=s.idb,e._meta=s.global,nextTick$1(function(){n(null,e)});var c=indexedDB.open(r,ADAPTER_VERSION);openReqList.set(r,c),c.onupgradeneeded=function(e){var t=e.target.result;if(e.oldVersion<1)return createSchema(t);var n=e.currentTarget.transaction;e.oldVersion<3&&createLocalStoreSchema(t),e.oldVersion<4&&addAttachAndSeqStore(t);var r=[addDeletedOrLocalIndex,migrateLocalStore,migrateAttsAndSeqs,migrateMetadata],a=e.oldVersion;function next(){var e=r[a-1];a++,e&&e(n,next)}next()},c.onsuccess=function(t){a=t.target.result,a.onversionchange=function(){a.close(),cachedDBs.delete(r)},a.onabort=function(e){guardedConsole$1(`error`,`Database has a global failure`,e.target.error),o=e.target.error,a.close(),cachedDBs.delete(r)};var s=a.transaction([META_STORE,DETECT_BLOB_SUPPORT_STORE,DOC_STORE],`readwrite`),c=!1,l,u,d,p;function completeSetup(){d===void 0||!c||(e._meta={name:r,instanceId:p,blobSupport:d},cachedDBs.set(r,{idb:a,global:e._meta}),n(null,e))}function storeMetaDocIfReady(){if(!(u===void 0||l===void 0)){var e=r+`_id`;e in l?p=l[e]:l[e]=p=uuid(),l.docCount=u,s.objectStore(META_STORE).put(l)}}s.objectStore(META_STORE).get(META_STORE).onsuccess=function(e){l=e.target.result||{id:META_STORE},storeMetaDocIfReady()},countDocs(s,function(e){u=e,storeMetaDocIfReady()}),blobSupportPromise||(blobSupportPromise=checkBlobSupport(s,DETECT_BLOB_SUPPORT_STORE,`key`)),blobSupportPromise.then(function(e){d=e,completeSetup()}),s.oncomplete=function(){c=!0,completeSetup()},s.onabort=idbError(n)},c.onerror=function(e){var t=e.target.error&&e.target.error.message;t?t.indexOf(`stored database is a higher version`)!==-1&&(t=Error(`This DB was created with the newer "indexeddb" adapter, but you are trying to open it with the older "idb" adapter`)):t=`Failed to open indexedDB, are you in private browsing mode?`,guardedConsole$1(`error`,t),n(createError$1(IDB_ERROR$1,t))}}IdbPouch.valid=function(){try{return typeof indexedDB<`u`&&typeof IDBKeyRange<`u`}catch{return!1}};function IDBPouch(e){e.adapter(`idb`,IdbPouch,!0)}function pool(e,t){return new Promise(function(n,r){var a=0,o=0,s=0,c=e.length,l;function runNext(){a++,e[o++]().then(onSuccess,onError)}function doNext(){++s===c?l?r(l):n():runNextBatch()}function onSuccess(){a--,doNext()}function onError(e){a--,l=l||e,doNext()}function runNextBatch(){for(;a<t&&o<c;)runNext()}runNextBatch()})}var CHANGES_BATCH_SIZE$1=25,MAX_SIMULTANEOUS_REVS=50,CHANGES_TIMEOUT_BUFFER=5e3,DEFAULT_HEARTBEAT=1e4,supportsBulkGetMap={};function readAttachmentsAsBlobOrBuffer(e){let t=e.doc||e.ok,n=t&&t._attachments;n&&Object.keys(n).forEach(function(e){let t=n[e];t.data=b64ToBluffer$1(t.data,t.content_type)})}function encodeDocId(e){return/^_design/.test(e)?`_design/`+encodeURIComponent(e.slice(8)):e.startsWith(`_local/`)?`_local/`+encodeURIComponent(e.slice(7)):encodeURIComponent(e)}function preprocessAttachments$1(e){return!e._attachments||!Object.keys(e._attachments)?Promise.resolve():Promise.all(Object.keys(e._attachments).map(function(t){let n=e._attachments[t];if(n.data&&typeof n.data!=`string`)return new Promise(function(e){blobToBase64(n.data,e)}).then(function(e){n.data=e})}))}function hasUrlPrefix(e){if(!e.prefix)return!1;let t=parseUri(e.prefix).protocol;return t===`http`||t===`https`}function getHost(e,t){if(hasUrlPrefix(t)){let n=t.name.substr(t.prefix.length);e=t.prefix.replace(/\/?$/,`/`)+encodeURIComponent(n)}let n=parseUri(e);(n.user||n.password)&&(n.auth={username:n.user,password:n.password});let r=n.path.replace(/(^\/|\/$)/g,``).split(`/`);return n.db=r.pop(),n.db.indexOf(`%`)===-1&&(n.db=encodeURIComponent(n.db)),n.path=r.join(`/`),n}function genDBUrl(e,t){return genUrl(e,e.db+`/`+t)}function genUrl(e,t){let n=e.path?`/`:``;return e.protocol+`://`+e.host+(e.port?`:`+e.port:``)+`/`+e.path+n+t}function paramsToStr(e){let t=Object.keys(e);return t.length===0?``:`?`+t.map(t=>t+`=`+encodeURIComponent(e[t])).join(`&`)}function shouldCacheBust(e){let t=typeof navigator<`u`&&navigator.userAgent?navigator.userAgent.toLowerCase():``,n=t.indexOf(`msie`)!==-1,r=t.indexOf(`trident`)!==-1,a=t.indexOf(`edge`)!==-1,o=!(`method`in e)||e.method===`GET`;return(n||r||a)&&o}function HttpPouch(e,t){let n=this,r=getHost(e.name,e),a=genDBUrl(r,``);e=clone$1(e);let ourFetch=async function(t,n){if(n=n||{},n.headers=n.headers||new h$1,n.credentials=`include`,e.auth||r.auth){let t=e.auth||r.auth,a=t.username+`:`+t.password,o=thisBtoa(unescape(encodeURIComponent(a)));n.headers.set(`Authorization`,`Basic `+o)}let a=e.headers||{};return Object.keys(a).forEach(function(e){n.headers.append(e,a[e])}),shouldCacheBust(n)&&(t+=(t.indexOf(`?`)===-1?`?`:`&`)+`_nonce=`+Date.now()),await(e.fetch||f$1)(t,n)};function adapterFun$$1(e,t){return adapterFun(e,function(...e){setup().then(function(){return t.apply(this,e)}).catch(function(t){e.pop()(t)})}).bind(n)}async function fetchJSON(e,t){let n={};t=t||{},t.headers=t.headers||new h$1,t.headers.get(`Content-Type`)||t.headers.set(`Content-Type`,`application/json`),t.headers.get(`Accept`)||t.headers.set(`Accept`,`application/json`);let r=await ourFetch(e,t);if(n.ok=r.ok,n.status=r.status,n.data=await r.json(),!n.ok)throw n.data.status=n.status,generateErrorFromResponse$1(n.data);return Array.isArray(n.data)&&(n.data=n.data.map(function(e){return e.error||e.missing?generateErrorFromResponse$1(e):e})),n}let o;async function setup(){return e.skip_setup?Promise.resolve():o||(o=fetchJSON(a).catch(function(e){return e&&e.status&&e.status===404?(explainError(404,`PouchDB is just detecting if the remote exists.`),fetchJSON(a,{method:`PUT`})):Promise.reject(e)}).catch(function(e){return e&&e.status&&e.status===412?!0:Promise.reject(e)}),o.catch(function(){o=null}),o)}nextTick$1(function(){t(null,n)}),n._remote=!0,n.type=function(){return`http`},n.id=adapterFun$$1(`id`,async function(e){let t;try{t=await(await ourFetch(genUrl(r,``))).json()}catch{t={}}e(null,t&&t.uuid?t.uuid+r.db:genDBUrl(r,``))}),n.compact=adapterFun$$1(`compact`,async function(e,t){typeof e==`function`&&(t=e,e={}),e=clone$1(e),await fetchJSON(genDBUrl(r,`_compact`),{method:`POST`});function ping(){n.info(function(n,r){r&&!r.compact_running?t(null,{ok:!0}):setTimeout(ping,e.interval||200)})}ping()}),n.bulkGet=adapterFun(`bulkGet`,function(e,t){let n=this;async function doBulkGet(t){let n={};e.revs&&(n.revs=!0),e.attachments&&(n.attachments=!0),e.latest&&(n.latest=!0);try{let a=await fetchJSON(genDBUrl(r,`_bulk_get`+paramsToStr(n)),{method:`POST`,body:JSON.stringify({docs:e.docs})});e.attachments&&e.binary&&a.data.results.forEach(function(e){e.docs.forEach(readAttachmentsAsBlobOrBuffer)}),t(null,a.data)}catch(e){t(e)}}function doBulkGetShim(){let r=MAX_SIMULTANEOUS_REVS,a=Math.ceil(e.docs.length/r),o=0,s=Array(a);function onResult(e){return function(n,r){s[e]=r.results,++o===a&&t(null,{results:s.flat()})}}for(let t=0;t<a;t++){let a=pick$1(e,[`revs`,`attachments`,`binary`,`latest`]);a.docs=e.docs.slice(t*r,Math.min(e.docs.length,(t+1)*r)),bulkGet(n,a,onResult(t))}}let a=genUrl(r,``),o=supportsBulkGetMap[a];typeof o==`boolean`?o?doBulkGet(t):doBulkGetShim():doBulkGet(function(e,n){e?(supportsBulkGetMap[a]=!1,explainError(e.status,`PouchDB is just detecting if the remote supports the _bulk_get API.`),doBulkGetShim()):(supportsBulkGetMap[a]=!0,t(null,n))})}),n._info=async function(e){try{await setup();let t=await(await ourFetch(genDBUrl(r,``))).json();t.host=genDBUrl(r,``),e(null,t)}catch(t){e(t)}},n.fetch=async function(e,t){return await setup(),ourFetch(e.substring(0,1)===`/`?genUrl(r,e.substring(1)):genDBUrl(r,e),t)},n.get=adapterFun$$1(`get`,async function(e,t,n){typeof t==`function`&&(n=t,t={}),t=clone$1(t);let a={};t.revs&&(a.revs=!0),t.revs_info&&(a.revs_info=!0),t.latest&&(a.latest=!0),t.open_revs&&(t.open_revs!==`all`&&(t.open_revs=JSON.stringify(t.open_revs)),a.open_revs=t.open_revs),t.rev&&(a.rev=t.rev),t.conflicts&&(a.conflicts=t.conflicts),t.update_seq&&(a.update_seq=t.update_seq),e=encodeDocId(e);function fetchAttachments(e){let n=e._attachments,a=n&&Object.keys(n);if(!n||!a.length)return;async function fetchData(a){let o=n[a],s=await ourFetch(genDBUrl(r,encodeDocId(e._id)+`/`+encodeAttachmentId(a)+`?rev=`+e._rev)),c;c=`buffer`in s?await s.buffer():await s.blob();let l;if(t.binary){let e=Object.getOwnPropertyDescriptor(c.__proto__,`type`);(!e||e.set)&&(c.type=o.content_type),l=c}else l=await new Promise(function(e){blobToBase64(c,e)});delete o.stub,delete o.length,o.data=l}return pool(a.map(function(e){return function(){return fetchData(e)}}),5)}function fetchAllAttachments(e){return Array.isArray(e)?Promise.all(e.map(function(e){if(e.ok)return fetchAttachments(e.ok)})):fetchAttachments(e)}let o=genDBUrl(r,e+paramsToStr(a));try{let e=await fetchJSON(o);t.attachments&&await fetchAllAttachments(e.data),n(null,e.data)}catch(t){t.docId=e,n(t)}}),n.remove=adapterFun$$1(`remove`,async function(e,t,n,a){let o;typeof t==`string`?(o={_id:e,_rev:t},typeof n==`function`&&(a=n,n={})):(o=e,typeof t==`function`?(a=t,n={}):(a=n,n=t));let s=o._rev||n.rev,c=genDBUrl(r,encodeDocId(o._id))+`?rev=`+s;try{let e=await fetchJSON(c,{method:`DELETE`});a(null,e.data)}catch(e){a(e)}});function encodeAttachmentId(e){return e.split(`/`).map(encodeURIComponent).join(`/`)}n.getAttachment=adapterFun$$1(`getAttachment`,async function(e,t,n,a){typeof n==`function`&&(a=n,n={});let o=n.rev?`?rev=`+n.rev:``,s=genDBUrl(r,encodeDocId(e))+`/`+encodeAttachmentId(t)+o;try{let e=await ourFetch(s,{method:`GET`});if(!e.ok)throw e;e.headers.get(`content-type`);let t;t=await e.blob(),a(null,t)}catch(e){a(e)}}),n.removeAttachment=adapterFun$$1(`removeAttachment`,async function(e,t,n,a){let o=genDBUrl(r,encodeDocId(e)+`/`+encodeAttachmentId(t))+`?rev=`+n;try{a(null,(await fetchJSON(o,{method:`DELETE`})).data)}catch(e){a(e)}}),n.putAttachment=adapterFun$$1(`putAttachment`,async function(e,t,n,a,o,s){typeof o==`function`&&(s=o,o=a,a=n,n=null);let c=genDBUrl(r,encodeDocId(e)+`/`+encodeAttachmentId(t));if(n&&(c+=`?rev=`+n),typeof a==`string`){let e;try{e=thisAtob$1(a)}catch{return s(createError$1(BAD_ARG$1,`Attachment is not a valid base64 string`))}a=e?binStringToBluffer$1(e,o):``}try{let e=await fetchJSON(c,{headers:new h$1({"Content-Type":o}),method:`PUT`,body:a});s(null,e.data)}catch(e){s(e)}}),n._bulkDocs=async function(e,t,n){e.new_edits=t.new_edits;try{await setup(),await Promise.all(e.docs.map(preprocessAttachments$1)),n(null,(await fetchJSON(genDBUrl(r,`_bulk_docs`),{method:`POST`,body:JSON.stringify(e)})).data)}catch(e){n(e)}},n._put=async function(e,t,n){try{await setup(),await preprocessAttachments$1(e),n(null,(await fetchJSON(genDBUrl(r,encodeDocId(e._id)),{method:`PUT`,body:JSON.stringify(e)})).data)}catch(t){t.docId=e&&e._id,n(t)}},n.allDocs=adapterFun$$1(`allDocs`,async function(e,t){typeof e==`function`&&(t=e,e={}),e=clone$1(e);let n={},a,o=`GET`;e.conflicts&&(n.conflicts=!0),e.update_seq&&(n.update_seq=!0),e.descending&&(n.descending=!0),e.include_docs&&(n.include_docs=!0),e.attachments&&(n.attachments=!0),e.key&&(n.key=JSON.stringify(e.key)),e.start_key&&(e.startkey=e.start_key),e.startkey&&(n.startkey=JSON.stringify(e.startkey)),e.end_key&&(e.endkey=e.end_key),e.endkey&&(n.endkey=JSON.stringify(e.endkey)),e.inclusive_end!==void 0&&(n.inclusive_end=!!e.inclusive_end),e.limit!==void 0&&(n.limit=e.limit),e.skip!==void 0&&(n.skip=e.skip);let s=paramsToStr(n);e.keys!==void 0&&(o=`POST`,a={keys:e.keys});try{let n=await fetchJSON(genDBUrl(r,`_all_docs`+s),{method:o,body:JSON.stringify(a)});e.include_docs&&e.attachments&&e.binary&&n.data.rows.forEach(readAttachmentsAsBlobOrBuffer),t(null,n.data)}catch(e){t(e)}}),n._changes=function(e){let t=`batch_size`in e?e.batch_size:CHANGES_BATCH_SIZE$1;e=clone$1(e),e.continuous&&!(`heartbeat`in e)&&(e.heartbeat=DEFAULT_HEARTBEAT);let n=`timeout`in e?e.timeout:30*1e3;`timeout`in e&&e.timeout&&n-e.timeout<CHANGES_TIMEOUT_BUFFER&&(n=e.timeout+CHANGES_TIMEOUT_BUFFER),`heartbeat`in e&&e.heartbeat&&n-e.heartbeat<CHANGES_TIMEOUT_BUFFER&&(n=e.heartbeat+CHANGES_TIMEOUT_BUFFER);let a={};`timeout`in e&&e.timeout&&(a.timeout=e.timeout);let o=e.limit===void 0?!1:e.limit,s=o;if(e.style&&(a.style=e.style),(e.include_docs||e.filter&&typeof e.filter==`function`)&&(a.include_docs=!0),e.attachments&&(a.attachments=!0),e.continuous&&(a.feed=`longpoll`),e.seq_interval&&(a.seq_interval=e.seq_interval),e.conflicts&&(a.conflicts=!0),e.descending&&(a.descending=!0),e.update_seq&&(a.update_seq=!0),`heartbeat`in e&&e.heartbeat&&(a.heartbeat=e.heartbeat),e.filter&&typeof e.filter==`string`&&(a.filter=e.filter),e.view&&typeof e.view==`string`&&(a.filter=`_view`,a.view=e.view),e.query_params&&typeof e.query_params==`object`)for(let t in e.query_params)Object.prototype.hasOwnProperty.call(e.query_params,t)&&(a[t]=e.query_params[t]);let c=`GET`,l;e.doc_ids?(a.filter=`_doc_ids`,c=`POST`,l={doc_ids:e.doc_ids}):e.selector&&(a.filter=`_selector`,c=`POST`,l={selector:e.selector});let u=new AbortController,d,fetchData=async function(n,p){if(e.aborted)return;a.since=n,typeof a.since==`object`&&(a.since=JSON.stringify(a.since)),e.descending?o&&(a.limit=s):a.limit=!o||s>t?t:s;let m=genDBUrl(r,`_changes`+paramsToStr(a)),g={signal:u.signal,method:c,body:JSON.stringify(l)};if(d=n,!e.aborted)try{await setup(),p(null,(await fetchJSON(m,g)).data)}catch(e){p(e)}},p={results:[]},fetched=function(n,r){if(e.aborted)return;let a=0;if(r&&r.results){a=r.results.length,p.last_seq=r.last_seq;let t=null,n=null;typeof r.pending==`number`&&(t=r.pending),(typeof p.last_seq==`string`||typeof p.last_seq==`number`)&&(n=p.last_seq);let o={};o.query=e.query_params,r.results=r.results.filter(function(r){s--;let a=filterChange(e)(r);return a&&(e.include_docs&&e.attachments&&e.binary&&readAttachmentsAsBlobOrBuffer(r),e.return_docs&&p.results.push(r),e.onChange(r,t,n)),a})}else if(n){e.aborted=!0,e.complete(n);return}r&&r.last_seq&&(d=r.last_seq);let c=o&&s<=0||r&&a<t||e.descending;e.continuous&&!(o&&s<=0)||!c?nextTick$1(function(){fetchData(d,fetched)}):e.complete(null,p)};return fetchData(e.since||0,fetched),{cancel:function(){e.aborted=!0,u.abort()}}},n.revsDiff=adapterFun$$1(`revsDiff`,async function(e,t,n){typeof t==`function`&&(n=t,t={});try{let t=await fetchJSON(genDBUrl(r,`_revs_diff`),{method:`POST`,body:JSON.stringify(e)});n(null,t.data)}catch(e){n(e)}}),n._close=function(e){e()},n._destroy=async function(e,t){try{t(null,await fetchJSON(genDBUrl(r,``),{method:`DELETE`}))}catch(e){e.status===404?t(null,{ok:!0}):t(e)}}}HttpPouch.valid=function(){return!0};function HttpPouch$1(e){e.adapter(`http`,HttpPouch,!1),e.adapter(`https`,HttpPouch,!1)}var QueryParseError$1=class QueryParseError$1 extends Error{static{__name(this,`QueryParseError`)}constructor(e){super(),this.status=400,this.name=`query_parse_error`,this.message=e,this.error=!0;try{Error.captureStackTrace(this,QueryParseError$1)}catch{}}},NotFoundError$1=class NotFoundError$1 extends Error{static{__name(this,`NotFoundError`)}constructor(e){super(),this.status=404,this.name=`not_found`,this.message=e,this.error=!0;try{Error.captureStackTrace(this,NotFoundError$1)}catch{}}},BuiltInError$1=class BuiltInError$1 extends Error{static{__name(this,`BuiltInError`)}constructor(e){super(),this.status=500,this.name=`invalid_value`,this.message=e,this.error=!0;try{Error.captureStackTrace(this,BuiltInError$1)}catch{}}};function promisedCallback$1(e,t){return t&&e.then(function(e){nextTick$1(function(){t(null,e)})},function(e){nextTick$1(function(){t(e)})}),e}__name(promisedCallback$1,`promisedCallback`);function callbackify$1(e){return function(...t){var n=t.pop(),r=e.apply(this,t);return typeof n==`function`&&promisedCallback$1(r,n),r}}__name(callbackify$1,`callbackify`);function fin$1(e,t){return e.then(function(e){return t().then(function(){return e})},function(e){return t().then(function(){throw e})})}__name(fin$1,`fin`);function sequentialize$1(e,t){return function(){var n=arguments,r=this;return e.add(function(){return t.apply(r,n)})}}__name(sequentialize$1,`sequentialize`);function uniq$2(e){var t=new Set(e),n=Array(t.size),r=-1;return t.forEach(function(e){n[++r]=e}),n}__name(uniq$2,`uniq`);function mapToKeysArray$1(e){var t=Array(e.size),n=-1;return e.forEach(function(e,r){t[++n]=r}),t}__name(mapToKeysArray$1,`mapToKeysArray`);function createBuiltInError(e){return new BuiltInError$1(`builtin `+e+` function requires map values to be numbers or number arrays`)}function sum(e){for(var t=0,n=0,r=e.length;n<r;n++){var a=e[n];if(typeof a!=`number`)if(Array.isArray(a)){t=typeof t==`number`?[t]:t;for(var o=0,s=a.length;o<s;o++){var c=a[o];if(typeof c!=`number`)throw createBuiltInError(`_sum`);t[o]===void 0?t.push(c):t[o]+=c}}else throw createBuiltInError(`_sum`);else typeof t==`number`?t+=a:t[0]+=a}return t}var log$1=guardedConsole$1.bind(null,`log`),isArray=Array.isArray,toJSON=JSON.parse;function evalFunctionWithEval(e,t){return scopeEval(`return (`+e.replace(/;\s*$/,``)+`);`,{emit:t,sum,log:log$1,isArray,toJSON})}var TaskQueue$1$1=class{static{__name(this,`TaskQueue$1`)}constructor(){this.promise=Promise.resolve()}add(e){return this.promise=this.promise.catch(()=>{}).then(()=>e()),this.promise}finish(){return this.promise}};function stringify$1(e){if(!e)return`undefined`;switch(typeof e){case`function`:return e.toString();case`string`:return e.toString();default:return JSON.stringify(e)}}__name(stringify$1,`stringify`);function createViewSignature$1(e,t){return stringify$1(e)+stringify$1(t)+`undefined`}__name(createViewSignature$1,`createViewSignature`);async function createView$1(e,t,n,r,a,o){let s=createViewSignature$1(n,r),c;if(!a&&(c=e._cachedViews=e._cachedViews||{},c[s]))return c[s];let l=e.info().then(async function(l){let u=l.db_name+`-mrview-`+(a?`temp`:stringMd5$1(s));function diffFunction(e){e.views=e.views||{};let n=t;n.indexOf(`/`)===-1&&(n=t+`/`+t);let r=e.views[n]=e.views[n]||{};if(!r[u])return r[u]=!0,e}await upsert$1(e,`_local/`+o,diffFunction);let d=(await e.registerDependentDatabase(u)).db;d.auto_compaction=!0;let p={name:u,db:d,sourceDB:e,adapter:e.adapter,mapFun:n,reduceFun:r},m;try{m=await p.db.get(`_local/lastSeq`)}catch(e){if(e.status!==404)throw e}return p.seq=m?m.seq:0,c&&p.db.once(`destroyed`,function(){delete c[s]}),p});return c&&(c[s]=l),l}__name(createView$1,`createView`);var persistentQueues$1={},tempViewQueue$1=new TaskQueue$1$1,CHANGES_BATCH_SIZE$1$1=50;function parseViewName$1(e){return e.indexOf(`/`)===-1?[e,e]:e.split(`/`)}__name(parseViewName$1,`parseViewName`);function isGenOne$1(e){return e.length===1&&/^1-/.test(e[0].rev)}__name(isGenOne$1,`isGenOne`);function emitError$1(e,t,n){try{e.emit(`error`,t)}catch{guardedConsole$1(`error`,`The user's map/reduce function threw an uncaught error.
|
|
@@ -8,10 +8,9 @@ Please double-check your map/reduce function.`),guardedConsole$1(`error`,t,n)}}_
|
|
|
8
8
|
You can debug this error by doing:
|
|
9
9
|
myDatabase.on('error', function (err) { debugger; });
|
|
10
10
|
Please double-check your map/reduce function.`),guardedConsole(`error`,t,n)}}function createAbstractMapReduce(e,t,n,r){function tryMap(e,t,n){try{t(n)}catch(r){emitError(e,r,{fun:t,doc:n})}}function tryReduce(e,t,n,r,a){try{return{output:t(n,r,a)}}catch(o){return emitError(e,o,{fun:t,keys:n,values:r,rereduce:a}),{error:o}}}function sortByKeyThenValue(e,t){let n=collate(e.key,t.key);return n===0?collate(e.value,t.value):n}function sliceResults(e,t,n){return n=n||0,typeof t==`number`?e.slice(n,t+n):n>0?e.slice(n):e}function rowToDocId(e){let t=e.value;return t&&typeof t==`object`&&t._id||e.id}function readAttachmentsAsBlobOrBuffer(e){for(let t of e.rows){let e=t.doc&&t.doc._attachments;if(e)for(let t of Object.keys(e)){let n=e[t];e[t].data=b64ToBluffer(n.data,n.content_type)}}}function postprocessAttachments(e){return function(t){return e.include_docs&&e.attachments&&e.binary&&readAttachmentsAsBlobOrBuffer(t),t}}function addHttpParam(e,t,n,r){let a=t[e];a!==void 0&&(r&&(a=encodeURIComponent(JSON.stringify(a))),n.push(e+`=`+a))}function coerceInteger(e){if(e!==void 0){let t=Number(e);return!isNaN(t)&&t===parseInt(e,10)?t:e}}function coerceOptions(e){return e.group_level=coerceInteger(e.group_level),e.limit=coerceInteger(e.limit),e.skip=coerceInteger(e.skip),e}function checkPositiveInteger(e){if(e){if(typeof e!=`number`)return new QueryParseError(`Invalid value for integer: "${e}"`);if(e<0)return new QueryParseError(`Invalid value for positive integer: "${e}"`)}}function checkQueryParseError(e,t){let n=e.descending?`endkey`:`startkey`,r=e.descending?`startkey`:`endkey`;if(e[n]!==void 0&&e[r]!==void 0&&collate(e[n],e[r])>0)throw new QueryParseError(`No rows can match your key range, reverse your start_key and end_key or set {descending : true}`);if(t.reduce&&e.reduce!==!1){if(e.include_docs)throw new QueryParseError(`{include_docs:true} is invalid for reduce`);if(e.keys&&e.keys.length>1&&!e.group&&!e.group_level)throw new QueryParseError(`Multi-key fetches for reduce views must use {group: true}`)}for(let t of[`group_level`,`limit`,`skip`]){let n=checkPositiveInteger(e[t]);if(n)throw n}}async function httpQuery(e,t,n){let r=[],a,o=`GET`,s;if(addHttpParam(`reduce`,n,r),addHttpParam(`include_docs`,n,r),addHttpParam(`attachments`,n,r),addHttpParam(`limit`,n,r),addHttpParam(`descending`,n,r),addHttpParam(`group`,n,r),addHttpParam(`group_level`,n,r),addHttpParam(`skip`,n,r),addHttpParam(`stale`,n,r),addHttpParam(`conflicts`,n,r),addHttpParam(`startkey`,n,r,!0),addHttpParam(`start_key`,n,r,!0),addHttpParam(`endkey`,n,r,!0),addHttpParam(`end_key`,n,r,!0),addHttpParam(`inclusive_end`,n,r),addHttpParam(`key`,n,r,!0),addHttpParam(`update_seq`,n,r),r=r.join(`&`),r=r===``?``:`?`+r,n.keys!==void 0){let e=2e3,s=`keys=${encodeURIComponent(JSON.stringify(n.keys))}`;s.length+r.length+1<=2e3?r+=(r[0]===`?`?`&`:`?`)+s:(o=`POST`,typeof t==`string`?a={keys:n.keys}:t.keys=n.keys)}if(typeof t==`string`){let c=parseViewName(t),l=await e.fetch(`_design/`+c[0]+`/_view/`+c[1]+r,{headers:new h({"Content-Type":`application/json`}),method:o,body:JSON.stringify(a)});s=l.ok;let u=await l.json();if(!s)throw u.status=l.status,generateErrorFromResponse(u);for(let e of u.rows)if(e.value&&e.value.error&&e.value.error===`builtin_reduce_error`)throw Error(e.reason);return new Promise(function(e){e(u)}).then(postprocessAttachments(n))}a=a||{};for(let e of Object.keys(t))Array.isArray(t[e])?a[e]=t[e]:a[e]=t[e].toString();let c=await e.fetch(`_temp_view`+r,{headers:new h({"Content-Type":`application/json`}),method:`POST`,body:JSON.stringify(a)});s=c.ok;let l=await c.json();if(!s)throw l.status=c.status,generateErrorFromResponse(l);return new Promise(function(e){e(l)}).then(postprocessAttachments(n))}function customQuery(e,t,n){return new Promise(function(r,a){e._query(t,n,function(e,t){if(e)return a(e);r(t)})})}function customViewCleanup(e){return new Promise(function(t,n){e._viewCleanup(function(e,r){if(e)return n(e);t(r)})})}function defaultsTo(e){return function(t){if(t.status===404)return e;throw t}}async function getDocsToPersist(e,t,n){let r=`_local/doc_`+e,a={_id:r,keys:[]},o=n.get(e),s=o[0],c=o[1];function getMetaDoc(){return isGenOne(c)?Promise.resolve(a):t.db.get(r).catch(defaultsTo(a))}function getKeyValueDocs(e){return e.keys.length?t.db.allDocs({keys:e.keys,include_docs:!0}):Promise.resolve({rows:[]})}function processKeyValueDocs(e,t){let n=[],r=new Set;for(let e of t.rows){let t=e.doc;if(t&&(n.push(t),r.add(t._id),t._deleted=!s.has(t._id),!t._deleted)){let e=s.get(t._id);`value`in e&&(t.value=e.value)}}let a=mapToKeysArray(s);for(let e of a)if(!r.has(e)){let t={_id:e},r=s.get(e);`value`in r&&(t.value=r.value),n.push(t)}return e.keys=uniq$1(a.concat(e.keys)),n.push(e),n}let l=await getMetaDoc();return processKeyValueDocs(l,await getKeyValueDocs(l))}function updatePurgeSeq(e){return e.sourceDB.get(`_local/purges`).then(function(t){let n=t.purgeSeq;return e.db.get(`_local/purgeSeq`).then(function(e){return e._rev}).catch(defaultsTo(void 0)).then(function(t){return e.db.put({_id:`_local/purgeSeq`,_rev:t,purgeSeq:n})})}).catch(function(e){if(e.status!==404)throw e})}function saveKeyValues(e,t,n){var r=`_local/lastSeq`;return e.db.get(r).catch(defaultsTo({_id:r,seq:0})).then(function(r){var a=mapToKeysArray(t);return Promise.all(a.map(function(n){return getDocsToPersist(n,e,t)})).then(function(t){var a=t.flat();return r.seq=n,a.push(r),e.db.bulkDocs({docs:a})}).then(()=>updatePurgeSeq(e))})}function getQueue(e){let t=typeof e==`string`?e:e.name,n=persistentQueues[t];return n||(n=persistentQueues[t]=new TaskQueue),n}async function updateView(e,t){return sequentialize(getQueue(e),function(){return updateViewInQueue(e,t)})()}async function updateViewInQueue(e,n){let r,a,o;function emit(e,t){let n={id:a._id,key:normalizeKey(e)};t!=null&&(n.value=normalizeKey(t)),r.push(n)}let s=t(e.mapFun,emit),c=e.seq||0;function createTask(){return e.sourceDB.info().then(function(t){o=e.sourceDB.activeTasks.add({name:`view_indexing`,total_items:t.update_seq-c})})}function processChange(t,n){return function(){return saveKeyValues(e,t,n)}}let l=0,u={view:e.name,indexed_docs:l};e.sourceDB.emit(`indexing`,u);let d=new TaskQueue;async function processNextBatch(){return processBatch(await e.sourceDB.changes({return_docs:!0,conflicts:!0,include_docs:!0,style:`all_docs`,since:c,limit:n.changes_batch_size}),await getRecentPurges())}function getRecentPurges(){return e.db.get(`_local/purgeSeq`).then(function(e){return e.purgeSeq}).catch(defaultsTo(-1)).then(function(t){return e.sourceDB.get(`_local/purges`).then(function(n){let r=n.purges.filter(function(e,n){return n>t}).map(e=>e.docId),a=r.filter(function(e,t){return r.indexOf(e)===t});return Promise.all(a.map(function(t){return e.sourceDB.get(t).then(function(e){return{docId:t,doc:e}}).catch(defaultsTo({docId:t}))}))}).catch(defaultsTo([]))})}function processBatch(t,r){let a=t.results;if(!a.length&&!r.length)return;for(let e of r)if(a.findIndex(function(t){return t.id===e.docId})<0){let t={_id:e.docId,doc:{_id:e.docId,_deleted:1},changes:[]};e.doc&&(t.doc=e.doc,t.changes.push({rev:e.doc._rev})),a.push(t)}let s=createDocIdsToChangesAndEmits(a);d.add(processChange(s,c)),l+=a.length;let u={view:e.name,last_seq:t.last_seq,results_count:a.length,indexed_docs:l};if(e.sourceDB.emit(`indexing`,u),e.sourceDB.activeTasks.update(o,{completed_items:l}),!(a.length<n.changes_batch_size))return processNextBatch()}function createDocIdsToChangesAndEmits(t){let n=new Map;for(let o of t){if(o.doc._id[0]!==`_`){r=[],a=o.doc,a._deleted||tryMap(e.sourceDB,s,a),r.sort(sortByKeyThenValue);let t=createIndexableKeysToKeyValues(r);n.set(o.doc._id,[t,o.changes])}c=o.seq}return n}function createIndexableKeysToKeyValues(e){let t=new Map,n;for(let r=0,a=e.length;r<a;r++){let a=e[r],o=[a.key,a.id];r>0&&collate(a.key,n)===0&&o.push(r),t.set(toIndexableString(o),a),n=a.key}return t}try{await createTask(),await processNextBatch(),await d.finish(),e.seq=c,e.sourceDB.activeTasks.remove(o)}catch(t){e.sourceDB.activeTasks.remove(o,t)}}function reduceView(e,t,r){r.group_level===0&&delete r.group_level;let a=r.group||r.group_level,o=n(e.reduceFun),s=[],c=isNaN(r.group_level)?1/0:r.group_level;for(let e of t){let t=s[s.length-1],n=a?e.key:null;if(a&&Array.isArray(n)&&(n=n.slice(0,c)),t&&collate(t.groupKey,n)===0){t.keys.push([e.key,e.id]),t.values.push(e.value);continue}s.push({keys:[[e.key,e.id]],values:[e.value],groupKey:n})}t=[];for(let n of s){let r=tryReduce(e.sourceDB,o,n.keys,n.values,!1);if(r.error&&r.error instanceof BuiltInError)throw r.error;t.push({value:r.error?null:r.output,key:n.groupKey})}return{rows:sliceResults(t,r.limit,r.skip)}}function queryView(e,t){return sequentialize(getQueue(e),function(){return queryViewInQueue(e,t)})()}async function queryViewInQueue(e,t){let n,r=e.reduceFun&&t.reduce!==!1,a=t.skip||0;t.keys!==void 0&&!t.keys.length&&(t.limit=0,delete t.keys);async function fetchFromView(t){t.include_docs=!0;let r=await e.db.allDocs(t);return n=r.total_rows,r.rows.map(function(e){if(`value`in e.doc&&typeof e.doc.value==`object`&&e.doc.value!==null){let t=Object.keys(e.doc.value).sort(),n=[`id`,`key`,`value`];if(!(t<n||t>n))return e.doc.value}let t=parseIndexableString(e.doc._id);return{key:t[0],id:t[1],value:`value`in e.doc?e.doc.value:null}})}async function onMapResultsReady(o){let s;if(s=r?reduceView(e,o,t):t.keys===void 0?{total_rows:n,offset:a,rows:o}:{total_rows:n,offset:a,rows:sliceResults(o,t.limit,t.skip)},t.update_seq&&(s.update_seq=e.seq),t.include_docs){let n=uniq$1(o.map(rowToDocId)),r=await e.sourceDB.allDocs({keys:n,include_docs:!0,conflicts:t.conflicts,attachments:t.attachments,binary:t.binary}),a=new Map;for(let e of r.rows)a.set(e.id,e.doc);for(let e of o){let t=rowToDocId(e),n=a.get(t);n&&(e.doc=n)}}return s}if(t.keys!==void 0){let e=t.keys.map(function(e){let n={startkey:toIndexableString([e]),endkey:toIndexableString([e,{}])};return t.update_seq&&(n.update_seq=!0),fetchFromView(n)});return onMapResultsReady((await Promise.all(e)).flat())}else{let e={descending:t.descending};t.update_seq&&(e.update_seq=!0);let n,o;if(`start_key`in t&&(n=t.start_key),`startkey`in t&&(n=t.startkey),`end_key`in t&&(o=t.end_key),`endkey`in t&&(o=t.endkey),n!==void 0&&(e.startkey=t.descending?toIndexableString([n,{}]):toIndexableString([n])),o!==void 0){let n=t.inclusive_end!==!1;t.descending&&(n=!n),e.endkey=toIndexableString(n?[o,{}]:[o])}if(t.key!==void 0){let n=toIndexableString([t.key]),r=toIndexableString([t.key,{}]);e.descending?(e.endkey=n,e.startkey=r):(e.startkey=n,e.endkey=r)}return r||(typeof t.limit==`number`&&(e.limit=t.limit),e.skip=a),onMapResultsReady(await fetchFromView(e))}}async function httpViewCleanup(e){return(await e.fetch(`_view_cleanup`,{headers:new h({"Content-Type":`application/json`}),method:`POST`})).json()}async function localViewCleanup(t){try{let n=await t.get(`_local/`+e),r=new Map;for(let e of Object.keys(n.views)){let t=parseViewName(e),n=`_design/`+t[0],a=t[1],o=r.get(n);o||(o=new Set,r.set(n,o)),o.add(a)}let a={keys:mapToKeysArray(r),include_docs:!0},o=await t.allDocs(a),s={};for(let e of o.rows){let t=e.key.substring(8);for(let a of r.get(e.key)){let r=t+`/`+a;n.views[r]||(r=a);let o=Object.keys(n.views[r]),c=e.doc&&e.doc.views&&e.doc.views[a];for(let e of o)s[e]=s[e]||c}}let c=Object.keys(s).filter(function(e){return!s[e]}).map(function(e){return sequentialize(getQueue(e),function(){return new t.constructor(e,t.__opts).destroy()})()});return Promise.all(c).then(function(){return{ok:!0}})}catch(e){if(e.status===404)return{ok:!0};throw e}}async function queryPromised(t,n,a){if(typeof t._query==`function`)return customQuery(t,n,a);if(isRemote(t))return httpQuery(t,n,a);let o={changes_batch_size:t.__opts.view_update_changes_batch_size||CHANGES_BATCH_SIZE};if(typeof n!=`string`)return checkQueryParseError(a,n),tempViewQueue.add(async function(){let r=await createView(t,`temp_view/temp_view`,n.map,n.reduce,!0,e);return fin(updateView(r,o).then(function(){return queryView(r,a)}),function(){return r.db.destroy()})}),tempViewQueue.finish();{let s=n,c=parseViewName(s),l=c[0],u=c[1],d=await t.get(`_design/`+l);if(n=d.views&&d.views[u],!n)throw new NotFoundError(`ddoc ${d._id} has no view named ${u}`);r(d,u),checkQueryParseError(a,n);let p=await createView(t,s,n.map,n.reduce,!1,e);return a.stale===`ok`||a.stale===`update_after`?(a.stale===`update_after`&&nextTick(function(){updateView(p,o)}),queryView(p,a)):(await updateView(p,o),queryView(p,a))}}function abstractQuery(e,t,n){let r=this;typeof t==`function`&&(n=t,t={}),t=t?coerceOptions(t):{},typeof e==`function`&&(e={map:e});let a=Promise.resolve().then(function(){return queryPromised(r,e,t)});return promisedCallback(a,n),a}return{query:abstractQuery,viewCleanup:callbackify(function(){let e=this;return typeof e._viewCleanup==`function`?customViewCleanup(e):isRemote(e)?httpViewCleanup(e):localViewCleanup(e)})}}function getFieldFromDoc(e,t){for(var n=e,r=0,a=t.length;r<a;r++){var o=t[r];if(n=n[o],!n)break}return n}function setFieldInDoc(e,t,n){for(var r=0,a=t.length;r<a-1;r++){var o=t[r];e=e[o]=e[o]||{}}e[t[a-1]]=n}function compare(e,t){return e<t?-1:e>t?1:0}function parseField(e){for(var t=[],n=``,r=0,a=e.length;r<a;r++){var o=e[r];r>0&&e[r-1]===`\\`&&(o===`$`||o===`.`)?n=n.substring(0,n.length-1)+o:o===`.`?(t.push(n),n=``):n+=o}return t.push(n),t}var combinationFields=[`$or`,`$nor`,`$not`];function isCombinationalField(e){return combinationFields.indexOf(e)>-1}function getKey(e){return Object.keys(e)[0]}function getValue(e){return e[getKey(e)]}function mergeAndedSelectors(e){var t={},n={$or:!0,$nor:!0};return e.forEach(function(e){Object.keys(e).forEach(function(r){var a=e[r];if(typeof a!=`object`&&(a={$eq:a}),isCombinationalField(r))if(a instanceof Array){if(n[r]){n[r]=!1,t[r]=a;return}var o=[];t[r].forEach(function(e){Object.keys(a).forEach(function(t){var n=a[t],r=Math.max(Object.keys(e).length,Object.keys(n).length),s=mergeAndedSelectors([e,n]);Object.keys(s).length<=r||o.push(s)})}),t[r]=o}else t[r]=mergeAndedSelectors([a]);else{var s=t[r]=t[r]||{};Object.keys(a).forEach(function(e){var t=a[e];if(e===`$gt`||e===`$gte`)return mergeGtGte(e,t,s);if(e===`$lt`||e===`$lte`)return mergeLtLte(e,t,s);if(e===`$ne`)return mergeNe(t,s);if(e===`$eq`)return mergeEq(t,s);if(e===`$regex`)return mergeRegex(t,s);s[e]=t})}})}),t}function mergeGtGte(e,t,n){n.$eq===void 0&&(n.$gte===void 0?n.$gt===void 0?n[e]=t:e===`$gte`?t>n.$gt&&(delete n.$gt,n.$gte=t):t>n.$gt&&(n.$gt=t):e===`$gte`?t>n.$gte&&(n.$gte=t):t>=n.$gte&&(delete n.$gte,n.$gt=t))}function mergeLtLte(e,t,n){n.$eq===void 0&&(n.$lte===void 0?n.$lt===void 0?n[e]=t:e===`$lte`?t<n.$lt&&(delete n.$lt,n.$lte=t):t<n.$lt&&(n.$lt=t):e===`$lte`?t<n.$lte&&(n.$lte=t):t<=n.$lte&&(delete n.$lte,n.$lt=t))}function mergeNe(e,t){`$ne`in t?t.$ne.push(e):t.$ne=[e]}function mergeEq(e,t){delete t.$gt,delete t.$gte,delete t.$lt,delete t.$lte,delete t.$ne,t.$eq=e}function mergeRegex(e,t){`$regex`in t?t.$regex.push(e):t.$regex=[e]}function mergeAndedSelectorsNested(e){for(var t in e){if(Array.isArray(e))for(var n in e)e[n].$and&&(e[n]=mergeAndedSelectors(e[n].$and));var r=e[t];typeof r==`object`&&mergeAndedSelectorsNested(r)}return e}function isAndInSelector(e,t){for(var n in e){n===`$and`&&(t=!0);var r=e[n];typeof r==`object`&&(t=isAndInSelector(r,t))}return t}function massageSelector(e){var t=clone(e);isAndInSelector(t,!1)&&(t=mergeAndedSelectorsNested(t),`$and`in t&&(t=mergeAndedSelectors(t.$and))),[`$or`,`$nor`].forEach(function(e){e in t&&t[e].forEach(function(e){for(var t=Object.keys(e),n=0;n<t.length;n++){var r=t[n],a=e[r];(typeof a!=`object`||!a)&&(e[r]={$eq:a})}})}),`$not`in t&&(t.$not=mergeAndedSelectors([t.$not]));for(var n=Object.keys(t),r=0;r<n.length;r++){var a=n[r],o=t[a];(typeof o!=`object`||!o)&&(o={$eq:o}),t[a]=o}return normalizeArrayOperators(t),t}function normalizeArrayOperators(e){Object.keys(e).forEach(function(t){var n=e[t];Array.isArray(n)?n.forEach(function(e){e&&typeof e==`object`&&normalizeArrayOperators(e)}):t===`$ne`?e.$ne=[n]:t===`$regex`?e.$regex=[n]:n&&typeof n==`object`&&normalizeArrayOperators(n)})}function createFieldSorter(e){function getFieldValuesAsArray(t){return e.map(function(e){return getFieldFromDoc(t,parseField(getKey(e)))})}return function(e,t){var n=collate(getFieldValuesAsArray(e.doc),getFieldValuesAsArray(t.doc));return n===0?compare(e.doc._id,t.doc._id):n}}function filterInMemoryFields(e,t,n){if(e=e.filter(function(e){return rowFilter(e.doc,t.selector,n)}),t.sort){var r=createFieldSorter(t.sort);e=e.sort(r),typeof t.sort[0]!=`string`&&getValue(t.sort[0])===`desc`&&(e=e.reverse())}if(`limit`in t||`skip`in t){var a=t.skip||0,o=(`limit`in t?t.limit:e.length)+a;e=e.slice(a,o)}return e}function rowFilter(e,t,n){return n.every(function(n){var r=t[n],a=parseField(n),o=getFieldFromDoc(e,a);return isCombinationalField(n)?matchCominationalSelector(n,r,e):matchSelector(r,e,a,o)})}function matchSelector(e,t,n,r){return e?typeof e==`object`?Object.keys(e).every(function(a){var o=e[a];if(a.indexOf(`$`)===0)return match(a,t,o,n,r);var s=parseField(a);if(r===void 0&&typeof o!=`object`&&s.length>0)return!1;var c=getFieldFromDoc(r,s);return typeof o==`object`?matchSelector(o,t,n,c):match(`$eq`,t,o,s,c)}):e===r:!0}function matchCominationalSelector(e,t,n){return e===`$or`?t.some(function(e){return rowFilter(n,e,Object.keys(e))}):e===`$not`?!rowFilter(n,t,Object.keys(t)):!t.find(function(e){return rowFilter(n,e,Object.keys(e))})}function match(e,t,n,r,a){if(!matchers[e])throw Error(`unknown operator "`+e+`" - should be one of $eq, $lte, $lt, $gt, $gte, $exists, $ne, $in, $nin, $size, $mod, $regex, $elemMatch, $type, $allMatch or $all`);return matchers[e](t,n,r,a)}function fieldExists(e){return e!=null}function fieldIsNotUndefined(e){return e!==void 0}function modField(e,t){if(typeof e!=`number`||parseInt(e,10)!==e)return!1;var n=t[0],r=t[1];return e%n===r}function arrayContainsValue(e,t){return t.some(function(t){return e instanceof Array?e.some(function(e){return collate(t,e)===0}):collate(t,e)===0})}function arrayContainsAllValues(e,t){return t.every(function(t){return e.some(function(e){return collate(t,e)===0})})}function arraySize(e,t){return e.length===t}function regexMatch(e,t){return new RegExp(t).test(e)}function typeMatch(e,t){switch(t){case`null`:return e===null;case`boolean`:return typeof e==`boolean`;case`number`:return typeof e==`number`;case`string`:return typeof e==`string`;case`array`:return e instanceof Array;case`object`:return{}.toString.call(e)===`[object Object]`}}var matchers={$elemMatch:function(e,t,n,r){return!Array.isArray(r)||r.length===0?!1:typeof r[0]==`object`&&r[0]!==null?r.some(function(e){return rowFilter(e,t,Object.keys(t))}):r.some(function(r){return matchSelector(t,e,n,r)})},$allMatch:function(e,t,n,r){return!Array.isArray(r)||r.length===0?!1:typeof r[0]==`object`&&r[0]!==null?r.every(function(e){return rowFilter(e,t,Object.keys(t))}):r.every(function(r){return matchSelector(t,e,n,r)})},$eq:function(e,t,n,r){return fieldIsNotUndefined(r)&&collate(r,t)===0},$gte:function(e,t,n,r){return fieldIsNotUndefined(r)&&collate(r,t)>=0},$gt:function(e,t,n,r){return fieldIsNotUndefined(r)&&collate(r,t)>0},$lte:function(e,t,n,r){return fieldIsNotUndefined(r)&&collate(r,t)<=0},$lt:function(e,t,n,r){return fieldIsNotUndefined(r)&&collate(r,t)<0},$exists:function(e,t,n,r){return t?fieldIsNotUndefined(r):!fieldIsNotUndefined(r)},$mod:function(e,t,n,r){return fieldExists(r)&&modField(r,t)},$ne:function(e,t,n,r){return t.every(function(e){return collate(r,e)!==0})},$in:function(e,t,n,r){return fieldExists(r)&&arrayContainsValue(r,t)},$nin:function(e,t,n,r){return fieldExists(r)&&!arrayContainsValue(r,t)},$size:function(e,t,n,r){return fieldExists(r)&&Array.isArray(r)&&arraySize(r,t)},$all:function(e,t,n,r){return Array.isArray(r)&&arrayContainsAllValues(r,t)},$regex:function(e,t,n,r){return fieldExists(r)&&typeof r==`string`&&t.every(function(e){return regexMatch(r,e)})},$type:function(e,t,n,r){return typeMatch(r,t)}};function matchesSelector(e,t){if(typeof t!=`object`)throw Error(`Selector error: expected a JSON object`);t=massageSelector(t);var n=filterInMemoryFields([{doc:e}],{selector:t},Object.keys(t));return n&&n.length===1}var nativeFlat=(...e)=>e.flat(1/0),polyFlat=(...e)=>{let t=[];for(let n of e)Array.isArray(n)?t=t.concat(polyFlat(...n)):t.push(n);return t},flatten=typeof Array.prototype.flat==`function`?nativeFlat:polyFlat;function mergeObjects(e){let t={};for(let n of e)Object.assign(t,n);return t}function pick(e,t){let n={};for(let r of t){let t=parseField(r),a=getFieldFromDoc(e,t);a!==void 0&&setFieldInDoc(n,t,a)}return n}function oneArrayIsSubArrayOfOther(e,t){for(let n=0,r=Math.min(e.length,t.length);n<r;n++)if(e[n]!==t[n])return!1;return!0}function oneArrayIsStrictSubArrayOfOther(e,t){return e.length>t.length?!1:oneArrayIsSubArrayOfOther(e,t)}function oneSetIsSubArrayOfOther(e,t){e=e.slice();for(let n of t){if(!e.length)break;let t=e.indexOf(n);if(t===-1)return!1;e.splice(t,1)}return!0}function arrayToObject(e){let t={};for(let n of e)t[n]=!0;return t}function max(e,t){let n=null,r=-1;for(let a of e){let e=t(a);e>r&&(r=e,n=a)}return n}function arrayEquals(e,t){if(e.length!==t.length)return!1;for(let n=0,r=e.length;n<r;n++)if(e[n]!==t[n])return!1;return!0}function uniq(e){return Array.from(new Set(e))}function resolveToCallback(e){return function(...t){let n=t[t.length-1];if(typeof n==`function`){let r=n.bind(null,null),a=n.bind(null);e.apply(this,t.slice(0,-1)).then(r,a)}else return e.apply(this,t)}}function massageCreateIndexRequest(e){e=clone(e),e.index||(e.index={});for(let t of[`type`,`name`,`ddoc`])e.index[t]&&(e[t]=e.index[t],delete e.index[t]);return e.fields&&(e.index.fields=e.fields,delete e.fields),e.type||(e.type=`json`),e}function isNonNullObject(e){return typeof e==`object`&&!!e}function checkFieldValueType(e,t,n){let r=``,a=t,o=!0;if([`$in`,`$nin`,`$or`,`$and`,`$mod`,`$nor`,`$all`].indexOf(e)!==-1&&(Array.isArray(t)||(r=`Query operator `+e+` must be an array.`)),[`$not`,`$elemMatch`,`$allMatch`].indexOf(e)!==-1&&(!Array.isArray(t)&&isNonNullObject(t)||(r=`Query operator `+e+` must be an object.`)),e===`$mod`&&Array.isArray(t))if(t.length!==2)r=`Query operator $mod must be in the format [divisor, remainder], where divisor and remainder are both integers.`;else{let e=t[0],n=t[1];e===0&&(r=`Query operator $mod's divisor cannot be 0, cannot divide by zero.`,o=!1),(typeof e!=`number`||parseInt(e,10)!==e)&&(r=`Query operator $mod's divisor is not an integer.`,a=e),parseInt(n,10)!==n&&(r=`Query operator $mod's remainder is not an integer.`,a=n)}if(e===`$exists`&&typeof t!=`boolean`&&(r=`Query operator $exists must be a boolean.`),e===`$type`){let e=[`null`,`boolean`,`number`,`string`,`array`,`object`],n=`"`+e.slice(0,e.length-1).join(`", "`)+`", or "`+e[e.length-1]+`"`;typeof t==`string`?e.indexOf(t)==-1&&(r=`Query operator $type must be a string. Supported values: `+n+`.`):r=`Query operator $type must be a string. Supported values: `+n+`.`}if(e===`$size`&&parseInt(t,10)!==t&&(r=`Query operator $size must be a integer.`),e===`$regex`&&typeof t!=`string`&&(n?r=`Query operator $regex must be a string.`:t instanceof RegExp||(r=`Query operator $regex must be a string or an instance of a javascript regular expression.`)),r){if(o){let e=a===null?` `:Array.isArray(a)?` array`:` `+typeof a,t=isNonNullObject(a)?JSON.stringify(a,null,` `):a;r+=` Received`+e+`: `+t}throw Error(r)}}var requireValidation=[`$all`,`$allMatch`,`$and`,`$elemMatch`,`$exists`,`$in`,`$mod`,`$nin`,`$nor`,`$not`,`$or`,`$regex`,`$size`,`$type`],arrayTypeComparisonOperators=[`$in`,`$nin`,`$mod`,`$all`],equalityOperators=[`$eq`,`$gt`,`$gte`,`$lt`,`$lte`];function validateSelector(e,t){if(Array.isArray(e))for(let n of e)isNonNullObject(n)&&validateSelector(n,t);else for(let[n,r]of Object.entries(e))requireValidation.indexOf(n)!==-1&&checkFieldValueType(n,r,t),equalityOperators.indexOf(n)===-1&&arrayTypeComparisonOperators.indexOf(n)===-1&&isNonNullObject(r)&&validateSelector(r,t)}async function dbFetch(e,t,n){n.body&&(n.body=JSON.stringify(n.body),n.headers=new h({"Content-type":`application/json`}));let r=await e.fetch(t,n),a=await r.json();if(!r.ok)throw a.status=r.status,generateErrorFromResponse(createError(a));return a}async function createIndex(e,t){return await dbFetch(e,`_index`,{method:`POST`,body:massageCreateIndexRequest(t)})}async function find(e,t){return validateSelector(t.selector,!0),await dbFetch(e,`_find`,{method:`POST`,body:t})}async function explain(e,t){return await dbFetch(e,`_explain`,{method:`POST`,body:t})}async function getIndexes(e){return await dbFetch(e,`_index`,{method:`GET`})}async function deleteIndex(e,t){let n=t.ddoc,r=t.type||`json`,a=t.name;if(!n)throw Error(`you must provide an index's ddoc`);if(!a)throw Error(`you must provide an index's name`);return await dbFetch(e,`_index/`+[n,r,a].map(encodeURIComponent).join(`/`),{method:`DELETE`})}function getDeepValue(e,t){for(let n of t)if(e=e[n],e===void 0)return;return e}function createDeepMultiMapper(e,t,n){return function(r){if(n&&!matchesSelector(r,n))return;let a=[];for(let t of e){let e=getDeepValue(r,parseField(t));if(e===void 0)return;a.push(e)}t(a)}}function createDeepSingleMapper(e,t,n){let r=parseField(e);return function(e){if(n&&!matchesSelector(e,n))return;let a=getDeepValue(e,r);a!==void 0&&t(a)}}function createShallowSingleMapper(e,t,n){return function(r){n&&!matchesSelector(r,n)||t(r[e])}}function createShallowMultiMapper(e,t,n){return function(r){n&&!matchesSelector(r,n)||t(e.map(e=>r[e]))}}function checkShallow(e){return e.every(e=>e.indexOf(`.`)===-1)}function createMapper(e,t,n){let r=checkShallow(e),a=e.length===1;return r?a?createShallowSingleMapper(e[0],t,n):createShallowMultiMapper(e,t,n):a?createDeepSingleMapper(e[0],t,n):createDeepMultiMapper(e,t,n)}function mapper(e,t){let n=Object.keys(e.fields),r=e.partial_filter_selector;return createMapper(n,t,r)}function reducer(){throw Error(`reduce not supported`)}function ddocValidator(e,t){let n=e.views[t];if(!n.map||!n.map.fields)throw Error(`ddoc `+e._id+` with view `+t+` doesn't have map.fields defined. maybe it wasn't created by this plugin?`)}var abstractMapper=createAbstractMapReduce(`indexes`,mapper,reducer,ddocValidator);function abstractMapper$1(e){return e._customFindAbstractMapper?{query:function addQueryFallback(t,n){let r=abstractMapper.query.bind(this);return e._customFindAbstractMapper.query.call(this,t,n,r)},viewCleanup:function addViewCleanupFallback(){let t=abstractMapper.viewCleanup.bind(this);return e._customFindAbstractMapper.viewCleanup.call(this,t)}}:abstractMapper}function massageSort(e){if(!Array.isArray(e))throw Error(`invalid sort json - should be an array`);return e.map(function(e){if(typeof e==`string`){let t={};return t[e]=`asc`,t}else return e})}var ddocIdPrefix=/^_design\//;function massageUseIndex(e){let t=[];return typeof e==`string`?t.push(e):t=e,t.map(function(e){return e.replace(ddocIdPrefix,``)})}function massageIndexDef(e){return e.fields=e.fields.map(function(e){if(typeof e==`string`){let t={};return t[e]=`asc`,t}return e}),e.partial_filter_selector&&(e.partial_filter_selector=massageSelector(e.partial_filter_selector)),e}function getKeyFromDoc(e,t){return t.def.fields.map(t=>getFieldFromDoc(e,parseField(getKey(t))))}function filterInclusiveStart(e,t,n){let r=n.def.fields,a=0;for(let o of e){let e=getKeyFromDoc(o.doc,n);if(r.length===1)e=e[0];else for(;e.length>t.length;)e.pop();if(Math.abs(collate(e,t))>0)break;++a}return a>0?e.slice(a):e}function reverseOptions(e){let t=clone(e);return delete t.startkey,delete t.endkey,delete t.inclusive_start,delete t.inclusive_end,`endkey`in e&&(t.startkey=e.endkey),`startkey`in e&&(t.endkey=e.startkey),`inclusive_start`in e&&(t.inclusive_end=e.inclusive_start),`inclusive_end`in e&&(t.inclusive_start=e.inclusive_end),t}function validateIndex(e){let t=e.fields.filter(function(e){return getValue(e)===`asc`});if(t.length!==0&&t.length!==e.fields.length)throw Error(`unsupported mixed sorting`)}function validateSort(e,t){if(t.defaultUsed&&e.sort){let t=e.sort.filter(function(e){return Object.keys(e)[0]!==`_id`}).map(function(e){return Object.keys(e)[0]});if(t.length>0)throw Error(`Cannot sort on field(s) "`+t.join(`,`)+`" when using the default index`)}t.defaultUsed}function validateFindRequest(e){if(typeof e.selector!=`object`)throw Error(`you must provide a selector when you find()`)}function getUserFields(e,t){let n=Object.keys(e),r=t?t.map(getKey):[],a;return a=n.length>=r.length?n:r,r.length===0?{fields:a}:(a=a.sort(function(e,t){let n=r.indexOf(e);n===-1&&(n=Number.MAX_VALUE);let a=r.indexOf(t);return a===-1&&(a=Number.MAX_VALUE),n<a?-1:n>a?1:0}),{fields:a,sortOrder:t.map(getKey)})}async function createIndex$1(e,t){t=massageCreateIndexRequest(t);let n=clone(t.index);t.index=massageIndexDef(t.index),validateIndex(t.index);let r;function getMd5(){return r||(r=stringMd5(JSON.stringify(t)))}let a=t.name||`idx-`+getMd5(),o=t.ddoc||`idx-`+getMd5(),s=`_design/`+o,c=!1,l=!1;function updateDdoc(e){return e._rev&&e.language!==`query`&&(c=!0),e.language=`query`,e.views=e.views||{},l=!!e.views[a],l?!1:(e.views[a]={map:{fields:mergeObjects(t.index.fields),partial_filter_selector:t.index.partial_filter_selector},reduce:`_count`,options:{def:n}},e)}if(e.constructor.emit(`debug`,[`find`,`creating index`,s]),await upsert(e,s,updateDdoc),c)throw Error(`invalid language for ddoc with id "`+s+`" (should be "query")`);let u=o+`/`+a;return await abstractMapper$1(e).query.call(e,u,{limit:0,reduce:!1}),{id:s,name:a,result:l?`exists`:`created`}}async function getIndexes$1(e){let t=await e.allDocs({startkey:`_design/`,endkey:`_design/`,include_docs:!0}),n={indexes:[{ddoc:null,name:`_all_docs`,type:`special`,def:{fields:[{_id:`asc`}]}}]};return n.indexes=flatten(n.indexes,t.rows.filter(function(e){return e.doc.language===`query`}).map(function(e){return(e.doc.views===void 0?[]:Object.keys(e.doc.views)).map(function(t){let n=e.doc.views[t];return{ddoc:e.id,name:t,type:`json`,def:massageIndexDef(n.options.def)}})})),n.indexes.sort(function(e,t){return compare(e.name,t.name)}),n.total_rows=n.indexes.length,n}var COLLATE_LO=null,COLLATE_HI={"":{}},SHORT_CIRCUIT_QUERY={queryOpts:{limit:0,startkey:COLLATE_HI,endkey:COLLATE_LO},inMemoryFields:[]};function checkFieldInIndex(e,t){return e.def.fields.some(e=>getKey(e)===t)}function userOperatorLosesPrecision(e,t){let n=e[t];return getKey(n)!==`$eq`}function sortFieldsByIndex(e,t){let n=t.def.fields.map(getKey);return e.slice().sort(function(e,t){let r=n.indexOf(e),a=n.indexOf(t);return r===-1&&(r=Number.MAX_VALUE),a===-1&&(a=Number.MAX_VALUE),compare(r,a)})}function getBasicInMemoryFields(e,t,n){n=sortFieldsByIndex(n,e);let r=!1;for(let a=0,o=n.length;a<o;a++){let s=n[a];if(r||!checkFieldInIndex(e,s))return n.slice(a);a<o-1&&userOperatorLosesPrecision(t,s)&&(r=!0)}return[]}function getInMemoryFieldsFromNe(e){let t=[];for(let[n,r]of Object.entries(e))for(let e of Object.keys(r))e===`$ne`&&t.push(n);return t}function getInMemoryFields(e,t,n,r){return sortFieldsByIndex(uniq(flatten(e,getBasicInMemoryFields(t,n,r),getInMemoryFieldsFromNe(n))),t)}function checkIndexFieldsMatch(e,t,n){if(t){let r=oneArrayIsStrictSubArrayOfOther(t,e),a=oneArrayIsSubArrayOfOther(n,e);return r&&a}return oneSetIsSubArrayOfOther(n,e)}var logicalMatchers=[`$eq`,`$gt`,`$gte`,`$lt`,`$lte`];function isNonLogicalMatcher(e){return logicalMatchers.indexOf(e)===-1}function checkFieldsLogicallySound(e,t){let n=t[e[0]];return n===void 0?!0:!(Object.keys(n).length===1&&getKey(n)===`$ne`)}function checkIndexMatches(e,t,n,r){let a=e.def.fields.map(getKey);return checkIndexFieldsMatch(a,t,n)?checkFieldsLogicallySound(a,r):!1}function findMatchingIndexes(e,t,n,r){return r.filter(function(r){return checkIndexMatches(r,n,t,e)})}function findBestMatchingIndex(e,t,n,r,a){let o=findMatchingIndexes(e,t,n,r);if(o.length===0){if(a)throw{error:`no_usable_index`,message:`There is no index available for this selector.`};let e=r[0];return e.defaultUsed=!0,e}if(o.length===1&&!a)return o[0];let s=arrayToObject(t);function scoreIndex(e){let t=e.def.fields.map(getKey),n=0;for(let e of t)s[e]&&n++;return n}if(a){let e=`_design/`+a[0],t=a.length===2?a[1]:!1,n=o.find(function(n){return!!(t&&n.ddoc===e&&t===n.name||n.ddoc===e)});if(!n)throw{error:`unknown_error`,message:`Could not find that index or could not use that index for the query`};return n}return max(o,scoreIndex)}function getSingleFieldQueryOptsFor(e,t){switch(e){case`$eq`:return{key:t};case`$lte`:return{endkey:t};case`$gte`:return{startkey:t};case`$lt`:return{endkey:t,inclusive_end:!1};case`$gt`:return{startkey:t,inclusive_start:!1}}return{startkey:COLLATE_LO}}function getSingleFieldCoreQueryPlan(e,t){let n=getKey(t.def.fields[0]),r=e[n]||{},a=[],o=Object.keys(r),s;for(let e of o){isNonLogicalMatcher(e)&&a.push(n);let t=r[e],o=getSingleFieldQueryOptsFor(e,t);s=s?mergeObjects([s,o]):o}return{queryOpts:s,inMemoryFields:a}}function getMultiFieldCoreQueryPlan(e,t){switch(e){case`$eq`:return{startkey:t,endkey:t};case`$lte`:return{endkey:t};case`$gte`:return{startkey:t};case`$lt`:return{endkey:t,inclusive_end:!1};case`$gt`:return{startkey:t,inclusive_start:!1}}}function getMultiFieldQueryOpts(e,t){let n=t.def.fields.map(getKey),r=[],a=[],o=[],s,c;function finish(e){s!==!1&&a.push(COLLATE_LO),c!==!1&&o.push(COLLATE_HI),r=n.slice(e)}for(let t=0,r=n.length;t<r;t++){let r=e[n[t]];if(!r||!Object.keys(r).length){finish(t);break}else if(Object.keys(r).some(isNonLogicalMatcher)){finish(t);break}else if(t>0){let a=`$gt`in r||`$gte`in r||`$lt`in r||`$lte`in r,o=Object.keys(e[n[t-1]]),s=arrayEquals(o,[`$eq`]),c=arrayEquals(o,Object.keys(r));if(a&&!s&&!c){finish(t);break}}let l=Object.keys(r),u=null;for(let e of l){let t=r[e],n=getMultiFieldCoreQueryPlan(e,t);u=u?mergeObjects([u,n]):n}a.push(`startkey`in u?u.startkey:COLLATE_LO),o.push(`endkey`in u?u.endkey:COLLATE_HI),`inclusive_start`in u&&(s=u.inclusive_start),`inclusive_end`in u&&(c=u.inclusive_end)}let l={startkey:a,endkey:o};return s!==void 0&&(l.inclusive_start=s),c!==void 0&&(l.inclusive_end=c),{queryOpts:l,inMemoryFields:r}}function shouldShortCircuit(e){return Object.keys(e).map(function(t){return e[t]}).some(function(e){return typeof e==`object`&&Object.keys(e).length===0})}function getDefaultQueryPlan(e){return{queryOpts:{startkey:null},inMemoryFields:[Object.keys(e)]}}function getCoreQueryPlan(e,t){return t.defaultUsed?getDefaultQueryPlan(e,t):t.def.fields.length===1?getSingleFieldCoreQueryPlan(e,t):getMultiFieldQueryOpts(e,t)}function planQuery(e,t){let n=e.selector,r=e.sort;if(shouldShortCircuit(n))return Object.assign({},SHORT_CIRCUIT_QUERY,{index:t[0]});let a=getUserFields(n,r),o=a.fields,s=a.sortOrder,c=findBestMatchingIndex(n,o,s,t,e.use_index),l=getCoreQueryPlan(n,c),u=l.queryOpts,d=l.inMemoryFields;return{queryOpts:u,index:c,inMemoryFields:getInMemoryFields(d,c,n,o)}}function indexToSignature(e){return e.ddoc.substring(8)+`/`+e.name}async function doAllDocs(e,t){let n=clone(t);n.descending?(`endkey`in n&&typeof n.endkey!=`string`&&(n.endkey=``),`startkey`in n&&typeof n.startkey!=`string`&&(n.limit=0)):(`startkey`in n&&typeof n.startkey!=`string`&&(n.startkey=``),`endkey`in n&&typeof n.endkey!=`string`&&(n.limit=0)),`key`in n&&typeof n.key!=`string`&&(n.limit=0),n.limit>0&&n.indexes_count&&(n.original_limit=n.limit,n.limit+=n.indexes_count);let r=await e.allDocs(n);return r.rows=r.rows.filter(function(e){return!/^_design\//.test(e.id)}),n.original_limit&&(n.limit=n.original_limit),r.rows=r.rows.slice(0,n.limit),r}async function queryAllOrIndex(e,t,n){return n.name===`_all_docs`?doAllDocs(e,t):abstractMapper$1(e).query.call(e,indexToSignature(n),t)}async function find$1(e,t,n){t.selector&&(validateSelector(t.selector,!1),t.selector=massageSelector(t.selector)),t.sort&&(t.sort=massageSort(t.sort)),t.use_index&&(t.use_index=massageUseIndex(t.use_index)),`limit`in t||(t.limit=25),validateFindRequest(t);let r=await getIndexes$1(e);e.constructor.emit(`debug`,[`find`,`planning query`,t]);let a=planQuery(t,r.indexes);e.constructor.emit(`debug`,[`find`,`query plan`,a]);let o=a.index;validateSort(t,o);let s=Object.assign({include_docs:!0,reduce:!1,indexes_count:r.total_rows},a.queryOpts);if(`startkey`in s&&`endkey`in s&&collate(s.startkey,s.endkey)>0)return{docs:[]};if(t.sort&&typeof t.sort[0]!=`string`&&getValue(t.sort[0])===`desc`&&(s.descending=!0,s=reverseOptions(s)),a.inMemoryFields.length||(s.limit=t.limit,`skip`in t&&(s.skip=t.skip)),n)return Promise.resolve(a,s);let c=await queryAllOrIndex(e,s,o);s.inclusive_start===!1&&(c.rows=filterInclusiveStart(c.rows,s.startkey,o)),a.inMemoryFields.length&&(c.rows=filterInMemoryFields(c.rows,t,a.inMemoryFields));let l={docs:c.rows.map(function(e){let n=e.doc;return t.fields?pick(n,t.fields):n})};return o.defaultUsed&&(l.warning=`No matching index found, create an index to optimize query time.`),l}async function explain$1(e,t){let n=await find$1(e,t,!0);return{dbname:e.name,index:n.index,selector:t.selector,range:{start_key:n.queryOpts.startkey,end_key:n.queryOpts.endkey},opts:{use_index:t.use_index||[],bookmark:`nil`,limit:t.limit,skip:t.skip,sort:t.sort||{},fields:t.fields,conflicts:!1,r:[49]},limit:t.limit,skip:t.skip||0,fields:t.fields}}async function deleteIndex$1(e,t){if(!t.ddoc)throw Error(`you must supply an index.ddoc when deleting`);if(!t.name)throw Error(`you must supply an index.name when deleting`);let n=t.ddoc,r=t.name;function deltaFun(e){return Object.keys(e.views).length===1&&e.views[r]?{_id:n,_deleted:!0}:(delete e.views[r],e)}return await upsert(e,n,deltaFun),await abstractMapper$1(e).viewCleanup.apply(e),{ok:!0}}var plugin$1={};plugin$1.createIndex=resolveToCallback(async function(e){if(typeof e!=`object`)throw Error(`you must provide an index to create`);return(isRemote(this)?createIndex:createIndex$1)(this,e)}),plugin$1.find=resolveToCallback(async function(e){if(typeof e!=`object`)throw Error(`you must provide search parameters to find()`);return(isRemote(this)?find:find$1)(this,e)}),plugin$1.explain=resolveToCallback(async function(e){if(typeof e!=`object`)throw Error(`you must provide search parameters to explain()`);return(isRemote(this)?explain:explain$1)(this,e)}),plugin$1.getIndexes=resolveToCallback(async function(){return(isRemote(this)?getIndexes:getIndexes$1)(this)}),plugin$1.deleteIndex=resolveToCallback(async function(e){if(typeof e!=`object`)throw Error(`you must provide an index to delete`);return(isRemote(this)?deleteIndex:deleteIndex$1)(this,e)});function getConfigUrl(e){return(e?`/_node/`+e:``)+`/_config`}function wrapError(e){throw e.name===`unknown_error`&&(e.message=(e.message||``)+` Unknown error! Did you remember to enable CORS?`),e}function fetchJSON(e,t,n){return n=n||{},n.body&&(n.body=JSON.stringify(n.body)),n.headers=n.headers||new h,n.headers.set(`Content-Type`,`application/json`),n.headers.set(`Accept`,`application/json`),e(t,n).then(function(e){return e.ok?e.json():e.json().then(function(e){throw e})}).catch(wrapError)}function toCallback(e){return function(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];if(typeof t[-1]==`function`){var r=t[-1];return e.apply(this,t.slice(0,-2)).then(function(e){return r(null,e)},function(e){return r(e)})}else return e.apply(this,t)}}var AuthError=function(e){function AuthError(t){e.call(this,t),this.name=`authentication_error`,this.status=400,this.error=!0,Object.setPrototypeOf(this,AuthError.prototype)}return e&&(AuthError.__proto__=e),AuthError.prototype=Object.create(e&&e.prototype),AuthError.prototype.constructor=AuthError,AuthError}(Error),getMembership=toCallback(function(e){var t=this;e===void 0&&(e={});var n=`/_membership`,r=Object.assign({method:`GET`},e.ajax||{});return fetchJSON(t.fetch,n,r)}),getNodeName=function(e,t){return e.getMembership(t).then(function(e){return e.all_nodes[0]},function(e){if(e.error!==`illegal_database_name`)throw e})},signUpAdmin=toCallback(function(e,t,n){var r=this;return n===void 0&&(n={}),[`http`,`https`].indexOf(r.type())===-1?Promise.reject(new AuthError(`This plugin only works for the http/https adapter. So you should use new PouchDB("http://mysite.com:5984/mydb") instead.`)):e?t?getNodeName(r,n).then(function(a){var o=getConfigUrl(a),s=(n.configUrl||o)+`/admins/`+encodeURIComponent(e),c=Object.assign({method:`PUT`,body:t},n.ajax||{});return fetchJSON(r.fetch,s,c)}):Promise.reject(new AuthError(`You must provide a password`)):Promise.reject(new AuthError(`You must provide a username`))}),deleteAdmin=toCallback(function(e,t){var n=this;return t===void 0&&(t={}),[`http`,`https`].indexOf(n.type())===-1?Promise.reject(new AuthError(`This plugin only works for the http/https adapter. So you should use new PouchDB("http://mysite.com:5984/mydb") instead.`)):e?getNodeName(n,t).then(function(r){var a=getConfigUrl(r),o=(t.configUrl||a)+`/admins/`+encodeURIComponent(e),s=Object.assign({method:`DELETE`,processData:!1},t.ajax||{});return fetchJSON(n.fetch,o,s)}):Promise.reject(new AuthError(`You must provide a username`))}),sessionPath=`/_session`,logIn=toCallback(function(e,t,n){var r=this;if(n===void 0&&(n={}),[`http`,`https`].indexOf(r.type())===-1)return Promise.reject(new AuthError(`this plugin only works for the http/https adapter`));if(!e)return Promise.reject(new AuthError(`you must provide a username`));if(!t)return Promise.reject(new AuthError(`you must provide a password`));var a=sessionPath,o=Object.assign({method:`POST`,body:{name:e,password:t}},n.ajax||{});return fetchJSON(r.fetch,a,o)}),logOut=toCallback(function(e){var t=this;e===void 0&&(e={});var n=sessionPath,r=Object.assign({method:`DELETE`},e.ajax||{});return fetchJSON(t.fetch,n,r)}),getSession=toCallback(function(e){var t=this;e===void 0&&(e={});var n=sessionPath,r=Object.assign({method:`GET`},e.ajax||{});return fetchJSON(t.fetch,n,r)}),usersPath=`/_users`;function updateUser(e,t,n){var r=[`_id`,`_rev`,`name`,`type`,`roles`,`password`,`password_scheme`,`iterations`,`derived_key`,`salt`];if(n.metadata){for(var a in n.metadata)if(n.metadata.hasOwnProperty(a)&&r.indexOf(a)!==-1)return Promise.reject(new AuthError(`cannot use reserved word in metadata: "`+a+`"`));t=Object.assign(t,n.metadata)}n.roles&&(t=Object.assign(t,{roles:n.roles}));var o=usersPath+`/`+encodeURIComponent(t._id),s=Object.assign({method:`PUT`,body:t},n.ajax||{});return fetchJSON(e.fetch,o,s)}var signUp=toCallback(function(e,t,n){var r=this;return n===void 0&&(n={}),[`http`,`https`].indexOf(r.type())===-1?Promise.reject(new AuthError(`This plugin only works for the http/https adapter. So you should use new PouchDB("http://mysite.com:5984/mydb") instead.`)):e?t?updateUser(r,{name:e,password:t,roles:[],type:`user`,_id:`org.couchdb.user:`+e},n):Promise.reject(new AuthError(`You must provide a password`)):Promise.reject(new AuthError(`You must provide a username`))}),getUser=toCallback(function(e,t){var n=this;if(t===void 0&&(t={}),!e)return Promise.reject(new AuthError(`you must provide a username`));var r=usersPath+`/`+encodeURIComponent(`org.couchdb.user:`+e),a=Object.assign({method:`GET`},t.ajax||{});return fetchJSON(n.fetch,r,a).then(function(e){return console.log(e),e})}),putUser=toCallback(function(e,t){var n=this;return t===void 0&&(t={}),[`http`,`https`].indexOf(n.type())===-1?Promise.reject(new AuthError(`This plugin only works for the http/https adapter. So you should use new PouchDB("http://mysite.com:5984/mydb") instead.`)):e?n.getUser(e,t).then(function(e){return updateUser(n,e,t)}):Promise.reject(new AuthError(`You must provide a username`))}),deleteUser=toCallback(function(e,t){var n=this;return t===void 0&&(t={}),[`http`,`https`].indexOf(n.type())===-1?Promise.reject(new AuthError(`This plugin only works for the http/https adapter. So you should use new PouchDB("http://mysite.com:5984/mydb") instead.`)):e?n.getUser(e,t).then(function(e){var r=usersPath+`/`+encodeURIComponent(e._id)+`?rev=`+e._rev,a=Object.assign({method:`DELETE`},t.ajax||{});return fetchJSON(n.fetch,r,a)}):Promise.reject(new AuthError(`You must provide a username`))}),changePassword=toCallback(function(e,t,n){var r=this;return n===void 0&&(n={}),[`http`,`https`].indexOf(r.type())===-1?Promise.reject(new AuthError(`This plugin only works for the http/https adapter. So you should use new PouchDB("http://mysite.com:5984/mydb") instead.`)):e?t?r.getUser(e,n).then(function(e){e.password=t;var a=usersPath+`/`+encodeURIComponent(e._id),o=Object.assign({method:`PUT`,body:e},n.ajax||{});return fetchJSON(r.fetch,a,o)}):Promise.reject(new AuthError(`You must provide a password`)):Promise.reject(new AuthError(`You must provide a username`))}),changeUsername=toCallback(function(e,t,n){var r=this,a=`org.couchdb.user:`,updateUser=function(e,t){var n=usersPath+`/`+encodeURIComponent(e._id),a=Object.assign({method:`PUT`,body:e},t.ajax);return fetchJSON(r.fetch,n,a)};return n===void 0&&(n={}),n.ajax=n.ajax||{},[`http`,`https`].indexOf(r.type())===-1?Promise.reject(new AuthError(`This plugin only works for the http/https adapter. So you should use new PouchDB("http://mysite.com:5984/mydb") instead.`)):t?e?r.getUser(t,n).then(function(){var e=new AuthError(`user already exists`);throw e.taken=!0,e},function(){return r.getUser(e,n)}).then(function(e){var r=clone(e);return delete r._rev,r._id=a+t,r.name=t,r.roles=n.roles||e.roles||{},updateUser(r,n).then(function(){return e._deleted=!0,updateUser(e,n)})}):Promise.reject(new AuthError(`You must provide a username to rename`)):Promise.reject(new AuthError(`You must provide a new username`))}),plugin={};plugin.login=logIn,plugin.logIn=logIn,plugin.logout=logOut,plugin.logOut=logOut,plugin.getSession=getSession,plugin.getMembership=getMembership,plugin.signUpAdmin=signUpAdmin,plugin.deleteAdmin=deleteAdmin,plugin.signup=signUp,plugin.signUp=signUp,plugin.getUser=getUser,plugin.putUser=putUser,plugin.deleteUser=deleteUser,plugin.changePassword=changePassword,plugin.changeUsername=changeUsername,typeof window<`u`&&window.PouchDB&&window.PouchDB.plugin(plugin);var byteToHex=[];for(let e=0;e<256;++e)byteToHex.push((e+256).toString(16).slice(1));function unsafeStringify(e,t=0){return(byteToHex[e[t+0]]+byteToHex[e[t+1]]+byteToHex[e[t+2]]+byteToHex[e[t+3]]+`-`+byteToHex[e[t+4]]+byteToHex[e[t+5]]+`-`+byteToHex[e[t+6]]+byteToHex[e[t+7]]+`-`+byteToHex[e[t+8]]+byteToHex[e[t+9]]+`-`+byteToHex[e[t+10]]+byteToHex[e[t+11]]+byteToHex[e[t+12]]+byteToHex[e[t+13]]+byteToHex[e[t+14]]+byteToHex[e[t+15]]).toLowerCase()}var getRandomValues,rnds8=new Uint8Array(16);function rng(){if(!getRandomValues){if(typeof crypto>`u`||!crypto.getRandomValues)throw Error(`crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported`);getRandomValues=crypto.getRandomValues.bind(crypto)}return getRandomValues(rnds8)}var randomUUID=typeof crypto<`u`&&crypto.randomUUID&&crypto.randomUUID.bind(crypto),native_default={randomUUID};function v4(e,t,n){if(native_default.randomUUID&&!t&&!e)return native_default.randomUUID();e=e||{};let r=e.random??e.rng?.()??rng();if(r.length<16)throw Error(`Random bytes length must be >= 16`);if(r[6]=r[6]&15|64,r[8]=r[8]&63|128,t){if(n=n||0,n<0||n+16>t.length)throw RangeError(`UUID byte range ${n}:${n+15} is out of buffer bounds`);for(let e=0;e<16;++e)t[n+e]=r[e];return t}return unsafeStringify(r)}var require_browser_ponyfill=__commonJSMin(((e,t)=>{var n=typeof globalThis<`u`&&globalThis||typeof self<`u`&&self||typeof window<`u`&&window,r=(function(){function F(){this.fetch=!1,this.DOMException=n.DOMException}return F.prototype=n,new F})();(function(e){(function(t){var n=e!==void 0&&e||typeof self<`u`&&self||typeof window<`u`&&window||{},r={searchParams:`URLSearchParams`in n,iterable:`Symbol`in n&&`iterator`in Symbol,blob:`FileReader`in n&&`Blob`in n&&(function(){try{return new Blob,!0}catch{return!1}})(),formData:`FormData`in n,arrayBuffer:`ArrayBuffer`in n};function isDataView(e){return e&&DataView.prototype.isPrototypeOf(e)}if(r.arrayBuffer)var a=[`[object Int8Array]`,`[object Uint8Array]`,`[object Uint8ClampedArray]`,`[object Int16Array]`,`[object Uint16Array]`,`[object Int32Array]`,`[object Uint32Array]`,`[object Float32Array]`,`[object Float64Array]`],o=ArrayBuffer.isView||function(e){return e&&a.indexOf(Object.prototype.toString.call(e))>-1};function normalizeName(e){if(typeof e!=`string`&&(e=String(e)),/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(e)||e===``)throw TypeError(`Invalid character in header field name: "`+e+`"`);return e.toLowerCase()}function normalizeValue(e){return typeof e!=`string`&&(e=String(e)),e}function iteratorFor(e){var t={next:function(){var t=e.shift();return{done:t===void 0,value:t}}};return r.iterable&&(t[Symbol.iterator]=function(){return t}),t}function Headers(e){this.map={},e instanceof Headers?e.forEach(function(e,t){this.append(t,e)},this):Array.isArray(e)?e.forEach(function(e){if(e.length!=2)throw TypeError(`Headers constructor: expected name/value pair to be length 2, found`+e.length);this.append(e[0],e[1])},this):e&&Object.getOwnPropertyNames(e).forEach(function(t){this.append(t,e[t])},this)}Headers.prototype.append=function(e,t){e=normalizeName(e),t=normalizeValue(t);var n=this.map[e];this.map[e]=n?n+`, `+t:t},Headers.prototype.delete=function(e){delete this.map[normalizeName(e)]},Headers.prototype.get=function(e){return e=normalizeName(e),this.has(e)?this.map[e]:null},Headers.prototype.has=function(e){return this.map.hasOwnProperty(normalizeName(e))},Headers.prototype.set=function(e,t){this.map[normalizeName(e)]=normalizeValue(t)},Headers.prototype.forEach=function(e,t){for(var n in this.map)this.map.hasOwnProperty(n)&&e.call(t,this.map[n],n,this)},Headers.prototype.keys=function(){var e=[];return this.forEach(function(t,n){e.push(n)}),iteratorFor(e)},Headers.prototype.values=function(){var e=[];return this.forEach(function(t){e.push(t)}),iteratorFor(e)},Headers.prototype.entries=function(){var e=[];return this.forEach(function(t,n){e.push([n,t])}),iteratorFor(e)},r.iterable&&(Headers.prototype[Symbol.iterator]=Headers.prototype.entries);function consumed(e){if(!e._noBody){if(e.bodyUsed)return Promise.reject(TypeError(`Already read`));e.bodyUsed=!0}}function fileReaderReady(e){return new Promise(function(t,n){e.onload=function(){t(e.result)},e.onerror=function(){n(e.error)}})}function readBlobAsArrayBuffer(e){var t=new FileReader,n=fileReaderReady(t);return t.readAsArrayBuffer(e),n}function readBlobAsText(e){var t=new FileReader,n=fileReaderReady(t),r=/charset=([A-Za-z0-9_-]+)/.exec(e.type),a=r?r[1]:`utf-8`;return t.readAsText(e,a),n}function readArrayBufferAsText(e){for(var t=new Uint8Array(e),n=Array(t.length),r=0;r<t.length;r++)n[r]=String.fromCharCode(t[r]);return n.join(``)}function bufferClone(e){if(e.slice)return e.slice(0);var t=new Uint8Array(e.byteLength);return t.set(new Uint8Array(e)),t.buffer}function Body(){return this.bodyUsed=!1,this._initBody=function(e){this.bodyUsed=this.bodyUsed,this._bodyInit=e,e?typeof e==`string`?this._bodyText=e:r.blob&&Blob.prototype.isPrototypeOf(e)?this._bodyBlob=e:r.formData&&FormData.prototype.isPrototypeOf(e)?this._bodyFormData=e:r.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)?this._bodyText=e.toString():r.arrayBuffer&&r.blob&&isDataView(e)?(this._bodyArrayBuffer=bufferClone(e.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer])):r.arrayBuffer&&(ArrayBuffer.prototype.isPrototypeOf(e)||o(e))?this._bodyArrayBuffer=bufferClone(e):this._bodyText=e=Object.prototype.toString.call(e):(this._noBody=!0,this._bodyText=``),this.headers.get(`content-type`)||(typeof e==`string`?this.headers.set(`content-type`,`text/plain;charset=UTF-8`):this._bodyBlob&&this._bodyBlob.type?this.headers.set(`content-type`,this._bodyBlob.type):r.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)&&this.headers.set(`content-type`,`application/x-www-form-urlencoded;charset=UTF-8`))},r.blob&&(this.blob=function(){var e=consumed(this);if(e)return e;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw Error(`could not read FormData body as blob`);return Promise.resolve(new Blob([this._bodyText]))}),this.arrayBuffer=function(){if(this._bodyArrayBuffer)return consumed(this)||(ArrayBuffer.isView(this._bodyArrayBuffer)?Promise.resolve(this._bodyArrayBuffer.buffer.slice(this._bodyArrayBuffer.byteOffset,this._bodyArrayBuffer.byteOffset+this._bodyArrayBuffer.byteLength)):Promise.resolve(this._bodyArrayBuffer));if(r.blob)return this.blob().then(readBlobAsArrayBuffer);throw Error(`could not read as ArrayBuffer`)},this.text=function(){var e=consumed(this);if(e)return e;if(this._bodyBlob)return readBlobAsText(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer));if(this._bodyFormData)throw Error(`could not read FormData body as text`);return Promise.resolve(this._bodyText)},r.formData&&(this.formData=function(){return this.text().then(decode)}),this.json=function(){return this.text().then(JSON.parse)},this}var s=[`CONNECT`,`DELETE`,`GET`,`HEAD`,`OPTIONS`,`PATCH`,`POST`,`PUT`,`TRACE`];function normalizeMethod(e){var t=e.toUpperCase();return s.indexOf(t)>-1?t:e}function Request(e,t){if(!(this instanceof Request))throw TypeError(`Please use the "new" operator, this DOM object constructor cannot be called as a function.`);t=t||{};var r=t.body;if(e instanceof Request){if(e.bodyUsed)throw TypeError(`Already read`);this.url=e.url,this.credentials=e.credentials,t.headers||(this.headers=new Headers(e.headers)),this.method=e.method,this.mode=e.mode,this.signal=e.signal,!r&&e._bodyInit!=null&&(r=e._bodyInit,e.bodyUsed=!0)}else this.url=String(e);if(this.credentials=t.credentials||this.credentials||`same-origin`,(t.headers||!this.headers)&&(this.headers=new Headers(t.headers)),this.method=normalizeMethod(t.method||this.method||`GET`),this.mode=t.mode||this.mode||null,this.signal=t.signal||this.signal||function(){if(`AbortController`in n)return new AbortController().signal}(),this.referrer=null,(this.method===`GET`||this.method===`HEAD`)&&r)throw TypeError(`Body not allowed for GET or HEAD requests`);if(this._initBody(r),(this.method===`GET`||this.method===`HEAD`)&&(t.cache===`no-store`||t.cache===`no-cache`)){var a=/([?&])_=[^&]*/;a.test(this.url)?this.url=this.url.replace(a,`$1_=`+new Date().getTime()):this.url+=(/\?/.test(this.url)?`&`:`?`)+`_=`+new Date().getTime()}}Request.prototype.clone=function(){return new Request(this,{body:this._bodyInit})};function decode(e){var t=new FormData;return e.trim().split(`&`).forEach(function(e){if(e){var n=e.split(`=`),r=n.shift().replace(/\+/g,` `),a=n.join(`=`).replace(/\+/g,` `);t.append(decodeURIComponent(r),decodeURIComponent(a))}}),t}function parseHeaders(e){var t=new Headers;return e.replace(/\r?\n[\t ]+/g,` `).split(`\r`).map(function(e){return e.indexOf(`
|
|
11
|
-
`)===0?e.substr(1,e.length):e}).forEach(function(e){var n=e.split(`:`),r=n.shift().trim();if(r){var a=n.join(`:`).trim();try{t.append(r,a)}catch(e){console.warn(`Response `+e.message)}}}),t}Body.call(Request.prototype);function Response(e,t){if(!(this instanceof Response))throw TypeError(`Please use the "new" operator, this DOM object constructor cannot be called as a function.`);if(t||(t={}),this.type=`default`,this.status=t.status===void 0?200:t.status,this.status<200||this.status>599)throw RangeError(`Failed to construct 'Response': The status provided (0) is outside the range [200, 599].`);this.ok=this.status>=200&&this.status<300,this.statusText=t.statusText===void 0?``:``+t.statusText,this.headers=new Headers(t.headers),this.url=t.url||``,this._initBody(e)}Body.call(Response.prototype),Response.prototype.clone=function(){return new Response(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new Headers(this.headers),url:this.url})},Response.error=function(){var e=new Response(null,{status:200,statusText:``});return e.ok=!1,e.status=0,e.type=`error`,e};var c=[301,302,303,307,308];Response.redirect=function(e,t){if(c.indexOf(t)===-1)throw RangeError(`Invalid status code`);return new Response(null,{status:t,headers:{location:e}})},t.DOMException=n.DOMException;try{new t.DOMException}catch{t.DOMException=function(e,t){this.message=e,this.name=t,this.stack=Error(e).stack},t.DOMException.prototype=Object.create(Error.prototype),t.DOMException.prototype.constructor=t.DOMException}function fetch(e,a){return new Promise(function(o,s){var c=new Request(e,a);if(c.signal&&c.signal.aborted)return s(new t.DOMException(`Aborted`,`AbortError`));var l=new XMLHttpRequest;function abortXhr(){l.abort()}l.onload=function(){var e={statusText:l.statusText,headers:parseHeaders(l.getAllResponseHeaders()||``)};c.url.indexOf(`file://`)===0&&(l.status<200||l.status>599)?e.status=200:e.status=l.status,e.url=`responseURL`in l?l.responseURL:e.headers.get(`X-Request-URL`);var t=`response`in l?l.response:l.responseText;setTimeout(function(){o(new Response(t,e))},0)},l.onerror=function(){setTimeout(function(){s(TypeError(`Network request failed`))},0)},l.ontimeout=function(){setTimeout(function(){s(TypeError(`Network request timed out`))},0)},l.onabort=function(){setTimeout(function(){s(new t.DOMException(`Aborted`,`AbortError`))},0)};function fixUrl(e){try{return e===``&&n.location.href?n.location.href:e}catch{return e}}if(l.open(c.method,fixUrl(c.url),!0),c.credentials===`include`?l.withCredentials=!0:c.credentials===`omit`&&(l.withCredentials=!1),`responseType`in l&&(r.blob?l.responseType=`blob`:r.arrayBuffer&&(l.responseType=`arraybuffer`)),a&&typeof a.headers==`object`&&!(a.headers instanceof Headers||n.Headers&&a.headers instanceof n.Headers)){var u=[];Object.getOwnPropertyNames(a.headers).forEach(function(e){u.push(normalizeName(e)),l.setRequestHeader(e,normalizeValue(a.headers[e]))}),c.headers.forEach(function(e,t){u.indexOf(t)===-1&&l.setRequestHeader(t,e)})}else c.headers.forEach(function(e,t){l.setRequestHeader(t,e)});c.signal&&(c.signal.addEventListener(`abort`,abortXhr),l.onreadystatechange=function(){l.readyState===4&&c.signal.removeEventListener(`abort`,abortXhr)}),l.send(c._bodyInit===void 0?null:c._bodyInit)})}return fetch.polyfill=!0,n.fetch||(n.fetch=fetch,n.Headers=Headers,n.Request=Request,n.Response=Response),t.Headers=Headers,t.Request=Request,t.Response=Response,t.fetch=fetch,t})({})})(r),r.fetch.ponyfill=!0,delete r.fetch.polyfill;var a=n.fetch?n:r;e=a.fetch,e.default=a.fetch,e.fetch=a.fetch,e.Headers=a.Headers,e.Request=a.Request,e.Response=a.Response,t.exports=e})),require_browser=__commonJSMin(((e,t)=>{var n=t.exports={},r,a;function defaultSetTimout(){throw Error(`setTimeout has not been defined`)}function defaultClearTimeout(){throw Error(`clearTimeout has not been defined`)}(function(){try{r=typeof setTimeout==`function`?setTimeout:defaultSetTimout}catch{r=defaultSetTimout}try{a=typeof clearTimeout==`function`?clearTimeout:defaultClearTimeout}catch{a=defaultClearTimeout}})();function runTimeout(e){if(r===setTimeout)return setTimeout(e,0);if((r===defaultSetTimout||!r)&&setTimeout)return r=setTimeout,setTimeout(e,0);try{return r(e,0)}catch{try{return r.call(null,e,0)}catch{return r.call(this,e,0)}}}function runClearTimeout(e){if(a===clearTimeout)return clearTimeout(e);if((a===defaultClearTimeout||!a)&&clearTimeout)return a=clearTimeout,clearTimeout(e);try{return a(e)}catch{try{return a.call(null,e)}catch{return a.call(this,e)}}}var o=[],s=!1,c,l=-1;function cleanUpNextTick(){!s||!c||(s=!1,c.length?o=c.concat(o):l=-1,o.length&&drainQueue())}function drainQueue(){if(!s){var e=runTimeout(cleanUpNextTick);s=!0;for(var t=o.length;t;){for(c=o,o=[];++l<t;)c&&c[l].run();l=-1,t=o.length}c=null,s=!1,runClearTimeout(e)}}n.nextTick=function(e){var t=Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];o.push(new Item(e,t)),o.length===1&&!s&&runTimeout(drainQueue)};function Item(e,t){this.fun=e,this.array=t}Item.prototype.run=function(){this.fun.apply(null,this.array)},n.title=`browser`,n.browser=!0,n.env={},n.argv=[],n.version=``,n.versions={};function noop(){}n.on=noop,n.addListener=noop,n.once=noop,n.off=noop,n.removeListener=noop,n.removeAllListeners=noop,n.emit=noop,n.prependListener=noop,n.prependOnceListener=noop,n.listeners=function(e){return[]},n.binding=function(e){throw Error(`process.binding is not supported`)},n.cwd=function(){return`/`},n.chdir=function(e){throw Error(`process.chdir is not supported`)},n.umask=function(){return 0}})),
|
|
11
|
+
`)===0?e.substr(1,e.length):e}).forEach(function(e){var n=e.split(`:`),r=n.shift().trim();if(r){var a=n.join(`:`).trim();try{t.append(r,a)}catch(e){console.warn(`Response `+e.message)}}}),t}Body.call(Request.prototype);function Response(e,t){if(!(this instanceof Response))throw TypeError(`Please use the "new" operator, this DOM object constructor cannot be called as a function.`);if(t||(t={}),this.type=`default`,this.status=t.status===void 0?200:t.status,this.status<200||this.status>599)throw RangeError(`Failed to construct 'Response': The status provided (0) is outside the range [200, 599].`);this.ok=this.status>=200&&this.status<300,this.statusText=t.statusText===void 0?``:``+t.statusText,this.headers=new Headers(t.headers),this.url=t.url||``,this._initBody(e)}Body.call(Response.prototype),Response.prototype.clone=function(){return new Response(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new Headers(this.headers),url:this.url})},Response.error=function(){var e=new Response(null,{status:200,statusText:``});return e.ok=!1,e.status=0,e.type=`error`,e};var c=[301,302,303,307,308];Response.redirect=function(e,t){if(c.indexOf(t)===-1)throw RangeError(`Invalid status code`);return new Response(null,{status:t,headers:{location:e}})},t.DOMException=n.DOMException;try{new t.DOMException}catch{t.DOMException=function(e,t){this.message=e,this.name=t,this.stack=Error(e).stack},t.DOMException.prototype=Object.create(Error.prototype),t.DOMException.prototype.constructor=t.DOMException}function fetch(e,a){return new Promise(function(o,s){var c=new Request(e,a);if(c.signal&&c.signal.aborted)return s(new t.DOMException(`Aborted`,`AbortError`));var l=new XMLHttpRequest;function abortXhr(){l.abort()}l.onload=function(){var e={statusText:l.statusText,headers:parseHeaders(l.getAllResponseHeaders()||``)};c.url.indexOf(`file://`)===0&&(l.status<200||l.status>599)?e.status=200:e.status=l.status,e.url=`responseURL`in l?l.responseURL:e.headers.get(`X-Request-URL`);var t=`response`in l?l.response:l.responseText;setTimeout(function(){o(new Response(t,e))},0)},l.onerror=function(){setTimeout(function(){s(TypeError(`Network request failed`))},0)},l.ontimeout=function(){setTimeout(function(){s(TypeError(`Network request timed out`))},0)},l.onabort=function(){setTimeout(function(){s(new t.DOMException(`Aborted`,`AbortError`))},0)};function fixUrl(e){try{return e===``&&n.location.href?n.location.href:e}catch{return e}}if(l.open(c.method,fixUrl(c.url),!0),c.credentials===`include`?l.withCredentials=!0:c.credentials===`omit`&&(l.withCredentials=!1),`responseType`in l&&(r.blob?l.responseType=`blob`:r.arrayBuffer&&(l.responseType=`arraybuffer`)),a&&typeof a.headers==`object`&&!(a.headers instanceof Headers||n.Headers&&a.headers instanceof n.Headers)){var u=[];Object.getOwnPropertyNames(a.headers).forEach(function(e){u.push(normalizeName(e)),l.setRequestHeader(e,normalizeValue(a.headers[e]))}),c.headers.forEach(function(e,t){u.indexOf(t)===-1&&l.setRequestHeader(t,e)})}else c.headers.forEach(function(e,t){l.setRequestHeader(t,e)});c.signal&&(c.signal.addEventListener(`abort`,abortXhr),l.onreadystatechange=function(){l.readyState===4&&c.signal.removeEventListener(`abort`,abortXhr)}),l.send(c._bodyInit===void 0?null:c._bodyInit)})}return fetch.polyfill=!0,n.fetch||(n.fetch=fetch,n.Headers=Headers,n.Request=Request,n.Response=Response),t.Headers=Headers,t.Request=Request,t.Response=Response,t.fetch=fetch,t})({})})(r),r.fetch.ponyfill=!0,delete r.fetch.polyfill;var a=n.fetch?n:r;e=a.fetch,e.default=a.fetch,e.fetch=a.fetch,e.Headers=a.Headers,e.Request=a.Request,e.Response=a.Response,t.exports=e})),require_browser=__commonJSMin(((e,t)=>{var n=t.exports={},r,a;function defaultSetTimout(){throw Error(`setTimeout has not been defined`)}function defaultClearTimeout(){throw Error(`clearTimeout has not been defined`)}(function(){try{r=typeof setTimeout==`function`?setTimeout:defaultSetTimout}catch{r=defaultSetTimout}try{a=typeof clearTimeout==`function`?clearTimeout:defaultClearTimeout}catch{a=defaultClearTimeout}})();function runTimeout(e){if(r===setTimeout)return setTimeout(e,0);if((r===defaultSetTimout||!r)&&setTimeout)return r=setTimeout,setTimeout(e,0);try{return r(e,0)}catch{try{return r.call(null,e,0)}catch{return r.call(this,e,0)}}}function runClearTimeout(e){if(a===clearTimeout)return clearTimeout(e);if((a===defaultClearTimeout||!a)&&clearTimeout)return a=clearTimeout,clearTimeout(e);try{return a(e)}catch{try{return a.call(null,e)}catch{return a.call(this,e)}}}var o=[],s=!1,c,l=-1;function cleanUpNextTick(){!s||!c||(s=!1,c.length?o=c.concat(o):l=-1,o.length&&drainQueue())}function drainQueue(){if(!s){var e=runTimeout(cleanUpNextTick);s=!0;for(var t=o.length;t;){for(c=o,o=[];++l<t;)c&&c[l].run();l=-1,t=o.length}c=null,s=!1,runClearTimeout(e)}}n.nextTick=function(e){var t=Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];o.push(new Item(e,t)),o.length===1&&!s&&runTimeout(drainQueue)};function Item(e,t){this.fun=e,this.array=t}Item.prototype.run=function(){this.fun.apply(null,this.array)},n.title=`browser`,n.browser=!0,n.env={},n.argv=[],n.version=``,n.versions={};function noop(){}n.on=noop,n.addListener=noop,n.once=noop,n.off=noop,n.removeListener=noop,n.removeAllListeners=noop,n.emit=noop,n.prependListener=noop,n.prependOnceListener=noop,n.listeners=function(e){return[]},n.binding=function(e){throw Error(`process.binding is not supported`)},n.cwd=function(){return`/`},n.chdir=function(e){throw Error(`process.chdir is not supported`)},n.umask=function(){return 0}})),import_browser_ponyfill=__toESM(require_browser_ponyfill(),1),import_browser=__toESM(require_browser(),1),import___vite_browser_external=__toESM(require___vite_browser_external(),1),__defProp=Object.defineProperty,__getOwnPropNames=Object.getOwnPropertyNames,__glob=e=>t=>{var n=e[t];if(n)return n();throw Error(`Module not found in bundle: `+t)},__esm=(e,t)=>function __init(){return e&&(t=(0,e[__getOwnPropNames(e)[0]])(e=0)),t},__export=(e,t)=>{for(var n in t)__defProp(e,n,{get:t[n],enumerable:!0})},init_adminDB=__esm({"src/core/interfaces/adminDB.ts"(){}}),init_classroomDB=__esm({"src/core/interfaces/classroomDB.ts"(){}}),init_SyncStrategy=__esm({"src/impl/common/SyncStrategy.ts"(){}}),isDevelopment,logger,init_logger=__esm({"src/util/logger.ts"(){isDevelopment=typeof process<`u`&&!1,logger={debug:(e,...t)=>{isDevelopment&&console.debug(`[DB:DEBUG] ${e}`,...t)},info:(e,...t)=>{console.info(`[DB:INFO] ${e}`,...t)},warn:(e,...t)=>{console.warn(`[DB:WARN] ${e}`,...t)},error:(e,...t)=>{console.error(`[DB:ERROR] ${e}`,...t)},log:(e,...t)=>{isDevelopment&&console.log(`[DB:LOG] ${e}`,...t)}}}}),GuestUsername,log,DocType,DocTypePrefixes,init_types_legacy=__esm({"src/core/types/types-legacy.ts"(){init_logger(),GuestUsername=`sk-guest-`,log=e=>{logger.log(e)},DocType=(e=>(e.DISPLAYABLE_DATA=`DISPLAYABLE_DATA`,e.CARD=`CARD`,e.DATASHAPE=`DATASHAPE`,e.QUESTIONTYPE=`QUESTION`,e.VIEW=`VIEW`,e.PEDAGOGY=`PEDAGOGY`,e.CARDRECORD=`CARDRECORD`,e.SCHEDULED_CARD=`SCHEDULED_CARD`,e.TAG=`TAG`,e.NAVIGATION_STRATEGY=`NAVIGATION_STRATEGY`,e.STRATEGY_STATE=`STRATEGY_STATE`,e.USER_OUTCOME=`USER_OUTCOME`,e.STRATEGY_LEARNING_STATE=`STRATEGY_LEARNING_STATE`,e.STUDY_SESSION=`STUDY_SESSION`,e))(DocType||{}),DocTypePrefixes={CARD:`c`,DISPLAYABLE_DATA:`dd`,TAG:`TAG`,CARDRECORD:`cardH`,SCHEDULED_CARD:`card_review_`,DATASHAPE:`DATASHAPE`,QUESTION:`QUESTION`,VIEW:`VIEW`,PEDAGOGY:`PEDAGOGY`,NAVIGATION_STRATEGY:`NAVIGATION_STRATEGY`,STRATEGY_STATE:`STRATEGY_STATE`,USER_OUTCOME:`USER_OUTCOME`,STRATEGY_LEARNING_STATE:`STRATEGY_LEARNING_STATE`,STUDY_SESSION:`SESSION`}}});function areQuestionRecords(e){return isQuestionRecord(e.records[0])}function isQuestionRecord(e){return e.userAnswer!==void 0}function getCardHistoryID(e,t){return`${DocTypePrefixes.CARDRECORD}-${e}-${t}`}function parseCardHistoryID(e){let t=e.split(`-`),n=``;if(n+=t.length===3?``:`
|
|
12
12
|
given ID has incorrect number of '-' characters`,n+=t[0]===DocTypePrefixes.CARDRECORD?``:`
|
|
13
|
-
given ID does not start with ${DocTypePrefixes.CARDRECORD}`,t.length===3&&t[0]===DocTypePrefixes.CARDRECORD)return{courseID:t[1],cardID:t[2]};throw Error(`parseCardHistory Error:`+n)}function docIsDeleted(e){return e?.error===`not_found`&&e?.reason===`deleted`}var init_util=__esm({"src/core/util/index.ts"(){init_types_legacy()}}),pouchdb_setup_default,init_pouchdb_setup=__esm({"src/impl/couch/pouchdb-setup.ts"(){PouchDB.plugin(plugin$1),PouchDB.plugin(plugin),PouchDB.debug!==void 0&&PouchDB.debug.disable(),PouchDB.defaults({}),pouchdb_setup_default=PouchDB}});function getAppDataDirectory(){return ENV.LOCAL_STORAGE_PREFIX?import___vite_browser_external.join(import___vite_browser_external.homedir(),`.tuilder`,ENV.LOCAL_STORAGE_PREFIX):import___vite_browser_external.join(import___vite_browser_external.homedir(),`.tuilder`)}async function ensureAppDataDirectory(){let e=getAppDataDirectory();try{await import___vite_browser_external.promises.mkdir(e,{recursive:!0})}catch(t){if(t.code!==`EEXIST`)throw Error(`Failed to create app data directory ${e}: ${t.message}`)}return e}function getDbPath(e){return import___vite_browser_external.join(getAppDataDirectory(),e)}async function initializeDataDirectory(){await ensureAppDataDirectory(),logger.info(`PouchDB data directory initialized: ${getAppDataDirectory()}`)}var init_dataDirectory=__esm({"src/util/dataDirectory.ts"(){init_logger(),init_factory()}});function makeScheduledCardId(e){return DocTypePrefixes.SCHEDULED_CARD+hooks.utc(e).format(REVIEW_TIME_FORMAT)}function hexEncode(e){let t,n=``;for(let r=0;r<e.length;r++)t=e.charCodeAt(r).toString(16),n+=(`000`+t).slice(3);return n}function filterAllDocsByPrefix(e,t,n){let r={startkey:t,endkey:t+``,include_docs:!0};return n&&Object.assign(r,n),e.allDocs(r)}function getStartAndEndKeys(e){return{startkey:e,endkey:e+``}}function updateGuestAccountExpirationDate(e){let t=hooks.utc().add(2,`months`).toISOString(),n=`GuestAccountExpirationDate`;e.get(n).then(r=>e.put({_id:n,_rev:r._rev,date:t})).catch(()=>e.put({_id:n,date:t}))}function getLocalUserDB(e){let t=`userdb-${e}`;return typeof window>`u`?new pouchdb_setup_default(getDbPath(t),{}):new pouchdb_setup_default(t,{})}function scheduleCardReviewLocal(e,t){let n=hooks.utc();logger.info(`Scheduling for review in: ${t.time.diff(n,`h`)/24} days`),e.put({_id:makeScheduledCardId(t.time),cardId:t.card_id,reviewTime:t.time.toISOString(),courseId:t.course_id,scheduledAt:n.toISOString(),scheduledFor:t.scheduledFor,schedulingAgentId:t.schedulingAgentId})}async function removeScheduledCardReviewLocal(e,t){let n=await e.get(t);e.remove(n).then(e=>{e.ok&&log2(`Removed Review Doc: ${t}`)}).catch(e=>{log2(`Failed to remove Review Doc: ${t},
|
|
14
|
-
${JSON.stringify(e)}`)})}var REVIEW_TIME_FORMAT,log2,init_userDBHelpers=__esm({"src/impl/common/userDBHelpers.ts"(){init_core(),init_logger(),init_pouchdb_setup(),init_dataDirectory(),REVIEW_TIME_FORMAT=`YYYY-MM-DD--kk:mm:ss-SSS`,log2=e=>{logger.info(e)}}}),Loggable,init_Loggable=__esm({"src/util/Loggable.ts"(){Loggable=class{log(...e){console.log(`LOG-${this._className}@${new Date}:`,...e)}error(...e){console.error(`ERROR-${this._className}@${new Date}:`,...e)}}}}),UpdateQueue,init_updateQueue=__esm({"src/impl/couch/updateQueue.ts"(){init_Loggable(),init_logger(),UpdateQueue=class extends Loggable{update(e,t){return logger.debug(`Update requested on doc: ${e}`),this.pendingUpdates[e]?this.pendingUpdates[e].push(t):this.pendingUpdates[e]=[t],this.applyUpdates(e)}constructor(e,t){super(),_defineProperty(this,`_className`,`UpdateQueue`),_defineProperty(this,`pendingUpdates`,{}),_defineProperty(this,`inprogressUpdates`,{}),_defineProperty(this,`readDB`,void 0),_defineProperty(this,`writeDB`,void 0),this.readDB=e,this.writeDB=t||e,logger.debug(`UpdateQ initialized...`),this.readDB.info().then(e=>{logger.debug(`db info: ${JSON.stringify(e)}`)})}async applyUpdates(e){if(logger.debug(`Applying updates on doc: ${e}`),this.inprogressUpdates[e]){for(;this.inprogressUpdates[e];)await new Promise(e=>setTimeout(e,Math.random()*50));return this.applyUpdates(e)}else if(this.pendingUpdates[e]&&this.pendingUpdates[e].length>0){this.inprogressUpdates[e]=!0;let t=5;for(let t=0;t<5;t++)try{let t={...await this.readDB.get(e)},n=[...this.pendingUpdates[e]];for(let e of n)t=typeof e==`function`?{...t,...e(t)}:{...t,...e};if(await this.writeDB.put(t),this.pendingUpdates[e].splice(0,n.length),this.pendingUpdates[e].length===0)this.inprogressUpdates[e]=!1,delete this.inprogressUpdates[e];else return this.applyUpdates(e);return t}catch(n){if(n.name===`conflict`&&t<4)logger.warn(`Conflict on update for doc ${e}, retry #${t+1}`),await new Promise(e=>setTimeout(e,50*Math.random()));else if(n.name===`not_found`&&t===0)throw logger.warn(`Update failed for ${e} - does not exist. Throwing to caller.`),delete this.inprogressUpdates[e],n;else throw delete this.inprogressUpdates[e],this.pendingUpdates[e]&&delete this.pendingUpdates[e],logger.error(`Error on attemped update (retry ${t}): ${JSON.stringify(n)}`),n}throw Error(`UpdateQueue failed for doc ${e} after 5 retries.`)}else throw Error(`Empty Updates Queue Triggered`)}}}}),UsrCrsData,init_user_course_relDB=__esm({"src/impl/couch/user-course-relDB.ts"(){init_logger(),UsrCrsData=class{constructor(e,t){_defineProperty(this,`user`,void 0),_defineProperty(this,`_courseId`,void 0),this.user=e,this._courseId=t}async getReviewsForcast(e){let t=hooks.utc().add(e,`days`);return this.getReviewstoDate(t)}async getPendingReviews(){let e=hooks.utc();return this.getReviewstoDate(e)}async getScheduledReviewCount(){return(await this.getPendingReviews()).length}async getCourseSettings(){let e=(await this.user.getCourseRegistrationsDoc()).courses.find(e=>e.courseID===this._courseId);return e&&e.settings?e.settings:(logger.warn(`no settings found during lookup on course ${this._courseId}`),{})}updateCourseSettings(e){`updateCourseSettings`in this.user&&this.user.updateCourseSettings(this._courseId,e)}async getStrategyState(e){return this.user.getStrategyState(this._courseId,e)}async putStrategyState(e,t){return this.user.putStrategyState(this._courseId,e,t)}async deleteStrategyState(e){return this.user.deleteStrategyState(this._courseId,e)}async getReviewstoDate(e){let t=await this.user.getPendingReviews(this._courseId);return logger.debug(`Fetching ${this.user.getUsername()}'s scheduled reviews for course ${this._courseId}.`),t.filter(t=>{let n=hooks.utc(t.reviewTime);return e.isAfter(n)})}}}});async function GET_CACHED(e,t){return CLIENT_CACHE[e]?CLIENT_CACHE[e]:(CLIENT_CACHE[e]=t?await t(e):await GET_ITEM(e),GET_CACHED(e))}async function GET_ITEM(e){throw Error(`No implementation found for GET_CACHED(${e})`)}var CLIENT_CACHE,init_clientCache=__esm({"src/impl/couch/clientCache.ts"(){CLIENT_CACHE={}}});async function addNote55(e,t,n,r,a,o,s,c=blankCourseElo()){let l=getCourseDB(e),u=prepareNote55(e,t,n,r,a,o,s),d=`${DocTypePrefixes.DISPLAYABLE_DATA}-${v4()}`,p=await l.put({...u,_id:d}),m=NameSpacer.getDataShapeString({course:t,dataShape:n.name});if(p.ok)try{await createCards(e,m,p.id,o,c,a)}catch(e){let t=`Unknown error`;t=e instanceof Error?e.message:e&&typeof e==`object`&&`reason`in e?e.reason:e&&typeof e==`object`&&`message`in e?e.message:String(e),logger.error(`[addNote55] Failed to create cards for note ${p.id}: ${t}`),p.cardCreationFailed=!0,p.cardCreationError=t}else logger.error(`[addNote55] Error adding note. Result: ${JSON.stringify(p)}`);return p}async function createCards(e,t,n,r,a=blankCourseElo(),o){let s=await getCredentialledCourseConfig(e),c=NameSpacer.getDataShapeDescriptor(t),l=[];for(let e of s.dataShapes)e.name===t&&(l=e.questionTypes);if(l.length===0){let e=`No questionViewTypes found for datashapeID: ${t} in course config. Cards cannot be created.`;throw logger.error(e),Error(e)}for(let t of l)await createCard(t,e,c,n,r,a,o)}async function createCard(e,t,n,r,a,o=blankCourseElo(),s){let c=NameSpacer.getQuestionDescriptor(e),l=await getCredentialledCourseConfig(t);for(let u of l.questionTypes)if(u.name===e)for(let e of u.viewList)await addCard(t,n.course,[r],NameSpacer.getViewString({course:c.course,questionType:c.questionType,view:e}),o,a,s)}async function addCard(e,t,n,r,a,o,s){let c=getCourseDB(e),l=`${DocTypePrefixes.CARD}-${v4()}`,u=await c.put({_id:l,course:t,id_displayable_data:n,id_view:r,docType:`CARD`,elo:a||toCourseElo(990+Math.round(20*Math.random())),author:s});for(let t of o)logger.info(`adding tag: ${t} to card ${u.id}`),await addTagToCard(e,u.id,t,s,!1);return u}async function getCredentialledCourseConfig(e){try{let t=await getCourseDB(e).get(`CourseConfig`);return t.courseID=e,logger.info(`Returning course config: ${JSON.stringify(t)}`),t}catch(t){throw logger.error(`Error fetching config for ${e}:`,t),t}}async function addTagToCard(e,t,n,r,a=!0){let o=getTagID(n),s=getCourseDB(e),c=new CourseDB(e,async()=>BaseUser.Dummy({setupRemoteDB:()=>null,startSync:()=>{},canCreateAccount:()=>!1,canAuthenticate:()=>!1,getCurrentUsername:async()=>`DummyUser`}));try{logger.info(`Applying tag ${n} to card ${e+`-`+t}...`);let r=await s.get(o);if(r.taggedCards.includes(t))throw new AlreadyTaggedErr(`Card ${t} is already tagged with ${n}`);if(r.taggedCards.push(t),a)try{let r=(await c.getCardEloData([t]))[0];r.tags[n]={count:0,score:r.global.score},await updateCardElo(e,t,r)}catch(e){logger.error(`Failed to update ELO data for card:`,t,e)}return s.put(r)}catch(o){if(o instanceof AlreadyTaggedErr)throw o;return await createTag(e,n,r),addTagToCard(e,t,n,r,a)}}async function updateCardElo(e,t,n){if(n){let r=getCourseDB(e),a=await r.get(t);return logger.debug(`Replacing ${JSON.stringify(a.elo)} with ${JSON.stringify(n)}`),a.elo=n,r.put(a)}}function getTagID(e){let t=`TAG`.valueOf()+`-`;return e.indexOf(t)===0?e:t+e}function getCourseDB(e){let t=`coursedb-${e}`;return new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+t,createPouchDBConfig())}var AlreadyTaggedErr,init_courseAPI=__esm({"src/impl/couch/courseAPI.ts"(){init_pouchdb_setup(),init_couch(),init_factory(),init_courseDB(),init_types_legacy(),init_common(),init_logger(),AlreadyTaggedErr=class extends Error{constructor(e){super(e),this.name=`AlreadyTaggedErr`}}}}),courseLookupDBTitle,CourseLookup,init_courseLookupDB=__esm({"src/impl/couch/courseLookupDB.ts"(){var e;init_pouchdb_setup(),init_factory(),init_logger(),courseLookupDBTitle=`coursedb-lookup`,logger.debug(`COURSELOOKUP FILE RUNNING`),CourseLookup=(e=class _CourseLookup{static get _db(){if(this._dbInstance)return this._dbInstance;if(ENV.COUCHDB_SERVER_URL===`NOT_SET`||!ENV.COUCHDB_SERVER_URL)throw Error(`CourseLookup.db: COUCHDB_SERVER_URL is not set. Ensure initializeDataLayer has been called with valid configuration.`);if(ENV.COUCHDB_SERVER_PROTOCOL===`NOT_SET`||!ENV.COUCHDB_SERVER_PROTOCOL)throw Error(`CourseLookup.db: COUCHDB_SERVER_PROTOCOL is not set. Ensure initializeDataLayer has been called with valid configuration.`);let e=`${ENV.COUCHDB_SERVER_PROTOCOL}://${ENV.COUCHDB_SERVER_URL}/${courseLookupDBTitle}`,t={};ENV.COUCHDB_USERNAME&&ENV.COUCHDB_PASSWORD?(t.auth={username:ENV.COUCHDB_USERNAME,password:ENV.COUCHDB_PASSWORD},logger.info(`CourseLookup: Connecting to ${e} with authentication.`)):logger.info(`CourseLookup: Connecting to ${e} without authentication.`);try{return this._dbInstance=new pouchdb_setup_default(e,t),logger.info(`CourseLookup: Database instance created for ${courseLookupDBTitle}.`),this._dbInstance}catch(t){throw logger.error(`CourseLookup: Failed to create PouchDB instance for ${e}`,t),this._dbInstance=null,Error(`CourseLookup: Failed to initialize database connection: ${t instanceof Error?t.message:String(t)}`)}}static async add(e){return(await _CourseLookup._db.post({name:e})).id}static async addWithId(e,t,n){let r={_id:e,name:t};n&&(r.disambiguator=n),await _CourseLookup._db.put(r)}static async delete(e){let t=await _CourseLookup._db.get(e);return await _CourseLookup._db.remove(t)}static async allCourseWare(){return(await _CourseLookup._db.allDocs({include_docs:!0})).rows.map(e=>e.doc)}static async updateDisambiguator(e,t){let n=await _CourseLookup._db.get(e);return n.disambiguator=t,await _CourseLookup._db.put(n)}static async isCourse(e){try{return await _CourseLookup._db.get(e),!0}catch(e){return logger.info(`Courselookup failed:`,e),!1}}},_defineProperty(e,`_dbInstance`,null),e)}}),diversityRerank_exports={};__export(diversityRerank_exports,{DIVERSITY_FLOOR:()=>DIVERSITY_FLOOR,DIVERSITY_STRENGTH:()=>DIVERSITY_STRENGTH,diversityRerank:()=>diversityRerank});function diversityRerank(e,t={}){let n=t.strength??DIVERSITY_STRENGTH,r=t.floor??DIVERSITY_FLOOR,a=e.length;if(a<=1)return e;let o=new Map;for(let t of e)for(let e of t.tags??[])o.set(e,(o.get(e)??0)+1);let s=new Map;for(let[e,t]of o)s.set(e,Math.log(a/t));let c=[...e],l=new Map,u=[],repetitionLoad=e=>{let t=0;for(let n of e.tags??[]){let e=l.get(n);e&&(t+=(s.get(n)??0)*e)}return t};for(;c.length>0;){let e=0,t=-1/0,a=1,o=0;for(let s=0;s<c.length;s++){let l=c[s],u=repetitionLoad(l),d=u>0?Math.max(r,1/(1+n*u)):1,p=l.score*d;p>t&&(t=p,e=s,a=d,o=u)}let[s]=c.splice(e,1);if(Number.isFinite(s.score)&&a<1){let e=s.score*a;u.push({...s,score:e,provenance:[...s.provenance,{strategy:STRATEGY,strategyId:STRATEGY_ID,strategyName:STRATEGY_NAME,action:`penalized`,score:e,reason:`repeated tags (load ${o.toFixed(2)}) \u2192 \xD7${a.toFixed(2)}`}]})}else u.push(s);for(let e of s.tags??[])l.set(e,(l.get(e)??0)+1)}return u}var DIVERSITY_STRENGTH,DIVERSITY_FLOOR,STRATEGY,STRATEGY_ID,STRATEGY_NAME,init_diversityRerank=__esm({"src/core/navigators/diversityRerank.ts"(){DIVERSITY_STRENGTH=.6,DIVERSITY_FLOOR=.3,STRATEGY=`diversityRerank`,STRATEGY_ID=`DIVERSITY_RERANK`,STRATEGY_NAME=`Diversity Re-rank`}}),PipelineDebugger_exports={};__export(PipelineDebugger_exports,{buildRunReport:()=>buildRunReport,captureRun:()=>captureRun,clearRunHistory:()=>clearRunHistory,drainCapturedRuns:()=>drainCapturedRuns,getActivePipeline:()=>getActivePipeline,getRunsForSession:()=>getRunsForSession,mountPipelineDebugger:()=>mountPipelineDebugger,pipelineDebugAPI:()=>pipelineDebugAPI,registerPipelineForDebug:()=>registerPipelineForDebug,setDebugSessionId:()=>setDebugSessionId});function registerPipelineForDebug(e){_activePipeline=e}function getActivePipeline(){return _activePipeline}function setDebugSessionId(e){_currentSessionId=e}function drainCapturedRuns(){let e=_pendingRuns;return _pendingRuns=[],e}function getRunsForSession(e){return runHistory.filter(t=>t.sessionId===e).reverse()}function clearRunHistory(){runHistory.length=0,_pendingRuns=[]}function getOrigin(e){let t=e.provenance[0];if(!t)return`unknown`;let n=t.reason?.toLowerCase()||``,r=t.strategy?.toLowerCase()||``;return n.includes(`new card`)||r.includes(`elo`)?`new`:n.includes(`review`)||r.includes(`srs`)?`review`:`unknown`}function captureRun(e){let t={...e,runId:`run-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,sessionId:_currentSessionId,timestamp:new Date};return runHistory.unshift(t),runHistory.length>MAX_RUNS&&runHistory.pop(),_pendingRuns.push(t),t}function parseCardElo(e){let t=e.find(e=>e.strategy===`elo`);if(!t?.reason)return;let n=t.reason.match(/card:\s*(\d+)/);return n?parseInt(n[1],10):void 0}function buildRunReport(e,t,n,r,a,o,s,c,l,u){let d=new Set(c.map(e=>e.cardId)),toReport=e=>({cardId:e.cardId,courseId:e.courseId,origin:getOrigin(e),generator:e.provenance[0]?.strategyName||e.provenance[0]?.strategy,finalScore:e.score,cardElo:parseCardElo(e.provenance),provenance:e.provenance,tags:e.tags,selected:d.has(e.cardId)}),p=[],m=[],g=[],_=0;for(let e of s)d.has(e.cardId)?p.push(toReport(e)):_<DISCARDED_KEEP_TOP?(m.push(toReport(e)),_++):g.push(e);let v=[...p,...m],y;if(g.length>0){let e=1/0,t=-1/0,n=1/0,r=-1/0,a=!1;for(let o of g){o.score<e&&(e=o.score),o.score>t&&(t=o.score);let s=parseCardElo(o.provenance);s!==void 0&&(a=!0,s<n&&(n=s),s>r&&(r=s))}let o=a?`, ELO ${n}\u2013${r}`:``;y={count:g.length,scoreRange:[e,t],eloRange:a?[n,r]:void 0,note:`${g.length} additional candidate(s) scored below the top ${DISCARDED_KEEP_TOP} near-misses and were not retained (score ${e.toExponential(2)}\u2013${t.toExponential(2)}${o}). Likely ELO-window pull remnants filtered out by hierarchy/lesson/priority gates.`}}let b=c.filter(e=>getOrigin(e)===`review`).length,x=c.filter(e=>getOrigin(e)===`new`).length;return{courseId:e,courseName:t,userElo:l,generatorName:n,generators:r,generatedCount:a,filters:o,hints:u,finalCount:c.length,reviewsSelected:b,newSelected:x,cards:v,discardedTail:y}}function formatProvenance(e){return e.map(e=>` ${e.action===`generated`?`🎲`:e.action===`boosted`?`⬆️`:e.action===`penalized`?`⬇️`:`➡️`} ${e.strategyName}: ${e.score.toFixed(3)} - ${e.reason}`).join(`
|
|
13
|
+
given ID does not start with ${DocTypePrefixes.CARDRECORD}`,t.length===3&&t[0]===DocTypePrefixes.CARDRECORD)return{courseID:t[1],cardID:t[2]};throw Error(`parseCardHistory Error:`+n)}function docIsDeleted(e){return e?.error===`not_found`&&e?.reason===`deleted`}var init_util=__esm({"src/core/util/index.ts"(){init_types_legacy()}}),pouchdb_setup_default,init_pouchdb_setup=__esm({"src/impl/couch/pouchdb-setup.ts"(){PouchDB.plugin(plugin$1),PouchDB.plugin(plugin),PouchDB.debug!==void 0&&PouchDB.debug.disable(),PouchDB.defaults({}),pouchdb_setup_default=PouchDB}}),Loggable,init_Loggable=__esm({"src/util/Loggable.ts"(){Loggable=class{log(...e){console.log(`LOG-${this._className}@${new Date}:`,...e)}error(...e){console.error(`ERROR-${this._className}@${new Date}:`,...e)}}}}),UpdateQueue,init_updateQueue=__esm({"src/impl/couch/updateQueue.ts"(){init_Loggable(),init_logger(),UpdateQueue=class extends Loggable{update(e,t){return logger.debug(`Update requested on doc: ${e}`),this.pendingUpdates[e]?this.pendingUpdates[e].push(t):this.pendingUpdates[e]=[t],this.applyUpdates(e)}constructor(e,t){super(),_defineProperty(this,`_className`,`UpdateQueue`),_defineProperty(this,`pendingUpdates`,{}),_defineProperty(this,`inprogressUpdates`,{}),_defineProperty(this,`readDB`,void 0),_defineProperty(this,`writeDB`,void 0),this.readDB=e,this.writeDB=t||e,logger.debug(`UpdateQ initialized...`),this.readDB.info().then(e=>{logger.debug(`db info: ${JSON.stringify(e)}`)})}async applyUpdates(e){if(logger.debug(`Applying updates on doc: ${e}`),this.inprogressUpdates[e]){for(;this.inprogressUpdates[e];)await new Promise(e=>setTimeout(e,Math.random()*50));return this.applyUpdates(e)}else if(this.pendingUpdates[e]&&this.pendingUpdates[e].length>0){this.inprogressUpdates[e]=!0;let t=5;for(let t=0;t<5;t++)try{let t={...await this.readDB.get(e)},n=[...this.pendingUpdates[e]];for(let e of n)t=typeof e==`function`?{...t,...e(t)}:{...t,...e};if(await this.writeDB.put(t),this.pendingUpdates[e].splice(0,n.length),this.pendingUpdates[e].length===0)this.inprogressUpdates[e]=!1,delete this.inprogressUpdates[e];else return this.applyUpdates(e);return t}catch(n){if(n.name===`conflict`&&t<4)logger.warn(`Conflict on update for doc ${e}, retry #${t+1}`),await new Promise(e=>setTimeout(e,50*Math.random()));else if(n.name===`not_found`&&t===0)throw logger.warn(`Update failed for ${e} - does not exist. Throwing to caller.`),delete this.inprogressUpdates[e],n;else throw delete this.inprogressUpdates[e],this.pendingUpdates[e]&&delete this.pendingUpdates[e],logger.error(`Error on attemped update (retry ${t}): ${JSON.stringify(n)}`),n}throw Error(`UpdateQueue failed for doc ${e} after 5 retries.`)}else throw Error(`Empty Updates Queue Triggered`)}}}});async function GET_CACHED(e,t){return CLIENT_CACHE[e]?CLIENT_CACHE[e]:(CLIENT_CACHE[e]=t?await t(e):await GET_ITEM(e),GET_CACHED(e))}async function GET_ITEM(e){throw Error(`No implementation found for GET_CACHED(${e})`)}var CLIENT_CACHE,init_clientCache=__esm({"src/impl/couch/clientCache.ts"(){CLIENT_CACHE={}}});async function addNote55(e,t,n,r,a,o,s,c=blankCourseElo()){let l=getCourseDB(e),u=prepareNote55(e,t,n,r,a,o,s),d=`${DocTypePrefixes.DISPLAYABLE_DATA}-${v4()}`,p=await l.put({...u,_id:d}),m=NameSpacer.getDataShapeString({course:t,dataShape:n.name});if(p.ok)try{await createCards(e,m,p.id,o,c,a)}catch(e){let t=`Unknown error`;t=e instanceof Error?e.message:e&&typeof e==`object`&&`reason`in e?e.reason:e&&typeof e==`object`&&`message`in e?e.message:String(e),logger.error(`[addNote55] Failed to create cards for note ${p.id}: ${t}`),p.cardCreationFailed=!0,p.cardCreationError=t}else logger.error(`[addNote55] Error adding note. Result: ${JSON.stringify(p)}`);return p}async function createCards(e,t,n,r,a=blankCourseElo(),o){let s=await getCredentialledCourseConfig(e),c=NameSpacer.getDataShapeDescriptor(t),l=[];for(let e of s.dataShapes)e.name===t&&(l=e.questionTypes);if(l.length===0){let e=`No questionViewTypes found for datashapeID: ${t} in course config. Cards cannot be created.`;throw logger.error(e),Error(e)}for(let t of l)await createCard(t,e,c,n,r,a,o)}async function createCard(e,t,n,r,a,o=blankCourseElo(),s){let c=NameSpacer.getQuestionDescriptor(e),l=await getCredentialledCourseConfig(t);for(let u of l.questionTypes)if(u.name===e)for(let e of u.viewList)await addCard(t,n.course,[r],NameSpacer.getViewString({course:c.course,questionType:c.questionType,view:e}),o,a,s)}async function addCard(e,t,n,r,a,o,s){let c=getCourseDB(e),l=`${DocTypePrefixes.CARD}-${v4()}`,u=await c.put({_id:l,course:t,id_displayable_data:n,id_view:r,docType:`CARD`,elo:a||toCourseElo(990+Math.round(20*Math.random())),author:s});for(let t of o)logger.info(`adding tag: ${t} to card ${u.id}`),await addTagToCard(e,u.id,t,s,!1);return u}async function getCredentialledCourseConfig(e){try{let t=await getCourseDB(e).get(`CourseConfig`);return t.courseID=e,logger.info(`Returning course config: ${JSON.stringify(t)}`),t}catch(t){throw logger.error(`Error fetching config for ${e}:`,t),t}}async function addTagToCard(e,t,n,r,a=!0){let o=getTagID(n),s=getCourseDB(e),c=new CourseDB(e,async()=>BaseUser.Dummy({setupRemoteDB:()=>null,startSync:()=>{},canCreateAccount:()=>!1,canAuthenticate:()=>!1,getCurrentUsername:async()=>`DummyUser`}));try{logger.info(`Applying tag ${n} to card ${e+`-`+t}...`);let r=await s.get(o);if(r.taggedCards.includes(t))throw new AlreadyTaggedErr(`Card ${t} is already tagged with ${n}`);if(r.taggedCards.push(t),a)try{let r=(await c.getCardEloData([t]))[0];r.tags[n]={count:0,score:r.global.score},await updateCardElo(e,t,r)}catch(e){logger.error(`Failed to update ELO data for card:`,t,e)}return s.put(r)}catch(o){if(o instanceof AlreadyTaggedErr)throw o;return await createTag(e,n,r),addTagToCard(e,t,n,r,a)}}async function updateCardElo(e,t,n){if(n){let r=getCourseDB(e),a=await r.get(t);return logger.debug(`Replacing ${JSON.stringify(a.elo)} with ${JSON.stringify(n)}`),a.elo=n,r.put(a)}}function getTagID(e){let t=`TAG`.valueOf()+`-`;return e.indexOf(t)===0?e:t+e}function getCourseDB(e){let t=`coursedb-${e}`;return new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+t,createPouchDBConfig())}var AlreadyTaggedErr,init_courseAPI=__esm({"src/impl/couch/courseAPI.ts"(){init_pouchdb_setup(),init_couch(),init_factory(),init_courseDB(),init_types_legacy(),init_common(),init_logger(),AlreadyTaggedErr=class extends Error{constructor(e){super(e),this.name=`AlreadyTaggedErr`}}}}),courseLookupDBTitle,CourseLookup,init_courseLookupDB=__esm({"src/impl/couch/courseLookupDB.ts"(){var e;init_pouchdb_setup(),init_factory(),init_logger(),courseLookupDBTitle=`coursedb-lookup`,logger.debug(`COURSELOOKUP FILE RUNNING`),CourseLookup=(e=class _CourseLookup{static get _db(){if(this._dbInstance)return this._dbInstance;if(ENV.COUCHDB_SERVER_URL===`NOT_SET`||!ENV.COUCHDB_SERVER_URL)throw Error(`CourseLookup.db: COUCHDB_SERVER_URL is not set. Ensure initializeDataLayer has been called with valid configuration.`);if(ENV.COUCHDB_SERVER_PROTOCOL===`NOT_SET`||!ENV.COUCHDB_SERVER_PROTOCOL)throw Error(`CourseLookup.db: COUCHDB_SERVER_PROTOCOL is not set. Ensure initializeDataLayer has been called with valid configuration.`);let e=`${ENV.COUCHDB_SERVER_PROTOCOL}://${ENV.COUCHDB_SERVER_URL}/${courseLookupDBTitle}`,t={};ENV.COUCHDB_USERNAME&&ENV.COUCHDB_PASSWORD?(t.auth={username:ENV.COUCHDB_USERNAME,password:ENV.COUCHDB_PASSWORD},logger.info(`CourseLookup: Connecting to ${e} with authentication.`)):logger.info(`CourseLookup: Connecting to ${e} without authentication.`);try{return this._dbInstance=new pouchdb_setup_default(e,t),logger.info(`CourseLookup: Database instance created for ${courseLookupDBTitle}.`),this._dbInstance}catch(t){throw logger.error(`CourseLookup: Failed to create PouchDB instance for ${e}`,t),this._dbInstance=null,Error(`CourseLookup: Failed to initialize database connection: ${t instanceof Error?t.message:String(t)}`)}}static async add(e){return(await _CourseLookup._db.post({name:e})).id}static async addWithId(e,t,n){let r={_id:e,name:t};n&&(r.disambiguator=n),await _CourseLookup._db.put(r)}static async delete(e){let t=await _CourseLookup._db.get(e);return await _CourseLookup._db.remove(t)}static async allCourseWare(){return(await _CourseLookup._db.allDocs({include_docs:!0})).rows.map(e=>e.doc)}static async updateDisambiguator(e,t){let n=await _CourseLookup._db.get(e);return n.disambiguator=t,await _CourseLookup._db.put(n)}static async isCourse(e){try{return await _CourseLookup._db.get(e),!0}catch(e){return logger.info(`Courselookup failed:`,e),!1}}},_defineProperty(e,`_dbInstance`,null),e)}}),diversityRerank_exports={};__export(diversityRerank_exports,{DIVERSITY_FLOOR:()=>DIVERSITY_FLOOR,DIVERSITY_STRENGTH:()=>DIVERSITY_STRENGTH,diversityRerank:()=>diversityRerank});function diversityRerank(e,t={}){let n=t.strength??DIVERSITY_STRENGTH,r=t.floor??DIVERSITY_FLOOR,a=e.length;if(a<=1)return e;let o=new Map;for(let t of e)for(let e of t.tags??[])o.set(e,(o.get(e)??0)+1);let s=new Map;for(let[e,t]of o)s.set(e,Math.log(a/t));let c=[...e],l=new Map,u=[],repetitionLoad=e=>{let t=0;for(let n of e.tags??[]){let e=l.get(n);e&&(t+=(s.get(n)??0)*e)}return t};for(;c.length>0;){let e=0,t=-1/0,a=1,o=0;for(let s=0;s<c.length;s++){let l=c[s],u=repetitionLoad(l),d=u>0?Math.max(r,1/(1+n*u)):1,p=l.score*d;p>t&&(t=p,e=s,a=d,o=u)}let[s]=c.splice(e,1);if(Number.isFinite(s.score)&&a<1){let e=s.score*a;u.push({...s,score:e,provenance:[...s.provenance,{strategy:STRATEGY,strategyId:STRATEGY_ID,strategyName:STRATEGY_NAME,action:`penalized`,score:e,reason:`repeated tags (load ${o.toFixed(2)}) \u2192 \xD7${a.toFixed(2)}`}]})}else u.push(s);for(let e of s.tags??[])l.set(e,(l.get(e)??0)+1)}return u}var DIVERSITY_STRENGTH,DIVERSITY_FLOOR,STRATEGY,STRATEGY_ID,STRATEGY_NAME,init_diversityRerank=__esm({"src/core/navigators/diversityRerank.ts"(){DIVERSITY_STRENGTH=.6,DIVERSITY_FLOOR=.3,STRATEGY=`diversityRerank`,STRATEGY_ID=`DIVERSITY_RERANK`,STRATEGY_NAME=`Diversity Re-rank`}}),PipelineDebugger_exports={};__export(PipelineDebugger_exports,{buildRunReport:()=>buildRunReport,captureRun:()=>captureRun,clearRunHistory:()=>clearRunHistory,drainCapturedRuns:()=>drainCapturedRuns,getActivePipeline:()=>getActivePipeline,getRunsForSession:()=>getRunsForSession,mountPipelineDebugger:()=>mountPipelineDebugger,pipelineDebugAPI:()=>pipelineDebugAPI,registerPipelineForDebug:()=>registerPipelineForDebug,setDebugSessionId:()=>setDebugSessionId});function registerPipelineForDebug(e){_activePipeline=e}function getActivePipeline(){return _activePipeline}function setDebugSessionId(e){_currentSessionId=e}function drainCapturedRuns(){let e=_pendingRuns;return _pendingRuns=[],e}function getRunsForSession(e){return runHistory.filter(t=>t.sessionId===e).reverse()}function clearRunHistory(){runHistory.length=0,_pendingRuns=[]}function getOrigin(e){let t=e.provenance[0];if(!t)return`unknown`;let n=t.reason?.toLowerCase()||``,r=t.strategy?.toLowerCase()||``;return n.includes(`new card`)||r.includes(`elo`)?`new`:n.includes(`review`)||r.includes(`srs`)?`review`:`unknown`}function captureRun(e){let t={...e,runId:`run-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,sessionId:_currentSessionId,timestamp:new Date};return runHistory.unshift(t),runHistory.length>MAX_RUNS&&runHistory.pop(),_pendingRuns.push(t),t}function parseCardElo(e){let t=e.find(e=>e.strategy===`elo`);if(!t?.reason)return;let n=t.reason.match(/card:\s*(\d+)/);return n?parseInt(n[1],10):void 0}function buildRunReport(e,t,n,r,a,o,s,c,l,u){let d=new Set(c.map(e=>e.cardId)),toReport=e=>({cardId:e.cardId,courseId:e.courseId,origin:getOrigin(e),generator:e.provenance[0]?.strategyName||e.provenance[0]?.strategy,finalScore:e.score,cardElo:parseCardElo(e.provenance),provenance:e.provenance,tags:e.tags,selected:d.has(e.cardId)}),p=[],m=[],g=[],_=0;for(let e of s)d.has(e.cardId)?p.push(toReport(e)):_<DISCARDED_KEEP_TOP?(m.push(toReport(e)),_++):g.push(e);let v=[...p,...m],y;if(g.length>0){let e=1/0,t=-1/0,n=1/0,r=-1/0,a=!1;for(let o of g){o.score<e&&(e=o.score),o.score>t&&(t=o.score);let s=parseCardElo(o.provenance);s!==void 0&&(a=!0,s<n&&(n=s),s>r&&(r=s))}let o=a?`, ELO ${n}\u2013${r}`:``;y={count:g.length,scoreRange:[e,t],eloRange:a?[n,r]:void 0,note:`${g.length} additional candidate(s) scored below the top ${DISCARDED_KEEP_TOP} near-misses and were not retained (score ${e.toExponential(2)}\u2013${t.toExponential(2)}${o}). Likely ELO-window pull remnants filtered out by hierarchy/lesson/priority gates.`}}let b=c.filter(e=>getOrigin(e)===`review`).length,x=c.filter(e=>getOrigin(e)===`new`).length;return{courseId:e,courseName:t,userElo:l,generatorName:n,generators:r,generatedCount:a,filters:o,hints:u,finalCount:c.length,reviewsSelected:b,newSelected:x,cards:v,discardedTail:y}}function formatProvenance(e){return e.map(e=>` ${e.action===`generated`?`🎲`:e.action===`boosted`?`⬆️`:e.action===`penalized`?`⬇️`:`➡️`} ${e.strategyName}: ${e.score.toFixed(3)} - ${e.reason}`).join(`
|
|
15
14
|
`)}function printRunSummary(e){if(console.group(`\u{1F50D} Pipeline Run: ${e.courseId} (${e.courseName||`unnamed`})`),logger.info(`Run ID: ${e.runId}`),logger.info(`Time: ${e.timestamp.toISOString()}`),logger.info(`User ELO: ${e.userElo??`unknown`}`),logger.info(`Generator: ${e.generatorName} \u2192 ${e.generatedCount} candidates`),e.generators&&e.generators.length>0){console.group(`Generator breakdown:`);for(let t of e.generators)logger.info(` ${t.name}: ${t.cardCount} cards (${t.newCount} new, ${t.reviewCount} reviews, top: ${t.topScore.toFixed(2)})`);console.groupEnd()}if(e.filters.length>0){console.group(`Filter impact:`);for(let t of e.filters)logger.info(` ${t.name}: \u2191${t.boosted} \u2193${t.penalized} =${t.passed} \u2715${t.removed}`);console.groupEnd()}logger.info(`Result: ${e.finalCount} cards selected (${e.newSelected} new, ${e.reviewsSelected} reviews)`),console.groupEnd()}function escapeHtml(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`)}function escapeAttr(e){return escapeHtml(e).replace(/"/g,`"`)}function copyTextToClipboard(e,t){let done=()=>{if(!t)return;let e=t.textContent??`Copy`;t.textContent=`Copied!`,t.classList.add(`copied`),setTimeout(()=>{t.textContent=e,t.classList.remove(`copied`)},1200)},fallback=()=>{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.opacity=`0`,document.body.appendChild(t),t.select();try{document.execCommand(`copy`)}catch(e){logger.warn(`[Pipeline Debug] Copy failed: ${e}`)}document.body.removeChild(t),done()};navigator.clipboard?.writeText?navigator.clipboard.writeText(e).then(done).catch(fallback):fallback()}function renderUI(){if(!_uiContainer)return;let e=runHistory,t=_selectedRunIndex===null?null:e[_selectedRunIndex],n=`
|
|
16
15
|
#sk-pipeline-debugger {
|
|
17
16
|
position: fixed;
|
|
@@ -252,7 +251,7 @@ Example:
|
|
|
252
251
|
Generator: ${e.name}
|
|
253
252
|
Filters:${n}`)}function logTagHydration(e,t){let n=Array.from(t.values()).reduce((e,t)=>e+t.length,0),r=Array.from(t.values()).filter(e=>e.length>0).length;logger.debug(`[Pipeline] Tag hydration: ${e.length} cards, ${r} have tags (${n} total tags) - single batch query`)}function logExecutionSummary(e,t,n,r,a,o){let s=a.length>0?a.map(e=>e.toFixed(2)).join(`, `):`none`,c=``;o.length>0&&(c=`
|
|
254
253
|
Filter impact: ${o.map(e=>{let t=[];return e.boosted>0&&t.push(`+${e.boosted}`),e.penalized>0&&t.push(`-${e.penalized}`),e.passed>0&&t.push(`=${e.passed}`),`${e.name}: ${t.join(`/`)}`}).join(`, `)}`),logger.info(`[Pipeline] Execution: ${e} produced ${t} \u2192 ${n} filters \u2192 ${r} results (top scores: ${s})`+c+`
|
|
255
|
-
💡 Inspect: window.skuilder.pipeline`)}function logResultCards(e){if(!(!VERBOSE_RESULTS||e.length===0)){logger.info(`[Pipeline] Results (${e.length} cards):`);for(let t=0;t<e.length;t++){let n=e[t],r=n.tags?.slice(0,3).join(`, `)||``,a=n.provenance.filter(e=>e.strategy===`hierarchyDefinition`||e.strategy===`priorityDefinition`||e.strategy===`interferenceFilter`||e.strategy===`letterGating`||e.strategy===`ephemeralHint`||e.strategy===`diversityRerank`).map(e=>{let t=e.action===`boosted`?`↑`:e.action===`penalized`?`↓`:`=`;return`${e.strategyName}${t}${e.score.toFixed(2)}`}).join(` | `);logger.info(`[Pipeline] ${String(t+1).padStart(2)}. ${n.score.toFixed(4)} ${n.cardId} [${r}]${a?` {${a}}`:``}`)}}}function logCardProvenance(e,t=3){let n=e.slice(0,t);logger.debug(`[Pipeline] Provenance for top ${n.length} cards:`);for(let e of n){logger.debug(`[Pipeline] ${e.cardId} (final score: ${e.score.toFixed(3)}):`);for(let t of e.provenance){let e=t.score.toFixed(3),n=t.action.padEnd(9);logger.debug(`[Pipeline] ${n} ${e} - ${t.strategyName}: ${t.reason}`)}}}var VERBOSE_RESULTS,Pipeline,init_Pipeline=__esm({"src/core/navigators/Pipeline.ts"(){init_navigators(),init_logger(),init_orchestration(),init_PipelineDebugger(),init_diversityRerank(),VERBOSE_RESULTS=!0,Pipeline=class extends ContentNavigator{constructor(e,t,n,r){super(),_defineProperty(this,`generator`,void 0),_defineProperty(this,`filters`,void 0),_defineProperty(this,`_cachedOrchestration`,null),_defineProperty(this,`_tagCache`,new Map),_defineProperty(this,`_ephemeralHints`,null),this.generator=e,this.filters=t,this.user=n,this.course=r,r.getCourseConfig().then(e=>{logger.debug(`[pipeline] Crated pipeline for ${e.name}`)}).catch(e=>{logger.error(`[pipeline] Failed to lookup courseCfg: ${e}`)}),logPipelineConfig(e,t),registerPipelineForDebug(this)}setEphemeralHints(e){this._ephemeralHints=e,logger.info(`[Pipeline] Ephemeral hints set: ${JSON.stringify(e)}`)}async getWeightedCards(e){let t=performance.now(),n=await this.buildContext(),r=performance.now(),a=500;logger.debug(`[Pipeline] Fetching 500 candidates from generator '${this.generator.name}'`);let o=await this.generator.getWeightedCards(500,n),s=o.cards,c=performance.now(),l=s.length;this._ephemeralHints=mergeHints2([this._ephemeralHints,o.hints])??null;let u;if(this.generator.generators){let e=new Map;for(let t of s){let n=t.provenance[0];if(n){let r=n.strategyName;e.has(r)||e.set(r,{cards:[]}),e.get(r).cards.push(t)}}u=Array.from(e.entries()).map(([e,t])=>{let n=t.cards.filter(e=>e.provenance[0]?.reason?.includes(`new card`)),r=t.cards.filter(e=>e.provenance[0]?.reason?.includes(`review`));return{name:e,cardCount:t.cards.length,newCount:n.length,reviewCount:r.length,topScore:Math.max(...t.cards.map(e=>e.score),0)}})}logger.debug(`[Pipeline] Generator returned ${l} candidates`),s=await this.hydrateTags(s);let d=performance.now(),p=[...s],m=this._ephemeralHints;if(m?.requireCards?.length){let e=new Set(p.map(e=>e.cardId)),t=m.requireCards.filter(t=>!t.includes(`*`)&&!e.has(t));if(t.length>0){let e=await this.course.getAppliedTagsBatch(t),n=this.course.getCourseID();for(let r of t)p.push({cardId:r,courseId:n,score:1,tags:e.get(r)??[],provenance:[]});logger.info(`[Pipeline] Pre-fetched ${t.length} required card(s) into pool: ${t.join(`, `)}`)}}let g=new Set(s.filter(e=>e.provenance.some(e=>e.strategy===`prescribed`)).map(e=>e.cardId)),_=[];for(let e of this.filters){let t=s.length,r=new Map(s.map(e=>[e.cardId,e.score]));s=await e.transform(s,n);let a=0,o=0,c=0,l=t-s.length;for(let e of s){let t=r.get(e.cardId)??0;e.score>t?a++:e.score<t?o++:c++}if(_.push({name:e.name,boosted:a,penalized:o,passed:c,removed:l}),g.size>0){let t=new Set(s.map(e=>e.cardId)),n=[...g].filter(e=>!t.has(e)),r=s.filter(e=>g.has(e.cardId)&&e.score===0).map(e=>e.cardId);(n.length>0||r.length>0)&&(logger.info(`[Pipeline] Filter '${e.name}' impact on prescribed cards: `+(n.length>0?`removed=[${n.join(`, `)}] `:``)+(r.length>0?`zeroed=[${r.join(`, `)}]`:``)),n.forEach(e=>g.delete(e)))}logger.debug(`[Pipeline] Filter '${e.name}': ${r.size} \u2192 ${s.length} cards (\u2191${a} \u2193${o} =${c})`)}s=s.filter(e=>e.score>0);let v=this._ephemeralHints;v&&(this._ephemeralHints=null,s=this.applyHints(s,v,p)),s=diversityRerank(s),s.sort((e,t)=>t.score-e.score);let y=performance.now(),b=s.slice(0,e);logger.info(`[Pipeline:timing] total=${(y-t).toFixed(0)}ms (context=${(r-t).toFixed(0)} generate=${(c-r).toFixed(0)} hydrate=${(d-c).toFixed(0)} filter=${(y-d).toFixed(0)})`);let x=b.slice(0,3).map(e=>e.score);logExecutionSummary(this.generator.name,l,this.filters.length,b.length,x,_),logResultCards(b),logCardProvenance(b,3);try{let e=await this.course?.getCourseConfig().then(e=>e.name).catch(()=>void 0);captureRun(buildRunReport(this.course?.getCourseID()||`unknown`,e,this.generator.name,u,l,_,s,b,n.userElo,v??void 0))}catch(e){logger.debug(`[Pipeline] Failed to capture debug run: ${e}`)}return{cards:b}}async hydrateTags(e){if(e.length===0)return e;let t=[];for(let n of e)this._tagCache.has(n.cardId)||t.push(n.cardId);if(t.length>0){let e=await this.course.getAppliedTagsBatch(t);for(let[t,n]of e)this._tagCache.set(t,n)}let n=new Map;for(let t of e)n.set(t.cardId,this._tagCache.get(t.cardId)??[]);return logTagHydration(e,n),e.map(e=>({...e,tags:this._tagCache.get(e.cardId)??[]}))}applyHints(e,t,n){let r=e.length;if(t.excludeCards?.length&&(e=e.filter(e=>!t.excludeCards.some(t=>globMatch(e.cardId,t)))),t.excludeTags?.length&&(e=e.filter(e=>!t.excludeTags.some(t=>cardMatchesTagPattern(e,t)))),t.boostTags)for(let[n,r]of Object.entries(t.boostTags))for(let a of e)cardMatchesTagPattern(a,n)&&(a.score*=r,a.provenance.push({strategy:`ephemeralHint`,strategyId:`ephemeral-hint`,strategyName:t._label?`Replan Hint (${t._label})`:`Replan Hint`,action:`boosted`,score:a.score,reason:`boostTag ${n} \xD7${r}`}));if(t.boostCards)for(let[n,r]of Object.entries(t.boostCards))for(let a of e)globMatch(a.cardId,n)&&(a.score*=r,a.provenance.push({strategy:`ephemeralHint`,strategyId:`ephemeral-hint`,strategyName:t._label?`Replan Hint (${t._label})`:`Replan Hint`,action:`boosted`,score:a.score,reason:`boostCard ${n} \xD7${r}`}));let a=new Set(e.map(e=>e.cardId)),o=new Map(e.map(e=>[e.cardId,e])),s=t._label?`Replan Hint (${t._label})`:`Replan Hint`,applyRequirement=(t,n)=>{let r=1/0,c=o.get(t.cardId);c?c.score<r&&(c.score=r,c.provenance.push({strategy:`ephemeralHint`,strategyId:`ephemeral-hint`,strategyName:s,action:`boosted`,score:r,reason:`${n} (upgrade to mandatory score)`})):(e.push({...t,score:r,provenance:[...t.provenance,{strategy:`ephemeralHint`,strategyId:`ephemeral-hint`,strategyName:s,action:`boosted`,score:r,reason:n}]}),a.add(t.cardId),o.set(t.cardId,e[e.length-1]))};if(t.requireCards?.length)for(let e of t.requireCards){for(let t of a)globMatch(t,e)&&applyRequirement(o.get(t),`requireCard ${e}`);for(let t of n)globMatch(t.cardId,e)&&applyRequirement(t,`requireCard ${e}`)}if(t.requireTags?.length)for(let e of t.requireTags){for(let t of a){let n=o.get(t);cardMatchesTagPattern(n,e)&&applyRequirement(n,`requireTag ${e}`)}for(let t of n)cardMatchesTagPattern(t,e)&&applyRequirement(t,`requireTag ${e}`)}return logger.info(`[Pipeline] Hints applied: ${r} \u2192 ${e.length} cards`),e}async buildContext(){let e=1e3;try{e=toCourseElo((await this.user.getCourseRegDoc(this.course.getCourseID())).elo).global.score}catch(e){logger.debug(`[Pipeline] Could not get user ELO, using default: ${e}`)}this._cachedOrchestration||(this._cachedOrchestration=await createOrchestrationContext(this.user,this.course));let t=this._cachedOrchestration;return{user:this.user,course:this.course,userElo:e,orchestration:t}}getCourseID(){return this.course.getCourseID()}async getOrchestrationContext(){return createOrchestrationContext(this.user,this.course)}getStrategyIds(){let e=[],extractId=e=>e.strategyId?e.strategyId:null,t=extractId(this.generator);t&&e.push(t),this.generator.generators&&Array.isArray(this.generator.generators)&&this.generator.generators.forEach(t=>{let n=extractId(t);n&&e.push(n)});for(let t of this.filters){let n=extractId(t);n&&e.push(n)}return[...new Set(e)]}async getTagEloStatus(e){let t=toCourseElo((await this.user.getCourseRegDoc(this.course.getCourseID())).elo),n={};if(e){let r=Array.isArray(e)?e:[e];for(let e of r){let r=globToRegex(e);for(let[e,a]of Object.entries(t.tags))r.test(e)&&(n[e]={score:a.score,count:a.count})}}else for(let[e,r]of Object.entries(t.tags))n[e]={score:r.score,count:r.count};return n}async forecast(e){let t=e?.threshold??.1,n=e?.unseenOnly??!0,r=this.course.getCourseID(),a=(await this.course.getAllCardIds()).map(e=>({cardId:e,courseId:r,score:1,provenance:[]}));a=await this.hydrateTags(a);let o=a.slice(),s=await this.buildContext();for(let e of this.filters)a=await e.transform(a,s);if(e?.hints&&(a=this.applyHints(a,e.hints,o)),a=a.filter(e=>e.score>=t),n){let e;try{e=new Set(await this.user.getSeenCards(r))}catch{e=new Set}a=a.filter(t=>!e.has(t.cardId))}return a.sort((e,t)=>t.score-e.score),e?.limit?a.slice(0,e.limit):a}async diagnoseCardSpace(e){let t=e?.threshold??.1,n=performance.now(),r=await this.course.getAllCardIds(),a=r.map(e=>({cardId:e,courseId:this.course.getCourseID(),score:1,provenance:[]}));a=await this.hydrateTags(a);let o=await this.buildContext(),s=[];for(let e of this.filters){a=await e.transform(a,o);let n=a.filter(e=>e.score>=t).length;s.push({name:e.name,wellIndicated:n})}let c=a.filter(e=>e.score>=t),l=new Set(c.map(e=>e.cardId)),u;try{let e=this.course.getCourseID(),t=await this.user.getSeenCards(e);u=new Set(t)}catch{u=new Set}let d=c.filter(e=>!u.has(e.cardId)),p=new Map;for(let e of a){let n=e.cardId.split(`-`)[1]||`unknown`;p.has(n)||p.set(n,{total:0,wellIndicated:0,new:0});let r=p.get(n);r.total++,e.score>=t&&(r.wellIndicated++,u.has(e.cardId)||r.new++)}let m=performance.now()-n,g={totalCards:r.length,threshold:t,wellIndicated:l.size,encountered:u.size,wellIndicatedNew:d.length,byType:Object.fromEntries(p),filterBreakdown:s,elapsedMs:Math.round(m)};logger.info(`[Pipeline:diagnose] Card space scan (${g.elapsedMs}ms):`),logger.info(`[Pipeline:diagnose] Total cards: ${g.totalCards}`),logger.info(`[Pipeline:diagnose] Well-indicated (score >= ${t}): ${g.wellIndicated}`),logger.info(`[Pipeline:diagnose] Encountered: ${g.encountered}`),logger.info(`[Pipeline:diagnose] Well-indicated & new: ${g.wellIndicatedNew}`),logger.info(`[Pipeline:diagnose] By type:`);for(let[e,t]of p)logger.info(`[Pipeline:diagnose] ${e}: ${t.wellIndicated}/${t.total} well-indicated, ${t.new} new`);logger.info(`[Pipeline:diagnose] After each filter:`);for(let e of s)logger.info(`[Pipeline:diagnose] ${e.name}: ${e.wellIndicated} well-indicated`);return g}}}}),defaults_exports={};__export(defaults_exports,{createDefaultEloStrategy:()=>createDefaultEloStrategy,createDefaultPipeline:()=>createDefaultPipeline,createDefaultSrsStrategy:()=>createDefaultSrsStrategy});function createDefaultEloStrategy(e){return{_id:`NAVIGATION_STRATEGY-ELO-default`,docType:`NAVIGATION_STRATEGY`,name:`ELO (default)`,description:`Default ELO-based navigation strategy for new cards`,implementingClass:`elo`,course:e,serializedData:``}}function createDefaultSrsStrategy(e){return{_id:`NAVIGATION_STRATEGY-SRS-default`,docType:`NAVIGATION_STRATEGY`,name:`SRS (default)`,description:`Default SRS-based navigation strategy for reviews`,implementingClass:`srs`,course:e,serializedData:``}}function createDefaultPipeline(e,t){let n=t.getCourseID(),r=new ELONavigator(e,t,createDefaultEloStrategy(n)),a=new SRSNavigator(e,t,createDefaultSrsStrategy(n)),o=new CompositeGenerator([r,a]),s=createEloDistanceFilter();return new Pipeline(o,[s],e,t)}var init_defaults=__esm({"src/core/navigators/defaults.ts"(){init_navigators(),init_Pipeline(),init_CompositeGenerator(),init_elo(),init_srs(),init_eloDistance(),init_types_legacy()}}),PipelineAssembler_exports={};__export(PipelineAssembler_exports,{PipelineAssembler:()=>PipelineAssembler});var PipelineAssembler,init_PipelineAssembler=__esm({"src/core/navigators/PipelineAssembler.ts"(){init_navigators(),init_WeightedFilter(),init_Pipeline(),init_logger(),init_CompositeGenerator(),init_defaults(),PipelineAssembler=class{async assemble(e){let{strategies:t,user:n,course:r}=e,a=[];if(t.length===0)return{pipeline:null,generatorStrategies:[],filterStrategies:[],warnings:a};let o=[],s=[];for(let e of t)isGenerator(e.implementingClass)?o.push(e):isFilter(e.implementingClass)?s.push(e):a.push(`Unknown strategy type '${e.implementingClass}', skipping: ${e.name}`);let c=r.getCourseID(),l=o.some(e=>e.implementingClass===`elo`),u=o.some(e=>e.implementingClass===`srs`);if(l||(logger.debug(`[PipelineAssembler] No ELO generator configured, adding default`),o.push(createDefaultEloStrategy(c))),u||(logger.debug(`[PipelineAssembler] No SRS generator configured, adding default`),o.push(createDefaultSrsStrategy(c))),o.length===0)return a.push(`No generator strategy found`),{pipeline:null,generatorStrategies:[],filterStrategies:[],warnings:a};let d;o.length===1?(d=await ContentNavigator.create(n,r,o[0]),logger.debug(`[PipelineAssembler] Using single generator: ${o[0].name}`)):(logger.debug(`[PipelineAssembler] Using CompositeGenerator for ${o.length} generators: ${o.map(e=>e.name).join(`, `)}`),d=await CompositeGenerator.fromStrategies(n,r,o));let p=[],m=[...s].sort((e,t)=>e.name.localeCompare(t.name));for(let e of m)try{let t=await ContentNavigator.create(n,r,e);if(`transform`in t&&typeof t.transform==`function`){let n=t;e.learnable&&(n=new WeightedFilter(n,e.learnable,e.staticWeight,e._id)),p.push(n),logger.debug(`[PipelineAssembler] Added filter: ${e.name}`)}else a.push(`Filter '${e.name}' does not implement CardFilter.transform(), skipping`)}catch(t){a.push(`Failed to instantiate filter '${e.name}': ${t}`)}let g=new Pipeline(d,p,n,r);return logger.debug(`[PipelineAssembler] Assembled pipeline with ${o.length} generator(s) and ${p.length} filter(s)`),{pipeline:g,generatorStrategies:o,filterStrategies:m,warnings:a}}}}}),globImport,init_3=__esm({'import("./**/*") in src/core/navigators/index.ts'(){globImport=__glob({"./Pipeline.ts":()=>Promise.resolve().then(()=>(init_Pipeline(),Pipeline_exports)),"./PipelineAssembler.ts":()=>Promise.resolve().then(()=>(init_PipelineAssembler(),PipelineAssembler_exports)),"./PipelineDebugger.ts":()=>Promise.resolve().then(()=>(init_PipelineDebugger(),PipelineDebugger_exports)),"./SrsDebugger.ts":()=>Promise.resolve().then(()=>(init_SrsDebugger(),SrsDebugger_exports)),"./StrategyPressureDebugger.ts":()=>Promise.resolve().then(()=>(init_StrategyPressureDebugger(),StrategyPressureDebugger_exports)),"./defaults.ts":()=>Promise.resolve().then(()=>(init_defaults(),defaults_exports)),"./diversityRerank.ts":()=>Promise.resolve().then(()=>(init_diversityRerank(),diversityRerank_exports)),"./filters/WeightedFilter.ts":()=>Promise.resolve().then(()=>(init_WeightedFilter(),WeightedFilter_exports)),"./filters/eloDistance.ts":()=>Promise.resolve().then(()=>(init_eloDistance(),eloDistance_exports)),"./filters/hierarchyDefinition.ts":()=>Promise.resolve().then(()=>(init_hierarchyDefinition(),hierarchyDefinition_exports)),"./filters/index.ts":()=>Promise.resolve().then(()=>(init_filters(),filters_exports)),"./filters/inferredPreferenceStub.ts":()=>Promise.resolve().then(()=>(init_inferredPreferenceStub(),inferredPreferenceStub_exports)),"./filters/interferenceMitigator.ts":()=>Promise.resolve().then(()=>(init_interferenceMitigator(),interferenceMitigator_exports)),"./filters/relativePriority.ts":()=>Promise.resolve().then(()=>(init_relativePriority(),relativePriority_exports)),"./filters/types.ts":()=>Promise.resolve().then(()=>(init_types2(),types_exports2)),"./filters/userGoalStub.ts":()=>Promise.resolve().then(()=>(init_userGoalStub(),userGoalStub_exports)),"./filters/userTagPreference.ts":()=>Promise.resolve().then(()=>(init_userTagPreference(),userTagPreference_exports)),"./generators/CompositeGenerator.ts":()=>Promise.resolve().then(()=>(init_CompositeGenerator(),CompositeGenerator_exports)),"./generators/elo.ts":()=>Promise.resolve().then(()=>(init_elo(),elo_exports)),"./generators/index.ts":()=>Promise.resolve().then(()=>(init_generators(),generators_exports)),"./generators/prescribed.ts":()=>Promise.resolve().then(()=>(init_prescribed(),prescribed_exports)),"./generators/srs.ts":()=>Promise.resolve().then(()=>(init_srs(),srs_exports)),"./generators/types.ts":()=>Promise.resolve().then(()=>(init_types(),types_exports)),"./index.ts":()=>Promise.resolve().then(()=>(init_navigators(),navigators_exports))})}}),navigators_exports={};__export(navigators_exports,{ContentNavigator:()=>ContentNavigator,DIVERSITY_FLOOR:()=>DIVERSITY_FLOOR,DIVERSITY_STRENGTH:()=>DIVERSITY_STRENGTH,NavigatorRole:()=>NavigatorRole,NavigatorRoles:()=>NavigatorRoles,Navigators:()=>Navigators,captureStrategyPressure:()=>captureStrategyPressure,clearSrsBacklogDebug:()=>clearSrsBacklogDebug,clearStrategyPressureDebug:()=>clearStrategyPressureDebug,diversityRerank:()=>diversityRerank,drainCapturedRuns:()=>drainCapturedRuns,getActivePipeline:()=>getActivePipeline,getCardOrigin:()=>getCardOrigin,getRegisteredNavigator:()=>getRegisteredNavigator,getRegisteredNavigatorNames:()=>getRegisteredNavigatorNames,getRegisteredNavigatorRole:()=>getRegisteredNavigatorRole,getRunsForSession:()=>getRunsForSession,getSrsBacklogDebug:()=>getSrsBacklogDebug,getStrategyPressureDebug:()=>getStrategyPressureDebug,hasRegisteredNavigator:()=>hasRegisteredNavigator,initializeNavigatorRegistry:()=>initializeNavigatorRegistry,isFilter:()=>isFilter,isGenerator:()=>isGenerator,mountPipelineDebugger:()=>mountPipelineDebugger,pipelineDebugAPI:()=>pipelineDebugAPI,registerNavigator:()=>registerNavigator,setDebugSessionId:()=>setDebugSessionId});function registerNavigator(e,t,n){navigatorRegistry.set(e,{constructor:t,role:n}),logger.debug(`[NavigatorRegistry] Registered: ${e}${n?` (${n})`:``}`)}function getRegisteredNavigator(e){return navigatorRegistry.get(e)?.constructor}function hasRegisteredNavigator(e){return navigatorRegistry.has(e)}function getRegisteredNavigatorRole(e){return navigatorRegistry.get(e)?.role}function getRegisteredNavigatorNames(){return Array.from(navigatorRegistry.keys())}async function initializeNavigatorRegistry(){logger.debug(`[NavigatorRegistry] Initializing built-in navigators...`);let[e,t]=await Promise.all([Promise.resolve().then(()=>(init_elo(),elo_exports)),Promise.resolve().then(()=>(init_srs(),srs_exports))]),n=await Promise.resolve().then(()=>(init_prescribed(),prescribed_exports));registerNavigator(`elo`,e.default),registerNavigator(`srs`,t.default),registerNavigator(`prescribed`,n.default);let[r,a,o,s]=await Promise.all([Promise.resolve().then(()=>(init_hierarchyDefinition(),hierarchyDefinition_exports)),Promise.resolve().then(()=>(init_interferenceMitigator(),interferenceMitigator_exports)),Promise.resolve().then(()=>(init_relativePriority(),relativePriority_exports)),Promise.resolve().then(()=>(init_userTagPreference(),userTagPreference_exports))]);registerNavigator(`hierarchyDefinition`,r.default),registerNavigator(`interferenceMitigator`,a.default),registerNavigator(`relativePriority`,o.default),registerNavigator(`userTagPreference`,s.default),logger.debug(`[NavigatorRegistry] Initialized ${navigatorRegistry.size} navigators: ${getRegisteredNavigatorNames().join(`, `)}`)}function getCardOrigin(e){if(e.provenance.length===0)throw Error(`Card has no provenance - cannot determine origin`);let t=e.provenance[0].reason.toLowerCase();return t.includes(`failed`)?`failed`:t.includes(`review`)?`review`:`new`}function isGenerator(e){return NavigatorRoles[e]===`generator`?!0:getRegisteredNavigatorRole(e)===`generator`}function isFilter(e){return NavigatorRoles[e]===`filter`?!0:getRegisteredNavigatorRole(e)===`filter`}var navigatorRegistry,Navigators,NavigatorRole,NavigatorRoles,ContentNavigator,init_navigators=__esm({"src/core/navigators/index.ts"(){init_diversityRerank(),init_PipelineDebugger(),init_SrsDebugger(),init_StrategyPressureDebugger(),init_logger(),init_(),init_2(),init_3(),navigatorRegistry=new Map,Navigators=(e=>(e.ELO=`elo`,e.SRS=`srs`,e.PRESCRIBED=`prescribed`,e.HIERARCHY=`hierarchyDefinition`,e.INTERFERENCE=`interferenceMitigator`,e.RELATIVE_PRIORITY=`relativePriority`,e.USER_TAG_PREFERENCE=`userTagPreference`,e))(Navigators||{}),NavigatorRole=(e=>(e.GENERATOR=`generator`,e.FILTER=`filter`,e))(NavigatorRole||{}),NavigatorRoles={elo:`generator`,srs:`generator`,prescribed:`generator`,hierarchyDefinition:`filter`,interferenceMitigator:`filter`,relativePriority:`filter`,userTagPreference:`filter`},ContentNavigator=class{constructor(e,t,n){_defineProperty(this,`user`,void 0),_defineProperty(this,`course`,void 0),_defineProperty(this,`strategyName`,void 0),_defineProperty(this,`strategyId`,void 0),_defineProperty(this,`learnable`,void 0),_defineProperty(this,`staticWeight`,void 0),this.user=e,this.course=t,n&&(this.strategyName=n.name,this.strategyId=n._id,this.learnable=n.learnable,this.staticWeight=n.staticWeight)}get strategyKey(){return this.constructor.name}async getStrategyState(){if(!this.user||!this.course)throw Error(`Cannot get strategy state: navigator not properly initialized. Ensure user and course are provided to constructor.`);return this.user.getStrategyState(this.course.getCourseID(),this.strategyKey)}async putStrategyState(e){if(!this.user||!this.course)throw Error(`Cannot put strategy state: navigator not properly initialized. Ensure user and course are provided to constructor.`);return this.user.putStrategyState(this.course.getCourseID(),this.strategyKey,e)}static async create(e,t,n){let r=n.implementingClass,a=getRegisteredNavigator(r);if(a)return logger.debug(`[ContentNavigator.create] Using registered navigator: ${r}`),new a(e,t,n);logger.debug(`[ContentNavigator.create] Navigator not in registry, attempting dynamic import: ${r}`);let o;for(let e of[`.ts`,`.js`,``]){try{if(o=(await globImport_generators(`./generators/${r}${e}`)).default,o)break}catch(t){logger.debug(`Failed to load generator ${r}${e}:`,t)}try{if(o=(await globImport_filters(`./filters/${r}${e}`)).default,o)break}catch(t){logger.debug(`Failed to load filter ${r}${e}:`,t)}try{if(o=(await globImport(`./${r}${e}`)).default,o)break}catch(t){logger.debug(`Failed to load legacy ${r}${e}:`,t)}if(o)break}if(!o)throw Error(`Could not load navigator implementation for: ${r}`);return new o(e,t,n)}async getWeightedCards(e){throw Error(`${this.constructor.name} must implement getWeightedCards(). `)}setEphemeralHints(e){}}}});function randIntWeightedTowardZero(e){return Math.floor(Math.random()*Math.random()*Math.random()*e)}async function getCourseTagStubs(e){logger.debug(`Getting tag stubs for course: ${e}`);let t=await filterAllDocsByPrefix2(getCourseDB2(e),`TAG`.valueOf()+`-`);return t.rows.forEach(e=>{logger.debug(` Tag stub for doc: ${e.id}`)}),t}async function createTag(e,t,n){logger.debug(`Creating tag: ${t}...`);let r=getTagID(t);return await getCourseDB2(e).put({course:e,docType:`TAG`,name:t,snippet:``,taggedCards:[],wiki:``,author:n,_id:r})}async function updateTag(e){let t=await getTag(e.course,e.name);return await getCourseDB2(e.course).put({...e,_rev:t._rev})}async function getTag(e,t){let n=getTagID(t);return getCourseDB2(e).get(n)}async function removeTagFromCard(e,t,n){n=getTagID(n);let r=getCourseDB2(e),a=await r.get(n);return a.taggedCards=a.taggedCards.filter(e=>t!==e),r.put(a)}async function getAppliedTags(e,t){return await getCourseDB2(e).query(`getTags`,{startkey:t,endkey:t})}async function updateCredentialledCourseConfig(e,t){logger.debug(`Updating course config:
|
|
254
|
+
💡 Inspect: window.skuilder.pipeline`)}function logResultCards(e){if(!(!VERBOSE_RESULTS||e.length===0)){logger.info(`[Pipeline] Results (${e.length} cards):`);for(let t=0;t<e.length;t++){let n=e[t],r=n.tags?.slice(0,3).join(`, `)||``,a=n.provenance.filter(e=>e.strategy===`hierarchyDefinition`||e.strategy===`priorityDefinition`||e.strategy===`interferenceFilter`||e.strategy===`letterGating`||e.strategy===`ephemeralHint`||e.strategy===`diversityRerank`).map(e=>{let t=e.action===`boosted`?`↑`:e.action===`penalized`?`↓`:`=`;return`${e.strategyName}${t}${e.score.toFixed(2)}`}).join(` | `);logger.info(`[Pipeline] ${String(t+1).padStart(2)}. ${n.score.toFixed(4)} ${n.cardId} [${r}]${a?` {${a}}`:``}`)}}}function logCardProvenance(e,t=3){let n=e.slice(0,t);logger.debug(`[Pipeline] Provenance for top ${n.length} cards:`);for(let e of n){logger.debug(`[Pipeline] ${e.cardId} (final score: ${e.score.toFixed(3)}):`);for(let t of e.provenance){let e=t.score.toFixed(3),n=t.action.padEnd(9);logger.debug(`[Pipeline] ${n} ${e} - ${t.strategyName}: ${t.reason}`)}}}var VERBOSE_RESULTS,Pipeline,init_Pipeline=__esm({"src/core/navigators/Pipeline.ts"(){init_navigators(),init_logger(),init_orchestration(),init_PipelineDebugger(),init_diversityRerank(),VERBOSE_RESULTS=!0,Pipeline=class extends ContentNavigator{constructor(e,t,n,r){super(),_defineProperty(this,`generator`,void 0),_defineProperty(this,`filters`,void 0),_defineProperty(this,`_cachedOrchestration`,null),_defineProperty(this,`_tagCache`,new Map),_defineProperty(this,`_ephemeralHints`,null),this.generator=e,this.filters=t,this.user=n,this.course=r,r.getCourseConfig().then(e=>{logger.debug(`[pipeline] Crated pipeline for ${e.name}`)}).catch(e=>{logger.error(`[pipeline] Failed to lookup courseCfg: ${e}`)}),logPipelineConfig(e,t),registerPipelineForDebug(this)}setEphemeralHints(e){this._ephemeralHints=e,logger.info(`[Pipeline] Ephemeral hints set: ${JSON.stringify(e)}`)}async getWeightedCards(e){let t=performance.now(),n=await this.buildContext(),r=performance.now(),a=500;logger.debug(`[Pipeline] Fetching 500 candidates from generator '${this.generator.name}'`);let o=await this.generator.getWeightedCards(500,n),s=o.cards,c=performance.now(),l=s.length;this._ephemeralHints=mergeHints2([this._ephemeralHints,o.hints])??null;let u;if(this.generator.generators){let e=new Map;for(let t of s){let n=t.provenance[0];if(n){let r=n.strategyName;e.has(r)||e.set(r,{cards:[]}),e.get(r).cards.push(t)}}u=Array.from(e.entries()).map(([e,t])=>{let n=t.cards.filter(e=>e.provenance[0]?.reason?.includes(`new card`)),r=t.cards.filter(e=>e.provenance[0]?.reason?.includes(`review`));return{name:e,cardCount:t.cards.length,newCount:n.length,reviewCount:r.length,topScore:Math.max(...t.cards.map(e=>e.score),0)}})}logger.debug(`[Pipeline] Generator returned ${l} candidates`),s=await this.hydrateTags(s);let d=performance.now(),p=[...s],m=this._ephemeralHints;if(m?.requireCards?.length){let e=new Set(p.map(e=>e.cardId)),t=m.requireCards.filter(t=>!t.includes(`*`)&&!e.has(t));if(t.length>0){let e=await this.course.getAppliedTagsBatch(t),n=this.course.getCourseID();for(let r of t)p.push({cardId:r,courseId:n,score:1,tags:e.get(r)??[],provenance:[]});logger.info(`[Pipeline] Pre-fetched ${t.length} required card(s) into pool: ${t.join(`, `)}`)}}let g=new Set(s.filter(e=>e.provenance.some(e=>e.strategy===`prescribed`)).map(e=>e.cardId)),_=[];for(let e of this.filters){let t=s.length,r=new Map(s.map(e=>[e.cardId,e.score]));s=await e.transform(s,n);let a=0,o=0,c=0,l=t-s.length;for(let e of s){let t=r.get(e.cardId)??0;e.score>t?a++:e.score<t?o++:c++}if(_.push({name:e.name,boosted:a,penalized:o,passed:c,removed:l}),g.size>0){let t=new Set(s.map(e=>e.cardId)),n=[...g].filter(e=>!t.has(e)),r=s.filter(e=>g.has(e.cardId)&&e.score===0).map(e=>e.cardId);(n.length>0||r.length>0)&&(logger.info(`[Pipeline] Filter '${e.name}' impact on prescribed cards: `+(n.length>0?`removed=[${n.join(`, `)}] `:``)+(r.length>0?`zeroed=[${r.join(`, `)}]`:``)),n.forEach(e=>g.delete(e)))}logger.debug(`[Pipeline] Filter '${e.name}': ${r.size} \u2192 ${s.length} cards (\u2191${a} \u2193${o} =${c})`)}s=s.filter(e=>e.score>0);let v=this._ephemeralHints;v&&(this._ephemeralHints=null,s=this.applyHints(s,v,p)),s=diversityRerank(s),s.sort((e,t)=>t.score-e.score);let y=performance.now(),b=s.slice(0,e);logger.info(`[Pipeline:timing] total=${(y-t).toFixed(0)}ms (context=${(r-t).toFixed(0)} generate=${(c-r).toFixed(0)} hydrate=${(d-c).toFixed(0)} filter=${(y-d).toFixed(0)})`);let x=b.slice(0,3).map(e=>e.score);logExecutionSummary(this.generator.name,l,this.filters.length,b.length,x,_),logResultCards(b),logCardProvenance(b,3);try{let e=await this.course?.getCourseConfig().then(e=>e.name).catch(()=>void 0);captureRun(buildRunReport(this.course?.getCourseID()||`unknown`,e,this.generator.name,u,l,_,s,b,n.userElo,v??void 0))}catch(e){logger.debug(`[Pipeline] Failed to capture debug run: ${e}`)}return{cards:b}}async hydrateTags(e){if(e.length===0)return e;let t=[];for(let n of e)this._tagCache.has(n.cardId)||t.push(n.cardId);if(t.length>0){let e=await this.course.getAppliedTagsBatch(t);for(let[t,n]of e)this._tagCache.set(t,n)}let n=new Map;for(let t of e)n.set(t.cardId,this._tagCache.get(t.cardId)??[]);return logTagHydration(e,n),e.map(e=>({...e,tags:this._tagCache.get(e.cardId)??[]}))}applyHints(e,t,n){let r=e.length;if(t.excludeCards?.length&&(e=e.filter(e=>!t.excludeCards.some(t=>globMatch(e.cardId,t)))),t.excludeTags?.length&&(e=e.filter(e=>!t.excludeTags.some(t=>cardMatchesTagPattern(e,t)))),t.boostTags)for(let[n,r]of Object.entries(t.boostTags))for(let a of e)cardMatchesTagPattern(a,n)&&(a.score*=r,a.provenance.push({strategy:`ephemeralHint`,strategyId:`ephemeral-hint`,strategyName:t._label?`Replan Hint (${t._label})`:`Replan Hint`,action:`boosted`,score:a.score,reason:`boostTag ${n} \xD7${r}`}));if(t.boostCards)for(let[n,r]of Object.entries(t.boostCards))for(let a of e)globMatch(a.cardId,n)&&(a.score*=r,a.provenance.push({strategy:`ephemeralHint`,strategyId:`ephemeral-hint`,strategyName:t._label?`Replan Hint (${t._label})`:`Replan Hint`,action:`boosted`,score:a.score,reason:`boostCard ${n} \xD7${r}`}));let a=new Set(e.map(e=>e.cardId)),o=new Map(e.map(e=>[e.cardId,e])),s=t._label?`Replan Hint (${t._label})`:`Replan Hint`,applyRequirement=(t,n)=>{let r=1/0,c=o.get(t.cardId);c?c.score<r&&(c.score=r,c.provenance.push({strategy:`ephemeralHint`,strategyId:`ephemeral-hint`,strategyName:s,action:`boosted`,score:r,reason:`${n} (upgrade to mandatory score)`})):(e.push({...t,score:r,provenance:[...t.provenance,{strategy:`ephemeralHint`,strategyId:`ephemeral-hint`,strategyName:s,action:`boosted`,score:r,reason:n}]}),a.add(t.cardId),o.set(t.cardId,e[e.length-1]))};if(t.requireCards?.length)for(let e of t.requireCards){for(let t of a)globMatch(t,e)&&applyRequirement(o.get(t),`requireCard ${e}`);for(let t of n)globMatch(t.cardId,e)&&applyRequirement(t,`requireCard ${e}`)}if(t.requireTags?.length)for(let e of t.requireTags){for(let t of a){let n=o.get(t);cardMatchesTagPattern(n,e)&&applyRequirement(n,`requireTag ${e}`)}for(let t of n)cardMatchesTagPattern(t,e)&&applyRequirement(t,`requireTag ${e}`)}return logger.info(`[Pipeline] Hints applied: ${r} \u2192 ${e.length} cards`),e}async buildContext(){let e=1e3;try{e=toCourseElo((await this.user.getCourseRegDoc(this.course.getCourseID())).elo).global.score}catch(e){logger.debug(`[Pipeline] Could not get user ELO, using default: ${e}`)}this._cachedOrchestration||(this._cachedOrchestration=await createOrchestrationContext(this.user,this.course));let t=this._cachedOrchestration;return{user:this.user,course:this.course,userElo:e,orchestration:t}}getCourseID(){return this.course.getCourseID()}async getOrchestrationContext(){return createOrchestrationContext(this.user,this.course)}getStrategyIds(){let e=[],extractId=e=>e.strategyId?e.strategyId:null,t=extractId(this.generator);t&&e.push(t),this.generator.generators&&Array.isArray(this.generator.generators)&&this.generator.generators.forEach(t=>{let n=extractId(t);n&&e.push(n)});for(let t of this.filters){let n=extractId(t);n&&e.push(n)}return[...new Set(e)]}async getTagEloStatus(e){let t=toCourseElo((await this.user.getCourseRegDoc(this.course.getCourseID())).elo),n={};if(e){let r=Array.isArray(e)?e:[e];for(let e of r){let r=globToRegex(e);for(let[e,a]of Object.entries(t.tags))r.test(e)&&(n[e]={score:a.score,count:a.count})}}else for(let[e,r]of Object.entries(t.tags))n[e]={score:r.score,count:r.count};return n}async forecast(e){let t=e?.threshold??.1,n=e?.unseenOnly??!0,r=this.course.getCourseID(),a=(await this.course.getAllCardIds()).map(e=>({cardId:e,courseId:r,score:1,provenance:[]}));a=await this.hydrateTags(a);let o=a.slice(),s=await this.buildContext();for(let e of this.filters)a=await e.transform(a,s);if(e?.hints&&(a=this.applyHints(a,e.hints,o)),a=a.filter(e=>e.score>=t),n){let e;try{e=new Set(await this.user.getSeenCards(r))}catch{e=new Set}a=a.filter(t=>!e.has(t.cardId))}return a.sort((e,t)=>t.score-e.score),e?.limit?a.slice(0,e.limit):a}async diagnoseCardSpace(e){let t=e?.threshold??.1,n=performance.now(),r=await this.course.getAllCardIds(),a=r.map(e=>({cardId:e,courseId:this.course.getCourseID(),score:1,provenance:[]}));a=await this.hydrateTags(a);let o=await this.buildContext(),s=[];for(let e of this.filters){a=await e.transform(a,o);let n=a.filter(e=>e.score>=t).length;s.push({name:e.name,wellIndicated:n})}let c=a.filter(e=>e.score>=t),l=new Set(c.map(e=>e.cardId)),u;try{let e=this.course.getCourseID(),t=await this.user.getSeenCards(e);u=new Set(t)}catch{u=new Set}let d=c.filter(e=>!u.has(e.cardId)),p=new Map;for(let e of a){let n=e.cardId.split(`-`)[1]||`unknown`;p.has(n)||p.set(n,{total:0,wellIndicated:0,new:0});let r=p.get(n);r.total++,e.score>=t&&(r.wellIndicated++,u.has(e.cardId)||r.new++)}let m=performance.now()-n,g={totalCards:r.length,threshold:t,wellIndicated:l.size,encountered:u.size,wellIndicatedNew:d.length,byType:Object.fromEntries(p),filterBreakdown:s,elapsedMs:Math.round(m)};logger.info(`[Pipeline:diagnose] Card space scan (${g.elapsedMs}ms):`),logger.info(`[Pipeline:diagnose] Total cards: ${g.totalCards}`),logger.info(`[Pipeline:diagnose] Well-indicated (score >= ${t}): ${g.wellIndicated}`),logger.info(`[Pipeline:diagnose] Encountered: ${g.encountered}`),logger.info(`[Pipeline:diagnose] Well-indicated & new: ${g.wellIndicatedNew}`),logger.info(`[Pipeline:diagnose] By type:`);for(let[e,t]of p)logger.info(`[Pipeline:diagnose] ${e}: ${t.wellIndicated}/${t.total} well-indicated, ${t.new} new`);logger.info(`[Pipeline:diagnose] After each filter:`);for(let e of s)logger.info(`[Pipeline:diagnose] ${e.name}: ${e.wellIndicated} well-indicated`);return g}}}}),defaults_exports={};__export(defaults_exports,{createDefaultEloStrategy:()=>createDefaultEloStrategy,createDefaultPipeline:()=>createDefaultPipeline,createDefaultSrsStrategy:()=>createDefaultSrsStrategy});function createDefaultEloStrategy(e){return{_id:`NAVIGATION_STRATEGY-ELO-default`,docType:`NAVIGATION_STRATEGY`,name:`ELO (default)`,description:`Default ELO-based navigation strategy for new cards`,implementingClass:`elo`,course:e,serializedData:``}}function createDefaultSrsStrategy(e){return{_id:`NAVIGATION_STRATEGY-SRS-default`,docType:`NAVIGATION_STRATEGY`,name:`SRS (default)`,description:`Default SRS-based navigation strategy for reviews`,implementingClass:`srs`,course:e,serializedData:``}}function createDefaultPipeline(e,t){let n=t.getCourseID(),r=new ELONavigator(e,t,createDefaultEloStrategy(n)),a=new SRSNavigator(e,t,createDefaultSrsStrategy(n)),o=new CompositeGenerator([r,a]),s=createEloDistanceFilter();return new Pipeline(o,[s],e,t)}var init_defaults=__esm({"src/core/navigators/defaults.ts"(){init_navigators(),init_Pipeline(),init_CompositeGenerator(),init_elo(),init_srs(),init_eloDistance(),init_types_legacy()}}),PipelineAssembler_exports={};__export(PipelineAssembler_exports,{PipelineAssembler:()=>PipelineAssembler});var PipelineAssembler,init_PipelineAssembler=__esm({"src/core/navigators/PipelineAssembler.ts"(){init_navigators(),init_WeightedFilter(),init_Pipeline(),init_logger(),init_CompositeGenerator(),init_defaults(),PipelineAssembler=class{async assemble(e){let{strategies:t,user:n,course:r}=e,a=[];if(t.length===0)return{pipeline:null,generatorStrategies:[],filterStrategies:[],warnings:a};let o=[],s=[];for(let e of t)isGenerator(e.implementingClass)?o.push(e):isFilter(e.implementingClass)?s.push(e):a.push(`Unknown strategy type '${e.implementingClass}', skipping: ${e.name}`);let c=r.getCourseID(),l=o.some(e=>e.implementingClass===`elo`),u=o.some(e=>e.implementingClass===`srs`);if(l||(logger.debug(`[PipelineAssembler] No ELO generator configured, adding default`),o.push(createDefaultEloStrategy(c))),u||(logger.debug(`[PipelineAssembler] No SRS generator configured, adding default`),o.push(createDefaultSrsStrategy(c))),o.length===0)return a.push(`No generator strategy found`),{pipeline:null,generatorStrategies:[],filterStrategies:[],warnings:a};let d;o.length===1?(d=await ContentNavigator.create(n,r,o[0]),logger.debug(`[PipelineAssembler] Using single generator: ${o[0].name}`)):(logger.debug(`[PipelineAssembler] Using CompositeGenerator for ${o.length} generators: ${o.map(e=>e.name).join(`, `)}`),d=await CompositeGenerator.fromStrategies(n,r,o));let p=[],m=[...s].sort((e,t)=>e.name.localeCompare(t.name));for(let e of m)try{let t=await ContentNavigator.create(n,r,e);if(`transform`in t&&typeof t.transform==`function`){let n=t;e.learnable&&(n=new WeightedFilter(n,e.learnable,e.staticWeight,e._id)),p.push(n),logger.debug(`[PipelineAssembler] Added filter: ${e.name}`)}else a.push(`Filter '${e.name}' does not implement CardFilter.transform(), skipping`)}catch(t){a.push(`Failed to instantiate filter '${e.name}': ${t}`)}let g=new Pipeline(d,p,n,r);return logger.debug(`[PipelineAssembler] Assembled pipeline with ${o.length} generator(s) and ${p.length} filter(s)`),{pipeline:g,generatorStrategies:o,filterStrategies:m,warnings:a}}}}}),globImport,init_3=__esm({'import("./**/*") in src/core/navigators/index.ts'(){globImport=__glob({"./Pipeline.ts":()=>Promise.resolve().then(()=>(init_Pipeline(),Pipeline_exports)),"./PipelineAssembler.ts":()=>Promise.resolve().then(()=>(init_PipelineAssembler(),PipelineAssembler_exports)),"./PipelineDebugger.ts":()=>Promise.resolve().then(()=>(init_PipelineDebugger(),PipelineDebugger_exports)),"./SrsDebugger.ts":()=>Promise.resolve().then(()=>(init_SrsDebugger(),SrsDebugger_exports)),"./StrategyPressureDebugger.ts":()=>Promise.resolve().then(()=>(init_StrategyPressureDebugger(),StrategyPressureDebugger_exports)),"./defaults.ts":()=>Promise.resolve().then(()=>(init_defaults(),defaults_exports)),"./diversityRerank.ts":()=>Promise.resolve().then(()=>(init_diversityRerank(),diversityRerank_exports)),"./filters/WeightedFilter.ts":()=>Promise.resolve().then(()=>(init_WeightedFilter(),WeightedFilter_exports)),"./filters/eloDistance.ts":()=>Promise.resolve().then(()=>(init_eloDistance(),eloDistance_exports)),"./filters/hierarchyDefinition.ts":()=>Promise.resolve().then(()=>(init_hierarchyDefinition(),hierarchyDefinition_exports)),"./filters/index.ts":()=>Promise.resolve().then(()=>(init_filters(),filters_exports)),"./filters/inferredPreferenceStub.ts":()=>Promise.resolve().then(()=>(init_inferredPreferenceStub(),inferredPreferenceStub_exports)),"./filters/interferenceMitigator.ts":()=>Promise.resolve().then(()=>(init_interferenceMitigator(),interferenceMitigator_exports)),"./filters/relativePriority.ts":()=>Promise.resolve().then(()=>(init_relativePriority(),relativePriority_exports)),"./filters/types.ts":()=>Promise.resolve().then(()=>(init_types2(),types_exports2)),"./filters/userGoalStub.ts":()=>Promise.resolve().then(()=>(init_userGoalStub(),userGoalStub_exports)),"./filters/userTagPreference.ts":()=>Promise.resolve().then(()=>(init_userTagPreference(),userTagPreference_exports)),"./generators/CompositeGenerator.ts":()=>Promise.resolve().then(()=>(init_CompositeGenerator(),CompositeGenerator_exports)),"./generators/elo.ts":()=>Promise.resolve().then(()=>(init_elo(),elo_exports)),"./generators/index.ts":()=>Promise.resolve().then(()=>(init_generators(),generators_exports)),"./generators/prescribed.ts":()=>Promise.resolve().then(()=>(init_prescribed(),prescribed_exports)),"./generators/srs.ts":()=>Promise.resolve().then(()=>(init_srs(),srs_exports)),"./generators/types.ts":()=>Promise.resolve().then(()=>(init_types(),types_exports)),"./index.ts":()=>Promise.resolve().then(()=>(init_navigators(),navigators_exports))})}}),navigators_exports={};__export(navigators_exports,{ContentNavigator:()=>ContentNavigator,DIVERSITY_FLOOR:()=>DIVERSITY_FLOOR,DIVERSITY_STRENGTH:()=>DIVERSITY_STRENGTH,NavigatorRole:()=>NavigatorRole,NavigatorRoles:()=>NavigatorRoles,Navigators:()=>Navigators,captureStrategyPressure:()=>captureStrategyPressure,clearSrsBacklogDebug:()=>clearSrsBacklogDebug,clearStrategyPressureDebug:()=>clearStrategyPressureDebug,diversityRerank:()=>diversityRerank,drainCapturedRuns:()=>drainCapturedRuns,getActivePipeline:()=>getActivePipeline,getCardOrigin:()=>getCardOrigin,getRegisteredNavigator:()=>getRegisteredNavigator,getRegisteredNavigatorNames:()=>getRegisteredNavigatorNames,getRegisteredNavigatorRole:()=>getRegisteredNavigatorRole,getRunsForSession:()=>getRunsForSession,getSrsBacklogDebug:()=>getSrsBacklogDebug,getStrategyPressureDebug:()=>getStrategyPressureDebug,hasRegisteredNavigator:()=>hasRegisteredNavigator,initializeNavigatorRegistry:()=>initializeNavigatorRegistry,isFilter:()=>isFilter,isGenerator:()=>isGenerator,mountPipelineDebugger:()=>mountPipelineDebugger,pipelineDebugAPI:()=>pipelineDebugAPI,registerNavigator:()=>registerNavigator,setDebugSessionId:()=>setDebugSessionId});function registerNavigator(e,t,n){navigatorRegistry.set(e,{constructor:t,role:n}),logger.debug(`[NavigatorRegistry] Registered: ${e}${n?` (${n})`:``}`)}function getRegisteredNavigator(e){return navigatorRegistry.get(e)?.constructor}function hasRegisteredNavigator(e){return navigatorRegistry.has(e)}function getRegisteredNavigatorRole(e){return navigatorRegistry.get(e)?.role}function getRegisteredNavigatorNames(){return Array.from(navigatorRegistry.keys())}async function initializeNavigatorRegistry(){logger.debug(`[NavigatorRegistry] Initializing built-in navigators...`);let[e,t]=await Promise.all([Promise.resolve().then(()=>(init_elo(),elo_exports)),Promise.resolve().then(()=>(init_srs(),srs_exports))]),n=await Promise.resolve().then(()=>(init_prescribed(),prescribed_exports));registerNavigator(`elo`,e.default),registerNavigator(`srs`,t.default),registerNavigator(`prescribed`,n.default);let[r,a,o,s]=await Promise.all([Promise.resolve().then(()=>(init_hierarchyDefinition(),hierarchyDefinition_exports)),Promise.resolve().then(()=>(init_interferenceMitigator(),interferenceMitigator_exports)),Promise.resolve().then(()=>(init_relativePriority(),relativePriority_exports)),Promise.resolve().then(()=>(init_userTagPreference(),userTagPreference_exports))]);registerNavigator(`hierarchyDefinition`,r.default),registerNavigator(`interferenceMitigator`,a.default),registerNavigator(`relativePriority`,o.default),registerNavigator(`userTagPreference`,s.default),logger.debug(`[NavigatorRegistry] Initialized ${navigatorRegistry.size} navigators: ${getRegisteredNavigatorNames().join(`, `)}`)}function getCardOrigin(e){if(e.provenance.length===0)throw Error(`Card has no provenance - cannot determine origin`);let t=e.provenance[0].reason.toLowerCase();return t.includes(`failed`)?`failed`:t.includes(`review`)?`review`:`new`}function isGenerator(e){return NavigatorRoles[e]===`generator`?!0:getRegisteredNavigatorRole(e)===`generator`}function isFilter(e){return NavigatorRoles[e]===`filter`?!0:getRegisteredNavigatorRole(e)===`filter`}var navigatorRegistry,Navigators,NavigatorRole,NavigatorRoles,ContentNavigator,init_navigators=__esm({"src/core/navigators/index.ts"(){init_diversityRerank(),init_PipelineDebugger(),init_SrsDebugger(),init_StrategyPressureDebugger(),init_logger(),init_(),init_2(),init_3(),navigatorRegistry=new Map,Navigators=(e=>(e.ELO=`elo`,e.SRS=`srs`,e.PRESCRIBED=`prescribed`,e.HIERARCHY=`hierarchyDefinition`,e.INTERFERENCE=`interferenceMitigator`,e.RELATIVE_PRIORITY=`relativePriority`,e.USER_TAG_PREFERENCE=`userTagPreference`,e))(Navigators||{}),NavigatorRole=(e=>(e.GENERATOR=`generator`,e.FILTER=`filter`,e))(NavigatorRole||{}),NavigatorRoles={elo:`generator`,srs:`generator`,prescribed:`generator`,hierarchyDefinition:`filter`,interferenceMitigator:`filter`,relativePriority:`filter`,userTagPreference:`filter`},ContentNavigator=class{constructor(e,t,n){_defineProperty(this,`user`,void 0),_defineProperty(this,`course`,void 0),_defineProperty(this,`strategyName`,void 0),_defineProperty(this,`strategyId`,void 0),_defineProperty(this,`learnable`,void 0),_defineProperty(this,`staticWeight`,void 0),this.user=e,this.course=t,n&&(this.strategyName=n.name,this.strategyId=n._id,this.learnable=n.learnable,this.staticWeight=n.staticWeight)}get strategyKey(){return this.constructor.name}async getStrategyState(){if(!this.user||!this.course)throw Error(`Cannot get strategy state: navigator not properly initialized. Ensure user and course are provided to constructor.`);return this.user.getStrategyState(this.course.getCourseID(),this.strategyKey)}async putStrategyState(e){if(!this.user||!this.course)throw Error(`Cannot put strategy state: navigator not properly initialized. Ensure user and course are provided to constructor.`);return this.user.putStrategyState(this.course.getCourseID(),this.strategyKey,e)}static async create(e,t,n){let r=n.implementingClass,a=getRegisteredNavigator(r);if(a)return logger.debug(`[ContentNavigator.create] Using registered navigator: ${r}`),new a(e,t,n);logger.debug(`[ContentNavigator.create] Navigator not in registry, attempting dynamic import: ${r}`);let o;for(let e of[`.ts`,`.js`,``]){try{if(o=(await globImport_generators(`./generators/${r}${e}`)).default,o)break}catch(t){logger.debug(`Failed to load generator ${r}${e}:`,t)}try{if(o=(await globImport_filters(`./filters/${r}${e}`)).default,o)break}catch(t){logger.debug(`Failed to load filter ${r}${e}:`,t)}try{if(o=(await globImport(`./${r}${e}`)).default,o)break}catch(t){logger.debug(`Failed to load legacy ${r}${e}:`,t)}if(o)break}if(!o)throw Error(`Could not load navigator implementation for: ${r}`);return new o(e,t,n)}async getWeightedCards(e){throw Error(`${this.constructor.name} must implement getWeightedCards(). `)}setEphemeralHints(e){}}}});function randIntWeightedTowardZero(e){return Math.floor(Math.random()*Math.random()*Math.random()*e)}async function getCourseTagStubs(e){logger.debug(`Getting tag stubs for course: ${e}`);let t=await filterAllDocsByPrefix(getCourseDB2(e),`TAG`.valueOf()+`-`);return t.rows.forEach(e=>{logger.debug(` Tag stub for doc: ${e.id}`)}),t}async function createTag(e,t,n){logger.debug(`Creating tag: ${t}...`);let r=getTagID(t);return await getCourseDB2(e).put({course:e,docType:`TAG`,name:t,snippet:``,taggedCards:[],wiki:``,author:n,_id:r})}async function updateTag(e){let t=await getTag(e.course,e.name);return await getCourseDB2(e.course).put({...e,_rev:t._rev})}async function getTag(e,t){let n=getTagID(t);return getCourseDB2(e).get(n)}async function removeTagFromCard(e,t,n){n=getTagID(n);let r=getCourseDB2(e),a=await r.get(n);return a.taggedCards=a.taggedCards.filter(e=>t!==e),r.put(a)}async function getAppliedTags(e,t){return await getCourseDB2(e).query(`getTags`,{startkey:t,endkey:t})}async function updateCredentialledCourseConfig(e,t){logger.debug(`Updating course config:
|
|
256
255
|
|
|
257
256
|
${JSON.stringify(t)}
|
|
258
257
|
`);let n=getCourseDB2(e),r=await getCredentialledCourseConfig(e);return await n.put({...t,_rev:r._rev})}function isSuccessRow(e){return`doc`in e&&e.doc!==null&&e.doc!==void 0}var CoursesDB,CourseDB,init_courseDB=__esm({"src/impl/couch/courseDB.ts"(){init_couch(),init_updateQueue(),init_types_legacy(),init_logger(),init_clientCache(),init_courseAPI(),init_courseLookupDB(),init_navigators(),init_PipelineAssembler(),init_defaults(),CoursesDB=class{constructor(e){_defineProperty(this,`_courseIDs`,void 0),e&&e.length>0?this._courseIDs=e:this._courseIDs=void 0}async getCourseList(){let e=await CourseLookup.allCourseWare();return logger.debug(`AllCourses: ${e.map(e=>e.name+`, `+e._id+`
|
|
@@ -268,57 +267,20 @@ ${o.rows.map(e=>` ${e.id}-${e.key}
|
|
|
268
267
|
`+l),c}async getCourseConfig(){let e=await getCredentialledCourseConfig(this.id);if(e)return e;throw Error(`Course config not found for course ID: ${this.id}`)}async updateCourseConfig(e){logger.debug(`Updating: ${JSON.stringify(e)}`);try{return await updateCredentialledCourseConfig(this.id,e)}catch(e){throw logger.error(`Error updating course config in course DB: ${e}`),e}}async updateCardElo(e,t){if(!t)throw Error(`Cannot update card elo with null or undefined value for card ID: ${e}`);try{return{ok:!0,id:e,rev:(await this.updateQueue.update(e,e=>(logger.debug(`Replacing ${JSON.stringify(e.elo)} with ${JSON.stringify(t)}`),e.elo=t,e)))._rev}}catch(t){throw logger.error(`Failed to update card elo for card ID: ${e}`,t),Error(`Failed to update card elo for card ID: ${e}`)}}async getAppliedTags(e){let t=await getAppliedTags(this.id,e);if(t)return t;throw Error(`Failed to find tags for card ${this.id}-${e}`)}async getAppliedTagsBatch(e){if(e.length===0)return new Map;let t=await this.db.query(`getTags`,{keys:e,include_docs:!1}),n=new Map;for(let t of e)n.set(t,[]);for(let e of t.rows){let t=e.key,r=e.value?.name;r&&n.has(t)&&n.get(t).push(r)}return n}async getAllCardIds(){let e=`${DocTypePrefixes.CARD}-`;return(await this.db.allDocs({startkey:e,endkey:`${e}\uFFF0`,include_docs:!1})).rows.map(e=>e.id)}async addTagToCard(e,t,n){return await addTagToCard(this.id,e,t,(await this._getCurrentUser()).getUsername(),n)}async removeTagFromCard(e,t){return await removeTagFromCard(this.id,e,t)}async createTag(e,t){return await createTag(this.id,e,t)}async getTag(e){return await getTag(this.id,e)}async updateTag(e){if(e.course!==this.id)throw Error(`Tag ${JSON.stringify(e)} does not belong to course ${this.id}`);return await updateTag(e)}async getCourseTagStubs(){return getCourseTagStubs(this.id)}async addNote(e,t,n,r,a,o,s=blankCourseElo()){try{let c=await addNote55(this.id,e,t,n,r,a,o,s);return c.ok?c.cardCreationFailed?(logger.warn(`[courseDB.addNote] Note added but card creation failed: ${c.cardCreationError}`),{status:Status.error,message:`Note was added but no cards were created: ${c.cardCreationError}`,id:c.id}):{status:Status.ok,message:``,id:c.id}:{status:Status.error,message:`Unexpected error adding note`}}catch(e){let t=e;return logger.error(`[addNote] error ${t.name}
|
|
269
268
|
reason: ${t.reason}
|
|
270
269
|
message: ${t.message}`),{status:Status.error,message:`Error adding note to course. ${e.reason||t.message}`}}}async getCourseDoc(e,t){return await this.db.get(e,t??{})}async getCourseDocs(e,t={}){return await this.db.allDocs({...t,keys:e})}getNavigationStrategy(e){if(logger.debug(`[courseDB] Getting navigation strategy: ${e}`),e==``){let e={_id:`NAVIGATION_STRATEGY-ELO`,docType:`NAVIGATION_STRATEGY`,name:`ELO`,description:`ELO-based navigation strategy for ordering content by difficulty`,implementingClass:`elo`,course:this.id,serializedData:``};return Promise.resolve(e)}else return this.db.get(e)}async getAllNavigationStrategies(){let e=DocTypePrefixes.NAVIGATION_STRATEGY;return(await this.db.allDocs({startkey:e,endkey:`${e}\uFFF0`,include_docs:!0})).rows.map(e=>e.doc)}async addNavigationStrategy(e){return logger.debug(`[courseDB] Adding navigation strategy: ${e._id}`),this.invalidateNavigatorCache(),this.remoteDB.put(e).then(()=>{})}updateNavigationStrategy(e,t){return logger.debug(`[courseDB] Updating navigation strategy: ${e}`),logger.debug(JSON.stringify(t)),Promise.resolve()}async createNavigator(e){try{let t=await this.getAllNavigationStrategies();if(t.length===0)return logger.debug(`[courseDB] No strategy documents found, using default Pipeline(Composite(ELO, SRS), [eloDistanceFilter])`),createDefaultPipeline(e,this);let{pipeline:n,generatorStrategies:r,filterStrategies:a,warnings:o}=await new PipelineAssembler().assemble({strategies:t,user:e,course:this});for(let e of o)logger.warn(`[PipelineAssembler] ${e}`);return n?(logger.debug(`[courseDB] Using assembled pipeline with ${r.length} generator(s) and ${a.length} filter(s)`),n):(logger.debug(`[courseDB] Pipeline assembly failed, using default pipeline`),createDefaultPipeline(e,this))}catch(e){let t=e instanceof Error?`${e.message}
|
|
271
|
-
${e.stack}`:JSON.stringify(e);throw logger.error(`[courseDB] Error creating navigator: ${t}`),e}}setEphemeralHints(e){this._pendingHints=e}async getWeightedCards(e){let t=await this._getCurrentUser();try{let{navigator:n}=await this._getCachedNavigator(t);return this._pendingHints&&(n.setEphemeralHints(this._pendingHints),this._pendingHints=null),await n.getWeightedCards(e)}catch(e){throw logger.error(`[courseDB] Error getting weighted cards: ${e}`),e}}async _getCachedNavigator(e){let t=e.getUsername(),n=Date.now();if(this._cachedNavigator&&this._cachedNavigator.userId===t&&n-this._cachedNavigator.builtAt<this._navigatorTtlMs)return{navigator:this._cachedNavigator.navigator,cacheStatus:`hit`};let r=await this.createNavigator(e);return this._cachedNavigator={navigator:r,userId:t,builtAt:n},{navigator:r,cacheStatus:`miss`}}invalidateNavigatorCache(){this._cachedNavigator=null}async getCardsCenteredAtELO(e={limit:99,elo:`user`},t){let n;if(e.elo===`user`){let e=await this._getCurrentUser();n=-1;try{n=EloToNumber((await e.getCourseRegistrationsDoc()).courses.find(e=>e.courseID===this.id).elo)}catch{n=1e3}}else if(e.elo===`random`){let e=await GET_CACHED(`elo-bounds-${this.id}`,()=>this.getELOBounds());n=Math.round(e.low+Math.random()*(e.high-e.low))}else n=e.elo;let r=Math.max(2e3,e.limit*4),a=Date.now(),o=`hit`;if(!this._eloPoolCache||a-this._eloPoolCache.fetchedAt>this._eloPoolTtlMs){let e=await this.getCardsByELO(n,r);e.length>0&&(this._eloPoolCache={rows:e,fetchedAt:a}),o=`miss`}let rankAgainstCurrentElo=()=>{let e=this._eloPoolCache?.rows??[];return(t?e.filter(e=>t(e)):e).map(e=>({...e})).sort((e,t)=>Math.abs((e.elo??n)-n)-Math.abs((t.elo??n)-n))},s=rankAgainstCurrentElo();if(s.length<e.limit&&(o===`hit`||!this._eloPoolCache)){let e=await this.getCardsByELO(n,r);e.length>0&&(this._eloPoolCache={rows:e,fetchedAt:a}),s=rankAgainstCurrentElo(),o=`refresh`}let c=[];for(;c.length<e.limit&&s.length>0;){let e=randIntWeightedTowardZero(s.length),t=s.splice(e,1)[0];c.push(t)}return c.map(e=>({courseID:this.id,cardID:e.cardID,contentSourceType:`course`,contentSourceID:this.id,elo:e.elo,status:`new`}))}async searchCards(e){logger.log(`[CourseDB ${this.id}] Searching for: "${e}"`);let t;try{t=await this.db.find({selector:{docType:`DISPLAYABLE_DATA`,"data.0.data":{$regex:`.*${e}.*`}}}),logger.log(`[CourseDB ${this.id}] Regex search on data[0].data successful`)}catch(n){logger.log(`[CourseDB ${this.id}] Regex search failed, falling back to manual search:`,n);let r=await this.db.find({selector:{docType:`DISPLAYABLE_DATA`}});logger.log(`[CourseDB ${this.id}] Retrieved ${r.docs.length} documents for manual filtering`),t={docs:r.docs.filter(t=>{let n=JSON.stringify(t).toLowerCase().includes(e.toLowerCase());return n&&logger.log(`[CourseDB ${this.id}] Manual match found in document: ${t._id}`),n})}}if(logger.log(`[CourseDB ${this.id}] Found ${t.docs.length} displayable data documents`),t.docs.length===0){let e=await this.db.find({selector:{docType:`DISPLAYABLE_DATA`},limit:5});logger.log(`[CourseDB ${this.id}] Sample displayable data:`,e.docs.map(e=>({id:e._id,docType:e.docType,dataStructure:e.data?Object.keys(e.data):`no data field`,dataContent:e.data,fullDoc:e})))}let n=[];for(let e of t.docs){let t=await this.db.find({selector:{docType:`CARD`,id_displayable_data:{$in:[e._id]}}});logger.log(`[CourseDB ${this.id}] Displayable data ${e._id} linked to ${t.docs.length} cards`),n.push(...t.docs)}return logger.log(`[CourseDB ${this.id}] Total cards found: ${n.length}`),n}async find(e){return this.db.find(e)}}}}),classroomLookupDBTitle,CLASSROOM_CONFIG,ClassroomDBBase,StudentClassroomDB,TeacherClassroomDB,ClassroomLookupDB,init_classroomDB2=__esm({"src/impl/couch/classroomDB.ts"(){init_factory(),init_logger(),init_pouchdb_setup(),init_couch(),init_courseDB(),classroomLookupDBTitle=`classdb-lookup`,CLASSROOM_CONFIG=`ClassroomConfig`,ClassroomDBBase=class{constructor(){_defineProperty(this,`_id`,void 0),_defineProperty(this,`_db`,void 0),_defineProperty(this,`_cfg`,void 0),_defineProperty(this,`_initComplete`,!1),_defineProperty(this,`_content_prefix`,`content`)}get _content_searchkeys(){return getStartAndEndKeys2(this._content_prefix)}async getAssignedContent(){return logger.info(`Getting assigned content...`),(await this._db.allDocs({startkey:this._content_prefix,endkey:this._content_prefix+``,include_docs:!0})).rows.map(e=>e.doc)}getContentId(e){return e.type===`tag`?`${this._content_prefix}-${e.courseID}-${e.tagID}`:`${this._content_prefix}-${e.courseID}`}get ready(){return this._initComplete}getConfig(){return this._cfg}},StudentClassroomDB=class _StudentClassroomDB extends ClassroomDBBase{constructor(e,t){super(),_defineProperty(this,`userMessages`,void 0),_defineProperty(this,`_user`,void 0),this._id=e,this._user=t}async init(){let e=`classdb-student-${this._id}`;this._db=new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+e,createPouchDBConfig());try{this._cfg=await this._db.get(CLASSROOM_CONFIG),this.userMessages=this._db.changes({since:`now`,live:!0,include_docs:!0}),this._initComplete=!0;return}catch(e){throw Error(`Error in StudentClassroomDB constructor: ${JSON.stringify(e)}`)}}static async factory(e,t){let n=new _StudentClassroomDB(e,t);return await n.init(),n}setChangeFcn(e){this.userMessages.on(`change`,e)}async getWeightedCards(e){let t=[],n=(await this._user.getPendingReviews()).filter(e=>e.scheduledFor===`classroom`&&e.schedulingAgentId===this._id);for(let e of n)t.push({cardId:e.cardId,courseId:e.courseId,score:1,reviewID:e._id,provenance:[{strategy:`classroom`,strategyName:`Classroom`,strategyId:`CLASSROOM`,action:`generated`,score:1,reason:`Classroom scheduled review`}]});let r=await this._user.getActiveCards(),a=new Set(r.map(e=>e.cardID)),o=hooks.utc(),s=(await this.getAssignedContent()).filter(e=>o.isAfter(hooks.utc(e.activeOn,REVIEW_TIME_FORMAT2)));logger.info(`[StudentClassroomDB] Due content: ${JSON.stringify(s)}`);for(let n of s)if(n.type===`course`){let{cards:r}=await new CourseDB(n.courseID,async()=>this._user).getWeightedCards(e);for(let e of r)a.has(e.cardId)||t.push({...e,provenance:[...e.provenance,{strategy:`classroom`,strategyName:`Classroom`,strategyId:`CLASSROOM`,action:`passed`,score:e.score,reason:`Assigned via classroom from course ${n.courseID}`}]})}else if(n.type===`tag`){let e=await getTag(n.courseID,n.tagID);for(let r of e.taggedCards)a.has(r)||t.push({cardId:r,courseId:n.courseID,score:1,provenance:[{strategy:`classroom`,strategyName:`Classroom`,strategyId:`CLASSROOM`,action:`generated`,score:1,reason:`Classroom assigned tag: ${n.tagID}, new card`}]})}else n.type===`card`&&(a.has(n.cardID)||t.push({cardId:n.cardID,courseId:n.courseID,score:1,provenance:[{strategy:`classroom`,strategyName:`Classroom`,strategyId:`CLASSROOM`,action:`generated`,score:1,reason:`Classroom assigned card, new card`}]}));return logger.info(`[StudentClassroomDB] New cards from classroom ${this._cfg.name}: ${t.length} total (reviews + new)`),{cards:t.sort((e,t)=>t.score-e.score).slice(0,e)}}},TeacherClassroomDB=class _TeacherClassroomDB extends ClassroomDBBase{constructor(e){super(),_defineProperty(this,`_stuDb`,void 0),this._id=e}async init(){let e=`classdb-teacher-${this._id}`,t=`classdb-student-${this._id}`;this._db=new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+e,createPouchDBConfig()),this._stuDb=new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+t,createPouchDBConfig());try{return this._db.get(CLASSROOM_CONFIG).then(e=>{this._cfg=e,this._initComplete=!0}).then(()=>{})}catch(e){throw Error(`Error in TeacherClassroomDB constructor: ${JSON.stringify(e)}`)}}static async factory(e){let t=new _TeacherClassroomDB(e);return await t.init(),t}async removeContent(e){let t=this.getContentId(e);try{let e=await this._db.get(t);await this._db.remove(e),this._db.replicate.to(this._stuDb,{doc_ids:[t]})}catch(e){logger.error(`Failed to remove content:`,t,e)}}async assignContent(e){let t,n=this.getContentId(e);return t=e.type===`tag`?await this._db.put({courseID:e.courseID,tagID:e.tagID,type:`tag`,_id:n,assignedBy:e.assignedBy,assignedOn:hooks.utc(),activeOn:e.activeOn||hooks.utc()}):await this._db.put({courseID:e.courseID,type:`course`,_id:n,assignedBy:e.assignedBy,assignedOn:hooks.utc(),activeOn:e.activeOn||hooks.utc()}),t.ok?(this._db.replicate.to(this._stuDb,{doc_ids:[n]}),!0):!1}},ClassroomLookupDB=()=>new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+classroomLookupDBTitle,{skip_setup:!0})}}),AdminDB,init_adminDB2=__esm({"src/impl/couch/adminDB.ts"(){init_pouchdb_setup(),init_factory(),init_couch(),init_classroomDB2(),init_courseLookupDB(),init_logger(),AdminDB=class{constructor(){_defineProperty(this,`usersDB`,void 0),this.usersDB=new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+`_users`,createPouchDBConfig())}async getUsers(){return(await this.usersDB.allDocs({include_docs:!0,...getStartAndEndKeys2(`org.couchdb.user:`)})).rows.map(e=>e.doc)}async getCourses(){let e=await CourseLookup.allCourseWare();return await Promise.all(e.map(e=>getCredentialledCourseConfig(e._id)))}async removeCourse(e){let t=await CourseLookup.delete(e),n=await getCredentialledCourseConfig(e);n.deleted=!0;let r=await updateCredentialledCourseConfig(e,n);return{ok:t.ok&&r.ok,id:t.id,rev:t.rev}}async getClassrooms(){let e=(await ClassroomLookupDB().allDocs({include_docs:!0})).rows.map(e=>e.doc.uuid);logger.debug(e.join(`, `));let t=[];for(let n=0;n<e.length;n++)try{let r=await TeacherClassroomDB.factory(e[n]);t.push(r)}catch(t){let r=t;r.error&&r.error===`not_found`&&logger.warn(`db ${e[n]} not found`)}return t.map(e=>({...e.getConfig(),_id:e._id}))}}}}),CourseSyncService_exports={};__export(CourseSyncService_exports,{CourseSyncService:()=>CourseSyncService});var DEFAULT_REPLICATION,CourseSyncService,init_CourseSyncService=__esm({"src/impl/couch/CourseSyncService.ts"(){var e;init_pouchdb_setup(),init_couch(),init_logger(),DEFAULT_REPLICATION={batchSize:1e3,batchesLimit:5},CourseSyncService=(e=class _CourseSyncService{constructor(){_defineProperty(this,`entries`,new Map),_defineProperty(this,`replicationOptions`,DEFAULT_REPLICATION)}static getInstance(){return _CourseSyncService.instance||(_CourseSyncService.instance=new _CourseSyncService),_CourseSyncService.instance}configure(e){e.replication&&(this.replicationOptions={...DEFAULT_REPLICATION,...e.replication},logger.info(`[CourseSyncService] Replication configured: batch_size=${this.replicationOptions.batchSize}, batches_limit=${this.replicationOptions.batchesLimit}`))}static resetInstance(){if(_CourseSyncService.instance){for(let[,e]of _CourseSyncService.instance.entries)e.localDB&&e.localDB.close().catch(()=>{});_CourseSyncService.instance.entries.clear()}_CourseSyncService.instance=null}async ensureSynced(e,t){let n=this.entries.get(e);if(n?.status.state===`ready`&&n.localDB){if(!await this.isLocalEpochStale(e,n.localDB))return;logger.info(`[CourseSyncService] Remote DB epoch changed for course ${e} \u2014 destroying stale local replica`);try{await n.localDB.destroy()}catch{}n.localDB=null,n.readyPromise=null}if(n?.status.state===`disabled`)return;if(n?.readyPromise)return n.readyPromise;let r={localDB:null,status:{state:`not-started`},readyPromise:null};return this.entries.set(e,r),r.readyPromise=this.performSync(e,r,t),r.readyPromise}getLocalDB(e){let t=this.entries.get(e);return t?.status.state===`ready`&&t.localDB?t.localDB:null}isReady(e){return this.entries.get(e)?.status.state===`ready`}getStatus(e){return this.entries.get(e)?.status??{state:`not-started`}}async performSync(e,t,n){try{if(!n&&(t.status={state:`checking-config`},!await this.checkLocalSyncEnabled(e))){t.status={state:`disabled`},t.readyPromise=null,logger.debug(`[CourseSyncService] Local sync disabled for course ${e}`);return}t.status={state:`syncing`};let r=this.localDBName(e),a=new pouchdb_setup_default(r);await this.isLocalEpochStale(e,a)&&(logger.info(`[CourseSyncService] Stale local DB detected for course ${e} \u2014 destroying before sync`),await a.destroy(),a=new pouchdb_setup_default(r)),t.localDB=a;let o=this.getRemoteDB(e),s=Date.now();logger.info(`[CourseSyncService] Starting one-shot replication for course ${e} (batch_size=${this.replicationOptions.batchSize}, batches_limit=${this.replicationOptions.batchesLimit})`);let c=await this.replicate(o,a),l=Date.now()-s;logger.info(`[CourseSyncService] Replication complete for course ${e}: ${c.docs_written} docs in ${l}ms`),t.status={state:`warming-views`};let u=Date.now();await this.warmViewIndices(a);let d=Date.now()-u;logger.info(`[CourseSyncService] View indices warmed for course ${e} in ${d}ms`),t.status={state:`ready`,docsReplicated:c.docs_written,syncTimeMs:l,viewWarmTimeMs:d}}catch(n){let r=n instanceof Error?n.message:String(n);if(logger.error(`[CourseSyncService] Sync failed for course ${e}: ${r}`),t.status={state:`error`,error:r},t.readyPromise=null,t.localDB){try{await t.localDB.destroy()}catch{}t.localDB=null}}}async checkLocalSyncEnabled(e){try{return(await this.getRemoteDB(e).get(`CourseConfig`)).localSync?.enabled===!0}catch(t){return logger.warn(`[CourseSyncService] Could not read CourseConfig for ${e}, assuming local sync disabled: ${t}`),!1}}replicate(e,t){return new Promise((n,r)=>{pouchdb_setup_default.replicate(e,t,{batch_size:this.replicationOptions.batchSize,batches_limit:this.replicationOptions.batchesLimit}).on(`complete`,e=>{n(e)}).on(`error`,e=>{r(e)})})}async warmViewIndices(e){for(let t of[`elo`,`getTags`])try{await e.query(t,{limit:1}),logger.debug(`[CourseSyncService] Warmed view index: ${t}`)}catch(e){logger.debug(`[CourseSyncService] Could not warm view ${t}: ${e}`)}}async isLocalEpochStale(e,t){try{let n=await this.getRemoteDB(e).get(`db-epoch`),r=null;try{r=await t.get(`db-epoch`)}catch{return!0}return n.epoch!==r.epoch}catch{return!1}}getRemoteDB(e){return getCourseDB2(e)}localDBName(e){return`coursedb-local-${e}`}},_defineProperty(e,`instance`,null),e)}});async function getCurrentSession(){try{if(ENV.COUCHDB_SERVER_URL===NOT_SET||ENV.COUCHDB_SERVER_PROTOCOL===NOT_SET)throw Error(`CouchDB server configuration not properly initialized. Protocol: "${ENV.COUCHDB_SERVER_PROTOCOL}", URL: "${ENV.COUCHDB_SERVER_URL}"`);let e=ENV.COUCHDB_SERVER_URL.endsWith(`/`)?ENV.COUCHDB_SERVER_URL.slice(0,-1):ENV.COUCHDB_SERVER_URL,t=`${ENV.COUCHDB_SERVER_PROTOCOL}://${e}/_session`;logger.debug(`Attempting session check at: ${t}`);let n=await(0,import_browser_ponyfill.default)(t,{method:`GET`,credentials:`include`});if(!n.ok)throw Error(`Session check failed: ${n.status}`);return await n.json()}catch(e){let t=ENV.COUCHDB_SERVER_URL.endsWith(`/`)?ENV.COUCHDB_SERVER_URL.slice(0,-1):ENV.COUCHDB_SERVER_URL,n=`${ENV.COUCHDB_SERVER_PROTOCOL}://${t}/_session`;throw logger.error(`Session check error attempting to connect to: ${n} - ${e}`),Error(`Session check failed connecting to ${n}: ${e}`)}}async function getLoggedInUsername(){let e=await getCurrentSession();if(e.userCtx.name&&e.userCtx.name!==``)return e.userCtx.name;throw Error(`No logged in user`)}var init_auth=__esm({"src/impl/couch/auth.ts"(){init_factory(),init_logger()}}),CouchDBSyncStrategy_exports={};__export(CouchDBSyncStrategy_exports,{CouchDBSyncStrategy:()=>CouchDBSyncStrategy});var log3,CouchDBSyncStrategy,init_CouchDBSyncStrategy=__esm({"src/impl/couch/CouchDBSyncStrategy.ts"(){init_factory(),init_types_legacy(),init_logger(),init_common(),init_pouchdb_setup(),init_couch(),init_auth(),log3=e=>{logger.info(e)},CouchDBSyncStrategy=class{constructor(){_defineProperty(this,`syncHandle`,void 0),_defineProperty(this,`hydrationHandle`,void 0)}setupRemoteDB(e){return e===GuestUsername||e.startsWith(GuestUsername)?getLocalUserDB(e):this.getUserDB(e)}getWriteDB(e){return e===GuestUsername||e.startsWith(GuestUsername)?getLocalUserDB(e):this.getUserDB(e)}async hydrate(e,t){let n=(await e.info()).doc_count===0,r=pouchdb_setup_default.replicate(t,e,n?{selector:{_deleted:{$exists:!1}}}:{});this.hydrationHandle=r;try{let e=await r;return{docsWritten:e.docs_written,lastSeq:n?e.last_seq:void 0}}finally{this.hydrationHandle=void 0}}startSync(e,t,n){e.name!==t.name&&(this.syncHandle=pouchdb_setup_default.sync(e,t,{live:!0,retry:!0,...n===void 0?{}:{pull:{since:n}}}))}stopSync(){if(this.hydrationHandle){try{this.hydrationHandle.cancel()}catch(e){logger.warn(`Failed to cancel hydration pull (continuing anyway): ${e}`)}this.hydrationHandle=void 0}if(this.syncHandle){try{this.syncHandle.cancel()}catch(e){logger.warn(`Failed to cancel user sync (continuing anyway): ${e}`)}this.syncHandle=void 0}}canCreateAccount(){return!0}canAuthenticate(){return!0}async createAccount(e,t){let n=await this.getCurrentUsername(),r=n.startsWith(GuestUsername);r&&logger.info(`Creating account for funnel user ${n} -> ${e}`);try{let a=await this.getRemoteCouchRootDB().signUp(e,t);if(a.ok){log3(`CREATEACCOUNT: Successfully created account for ${e}`);try{let e=await this.getRemoteCouchRootDB().logOut();log3(`CREATEACCOUNT: logged out: ${e.ok}`)}catch{}let a=await this.getRemoteCouchRootDB().logIn(e,t);if(log3(`CREATEACCOUNT: logged in as new user: ${a.ok}`),a.ok){if(r){logger.info(`Migrating data from funnel account ${n} to ${e}`);let t=await this.migrateFunnelData(n,e);t.success||logger.warn(`Migration failed: ${t.error}`)}return{status:Status.ok,error:void 0}}else return{status:Status.error,error:`Failed to log in after account creation`}}else return logger.warn(`Signup not OK: ${JSON.stringify(a)}`),{status:Status.error,error:`Account creation failed`}}catch(e){return e.reason===`Document update conflict.`?{status:Status.error,error:`This username is taken!`}:(logger.error(`Error on signup: ${JSON.stringify(e)}`),{status:Status.error,error:e.message||`Unknown error during account creation`})}}async authenticate(e,t){try{return(await this.getRemoteCouchRootDB().logIn(e,t)).ok?(log3(`Successfully logged in as ${e}`),{ok:!0}):(log3(`Login failed for ${e}`),{ok:!1,error:`Invalid username or password`})}catch(t){return logger.error(`Authentication error for ${e}:`,t),{ok:!1,error:t.message||`Authentication failed`}}}async logout(){try{let e=await this.getRemoteCouchRootDB().logOut();return{ok:e.ok,error:e.ok?void 0:`Logout failed`}}catch(e){return logger.error(`Logout error:`,e),{ok:!1,error:e.message||`Logout failed`}}}async getCurrentUsername(){logger.log(`[funnel] CouchDBSyncStrategy.getCurrentUsername() called`);try{let e=await getLoggedInUsername();return logger.log(`[funnel] getLoggedInUsername() returned:`,e),e}catch(e){logger.log(`[funnel] getLoggedInUsername() failed, calling accomodateGuest()`),logger.log(`[funnel] Error was:`,e);let t=accomodateGuest();return logger.log(`[funnel] accomodateGuest() returned:`,t),t.username}}async migrateFunnelData(e,t){try{logger.info(`Starting data migration from ${e} to ${t}`);let n=getLocalUserDB(e),r=getLocalUserDB(t),a=await n.allDocs({include_docs:!0});logger.info(`Found ${a.rows.length} documents in funnel account`);let o=a.rows.filter(e=>!e.id.startsWith(`_design/`)).map(e=>({...e.doc,_rev:void 0}));o.length>0?(await r.bulkDocs(o),logger.info(`Successfully migrated ${o.length} documents from ${e} to ${t}`)):logger.info(`No documents to migrate from funnel account`);try{await n.destroy(),logger.info(`Destroyed consumed guest DB for ${e}`)}catch(t){logger.warn(`Failed to destroy consumed guest DB for ${e} (non-fatal): ${t instanceof Error?t.message:String(t)}`)}return{success:!0}}catch(e){return logger.error(`Migration failed:`,e),{success:!1,error:e instanceof Error?e.message:`Unknown error`}}}getRemoteCouchRootDB(){let e=ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+`skuilder`;try{return new pouchdb_setup_default(e,{skip_setup:!0})}catch(e){throw logger.error(`Failed to initialize remote CouchDB connection:`,e),Error(`Failed to initialize CouchDB: ${JSON.stringify(e)}`)}}getUserDB(e){let t=!1,n=`userdb-${hexEncode(e)}`;return log3(`Fetching user database: ${n} (${e})`),new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+n,createPouchDBConfig())}}}});function createPouchDBConfig(){return ENV.COUCHDB_USERNAME&&ENV.COUCHDB_PASSWORD&&typeof window>`u`?{fetch(e,t={}){let n=btoa(`${ENV.COUCHDB_USERNAME}:${ENV.COUCHDB_PASSWORD}`),r=new Headers(t.headers||{});r.set(`Authorization`,`Basic ${n}`);let a={...t,headers:r};return pouchdb_setup_default.fetch(e,a)}}:pouchDBincludeCredentialsConfig}function getCourseDB2(e){return new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+`coursedb-`+e,createPouchDBConfig())}function filterAllDocsByPrefix2(e,t,n){let r={startkey:t,endkey:t+``,include_docs:!0};return n&&Object.assign(r,n),e.allDocs(r)}function getStartAndEndKeys2(e){return{startkey:e,endkey:e+``}}var isBrowser,GUEST_LOCAL_DB,localUserDB,pouchDBincludeCredentialsConfig,REVIEW_TIME_FORMAT2,init_couch=__esm({"src/impl/couch/index.ts"(){init_factory(),init_types_legacy(),init_logger(),init_pouchdb_setup(),init_contentSource(),init_adminDB2(),init_classroomDB2(),init_courseAPI(),init_courseDB(),init_CourseSyncService(),init_CouchDBSyncStrategy(),isBrowser=typeof window<`u`,isBrowser&&(window.process=import_browser.default),GUEST_LOCAL_DB=`userdb-${GuestUsername}`,new pouchdb_setup_default(GUEST_LOCAL_DB),pouchDBincludeCredentialsConfig={fetch(e,t){return t.credentials=`include`,pouchdb_setup_default.fetch(e,t)}},REVIEW_TIME_FORMAT2=`YYYY-MM-DD--kk:mm:ss-SSS`}});function withTimeout(e,t,n){let r;return Promise.race([e,new Promise((e,a)=>{r=setTimeout(()=>a(Error(`${n} timed out after ${t}ms`)),t)})]).finally(()=>{r!==void 0&&clearTimeout(r)})}function accomodateGuest(){if(logger.log(`[funnel] accomodateGuest() called`),typeof localStorage>`u`)return logger.log(`[funnel] localStorage not available (Node.js environment), returning default guest`),{username:GuestUsername+`nodejs-test`,firstVisit:!0};let e=`sk-guest-uuid`,t,n=localStorage.getItem(e);if(logger.log(`[funnel] Checking localStorage for key:`,e),logger.log(`[funnel] Existing UUID value:`,n),logger.log(`[funnel] existingUUID !== null:`,n!==null),n!==null)t=!1,logger.log(`[funnel] Returning guest ${n} "logging in".`);else{t=!0,logger.log(`[funnel] No existing UUID, generating new one...`);let n=generateUUID();logger.log(`[funnel] Generated UUID:`,n),logger.log(`[funnel] UUID length:`,n.length);try{localStorage.setItem(e,n),logger.log(`[funnel] Successfully stored UUID in localStorage`);let t=localStorage.getItem(e);logger.log(`[funnel] Verification read from localStorage:`,t)}catch(e){logger.error(`[funnel] ERROR storing UUID:`,e)}logger.log(`[funnel] Accommodating a new guest with account: ${n}`)}let r=localStorage.getItem(e),a=GuestUsername+r;return logger.log(`[funnel] Final UUID from localStorage:`,r),logger.log(`[funnel] GuestUsername constant:`,GuestUsername),logger.log(`[funnel] Final username to return:`,a),{username:a,firstVisit:t};function generateUUID(){if(logger.log(`[funnel] Inside generateUUID()`),typeof crypto<`u`&&typeof crypto.randomUUID==`function`){let e=crypto.randomUUID();return logger.log(`[funnel] Generated UUID using crypto.randomUUID():`,e),e}if(typeof crypto<`u`&&typeof crypto.getRandomValues==`function`){let e=new Uint8Array(16);crypto.getRandomValues(e),e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=[Array.from(e.slice(0,4)).map(e=>e.toString(16).padStart(2,`0`)).join(``),Array.from(e.slice(4,6)).map(e=>e.toString(16).padStart(2,`0`)).join(``),Array.from(e.slice(6,8)).map(e=>e.toString(16).padStart(2,`0`)).join(``),Array.from(e.slice(8,10)).map(e=>e.toString(16).padStart(2,`0`)).join(``),Array.from(e.slice(10,16)).map(e=>e.toString(16).padStart(2,`0`)).join(``)].join(`-`);return logger.log(`[funnel] Generated UUID using crypto.getRandomValues():`,t),t}logger.warn(`[funnel] crypto API not available, using timestamp-based UUID (NOT SECURE)`);let e=new Date().getTime();typeof performance<`u`&&typeof performance.now==`function`&&(e+=performance.now());let t=`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g,t=>{let n=(e+Math.random()*16)%16|0;return e=Math.floor(e/16),(t===`x`?n:n&3|8).toString(16)});return logger.log(`[funnel] Generated UUID (fallback):`,t),t}}async function getOrCreateClassroomRegistrationsDoc(e){let t;try{t=await getLocalUserDB(e).get(userClassroomsDoc)}catch(n){let r=n;if(r.status===404)await getLocalUserDB(e).put({_id:userClassroomsDoc,registrations:[]}),t=await getOrCreateClassroomRegistrationsDoc(e);else{let e={name:r.name,status:r.status,message:r.message,reason:r.reason,error:r.error};throw logger.error(`Database error in getOrCreateClassroomRegistrationsDoc (standalone function):`,e),Error(`Database error accessing classroom registrations: ${r.message||r.name||`Unknown error`} (status: ${r.status})`)}}return t}async function getOrCreateCourseRegistrationsDoc(e){let t;try{t=await getLocalUserDB(e).get(userCoursesDoc)}catch(n){if(n.status===404)await getLocalUserDB(e).put({_id:userCoursesDoc,courses:[],studyWeight:{}}),t=await getOrCreateCourseRegistrationsDoc(e);else throw Error(`Unexpected error ${JSON.stringify(n)} in getOrCreateCourseRegistrationDoc...`)}return t}async function updateUserElo(e,t,n){let r=await getOrCreateCourseRegistrationsDoc(e),a=r.courses.find(e=>e.courseID===t);return a.elo=n,getLocalUserDB(e).put(r)}async function registerUserForClassroom(e,t,n){return log4(`Registering user: ${e} in course: ${t}`),getOrCreateClassroomRegistrationsDoc(e).then(r=>{let a={classID:t,registeredAs:n};return r.registrations.filter(e=>e.classID===a.classID&&e.registeredAs===a.registeredAs).length===0?r.registrations.push(a):log4(`User ${e} is already registered for class ${t}`),getLocalUserDB(e).put(r)})}async function dropUserFromClassroom(e,t){return getOrCreateClassroomRegistrationsDoc(e).then(n=>{let r=-1;for(let e=0;e<n.registrations.length;e++)n.registrations[e].classID===t&&(r=e);return r!==-1&&n.registrations.splice(r,1),getLocalUserDB(e).put(n)})}async function getUserClassrooms(e){return getOrCreateClassroomRegistrationsDoc(e)}var log4,HYDRATION_TIMEOUT_MS,BaseUser,userCoursesDoc,userClassroomsDoc,init_BaseUserDB=__esm({"src/impl/common/BaseUserDB.ts"(){var e;init_core(),init_util(),init_types_legacy(),init_logger(),init_userDBHelpers(),init_updateQueue(),init_user_course_relDB(),init_couch(),log4=e=>{logger.info(e)},HYDRATION_TIMEOUT_MS=15e3,BaseUser=(e=class _BaseUser{static Dummy(e){return new _BaseUser(`Me`,e)}getUsername(){return this._username}isLoggedIn(){return!this._username.startsWith(GuestUsername)}remote(){return this.remoteDB}hydrationStatus(){return{...this._hydration}}async awaitHydration(){try{await this._hydrationPromise}catch{}return this.hydrationStatus()}canMaterializeDefaults(){return this._hydration.state!==`failed`&&this._hydration.state!==`hydrating`}async createAccount(e,t){if(!this.syncStrategy.canCreateAccount())throw Error(`Account creation not supported by current sync strategy`);if(!this._username.startsWith(GuestUsername))throw Error(`Cannot create a new account while logged in:
|
|
272
|
-
|
|
273
|
-
Log out of account ${this.getUsername()} before logging in as ${e}.`);logger.warn(`User ${this._username} is already logged in, but executing login again.`)}let n=await this.syncStrategy.authenticate(e,t);if(n.ok){log4(`Logged in as ${e}`),this._username=e;try{localStorage.removeItem(`sk-guest-uuid`)}catch(e){logger.warn(`localStorage not available (Node.js environment):`,e)}await this.init()}return n}async resetUserData(){if(this.syncStrategy.canAuthenticate())return{status:Status.error,error:`Reset user data is only available for local-only mode. Use logout instead for remote sync.`};try{let e=getLocalUserDB(this._username),t=(await e.allDocs({include_docs:!1})).rows.filter(e=>{let t=e.id;return t.startsWith(DocTypePrefixes.CARDRECORD)||t.startsWith(DocTypePrefixes.SCHEDULED_CARD)||t.startsWith(DocTypePrefixes.STRATEGY_STATE)||t.startsWith(DocTypePrefixes.USER_OUTCOME)||t.startsWith(DocTypePrefixes.STRATEGY_LEARNING_STATE)||t===_BaseUser.DOC_IDS.COURSE_REGISTRATIONS||t===_BaseUser.DOC_IDS.CLASSROOM_REGISTRATIONS||t===_BaseUser.DOC_IDS.CONFIG}).map(e=>({_id:e.id,_rev:e.value.rev,_deleted:!0}));return t.length>0&&await e.bulkDocs(t),await this.init(),{status:Status.ok}}catch(e){return logger.error(`Failed to reset user data:`,e),{status:Status.error,error:e instanceof Error?e.message:`Unknown error during reset`}}}async logout(){if(!this.syncStrategy.canAuthenticate())return this._username=await this.syncStrategy.getCurrentUsername(),await this.init(),{ok:!0};let e=await this.syncStrategy.logout();try{localStorage.removeItem(`sk-guest-uuid`)}catch(e){logger.warn(`localStorage not available (Node.js environment):`,e)}return this._username=await this.syncStrategy.getCurrentUsername(),await this.init(),e}async get(e){return this.localDB.get(e)}update(e,t){return this.updateQueue.update(e,t)}async getCourseRegistrationsDoc(){logger.debug(`Fetching courseRegistrations for ${this.getUsername()}`);let e;try{return await this.localDB.get(_BaseUser.DOC_IDS.COURSE_REGISTRATIONS)}catch(t){if(t.status===404){if(!this.canMaterializeDefaults())throw Error(`Cannot read course registrations for ${this._username}: the local mirror is unavailable (hydration state '${this._hydration.state}'). Refusing to create an empty registration doc \u2014 that would report an existing user as unregistered, and then lose to their real document once sync resumes.`);await this.localDB.put({_id:_BaseUser.DOC_IDS.COURSE_REGISTRATIONS,courses:[],studyWeight:{}}),e=await this.getCourseRegistrationsDoc()}else throw Error(`Unexpected error ${JSON.stringify(t)} in getOrCreateCourseRegistrationDoc...`)}return e}async getActiveCourses(){return(await this.getCourseRegistrationsDoc()).courses.filter(e=>e.status===void 0||e.status===`active`)}async getActiveCards(){let e=getStartAndEndKeys(DocTypePrefixes.SCHEDULED_CARD);return(await this.remoteDB.allDocs({startkey:e.startkey,endkey:e.endkey,include_docs:!0})).rows.map(e=>({courseID:e.doc.courseId,cardID:e.doc.cardId}))}async getActivityRecords(){try{let e=await this.getHistory(),t=[];if(!Array.isArray(e))return logger.error(`getHistory did not return an array:`,e),t;let n=0;for(let r=0;r<e.length;r++)try{e[r]&&Array.isArray(e[r].records)&&e[r].records.forEach(e=>{try{if(!e.timeStamp)return;let r;if(typeof e.timeStamp==`object`)if(typeof e.timeStamp.toDate==`function`)r=e.timeStamp.toISOString();else if(e.timeStamp instanceof Date)r=e.timeStamp.toISOString();else{n<3&&(logger.warn(`Unknown timestamp object type:`,e.timeStamp),n++);return}else if(typeof e.timeStamp==`string`){let t=new Date(e.timeStamp);if(isNaN(t.getTime()))return;r=e.timeStamp}else if(typeof e.timeStamp==`number`)r=new Date(e.timeStamp).toISOString();else return;t.push({timeStamp:r,courseID:e.courseID||`unknown`,cardID:e.cardID||`unknown`,timeSpent:e.timeSpent||0,type:`card_view`})}catch{}})}catch(e){logger.error(`Error processing history item:`,e)}return logger.debug(`Found ${t.length} activity records`),t}catch(e){return logger.error(`Error in getActivityRecords:`,e),[]}}async getReviewstoDate(e,t){let n=getStartAndEndKeys(DocTypePrefixes.SCHEDULED_CARD),r=await this.remoteDB.allDocs({startkey:n.startkey,endkey:n.endkey,include_docs:!0});return log4(`Fetching ${this._username}'s scheduled reviews${t?` for course ${t}`:``}.`),r.rows.filter(n=>{if(n.id.startsWith(DocTypePrefixes.SCHEDULED_CARD)){let r=hooks.utc(n.id.substr(DocTypePrefixes.SCHEDULED_CARD.length),REVIEW_TIME_FORMAT);if(e.isAfter(r)&&(t===void 0||n.doc.courseId===t))return!0}}).map(e=>e.doc)}async getReviewsForcast(e,t){let n=hooks.utc().add(e,`days`);return this.getReviewstoDate(n,t)}async getPendingReviews(e){let t=hooks.utc();return this.getReviewstoDate(t,e)}async getScheduledReviewCount(e){return(await this.getPendingReviews(e)).length}async getRegisteredCourses(){return(await this.getCourseRegistrationsDoc()).courses.filter(e=>!e.status||e.status===`active`||e.status===`maintenance-mode`)}async getCourseRegDoc(e){let t=(await this.getCourseRegistrationsDoc()).courses.find(t=>t.courseID===e);if(t)return t;throw Error(`Course registration not found for course ID: ${e}`)}async registerForCourse(e,t=!1){return this.getCourseRegistrationsDoc().then(n=>{let r=t?`preview`:`active`;logger.debug(`Registering for ${e} with status: ${r}`);let a={status:r,courseID:e,user:!0,admin:!1,moderator:!1,elo:{global:{score:1e3,count:0},tags:{},misc:{}}};return n.courses.filter(e=>e.courseID===a.courseID).length===0?(log4(`It's a new course registration!`),n.courses.push(a),n.studyWeight[e]=1):n.courses.forEach(t=>{log4(`Found the previously registered course!`),t.courseID===e&&(t.status=r)}),this.localDB.put(n)}).catch(e=>{throw log4(`Registration failed because of: ${JSON.stringify(e)}`),e})}async dropCourse(e,t=`dropped`){return this.getCourseRegistrationsDoc().then(n=>{let r=-1;for(let t=0;t<n.courses.length;t++)n.courses[t].courseID===e&&(r=t);if(r!==-1)delete n.studyWeight[e],n.courses[r].status=t;else throw Error(`User ${this.getUsername()} is not currently registered for course ${e}`);return this.localDB.put(n)})}async getCourseInterface(e){return new UsrCrsData(this,e)}async getUserEditableCourses(){let e=[],t=await this.getCourseRegistrationsDoc();return e=e.concat(t.courses.map(e=>e.courseID)),await Promise.all(e.map(async e=>await getCredentialledCourseConfig(e)))}async getConfig(){let e={_id:_BaseUser.DOC_IDS.CONFIG,darkMode:!1,likesConfetti:!1,sessionTimeLimit:5};try{let e=await this.localDB.get(_BaseUser.DOC_IDS.CONFIG);return logger.debug(`Raw config from DB:`,e),e}catch(t){let n=t;if(n.name&&n.name===`not_found`){if(!this.canMaterializeDefaults())throw Error(`Cannot read config for ${this._username}: the local mirror is unavailable (hydration state '${this._hydration.state}'). Refusing to write a default config over what may be an existing one.`);return await this.localDB.put(e),this.getConfig()}else throw logger.error(`Error setting user default config:`,t),Error(`Error returning the user's configuration: ${JSON.stringify(t)}`)}}async setConfig(e){logger.debug(`Setting Config items ${JSON.stringify(e)}`);let t=await this.getConfig(),n=await this.localDB.put({...t,...e});n.ok?logger.debug(`Config items set: ${JSON.stringify(e)}`):logger.error(`Error setting config items: ${JSON.stringify(n)}`)}static async instance(e,t){return t?(_BaseUser._instance=new _BaseUser(t,e),await _BaseUser._instance.init(),_BaseUser._instance):_BaseUser._instance&&_BaseUser._initialized?_BaseUser._instance:_BaseUser._instance?new Promise(e=>{(function waitForUser(){if(_BaseUser._initialized)return e(_BaseUser._instance);setTimeout(waitForUser,50)})()}):(_BaseUser._instance=new _BaseUser(await e.getCurrentUsername(),e),await _BaseUser._instance.init(),_BaseUser._instance)}constructor(e,t){_defineProperty(this,`_username`,void 0),_defineProperty(this,`syncStrategy`,void 0),_defineProperty(this,`localDB`,void 0),_defineProperty(this,`remoteDB`,void 0),_defineProperty(this,`writeDB`,void 0),_defineProperty(this,`updateQueue`,void 0),_defineProperty(this,`_hydration`,{state:`not-required`}),_defineProperty(this,`_hydrationPromise`,null),_defineProperty(this,`_hydratedSeq`,void 0),_BaseUser._initialized=!1,this._username=e,this.syncStrategy=t,this.setDBandQ()}setDBandQ(){this.localDB=getLocalUserDB(this._username),this.remoteDB=this.syncStrategy.setupRemoteDB(this._username),this.writeDB=this.syncStrategy.getWriteDB?this.syncStrategy.getWriteDB(this._username):this.localDB,this.updateQueue=new UpdateQueue(this.localDB,this.writeDB)}async init(){if(_BaseUser._initialized=!1,this._username===`admin`){_BaseUser._initialized=!0;return}this.syncStrategy.stopSync?.(),this.setDBandQ(),this._hydrationPromise=this.hydrateLocalMirror(),await this._hydrationPromise,this.syncStrategy.startSync(this.localDB,this.remoteDB,this._hydratedSeq),this.applyDesignDocs().catch(e=>{log4(`Error in applyDesignDocs background task: ${e}`),e&&typeof e==`object`&&log4(`Full error details in applyDesignDocs: ${JSON.stringify(e)}`)}),this.deduplicateReviews().catch(e=>{log4(`Error in deduplicateReviews background task: ${e}`),e&&typeof e==`object`&&log4(`Full error details in background task: ${JSON.stringify(e)}`)}),_BaseUser._initialized=!0}async hydrateLocalMirror(){if(this._hydratedSeq=void 0,this.localDB.name===this.remoteDB.name||!this.syncStrategy.hydrate){this._hydration={state:`not-required`};return}if(await this.hasHydrationMarker()){this._hydration={state:`stale`};return}this._hydration={state:`hydrating`};let e=Date.now();try{let{docsWritten:t,lastSeq:n}=await withTimeout(this.syncStrategy.hydrate(this.localDB,this.remoteDB),HYDRATION_TIMEOUT_MS,`Hydration of local mirror for ${this._username}`);this._hydratedSeq=n,await this.writeHydrationMarker(),this._hydration={state:`hydrated`,docsWritten:t,durationMs:Date.now()-e},log4(`Hydrated local mirror for ${this._username}: ${t} docs in ${this._hydration.durationMs}ms`)}catch(t){this.syncStrategy.stopSync?.(),this._hydration={state:`failed`,durationMs:Date.now()-e,error:t instanceof Error?t.message:String(t)},logger.error(`Failed to hydrate local mirror for ${this._username}:`,t)}}async hasHydrationMarker(){try{return(await this.localDB.get(HYDRATION_MARKER_ID)).username===this._username}catch{return!1}}async writeHydrationMarker(){try{let e;try{e=(await this.localDB.get(HYDRATION_MARKER_ID))._rev}catch{}await this.localDB.put({_id:HYDRATION_MARKER_ID,_rev:e,username:this._username,hydratedAt:new Date().toISOString()})}catch(e){logger.warn(`Could not write hydration marker for ${this._username}: ${e}`)}}async applyDesignDocs(){if(log4(`Starting applyDesignDocs for user: ${this._username}`),log4(`Remote DB name: ${this.remoteDB.name||`unknown`}`),this._username===`admin`){log4(`Skipping design docs for admin user`);return}log4(`Applying ${_BaseUser.designDocs.length} design docs`);for(let e of _BaseUser.designDocs){log4(`Applying design doc: ${e._id}`);try{try{let t=await this.remoteDB.get(e._id);await this.remoteDB.put({...e,_rev:t._rev})}catch(t){if(t?.name===`not_found`)await this.remoteDB.put(e);else throw t}}catch(t){if(t.name&&t.name===`conflict`)logger.warn(`Design doc ${e._id} update conflict - will retry`),await new Promise(e=>setTimeout(e,1e3)),await this.applyDesignDoc(e);else throw logger.error(`Failed to apply design doc ${e._id}:`,t),t}}}async applyDesignDoc(e,t=3){try{let t=await this.remoteDB.get(e._id);await this.remoteDB.put({...e,_rev:t._rev})}catch(n){if(n?.name===`conflict`&&t>0)return await new Promise(e=>setTimeout(e,1e3)),this.applyDesignDoc(e,t-1);throw n}}async putCardRecord(e){let t=getCardHistoryID(e.courseID,e.cardID);e.timeStamp=hooks.utc(e.timeStamp).toString();try{let n=await this.update(t,function(t){return t.records.push(e),t.bestInterval=t.bestInterval||0,t.lapses=t.lapses||0,t.streak=t.streak||0,t});return n.records=n.records.map(e=>{let t={...e};return t.timeStamp=hooks.utc(e.timeStamp),t}),n}catch(n){let r=n;if(r.status===404)try{let n={_id:t,cardID:e.cardID,courseID:e.courseID,records:[e],lapses:0,streak:0,bestInterval:0},r=await this.writeDB.put(n);return{...n,_rev:r.rev}}catch(e){throw Error(`Failed to create CardHistory for ${t}. Reason: ${e}`)}else throw Error(`putCardRecord failed because of:
|
|
274
|
-
name:${r.name}
|
|
275
|
-
error: ${r.error}
|
|
276
|
-
message: ${r.message}`)}}async deduplicateReviews(){try{log4(`Starting deduplication of scheduled reviews...`),log4(`Remote DB name: ${this.remoteDB.name||`unknown`}`),log4(`Write DB name: ${this.writeDB.name||`unknown`}`);let e={},t=[];log4(`Attempting to query remoteDB for reviewCards/reviewCards. Database: ${this.remoteDB.name||`unknown`}`);let n=await this.remoteDB.query(`reviewCards/reviewCards`);if(log4(`Found ${n.rows.length} scheduled reviews to process`),n.rows.forEach(n=>{let r=n.value,a=n.key;e[r]?(log4(`Found duplicate scheduled review for card: ${r}`),log4(`Marking earlier review ${e[r]} for deletion, keeping ${a}`),t.push(e[r]),e[r]=a):e[r]=a}),t.length>0){log4(`Removing ${t.length} duplicate reviews...`);let e=t.map(async e=>{try{let t=await this.remoteDB.get(e);await this.writeDB.remove(t),log4(`Successfully removed duplicate review: ${e}`)}catch(t){log4(`Failed to remove duplicate review ${e}: ${t}`)}});await Promise.all(e),log4(`Deduplication complete. Processed ${t.length} duplicates`)}else log4(`No duplicate reviews found`)}catch(e){log4(`Error during review deduplication: ${e}`),e&&typeof e==`object`&&`status`in e&&e.status===404&&(log4(`Database not found (404) during review deduplication. Database: ${this.remoteDB.name||`unknown`}`),log4(`This might indicate the user database doesn't exist or the reviewCards view isn't available`)),e&&typeof e==`object`&&log4(`Full error details: ${JSON.stringify(e)}`)}}async getSeenCards(e){let t=DocTypePrefixes.CARDRECORD;e&&(t+=`-${e}-`);let n=await filterAllDocsByPrefix(this.localDB,t,{include_docs:!1}),r=[];return n.rows.forEach(e=>{e.id.startsWith(t)&&r.push(e.id.substr(t.length))}),r}async getHistory(){return(await filterAllDocsByPrefix(this.remoteDB,DocTypePrefixes.CARDRECORD,{include_docs:!0,attachments:!1})).rows.map(e=>e.doc)}async updateCourseSettings(e,t){this.getCourseRegistrationsDoc().then(n=>{let r=n.courses.find(t=>t.courseID===e);return r&&((r.settings===null||r.settings===void 0)&&(r.settings={}),t.forEach(e=>{r.settings[e.key]=e.value})),this.localDB.put(n)})}async getCourseSettings(e){let t=(await this.getCourseRegistrationsDoc()).courses.find(t=>t.courseID===e);if(t)return t.settings;throw Error(`getCourseSettings Failed:
|
|
277
|
-
User is not registered for course ${e}`)}async getOrCreateClassroomRegistrationsDoc(){let e;try{e=await this.remoteDB.get(_BaseUser.DOC_IDS.CLASSROOM_REGISTRATIONS)}catch(t){let n=t;if(n.status===404)await this.writeDB.put({_id:_BaseUser.DOC_IDS.CLASSROOM_REGISTRATIONS,registrations:[]}),e=await this.getOrCreateClassroomRegistrationsDoc();else{let e={name:n.name,status:n.status,message:n.message,reason:n.reason,error:n.error};throw logger.error(`Database error in getOrCreateClassroomRegistrationsDoc (private method):`,e),Error(`Database error accessing classroom registrations: ${n.message||n.name||`Unknown error`} (status: ${n.status})`)}}return logger.debug(`Returning classroom registrations doc: ${JSON.stringify(e)}`),e}async getActiveClasses(){try{return(await this.getOrCreateClassroomRegistrationsDoc()).registrations.filter(e=>e.registeredAs===`student`).map(e=>e.classID)}catch(e){return logger.warn(`Failed to load classroom registrations, continuing without classroom data:`,e),[]}}async scheduleCardReview(e){return scheduleCardReviewLocal(this.writeDB,e)}async removeScheduledCardReview(e){return removeScheduledCardReviewLocal(this.writeDB,e)}async registerForClassroom(e,t){return registerUserForClassroom(this._username,e,t)}async dropFromClassroom(e){return dropUserFromClassroom(this._username,e)}async getUserClassrooms(){return getUserClassrooms(this._username)}async updateUserElo(e,t){return updateUserElo(this._username,e,t)}async getStrategyState(e,t){let n=buildStrategyStateId(e,t);try{return(await this.localDB.get(n)).data}catch(e){if(e.status===404){if(!this.canMaterializeDefaults())throw Error(`Cannot read strategy state '${t}' for ${this._username}: the local mirror is unavailable (hydration state '${this._hydration.state}').`);return null}throw e}}async putStrategyState(e,t,n){let r=buildStrategyStateId(e,t),a;try{a=(await this.localDB.get(r))._rev}catch(e){if(e.status!==404)throw e}let o={_id:r,_rev:a,docType:`STRATEGY_STATE`,courseId:e,strategyKey:t,data:n,updatedAt:new Date().toISOString()};await this.localDB.put(o)}async putStudySession(e){try{await this.localDB.put(e)}catch(t){if(t.status===409){let t=await this.localDB.get(e._id);await this.localDB.put({...e,_rev:t._rev})}else throw t}}async getStudySessions(e){let t=getStartAndEndKeys(e?`${DocTypePrefixes.STUDY_SESSION}::${e}::`:`${DocTypePrefixes.STUDY_SESSION}::`);return(await this.localDB.allDocs({startkey:t.startkey,endkey:t.endkey,include_docs:!0})).rows.map(e=>e.doc).filter(e=>!!e).sort((e,t)=>t.startTime.localeCompare(e.startTime))}async putUserOutcome(e){try{await this.localDB.put(e)}catch(t){if(t.status===409)e._rev=(await this.localDB.get(e._id))._rev,await this.localDB.put(e);else throw t}}async deleteStrategyState(e,t){let n=buildStrategyStateId(e,t);try{let e=await this.localDB.get(n);await this.localDB.remove(e)}catch(e){if(e.status===404)return;throw e}}},_defineProperty(e,`_instance`,void 0),_defineProperty(e,`_initialized`,!1),_defineProperty(e,`DOC_IDS`,{CONFIG:`CONFIG`,COURSE_REGISTRATIONS:`CourseRegistrations`,CLASSROOM_REGISTRATIONS:`ClassroomRegistrations`}),_defineProperty(e,`designDocs`,[{_id:`_design/reviewCards`,views:{reviewCards:{map:`function (doc) {
|
|
278
|
-
if (doc._id && doc._id.indexOf('card_review') === 0 && doc.courseId && doc.cardId) {
|
|
279
|
-
emit(doc._id, doc.courseId + '-' + doc.cardId);
|
|
280
|
-
}
|
|
281
|
-
}`}}}]),e),userCoursesDoc=`CourseRegistrations`,userClassroomsDoc=`ClassroomRegistrations`}}),init_common=__esm({"src/impl/common/index.ts"(){init_SyncStrategy(),init_BaseUserDB(),init_userDBHelpers()}}),PouchDataLayerProvider_exports={};__export(PouchDataLayerProvider_exports,{CouchDataLayerProvider:()=>CouchDataLayerProvider});var CouchDataLayerProvider,init_PouchDataLayerProvider=__esm({"src/impl/couch/PouchDataLayerProvider.ts"(){init_logger(),init_dataDirectory(),init_auth(),init_adminDB2(),init_classroomDB2(),init_courseDB(),init_CourseSyncService(),init_common(),init_CouchDBSyncStrategy(),CouchDataLayerProvider=class{constructor(e){_defineProperty(this,`initialized`,!1),_defineProperty(this,`userDB`,void 0),_defineProperty(this,`currentUsername`,``),_defineProperty(this,`_courseIDs`,[]),e&&(this._courseIDs=e)}async initialize(){if(!this.initialized){if(typeof process<`u`&&process.versions!=null&&process.versions.node!=null){logger.info(`CouchDataLayerProvider: Running in Node.js environment, creating guest UserDB for testing.`),await initializeDataDirectory();let e=new CouchDBSyncStrategy;this.userDB=await BaseUser.instance(e)}else{let e=new CouchDBSyncStrategy;this.userDB=await BaseUser.instance(e),this.currentUsername=this.userDB.getUsername(),logger.debug(`Current username: ${this.currentUsername}`)}this.initialized=!0}}async teardown(){this.initialized=!1}getUserDB(){return this.userDB}getCourseDB(e){let t=CourseSyncService.getInstance().getLocalDB(e);return new CourseDB(e,async()=>this.getUserDB(),t??void 0)}async ensureCourseSynced(e,t){return CourseSyncService.getInstance().ensureSynced(e,t)}getCoursesDB(){return new CoursesDB(this._courseIDs)}async getClassroomDB(e,t){return t===`student`?await StudentClassroomDB.factory(e,this.getUserDB()):await TeacherClassroomDB.factory(e)}getAdminDB(){return new AdminDB}async createUserReaderForUser(e){let t=await getLoggedInUsername();if(t!==`admin`)throw Error(`Unauthorized: Only admin users can access other users' data`);logger.info(`Admin user '${t}' requesting UserDBReader for '${e}'`);let n=new CouchDBSyncStrategy;return await BaseUser.instance(n,e)}isReadOnly(){return!1}}}}),pathUtils,nodeFS,StaticDataUnpacker,init_StaticDataUnpacker=__esm({"src/impl/static/StaticDataUnpacker.ts"(){init_logger(),init_core(),pathUtils={isAbsolute:e=>!!(/^[a-zA-Z]:[\\/]/.test(e)||/^\\\\/.test(e)||e.startsWith(`/`))},nodeFS=null;try{typeof window>`u`&&typeof process<`u`&&process.versions?.node&&(nodeFS=eval(`require`)(`fs`))}catch{}StaticDataUnpacker=class{constructor(e,t){_defineProperty(this,`manifest`,void 0),_defineProperty(this,`basePath`,void 0),_defineProperty(this,`documentCache`,new Map),_defineProperty(this,`chunkCache`,new Map),_defineProperty(this,`indexCache`,new Map),this.manifest=e,this.basePath=t}async getDocument(e){if(this.documentCache.has(e)){let t=this.documentCache.get(e);return await this.hydrateAttachments(t)}let t=await this.findChunkForDocument(e);if(!t)throw logger.error(`Document ${e} not found in any chunk. Available chunks:`,this.manifest.chunks.map(e=>`${e.id} (${e.docType}): ${e.startKey} - ${e.endKey}`)),Error(`Document ${e} not found in any chunk`);if(await this.loadChunk(t.id),this.documentCache.has(e)){let t=this.documentCache.get(e);return await this.hydrateAttachments(t)}throw logger.error(`Document ${e} not found in chunk ${t.id}`),Error(`Document ${e} not found in chunk ${t.id}`)}async getAllDocumentsByPrefix(e){let t=this.manifest.chunks.filter(t=>{let n=e+``;return t.startKey<=n&&t.endKey>=e});if(t.length===0)return logger.debug(`[StaticDataUnpacker] No chunks found for prefix: ${e}`),[];await Promise.all(t.map(e=>this.loadChunk(e.id)));let n=[];for(let[t,r]of this.documentCache.entries())t.startsWith(e)&&n.push(await this.hydrateAttachments(r));return logger.debug(`[StaticDataUnpacker] Found ${n.length} documents with prefix: ${e}`),n}async queryByElo(e,t=25){let n=await this.loadIndex(`elo`);if(!n||!n.sorted)return logger.warn(`ELO index not found or malformed, returning empty results`),[];let r=n.sorted,a=0,o=0,s=r.length-1;for(;o<=s;){let t=Math.floor((o+s)/2);r[t].elo<e?o=t+1:s=t-1}a=o;let c=[],l=Math.floor(t/2);for(let e=Math.max(0,a-l);e<a&&c.length<t;e++)c.push(r[e].cardId);for(let e=a;e<r.length&&c.length<t;e++)c.push(r[e].cardId);return c}async getTagsIndex(){try{return await this.loadIndex(`tags`)}catch{return{byCard:{},byTag:{}}}}getDocTypeFromId(e){for(let t in DocTypePrefixes){let n=DocTypePrefixes[t];if(e.startsWith(`${n}-`))return t}}async findChunkForDocument(e){let t=this.getDocTypeFromId(e);if(t){let n=this.manifest.chunks.filter(e=>e.docType===t);for(let t of n)if(e>=t.startKey&&e<=t.endKey&&await this.verifyDocumentInChunk(e,t))return t}else{for(let t of this.manifest.chunks)if(e>=t.startKey&&e<=t.endKey&&await this.verifyDocumentInChunk(e,t))return t;let t=this.manifest.chunks.filter(e=>e.docType!==`CARD`&&e.docType!==`DISPLAYABLE_DATA`&&e.docType!==`TAG`);for(let n of t)if(e>=n.startKey&&e<=n.endKey&&await this.verifyDocumentInChunk(e,n))return n;return}}async verifyDocumentInChunk(e,t){try{return await this.loadChunk(t.id),this.documentCache.has(e)}catch{return!1}}async loadChunk(e){if(this.chunkCache.has(e))return;let t=this.manifest.chunks.find(t=>t.id===e);if(!t)throw Error(`Chunk ${e} not found in manifest`);try{let n=`${this.basePath}/${t.path}`;logger.debug(`Loading chunk from ${n}`);let r;if(this.isLocalPath(n)&&nodeFS){let e=await nodeFS.promises.readFile(n,`utf8`);r=JSON.parse(e)}else{let t=await fetch(n);if(!t.ok)throw Error(`Failed to fetch chunk ${e}: ${t.status} ${t.statusText}`);r=await t.json()}this.chunkCache.set(e,r);for(let e of r)e._id&&this.documentCache.set(e._id,e);logger.debug(`Loaded ${r.length} documents from chunk ${e}`)}catch(t){throw logger.error(`Failed to load chunk ${e}:`,t),t}}async loadIndex(e){if(this.indexCache.has(e))return this.indexCache.get(e);let t=this.manifest.indices.find(t=>t.name===e);if(!t)throw Error(`Index ${e} not found in manifest`);try{let n=`${this.basePath}/${t.path}`;logger.debug(`Loading index from ${n}`);let r;if(this.isLocalPath(n)&&nodeFS){let e=await nodeFS.promises.readFile(n,`utf8`);r=JSON.parse(e)}else{let t=await fetch(n);if(!t.ok)throw Error(`Failed to fetch index ${e}: ${t.status} ${t.statusText}`);r=await t.json()}return this.indexCache.set(e,r),logger.debug(`Loaded index ${e}`),r}catch(t){throw logger.error(`Failed to load index ${e}:`,t),t}}async getRawDocument(e){if(this.documentCache.has(e))return this.documentCache.get(e);let t=await this.findChunkForDocument(e);if(!t)throw logger.error(`Document ${e} not found in any chunk. Available chunks:`,this.manifest.chunks.map(e=>`${e.id} (${e.docType}): ${e.startKey} - ${e.endKey}`)),Error(`Document ${e} not found in any chunk`);if(await this.loadChunk(t.id),this.documentCache.has(e))return this.documentCache.get(e);throw logger.error(`Document ${e} not found in chunk ${t.id}`),Error(`Document ${e} not found in chunk ${t.id}`)}getAttachmentUrl(e,t){return`${this.basePath}/attachments/${e}/${t}`}async getAttachmentPath(e,t){try{let n=await this.getRawDocument(e);if(n._attachments&&n._attachments[t]){let e=n._attachments[t];if(e.path)return`${this.basePath}/${e.path}`}return null}catch{return null}}async getAttachmentBlob(e,t){let n=await this.getAttachmentPath(e,t);if(!n)return null;try{if(this.isLocalPath(n)&&nodeFS)return await nodeFS.promises.readFile(n);{let r=await fetch(n);if(!r.ok)throw Error(`Failed to fetch attachment ${e}/${t}: ${r.status} ${r.statusText}`);return await r.blob()}}catch(n){return logger.error(`Failed to load attachment ${e}/${t}:`,n),null}}async hydrateAttachments(e){let t=e;if(!t._attachments)return e;let n=JSON.parse(JSON.stringify(e));for(let[e,r]of Object.entries(t._attachments)){let a=r;if(a.path)try{let r=await this.getAttachmentBlob(t._id,e);r?typeof window<`u`&&window.URL?n._attachments[e]={...a,data:r,stub:!1}:n._attachments[e]={...a,buffer:r}:logger.warn(`[hydrateAttachments] getAttachmentBlob returned null for ${t._id}/${e}. Skipping hydration for this attachment.`)}catch(n){logger.warn(`[hydrateAttachments] Failed to hydrate attachment ${t._id}/${e}:`,n)}else logger.debug(`[hydrateAttachments] Attachment ${e} for doc ${t._id} has no path. Skipping blob conversion.`)}return n}clearCaches(){this.documentCache.clear(),this.chunkCache.clear(),this.indexCache.clear()}getCacheStats(){return{documents:this.documentCache.size,chunks:this.chunkCache.size,indices:this.indexCache.size}}isLocalPath(e){return!e.startsWith(`http://`)&&!e.startsWith(`https://`)&&(pathUtils.isAbsolute(e)||e.startsWith(`./`)||e.startsWith(`../`))}}}}),StaticCourseDB,init_courseDB2=__esm({"src/impl/static/courseDB.ts"(){init_types_legacy(),init_logger(),init_defaults(),init_PipelineAssembler(),StaticCourseDB=class{constructor(e,t,n,r){_defineProperty(this,`_pendingHints`,null),this.courseId=e,this.unpacker=t,this.userDB=n,this.manifest=r}getCourseID(){return this.courseId}async getCourseConfig(){if(this.manifest.courseConfig!=null)return this.manifest.courseConfig;throw Error(`Course config not found for course ${this.courseId}`)}async updateCourseConfig(e){throw Error(`Cannot update course config in static mode`)}async getCourseInfo(){return{cardCount:this.manifest.chunks.filter(e=>e.docType===`CARD`).reduce((e,t)=>e+t.documentCount,0),registeredUsers:0}}async getCourseDoc(e,t){return this.unpacker.getDocument(e)}async getCourseDocs(e,t){let n=await Promise.all(e.map(async e=>{try{return{id:e,key:e,value:{rev:`1-static`},doc:await this.unpacker.getDocument(e)}}catch{return{key:e,error:`not_found`}}}));return{total_rows:e.length,offset:0,rows:n}}async getCardsByELO(e,t){return(await this.unpacker.queryByElo(e,t||25)).map(e=>{let[t,n,r]=e.split(`-`);return{courseID:t,cardID:n,elo:r?parseInt(r):void 0}})}async getCardEloData(e){return await Promise.all(e.map(async e=>{try{return(await this.unpacker.getDocument(e)).elo||{global:{score:1e3,count:0},tags:{},misc:{}}}catch{return{global:{score:1e3,count:0},tags:{},misc:{}}}}))}async updateCardElo(e,t){return{ok:!0,id:e,rev:`1-static`}}async getCardsCenteredAtELO(e,t){let n=typeof e.elo==`number`?e.elo:1e3;if(e.elo===`user`)try{let e=(await this.userDB.getCourseRegistrationsDoc()).courses.find(e=>e.courseID===this.courseId);e&&typeof e.elo==`object`&&(n=e.elo.global.score)}catch{n=1e3}else e.elo===`random`&&(n=800+Math.random()*400);let r=(await this.unpacker.queryByElo(n,e.limit*2)).map(e=>({cardID:e,courseID:this.courseId}));return t&&(r=r.filter(t)),r.slice(0,e.limit).map(e=>({status:`new`,cardID:e.cardID,contentSourceType:`course`,contentSourceID:this.courseId,courseID:this.courseId}))}async getAppliedTags(e){try{let t=await this.unpacker.getTagsIndex(),n=t.byCard[e]||[],r=await Promise.all(n.map(async n=>{let r=`TAG-${n}`;try{let t=await this.unpacker.getDocument(r);return{id:r,key:e,value:{name:t.name,snippet:t.snippet,count:t.taggedCards?.length||0}}}catch(a){if(a&&a.status===404)logger.warn(`Tag document not found for ${n}, creating stub`);else throw logger.error(`Error getting tag document for ${n}:`,a),a;return{id:r,key:e,value:{name:n,snippet:`Tag: ${n}`,count:t.byTag[n]?.length||0}}}}));return{total_rows:r.length,offset:0,rows:r}}catch(t){return logger.error(`Error getting applied tags for card ${e}:`,t),{total_rows:0,offset:0,rows:[]}}}async getAppliedTagsBatch(e){let t=await this.unpacker.getTagsIndex(),n=new Map;for(let r of e)n.set(r,t.byCard[r]||[]);return n}async getAllCardIds(){let e=await this.unpacker.getTagsIndex();return Object.keys(e.byCard)}async addTagToCard(e,t){throw Error(`Cannot modify tags in static mode`)}async removeTagFromCard(e,t){throw Error(`Cannot modify tags in static mode`)}async createTag(e){throw Error(`Cannot create tags in static mode`)}async getTag(e){return this.unpacker.getDocument(`TAG-${e}`)}async updateTag(e){throw Error(`Cannot update tags in static mode`)}async getCourseTagStubs(){try{let e=await this.unpacker.getTagsIndex();if(!e||!e.byTag)return logger.warn(`Tags index not found or empty`),{total_rows:0,offset:0,rows:[]};let t=Object.keys(e.byTag),n=await Promise.all(t.map(async t=>{let n=e.byTag[t]||[],r=`TAG-${t}`;try{return{id:r,key:r,value:{rev:`1-static`},doc:await this.unpacker.getDocument(r)}}catch(e){if(e&&e.status===404)return logger.warn(`Tag document not found for ${t}, creating stub`),{id:r,key:r,value:{rev:`1-static`},doc:{_id:r,_rev:`1-static`,course:this.courseId,docType:`TAG`,name:t,snippet:`Tag: ${t}`,wiki:``,taggedCards:n,author:`system`}};throw logger.error(`Error getting tag document for ${t}:`,e),e}}));return{total_rows:n.length,offset:0,rows:n}}catch(e){return logger.error(`Failed to get course tag stubs:`,e),{total_rows:0,offset:0,rows:[]}}}async addNote(e,t,n,r,a,o,s){return{status:Status.error,message:`Cannot add notes in static mode`}}async removeCard(e){throw Error(`Cannot remove cards in static mode`)}async getInexperiencedCards(){return[]}async getNavigationStrategy(e){try{return await this.unpacker.getDocument(e)}catch(t){throw logger.error(`[static/courseDB] Strategy ${e} not found: ${t}`),t}}async getAllNavigationStrategies(){let e=DocTypePrefixes.NAVIGATION_STRATEGY;try{return await this.unpacker.getAllDocumentsByPrefix(e)}catch(e){return logger.warn(`[static/courseDB] Error loading navigation strategies: ${e}`),[]}}async addNavigationStrategy(e){throw Error(`Cannot add navigation strategies in static mode`)}async updateNavigationStrategy(e,t){throw Error(`Cannot update navigation strategies in static mode`)}async createNavigator(e){try{let t=await this.getAllNavigationStrategies();if(t.length===0)return logger.debug(`[static/courseDB] No strategy documents found, using default Pipeline(Composite(ELO, SRS), [eloDistanceFilter])`),createDefaultPipeline(e,this);let{pipeline:n,generatorStrategies:r,filterStrategies:a,warnings:o}=await new PipelineAssembler().assemble({strategies:t,user:e,course:this});for(let e of o)logger.warn(`[PipelineAssembler] ${e}`);return n?(logger.debug(`[static/courseDB] Using assembled pipeline with ${r.length} generator(s) and ${a.length} filter(s)`),n):(logger.debug(`[static/courseDB] Pipeline assembly failed, using default pipeline`),createDefaultPipeline(e,this))}catch(e){throw logger.error(`[static/courseDB] Error creating navigator: ${e}`),e}}setEphemeralHints(e){this._pendingHints=e}async getWeightedCards(e){try{let t=await this.createNavigator(this.userDB);return this._pendingHints&&(t.setEphemeralHints(this._pendingHints),this._pendingHints=null),t.getWeightedCards(e)}catch(e){throw logger.error(`[static/courseDB] Error getting weighted cards: ${e}`),e}}getAttachmentUrl(e,t){return this.unpacker.getAttachmentUrl(e,t)}async getAttachmentBlob(e,t){return this.unpacker.getAttachmentBlob(e,t)}async searchCards(e){return[]}async find(e){return{docs:[],warning:`Find operations not supported in static mode`}}}}}),StaticCoursesDB,init_coursesDB=__esm({"src/impl/static/coursesDB.ts"(){init_logger(),StaticCoursesDB=class{constructor(e,t){this.manifests=e,this.dependencyNameToCourseId=t}async getCourseConfig(e){let t=this.manifests[e];if(!t&&this.dependencyNameToCourseId){let n=this.dependencyNameToCourseId.get(e);n&&(t=this.manifests[n])}if(!t)throw logger.warn(`Course manifest for ${e} not found`),Error(`Course ${e} not found`);if(t.courseConfig)return t.courseConfig;throw logger.warn(`Course config not found in manifest for course ${e}`),Error(`Course config not found for course ${e}`)}async getCourseList(){return Object.keys(this.manifests).map(e=>({courseID:e,name:this.manifests[e].courseName}))}async disambiguateCourse(e,t){logger.warn(`Cannot disambiguate courses in static mode`)}}}}),NoOpSyncStrategy,init_NoOpSyncStrategy=__esm({"src/impl/static/NoOpSyncStrategy.ts"(){init_common(),NoOpSyncStrategy=class{constructor(){_defineProperty(this,`currentUsername`,accomodateGuest().username)}setupRemoteDB(e){return getLocalUserDB(e)}getWriteDB(e){return getLocalUserDB(e)}startSync(e,t){}stopSync(){}canCreateAccount(){return!1}canAuthenticate(){return!1}async createAccount(e,t){throw Error(`Account creation not supported in static mode. Use local account switching instead.`)}async authenticate(e,t){throw Error(`Remote authentication not supported in static mode. Use local account switching instead.`)}async logout(){return this.currentUsername=accomodateGuest().username,{ok:!0}}async getCurrentUsername(){return this.currentUsername}setCurrentUsername(e){this.currentUsername=e}}}}),StaticDataLayerProvider_exports={};__export(StaticDataLayerProvider_exports,{StaticDataLayerProvider:()=>StaticDataLayerProvider});var StaticDataLayerProvider,init_StaticDataLayerProvider=__esm({"src/impl/static/StaticDataLayerProvider.ts"(){init_logger(),init_StaticDataUnpacker(),init_courseDB2(),init_coursesDB(),init_common(),init_NoOpSyncStrategy(),StaticDataLayerProvider=class{constructor(e){_defineProperty(this,`config`,void 0),_defineProperty(this,`initialized`,!1),_defineProperty(this,`courseUnpackers`,new Map),_defineProperty(this,`manifests`,{}),_defineProperty(this,`dependencyNameToCourseId`,new Map),this.config={localStoragePrefix:e.localStoragePrefix||`skuilder-static`,rootManifest:e.rootManifest||{dependencies:{}},rootManifestUrl:e.rootManifestUrl||`/`}}async resolveCourseDependencies(){logger.info(`[StaticDataLayerProvider] Starting course dependency resolution...`);let e=this.config.rootManifest;for(let[t,n]of Object.entries(e.dependencies||{}))try{logger.debug(`[StaticDataLayerProvider] Resolving dependency: ${t} from ${n}`);let e=new URL(n,this.config.rootManifestUrl).href,r=await fetch(e);if(!r.ok)throw Error(`Failed to fetch course manifest for ${t}`);let a=await r.json();if(a.content&&a.content.manifest){let n=new URL(`.`,e).href,r=new URL(a.content.manifest,e).href,o=await fetch(r);if(!o.ok)throw Error(`Failed to fetch final content manifest for ${t} at ${r}`);let s=await o.json(),c=s.courseId||s.courseConfig?.courseID;if(!c)throw Error(`Course manifest for ${t} missing courseId`);this.manifests[c]=s;let l=new StaticDataUnpacker(s,n);this.courseUnpackers.set(c,l),this.dependencyNameToCourseId.set(t,c),logger.info(`[StaticDataLayerProvider] Successfully resolved and prepared course: ${t} (courseId: ${c})`)}}catch(e){logger.error(`[StaticDataLayerProvider] Failed to resolve dependency ${t}:`,e)}logger.info(`[StaticDataLayerProvider] Course dependency resolution complete.`)}async initialize(){this.initialized||(logger.info(`Initializing static data layer provider`),await this.resolveCourseDependencies(),this.initialized=!0)}async teardown(){this.courseUnpackers.clear(),this.initialized=!1}getUserDB(){let e=new NoOpSyncStrategy;return BaseUser.Dummy(e)}getCourseDB(e){let t=this.courseUnpackers.get(e),n=e;if(!t){let r=this.dependencyNameToCourseId.get(e);r&&(t=this.courseUnpackers.get(r),n=r)}if(!t)throw Error(`Course ${e} not found or failed to initialize in static data layer.`);let r=this.manifests[n];return new StaticCourseDB(n,t,this.getUserDB(),r)}getCoursesDB(){return new StaticCoursesDB(this.manifests,this.dependencyNameToCourseId)}async getClassroomDB(e,t){throw Error(`Classrooms not supported in static mode`)}getAdminDB(){throw Error(`Admin functions not supported in static mode`)}async createUserReaderForUser(e){return logger.warn(`StaticDataLayerProvider: Multi-user access not supported in static mode`),logger.warn(`Request: trying to access data for ${e}`),logger.warn(`Returning current user's data instead`),this.getUserDB()}isReadOnly(){return!0}}}});async function initializeDataLayer(e){if(dataLayerInstance)return logger.warn(`Data layer already initialized. Returning existing instance.`),dataLayerInstance;if(await initializeNavigatorRegistry(),e.options.localStoragePrefix&&(ENV.LOCAL_STORAGE_PREFIX=e.options.localStoragePrefix),e.type===`couch`){if(!e.options.COUCHDB_SERVER_URL||!e.options.COUCHDB_SERVER_PROTOCOL)throw Error(`Missing CouchDB server URL or protocol`);if(ENV.COUCHDB_SERVER_PROTOCOL=e.options.COUCHDB_SERVER_PROTOCOL,ENV.COUCHDB_SERVER_URL=e.options.COUCHDB_SERVER_URL,ENV.COUCHDB_USERNAME=e.options.COUCHDB_USERNAME,ENV.COUCHDB_PASSWORD=e.options.COUCHDB_PASSWORD,e.options.courseSync){let{CourseSyncService:t}=await Promise.resolve().then(()=>(init_CourseSyncService(),CourseSyncService_exports));t.getInstance().configure(e.options.courseSync)}if(e.options.COUCHDB_PASSWORD&&e.options.COUCHDB_USERNAME&&typeof window<`u`){let{CouchDBSyncStrategy:t}=await Promise.resolve().then(()=>(init_CouchDBSyncStrategy(),CouchDBSyncStrategy_exports)),n=new t,r=await(await BaseUser.instance(n,e.options.COUCHDB_USERNAME)).login(e.options.COUCHDB_USERNAME,e.options.COUCHDB_PASSWORD);r.ok?logger.info(`Successfully authenticated as ${e.options.COUCHDB_USERNAME}`):logger.warn(`Authentication failed: ${r.error}`)}let{CouchDataLayerProvider:t}=await Promise.resolve().then(()=>(init_PouchDataLayerProvider(),PouchDataLayerProvider_exports));dataLayerInstance=new t(e.options.COURSE_IDS)}else if(e.type===`static`){let{StaticDataLayerProvider:t}=await Promise.resolve().then(()=>(init_StaticDataLayerProvider(),StaticDataLayerProvider_exports));dataLayerInstance=new t(e.options)}else throw Error(`Unknown data layer type: ${e.type}`);return await dataLayerInstance.initialize(),dataLayerInstance}function getDataLayer(){if(!dataLayerInstance)throw Error(`Data layer not initialized. Call initializeDataLayer first.`);return dataLayerInstance}async function _resetDataLayer(){dataLayerInstance&&await dataLayerInstance.teardown(),dataLayerInstance=null}var NOT_SET,ENV,dataLayerInstance,init_factory=__esm({"src/factory.ts"(){init_common(),init_logger(),init_navigators(),NOT_SET=`NOT_SET`,ENV={COUCHDB_SERVER_PROTOCOL:NOT_SET,COUCHDB_SERVER_URL:NOT_SET,LOCAL_STORAGE_PREFIX:``},dataLayerInstance=null}}),TagFilteredContentSource,init_TagFilteredContentSource=__esm({"src/study/TagFilteredContentSource.ts"(){init_courseDB(),init_logger(),TagFilteredContentSource=class{constructor(e,t,n){_defineProperty(this,`courseId`,void 0),_defineProperty(this,`filter`,void 0),_defineProperty(this,`user`,void 0),_defineProperty(this,`resolvedCardIds`,null),this.courseId=e,this.filter=t,this.user=n,logger.info(`[TagFilteredContentSource] Created for course "${e}" with filter:`,JSON.stringify(t))}async resolveFilteredCardIds(){if(this.resolvedCardIds!==null)return this.resolvedCardIds;let e=new Set;if(this.filter.include.length>0)for(let t of this.filter.include)try{(await getTag(this.courseId,t)).taggedCards.forEach(t=>e.add(t))}catch(e){logger.warn(`[TagFilteredContentSource] Could not resolve tag "${t}" for inclusion:`,e)}if(e.size===0&&this.filter.include.length>0)return logger.warn(`[TagFilteredContentSource] No cards found for include tags: ${this.filter.include.join(`, `)}`),this.resolvedCardIds=new Set,this.resolvedCardIds;let t=new Set;if(this.filter.exclude.length>0)for(let e of this.filter.exclude)try{(await getTag(this.courseId,e)).taggedCards.forEach(e=>t.add(e))}catch(t){logger.warn(`[TagFilteredContentSource] Could not resolve tag "${e}" for exclusion:`,t)}let n=new Set;for(let r of e)t.has(r)||n.add(r);return logger.info(`[TagFilteredContentSource] Resolved ${n.size} cards (included: ${e.size}, excluded: ${t.size})`),this.resolvedCardIds=n,n}async getWeightedCards(e){if(!hasActiveFilter(this.filter))return logger.warn(`[TagFilteredContentSource] getWeightedCards called with no active filter`),{cards:[]};let t=await this.resolveFilteredCardIds(),n=await this.user.getActiveCards(),r=new Set(n.map(e=>e.cardID)),a=[];for(let n of t)if(r.has(n)||a.push({cardId:n,courseId:this.courseId,score:1,provenance:[{strategy:`tagFilter`,strategyName:`Tag Filter`,strategyId:`TAG_FILTER`,action:`generated`,score:1,reason:`Tag-filtered new card (tags: ${this.filter.include.join(`, `)})`}]}),a.length>=e)break;logger.info(`[TagFilteredContentSource] Found ${a.length} new cards matching filter`);let o=await this.user.getPendingReviews(this.courseId),s=o.filter(e=>t.has(e.cardId));return logger.info(`[TagFilteredContentSource] Found ${s.length} pending reviews matching filter (of ${o.length} total)`),{cards:[...s.map(e=>({cardId:e.cardId,courseId:e.courseId,score:1,reviewID:e._id,provenance:[{strategy:`tagFilter`,strategyName:`Tag Filter`,strategyId:`TAG_FILTER`,action:`generated`,score:1,reason:`Tag-filtered review (tags: ${this.filter.include.join(`, `)})`}]})),...a].slice(0,e)}}clearCache(){this.resolvedCardIds=null}getCourseId(){return this.courseId}getFilter(){return this.filter}}}});function isReview(e){return e.status===`review`||e.status===`failed-review`||`reviewID`in e}async function getStudySource(e,t){return e.type===`classroom`?await StudentClassroomDB.factory(e.id,t):hasActiveFilter(e.tagFilter)?new TagFilteredContentSource(e.id,e.tagFilter,t):getDataLayer().getCourseDB(e.id)}var init_contentSource=__esm({"src/core/interfaces/contentSource.ts"(){init_factory(),init_classroomDB2(),init_TagFilteredContentSource()}}),init_courseDB3=__esm({"src/core/interfaces/courseDB.ts"(){}}),init_dataLayerProvider=__esm({"src/core/interfaces/dataLayerProvider.ts"(){}}),init_userDB=__esm({"src/core/interfaces/userDB.ts"(){}}),init_interfaces=__esm({"src/core/interfaces/index.ts"(){init_adminDB(),init_classroomDB(),init_contentSource(),init_courseDB3(),init_dataLayerProvider(),init_userDB()}}),init_user=__esm({"src/core/types/user.ts"(){}});function buildStrategyStateId(e,t){return`STRATEGY_STATE::${e}::${t}`}var init_strategyState=__esm({"src/core/types/strategyState.ts"(){}}),init_userOutcome=__esm({"src/core/types/userOutcome.ts"(){}});function makeStudySessionId(e,t,n){return`${DocTypePrefixes.STUDY_SESSION}::${e}::${t}::${n}`}function newSessionId(){return`session-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}var init_studySession=__esm({"src/core/types/studySession.ts"(){init_types_legacy()}}),HYDRATION_MARKER_ID,init_hydration=__esm({"src/core/types/hydration.ts"(){HYDRATION_MARKER_ID=`_local/hydration`}});async function importParsedCards(e,t,n){let r=[];for(let a of e)try{let e=await processCard(a,t,n);r.push(e)}catch(e){logger.error(`Error processing card:`,e);let t=a.markdown;a.tags&&a.tags.length>0&&(t+=`
|
|
282
|
-
tags: ${a.tags.join(`, `)}`),a.elo!==void 0&&(t+=`
|
|
283
|
-
elo: ${a.elo}`),r.push({originalText:t,status:`error`,message:`Error processing card: ${e instanceof Error?e.message:`Unknown error`}`})}return r}async function processCard(e,t,n){let{markdown:r,tags:a,elo:o}=e,s=r;a.length>0&&(s+=`
|
|
284
|
-
tags: ${a.join(`, `)}`),o!==void 0&&(s+=`
|
|
285
|
-
elo: ${o}`);let c={Input:r,Uploads:[]},l={};for(let e of a)l[e]={score:o||0,count:1};try{let e=await t.addNote(n.courseCode,n.dataShape,c,n.userName,a,void 0,o?{global:{score:o,count:1},tags:l,misc:{}}:void 0);return e.status===Status.ok?{originalText:s,status:`success`,message:`Card added successfully.`,cardId:e.id?e.id:`(unknown)`}:{originalText:s,status:`error`,message:e.message||`Failed to add card to database. Unknown error.`}}catch(e){return logger.error(`Error adding note:`,e),{originalText:s,status:`error`,message:`Error adding card: ${e instanceof Error?e.message:`Unknown error`}`}}}function validateProcessorConfig(e){return e.dataShape?e.courseCode?e.userName?{isValid:!0}:{isValid:!1,errorMessage:`No user name provided for card processing`}:{isValid:!1,errorMessage:`No course code provided for card processing`}:{isValid:!1,errorMessage:`No data shape provided for card processing`}}var init_cardProcessor=__esm({"src/core/bulkImport/cardProcessor.ts"(){init_logger()}}),init_types3=__esm({"src/core/bulkImport/types.ts"(){}}),init_bulkImport=__esm({"src/core/bulkImport/index.ts"(){init_cardProcessor(),init_types3()}});function getUserDB(){try{return getDataLayer().getUserDB()}catch{return logger.info(`[UserDB Debug] Data layer not initialized yet.`),null}}function getRawDB(){let e=getUserDB();return e?e.localDB||(logger.info(`[UserDB Debug] Unable to access raw database instance.`),null):null}function formatTimestamp(e){return new Date(e).toLocaleString()}function mountUserDBDebugger(){if(typeof window>`u`)return;let e=window;e.skuilder=e.skuilder||{},e.skuilder.userdb=userDBDebugAPI}var userDBDebugAPI,init_UserDBDebugger=__esm({"src/core/UserDBDebugger.ts"(){init_logger(),init_factory(),init_types_legacy(),init_userDBHelpers(),userDBDebugAPI={showUser(){let e=getUserDB();e&&(console.group(`👤 User Information`),logger.info(`Username: ${e.getUsername()}`),logger.info(`Logged in: ${e.isLoggedIn()?`Yes ✅`:`No (Guest) ❌`}`),e.getConfig().then(e=>{logger.info(`Configuration:`),logger.info(JSON.stringify(e,null,2))}).catch(e=>{logger.info(`Error loading config: ${e.message}`)}).finally(()=>{console.groupEnd()}))},async showScheduledReviews(e){let t=getUserDB();if(!t){logger.info(`[UserDB Debug] Data layer not available`);return}logger.info(`[UserDB Debug] Fetching pending reviews${e?` for course: ${e}`:``}...`);try{let n=await t.getPendingReviews(e);if(logger.info(`[UserDB Debug] Got ${n.length} reviews`),console.group(`\u{1F4C5} Scheduled Reviews${e?` (${e})`:``}`),logger.info(`Total: ${n.length}`),n.length>0){let e=new Map;for(let t of n)e.has(t.courseId)||e.set(t.courseId,[]),e.get(t.courseId).push(t);for(let[t,n]of e){console.group(`Course: ${t} (${n.length} reviews)`);let e=n.sort((e,t)=>{let n=typeof e.reviewTime==`string`?e.reviewTime:e.reviewTime.toISOString(),r=typeof t.reviewTime==`string`?t.reviewTime:t.reviewTime.toISOString();return new Date(n).getTime()-new Date(r).getTime()});for(let t of e.slice(0,10)){let e=typeof t.reviewTime==`string`?t.reviewTime:t.reviewTime.toISOString();logger.info(` ${t.cardId.slice(0,12)}... @ ${formatTimestamp(e)} [${t.scheduledFor}/${t.schedulingAgentId}]`)}e.length>10&&logger.info(` ... and ${e.length-10} more`),console.groupEnd()}}console.groupEnd()}catch(e){logger.info(`Error loading scheduled reviews: ${e.message}`)}},async showCourseRegistrations(){let e=getUserDB();if(e)try{let t=await e.getActiveCourses();console.group(`📚 Course Registrations`),logger.info(`Total: ${t.length}`),t.length>0&&console.table(t.map(e=>({courseId:e.courseID,status:e.status||`active`,elo:typeof e.elo==`number`?e.elo.toFixed(0):e.elo?.global?.score?.toFixed(0)||`N/A`}))),console.groupEnd()}catch(e){logger.info(`Error loading course registrations: ${e.message}`)}},async showCardHistory(e){let t=getRawDB();if(t)try{let n=(await filterAllDocsByPrefix(t,DocTypePrefixes.CARDRECORD)).rows.filter(t=>t.doc&&t.doc.cardID===e).map(e=>e.doc);if(console.group(`\u{1F3B4} Card History: ${e}`),logger.info(`Total interactions: ${n.length}`),n.length>0){let e=n.sort((e,t)=>new Date(t.timestamp).getTime()-new Date(e.timestamp).getTime());console.table(e.slice(0,20).map(e=>({time:formatTimestamp(e.timestamp),outcome:e.outcome||`N/A`,duration:e.duration?`${(e.duration/1e3).toFixed(1)}s`:`N/A`,courseId:e.courseId}))),e.length>20&&logger.info(`... and ${e.length-20} more interactions`)}console.groupEnd()}catch(e){logger.info(`Error loading card history: ${e.message}`)}},async queryByType(e,t=50){let n=getRawDB();if(n)try{let r=DocTypePrefixes[DocType[e]];if(!r){logger.info(`Unknown document type: ${e}`);return}let a=await filterAllDocsByPrefix(n,r);if(console.group(`\u{1F4C4} Documents: ${e}`),logger.info(`Total: ${a.rows.length}`),logger.info(`Prefix: ${r}`),a.rows.length>0){logger.info(`Sample documents:`);let e=a.rows.slice(0,Math.min(t,a.rows.length));for(let t of e)logger.info(`
|
|
286
|
-
${t.id}:`),logger.info(JSON.stringify(t.doc,null,2));a.rows.length>t&&logger.info(`
|
|
287
|
-
... and ${a.rows.length-t} more documents`)}console.groupEnd()}catch(e){logger.info(`Error querying documents: ${e.message}`)}},async dbInfo(){let e=getRawDB();if(e)try{let t=await e.info();console.group(`ℹ️ Database Information`),logger.info(`Database name: ${t.db_name}`),logger.info(`Total documents: ${t.doc_count}`),logger.info(`Update sequence: ${t.update_seq}`),`disk_size`in t&&logger.info(`Disk size: ${(t.disk_size||0)/1024/1024} MB`),logger.info(`
|
|
288
|
-
Document counts by type:`);let n=await e.allDocs({include_docs:!1}),r=new Map;for(let e of n.rows){let t=`other`;for(let[n,r]of Object.entries(DocTypePrefixes))if(e.id.startsWith(r)){t=n;break}r.set(t,(r.get(t)||0)+1)}console.table(Array.from(r.entries()).sort((e,t)=>t[1]-e[1]).map(([e,t])=>({type:e,count:t}))),console.groupEnd()}catch(e){logger.info(`Error getting database info: ${e.message}`)}},listDocTypes(){console.group(`📋 Available Document Types`),logger.info(`Use with queryByType(type):`);for(let[e,t]of Object.entries(DocTypePrefixes))logger.info(` ${e.padEnd(30)} \u2192 prefix: "${t}"`);console.groupEnd()},async export(e=!1){let t=getRawDB(),n=getUserDB();if(!t||!n)return`{}`;try{let r={username:n.getUsername(),loggedIn:n.isLoggedIn(),timestamp:new Date().toISOString()};if(e){let e=await t.allDocs({include_docs:!0});r.documents=e.rows.map(e=>({id:e.id,doc:e.doc})),r.totalDocs=e.rows.length}else{let e=await t.allDocs({include_docs:!1});r.totalDocs=e.rows.length;let n=new Map;for(let t of e.rows){let e=`other`;for(let[n,r]of Object.entries(DocTypePrefixes))if(t.id.startsWith(r)){e=n;break}n.set(e,(n.get(e)||0)+1)}r.docCounts=Object.fromEntries(n)}let a=JSON.stringify(r,null,2);return logger.info(`[UserDB Debug] Database info exported. Copy the returned string or use:`),logger.info(` copy(window.skuilder.userdb.export())`),e||logger.info(` For full content export: window.skuilder.userdb.export(true)`),a}catch(e){return logger.info(`Error exporting database: ${e.message}`),`{}`}},async raw(e){let t=getRawDB();if(t)try{let n=await e(t);logger.info(`[UserDB Debug] Query result:`),logger.info(n)}catch(e){logger.info(`[UserDB Debug] Query error: ${e.message}`)}},help(){logger.info(`
|
|
289
|
-
🔧 UserDB Debug API
|
|
290
|
-
|
|
291
|
-
Commands:
|
|
292
|
-
.showUser() Show current user info and config
|
|
293
|
-
.showScheduledReviews(courseId?) Show scheduled reviews (optionally filter by course)
|
|
294
|
-
.showCourseRegistrations() Show all course registrations
|
|
295
|
-
.showCardHistory(cardId) Show interaction history for a card
|
|
296
|
-
.queryByType(docType, limit?) Query documents by type (e.g., 'SCHEDULED_CARD')
|
|
297
|
-
.listDocTypes() List all available document types
|
|
298
|
-
.dbInfo() Show database info and statistics
|
|
299
|
-
.export(includeContent?) Export database info (true = include all docs)
|
|
300
|
-
.raw(queryFn) Execute raw PouchDB query
|
|
301
|
-
.help() Show this help message
|
|
302
|
-
|
|
303
|
-
Examples:
|
|
304
|
-
window.skuilder.userdb.showUser()
|
|
305
|
-
window.skuilder.userdb.showScheduledReviews('course123')
|
|
306
|
-
window.skuilder.userdb.queryByType('SCHEDULED_CARD', 10)
|
|
307
|
-
window.skuilder.userdb.raw(db => db.allDocs({ limit: 5 }))
|
|
308
|
-
`)}},mountUserDBDebugger()}}),init_core=__esm({"src/core/index.ts"(){init_interfaces(),init_types_legacy(),init_user(),init_strategyState(),init_userOutcome(),init_studySession(),init_hydration(),init_Loggable(),init_util(),init_navigators(),init_bulkImport(),init_orchestration(),init_UserDBDebugger()}});init_core(),init_courseLookupDB(),init_logger();function isDataShapeRegistered(e,t){let n=NameSpacer.getDataShapeString({dataShape:e.name,course:e.course});return t.dataShapes.find(e=>e.name===n)!==void 0}function isDataShapeSchemaAvailable(e,t){let n=NameSpacer.getDataShapeString({dataShape:e.name,course:e.course}),r=t.dataShapes.find(e=>e.name===n);return r!==void 0&&r.serializedZodSchema!==void 0}function isQuestionTypeRegistered(e,t){let n=NameSpacer.getQuestionString({course:e.course,questionType:e.name});return t.questionTypes.some(e=>e.name===n)}function processCustomQuestionsData(e){let t=[],n=[],r=e.courses.map(e=>e.name);return e.questionClasses.forEach(a=>{let o=r.length>0?r[0]:e.meta.packageName;a.dataShapes&&Array.isArray(a.dataShapes)&&a.dataShapes.forEach(e=>{t.push({name:e.name,course:o,dataShape:e})}),n.push({name:a.name,course:o,questionClass:a,dataShapes:a.dataShapes||[],views:a.views||[]})}),{dataShapes:t,questions:n}}function registerDataShape(e,t){let n=NameSpacer.getDataShapeString({dataShape:e.name,course:e.course}),r;try{r=toZodJSON(e.dataShape)}catch(e){logger.warn(`Failed to generate schema for ${n}:`,e),r=void 0}let a=t.dataShapes.findIndex(e=>e.name===n);if(a!==-1){let o=t.dataShapes[a];return o.serializedZodSchema===r?(logger.info(`DataShape '${e.name}' from '${e.course}' already registered with identical schema`),!1):(o.serializedZodSchema?logger.info(`DataShape '${e.name}' from '${e.course}' schema has changed, updating...`):logger.info(`DataShape '${e.name}' from '${e.course}' already registered, but with no schema. Adding schema to existing entry`),t.dataShapes[a]={name:n,questionTypes:o.questionTypes,serializedZodSchema:r},logger.info(`Updated DataShape: ${n}`),!0)}return t.dataShapes.push({name:n,questionTypes:[],serializedZodSchema:r}),logger.info(`Registered DataShape: ${n}`),!0}function registerQuestionType(e,t){if(isQuestionTypeRegistered(e,t))return logger.info(`QuestionType '${e.name}' from '${e.course}' already registered`),!1;let n=NameSpacer.getQuestionString({course:e.course,questionType:e.name}),r=e.views.map(e=>e.name?e.name:`unnamedComponent`),a=e.dataShapes.map(t=>NameSpacer.getDataShapeString({course:e.course,dataShape:t.name}));return t.questionTypes.push({name:n,viewList:r,dataShapeList:a}),e.dataShapes.forEach(r=>{let a=NameSpacer.getDataShapeString({course:e.course,dataShape:r.name});for(let e of t.dataShapes)e.name===a&&e.questionTypes.push(n)}),logger.info(`Registered QuestionType: ${n}`),!0}function removeDataShape(e,t){let n=t.dataShapes.findIndex(t=>t.name===e);return n===-1?(logger.info(`DataShape '${e}' not found in course config`),!1):(t.dataShapes.splice(n,1),t.questionTypes.forEach(t=>{let n=t.dataShapeList.indexOf(e);n!==-1&&t.dataShapeList.splice(n,1)}),logger.info(`Removed DataShape: ${e}`),!0)}function removeQuestionType(e,t){let n=t.questionTypes.findIndex(t=>t.name===e);return n===-1?(logger.info(`QuestionType '${e}' not found in course config`),!1):(t.questionTypes.splice(n,1),t.dataShapes.forEach(t=>{let n=t.questionTypes.indexOf(e);n!==-1&&t.questionTypes.splice(n,1)}),logger.info(`Removed QuestionType: ${e}`),!0)}async function removeCustomQuestionTypes(e,t,n,r){try{logger.info(`Beginning custom question removal`),logger.info(`Removing ${e.length} data shapes and ${t.length} question types`);let a=0;for(let e of t)removeQuestionType(e,n)&&a++;for(let t of e)removeDataShape(t,n)&&a++;logger.info(`Updating course configuration...`);let o=await r.updateCourseConfig(n);if(!o.ok)throw Error(`Failed to update course config: ${JSON.stringify(o)}`);return logger.info(`Custom question removal complete: ${a} items removed`),{success:!0,removedCount:a}}catch(e){let t=e instanceof Error?e.message:String(e);return logger.error(`Custom question removal failed: ${t}`),{success:!1,removedCount:0,errorMessage:t}}}async function registerSeedData(e,t,n){if(e.questionClass.seedData&&Array.isArray(e.questionClass.seedData)){logger.info(`Registering seed data for question: ${e.name}`);try{let r=e.questionClass.seedData.filter(()=>e.dataShapes.length>0).map(r=>t.addNote(e.course,e.dataShapes[0],r,n,[]));await Promise.all(r),logger.info(`Seed data registered for question: ${e.name}`)}catch(t){logger.warn(`Failed to register seed data for question '${e.name}': ${t instanceof Error?t.message:String(t)}`)}}}async function registerBlanksCard(e,t,n,r,a){try{logger.info(`Registering BlanksCard data shapes and question type...`);let o=0,s=`default`;for(let e of t)registerDataShape({name:e.name,course:s,dataShape:e},n)&&o++;let c={name:e.name,course:s,questionClass:{name:e.name,dataShapes:t,views:e.views||[]},dataShapes:t,views:e.views||[]};registerQuestionType(c,n)&&o++,logger.info(`Updating course configuration with BlanksCard...`);let l=await r.updateCourseConfig(n);if(!l.ok)throw Error(`Failed to update course config: ${JSON.stringify(l)}`);return a&&await registerSeedData(c,r,a),logger.info(`BlanksCard registration complete: ${o} items registered`),{success:!0}}catch(e){let t=e instanceof Error?e.message:String(e);return logger.error(`BlanksCard registration failed: ${t}`),{success:!1,errorMessage:t}}}async function registerCustomQuestionTypes(e,t,n,r){try{logger.info(`Beginning custom question registration`),logger.info(`Processing ${e.questionClasses.length} question classes`);let{dataShapes:a,questions:o}=processCustomQuestionsData(e);logger.info(`Found ${a.length} data shapes and ${o.length} questions`);let s=0;logger.info(`Registering data shapes...`);for(let e of a)registerDataShape(e,t)&&s++;logger.info(`Registering question types...`);for(let e of o)registerQuestionType(e,t)&&s++;logger.info(`Updating course configuration...`);let c=await n.updateCourseConfig(t);if(!c.ok)throw Error(`Failed to update course config: ${JSON.stringify(c)}`);if(r){logger.info(`Registering seed data...`);for(let e of o)await registerSeedData(e,n,r)}return logger.info(`Custom question registration complete: ${s} items registered`),{success:!0,registeredCount:s}}catch(e){let t=e instanceof Error?e.message:String(e);return logger.error(`Custom question registration failed: ${t}`),{success:!1,registeredCount:0,errorMessage:t}}}init_couch(),init_util(),init_logger();var duration=hooks.duration;function newInterval(e,t){return areQuestionRecords(t)?newQuestionInterval(e,t):1e5}function newQuestionInterval(e,t){let n=t.records,r=n[n.length-1],a=lastSuccessfulInterval(n);if(a>t.bestInterval&&(t.bestInterval=a,e.update(t._id,{bestInterval:a}).catch(e=>{logger.warn(`[SpacedRepetition] Failed to update bestInterval for ${t._id}: ${e?.message??e}`)})),r.isCorrect){let e=r.performance,n=isTaggedPerformance(e)?e._global:e,o=Math.min(1,Math.max(0,n));logger.debug(`Demontrated skill: ${o}`);let s=a*(.75+o);if(t.lapses=getLapses(t.records),t.streak=getStreak(t.records),t.lapses&&t.streak&&t.bestInterval&&(t.lapses>=0||t.streak>=0)){let e=(t.lapses*s+t.streak*t.bestInterval)/(t.lapses+t.streak);return logger.debug(`Weighted average interval calculation:
|
|
309
|
-
(${t.lapses} * ${s} + ${t.streak} * ${t.bestInterval}) / (${t.lapses} + ${t.streak}) = ${e}`),e}else return s}else return 0}function lastSuccessfulInterval(e){for(let t=e.length-1;t>=1;t--)if(e[t].priorAttemps===0&&e[t].isCorrect){let n=secondsBetween(e[t-1].timeStamp,e[t].timeStamp),r=Math.max(n,1200*60);return logger.debug(`Last interval w/ this card was: ${n}s, returning ${r}s`),r}return getInitialInterval(e)}function getStreak(e){let t=0,n=e.length-1;for(;n>=0&&e[n].isCorrect;)n--,t++;return t}function getLapses(e){return e.filter(e=>e.isCorrect===!1).length}function getInitialInterval(e){return logger.warn(`history of length: ${e.length} ignored!`),3600*24*3}function secondsBetween(e,t){return e=hooks(e),t=hooks(t),duration(t.diff(e)).asSeconds()}init_logger();var SrsService=class{constructor(e){_defineProperty(this,`user`,void 0),this.user=e}removeReview(e){logger.info(`[SrsService] Removing orphaned scheduled review: ${e}`),this.user.removeScheduledCardReview(e)}async scheduleReview(e,t){let n=newInterval(this.user,e),r=hooks.utc().add(n,`seconds`);isReview(t)&&(logger.info(`[SrsService] Removing previously scheduled review for: ${t.cardID}`),this.user.removeScheduledCardReview(t.reviewID)),this.user.scheduleCardReview({user:this.user.getUsername(),course_id:e.courseID,card_id:e.cardID,time:r,scheduledFor:t.contentSourceType,schedulingAgentId:t.contentSourceID})}};init_logger();var EloService=class{constructor(e,t){_defineProperty(this,`dataLayer`,void 0),_defineProperty(this,`user`,void 0),this.dataLayer=e,this.user=t}async updateUserAndCardElo(e,t,n,r,a,o){o&&logger.warn(`k value interpretation not currently implemented`);let s=this.dataLayer.getCourseDB(a.card.course_id),c=r.courses.find(e=>e.courseID===t);if(!c)return logger.error(`[EloService] No registration for course ${t} on user's registration doc \u2014 skipping ELO update for card ${n}. (Is the user registered for this course?)`),null;let l=toCourseElo(c.elo),u=(await s.getCardEloData([a.card.card_id]))[0];if(u&&l){let r=l.global.score,a=u.global.score,o=Object.keys(u.tags),d={};for(let e of o)d[e]=l.tags[e]?.score??l.global.score;let p=adjustCourseScores(l,u,e);c.elo=p.userElo;let m={};for(let t of o)m[t]={before:d[t],after:p.userElo.tags[t].score,score:e};let g={cardId:n,at:new Date().toISOString(),userScore:e,global:{before:r,after:p.userElo.global.score},card:{before:a,after:p.cardElo.global.score},...o.length?{tags:m}:{}},_=await Promise.allSettled([this.user.updateUserElo(t,p.userElo),s.updateCardElo(n,p.cardElo)]),v=_[0].status===`fulfilled`,y=_[1].status===`fulfilled`;if(v&&y){let e=_[0].value,t=_[1].value;e.ok&&t&&t.ok&&logger.info(`[EloService] Updated ELOS:
|
|
270
|
+
${e.stack}`:JSON.stringify(e);throw logger.error(`[courseDB] Error creating navigator: ${t}`),e}}setEphemeralHints(e){this._pendingHints=e}async getWeightedCards(e){let t=await this._getCurrentUser();try{let{navigator:n}=await this._getCachedNavigator(t);return this._pendingHints&&(n.setEphemeralHints(this._pendingHints),this._pendingHints=null),await n.getWeightedCards(e)}catch(e){throw logger.error(`[courseDB] Error getting weighted cards: ${e}`),e}}async _getCachedNavigator(e){let t=e.getUsername(),n=Date.now();if(this._cachedNavigator&&this._cachedNavigator.userId===t&&n-this._cachedNavigator.builtAt<this._navigatorTtlMs)return{navigator:this._cachedNavigator.navigator,cacheStatus:`hit`};let r=await this.createNavigator(e);return this._cachedNavigator={navigator:r,userId:t,builtAt:n},{navigator:r,cacheStatus:`miss`}}invalidateNavigatorCache(){this._cachedNavigator=null}async getCardsCenteredAtELO(e={limit:99,elo:`user`},t){let n;if(e.elo===`user`){let e=await this._getCurrentUser();n=-1;try{n=EloToNumber((await e.getCourseRegistrationsDoc()).courses.find(e=>e.courseID===this.id).elo)}catch{n=1e3}}else if(e.elo===`random`){let e=await GET_CACHED(`elo-bounds-${this.id}`,()=>this.getELOBounds());n=Math.round(e.low+Math.random()*(e.high-e.low))}else n=e.elo;let r=Math.max(2e3,e.limit*4),a=Date.now(),o=`hit`;if(!this._eloPoolCache||a-this._eloPoolCache.fetchedAt>this._eloPoolTtlMs){let e=await this.getCardsByELO(n,r);e.length>0&&(this._eloPoolCache={rows:e,fetchedAt:a}),o=`miss`}let rankAgainstCurrentElo=()=>{let e=this._eloPoolCache?.rows??[];return(t?e.filter(e=>t(e)):e).map(e=>({...e})).sort((e,t)=>Math.abs((e.elo??n)-n)-Math.abs((t.elo??n)-n))},s=rankAgainstCurrentElo();if(s.length<e.limit&&(o===`hit`||!this._eloPoolCache)){let e=await this.getCardsByELO(n,r);e.length>0&&(this._eloPoolCache={rows:e,fetchedAt:a}),s=rankAgainstCurrentElo(),o=`refresh`}let c=[];for(;c.length<e.limit&&s.length>0;){let e=randIntWeightedTowardZero(s.length),t=s.splice(e,1)[0];c.push(t)}return c.map(e=>({courseID:this.id,cardID:e.cardID,contentSourceType:`course`,contentSourceID:this.id,elo:e.elo,status:`new`}))}async searchCards(e){logger.log(`[CourseDB ${this.id}] Searching for: "${e}"`);let t;try{t=await this.db.find({selector:{docType:`DISPLAYABLE_DATA`,"data.0.data":{$regex:`.*${e}.*`}}}),logger.log(`[CourseDB ${this.id}] Regex search on data[0].data successful`)}catch(n){logger.log(`[CourseDB ${this.id}] Regex search failed, falling back to manual search:`,n);let r=await this.db.find({selector:{docType:`DISPLAYABLE_DATA`}});logger.log(`[CourseDB ${this.id}] Retrieved ${r.docs.length} documents for manual filtering`),t={docs:r.docs.filter(t=>{let n=JSON.stringify(t).toLowerCase().includes(e.toLowerCase());return n&&logger.log(`[CourseDB ${this.id}] Manual match found in document: ${t._id}`),n})}}if(logger.log(`[CourseDB ${this.id}] Found ${t.docs.length} displayable data documents`),t.docs.length===0){let e=await this.db.find({selector:{docType:`DISPLAYABLE_DATA`},limit:5});logger.log(`[CourseDB ${this.id}] Sample displayable data:`,e.docs.map(e=>({id:e._id,docType:e.docType,dataStructure:e.data?Object.keys(e.data):`no data field`,dataContent:e.data,fullDoc:e})))}let n=[];for(let e of t.docs){let t=await this.db.find({selector:{docType:`CARD`,id_displayable_data:{$in:[e._id]}}});logger.log(`[CourseDB ${this.id}] Displayable data ${e._id} linked to ${t.docs.length} cards`),n.push(...t.docs)}return logger.log(`[CourseDB ${this.id}] Total cards found: ${n.length}`),n}async find(e){return this.db.find(e)}}}}),classroomLookupDBTitle,CLASSROOM_CONFIG,ClassroomDBBase,StudentClassroomDB,TeacherClassroomDB,ClassroomLookupDB,init_classroomDB2=__esm({"src/impl/couch/classroomDB.ts"(){init_factory(),init_logger(),init_pouchdb_setup(),init_couch(),init_courseDB(),classroomLookupDBTitle=`classdb-lookup`,CLASSROOM_CONFIG=`ClassroomConfig`,ClassroomDBBase=class{constructor(){_defineProperty(this,`_id`,void 0),_defineProperty(this,`_db`,void 0),_defineProperty(this,`_cfg`,void 0),_defineProperty(this,`_initComplete`,!1),_defineProperty(this,`_content_prefix`,`content`)}get _content_searchkeys(){return getStartAndEndKeys(this._content_prefix)}async getAssignedContent(){return logger.info(`Getting assigned content...`),(await this._db.allDocs({startkey:this._content_prefix,endkey:this._content_prefix+``,include_docs:!0})).rows.map(e=>e.doc)}getContentId(e){return e.type===`tag`?`${this._content_prefix}-${e.courseID}-${e.tagID}`:`${this._content_prefix}-${e.courseID}`}get ready(){return this._initComplete}getConfig(){return this._cfg}},StudentClassroomDB=class _StudentClassroomDB extends ClassroomDBBase{constructor(e,t){super(),_defineProperty(this,`userMessages`,void 0),_defineProperty(this,`_user`,void 0),this._id=e,this._user=t}async init(){let e=`classdb-student-${this._id}`;this._db=new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+e,createPouchDBConfig());try{this._cfg=await this._db.get(CLASSROOM_CONFIG),this.userMessages=this._db.changes({since:`now`,live:!0,include_docs:!0}),this._initComplete=!0;return}catch(e){throw Error(`Error in StudentClassroomDB constructor: ${JSON.stringify(e)}`)}}static async factory(e,t){let n=new _StudentClassroomDB(e,t);return await n.init(),n}setChangeFcn(e){this.userMessages.on(`change`,e)}async getWeightedCards(e){let t=[],n=(await this._user.getPendingReviews()).filter(e=>e.scheduledFor===`classroom`&&e.schedulingAgentId===this._id);for(let e of n)t.push({cardId:e.cardId,courseId:e.courseId,score:1,reviewID:e._id,provenance:[{strategy:`classroom`,strategyName:`Classroom`,strategyId:`CLASSROOM`,action:`generated`,score:1,reason:`Classroom scheduled review`}]});let r=await this._user.getActiveCards(),a=new Set(r.map(e=>e.cardID)),o=hooks.utc(),s=(await this.getAssignedContent()).filter(e=>o.isAfter(hooks.utc(e.activeOn,REVIEW_TIME_FORMAT)));logger.info(`[StudentClassroomDB] Due content: ${JSON.stringify(s)}`);for(let n of s)if(n.type===`course`){let{cards:r}=await new CourseDB(n.courseID,async()=>this._user).getWeightedCards(e);for(let e of r)a.has(e.cardId)||t.push({...e,provenance:[...e.provenance,{strategy:`classroom`,strategyName:`Classroom`,strategyId:`CLASSROOM`,action:`passed`,score:e.score,reason:`Assigned via classroom from course ${n.courseID}`}]})}else if(n.type===`tag`){let e=await getTag(n.courseID,n.tagID);for(let r of e.taggedCards)a.has(r)||t.push({cardId:r,courseId:n.courseID,score:1,provenance:[{strategy:`classroom`,strategyName:`Classroom`,strategyId:`CLASSROOM`,action:`generated`,score:1,reason:`Classroom assigned tag: ${n.tagID}, new card`}]})}else n.type===`card`&&(a.has(n.cardID)||t.push({cardId:n.cardID,courseId:n.courseID,score:1,provenance:[{strategy:`classroom`,strategyName:`Classroom`,strategyId:`CLASSROOM`,action:`generated`,score:1,reason:`Classroom assigned card, new card`}]}));return logger.info(`[StudentClassroomDB] New cards from classroom ${this._cfg.name}: ${t.length} total (reviews + new)`),{cards:t.sort((e,t)=>t.score-e.score).slice(0,e)}}},TeacherClassroomDB=class _TeacherClassroomDB extends ClassroomDBBase{constructor(e){super(),_defineProperty(this,`_stuDb`,void 0),this._id=e}async init(){let e=`classdb-teacher-${this._id}`,t=`classdb-student-${this._id}`;this._db=new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+e,createPouchDBConfig()),this._stuDb=new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+t,createPouchDBConfig());try{return this._db.get(CLASSROOM_CONFIG).then(e=>{this._cfg=e,this._initComplete=!0}).then(()=>{})}catch(e){throw Error(`Error in TeacherClassroomDB constructor: ${JSON.stringify(e)}`)}}static async factory(e){let t=new _TeacherClassroomDB(e);return await t.init(),t}async removeContent(e){let t=this.getContentId(e);try{let e=await this._db.get(t);await this._db.remove(e),this._db.replicate.to(this._stuDb,{doc_ids:[t]})}catch(e){logger.error(`Failed to remove content:`,t,e)}}async assignContent(e){let t,n=this.getContentId(e);return t=e.type===`tag`?await this._db.put({courseID:e.courseID,tagID:e.tagID,type:`tag`,_id:n,assignedBy:e.assignedBy,assignedOn:hooks.utc(),activeOn:e.activeOn||hooks.utc()}):await this._db.put({courseID:e.courseID,type:`course`,_id:n,assignedBy:e.assignedBy,assignedOn:hooks.utc(),activeOn:e.activeOn||hooks.utc()}),t.ok?(this._db.replicate.to(this._stuDb,{doc_ids:[n]}),!0):!1}},ClassroomLookupDB=()=>new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+classroomLookupDBTitle,{skip_setup:!0})}}),AdminDB,init_adminDB2=__esm({"src/impl/couch/adminDB.ts"(){init_pouchdb_setup(),init_factory(),init_couch(),init_classroomDB2(),init_courseLookupDB(),init_logger(),AdminDB=class{constructor(){_defineProperty(this,`usersDB`,void 0),this.usersDB=new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+`_users`,createPouchDBConfig())}async getUsers(){return(await this.usersDB.allDocs({include_docs:!0,...getStartAndEndKeys(`org.couchdb.user:`)})).rows.map(e=>e.doc)}async getCourses(){let e=await CourseLookup.allCourseWare();return await Promise.all(e.map(e=>getCredentialledCourseConfig(e._id)))}async removeCourse(e){let t=await CourseLookup.delete(e),n=await getCredentialledCourseConfig(e);n.deleted=!0;let r=await updateCredentialledCourseConfig(e,n);return{ok:t.ok&&r.ok,id:t.id,rev:t.rev}}async getClassrooms(){let e=(await ClassroomLookupDB().allDocs({include_docs:!0})).rows.map(e=>e.doc.uuid);logger.debug(e.join(`, `));let t=[];for(let n=0;n<e.length;n++)try{let r=await TeacherClassroomDB.factory(e[n]);t.push(r)}catch(t){let r=t;r.error&&r.error===`not_found`&&logger.warn(`db ${e[n]} not found`)}return t.map(e=>({...e.getConfig(),_id:e._id}))}}}}),CourseSyncService_exports={};__export(CourseSyncService_exports,{CourseSyncService:()=>CourseSyncService});var DEFAULT_REPLICATION,CourseSyncService,init_CourseSyncService=__esm({"src/impl/couch/CourseSyncService.ts"(){var e;init_pouchdb_setup(),init_couch(),init_logger(),DEFAULT_REPLICATION={batchSize:1e3,batchesLimit:5},CourseSyncService=(e=class _CourseSyncService{constructor(){_defineProperty(this,`entries`,new Map),_defineProperty(this,`replicationOptions`,DEFAULT_REPLICATION)}static getInstance(){return _CourseSyncService.instance||(_CourseSyncService.instance=new _CourseSyncService),_CourseSyncService.instance}configure(e){e.replication&&(this.replicationOptions={...DEFAULT_REPLICATION,...e.replication},logger.info(`[CourseSyncService] Replication configured: batch_size=${this.replicationOptions.batchSize}, batches_limit=${this.replicationOptions.batchesLimit}`))}static resetInstance(){if(_CourseSyncService.instance){for(let[,e]of _CourseSyncService.instance.entries)e.localDB&&e.localDB.close().catch(()=>{});_CourseSyncService.instance.entries.clear()}_CourseSyncService.instance=null}async ensureSynced(e,t){let n=this.entries.get(e);if(n?.status.state===`ready`&&n.localDB){if(!await this.isLocalEpochStale(e,n.localDB))return;logger.info(`[CourseSyncService] Remote DB epoch changed for course ${e} \u2014 destroying stale local replica`);try{await n.localDB.destroy()}catch{}n.localDB=null,n.readyPromise=null}if(n?.status.state===`disabled`)return;if(n?.readyPromise)return n.readyPromise;let r={localDB:null,status:{state:`not-started`},readyPromise:null};return this.entries.set(e,r),r.readyPromise=this.performSync(e,r,t),r.readyPromise}getLocalDB(e){let t=this.entries.get(e);return t?.status.state===`ready`&&t.localDB?t.localDB:null}isReady(e){return this.entries.get(e)?.status.state===`ready`}getStatus(e){return this.entries.get(e)?.status??{state:`not-started`}}async performSync(e,t,n){try{if(!n&&(t.status={state:`checking-config`},!await this.checkLocalSyncEnabled(e))){t.status={state:`disabled`},t.readyPromise=null,logger.debug(`[CourseSyncService] Local sync disabled for course ${e}`);return}t.status={state:`syncing`};let r=this.localDBName(e),a=new pouchdb_setup_default(r);await this.isLocalEpochStale(e,a)&&(logger.info(`[CourseSyncService] Stale local DB detected for course ${e} \u2014 destroying before sync`),await a.destroy(),a=new pouchdb_setup_default(r)),t.localDB=a;let o=this.getRemoteDB(e),s=Date.now();logger.info(`[CourseSyncService] Starting one-shot replication for course ${e} (batch_size=${this.replicationOptions.batchSize}, batches_limit=${this.replicationOptions.batchesLimit})`);let c=await this.replicate(o,a),l=Date.now()-s;logger.info(`[CourseSyncService] Replication complete for course ${e}: ${c.docs_written} docs in ${l}ms`),t.status={state:`warming-views`};let u=Date.now();await this.warmViewIndices(a);let d=Date.now()-u;logger.info(`[CourseSyncService] View indices warmed for course ${e} in ${d}ms`),t.status={state:`ready`,docsReplicated:c.docs_written,syncTimeMs:l,viewWarmTimeMs:d}}catch(n){let r=n instanceof Error?n.message:String(n);if(logger.error(`[CourseSyncService] Sync failed for course ${e}: ${r}`),t.status={state:`error`,error:r},t.readyPromise=null,t.localDB){try{await t.localDB.destroy()}catch{}t.localDB=null}}}async checkLocalSyncEnabled(e){try{return(await this.getRemoteDB(e).get(`CourseConfig`)).localSync?.enabled===!0}catch(t){return logger.warn(`[CourseSyncService] Could not read CourseConfig for ${e}, assuming local sync disabled: ${t}`),!1}}replicate(e,t){return new Promise((n,r)=>{pouchdb_setup_default.replicate(e,t,{batch_size:this.replicationOptions.batchSize,batches_limit:this.replicationOptions.batchesLimit}).on(`complete`,e=>{n(e)}).on(`error`,e=>{r(e)})})}async warmViewIndices(e){for(let t of[`elo`,`getTags`])try{await e.query(t,{limit:1}),logger.debug(`[CourseSyncService] Warmed view index: ${t}`)}catch(e){logger.debug(`[CourseSyncService] Could not warm view ${t}: ${e}`)}}async isLocalEpochStale(e,t){try{let n=await this.getRemoteDB(e).get(`db-epoch`),r=null;try{r=await t.get(`db-epoch`)}catch{return!0}return n.epoch!==r.epoch}catch{return!1}}getRemoteDB(e){return getCourseDB2(e)}localDBName(e){return`coursedb-local-${e}`}},_defineProperty(e,`instance`,null),e)}});async function getCurrentSession(){try{if(ENV.COUCHDB_SERVER_URL===NOT_SET||ENV.COUCHDB_SERVER_PROTOCOL===NOT_SET)throw Error(`CouchDB server configuration not properly initialized. Protocol: "${ENV.COUCHDB_SERVER_PROTOCOL}", URL: "${ENV.COUCHDB_SERVER_URL}"`);let e=ENV.COUCHDB_SERVER_URL.endsWith(`/`)?ENV.COUCHDB_SERVER_URL.slice(0,-1):ENV.COUCHDB_SERVER_URL,t=`${ENV.COUCHDB_SERVER_PROTOCOL}://${e}/_session`;logger.debug(`Attempting session check at: ${t}`);let n=await(0,import_browser_ponyfill.default)(t,{method:`GET`,credentials:`include`});if(!n.ok)throw Error(`Session check failed: ${n.status}`);return await n.json()}catch(e){let t=ENV.COUCHDB_SERVER_URL.endsWith(`/`)?ENV.COUCHDB_SERVER_URL.slice(0,-1):ENV.COUCHDB_SERVER_URL,n=`${ENV.COUCHDB_SERVER_PROTOCOL}://${t}/_session`;throw logger.error(`Session check error attempting to connect to: ${n} - ${e}`),Error(`Session check failed connecting to ${n}: ${e}`)}}async function getLoggedInUsername(){let e=await getCurrentSession();if(e.userCtx.name&&e.userCtx.name!==``)return e.userCtx.name;throw Error(`No logged in user`)}var init_auth=__esm({"src/impl/couch/auth.ts"(){init_factory(),init_logger()}}),CouchDBSyncStrategy_exports={};__export(CouchDBSyncStrategy_exports,{CouchDBSyncStrategy:()=>CouchDBSyncStrategy});var log2,CouchDBSyncStrategy,init_CouchDBSyncStrategy=__esm({"src/impl/couch/CouchDBSyncStrategy.ts"(){init_factory(),init_types_legacy(),init_logger(),init_common(),init_pouchdb_setup(),init_couch(),init_auth(),log2=e=>{logger.info(e)},CouchDBSyncStrategy=class{constructor(){_defineProperty(this,`syncHandle`,void 0),_defineProperty(this,`hydrationHandle`,void 0)}setupRemoteDB(e){return e===GuestUsername||e.startsWith(GuestUsername)?getLocalUserDB(e):this.getUserDB(e)}getWriteDB(e){return e===GuestUsername||e.startsWith(GuestUsername)?getLocalUserDB(e):this.getUserDB(e)}async hydrate(e,t){let n=(await e.info()).doc_count===0,r=pouchdb_setup_default.replicate(t,e,n?{selector:{_deleted:{$exists:!1}}}:{});this.hydrationHandle=r;try{let e=await r;return{docsWritten:e.docs_written,lastSeq:n?e.last_seq:void 0}}finally{this.hydrationHandle=void 0}}startSync(e,t,n){e.name!==t.name&&(this.syncHandle=pouchdb_setup_default.sync(e,t,{live:!0,retry:!0,...n===void 0?{}:{pull:{since:n}}}))}stopSync(){if(this.hydrationHandle){try{this.hydrationHandle.cancel()}catch(e){logger.warn(`Failed to cancel hydration pull (continuing anyway): ${e}`)}this.hydrationHandle=void 0}if(this.syncHandle){try{this.syncHandle.cancel()}catch(e){logger.warn(`Failed to cancel user sync (continuing anyway): ${e}`)}this.syncHandle=void 0}}canCreateAccount(){return!0}canAuthenticate(){return!0}async createAccount(e,t){let n=await this.getCurrentUsername(),r=n.startsWith(GuestUsername);r&&logger.info(`Creating account for funnel user ${n} -> ${e}`);try{let a=await this.getRemoteCouchRootDB().signUp(e,t);if(a.ok){log2(`CREATEACCOUNT: Successfully created account for ${e}`);try{let e=await this.getRemoteCouchRootDB().logOut();log2(`CREATEACCOUNT: logged out: ${e.ok}`)}catch{}let a=await this.getRemoteCouchRootDB().logIn(e,t);if(log2(`CREATEACCOUNT: logged in as new user: ${a.ok}`),a.ok){if(r){logger.info(`Migrating data from funnel account ${n} to ${e}`);let t=await this.migrateFunnelData(n,e);t.success||logger.warn(`Migration failed: ${t.error}`)}return{status:Status.ok,error:void 0}}else return{status:Status.error,error:`Failed to log in after account creation`}}else return logger.warn(`Signup not OK: ${JSON.stringify(a)}`),{status:Status.error,error:`Account creation failed`}}catch(e){return e.reason===`Document update conflict.`?{status:Status.error,error:`This username is taken!`}:(logger.error(`Error on signup: ${JSON.stringify(e)}`),{status:Status.error,error:e.message||`Unknown error during account creation`})}}async authenticate(e,t){try{return(await this.getRemoteCouchRootDB().logIn(e,t)).ok?(log2(`Successfully logged in as ${e}`),{ok:!0}):(log2(`Login failed for ${e}`),{ok:!1,error:`Invalid username or password`})}catch(t){return logger.error(`Authentication error for ${e}:`,t),{ok:!1,error:t.message||`Authentication failed`}}}async adoptSession(e){let t;try{t=await getLoggedInUsername()}catch{return{ok:!1,error:`No session to adopt`}}if(e?.startsWith(GuestUsername)){logger.info(`Migrating data from funnel account ${e} to ${t}`);let n=await this.migrateFunnelData(e,t);n.success||logger.warn(`Migration failed: ${n.error}`)}return{ok:!0,username:t}}async logout(){try{let e=await this.getRemoteCouchRootDB().logOut();return{ok:e.ok,error:e.ok?void 0:`Logout failed`}}catch(e){return logger.error(`Logout error:`,e),{ok:!1,error:e.message||`Logout failed`}}}async getCurrentUsername(){logger.log(`[funnel] CouchDBSyncStrategy.getCurrentUsername() called`);try{let e=await getLoggedInUsername();return logger.log(`[funnel] getLoggedInUsername() returned:`,e),e}catch(e){logger.log(`[funnel] getLoggedInUsername() failed, calling accomodateGuest()`),logger.log(`[funnel] Error was:`,e);let t=accomodateGuest();return logger.log(`[funnel] accomodateGuest() returned:`,t),t.username}}async migrateFunnelData(e,t){try{logger.info(`Starting data migration from ${e} to ${t}`);let n=getLocalUserDB(e),r=getLocalUserDB(t),a=await n.allDocs({include_docs:!0});logger.info(`Found ${a.rows.length} documents in funnel account`);let o=a.rows.filter(e=>!e.id.startsWith(`_design/`)).map(e=>({...e.doc,_rev:void 0}));o.length>0?(await r.bulkDocs(o),logger.info(`Successfully migrated ${o.length} documents from ${e} to ${t}`)):logger.info(`No documents to migrate from funnel account`);try{await n.destroy(),logger.info(`Destroyed consumed guest DB for ${e}`)}catch(t){logger.warn(`Failed to destroy consumed guest DB for ${e} (non-fatal): ${t instanceof Error?t.message:String(t)}`)}return{success:!0}}catch(e){return logger.error(`Migration failed:`,e),{success:!1,error:e instanceof Error?e.message:`Unknown error`}}}getRemoteCouchRootDB(){let e=ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+`skuilder`;try{return new pouchdb_setup_default(e,{skip_setup:!0})}catch(e){throw logger.error(`Failed to initialize remote CouchDB connection:`,e),Error(`Failed to initialize CouchDB: ${JSON.stringify(e)}`)}}getUserDB(e){let t=!1,n=`userdb-${hexEncode(e)}`;return log2(`Fetching user database: ${n} (${e})`),new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+n,createPouchDBConfig())}}}});function createPouchDBConfig(){return ENV.COUCHDB_USERNAME&&ENV.COUCHDB_PASSWORD&&typeof window>`u`?{fetch(e,t={}){let n=btoa(`${ENV.COUCHDB_USERNAME}:${ENV.COUCHDB_PASSWORD}`),r=new Headers(t.headers||{});r.set(`Authorization`,`Basic ${n}`);let a={...t,headers:r};return pouchdb_setup_default.fetch(e,a)}}:pouchDBincludeCredentialsConfig}function getCourseDB2(e){return new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL+`://`+ENV.COUCHDB_SERVER_URL+`coursedb-`+e,createPouchDBConfig())}function filterAllDocsByPrefix(e,t,n){let r={startkey:t,endkey:t+``,include_docs:!0};return n&&Object.assign(r,n),e.allDocs(r)}function getStartAndEndKeys(e){return{startkey:e,endkey:e+``}}var isBrowser,GUEST_LOCAL_DB,localUserDB,pouchDBincludeCredentialsConfig,REVIEW_TIME_FORMAT,init_couch=__esm({"src/impl/couch/index.ts"(){init_factory(),init_types_legacy(),init_logger(),init_pouchdb_setup(),init_contentSource(),init_adminDB2(),init_classroomDB2(),init_courseAPI(),init_courseDB(),init_CourseSyncService(),init_CouchDBSyncStrategy(),isBrowser=typeof window<`u`,isBrowser&&(window.process=import_browser.default),GUEST_LOCAL_DB=`userdb-${GuestUsername}`,new pouchdb_setup_default(GUEST_LOCAL_DB),pouchDBincludeCredentialsConfig={fetch(e,t){return t.credentials=`include`,pouchdb_setup_default.fetch(e,t)}},REVIEW_TIME_FORMAT=`YYYY-MM-DD--kk:mm:ss-SSS`}});function newInterval(e,t){return areQuestionRecords(t)?newQuestionInterval(e,t):1e5}function newQuestionInterval(e,t){let n=t.records,r=n[n.length-1],a=lastSuccessfulInterval(n);if(a>t.bestInterval&&(t.bestInterval=a,e.update(t._id,{bestInterval:a}).catch(e=>{logger.warn(`[SpacedRepetition] Failed to update bestInterval for ${t._id}: ${e?.message??e}`)})),r.isCorrect){let e=r.performance,n=isTaggedPerformance(e)?e._global:e,o=Math.min(1,Math.max(0,n));logger.debug(`Demontrated skill: ${o}`);let s=a*(.75+o);if(t.lapses=getLapses(t.records),t.streak=getStreak(t.records),t.lapses&&t.streak&&t.bestInterval&&(t.lapses>=0||t.streak>=0)){let e=(t.lapses*s+t.streak*t.bestInterval)/(t.lapses+t.streak);return logger.debug(`Weighted average interval calculation:
|
|
271
|
+
(${t.lapses} * ${s} + ${t.streak} * ${t.bestInterval}) / (${t.lapses} + ${t.streak}) = ${e}`),e}else return s}else return 0}function lastSuccessfulInterval(e){for(let t=e.length-1;t>=1;t--)if(e[t].priorAttemps===0&&e[t].isCorrect){let n=secondsBetween(e[t-1].timeStamp,e[t].timeStamp),r=Math.max(n,1200*60);return logger.debug(`Last interval w/ this card was: ${n}s, returning ${r}s`),r}return getInitialInterval(e)}function getStreak(e){let t=0,n=e.length-1;for(;n>=0&&e[n].isCorrect;)n--,t++;return t}function getLapses(e){return e.filter(e=>e.isCorrect===!1).length}function getInitialInterval(e){return logger.warn(`history of length: ${e.length} ignored!`),3600*24*3}function secondsBetween(e,t){return e=hooks(e),t=hooks(t),duration(t.diff(e)).asSeconds()}var duration,init_SpacedRepetition=__esm({"src/study/SpacedRepetition.ts"(){init_util(),init_logger(),duration=hooks.duration}}),SrsService,init_SrsService=__esm({"src/study/services/SrsService.ts"(){init_couch(),init_SpacedRepetition(),init_logger(),SrsService=class{constructor(e){_defineProperty(this,`user`,void 0),this.user=e}removeReview(e){logger.info(`[SrsService] Removing orphaned scheduled review: ${e}`),this.user.removeScheduledCardReview(e)}async scheduleReview(e,t){let n=newInterval(this.user,e),r=hooks.utc().add(n,`seconds`);isReview(t)&&(logger.info(`[SrsService] Removing previously scheduled review for: ${t.cardID}`),this.user.removeScheduledCardReview(t.reviewID)),this.user.scheduleCardReview({user:this.user.getUsername(),course_id:e.courseID,card_id:e.cardID,time:r,scheduledFor:t.contentSourceType,schedulingAgentId:t.contentSourceID})}}}});function currentRecord(e){return e.length?e[e.length-1]:null}function isFirstAttempt(e){let t=currentRecord(e);if(!t)return!1;let n=t.priorAttemps;return typeof n==`number`?n===0:e.length===1}function recordTagPresentations(e,t,n,r,a){if(!isFirstAttempt(n))return[];let o=currentRecord(n)?.isCorrect===!0,s=[];for(let[n,c]of Object.entries(t)){if(n===`_global`||typeof c!=`number`)continue;let t=e.tags[n]??{score:e.global.score,count:0},l={at:a,ok:o,perf:c,card:r};e.tags[n]=pushTagPresentation(t,l),s.push(n)}return s}var init_tagRecent=__esm({"src/study/services/tagRecent.ts"(){}}),EloService,init_EloService=__esm({"src/study/services/EloService.ts"(){init_logger(),init_tagRecent(),EloService=class{constructor(e,t){_defineProperty(this,`dataLayer`,void 0),_defineProperty(this,`user`,void 0),this.dataLayer=e,this.user=t}async updateUserAndCardElo(e,t,n,r,a,o){o&&logger.warn(`k value interpretation not currently implemented`);let s=this.dataLayer.getCourseDB(a.card.course_id),c=r.courses.find(e=>e.courseID===t);if(!c)return logger.error(`[EloService] No registration for course ${t} on user's registration doc \u2014 skipping ELO update for card ${n}. (Is the user registered for this course?)`),null;let l=toCourseElo(c.elo),u=(await s.getCardEloData([a.card.card_id]))[0];if(u&&l){let r=l.global.score,a=u.global.score,o=Object.keys(u.tags),d={};for(let e of o)d[e]=l.tags[e]?.score??l.global.score;let p=adjustCourseScores(l,u,e);c.elo=p.userElo;let m={};for(let t of o)m[t]={before:d[t],after:p.userElo.tags[t].score,score:e};let g={cardId:n,at:new Date().toISOString(),userScore:e,global:{before:r,after:p.userElo.global.score},card:{before:a,after:p.cardElo.global.score},...o.length?{tags:m}:{}},_=await Promise.allSettled([this.user.updateUserElo(t,p.userElo),s.updateCardElo(n,p.cardElo)]),v=_[0].status===`fulfilled`,y=_[1].status===`fulfilled`;if(v&&y){let e=_[0].value,t=_[1].value;e.ok&&t&&t.ok&&logger.info(`[EloService] Updated ELOS:
|
|
310
272
|
User: ${JSON.stringify(p.userElo)})
|
|
311
273
|
Card: ${JSON.stringify(p.cardElo)})
|
|
312
274
|
`)}else logger.warn(`[EloService] Partial ELO update:
|
|
313
275
|
User ELO update: ${v?`SUCCESS`:`FAILED`}
|
|
314
|
-
Card ELO update: ${y?`SUCCESS`:`FAILED`}`),!v&&_[0].status===`rejected`&&logger.error(`[EloService] User ELO update error:`,_[0].reason),!y&&_[1].status===`rejected`&&logger.error(`[EloService] Card ELO update error:`,_[1].reason);return g}return null}async updateUserAndCardEloPerTag(e,t,n,r,a){let o=this.dataLayer.getCourseDB(a.card.course_id),s=r.courses.find(e=>e.courseID===t);if(!s)return logger.error(`[EloService] No registration for course ${t} on user's registration doc \u2014 skipping per-tag ELO update for card ${n}. (Is the user registered for this course?)`),null;let c=toCourseElo(s.elo),[l,u]=await Promise.all([o.getCardEloData([a.card.card_id]),o.getAppliedTagsBatch([n])]),d=l[0],p=u.get(n)??[],m={...e},g=e._global;for(let e of p)e in m||(m[e]=g);if(d&&c){let
|
|
315
|
-
User: ${JSON.stringify(
|
|
316
|
-
Card: ${JSON.stringify(
|
|
276
|
+
Card ELO update: ${y?`SUCCESS`:`FAILED`}`),!v&&_[0].status===`rejected`&&logger.error(`[EloService] User ELO update error:`,_[0].reason),!y&&_[1].status===`rejected`&&logger.error(`[EloService] Card ELO update error:`,_[1].reason);return g}return null}async updateUserAndCardEloPerTag(e,t,n,r,a){let o=this.dataLayer.getCourseDB(a.card.course_id),s=r.courses.find(e=>e.courseID===t);if(!s)return logger.error(`[EloService] No registration for course ${t} on user's registration doc \u2014 skipping per-tag ELO update for card ${n}. (Is the user registered for this course?)`),null;let c=toCourseElo(s.elo),[l,u]=await Promise.all([o.getCardEloData([a.card.card_id]),o.getAppliedTagsBatch([n])]),d=l[0],p=u.get(n)??[],m={...e},g=e._global;for(let e of p)e in m||(m[e]=g);if(d&&c){let r=c.global.score,l=d.global.score,u=Object.keys(m).filter(e=>e!==`_global`),p={};for(let e of u)p[e]=c.tags[e]?.score??c.global.score;let _=adjustCourseScoresPerTag(c,d,m),v=new Date().toISOString(),y=recordTagPresentations(_.userElo,e,a.records,n,v);y.length&&logger.info(`[EloService] recent-presentation entries for ${n}: [${y.join(`, `)}]`),s.elo=_.userElo;let b={};for(let e of u){let t=m[e],n=t===null?p[e]:_.userElo.tags[e]?.score??p[e];b[e]={before:p[e],after:n,score:t}}let x={cardId:n,at:v,userScore:g,global:{before:r,after:_.userElo.global.score},card:{before:l,after:_.cardElo.global.score},...u.length?{tags:b}:{}},S=await Promise.allSettled([this.user.updateUserElo(t,_.userElo),o.updateCardElo(n,_.cardElo)]),C=S[0].status===`fulfilled`,w=S[1].status===`fulfilled`;if(C&&w){let e=S[0].value,t=S[1].value;if(e.ok&&t&&t.ok){let e=Object.keys(m).length-1;logger.info(`[EloService] Updated ELOS (per-tag, ${e} tags):
|
|
277
|
+
User: ${JSON.stringify(_.userElo)})
|
|
278
|
+
Card: ${JSON.stringify(_.cardElo)})
|
|
317
279
|
`)}}else logger.warn(`[EloService] Partial ELO update (per-tag):
|
|
318
|
-
User ELO update: ${
|
|
319
|
-
Card ELO update: ${
|
|
280
|
+
User ELO update: ${C?`SUCCESS`:`FAILED`}
|
|
281
|
+
Card ELO update: ${w?`SUCCESS`:`FAILED`}`),!C&&S[0].status===`rejected`&&logger.error(`[EloService] User ELO update error:`,S[0].reason),!w&&S[1].status===`rejected`&&logger.error(`[EloService] Card ELO update error:`,S[1].reason);return x}return null}}}}),ResponseProcessor,init_ResponseProcessor=__esm({"src/study/services/ResponseProcessor.ts"(){init_core(),init_logger(),ResponseProcessor=class{constructor(e,t,n){_defineProperty(this,`srsService`,void 0),_defineProperty(this,`eloService`,void 0),_defineProperty(this,`onEloEvent`,void 0),this.srsService=e,this.eloService=t,this.onEloEvent=n}logEloFailure(e,t){return n=>logger.error(`[ResponseProcessor] ELO update failed (${e}) for ${t}:`,n)}trackElo(e,t,n){e.then(e=>{e&&this.onEloEvent?.(e)}).catch(this.logEloFailure(t,n))}parsePerformance(e){return typeof e==`number`?{globalScore:e,taggedPerformance:null}:isTaggedPerformance(e)?{globalScore:e._global,taggedPerformance:e}:(logger.warn(`[ResponseProcessor] Unexpected performance structure, using neutral score`,{performance:e}),{globalScore:.5,taggedPerformance:null})}async processResponse(e,t,n,r,a,o,s,c,l,u){if(!isQuestionRecord(e))return{nextCardAction:`dismiss-success`,shouldLoadNextCard:!0,isCorrect:!0,shouldClearFeedbackShadow:!0};try{let d=await t,p;return p=e.isCorrect?this.processCorrectResponse(e,d,n,r,a,o,s,l,u):this.processIncorrectResponse(e,d,r,a,o,s,c,l,u),e.deferAdvance&&p.shouldLoadNextCard&&(logger.info(`[ResponseProcessor] deferAdvance requested — suppressing navigation, action stashed:`,{nextCardAction:p.nextCardAction}),p={...p,shouldLoadNextCard:!1,deferred:!0}),p}catch(e){throw logger.error(`[ResponseProcessor] Failed to load card history`,{e,cardId:s}),e}}processCorrectResponse(e,t,n,r,a,o,s,c,l){if(e.priorAttemps===0){a.card.tags.includes(`srs:skip`)||this.srsService.scheduleReview(t,n);let{globalScore:c,taggedPerformance:l}=this.parsePerformance(e.performance);if(l){let n=Object.keys(l).filter(e=>e!==`_global`),c=n.filter(e=>l[e]===null),u=n.filter(e=>l[e]!==null);logger.info(`[FirstContactElo] correct first-attempt per-tag ELO update for ${s} (historyLen=${t.records.length}, priorAttemps=${e.priorAttemps}): scored=[${u.join(`, `)}] count-only=[${c.join(`, `)}]`),this.trackElo(this.eloService.updateUserAndCardEloPerTag(l,o,s,r,a),`correct per-tag`,s)}else{let n=.5+c/2;if(t.records.length===1)this.trackElo(this.eloService.updateUserAndCardElo(n,o,s,r,a),`correct`,s);else{let e=Math.ceil(32/t.records.length);this.trackElo(this.eloService.updateUserAndCardElo(n,o,s,r,a,e),`correct repeat-view`,s)}logger.info(`[FirstContactElo] correct first-attempt ELO update (score=${n.toFixed(3)}) for ${s} (historyLen=${t.records.length}, priorAttemps=${e.priorAttemps})`)}return{nextCardAction:`dismiss-success`,shouldLoadNextCard:!0,isCorrect:!0,performanceScore:c,shouldClearFeedbackShadow:!0}}else{let t=l>=c;logger.info(`[ResponseProcessor] Processed correct response (retry attempt - no scheduling/ELO); sessionViews=${l}/${c} -> ${t?`dismiss-success`:`marked-failed`}`);let{globalScore:n}=this.parsePerformance(e.performance);return{nextCardAction:t?`dismiss-success`:`marked-failed`,shouldLoadNextCard:!0,isCorrect:!0,performanceScore:n,shouldClearFeedbackShadow:!0}}}processIncorrectResponse(e,t,n,r,a,o,s,c,l){let{taggedPerformance:u}=this.parsePerformance(e.performance),d=!1;return e.priorAttemps===0?(u?(this.trackElo(this.eloService.updateUserAndCardEloPerTag(u,a,o,n,r),`incorrect per-tag`,o),logger.info(`[FirstContactElo] incorrect first-attempt per-tag ELO update for ${o} (historyLen=${t.records.length}, priorAttemps=${e.priorAttemps}, tags=${Object.keys(u).length-1})`)):(this.trackElo(this.eloService.updateUserAndCardElo(0,a,o,n,r),`incorrect`,o),logger.info(`[FirstContactElo] incorrect first-attempt ELO update (score=0) for ${o} (historyLen=${t.records.length}, priorAttemps=${e.priorAttemps})`)),d=!0):logger.info(`[FirstContactElo] incorrect retry \u2014 no ELO update for ${o} (historyLen=${t.records.length}, priorAttemps=${e.priorAttemps})`),r.records.length>=s?l>=c?(d?logger.info(`[FirstContactElo] dismiss-failed \u2014 ELO already updated this response, skipping double penalty for ${o}`):(u?this.trackElo(this.eloService.updateUserAndCardEloPerTag(u,a,o,n,r),`dismiss-failed per-tag`,o):this.trackElo(this.eloService.updateUserAndCardElo(0,a,o,n,r),`dismiss-failed`,o),logger.info(`[FirstContactElo] dismiss-failed final ELO penalty for ${o} (historyLen=${t.records.length}, sessionViews=${l})`)),{nextCardAction:`dismiss-failed`,shouldLoadNextCard:!0,isCorrect:!1,shouldClearFeedbackShadow:!0}):{nextCardAction:`marked-failed`,shouldLoadNextCard:!0,isCorrect:!1,shouldClearFeedbackShadow:!0}:{nextCardAction:`none`,shouldLoadNextCard:!1,isCorrect:!1,shouldClearFeedbackShadow:!0}}}}});function parseAudioURIs(e){return typeof e==`string`?e.match(/https?:\/\/[^\s"'<>]+\.(wav|mp3|ogg|m4a|aac|webm)/gi)??[]:[]}function prefetchAudio(e){return new Promise(t=>{let n=new Audio;n.preload=`auto`;let cleanup=()=>{n.oncanplaythrough=null,n.onerror=null};n.oncanplaythrough=()=>{cleanup(),t()},n.onerror=()=>{cleanup(),logger.warn(`[CardHydrationService] Failed to prefetch audio: ${e}`),t()},n.src=e})}var CardHydrationService,init_CardHydrationService=__esm({"src/study/services/CardHydrationService.ts"(){init_logger(),CardHydrationService=class{constructor(e,t,n){_defineProperty(this,`hydratedCards`,new Map),_defineProperty(this,`hydrationInFlight`,new Set),_defineProperty(this,`hydrationInProgress`,!1),this.getViewComponent=e,this.getCourseDB=t,this.getItemsToHydrate=n}getHydratedCard(e){return this.hydratedCards.get(e)??null}hasHydratedCard(e){return this.hydratedCards.has(e)}removeCard(e){this.hydratedCards.delete(e)}async ensureHydratedCards(){this.fillHydratedCards()}async waitForCard(e){if(this.hydratedCards.has(e))return this.hydratedCards.get(e);this.hydrationInProgress||this.fillHydratedCards();let t=1e4,n=25,r=0;for(;r<1e4;){if(this.hydratedCards.has(e))return this.hydratedCards.get(e);if(!this.hydrationInFlight.has(e)&&!this.hydrationInProgress)break;await new Promise(e=>setTimeout(e,25)),r+=25}return this.hydratedCards.get(e)??null}get hydratedCount(){return this.hydratedCards.size}getHydratedCardIds(){return Array.from(this.hydratedCards.keys())}async fillHydratedCards(){if(!this.hydrationInProgress){this.hydrationInProgress=!0;try{let e=this.getItemsToHydrate();for(let t of e)if(!(this.hydratedCards.has(t.cardID)||this.hydrationInFlight.has(t.cardID)))try{await this.hydrateCard(t)}catch(e){logger.error(`[CardHydrationService] Error hydrating card ${t.cardID}:`,e)}}finally{this.hydrationInProgress=!1}}}async hydrateCard(e){if(!(this.hydratedCards.has(e.cardID)||this.hydrationInFlight.has(e.cardID))){this.hydrationInFlight.add(e.cardID);try{let t=this.getCourseDB(e.courseID),[n,r]=await Promise.all([t.getCourseDoc(e.cardID),t.getAppliedTagsBatch([e.cardID])]);isCourseElo(n.elo)||(n.elo=toCourseElo(n.elo));let a=this.getViewComponent(n.id_view),o=await Promise.all(n.id_displayable_data.map(e=>t.getCourseDoc(e,{attachments:!0,binary:!0}))),s=[];o.forEach(e=>{e.data.forEach(e=>{s.push(...parseAudioURIs(e.data))})});let c=[...new Set(s)];c.length>0&&(logger.debug(`[CardHydrationService] Prefetching ${c.length} audio files for card ${e.cardID}`),await Promise.allSettled(c.map(prefetchAudio)));let l=o.map(displayableDataToViewData).reverse();this.hydratedCards.set(e.cardID,{item:{...e,elo:toCourseElo(n.elo).global.score},view:a,data:l,tags:r.get(e.cardID)??[]}),logger.debug(`[CardHydrationService] Hydrated card ${e.cardID}`)}finally{this.hydrationInFlight.delete(e.cardID)}}}}}}),ItemQueue,init_ItemQueue=__esm({"src/study/ItemQueue.ts"(){ItemQueue=class{constructor(){_defineProperty(this,`q`,[]),_defineProperty(this,`seenCardIds`,[]),_defineProperty(this,`_dequeueCount`,0)}get dequeueCount(){return this._dequeueCount}add(e,t){this.seenCardIds.find(e=>e===t)||(this.seenCardIds.push(t),this.q.push(e))}addAll(e,t){e.forEach(e=>this.add(e,t(e)))}get length(){return this.q.length}peek(e){return this.q[e]}dequeue(e){if(this.q.length!==0){this._dequeueCount++;let t=this.q.splice(0,1)[0];if(e){let n=e(t),r=this.seenCardIds.indexOf(n);r>-1&&this.seenCardIds.splice(r,1)}return t}else return null}replaceAll(e,t){this.q=[],this.seenCardIds=[];for(let n of e){let e=t(n);this.seenCardIds.includes(e)||(this.seenCardIds.push(e),this.q.push(n))}}mergeToFront(e,t,n){let r=0,a=[];for(let o of e){let e=t(o);if(!this.seenCardIds.includes(e))this.seenCardIds.push(e),a.push(o),r++;else if(n?.has(e)){let n=this.q.findIndex(n=>t(n)===e);n>=0&&a.push(...this.q.splice(n,1))}}return this.q.unshift(...a),r}get toString(){return`${typeof this.q[0]}:
|
|
320
282
|
`+this.q.map(e=>` ${e.courseID}+${e.cardID}: ${e.status}`).join(`
|
|
321
|
-
`)}};init_couch(),init_core(),init_types_legacy(),init_studySession(),init_recording(),init_Loggable(),init_types_legacy(),init_logger();var CouchDBToStaticPacker=class{constructor(e={}){_defineProperty(this,`config`,void 0),_defineProperty(this,`sourceDB`,null),this.config={chunkSize:1e3,includeAttachments:!0,...e}}async packCourse(e,t){logger.info(`Starting static pack for course: ${t}`),this.sourceDB=e;let n={version:`1.0.0`,courseId:t,courseName:``,courseConfig:null,lastUpdated:new Date().toISOString(),documentCount:0,chunks:[],indices:[],designDocs:[]},r=await this.extractCourseConfig(e);n.courseName=r.name,n.courseConfig=r,n.designDocs=await this.extractDesignDocs(e);let a=await this.extractDocumentsByType(e),o=new Map;this.config.includeAttachments&&await this.extractAllAttachments(a,o);let s=new Map;for(let[e,t]of Object.entries(a)){let r=this.createChunks(t,e);n.chunks.push(...r),n.documentCount+=t.length,this.prepareChunkData(r,t,s)}let c=new Map;return n.indices=await this.buildIndices(a,n.designDocs,c),{manifest:n,chunks:s,indices:c,attachments:o}}async packCourseToFiles(e,t,n,r){logger.info(`Packing course ${t} to files in ${n}`);let a=await this.packCourse(e,t),o=await this.writePackedDataToFiles(a,n,r);return{manifest:a.manifest,filesWritten:o,attachmentsFound:a.attachments?a.attachments.size:0}}async writePackedDataToFiles(e,t,n){let r=0;await n.ensureDir(t);let a=n.joinPath(t,`manifest.json`);await n.writeJson(a,e.manifest,{spaces:2}),r++,logger.info(`Wrote manifest: ${a}`);let o=n.joinPath(t,`chunks`),s=n.joinPath(t,`indices`);await n.ensureDir(o),await n.ensureDir(s);for(let[t,a]of e.chunks){let e=n.joinPath(o,`${t}.json`);await n.writeJson(e,a),r++}logger.info(`Wrote ${e.chunks.size} chunk files`);for(let[t,a]of e.indices){let e=n.joinPath(s,`${t}.json`);await n.writeJson(e,a,{spaces:2}),r++}if(logger.info(`Wrote ${e.indices.size} index files`),e.attachments&&e.attachments.size>0){for(let[a,o]of e.attachments){let e=n.joinPath(t,a),s=n.dirname(e);await n.ensureDir(s),await n.writeFile(e,o.buffer),r++}logger.info(`Wrote ${e.attachments.size} attachment files`)}return r}async extractCourseConfig(e){try{return await e.get(`CourseConfig`)}catch(e){throw logger.error(`Failed to extract course config:`,e),Error(`Course config not found`)}}async extractDesignDocs(e){return(await e.allDocs({startkey:`_design/`,endkey:`_design/`,include_docs:!0})).rows.map(e=>({_id:e.id,views:e.doc.views||{}}))}async extractDocumentsByType(e){let t=await e.allDocs({include_docs:!0}),n={};for(let e of t.rows){if(e.id.startsWith(`_`))continue;let t=e.doc;t.docType&&(n[t.docType]||(n[t.docType]=[]),n[t.docType].push(t))}return n}createChunks(e,t){let n=[],r=e.sort((e,t)=>e._id.localeCompare(t._id));for(let e=0;e<r.length;e+=this.config.chunkSize){let a=r.slice(e,e+this.config.chunkSize),o=`${t}-${String(Math.floor(e/this.config.chunkSize)).padStart(4,`0`)}`;n.push({id:o,docType:t,startKey:a[0]._id,endKey:a[a.length-1]._id,documentCount:a.length,path:`chunks/${o}.json`})}return n}prepareChunkData(e,t,n){let r=t.sort((e,t)=>e._id.localeCompare(t._id));for(let t of e){let e=r.filter(e=>e._id>=t.startKey&&e._id<=t.endKey).map(e=>{let t={...e};return delete t._rev,this.config.includeAttachments&&t._attachments?t._attachments=this.transformAttachmentStubs(t._attachments,t._id):this.config.includeAttachments||delete t._attachments,t});n.set(t.id,e)}}async buildIndices(e,t,n){let r=[];if(e.CARD){let t=await this.buildEloIndex(e.CARD,n);r.push(t)}if(e.TAG){let t=await this.buildTagIndex(e.TAG,n);r.push(t)}for(let e of t)for(let[t,a]of Object.entries(e.views))if(a.map){logger.info(`Processing view: ${e._id}/${t}`);let a=await this.buildViewIndex(t,e,n);a?(r.push(a),logger.info(`Successfully built index: ${a.name}`)):logger.warn(`Skipped view index: ${e._id}/${t}`)}return r}async buildEloIndex(e,t){let n=[];for(let t of e)t.elo?.global?.score&&n.push({elo:t.elo.global.score,cardId:t._id});n.sort((e,t)=>e.elo-t.elo);let r={},a=50;for(let e of n){let t=Math.floor(e.elo/50)*50;r[t]||(r[t]=[]),r[t].push(e.cardId)}return t.set(`elo`,{sorted:n,buckets:r,stats:{min:n[0]?.elo||0,max:n[n.length-1]?.elo||0,count:n.length}}),{name:`elo`,type:`btree`,path:`indices/elo.json`}}async buildTagIndex(e,t){let n={};for(let t of e)n[t.name]={cardIds:t.taggedCards,snippet:t.snippet,count:t.taggedCards.length};let r={};for(let t of e)for(let e of t.taggedCards)r[e]||(r[e]=[]),r[e].push(t.name);return t.set(`tags`,{byTag:n,byCard:r}),{name:`tags`,type:`hash`,path:`indices/tags.json`}}async buildViewIndex(e,t,n){if(!this.sourceDB)return logger.error(`Source database not available for view querying`),null;try{let r=`${t._id.replace(`_design/`,``)}/${e}`;logger.info(`Querying CouchDB view: ${r}`);let a=await this.sourceDB.query(r,{include_docs:!1});if(!a.rows||a.rows.length===0)return logger.warn(`View ${r} returned no results`),null;logger.info(`Successfully queried view ${r}: ${a.rows.length} results`);let o=this.formatViewResults(e,a.rows,t),s=`view-${t._id.replace(`_design/`,``)}-${e}`;return n.set(s,o),{name:s,type:`view`,path:`indices/${s}.json`}}catch(n){return logger.error(`Failed to query view ${t._id}/${e}:`,n),null}}formatViewResults(e,t,n){let r={type:`couchdb-view`,viewName:e,designDoc:n._id,results:t,metadata:{resultCount:t.length,generatedAt:new Date().toISOString()}};switch(e){case`elo`:return this.formatEloViewIndex(t,r);case`getTags`:return this.formatTagsViewIndex(t,r);case`cardsByInexperience`:return this.formatInexperienceViewIndex(t,r);default:return this.formatGenericViewIndex(t,r)}}formatEloViewIndex(e,t){let n=e.sort((e,t)=>typeof e.key==`number`&&typeof t.key==`number`?e.key-t.key:0);return{...t,sorted:n,stats:{min:n[0]?.key||0,max:n[n.length-1]?.key||0,count:n.length}}}formatTagsViewIndex(e,t){let n={};for(let t of e){let e=t.key;typeof e==`string`&&(n[e]||(n[e]=[]),n[e].push(t.id))}return{...t,byTag:n,tagCount:Object.keys(n).length}}formatInexperienceViewIndex(e,t){let n=e.sort((e,t)=>typeof e.key==`number`&&typeof t.key==`number`?e.key-t.key:0);return{...t,sorted:n,stats:{minInexperience:n[0]?.key||0,maxInexperience:n[n.length-1]?.key||0,count:n.length}}}formatGenericViewIndex(e,t){return{...t}}async extractAllAttachments(e,t){logger.info(`Extracting attachments...`);let n=[];for(let t of Object.values(e))n.push(...t);let r=n.filter(e=>e._attachments&&Object.keys(e._attachments).length>0);if(r.length===0){logger.info(`No attachments found`);return}logger.info(`Found ${r.length} documents with attachments`);let a=r.map(e=>this.extractDocumentAttachments(e,t));await Promise.all(a),logger.info(`Extracted ${t.size} attachment files`)}async extractDocumentAttachments(e,t){if(!e._attachments||!this.sourceDB)return;let n=e._id;for(let[r,a]of Object.entries(e._attachments))try{let e=await this.sourceDB.getAttachment(n,r),o;if(e instanceof ArrayBuffer)o=Buffer.from(e);else if(Buffer.isBuffer(e))o=e;else{let t=e;o=Buffer.from(await t.arrayBuffer())}let s=`${r}${this.getFileExtension(a.content_type)}`,c=`attachments/${n}/${s}`;t.set(c,{docId:n,attachmentName:r,filename:s,path:c,contentType:a.content_type,length:a.length||o.length,digest:a.digest,buffer:o}),logger.debug(`Extracted attachment: ${c}`)}catch(e){throw logger.error(`Failed to extract attachment ${n}/${r}:`,e),Error(`Failed to extract attachment ${n}/${r}: ${e}`)}}transformAttachmentStubs(e,t){let n={};for(let[r,a]of Object.entries(e))n[r]={path:`attachments/${t}/${`${r}${this.getFileExtension(a.content_type)}`}`,content_type:a.content_type,length:a.length,digest:a.digest,stub:!1};return n}getFileExtension(e){return{"image/jpeg":`.jpg`,"image/jpg":`.jpg`,"image/png":`.png`,"image/gif":`.gif`,"image/webp":`.webp`,"audio/mpeg":`.mp3`,"audio/mp3":`.mp3`,"audio/wav":`.wav`,"audio/ogg":`.ogg`,"video/mp4":`.mp4`,"video/webm":`.webm`,"application/pdf":`.pdf`,"text/plain":`.txt`,"application/json":`.json`}[e]||``}};init_logger();var DEFAULT_MIGRATION_OPTIONS={chunkBatchSize:100,validateRoundTrip:!1,cleanupOnFailure:!0,timeout:3e5};init_logger();var FileSystemError=class extends Error{constructor(e,t,n,r){super(e),this.operation=t,this.filePath=n,this.cause=r,this.name=`FileSystemError`}},nodeFS2=null;try{typeof window>`u`&&typeof process<`u`&&process.versions?.node&&(nodeFS2=eval(`require`)(`fs`),nodeFS2.promises=nodeFS2.promises||eval(`require`)(`fs`).promises)}catch{}async function validateStaticCourse(e,t){let n={valid:!0,manifestExists:!1,chunksExist:!1,attachmentsExist:!1,errors:[],warnings:[]};try{if(t){if(!(await t.stat(e)).isDirectory())return n.errors.push(`Path is not a directory: ${e}`),n.valid=!1,n}else if(!nodeFS2)return n.errors.push(`File system access not available - validation skipped`),n.valid=!1,n;else if(!(await nodeFS2.promises.stat(e)).isDirectory())return n.errors.push(`Path is not a directory: ${e}`),n.valid=!1,n;let r=`${e}/manifest.json`;try{if(t)if(r=t.joinPath(e,`manifest.json`),await t.exists(r)){n.manifestExists=!0;let e=await t.readFile(r),a=JSON.parse(e);n.courseId=a.courseId,n.courseName=a.courseName,(!a.version||!a.courseId||!a.chunks||!Array.isArray(a.chunks))&&(n.errors.push(`Invalid manifest structure`),n.valid=!1)}else n.errors.push(`Manifest not found: ${r}`),n.valid=!1;else{r=`${e}/manifest.json`,await nodeFS2.promises.access(r),n.manifestExists=!0;let t=await nodeFS2.promises.readFile(r,`utf8`),a=JSON.parse(t);n.courseId=a.courseId,n.courseName=a.courseName,(!a.version||!a.courseId||!a.chunks||!Array.isArray(a.chunks))&&(n.errors.push(`Invalid manifest structure`),n.valid=!1)}}catch(e){let t=e instanceof FileSystemError?e.message:`Manifest not found or invalid: ${r}`;n.errors.push(t),n.valid=!1}let a=`${e}/chunks`;try{t?(a=t.joinPath(e,`chunks`),await t.exists(a)?(await t.stat(a)).isDirectory()?n.chunksExist=!0:(n.errors.push(`Chunks path is not a directory: ${a}`),n.valid=!1):(n.errors.push(`Chunks directory not found: ${a}`),n.valid=!1)):(a=`${e}/chunks`,(await nodeFS2.promises.stat(a)).isDirectory()?n.chunksExist=!0:(n.errors.push(`Chunks path is not a directory: ${a}`),n.valid=!1))}catch(e){let t=e instanceof FileSystemError?e.message:`Chunks directory not found: ${a}`;n.errors.push(t),n.valid=!1}let o;try{t?(o=t.joinPath(e,`attachments`),await t.exists(o)?(await t.stat(o)).isDirectory()&&(n.attachmentsExist=!0):n.warnings.push(`Attachments directory not found: ${o} (this is OK if course has no attachments)`)):(o=`${e}/attachments`,(await nodeFS2.promises.stat(o)).isDirectory()&&(n.attachmentsExist=!0))}catch(t){o=o||`${e}/attachments`;let r=t instanceof FileSystemError?t.message:`Attachments directory not found: ${o} (this is OK if course has no attachments)`;n.warnings.push(r)}}catch(e){n.errors.push(`Failed to validate static course: ${e instanceof Error?e.message:String(e)}`),n.valid=!1}return n}async function validateMigration(e,t,n){let r={valid:!0,documentCountMatch:!1,attachmentIntegrity:!1,viewFunctionality:!1,issues:[]};try{logger.info(`Starting migration validation...`),r.documentCountMatch=compareDocumentCounts(t,await getActualDocumentCounts(e),r.issues),await validateCourseConfig(e,n,r.issues),r.viewFunctionality=await validateViews(e,n,r.issues),r.attachmentIntegrity=await validateAttachmentIntegrity(e,r.issues),r.valid=r.documentCountMatch&&r.viewFunctionality&&r.attachmentIntegrity,logger.info(`Migration validation completed. Valid: ${r.valid}`),r.issues.length>0&&(logger.info(`Validation issues: ${r.issues.length}`),r.issues.forEach(e=>{e.type===`error`?logger.error(`${e.category}: ${e.message}`):logger.warn(`${e.category}: ${e.message}`)}))}catch(e){r.valid=!1,r.issues.push({type:`error`,category:`metadata`,message:`Validation failed: ${e instanceof Error?e.message:String(e)}`})}return r}async function getActualDocumentCounts(e){let t={};try{let n=await e.allDocs({include_docs:!0});for(let e of n.rows){if(e.id.startsWith(`_design/`)){t._design=(t._design||0)+1;continue}let n=e.doc;n&&n.docType?t[n.docType]=(t[n.docType]||0)+1:t.unknown=(t.unknown||0)+1}}catch(e){logger.error(`Failed to get actual document counts:`,e)}return t}function compareDocumentCounts(e,t,n){let r=!0;for(let[a,o]of Object.entries(e)){let e=t[a]||0;e!==o&&(r=!1,n.push({type:`error`,category:`documents`,message:`Document count mismatch for ${a}: expected ${o}, got ${e}`}))}for(let[r,a]of Object.entries(t))!e[r]&&r!==`_design`&&n.push({type:`warning`,category:`documents`,message:`Unexpected document type found: ${r} (${a} documents)`});return r}async function validateCourseConfig(e,t,n){try{let r=await e.get(`CourseConfig`);if(!r){n.push({type:`error`,category:`course_config`,message:`CourseConfig document not found after migration`});return}r.courseID||n.push({type:`warning`,category:`course_config`,message:`CourseConfig document missing courseID field`}),r.courseID!==t.courseId&&n.push({type:`warning`,category:`course_config`,message:`CourseConfig courseID mismatch: expected ${t.courseId}, got ${r.courseID}`}),logger.debug(`CourseConfig document validation passed`)}catch(e){e.status===404?n.push({type:`error`,category:`course_config`,message:`CourseConfig document not found in database`}):n.push({type:`error`,category:`course_config`,message:`Failed to validate CourseConfig document: ${e instanceof Error?e.message:String(e)}`})}}async function validateViews(e,t,n){let r=!0;try{for(let a of t.designDocs)try{if(!await e.get(a._id)){r=!1,n.push({type:`error`,category:`views`,message:`Design document not found: ${a._id}`});continue}for(let t of Object.keys(a.views))try{let n=`${a._id}/${t}`;await e.query(n,{limit:1})}catch(e){r=!1,n.push({type:`error`,category:`views`,message:`View not accessible: ${a._id}/${t} - ${e}`})}}catch(e){r=!1,n.push({type:`error`,category:`views`,message:`Failed to validate design document ${a._id}: ${e}`})}}catch(e){r=!1,n.push({type:`error`,category:`views`,message:`View validation failed: ${e instanceof Error?e.message:String(e)}`})}return r}async function validateAttachmentIntegrity(e,t){let n=!0;try{let r=await e.allDocs({include_docs:!0,limit:10}),a=0,o=0;for(let s of r.rows){let r=s.doc;if(r&&r._attachments)for(let[s,c]of Object.entries(r._attachments)){a++;try{await e.getAttachment(r._id,s)&&o++}catch(e){n=!1,t.push({type:`error`,category:`attachments`,message:`Attachment not accessible: ${r._id}/${s} - ${e}`})}}}a===0?t.push({type:`warning`,category:`attachments`,message:`No attachments found in sampled documents`}):logger.info(`Validated ${o}/${a} sampled attachments`)}catch(e){n=!1,t.push({type:`error`,category:`attachments`,message:`Attachment validation failed: ${e instanceof Error?e.message:String(e)}`})}return n}var nodeFS3=null,nodePath=null;try{typeof window>`u`&&typeof process<`u`&&process.versions?.node&&(nodeFS3=eval(`require`)(`fs`),nodePath=eval(`require`)(`path`),nodeFS3.promises=nodeFS3.promises||eval(`require`)(`fs`).promises)}catch{}var StaticToCouchDBMigrator=class{constructor(e={},t){_defineProperty(this,`options`,void 0),_defineProperty(this,`progressCallback`,void 0),_defineProperty(this,`fs`,void 0),this.options={...DEFAULT_MIGRATION_OPTIONS,...e},this.fs=t}setProgressCallback(e){this.progressCallback=e}async migrateCourse(e,t){let n=Date.now(),r={success:!1,documentsRestored:0,attachmentsRestored:0,designDocsRestored:0,courseConfigRestored:0,errors:[],warnings:[],migrationTime:0};try{logger.info(`Starting migration from ${e} to CouchDB`),this.reportProgress(`manifest`,0,1,`Validating static course...`);let a=await validateStaticCourse(e,this.fs);if(!a.valid)throw r.errors.push(...a.errors),Error(`Static course validation failed: ${a.errors.join(`, `)}`);r.warnings.push(...a.warnings),this.reportProgress(`manifest`,1,1,`Loading course manifest...`);let o=await this.loadManifest(e);logger.info(`Loaded manifest for course: ${o.courseId} (${o.courseName})`),this.reportProgress(`design_docs`,0,o.designDocs.length,`Restoring design documents...`);let s=await this.restoreDesignDocuments(o.designDocs,t);r.designDocsRestored=s.restored,r.errors.push(...s.errors),r.warnings.push(...s.warnings),this.reportProgress(`course_config`,0,1,`Restoring CourseConfig document...`);let c=await this.restoreCourseConfig(o,t);r.courseConfigRestored=c.restored,r.errors.push(...c.errors),r.warnings.push(...c.warnings),this.reportProgress(`course_config`,1,1,`CourseConfig document restored`);let l=this.calculateExpectedCounts(o);this.reportProgress(`documents`,0,o.documentCount,`Aggregating documents from chunks...`);let u=await this.aggregateDocuments(e,o),d=u.filter(e=>e._id!==`CourseConfig`);u.length!==d.length&&r.warnings.push(`Filtered out ${u.length-d.length} CourseConfig document(s) from chunks to prevent conflicts`),this.reportProgress(`documents`,d.length,o.documentCount,`Uploading documents to CouchDB...`);let p=await this.uploadDocuments(d,t);r.documentsRestored=p.restored,r.errors.push(...p.errors),r.warnings.push(...p.warnings);let m=u.filter(e=>e._attachments&&Object.keys(e._attachments).length>0);this.reportProgress(`attachments`,0,m.length,`Uploading attachments...`);let g=await this.uploadAttachments(e,m,t);if(r.attachmentsRestored=g.restored,r.errors.push(...g.errors),r.warnings.push(...g.warnings),this.options.validateRoundTrip){this.reportProgress(`validation`,0,1,`Validating migration...`);let e=await validateMigration(t,l,o);e.valid||(r.warnings.push(`Migration validation found issues`),e.issues.forEach(e=>{e.type===`error`?r.errors.push(`Validation: ${e.message}`):r.warnings.push(`Validation: ${e.message}`)})),this.reportProgress(`validation`,1,1,`Migration validation completed`)}r.success=r.errors.length===0,r.migrationTime=Date.now()-n,logger.info(`Migration completed in ${r.migrationTime}ms`),logger.info(`Documents restored: ${r.documentsRestored}`),logger.info(`Attachments restored: ${r.attachmentsRestored}`),logger.info(`Design docs restored: ${r.designDocsRestored}`),logger.info(`CourseConfig restored: ${r.courseConfigRestored}`),r.errors.length>0&&logger.error(`Migration completed with ${r.errors.length} errors`),r.warnings.length>0&&logger.warn(`Migration completed with ${r.warnings.length} warnings`)}catch(e){r.success=!1,r.migrationTime=Date.now()-n;let a=e instanceof Error?e.message:String(e);if(r.errors.push(`Migration failed: ${a}`),logger.error(`Migration failed:`,e),this.options.cleanupOnFailure)try{await this.cleanupFailedMigration(t)}catch(e){logger.error(`Failed to cleanup after migration failure:`,e),r.warnings.push(`Failed to cleanup after migration failure`)}}return r}async loadManifest(e){try{let t,n;if(this.fs)n=this.fs.joinPath(e,`manifest.json`),t=await this.fs.readFile(n);else if(n=nodeFS3&&nodePath?nodePath.join(e,`manifest.json`):`${e}/manifest.json`,nodeFS3&&this.isLocalPath(e))t=await nodeFS3.promises.readFile(n,`utf8`);else{let e=await fetch(n);if(!e.ok)throw Error(`Failed to fetch manifest: ${e.status} ${e.statusText}`);t=await e.text()}let r=JSON.parse(t);if(!r.version||!r.courseId||!r.chunks)throw Error(`Invalid manifest structure`);return r}catch(e){let t=e instanceof FileSystemError?e.message:`Failed to load manifest: ${e instanceof Error?e.message:String(e)}`;throw Error(t)}}async restoreDesignDocuments(e,t){let n={restored:0,errors:[],warnings:[]};for(let r=0;r<e.length;r++){let a=e[r];this.reportProgress(`design_docs`,r,e.length,`Restoring ${a._id}...`);try{let e;try{e=await t.get(a._id)}catch{}let r={_id:a._id,views:a.views};e?(r._rev=e._rev,logger.debug(`Updating existing design document: ${a._id}`)):logger.debug(`Creating new design document: ${a._id}`),await t.put(r),n.restored++}catch(e){let t=`Failed to restore design document ${a._id}: ${e instanceof Error?e.message:String(e)}`;n.errors.push(t),logger.error(t)}}return this.reportProgress(`design_docs`,e.length,e.length,`Restored ${n.restored} design documents`),n}async aggregateDocuments(e,t){let n=[],r=new Map;for(let a=0;a<t.chunks.length;a++){let o=t.chunks[a];this.reportProgress(`documents`,n.length,t.documentCount,`Loading chunk ${o.id}...`);try{let t=await this.loadChunk(e,o);for(let e of t){if(!e._id){logger.warn(`Document without _id found in chunk ${o.id}, skipping`);continue}r.has(e._id)&&logger.warn(`Duplicate document ID found: ${e._id}, using latest version`),r.set(e._id,e)}}catch(e){throw Error(`Failed to load chunk ${o.id}: ${e instanceof Error?e.message:String(e)}`)}}return n.push(...r.values()),logger.info(`Aggregated ${n.length} unique documents from ${t.chunks.length} chunks`),n}async loadChunk(e,t){try{let n,r;if(this.fs)r=this.fs.joinPath(e,t.path),n=await this.fs.readFile(r);else if(r=nodeFS3&&nodePath?nodePath.join(e,t.path):`${e}/${t.path}`,nodeFS3&&this.isLocalPath(e))n=await nodeFS3.promises.readFile(r,`utf8`);else{let e=await fetch(r);if(!e.ok)throw Error(`Failed to fetch chunk: ${e.status} ${e.statusText}`);n=await e.text()}let a=JSON.parse(n);if(!Array.isArray(a))throw Error(`Chunk file does not contain an array of documents`);return a}catch(e){let t=e instanceof FileSystemError?e.message:`Failed to load chunk: ${e instanceof Error?e.message:String(e)}`;throw Error(t)}}async uploadDocuments(e,t){let n={restored:0,errors:[],warnings:[]},r=this.options.chunkBatchSize;for(let a=0;a<e.length;a+=r){let o=e.slice(a,a+r);this.reportProgress(`documents`,a,e.length,`Uploading batch ${Math.floor(a/r)+1}...`);try{let e=o.map(e=>{let t={...e};return delete t._rev,delete t._attachments,t}),r=await t.bulkDocs(e);for(let e=0;e<r.length;e++){let t=r[e],a=o[e];if(`error`in t){let e=`Failed to upload document ${a._id}: ${t.error} - ${t.reason}`;n.errors.push(e),logger.error(e)}else n.restored++}}catch(e){let t;t=e instanceof Error||e&&typeof e==`object`&&`message`in e?`Failed to upload document batch starting at index ${a}: ${e.message}`:`Failed to upload document batch starting at index ${a}: ${JSON.stringify(e)}`,n.errors.push(t),logger.error(t)}}return this.reportProgress(`documents`,e.length,e.length,`Uploaded ${n.restored} documents`),n}async uploadAttachments(e,t,n){let r={restored:0,errors:[],warnings:[]},a=0;for(let o of t)if(this.reportProgress(`attachments`,a,t.length,`Processing attachments for ${o._id}...`),a++,o._attachments)for(let[t,a]of Object.entries(o._attachments))try{let s=await this.uploadSingleAttachment(e,o._id,t,a,n);s.success?r.restored++:r.errors.push(s.error||`Unknown attachment upload error`)}catch(e){let n=`Failed to upload attachment ${o._id}/${t}: ${e instanceof Error?e.message:String(e)}`;r.errors.push(n),logger.error(n)}return this.reportProgress(`attachments`,t.length,t.length,`Uploaded ${r.restored} attachments`),r}async uploadSingleAttachment(e,t,n,r,a){let o={success:!1,attachmentName:n,docId:t};try{if(!r.path)return o.error=`Attachment metadata missing file path`,o;let s,c;if(this.fs)c=this.fs.joinPath(e,r.path),s=await this.fs.readBinary(c);else if(c=nodeFS3&&nodePath?nodePath.join(e,r.path):`${e}/${r.path}`,nodeFS3&&this.isLocalPath(e))s=await nodeFS3.promises.readFile(c);else{let e=await fetch(c);if(!e.ok)return o.error=`Failed to fetch attachment: ${e.status} ${e.statusText}`,o;s=await e.arrayBuffer()}let l=await a.get(t);await a.putAttachment(t,n,l._rev,s,r.content_type),o.success=!0}catch(e){o.error=e instanceof Error?e.message:String(e)}return o}async restoreCourseConfig(e,t){let n={restored:0,errors:[],warnings:[]};try{if(!e.courseConfig)return n.warnings.push(`No courseConfig found in manifest, skipping CourseConfig document creation`),n;let r={_id:`CourseConfig`,...e.courseConfig,courseID:e.courseId};delete r._rev,await t.put(r),n.restored=1,logger.info(`CourseConfig document created for course: ${e.courseId}`)}catch(e){let t=e instanceof Error?e.message:JSON.stringify(e);n.errors.push(`Failed to restore CourseConfig: ${t}`),logger.error(`CourseConfig restoration failed:`,e)}return n}calculateExpectedCounts(e){let t={};for(let n of e.chunks)t[n.docType]=(t[n.docType]||0)+n.documentCount;return e.designDocs.length>0&&(t._design=e.designDocs.length),t}async cleanupFailedMigration(e){logger.info(`Cleaning up failed migration...`);try{let t=(await e.allDocs()).rows.map(e=>({_id:e.id,_rev:e.value.rev,_deleted:!0}));t.length>0&&(await e.bulkDocs(t),logger.info(`Cleaned up ${t.length} documents from failed migration`))}catch(e){throw logger.error(`Failed to cleanup documents:`,e),e}}reportProgress(e,t,n,r){this.progressCallback&&this.progressCallback({phase:e,current:t,total:n,message:r})}isLocalPath(e){return!e.startsWith(`http://`)&&!e.startsWith(`https://`)}};init_dataDirectory(),init_navigators(),init_Pipeline();var QuotaRoundRobinMixer=class{mix(e,t){if(e.length===0)return[];let n=Math.ceil(t/e.length),r=e.map(e=>[...e.weighted].sort((e,t)=>t.score-e.score).slice(0,n));for(let e=r.length-1;e>0;e--){let t=Math.floor(Math.random()*(e+1));[r[e],r[t]]=[r[t],r[e]]}let a=[],o=0,s=Array(r.length).fill(0);for(;a.length<t&&o<r.length;){o=0;for(let e=0;e<r.length&&!(a.length>=t);e++)s[e]<r[e].length?(a.push(r[e][s[e]]),s[e]++):o++}return a}};init_logger(),init_navigators();var MAX_RUNS2=10,runHistory2=[];function buildSourceSummary(e,t,n){let r=e.weighted.map(e=>e.score),a=e.weighted.filter(e=>getCardOrigin(e)===`review`).length,o=e.weighted.filter(e=>getCardOrigin(e)===`new`).length;return{sourceIndex:e.sourceIndex,sourceId:t,sourceName:n,totalCards:e.weighted.length,reviewCount:a,newCount:o,topScore:r.length>0?Math.max(...r):0,bottomScore:r.length>0?Math.min(...r):0,scoreRange:r.length>0?[Math.min(...r),Math.max(...r)]:[0,0],avgScore:r.length>0?r.reduce((e,t)=>e+t,0)/r.length:0}}function buildSourceBreakdown(e,t,n){let r=n.filter(t=>t.courseId===e),a=r.filter(e=>e.selected);return{sourceId:e,sourceName:t,reviewsProvided:r.filter(e=>e.origin===`review`).length,newProvided:r.filter(e=>e.origin===`new`).length,reviewsSelected:a.filter(e=>e.origin===`review`).length,newSelected:a.filter(e=>e.origin===`new`).length,totalSelected:a.length,selectionRate:r.length>0?a.length/r.length*100:0}}function captureMixerRun(e,t,n,r,a,o,s){let c=t.map((e,t)=>buildSourceSummary(e,n[t]||`source-${t}`,r[t])),l=new Set(s.map(e=>e.cardId)),u=new Map;t.forEach(e=>{let t=[...e.weighted].sort((e,t)=>t.score-e.score),r=new Map;t.forEach((e,t)=>{r.set(e.cardId,t+1)}),u.set(n[e.sourceIndex]||`source-${e.sourceIndex}`,r)});let d=new Map;s.forEach((e,t)=>{d.set(e.cardId,t+1)});let p=new Map;t.forEach(e=>{e.weighted.forEach(e=>{p.set(e.cardId,e)})});let m=Array.from(p.values()).map(e=>({cardId:e.cardId,courseId:e.courseId,origin:getCardOrigin(e),score:e.score,sourceIndex:t.findIndex(t=>t.weighted.some(t=>t.cardId===e.cardId)),selected:l.has(e.cardId),rankInSource:u.get(e.courseId)?.get(e.cardId),rankInMix:d.get(e.cardId)})),g=Array.from(new Set(n.filter(e=>e))).map((e,t)=>buildSourceBreakdown(e,r[t],m)),_={runId:`mix-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,timestamp:new Date,mixerType:e,requestedLimit:a,quotaPerSource:o,sourceSummaries:c,cards:m,finalCount:s.length,reviewsSelected:s.filter(e=>getCardOrigin(e)===`review`).length,newSelected:s.filter(e=>getCardOrigin(e)===`new`).length,sourceBreakdowns:g};runHistory2.unshift(_),runHistory2.length>MAX_RUNS2&&runHistory2.pop()}function printMixerSummary(e){console.group(`\u{1F3A8} Mixer Run: ${e.mixerType}`),logger.info(`Run ID: ${e.runId}`),logger.info(`Time: ${e.timestamp.toISOString()}`),logger.info(`Config: limit=${e.requestedLimit}${e.quotaPerSource?`, quota/source=${e.quotaPerSource}`:``}`),console.group(`\u{1F4E5} Input: ${e.sourceSummaries.length} sources`);for(let t of e.sourceSummaries)logger.info(` ${t.sourceName||t.sourceId}: ${t.totalCards} cards (${t.reviewCount} reviews, ${t.newCount} new)`),logger.info(` Score range: [${t.scoreRange[0].toFixed(2)}, ${t.scoreRange[1].toFixed(2)}], avg: ${t.avgScore.toFixed(2)}`);console.groupEnd(),console.group(`\u{1F4E4} Output: ${e.finalCount} cards selected (${e.reviewsSelected} reviews, ${e.newSelected} new)`);for(let t of e.sourceBreakdowns){let e=t.sourceName||t.sourceId;logger.info(` ${e}: ${t.totalSelected} selected (${t.reviewsSelected} reviews, ${t.newSelected} new) - ${t.selectionRate.toFixed(1)}% selection rate`)}console.groupEnd(),console.groupEnd()}var mixerDebugAPI={get runs(){return[...runHistory2]},showRun(e=0){if(runHistory2.length===0){logger.info(`[Mixer Debug] No runs captured yet.`);return}let t;if(typeof e==`number`){if(t=runHistory2[e],!t){logger.info(`[Mixer Debug] No run found at index ${e}. History length: ${runHistory2.length}`);return}}else if(t=runHistory2.find(t=>t.runId.endsWith(e)),!t){logger.info(`[Mixer Debug] No run found matching ID '${e}'.`);return}printMixerSummary(t)},showLastMix(){this.showRun(0)},explainSourceBalance(){if(runHistory2.length===0){logger.info(`[Mixer Debug] No runs captured yet.`);return}let e=runHistory2[0];console.group(`⚖️ Source Balance Analysis`),logger.info(`Mixer: ${e.mixerType}`),logger.info(`Requested limit: ${e.requestedLimit}`),e.quotaPerSource&&logger.info(`Quota per source: ${e.quotaPerSource}`),console.group(`Input Distribution:`);for(let t of e.sourceSummaries){let e=t.sourceName||t.sourceId;logger.info(`${e}:`),logger.info(` Provided: ${t.totalCards} cards (${t.reviewCount} reviews, ${t.newCount} new)`),logger.info(` Score range: [${t.scoreRange[0].toFixed(2)}, ${t.scoreRange[1].toFixed(2)}]`)}console.groupEnd(),console.group(`Selection Results:`);for(let t of e.sourceBreakdowns){let e=t.sourceName||t.sourceId;logger.info(`${e}:`),logger.info(` Selected: ${t.totalSelected}/${t.reviewsProvided+t.newProvided} (${t.selectionRate.toFixed(1)}%)`),logger.info(` Reviews: ${t.reviewsSelected}/${t.reviewsProvided}`),logger.info(` New: ${t.newSelected}/${t.newProvided}`),t.reviewsProvided>0&&t.reviewsSelected===0&&logger.info(` ⚠️ Had reviews but none selected!`),t.totalSelected===0&&t.reviewsProvided+t.newProvided>0&&logger.info(` ⚠️ Had cards but none selected!`)}console.groupEnd();let t=e.sourceBreakdowns.map(e=>e.selectionRate),n=t.reduce((e,t)=>e+t,0)/t.length,r=Math.max(...t.map(e=>Math.abs(e-n)));r>20&&(logger.info(`
|
|
283
|
+
`)}}}});function makeStudySessionId(e,t,n){return`${DocTypePrefixes.STUDY_SESSION}::${e}::${t}::${n}`}function newSessionId(){return`session-${Date.now()}-${Math.random().toString(36).slice(2,8)}`}var init_studySession=__esm({"src/core/types/studySession.ts"(){init_types_legacy()}}),init_types3=__esm({"src/util/packer/types.ts"(){}}),CouchDBToStaticPacker,init_CouchDBToStaticPacker=__esm({"src/util/packer/CouchDBToStaticPacker.ts"(){init_types_legacy(),init_logger(),CouchDBToStaticPacker=class{constructor(e={}){_defineProperty(this,`config`,void 0),_defineProperty(this,`sourceDB`,null),this.config={chunkSize:1e3,includeAttachments:!0,...e}}async packCourse(e,t){logger.info(`Starting static pack for course: ${t}`),this.sourceDB=e;let n={version:`1.0.0`,courseId:t,courseName:``,courseConfig:null,lastUpdated:new Date().toISOString(),documentCount:0,chunks:[],indices:[],designDocs:[]},r=await this.extractCourseConfig(e);n.courseName=r.name,n.courseConfig=r,n.designDocs=await this.extractDesignDocs(e);let a=await this.extractDocumentsByType(e),o=new Map;this.config.includeAttachments&&await this.extractAllAttachments(a,o);let s=new Map;for(let[e,t]of Object.entries(a)){let r=this.createChunks(t,e);n.chunks.push(...r),n.documentCount+=t.length,this.prepareChunkData(r,t,s)}let c=new Map;return n.indices=await this.buildIndices(a,n.designDocs,c),{manifest:n,chunks:s,indices:c,attachments:o}}async packCourseToFiles(e,t,n,r){logger.info(`Packing course ${t} to files in ${n}`);let a=await this.packCourse(e,t),o=await this.writePackedDataToFiles(a,n,r);return{manifest:a.manifest,filesWritten:o,attachmentsFound:a.attachments?a.attachments.size:0}}async writePackedDataToFiles(e,t,n){let r=0;await n.ensureDir(t);let a=n.joinPath(t,`manifest.json`);await n.writeJson(a,e.manifest,{spaces:2}),r++,logger.info(`Wrote manifest: ${a}`);let o=n.joinPath(t,`chunks`),s=n.joinPath(t,`indices`);await n.ensureDir(o),await n.ensureDir(s);for(let[t,a]of e.chunks){let e=n.joinPath(o,`${t}.json`);await n.writeJson(e,a),r++}logger.info(`Wrote ${e.chunks.size} chunk files`);for(let[t,a]of e.indices){let e=n.joinPath(s,`${t}.json`);await n.writeJson(e,a,{spaces:2}),r++}if(logger.info(`Wrote ${e.indices.size} index files`),e.attachments&&e.attachments.size>0){for(let[a,o]of e.attachments){let e=n.joinPath(t,a),s=n.dirname(e);await n.ensureDir(s),await n.writeFile(e,o.buffer),r++}logger.info(`Wrote ${e.attachments.size} attachment files`)}return r}async extractCourseConfig(e){try{return await e.get(`CourseConfig`)}catch(e){throw logger.error(`Failed to extract course config:`,e),Error(`Course config not found`)}}async extractDesignDocs(e){return(await e.allDocs({startkey:`_design/`,endkey:`_design/`,include_docs:!0})).rows.map(e=>({_id:e.id,views:e.doc.views||{}}))}async extractDocumentsByType(e){let t=await e.allDocs({include_docs:!0}),n={};for(let e of t.rows){if(e.id.startsWith(`_`))continue;let t=e.doc;t.docType&&(n[t.docType]||(n[t.docType]=[]),n[t.docType].push(t))}return n}createChunks(e,t){let n=[],r=e.sort((e,t)=>e._id.localeCompare(t._id));for(let e=0;e<r.length;e+=this.config.chunkSize){let a=r.slice(e,e+this.config.chunkSize),o=`${t}-${String(Math.floor(e/this.config.chunkSize)).padStart(4,`0`)}`;n.push({id:o,docType:t,startKey:a[0]._id,endKey:a[a.length-1]._id,documentCount:a.length,path:`chunks/${o}.json`})}return n}prepareChunkData(e,t,n){let r=t.sort((e,t)=>e._id.localeCompare(t._id));for(let t of e){let e=r.filter(e=>e._id>=t.startKey&&e._id<=t.endKey).map(e=>{let t={...e};return delete t._rev,this.config.includeAttachments&&t._attachments?t._attachments=this.transformAttachmentStubs(t._attachments,t._id):this.config.includeAttachments||delete t._attachments,t});n.set(t.id,e)}}async buildIndices(e,t,n){let r=[];if(e.CARD){let t=await this.buildEloIndex(e.CARD,n);r.push(t)}if(e.TAG){let t=await this.buildTagIndex(e.TAG,n);r.push(t)}for(let e of t)for(let[t,a]of Object.entries(e.views))if(a.map){logger.info(`Processing view: ${e._id}/${t}`);let a=await this.buildViewIndex(t,e,n);a?(r.push(a),logger.info(`Successfully built index: ${a.name}`)):logger.warn(`Skipped view index: ${e._id}/${t}`)}return r}async buildEloIndex(e,t){let n=[];for(let t of e)t.elo?.global?.score&&n.push({elo:t.elo.global.score,cardId:t._id});n.sort((e,t)=>e.elo-t.elo);let r={},a=50;for(let e of n){let t=Math.floor(e.elo/50)*50;r[t]||(r[t]=[]),r[t].push(e.cardId)}return t.set(`elo`,{sorted:n,buckets:r,stats:{min:n[0]?.elo||0,max:n[n.length-1]?.elo||0,count:n.length}}),{name:`elo`,type:`btree`,path:`indices/elo.json`}}async buildTagIndex(e,t){let n={};for(let t of e)n[t.name]={cardIds:t.taggedCards,snippet:t.snippet,count:t.taggedCards.length};let r={};for(let t of e)for(let e of t.taggedCards)r[e]||(r[e]=[]),r[e].push(t.name);return t.set(`tags`,{byTag:n,byCard:r}),{name:`tags`,type:`hash`,path:`indices/tags.json`}}async buildViewIndex(e,t,n){if(!this.sourceDB)return logger.error(`Source database not available for view querying`),null;try{let r=`${t._id.replace(`_design/`,``)}/${e}`;logger.info(`Querying CouchDB view: ${r}`);let a=await this.sourceDB.query(r,{include_docs:!1});if(!a.rows||a.rows.length===0)return logger.warn(`View ${r} returned no results`),null;logger.info(`Successfully queried view ${r}: ${a.rows.length} results`);let o=this.formatViewResults(e,a.rows,t),s=`view-${t._id.replace(`_design/`,``)}-${e}`;return n.set(s,o),{name:s,type:`view`,path:`indices/${s}.json`}}catch(n){return logger.error(`Failed to query view ${t._id}/${e}:`,n),null}}formatViewResults(e,t,n){let r={type:`couchdb-view`,viewName:e,designDoc:n._id,results:t,metadata:{resultCount:t.length,generatedAt:new Date().toISOString()}};switch(e){case`elo`:return this.formatEloViewIndex(t,r);case`getTags`:return this.formatTagsViewIndex(t,r);case`cardsByInexperience`:return this.formatInexperienceViewIndex(t,r);default:return this.formatGenericViewIndex(t,r)}}formatEloViewIndex(e,t){let n=e.sort((e,t)=>typeof e.key==`number`&&typeof t.key==`number`?e.key-t.key:0);return{...t,sorted:n,stats:{min:n[0]?.key||0,max:n[n.length-1]?.key||0,count:n.length}}}formatTagsViewIndex(e,t){let n={};for(let t of e){let e=t.key;typeof e==`string`&&(n[e]||(n[e]=[]),n[e].push(t.id))}return{...t,byTag:n,tagCount:Object.keys(n).length}}formatInexperienceViewIndex(e,t){let n=e.sort((e,t)=>typeof e.key==`number`&&typeof t.key==`number`?e.key-t.key:0);return{...t,sorted:n,stats:{minInexperience:n[0]?.key||0,maxInexperience:n[n.length-1]?.key||0,count:n.length}}}formatGenericViewIndex(e,t){return{...t}}async extractAllAttachments(e,t){logger.info(`Extracting attachments...`);let n=[];for(let t of Object.values(e))n.push(...t);let r=n.filter(e=>e._attachments&&Object.keys(e._attachments).length>0);if(r.length===0){logger.info(`No attachments found`);return}logger.info(`Found ${r.length} documents with attachments`);let a=r.map(e=>this.extractDocumentAttachments(e,t));await Promise.all(a),logger.info(`Extracted ${t.size} attachment files`)}async extractDocumentAttachments(e,t){if(!e._attachments||!this.sourceDB)return;let n=e._id;for(let[r,a]of Object.entries(e._attachments))try{let e=await this.sourceDB.getAttachment(n,r),o;if(e instanceof ArrayBuffer)o=Buffer.from(e);else if(Buffer.isBuffer(e))o=e;else{let t=e;o=Buffer.from(await t.arrayBuffer())}let s=`${r}${this.getFileExtension(a.content_type)}`,c=`attachments/${n}/${s}`;t.set(c,{docId:n,attachmentName:r,filename:s,path:c,contentType:a.content_type,length:a.length||o.length,digest:a.digest,buffer:o}),logger.debug(`Extracted attachment: ${c}`)}catch(e){throw logger.error(`Failed to extract attachment ${n}/${r}:`,e),Error(`Failed to extract attachment ${n}/${r}: ${e}`)}}transformAttachmentStubs(e,t){let n={};for(let[r,a]of Object.entries(e))n[r]={path:`attachments/${t}/${`${r}${this.getFileExtension(a.content_type)}`}`,content_type:a.content_type,length:a.length,digest:a.digest,stub:!1};return n}getFileExtension(e){return{"image/jpeg":`.jpg`,"image/jpg":`.jpg`,"image/png":`.png`,"image/gif":`.gif`,"image/webp":`.webp`,"audio/mpeg":`.mp3`,"audio/mp3":`.mp3`,"audio/wav":`.wav`,"audio/ogg":`.ogg`,"video/mp4":`.mp4`,"video/webm":`.webm`,"application/pdf":`.pdf`,"text/plain":`.txt`,"application/json":`.json`}[e]||``}}}}),init_packer=__esm({"src/util/packer/index.ts"(){init_types3(),init_CouchDBToStaticPacker()}}),DEFAULT_MIGRATION_OPTIONS,init_types4=__esm({"src/util/migrator/types.ts"(){DEFAULT_MIGRATION_OPTIONS={chunkBatchSize:100,validateRoundTrip:!1,cleanupOnFailure:!0,timeout:3e5}}}),FileSystemError,init_FileSystemAdapter=__esm({"src/util/migrator/FileSystemAdapter.ts"(){FileSystemError=class extends Error{constructor(e,t,n,r){super(e),this.operation=t,this.filePath=n,this.cause=r,this.name=`FileSystemError`}}}});async function validateStaticCourse(e,t){let n={valid:!0,manifestExists:!1,chunksExist:!1,attachmentsExist:!1,errors:[],warnings:[]};try{if(t){if(!(await t.stat(e)).isDirectory())return n.errors.push(`Path is not a directory: ${e}`),n.valid=!1,n}else if(!nodeFS)return n.errors.push(`File system access not available - validation skipped`),n.valid=!1,n;else if(!(await nodeFS.promises.stat(e)).isDirectory())return n.errors.push(`Path is not a directory: ${e}`),n.valid=!1,n;let r=`${e}/manifest.json`;try{if(t)if(r=t.joinPath(e,`manifest.json`),await t.exists(r)){n.manifestExists=!0;let e=await t.readFile(r),a=JSON.parse(e);n.courseId=a.courseId,n.courseName=a.courseName,(!a.version||!a.courseId||!a.chunks||!Array.isArray(a.chunks))&&(n.errors.push(`Invalid manifest structure`),n.valid=!1)}else n.errors.push(`Manifest not found: ${r}`),n.valid=!1;else{r=`${e}/manifest.json`,await nodeFS.promises.access(r),n.manifestExists=!0;let t=await nodeFS.promises.readFile(r,`utf8`),a=JSON.parse(t);n.courseId=a.courseId,n.courseName=a.courseName,(!a.version||!a.courseId||!a.chunks||!Array.isArray(a.chunks))&&(n.errors.push(`Invalid manifest structure`),n.valid=!1)}}catch(e){let t=e instanceof FileSystemError?e.message:`Manifest not found or invalid: ${r}`;n.errors.push(t),n.valid=!1}let a=`${e}/chunks`;try{t?(a=t.joinPath(e,`chunks`),await t.exists(a)?(await t.stat(a)).isDirectory()?n.chunksExist=!0:(n.errors.push(`Chunks path is not a directory: ${a}`),n.valid=!1):(n.errors.push(`Chunks directory not found: ${a}`),n.valid=!1)):(a=`${e}/chunks`,(await nodeFS.promises.stat(a)).isDirectory()?n.chunksExist=!0:(n.errors.push(`Chunks path is not a directory: ${a}`),n.valid=!1))}catch(e){let t=e instanceof FileSystemError?e.message:`Chunks directory not found: ${a}`;n.errors.push(t),n.valid=!1}let o;try{t?(o=t.joinPath(e,`attachments`),await t.exists(o)?(await t.stat(o)).isDirectory()&&(n.attachmentsExist=!0):n.warnings.push(`Attachments directory not found: ${o} (this is OK if course has no attachments)`)):(o=`${e}/attachments`,(await nodeFS.promises.stat(o)).isDirectory()&&(n.attachmentsExist=!0))}catch(t){o=o||`${e}/attachments`;let r=t instanceof FileSystemError?t.message:`Attachments directory not found: ${o} (this is OK if course has no attachments)`;n.warnings.push(r)}}catch(e){n.errors.push(`Failed to validate static course: ${e instanceof Error?e.message:String(e)}`),n.valid=!1}return n}async function validateMigration(e,t,n){let r={valid:!0,documentCountMatch:!1,attachmentIntegrity:!1,viewFunctionality:!1,issues:[]};try{logger.info(`Starting migration validation...`),r.documentCountMatch=compareDocumentCounts(t,await getActualDocumentCounts(e),r.issues),await validateCourseConfig(e,n,r.issues),r.viewFunctionality=await validateViews(e,n,r.issues),r.attachmentIntegrity=await validateAttachmentIntegrity(e,r.issues),r.valid=r.documentCountMatch&&r.viewFunctionality&&r.attachmentIntegrity,logger.info(`Migration validation completed. Valid: ${r.valid}`),r.issues.length>0&&(logger.info(`Validation issues: ${r.issues.length}`),r.issues.forEach(e=>{e.type===`error`?logger.error(`${e.category}: ${e.message}`):logger.warn(`${e.category}: ${e.message}`)}))}catch(e){r.valid=!1,r.issues.push({type:`error`,category:`metadata`,message:`Validation failed: ${e instanceof Error?e.message:String(e)}`})}return r}async function getActualDocumentCounts(e){let t={};try{let n=await e.allDocs({include_docs:!0});for(let e of n.rows){if(e.id.startsWith(`_design/`)){t._design=(t._design||0)+1;continue}let n=e.doc;n&&n.docType?t[n.docType]=(t[n.docType]||0)+1:t.unknown=(t.unknown||0)+1}}catch(e){logger.error(`Failed to get actual document counts:`,e)}return t}function compareDocumentCounts(e,t,n){let r=!0;for(let[a,o]of Object.entries(e)){let e=t[a]||0;e!==o&&(r=!1,n.push({type:`error`,category:`documents`,message:`Document count mismatch for ${a}: expected ${o}, got ${e}`}))}for(let[r,a]of Object.entries(t))!e[r]&&r!==`_design`&&n.push({type:`warning`,category:`documents`,message:`Unexpected document type found: ${r} (${a} documents)`});return r}async function validateCourseConfig(e,t,n){try{let r=await e.get(`CourseConfig`);if(!r){n.push({type:`error`,category:`course_config`,message:`CourseConfig document not found after migration`});return}r.courseID||n.push({type:`warning`,category:`course_config`,message:`CourseConfig document missing courseID field`}),r.courseID!==t.courseId&&n.push({type:`warning`,category:`course_config`,message:`CourseConfig courseID mismatch: expected ${t.courseId}, got ${r.courseID}`}),logger.debug(`CourseConfig document validation passed`)}catch(e){e.status===404?n.push({type:`error`,category:`course_config`,message:`CourseConfig document not found in database`}):n.push({type:`error`,category:`course_config`,message:`Failed to validate CourseConfig document: ${e instanceof Error?e.message:String(e)}`})}}async function validateViews(e,t,n){let r=!0;try{for(let a of t.designDocs)try{if(!await e.get(a._id)){r=!1,n.push({type:`error`,category:`views`,message:`Design document not found: ${a._id}`});continue}for(let t of Object.keys(a.views))try{let n=`${a._id}/${t}`;await e.query(n,{limit:1})}catch(e){r=!1,n.push({type:`error`,category:`views`,message:`View not accessible: ${a._id}/${t} - ${e}`})}}catch(e){r=!1,n.push({type:`error`,category:`views`,message:`Failed to validate design document ${a._id}: ${e}`})}}catch(e){r=!1,n.push({type:`error`,category:`views`,message:`View validation failed: ${e instanceof Error?e.message:String(e)}`})}return r}async function validateAttachmentIntegrity(e,t){let n=!0;try{let r=await e.allDocs({include_docs:!0,limit:10}),a=0,o=0;for(let s of r.rows){let r=s.doc;if(r&&r._attachments)for(let[s,c]of Object.entries(r._attachments)){a++;try{await e.getAttachment(r._id,s)&&o++}catch(e){n=!1,t.push({type:`error`,category:`attachments`,message:`Attachment not accessible: ${r._id}/${s} - ${e}`})}}}a===0?t.push({type:`warning`,category:`attachments`,message:`No attachments found in sampled documents`}):logger.info(`Validated ${o}/${a} sampled attachments`)}catch(e){n=!1,t.push({type:`error`,category:`attachments`,message:`Attachment validation failed: ${e instanceof Error?e.message:String(e)}`})}return n}var nodeFS,init_validation=__esm({"src/util/migrator/validation.ts"(){init_logger(),init_FileSystemAdapter(),nodeFS=null;try{typeof window>`u`&&typeof process<`u`&&process.versions?.node&&(nodeFS=eval(`require`)(`fs`),nodeFS.promises=nodeFS.promises||eval(`require`)(`fs`).promises)}catch{}}}),nodeFS2,nodePath,StaticToCouchDBMigrator,init_StaticToCouchDBMigrator=__esm({"src/util/migrator/StaticToCouchDBMigrator.ts"(){init_logger(),init_types4(),init_validation(),init_FileSystemAdapter(),nodeFS2=null,nodePath=null;try{typeof window>`u`&&typeof process<`u`&&process.versions?.node&&(nodeFS2=eval(`require`)(`fs`),nodePath=eval(`require`)(`path`),nodeFS2.promises=nodeFS2.promises||eval(`require`)(`fs`).promises)}catch{}StaticToCouchDBMigrator=class{constructor(e={},t){_defineProperty(this,`options`,void 0),_defineProperty(this,`progressCallback`,void 0),_defineProperty(this,`fs`,void 0),this.options={...DEFAULT_MIGRATION_OPTIONS,...e},this.fs=t}setProgressCallback(e){this.progressCallback=e}async migrateCourse(e,t){let n=Date.now(),r={success:!1,documentsRestored:0,attachmentsRestored:0,designDocsRestored:0,courseConfigRestored:0,errors:[],warnings:[],migrationTime:0};try{logger.info(`Starting migration from ${e} to CouchDB`),this.reportProgress(`manifest`,0,1,`Validating static course...`);let a=await validateStaticCourse(e,this.fs);if(!a.valid)throw r.errors.push(...a.errors),Error(`Static course validation failed: ${a.errors.join(`, `)}`);r.warnings.push(...a.warnings),this.reportProgress(`manifest`,1,1,`Loading course manifest...`);let o=await this.loadManifest(e);logger.info(`Loaded manifest for course: ${o.courseId} (${o.courseName})`),this.reportProgress(`design_docs`,0,o.designDocs.length,`Restoring design documents...`);let s=await this.restoreDesignDocuments(o.designDocs,t);r.designDocsRestored=s.restored,r.errors.push(...s.errors),r.warnings.push(...s.warnings),this.reportProgress(`course_config`,0,1,`Restoring CourseConfig document...`);let c=await this.restoreCourseConfig(o,t);r.courseConfigRestored=c.restored,r.errors.push(...c.errors),r.warnings.push(...c.warnings),this.reportProgress(`course_config`,1,1,`CourseConfig document restored`);let l=this.calculateExpectedCounts(o);this.reportProgress(`documents`,0,o.documentCount,`Aggregating documents from chunks...`);let u=await this.aggregateDocuments(e,o),d=u.filter(e=>e._id!==`CourseConfig`);u.length!==d.length&&r.warnings.push(`Filtered out ${u.length-d.length} CourseConfig document(s) from chunks to prevent conflicts`),this.reportProgress(`documents`,d.length,o.documentCount,`Uploading documents to CouchDB...`);let p=await this.uploadDocuments(d,t);r.documentsRestored=p.restored,r.errors.push(...p.errors),r.warnings.push(...p.warnings);let m=u.filter(e=>e._attachments&&Object.keys(e._attachments).length>0);this.reportProgress(`attachments`,0,m.length,`Uploading attachments...`);let g=await this.uploadAttachments(e,m,t);if(r.attachmentsRestored=g.restored,r.errors.push(...g.errors),r.warnings.push(...g.warnings),this.options.validateRoundTrip){this.reportProgress(`validation`,0,1,`Validating migration...`);let e=await validateMigration(t,l,o);e.valid||(r.warnings.push(`Migration validation found issues`),e.issues.forEach(e=>{e.type===`error`?r.errors.push(`Validation: ${e.message}`):r.warnings.push(`Validation: ${e.message}`)})),this.reportProgress(`validation`,1,1,`Migration validation completed`)}r.success=r.errors.length===0,r.migrationTime=Date.now()-n,logger.info(`Migration completed in ${r.migrationTime}ms`),logger.info(`Documents restored: ${r.documentsRestored}`),logger.info(`Attachments restored: ${r.attachmentsRestored}`),logger.info(`Design docs restored: ${r.designDocsRestored}`),logger.info(`CourseConfig restored: ${r.courseConfigRestored}`),r.errors.length>0&&logger.error(`Migration completed with ${r.errors.length} errors`),r.warnings.length>0&&logger.warn(`Migration completed with ${r.warnings.length} warnings`)}catch(e){r.success=!1,r.migrationTime=Date.now()-n;let a=e instanceof Error?e.message:String(e);if(r.errors.push(`Migration failed: ${a}`),logger.error(`Migration failed:`,e),this.options.cleanupOnFailure)try{await this.cleanupFailedMigration(t)}catch(e){logger.error(`Failed to cleanup after migration failure:`,e),r.warnings.push(`Failed to cleanup after migration failure`)}}return r}async loadManifest(e){try{let t,n;if(this.fs)n=this.fs.joinPath(e,`manifest.json`),t=await this.fs.readFile(n);else if(n=nodeFS2&&nodePath?nodePath.join(e,`manifest.json`):`${e}/manifest.json`,nodeFS2&&this.isLocalPath(e))t=await nodeFS2.promises.readFile(n,`utf8`);else{let e=await fetch(n);if(!e.ok)throw Error(`Failed to fetch manifest: ${e.status} ${e.statusText}`);t=await e.text()}let r=JSON.parse(t);if(!r.version||!r.courseId||!r.chunks)throw Error(`Invalid manifest structure`);return r}catch(e){let t=e instanceof FileSystemError?e.message:`Failed to load manifest: ${e instanceof Error?e.message:String(e)}`;throw Error(t)}}async restoreDesignDocuments(e,t){let n={restored:0,errors:[],warnings:[]};for(let r=0;r<e.length;r++){let a=e[r];this.reportProgress(`design_docs`,r,e.length,`Restoring ${a._id}...`);try{let e;try{e=await t.get(a._id)}catch{}let r={_id:a._id,views:a.views};e?(r._rev=e._rev,logger.debug(`Updating existing design document: ${a._id}`)):logger.debug(`Creating new design document: ${a._id}`),await t.put(r),n.restored++}catch(e){let t=`Failed to restore design document ${a._id}: ${e instanceof Error?e.message:String(e)}`;n.errors.push(t),logger.error(t)}}return this.reportProgress(`design_docs`,e.length,e.length,`Restored ${n.restored} design documents`),n}async aggregateDocuments(e,t){let n=[],r=new Map;for(let a=0;a<t.chunks.length;a++){let o=t.chunks[a];this.reportProgress(`documents`,n.length,t.documentCount,`Loading chunk ${o.id}...`);try{let t=await this.loadChunk(e,o);for(let e of t){if(!e._id){logger.warn(`Document without _id found in chunk ${o.id}, skipping`);continue}r.has(e._id)&&logger.warn(`Duplicate document ID found: ${e._id}, using latest version`),r.set(e._id,e)}}catch(e){throw Error(`Failed to load chunk ${o.id}: ${e instanceof Error?e.message:String(e)}`)}}return n.push(...r.values()),logger.info(`Aggregated ${n.length} unique documents from ${t.chunks.length} chunks`),n}async loadChunk(e,t){try{let n,r;if(this.fs)r=this.fs.joinPath(e,t.path),n=await this.fs.readFile(r);else if(r=nodeFS2&&nodePath?nodePath.join(e,t.path):`${e}/${t.path}`,nodeFS2&&this.isLocalPath(e))n=await nodeFS2.promises.readFile(r,`utf8`);else{let e=await fetch(r);if(!e.ok)throw Error(`Failed to fetch chunk: ${e.status} ${e.statusText}`);n=await e.text()}let a=JSON.parse(n);if(!Array.isArray(a))throw Error(`Chunk file does not contain an array of documents`);return a}catch(e){let t=e instanceof FileSystemError?e.message:`Failed to load chunk: ${e instanceof Error?e.message:String(e)}`;throw Error(t)}}async uploadDocuments(e,t){let n={restored:0,errors:[],warnings:[]},r=this.options.chunkBatchSize;for(let a=0;a<e.length;a+=r){let o=e.slice(a,a+r);this.reportProgress(`documents`,a,e.length,`Uploading batch ${Math.floor(a/r)+1}...`);try{let e=o.map(e=>{let t={...e};return delete t._rev,delete t._attachments,t}),r=await t.bulkDocs(e);for(let e=0;e<r.length;e++){let t=r[e],a=o[e];if(`error`in t){let e=`Failed to upload document ${a._id}: ${t.error} - ${t.reason}`;n.errors.push(e),logger.error(e)}else n.restored++}}catch(e){let t;t=e instanceof Error||e&&typeof e==`object`&&`message`in e?`Failed to upload document batch starting at index ${a}: ${e.message}`:`Failed to upload document batch starting at index ${a}: ${JSON.stringify(e)}`,n.errors.push(t),logger.error(t)}}return this.reportProgress(`documents`,e.length,e.length,`Uploaded ${n.restored} documents`),n}async uploadAttachments(e,t,n){let r={restored:0,errors:[],warnings:[]},a=0;for(let o of t)if(this.reportProgress(`attachments`,a,t.length,`Processing attachments for ${o._id}...`),a++,o._attachments)for(let[t,a]of Object.entries(o._attachments))try{let s=await this.uploadSingleAttachment(e,o._id,t,a,n);s.success?r.restored++:r.errors.push(s.error||`Unknown attachment upload error`)}catch(e){let n=`Failed to upload attachment ${o._id}/${t}: ${e instanceof Error?e.message:String(e)}`;r.errors.push(n),logger.error(n)}return this.reportProgress(`attachments`,t.length,t.length,`Uploaded ${r.restored} attachments`),r}async uploadSingleAttachment(e,t,n,r,a){let o={success:!1,attachmentName:n,docId:t};try{if(!r.path)return o.error=`Attachment metadata missing file path`,o;let s,c;if(this.fs)c=this.fs.joinPath(e,r.path),s=await this.fs.readBinary(c);else if(c=nodeFS2&&nodePath?nodePath.join(e,r.path):`${e}/${r.path}`,nodeFS2&&this.isLocalPath(e))s=await nodeFS2.promises.readFile(c);else{let e=await fetch(c);if(!e.ok)return o.error=`Failed to fetch attachment: ${e.status} ${e.statusText}`,o;s=await e.arrayBuffer()}let l=await a.get(t);await a.putAttachment(t,n,l._rev,s,r.content_type),o.success=!0}catch(e){o.error=e instanceof Error?e.message:String(e)}return o}async restoreCourseConfig(e,t){let n={restored:0,errors:[],warnings:[]};try{if(!e.courseConfig)return n.warnings.push(`No courseConfig found in manifest, skipping CourseConfig document creation`),n;let r={_id:`CourseConfig`,...e.courseConfig,courseID:e.courseId};delete r._rev,await t.put(r),n.restored=1,logger.info(`CourseConfig document created for course: ${e.courseId}`)}catch(e){let t=e instanceof Error?e.message:JSON.stringify(e);n.errors.push(`Failed to restore CourseConfig: ${t}`),logger.error(`CourseConfig restoration failed:`,e)}return n}calculateExpectedCounts(e){let t={};for(let n of e.chunks)t[n.docType]=(t[n.docType]||0)+n.documentCount;return e.designDocs.length>0&&(t._design=e.designDocs.length),t}async cleanupFailedMigration(e){logger.info(`Cleaning up failed migration...`);try{let t=(await e.allDocs()).rows.map(e=>({_id:e.id,_rev:e.value.rev,_deleted:!0}));t.length>0&&(await e.bulkDocs(t),logger.info(`Cleaned up ${t.length} documents from failed migration`))}catch(e){throw logger.error(`Failed to cleanup documents:`,e),e}}reportProgress(e,t,n,r){this.progressCallback&&this.progressCallback({phase:e,current:t,total:n,message:r})}isLocalPath(e){return!e.startsWith(`http://`)&&!e.startsWith(`https://`)}}}}),init_migrator=__esm({"src/util/migrator/index.ts"(){init_StaticToCouchDBMigrator(),init_validation(),init_FileSystemAdapter()}});function getAppDataDirectory(){return ENV.LOCAL_STORAGE_PREFIX?import___vite_browser_external.join(import___vite_browser_external.homedir(),`.tuilder`,ENV.LOCAL_STORAGE_PREFIX):import___vite_browser_external.join(import___vite_browser_external.homedir(),`.tuilder`)}async function ensureAppDataDirectory(){let e=getAppDataDirectory();try{await import___vite_browser_external.promises.mkdir(e,{recursive:!0})}catch(t){if(t.code!==`EEXIST`)throw Error(`Failed to create app data directory ${e}: ${t.message}`)}return e}function getDbPath(e){return import___vite_browser_external.join(getAppDataDirectory(),e)}async function initializeDataDirectory(){await ensureAppDataDirectory(),logger.info(`PouchDB data directory initialized: ${getAppDataDirectory()}`)}var init_dataDirectory=__esm({"src/util/dataDirectory.ts"(){init_logger(),init_factory()}}),init_util2=__esm({"src/util/index.ts"(){init_Loggable(),init_packer(),init_migrator(),init_dataDirectory()}}),QuotaRoundRobinMixer,init_SourceMixer=__esm({"src/study/SourceMixer.ts"(){QuotaRoundRobinMixer=class{mix(e,t){if(e.length===0)return[];let n=Math.ceil(t/e.length),r=e.map(e=>[...e.weighted].sort((e,t)=>t.score-e.score).slice(0,n));for(let e=r.length-1;e>0;e--){let t=Math.floor(Math.random()*(e+1));[r[e],r[t]]=[r[t],r[e]]}let a=[],o=0,s=Array(r.length).fill(0);for(;a.length<t&&o<r.length;){o=0;for(let e=0;e<r.length&&!(a.length>=t);e++)s[e]<r[e].length?(a.push(r[e][s[e]]),s[e]++):o++}return a}}}});function buildSourceSummary(e,t,n){let r=e.weighted.map(e=>e.score),a=e.weighted.filter(e=>getCardOrigin(e)===`review`).length,o=e.weighted.filter(e=>getCardOrigin(e)===`new`).length;return{sourceIndex:e.sourceIndex,sourceId:t,sourceName:n,totalCards:e.weighted.length,reviewCount:a,newCount:o,topScore:r.length>0?Math.max(...r):0,bottomScore:r.length>0?Math.min(...r):0,scoreRange:r.length>0?[Math.min(...r),Math.max(...r)]:[0,0],avgScore:r.length>0?r.reduce((e,t)=>e+t,0)/r.length:0}}function buildSourceBreakdown(e,t,n){let r=n.filter(t=>t.courseId===e),a=r.filter(e=>e.selected);return{sourceId:e,sourceName:t,reviewsProvided:r.filter(e=>e.origin===`review`).length,newProvided:r.filter(e=>e.origin===`new`).length,reviewsSelected:a.filter(e=>e.origin===`review`).length,newSelected:a.filter(e=>e.origin===`new`).length,totalSelected:a.length,selectionRate:r.length>0?a.length/r.length*100:0}}function captureMixerRun(e,t,n,r,a,o,s){let c=t.map((e,t)=>buildSourceSummary(e,n[t]||`source-${t}`,r[t])),l=new Set(s.map(e=>e.cardId)),u=new Map;t.forEach(e=>{let t=[...e.weighted].sort((e,t)=>t.score-e.score),r=new Map;t.forEach((e,t)=>{r.set(e.cardId,t+1)}),u.set(n[e.sourceIndex]||`source-${e.sourceIndex}`,r)});let d=new Map;s.forEach((e,t)=>{d.set(e.cardId,t+1)});let p=new Map;t.forEach(e=>{e.weighted.forEach(e=>{p.set(e.cardId,e)})});let m=Array.from(p.values()).map(e=>({cardId:e.cardId,courseId:e.courseId,origin:getCardOrigin(e),score:e.score,sourceIndex:t.findIndex(t=>t.weighted.some(t=>t.cardId===e.cardId)),selected:l.has(e.cardId),rankInSource:u.get(e.courseId)?.get(e.cardId),rankInMix:d.get(e.cardId)})),g=Array.from(new Set(n.filter(e=>e))).map((e,t)=>buildSourceBreakdown(e,r[t],m)),_={runId:`mix-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,timestamp:new Date,mixerType:e,requestedLimit:a,quotaPerSource:o,sourceSummaries:c,cards:m,finalCount:s.length,reviewsSelected:s.filter(e=>getCardOrigin(e)===`review`).length,newSelected:s.filter(e=>getCardOrigin(e)===`new`).length,sourceBreakdowns:g};runHistory2.unshift(_),runHistory2.length>MAX_RUNS2&&runHistory2.pop()}function printMixerSummary(e){console.group(`\u{1F3A8} Mixer Run: ${e.mixerType}`),logger.info(`Run ID: ${e.runId}`),logger.info(`Time: ${e.timestamp.toISOString()}`),logger.info(`Config: limit=${e.requestedLimit}${e.quotaPerSource?`, quota/source=${e.quotaPerSource}`:``}`),console.group(`\u{1F4E5} Input: ${e.sourceSummaries.length} sources`);for(let t of e.sourceSummaries)logger.info(` ${t.sourceName||t.sourceId}: ${t.totalCards} cards (${t.reviewCount} reviews, ${t.newCount} new)`),logger.info(` Score range: [${t.scoreRange[0].toFixed(2)}, ${t.scoreRange[1].toFixed(2)}], avg: ${t.avgScore.toFixed(2)}`);console.groupEnd(),console.group(`\u{1F4E4} Output: ${e.finalCount} cards selected (${e.reviewsSelected} reviews, ${e.newSelected} new)`);for(let t of e.sourceBreakdowns){let e=t.sourceName||t.sourceId;logger.info(` ${e}: ${t.totalSelected} selected (${t.reviewsSelected} reviews, ${t.newSelected} new) - ${t.selectionRate.toFixed(1)}% selection rate`)}console.groupEnd(),console.groupEnd()}function mountMixerDebugger(){if(typeof window>`u`)return;let e=window;e.skuilder=e.skuilder||{},e.skuilder.mixer=mixerDebugAPI}var MAX_RUNS2,runHistory2,mixerDebugAPI,init_MixerDebugger=__esm({"src/study/MixerDebugger.ts"(){init_logger(),init_navigators(),MAX_RUNS2=10,runHistory2=[],mixerDebugAPI={get runs(){return[...runHistory2]},showRun(e=0){if(runHistory2.length===0){logger.info(`[Mixer Debug] No runs captured yet.`);return}let t;if(typeof e==`number`){if(t=runHistory2[e],!t){logger.info(`[Mixer Debug] No run found at index ${e}. History length: ${runHistory2.length}`);return}}else if(t=runHistory2.find(t=>t.runId.endsWith(e)),!t){logger.info(`[Mixer Debug] No run found matching ID '${e}'.`);return}printMixerSummary(t)},showLastMix(){this.showRun(0)},explainSourceBalance(){if(runHistory2.length===0){logger.info(`[Mixer Debug] No runs captured yet.`);return}let e=runHistory2[0];console.group(`⚖️ Source Balance Analysis`),logger.info(`Mixer: ${e.mixerType}`),logger.info(`Requested limit: ${e.requestedLimit}`),e.quotaPerSource&&logger.info(`Quota per source: ${e.quotaPerSource}`),console.group(`Input Distribution:`);for(let t of e.sourceSummaries){let e=t.sourceName||t.sourceId;logger.info(`${e}:`),logger.info(` Provided: ${t.totalCards} cards (${t.reviewCount} reviews, ${t.newCount} new)`),logger.info(` Score range: [${t.scoreRange[0].toFixed(2)}, ${t.scoreRange[1].toFixed(2)}]`)}console.groupEnd(),console.group(`Selection Results:`);for(let t of e.sourceBreakdowns){let e=t.sourceName||t.sourceId;logger.info(`${e}:`),logger.info(` Selected: ${t.totalSelected}/${t.reviewsProvided+t.newProvided} (${t.selectionRate.toFixed(1)}%)`),logger.info(` Reviews: ${t.reviewsSelected}/${t.reviewsProvided}`),logger.info(` New: ${t.newSelected}/${t.newProvided}`),t.reviewsProvided>0&&t.reviewsSelected===0&&logger.info(` ⚠️ Had reviews but none selected!`),t.totalSelected===0&&t.reviewsProvided+t.newProvided>0&&logger.info(` ⚠️ Had cards but none selected!`)}console.groupEnd();let t=e.sourceBreakdowns.map(e=>e.selectionRate),n=t.reduce((e,t)=>e+t,0)/t.length,r=Math.max(...t.map(e=>Math.abs(e-n)));r>20&&(logger.info(`
|
|
322
284
|
\u26A0\uFE0F Significant imbalance detected (max deviation: ${r.toFixed(1)}%)`),logger.info(`Possible causes:`),logger.info(` - Score range differences between sources`),logger.info(` - One source has much better quality cards`),logger.info(` - Different card availability (reviews vs new)`)),console.groupEnd()},compareScores(){if(runHistory2.length===0){logger.info(`[Mixer Debug] No runs captured yet.`);return}let e=runHistory2[0];console.group(`📊 Score Distribution Comparison`),console.table(e.sourceSummaries.map(e=>({source:e.sourceName||e.sourceId,cards:e.totalCards,min:e.bottomScore.toFixed(3),max:e.topScore.toFixed(3),avg:e.avgScore.toFixed(3),range:(e.topScore-e.bottomScore).toFixed(3)})));let t=e.sourceSummaries.map(e=>e.topScore-e.bottomScore),n=e.sourceSummaries.map(e=>e.avgScore),r=Math.max(...t)-Math.min(...t),a=Math.max(...n)-Math.min(...n);(r>.3||a>.2)&&(logger.info(`
|
|
323
285
|
⚠️ Significant score distribution differences detected`),logger.info(`This may cause one source to dominate selection if using global sorting (not quota-based)`)),console.groupEnd()},showCard(e){for(let t of runHistory2){let n=t.cards.find(t=>t.cardId===e);if(n){let r=t.sourceSummaries.find(e=>e.sourceIndex===n.sourceIndex);console.group(`\u{1F3B4} Card: ${e}`),logger.info(`Course: ${n.courseId}`),logger.info(`Source: ${r?.sourceName||r?.sourceId||`unknown`}`),logger.info(`Origin: ${n.origin}`),logger.info(`Score: ${n.score.toFixed(3)}`),n.rankInSource&&logger.info(`Rank in source: #${n.rankInSource}`),n.rankInMix&&logger.info(`Rank in mixed results: #${n.rankInMix}`),logger.info(`Selected: ${n.selected?`Yes ✅`:`No ❌`}`),!n.selected&&n.rankInSource&&(logger.info(`
|
|
324
286
|
Why not selected:`),t.quotaPerSource&&n.rankInSource>t.quotaPerSource&&logger.info(` - Ranked #${n.rankInSource} in source, but quota was ${t.quotaPerSource}`),logger.info(` - Check score compared to selected cards using .showRun()`)),console.groupEnd();return}}logger.info(`[Mixer Debug] Card '${e}' not found in recent runs.`)},listRuns(){if(runHistory2.length===0){logger.info(`[Mixer Debug] No runs captured yet.`);return}console.table(runHistory2.map(e=>({id:e.runId.slice(-8),time:e.timestamp.toLocaleTimeString(),mixer:e.mixerType,sources:e.sourceSummaries.length,selected:e.finalCount,reviews:e.reviewsSelected,new:e.newSelected})))},export(){let e=JSON.stringify(runHistory2,null,2);return logger.info(`[Mixer Debug] Run history exported. Copy the returned string or use:`),logger.info(` copy(window.skuilder.mixer.export())`),e},clear(){runHistory2.length=0,logger.info(`[Mixer Debug] Run history cleared.`)},help(){logger.info(`
|
|
@@ -340,13 +302,13 @@ Example:
|
|
|
340
302
|
window.skuilder.mixer.showLastMix()
|
|
341
303
|
window.skuilder.mixer.explainSourceBalance()
|
|
342
304
|
window.skuilder.mixer.compareScores()
|
|
343
|
-
`)}}
|
|
305
|
+
`)}},mountMixerDebugger()}});function registerActiveController(e){activeController=e}function getActiveController(){return activeController}function toggleSessionOverlay(){if(typeof document>`u`){logger.info(`[Session Overlay] No DOM available (non-browser host); overlay unavailable.`);return}overlayEl?(teardown(),logger.info(`[Session Overlay] Hidden.`)):(mount(),logger.info(`[Session Overlay] Shown. Toggle off with window.skuilder.session.dbgOverlay().`))}function mount(){minified=!1,overlayEl=document.createElement(`div`),overlayEl.id=OVERLAY_ID,Object.assign(overlayEl.style,{position:`fixed`,top:`8px`,left:`8px`,zIndex:`2147483647`,maxWidth:`320px`,maxHeight:`90vh`,overflowY:`auto`,padding:`8px 10px`,background:`rgba(17, 24, 39, 0.92)`,color:`#e5e7eb`,font:`11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace`,borderRadius:`6px`,boxShadow:`0 4px 16px rgba(0,0,0,0.4)`,pointerEvents:`auto`,userSelect:`none`}),document.body.appendChild(overlayEl),render(),pollHandle=setInterval(render,POLL_MS)}function teardown(){pollHandle!==null&&(clearInterval(pollHandle),pollHandle=null),overlayEl?.parentNode&&overlayEl.parentNode.removeChild(overlayEl),overlayEl=null}function render(){if(!overlayEl)return;spinnerFrame++;let e=getActiveController();if(!e){lastSnapshot=null,overlayEl.innerHTML=headerHtml()+(minified?``:`<div style="opacity:.65">No active session.</div>`),attachHandlers();return}let t=e.getDebugSnapshot();if(lastSnapshot=t,minified){overlayEl.innerHTML=headerHtml(),attachHandlers();return}overlayEl.innerHTML=headerHtml()+replanHtml(t)+metaHtml(t)+hintsHtml(t.sessionHints)+backlogHtml(t.reviewBacklog)+strategyPressureHtml(t.strategyPressure)+queueHtml(`supplyQ`,`supplyQ`,t.supplyQ)+queueHtml(`failedQ`,`failedQ`,t.failedQ)+drawnHtml(`drawn`,t.drawnCards),attachHandlers()}function attachHandlers(){if(!overlayEl)return;overlayEl.querySelectorAll(`[data-q]`).forEach(e=>{e.onclick=()=>{let t=e.dataset.q;t&&(expanded[t]=!expanded[t],render())}});let e=overlayEl.querySelector(`[data-copy]`);e&&(e.onclick=e=>{e.stopPropagation(),copySnapshot()});let t=overlayEl.querySelector(`[data-min]`);t&&(t.onclick=e=>{e.stopPropagation(),minified=!minified,render()})}function copySnapshot(){let e=snapshotToText(lastSnapshot),flash=()=>{copyFlashUntil=Date.now()+1200,render()},t=typeof navigator<`u`?navigator.clipboard:void 0;t?.writeText?t.writeText(e).then(flash,e=>{logger.warn(`[Session Overlay] Clipboard write failed: ${String(e)}`)}):logger.info(`[Session Overlay] Clipboard unavailable; snapshot follows:
|
|
344
306
|
${e}`)}function headerHtml(){let e=Date.now()<copyFlashUntil;return`<div style="font-weight:600;color:#93c5fd;margin-bottom:${minified?0:4}px">${`<span data-copy style="cursor:pointer;float:right;font-weight:400;color:${e?`#86efac`:`#93c5fd`};border:1px solid currentColor;border-radius:4px;padding:0 4px;line-height:1.3">${e?`✓ copied`:`⎘ copy`}</span>`}${`<span data-min title="${minified?`Restore`:`Minify`}" style="cursor:pointer;float:right;font-weight:400;color:#93c5fd;border:1px solid currentColor;border-radius:4px;padding:0 5px;margin-right:4px;line-height:1.3">${minified?`▢`:`—`}</span>`}\u2699 SessionController</div>`}function replanHtml(e){return e.replanActive?`<div style="margin-bottom:6px;color:#fde047">${SPINNER_FRAMES[spinnerFrame%SPINNER_FRAMES.length]} replanning <span style="opacity:.85">[${esc(e.replanLabel??`(auto)`)}]</span></div>`:`<div style="margin-bottom:6px;opacity:.45">○ idle</div>`}function metaHtml(e){return`<div style="margin-bottom:6px">${[`time ${formatTime(e.secondsRemaining)}${e.hasCardGuarantee?` \xB7 <span style="color:#fbbf24">guarantee ${e.minCardsGuarantee}</span>`:``}`,`well-indicated left: ${e.wellIndicatedRemaining}`,`current: ${e.currentCard?esc(e.currentCard):`<span style="opacity:.6">—</span>`}`].map(e=>`<div>${e}</div>`).join(``)}</div>`}function hintsHtml(e){let t=[];return e&&(e.boostTags&&Object.keys(e.boostTags).length&&t.push(`boost: `+Object.entries(e.boostTags).map(([e,t])=>`${esc(e)}<span style="opacity:.6">\xD7${t}</span>`).join(`, `)),e.boostCards&&Object.keys(e.boostCards).length&&t.push(`boostCards: `+Object.entries(e.boostCards).map(([e,t])=>`${esc(e)}<span style="opacity:.6">\xD7${t}</span>`).join(`, `)),e.requireCards?.length&&t.push(`require: ${e.requireCards.map(esc).join(`, `)}`),e.requireTags?.length&&t.push(`requireTags: ${e.requireTags.map(esc).join(`, `)}`),e.excludeTags?.length&&t.push(`exclude: ${e.excludeTags.map(esc).join(`, `)}`),e.excludeCards?.length&&t.push(`excludeCards: ${e.excludeCards.map(esc).join(`, `)}`)),`<div style="margin-bottom:6px"><div style="color:#86efac">sessionHints</div>${t.length?t.map(e=>`<div style="margin-left:6px">${e}</div>`).join(``):`<div style="margin-left:6px;opacity:.6">none</div>`}</div>`}function backlogHtml(e){return e.length?`<div style="margin-bottom:6px"><div style="color:#93c5fd">review backpressure</div>${e.map(e=>{let t=e.backlogMultiplier>=3,n=e.backlogMultiplier<=1?`#86efac`:t?`#fca5a5`:`#fcd34d`,r=e.backlogMultiplier>1?`climbing (\xD7${e.backlogGrowthRate.toFixed(2)} per ${e.healthyBacklog}-review excess, unbounded)`:`healthy — no pressure`,a=e.topReviewScore===null?`—`:e.topReviewScore.toFixed(2),o=e.nextDueIn?` <span style="opacity:.6">\xB7 next due ${esc(e.nextDueIn)}</span>`:``;return`<div style="margin-left:6px"><span style="opacity:.7">${esc(e.courseId.slice(0,8))}</span> due ${e.dueNow}/${e.scheduledTotal} <span style="opacity:.6">(healthy ${e.healthyBacklog})</span>${o}<div style="margin-left:6px">pressure <span style="color:${n}">\xD7${e.backlogMultiplier.toFixed(2)}</span> <span style="opacity:.6">${r} \xB7 top review ${a}</span></div></div>`}).join(``)}</div>`:``}function pressureColor(e,t){return e<=1.001?`#86efac`:t!==void 0&&t>1?(e-1)/(t-1)>=.75?`#fca5a5`:`#fcd34d`:e>=3?`#fca5a5`:`#fcd34d`}function toggleKey(e){return e.replace(/[^\w:.|-]/g,`_`)}function gaugeHtml(e,t){let n=t.max===void 0?``:`<span style="opacity:.5">/${t.max}</span>`,r=t.detail?` <span style="opacity:.6">${esc(t.detail)}</span>`:``,a=`<div style="margin-left:6px">${esc(t.label)} <span style="color:${pressureColor(t.multiplier,t.max)}">\xD7${t.multiplier.toFixed(2)}</span>${n}${r}`,o=t.items??[];if(o.length>0){let n=toggleKey(`sp|${e}|${t.id}`),r=!!expanded[n],s=r?o:o.slice(0,INLINE_THRESHOLD);if(a+=`<div style="margin-left:6px">`+s.map(e=>`<div style="white-space:nowrap;opacity:.75">${esc(e.label)}${e.value?` <span style="opacity:.6">${esc(e.value)}</span>`:``}</div>`).join(``),o.length>INLINE_THRESHOLD){let e=r?`▾ show less`:`\u2026 +${o.length-s.length} more`;a+=`<div data-q="${n}" style="cursor:pointer;opacity:.6">${e}</div>`}a+=`</div>`}return a+`</div>`}function strategyPressureHtml(e){return e.length?`<div style="margin-bottom:6px"><div style="color:#fdba74">strategy backpressure</div>${e.map(e=>{let t=`${e.source}:${e.courseId.slice(0,8)}`,n=e.topScore!==null&&e.topScore!==void 0?e.topScore.toFixed(2):`—`,r=e.hintsLabel?`<div style="margin-left:6px;opacity:.6">hints: ${esc(e.hintsLabel)}</div>`:``;return`<div style="margin-left:6px"><span style="opacity:.7">${esc(e.source)} \xB7 ${esc(e.courseId.slice(0,8))}</span> <span style="opacity:.6">top score ${n}</span>`+e.gauges.map(e=>gaugeHtml(t,e)).join(``)+r+`</div>`}).join(``)}</div>`:``}function fmtScore(e){return e===void 0?``:Number.isFinite(e)?e.toFixed(2):`REQ`}function queueItemHtml(e){let t=e.origin===`review`?`#93c5fd`:`#fcd34d`,n=fmtScore(e.score),r=`${e.origin===`review`?`r`:`n`}${n?` `+n:``}`;return`${esc(e.cardID)}<span style="color:${t};opacity:.85"> [${r}]</span>`}function queueHtml(e,t,n){let r=n.length>INLINE_THRESHOLD,a=r&&expanded[e],o=r?expanded[e]?`▾ `:`▸ `:``,s=n.dequeueCount?` <span style="opacity:.5">drawn ${n.dequeueCount}</span>`:``,c=r?`cursor:pointer;color:#f9a8d4`:`color:#f9a8d4`,l=`<div${r?` data-q="${e}"`:``} style="${c}">${o}${t}: ${n.length}${s}</div>`;if(!n.cards.length)return l+`<div style="margin:1px 0 6px 6px;opacity:.5">empty</div>`;let u=a?n.cards:n.cards.slice(0,INLINE_THRESHOLD),d=n.length-u.length,p=`<ol style="margin:2px 0 ${r?2:6}px 0;padding-left:20px">`+u.map(e=>`<li style="white-space:nowrap">${queueItemHtml(e)}</li>`).join(``)+`</ol>`;if(r){let t=a?`▾ show less`:`\u2026 +${d} more`;p+=`<div data-q="${e}" style="cursor:pointer;margin:0 0 6px 20px;opacity:.6">${t}</div>`}return l+p}function outcomeGlyph(e){return e===!0?`<span style="color:#86efac">✓</span>`:e===!1?`<span style="color:#fca5a5">✗</span>`:`<span style="opacity:.5">·</span>`}function drawnHtml(e,t){let n=t.length>INLINE_THRESHOLD,r=n&&expanded[e],a=n?expanded[e]?`▾ `:`▸ `:``,o=n?`cursor:pointer;color:#c4b5fd`:`color:#c4b5fd`,s=`<div${n?` data-q="${e}"`:``} style="${o}">${a}drawn: ${t.length}</div>`;if(!t.length)return s+`<div style="margin:1px 0 6px 6px;opacity:.5">none yet</div>`;let c=r?t:t.slice(0,INLINE_THRESHOLD),l=t.length-c.length,u=`<ol style="margin:2px 0 ${n?2:6}px 0;padding-left:20px">${c.map(e=>{let t=e.attempts>1?`<span style="opacity:.5"> \xD7${e.attempts}</span>`:``,n=`<span style="opacity:.45"> ${Math.round(e.timeSpentMs/100)/10}s</span>`;return`<li style="white-space:nowrap">${outcomeGlyph(e.correct)} ${esc(e.cardID)}<span style="opacity:.5"> [${esc(e.status)}]</span>${t}${n}</li>`}).join(``)}</ol>`;if(n){let t=r?`▾ show less`:`\u2026 +${l} more`;u+=`<div data-q="${e}" style="cursor:pointer;margin:0 0 6px 20px;opacity:.6">${t}</div>`}return s+u}function snapshotToText(e){if(!e)return`SessionController — no active session.`;let t=[];t.push(`=== SessionController ===`),t.push(`time ${formatTime(e.secondsRemaining)}`),e.hasCardGuarantee&&t.push(`guarantee: ${e.minCardsGuarantee}`),t.push(`well-indicated left: ${e.wellIndicatedRemaining}`),t.push(`current: ${e.currentCard??`—`}`),t.push(e.replanActive?`replan: ACTIVE [${e.replanLabel??`(auto)`}]`:`replan: idle`),t.push(``),t.push(`sessionHints:`);let n=e.sessionHints,r=[];if(n&&(n.boostTags&&Object.keys(n.boostTags).length&&r.push(` boost: ${Object.entries(n.boostTags).map(([e,t])=>`${e}\xD7${t}`).join(`, `)}`),n.boostCards&&Object.keys(n.boostCards).length&&r.push(` boostCards: ${Object.entries(n.boostCards).map(([e,t])=>`${e}\xD7${t}`).join(`, `)}`),n.requireCards?.length&&r.push(` require: ${n.requireCards.join(`, `)}`),n.requireTags?.length&&r.push(` requireTags: ${n.requireTags.join(`, `)}`),n.excludeTags?.length&&r.push(` exclude: ${n.excludeTags.join(`, `)}`),n.excludeCards?.length&&r.push(` excludeCards: ${n.excludeCards.join(`, `)}`)),t.push(r.length?r.join(`
|
|
345
307
|
`):` none`),e.reviewBacklog.length){t.push(``),t.push(`review backpressure:`);for(let n of e.reviewBacklog){let e=n.backlogMultiplier>1?`climbing`:`healthy`,r=n.topReviewScore===null?`—`:n.topReviewScore.toFixed(2),a=n.nextDueIn?`, next due ${n.nextDueIn}`:``;t.push(` ${n.courseId.slice(0,8)}: due ${n.dueNow}/${n.scheduledTotal} (healthy ${n.healthyBacklog})${a}; pressure \xD7${n.backlogMultiplier.toFixed(2)} ${e}; top review ${r}`)}}if(e.strategyPressure.length){t.push(``),t.push(`strategy backpressure:`);for(let n of e.strategyPressure){let e=n.topScore!==null&&n.topScore!==void 0?n.topScore.toFixed(2):`—`;t.push(` ${n.source} (${n.courseId.slice(0,8)}): top score ${e}`);for(let e of n.gauges){let n=e.max===void 0?``:`/${e.max}`;t.push(` ${e.label} \xD7${e.multiplier.toFixed(2)}${n}${e.detail?` \u2014 ${e.detail}`:``}`);for(let n of e.items??[])t.push(` ${n.label}${n.value?` (${n.value})`:``}`)}n.hintsLabel&&t.push(` hints: ${n.hintsLabel}`)}}let queueText=(e,n)=>{t.push(``),t.push(`${e}: ${n.length} (drawn ${n.dequeueCount})`),n.cards.forEach((e,n)=>{let r=fmtScore(e.score),a=`${e.origin===`review`?`r`:`n`}${r?` `+r:``}`;t.push(` ${n+1}. ${e.cardID} [${a}]`)})};return queueText(`supplyQ`,e.supplyQ),queueText(`failedQ`,e.failedQ),t.push(``),t.push(`drawn: ${e.drawnCards.length}`),e.drawnCards.forEach((e,n)=>{let r=e.correct===!0?`✓`:e.correct===!1?`✗`:`·`,a=`${Math.round(e.timeSpentMs/100)/10}s`;t.push(` ${n+1}. ${r} ${e.cardID} [${e.status}] \xD7${e.attempts} ${a}`)}),t.join(`
|
|
346
|
-
`)}function formatTime(e){let t=Math.max(0,Math.round(e));return`${Math.floor(t/60)}:${(t%60).toString().padStart(2,`0`)}`}function esc(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`)}var
|
|
308
|
+
`)}function formatTime(e){let t=Math.max(0,Math.round(e));return`${Math.floor(t/60)}:${(t%60).toString().padStart(2,`0`)}`}function esc(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`)}var activeController,OVERLAY_ID,POLL_MS,INLINE_THRESHOLD,SPINNER_FRAMES,spinnerFrame,overlayEl,pollHandle,lastSnapshot,copyFlashUntil,minified,expanded,init_SessionOverlay=__esm({"src/study/SessionOverlay.ts"(){init_logger(),activeController=null,OVERLAY_ID=`skuilder-session-overlay`,POLL_MS=300,INLINE_THRESHOLD=5,SPINNER_FRAMES=[`⠋`,`⠙`,`⠹`,`⠸`,`⠼`,`⠴`,`⠦`,`⠧`,`⠇`,`⠏`],spinnerFrame=0,overlayEl=null,pollHandle=null,lastSnapshot=null,copyFlashUntil=0,minified=!1,expanded={supplyQ:!1,failedQ:!1,drawn:!1}}});function clearStaleSessionDebugState(){clearRunHistory(),clearSrsBacklogDebug(),clearStrategyPressureDebug()}function startSessionTracking(e,t,n){activeSession={sessionId:e,startTime:new Date,initialQueues:{timestamp:new Date,supplyQLength:t,failedQLength:n},presentations:[],queueSnapshots:[]},logger.debug(`[SessionDebugger] Started tracking session: ${e}`)}function recordCardPresentation(e,t,n,r,a,o){if(!activeSession){logger.warn(`[SessionDebugger] No active session to record presentation`);return}activeSession.presentations.push({timestamp:new Date,sequenceNumber:activeSession.presentations.length+1,cardId:e,courseId:t,courseName:n,origin:r,queueSource:a,score:o})}function snapshotQueues(e,t,n){activeSession&&activeSession.queueSnapshots.push({timestamp:new Date,supplyQLength:e,failedQLength:t,supplyQNext3:n})}function endSessionTracking(){activeSession&&(activeSession.endTime=new Date,sessionHistory.unshift(activeSession),sessionHistory.length>MAX_HISTORY&&sessionHistory.pop(),logger.debug(`[SessionDebugger] Ended session: ${activeSession.sessionId}`),activeSession=null)}function showCurrentQueue(){if(!activeSession){logger.info(`[Session Debug] No active session.`);return}let e=activeSession.queueSnapshots[activeSession.queueSnapshots.length-1]||activeSession.initialQueues;console.group(`📊 Current Queue State`),logger.info(`Supply Queue: ${e.supplyQLength} cards`),e.supplyQNext3&&e.supplyQNext3.length>0&&logger.info(` Next: ${e.supplyQNext3.join(`, `)}`),logger.info(`Failed Queue: ${e.failedQLength} cards`),console.groupEnd()}function showPresentationHistory(e=0){let t=e===0&&activeSession?activeSession:sessionHistory[e];if(!t){logger.info(`[Session Debug] No session found at index ${e}`);return}console.group(`\u{1F4DC} Session History: ${t.sessionId}`),logger.info(`Started: ${t.startTime.toLocaleTimeString()}`),t.endTime&&logger.info(`Ended: ${t.endTime.toLocaleTimeString()}`),logger.info(`Cards presented: ${t.presentations.length}`),t.presentations.length>0&&console.table(t.presentations.map(e=>({"#":e.sequenceNumber,course:e.courseName||e.courseId.slice(0,8),origin:e.origin,queue:e.queueSource,score:e.score?.toFixed(3)||`-`,time:e.timestamp.toLocaleTimeString()}))),console.groupEnd()}function showInterleaving(e=0){let t=e===0&&activeSession?activeSession:sessionHistory[e];if(!t){logger.info(`[Session Debug] No session found at index ${e}`);return}console.group(`🔀 Interleaving Analysis`);let n=new Map,r=new Map;if(t.presentations.forEach(e=>{let t=e.courseName||e.courseId;n.set(t,(n.get(t)||0)+1),r.has(t)||r.set(t,{review:0,new:0,failed:0});let a=r.get(t);a[e.origin]++}),logger.info(`Course distribution:`),console.table(Array.from(n.entries()).map(([e,n])=>{let a=r.get(e);return{course:e,total:n,reviews:a.review,new:a.new,failed:a.failed,percentage:(n/t.presentations.length*100).toFixed(1)+`%`}})),t.presentations.length>0){logger.info(`
|
|
347
309
|
Presentation sequence (first 20):`);let e=t.presentations.slice(0,20).map((e,t)=>`${t+1}. ${e.courseName||e.courseId.slice(0,8)} (${e.origin})`).join(`
|
|
348
310
|
`);logger.info(e)}let a=0,o=1,s=t.presentations[0]?.courseId;for(let e=1;e<t.presentations.length;e++)t.presentations[e].courseId===s?(o++,a=Math.max(a,o)):(s=t.presentations[e].courseId,o=1);a>3&&(logger.info(`
|
|
349
|
-
\u26A0\uFE0F Detected clustering: max ${a} cards from same course in a row`),logger.info(`This suggests cards are sorted by score rather than round-robin by course.`)),console.groupEnd()}var sessionDebugAPI={get sessions(){return[...sessionHistory]},get active(){return activeSession},showQueue(){showCurrentQueue()},dbgOverlay(){toggleSessionOverlay()},showHistory(e=0){showPresentationHistory(e)},showInterleaving(e=0){showInterleaving(e)},listSessions(){if(activeSession&&logger.info(`Active session: ${activeSession.sessionId} (${activeSession.presentations.length} cards presented)`),sessionHistory.length===0){logger.info(`[Session Debug] No completed sessions in history.`);return}console.table(sessionHistory.map((e,t)=>({index:t,id:e.sessionId.slice(-8),started:e.startTime.toLocaleTimeString(),ended:e.endTime?.toLocaleTimeString()||`incomplete`,cards:e.presentations.length})))},export(){let e={active:activeSession,history:sessionHistory},t=JSON.stringify(e,null,2);return logger.info(`[Session Debug] Session data exported. Copy the returned string or use:`),logger.info(` copy(window.skuilder.session.export())`),t},clear(){sessionHistory.length=0,logger.info(`[Session Debug] Session history cleared.`)},help(){logger.info(`
|
|
311
|
+
\u26A0\uFE0F Detected clustering: max ${a} cards from same course in a row`),logger.info(`This suggests cards are sorted by score rather than round-robin by course.`)),console.groupEnd()}function mountSessionDebugger(){if(typeof window>`u`)return;let e=window;e.skuilder=e.skuilder||{},e.skuilder.session=sessionDebugAPI}var activeSession,sessionHistory,MAX_HISTORY,sessionDebugAPI,init_SessionDebugger=__esm({"src/study/SessionDebugger.ts"(){init_logger(),init_PipelineDebugger(),init_SrsDebugger(),init_StrategyPressureDebugger(),init_SessionOverlay(),activeSession=null,sessionHistory=[],MAX_HISTORY=5,sessionDebugAPI={get sessions(){return[...sessionHistory]},get active(){return activeSession},showQueue(){showCurrentQueue()},dbgOverlay(){toggleSessionOverlay()},showHistory(e=0){showPresentationHistory(e)},showInterleaving(e=0){showInterleaving(e)},listSessions(){if(activeSession&&logger.info(`Active session: ${activeSession.sessionId} (${activeSession.presentations.length} cards presented)`),sessionHistory.length===0){logger.info(`[Session Debug] No completed sessions in history.`);return}console.table(sessionHistory.map((e,t)=>({index:t,id:e.sessionId.slice(-8),started:e.startTime.toLocaleTimeString(),ended:e.endTime?.toLocaleTimeString()||`incomplete`,cards:e.presentations.length})))},export(){let e={active:activeSession,history:sessionHistory},t=JSON.stringify(e,null,2);return logger.info(`[Session Debug] Session data exported. Copy the returned string or use:`),logger.info(` copy(window.skuilder.session.export())`),t},clear(){sessionHistory.length=0,logger.info(`[Session Debug] Session history cleared.`)},help(){logger.info(`
|
|
350
312
|
🎯 Session Debug API
|
|
351
313
|
|
|
352
314
|
Commands:
|
|
@@ -365,14 +327,53 @@ Example:
|
|
|
365
327
|
window.skuilder.session.showHistory()
|
|
366
328
|
window.skuilder.session.showInterleaving()
|
|
367
329
|
window.skuilder.session.showQueue()
|
|
368
|
-
`)}}
|
|
330
|
+
`)}},mountSessionDebugger()}}),SessionController,init_SessionController=__esm({"src/study/SessionController.ts"(){var e;init_SrsService(),init_EloService(),init_ResponseProcessor(),init_CardHydrationService(),init_ItemQueue(),init_couch(),init_core(),init_types_legacy(),init_studySession(),init_recording(),init_util2(),init_navigators(),init_Pipeline(),init_SourceMixer(),init_MixerDebugger(),init_SessionDebugger(),init_SessionOverlay(),init_logger(),SessionController=(e=class _SessionController extends Loggable{set sessionRecord(e){this._sessionRecord=e}get secondsRemaining(){return this._secondsRemaining}get hasCardGuarantee(){return this._minCardsGuarantee>0}get report(){let e=this.supplyQ.dequeueCount;return`${e} supply ${e===1?`card`:`cards`} drawn`}get detailedReport(){return this.supplyQ.toString+`
|
|
369
331
|
`+this.failedQ.toString}constructor(e,t,n,r,a,o){super(),_defineProperty(this,`_className`,`SessionController`),_defineProperty(this,`services`,void 0),_defineProperty(this,`srsService`,void 0),_defineProperty(this,`eloService`,void 0),_defineProperty(this,`hydrationService`,void 0),_defineProperty(this,`mixer`,void 0),_defineProperty(this,`dataLayer`,void 0),_defineProperty(this,`courseNameCache`,new Map),_defineProperty(this,`_defaultBatchLimit`,20),_defineProperty(this,`sources`,void 0),_defineProperty(this,`_sessionRecord`,[]),_defineProperty(this,`_currentCard`,null),_defineProperty(this,`supplyQ`,new ItemQueue),_defineProperty(this,`failedQ`,new ItemQueue),_defineProperty(this,`_supplyDrawsSinceFailed`,0),_defineProperty(this,`_replanPromise`,null),_defineProperty(this,`_activeReplanLabel`,null),_defineProperty(this,`_wellIndicatedRemaining`,0),_defineProperty(this,`_suppressQualityReplan`,!1),_defineProperty(this,`_minCardsGuarantee`,0),_defineProperty(this,`_sessionHints`,null),_defineProperty(this,`_servedCardIds`,new Set),_defineProperty(this,`_outcomeObservers`,[]),_defineProperty(this,`_sessionControls`,null),_defineProperty(this,`sessionId`,void 0),_defineProperty(this,`_courseId`,void 0),_defineProperty(this,`_stateSnapshotProvider`,void 0),_defineProperty(this,`_sessionDoc`,null),_defineProperty(this,`_openDocPromise`,null),_defineProperty(this,`_runLog`,[]),_defineProperty(this,`_eloLog`,[]),_defineProperty(this,`_sessionClosed`,!1),_defineProperty(this,`startTime`,void 0),_defineProperty(this,`endTime`,void 0),_defineProperty(this,`_secondsRemaining`,void 0),_defineProperty(this,`_intervalHandle`,void 0),this.sessionId=newSessionId(),setDebugSessionId(this.sessionId),this.dataLayer=n,this.mixer=a||new QuotaRoundRobinMixer,this.srsService=new SrsService(n.getUserDB()),this.eloService=new EloService(n,n.getUserDB()),this.hydrationService=new CardHydrationService(r,e=>n.getCourseDB(e),()=>this._getItemsToHydrate()),this.services={response:new ResponseProcessor(this.srsService,this.eloService,e=>this._recordEloEvent(e))},this.sources=e,this.startTime=new Date,this._secondsRemaining=t,this.endTime=new Date(this.startTime.valueOf()+1e3*this._secondsRemaining),o?.defaultBatchLimit!==void 0&&(this._defaultBatchLimit=o.defaultBatchLimit),o?.outcomeObservers?.length&&(this._outcomeObservers=[...o.outcomeObservers]),this._courseId=o?.courseId,this._stateSnapshotProvider=o?.stateSnapshotProvider,this.log(`Session constructed:
|
|
370
332
|
sessionId: ${this.sessionId}
|
|
371
333
|
startTime: ${this.startTime}
|
|
372
334
|
endTime: ${this.endTime}
|
|
373
|
-
defaultBatchLimit: ${this._defaultBatchLimit}`),registerActiveController(this)}tick(){this._secondsRemaining=Math.floor((this.endTime.valueOf()-Date.now())/1e3),this._secondsRemaining<=0&&clearInterval(this._intervalHandle)}estimateCleanupTime(){let e=0;for(let t=0;t<this.failedQ.length;t++){let n=this.failedQ.peek(t),r=this._sessionRecord.find(e=>e.item.cardID===n.cardID),a=0;if(r){for(let e=0;e<r.records.length;e++)a+=r.records[e].timeSpent;a/=r.records.length,e+=a}}let t=e/1e3;return this.log(`Failed card cleanup estimate: ${Math.round(t)}`),t}async prepareSession(){if(this.sources.some(e=>typeof e.getWeightedCards!=`function`))throw Error(`[SessionController] All content sources must implement getWeightedCards().`);clearStaleSessionDebugState();let e=await this.getWeightedContent();this._recordRuns(`bootstrap`),this._wellIndicatedRemaining=e,e>=0&&e<_SessionController.MIN_WELL_INDICATED&&this.log(`[Init] Only ${e}/${_SessionController.MIN_WELL_INDICATED} well-indicated cards in initial load`),await this.hydrationService.ensureHydratedCards(),startSessionTracking(this.sessionId,this.supplyQ.length,this.failedQ.length),this._openDocPromise=this._openSessionDoc(),this._intervalHandle=setInterval(()=>{this.tick()},1e3)}_recordRuns(e,t){for(let n of drainCapturedRuns()){if(this._runLog.length>=_SessionController.MAX_LOGGED_RUNS)break;this._runLog.push({runId:n.runId,at:n.timestamp.toISOString(),label:e,...t?{mode:t}:{},generatedCount:n.generatedCount,finalCount:n.finalCount,reviewsSelected:n.reviewsSelected,newSelected:n.newSelected,...typeof n.userElo==`number`?{userElo:n.userElo}:{},...n.generators?{generators:n.generators}:{},...n.filters?{filters:n.filters}:{},...n.hints?{hints:n.hints}:{},...n.discardedTail?{discardedTail:n.discardedTail}:{}})}}async _captureState(e){if(!this._stateSnapshotProvider)return;let t=3e3;try{return await Promise.race([Promise.resolve(this._stateSnapshotProvider(e)),new Promise(e=>setTimeout(()=>e(void 0),3e3))])}catch(t){this.log(`[Session] state snapshot (${e}) failed: ${t}`);return}}async _openSessionDoc(){if(this._courseId)try{let e=this.dataLayer.getUserDB(),t={_id:makeStudySessionId(this._courseId,e.getUsername(),this.sessionId),docType:`STUDY_SESSION`,sessionId:this.sessionId,courseId:this._courseId,userId:e.getUsername(),startTime:this.startTime.toISOString(),status:`open`,plannedSeconds:Math.round((this.endTime.valueOf()-this.startTime.valueOf())/1e3),config:{defaultBatchLimit:this._defaultBatchLimit,sourceCount:this.sources.length,initHints:this._sessionHints},initialQueues:{supplyQ:this.supplyQ.length,failedQ:this.failedQ.length},runs:[...this._runLog],stateAtStart:await this._captureState(`start`)};this._sessionDoc=t,await e.putStudySession(t),this.log(`[Session] Opened session record ${t._id}`)}catch(e){logger.warn(`[SessionController] Failed to open session record: ${e}`)}}async requestReplan(e){let t=this.normalizeReplanOptions(e),n=this._replanHasIntent(t);if(this._replanPromise){if(!n)return this.log(`Replan already in progress, coalescing unhinted auto-replan`),this._replanPromise;let e=t.label?` [${t.label}]`:``;this.log(`Replan in progress; queueing hint-bearing replan${e} behind in-flight run`);let r=this._replanPromise.catch(()=>void 0).then(()=>this._runReplan(t)),a=r.finally(()=>{this._replanPromise===a&&(this._replanPromise=null,this._activeReplanLabel=null)});return this._replanPromise=a,r}let r=this._runReplan(t),a=r.finally(()=>{this._replanPromise===a&&(this._replanPromise=null,this._activeReplanLabel=null)});this._replanPromise=a,await r}_replanHasIntent(e){return!!(e.limit!==void 0||e.minFollowUpCards!==void 0||e.mode&&e.mode!==`replace`||e.hints&&Object.keys(e.hints).length>0||e.sessionHints!==void 0||e.mergeSessionHints!==void 0)}async _runReplan(e){this._activeReplanLabel=e.label??`(auto)`,e.hints||(e.hints={});let t=e.hints,n=new Set(t.excludeCards??[]);this._currentCard?.item.cardID&&n.add(this._currentCard.item.cardID);for(let e of this._sessionRecord)n.add(e.card.card_id);this.supplyQ.length>0&&n.add(this.supplyQ.peek(0).cardID),t.excludeCards=[...n],e.sessionHints!==void 0&&(this._sessionHints=e.sessionHints,this.log(`[Replan] Session hints ${e.sessionHints?`set`:`cleared`}: ${JSON.stringify(e.sessionHints)}`)),e.mergeSessionHints!==void 0&&(this._sessionHints=mergeHints2([this._sessionHints,e.mergeSessionHints])??null,this.log(`[Replan] Session hints merged: ${JSON.stringify(this._sessionHints)}`)),this._applyHintsToSources(e.hints,e.label);let r=e.label?` [${e.label}]`:``;this.log(`Mid-session replan requested${r} (limit: ${e.limit??`default`}, mode: ${e.mode??`replace`}${e.hints?`, with hints`:``})`),e.minFollowUpCards!==void 0&&e.minFollowUpCards>0&&(this._minCardsGuarantee=Math.max(this._minCardsGuarantee,e.minFollowUpCards),this.log(`[Replan] Card guarantee set to ${this._minCardsGuarantee}`)),await this._executeReplan(e)}setSessionHints(e){this._sessionHints=e,this.log(`Session hints ${e?`set`:`cleared`}: ${JSON.stringify(e)}`)}getSessionHints(){return this._sessionHints}getDebugSnapshot(){let describe=e=>{let t=[];for(let n=0;n<e.length;n++){let r=e.peek(n);t.push({cardID:r.cardID,status:r.status,origin:isReview(r)?`review`:`new`,score:r.score})}return{length:e.length,dequeueCount:e.dequeueCount,cards:t}},e=this._sessionRecord.map(e=>{let t=e.records[e.records.length-1];return{cardID:e.item.cardID,status:e.item.status,attempts:e.records.length,correct:t&&isQuestionRecord(t)?t.isCorrect:null,timeSpentMs:e.records.reduce((e,t)=>e+t.timeSpent,0)}});return{sessionId:this.sessionId,secondsRemaining:this.secondsRemaining,hasCardGuarantee:this.hasCardGuarantee,minCardsGuarantee:this._minCardsGuarantee,wellIndicatedRemaining:this._wellIndicatedRemaining,currentCard:this._currentCard?.item.cardID??null,sessionHints:this._sessionHints,replanActive:this._replanPromise!==null,replanLabel:this._activeReplanLabel,supplyQ:describe(this.supplyQ),failedQ:describe(this.failedQ),reviewBacklog:getSrsBacklogDebug(),strategyPressure:getStrategyPressureDebug(),drawnCards:e}}mergeSessionHints(e){this._sessionHints=mergeHints2([this._sessionHints,e])??null,this.log(`Session hints merged: ${JSON.stringify(this._sessionHints)}`)}_applyHintsToSources(e,t){let n=e&&t?{...e,_label:t}:e,r=mergeHints2([this._sessionHints,n]);if(r)for(let e of this.sources)e.setEphemeralHints?.(r)}_getSessionControls(){return this._sessionControls||(this._sessionControls={getSessionHints:()=>this.getSessionHints(),setSessionHints:e=>this.setSessionHints(e),mergeSessionHints:e=>this.mergeSessionHints(e),requestReplan:e=>this.requestReplan(e)}),this._sessionControls}_recordEloEvent(e){this._eloLog.length>=_SessionController.MAX_LOGGED_ELO_EVENTS||this._eloLog.push(e)}async _notifyOutcomeObservers(e,t,n){if(this._outcomeObservers.length===0||!isQuestionRecord(e))return;let r={record:e,card:t.card,result:n},a=this._getSessionControls();for(let e of this._outcomeObservers)try{await e(r,a)}catch(e){this.error(`[OutcomeObserver] observer threw; ignoring`,e)}}async _replanUncoalesced(e){let t=this._runReplan(e),n=t.finally(()=>{this._replanPromise===n&&(this._replanPromise=null,this._activeReplanLabel=null)});this._replanPromise=n,await t}normalizeReplanOptions(e){if(!e)return{};let t=[`hints`,`sessionHints`,`limit`,`mode`,`label`,`minFollowUpCards`];return Object.keys(e).some(e=>t.includes(e))?e:{hints:e}}async _executeReplan(e={}){let t=e.limit,n=e.mode??`replace`,r=await this.getWeightedContent({replan:!0,additive:n===`merge`,limit:t});this._recordRuns(e.label??`(auto)`,n),this._wellIndicatedRemaining=r,t!==void 0&&t<this._defaultBatchLimit?(this._suppressQualityReplan=!0,this.log(`[Replan] Burst mode (limit=${t}): suppressing quality-based auto-replan`)):this._suppressQualityReplan=!1,r>=0&&r<_SessionController.MIN_WELL_INDICATED&&this.log(`[Replan] Only ${r}/${_SessionController.MIN_WELL_INDICATED} well-indicated cards after replan`),await this.hydrationService.ensureHydratedCards();let a=e.label?` [${e.label}]`:``;this.log(`Replan complete${a}: supplyQ now has ${this.supplyQ.length} cards (mode=${n})`),snapshotQueues(this.supplyQ.length,this.failedQ.length)}addTime(e){this.endTime=new Date(this.endTime.valueOf()+1e3*e)}get failedCount(){return this.failedQ.length}toString(){return`Session: ${this.supplyQ.length} supply, ${this.failedQ.length} failed`}reportString(){return`${this.supplyQ.dequeueCount} supply, ${this.failedQ.dequeueCount} failed`}getDebugInfo(){let e=this.sources.some(e=>typeof e.getWeightedCards==`function`),extractQueueItems=(e,t=10)=>{let n=[];for(let r=0;r<Math.min(e.length,t);r++){let t=e.peek(r);n.push({courseID:t.courseID||`unknown`,cardID:t.cardID||`unknown`,status:t.status||`unknown`,score:t.score})}return n};return{api:{mode:e?`weighted`:`legacy`,description:e?`Using getWeightedCards() API with scored candidates`:`ERROR: getWeightedCards() not a function.`},supplyQueue:{length:this.supplyQ.length,dequeueCount:this.supplyQ.dequeueCount,items:extractQueueItems(this.supplyQ)},failedQueue:{length:this.failedQ.length,dequeueCount:this.failedQ.dequeueCount,items:extractQueueItems(this.failedQ)},hydratedCache:{count:this.hydrationService.hydratedCount,cardIds:this.hydrationService.getHydratedCardIds()},replan:{inProgress:this._replanPromise!==null,suppressQualityReplan:this._suppressQualityReplan,defaultBatchLimit:this._defaultBatchLimit,minCardsGuarantee:this._minCardsGuarantee}}}async getWeightedContent(e){let t=e?.replan??!1,n=e?.additive??!1,r=e?.limit??this._defaultBatchLimit,a=r;t||this._applyHintsToSources();let o=[];for(let e=0;e<this.sources.length;e++){let t=this.sources[e];try{let n=(await t.getWeightedCards(a)).cards;o.push({sourceIndex:e,weighted:n})}catch(t){if(this.error(`Failed to get content from source ${e}:`,t),this.sources.length===1)throw Error(`Cannot start session: failed to load content from source ${e}`)}}if(o.length===0){if(t)return this.log(`Replan: no content from any source, keeping existing supplyQ`),-1;throw Error(`Cannot start session: failed to load content from all ${this.sources.length} source(s). Check logs for details.`)}let s=this.mixer.mix(o,a*this.sources.length),c=o.map(e=>e.weighted[0]?.courseId||`source-${e.sourceIndex}`);await Promise.all(c.map(async e=>{if(!this.courseNameCache.has(e))try{let t=await this.dataLayer.getCoursesDB().getCourseConfig(e);this.courseNameCache.set(e,t.name)}catch{}}));let l=c.map(e=>this.courseNameCache.get(e)),u=this.mixer instanceof QuotaRoundRobinMixer?Math.ceil(a*this.sources.length/o.length):void 0;captureMixerRun(this.mixer.constructor.name,o,c,l,a*this.sources.length,u,s);let d=s.filter(e=>!this._servedCardIds.has(e.cardId)),p=d.filter(e=>e.score===1/0),m=d.filter(e=>e.score!==1/0),g=[...p,...m.slice(0,Math.max(0,r-p.length))],_=new Set(p.map(e=>e.cardId)),v=g.filter(e=>e.score>=_SessionController.WELL_INDICATED_SCORE).length,y=t?`Replan content:
|
|
335
|
+
defaultBatchLimit: ${this._defaultBatchLimit}`),registerActiveController(this)}tick(){this._secondsRemaining=Math.floor((this.endTime.valueOf()-Date.now())/1e3),this._secondsRemaining<=0&&clearInterval(this._intervalHandle)}estimateCleanupTime(){let e=0;for(let t=0;t<this.failedQ.length;t++){let n=this.failedQ.peek(t),r=this._sessionRecord.find(e=>e.item.cardID===n.cardID),a=0;if(r){for(let e=0;e<r.records.length;e++)a+=r.records[e].timeSpent;a/=r.records.length,e+=a}}let t=e/1e3;return this.log(`Failed card cleanup estimate: ${Math.round(t)}`),t}async prepareSession(){if(this.sources.some(e=>typeof e.getWeightedCards!=`function`))throw Error(`[SessionController] All content sources must implement getWeightedCards().`);clearStaleSessionDebugState();let e=await this.getWeightedContent();this._recordRuns(`bootstrap`),this._wellIndicatedRemaining=e,e>=0&&e<_SessionController.MIN_WELL_INDICATED&&this.log(`[Init] Only ${e}/${_SessionController.MIN_WELL_INDICATED} well-indicated cards in initial load`),await this.hydrationService.ensureHydratedCards(),startSessionTracking(this.sessionId,this.supplyQ.length,this.failedQ.length),this._openDocPromise=this._openSessionDoc(),this._intervalHandle=setInterval(()=>{this.tick()},1e3)}_recordRuns(e,t){for(let n of drainCapturedRuns()){if(this._runLog.length>=_SessionController.MAX_LOGGED_RUNS)break;this._runLog.push({runId:n.runId,at:n.timestamp.toISOString(),label:e,...t?{mode:t}:{},generatedCount:n.generatedCount,finalCount:n.finalCount,reviewsSelected:n.reviewsSelected,newSelected:n.newSelected,...typeof n.userElo==`number`?{userElo:n.userElo}:{},...n.generators?{generators:n.generators}:{},...n.filters?{filters:n.filters}:{},...n.hints?{hints:n.hints}:{},...n.discardedTail?{discardedTail:n.discardedTail}:{}})}}async _captureState(e){if(!this._stateSnapshotProvider)return;let t=3e3;try{return await Promise.race([Promise.resolve(this._stateSnapshotProvider(e)),new Promise(e=>setTimeout(()=>e(void 0),3e3))])}catch(t){this.log(`[Session] state snapshot (${e}) failed: ${t}`);return}}async _openSessionDoc(){if(this._courseId)try{let e=this.dataLayer.getUserDB(),t={_id:makeStudySessionId(this._courseId,e.getUsername(),this.sessionId),docType:`STUDY_SESSION`,sessionId:this.sessionId,courseId:this._courseId,userId:e.getUsername(),startTime:this.startTime.toISOString(),status:`open`,plannedSeconds:Math.round((this.endTime.valueOf()-this.startTime.valueOf())/1e3),config:{defaultBatchLimit:this._defaultBatchLimit,sourceCount:this.sources.length,initHints:this._sessionHints},initialQueues:{supplyQ:this.supplyQ.length,failedQ:this.failedQ.length},runs:[...this._runLog],stateAtStart:await this._captureState(`start`)};this._sessionDoc=t,await e.putStudySession(t),this.log(`[Session] Opened session record ${t._id}`)}catch(e){logger.warn(`[SessionController] Failed to open session record: ${e}`)}}async requestReplan(e){let t=this.normalizeReplanOptions(e),n=this._replanHasIntent(t);if(this._replanPromise){if(!n)return this.log(`Replan already in progress, coalescing unhinted auto-replan`),this._replanPromise;let e=t.label?` [${t.label}]`:``;this.log(`Replan in progress; queueing hint-bearing replan${e} behind in-flight run`);let r=this._replanPromise.catch(()=>void 0).then(()=>this._runReplan(t)),a=r.finally(()=>{this._replanPromise===a&&(this._replanPromise=null,this._activeReplanLabel=null)});return this._replanPromise=a,r}let r=this._runReplan(t),a=r.finally(()=>{this._replanPromise===a&&(this._replanPromise=null,this._activeReplanLabel=null)});this._replanPromise=a,await r}_replanHasIntent(e){return!!(e.limit!==void 0||e.minFollowUpCards!==void 0||e.mode&&e.mode!==`replace`||e.hints&&Object.keys(e.hints).length>0||e.sessionHints!==void 0||e.mergeSessionHints!==void 0)}async _runReplan(e){this._activeReplanLabel=e.label??`(auto)`,e.hints||(e.hints={});let t=e.hints,n=new Set(t.excludeCards??[]);this._currentCard?.item.cardID&&n.add(this._currentCard.item.cardID);for(let e of this._sessionRecord)n.add(e.card.card_id);this.supplyQ.length>0&&n.add(this.supplyQ.peek(0).cardID),t.excludeCards=[...n],e.sessionHints!==void 0&&(this._sessionHints=e.sessionHints,this.log(`[Replan] Session hints ${e.sessionHints?`set`:`cleared`}: ${JSON.stringify(e.sessionHints)}`)),e.mergeSessionHints!==void 0&&(this._sessionHints=mergeHints2([this._sessionHints,e.mergeSessionHints])??null,this.log(`[Replan] Session hints merged: ${JSON.stringify(this._sessionHints)}`)),this._applyHintsToSources(e.hints,e.label);let r=e.label?` [${e.label}]`:``;this.log(`Mid-session replan requested${r} (limit: ${e.limit??`default`}, mode: ${e.mode??`replace`}${e.hints?`, with hints`:``})`),e.minFollowUpCards!==void 0&&e.minFollowUpCards>0&&(this._minCardsGuarantee=Math.max(this._minCardsGuarantee,e.minFollowUpCards),this.log(`[Replan] Card guarantee set to ${this._minCardsGuarantee}`)),await this._executeReplan(e)}setSessionHints(e){this._sessionHints=e,this.log(`Session hints ${e?`set`:`cleared`}: ${JSON.stringify(e)}`)}getSessionHints(){return this._sessionHints}getDebugSnapshot(){let describe=e=>{let t=[];for(let n=0;n<e.length;n++){let r=e.peek(n);t.push({cardID:r.cardID,status:r.status,origin:isReview(r)?`review`:`new`,score:r.score})}return{length:e.length,dequeueCount:e.dequeueCount,cards:t}},e=this._sessionRecord.map(e=>{let t=e.records[e.records.length-1];return{cardID:e.item.cardID,status:e.item.status,attempts:e.records.length,correct:t&&isQuestionRecord(t)?t.isCorrect:null,timeSpentMs:e.records.reduce((e,t)=>e+t.timeSpent,0)}});return{sessionId:this.sessionId,secondsRemaining:this.secondsRemaining,hasCardGuarantee:this.hasCardGuarantee,minCardsGuarantee:this._minCardsGuarantee,wellIndicatedRemaining:this._wellIndicatedRemaining,currentCard:this._currentCard?.item.cardID??null,sessionHints:this._sessionHints,replanActive:this._replanPromise!==null,replanLabel:this._activeReplanLabel,supplyQ:describe(this.supplyQ),failedQ:describe(this.failedQ),reviewBacklog:getSrsBacklogDebug(),strategyPressure:getStrategyPressureDebug(),drawnCards:e}}mergeSessionHints(e){this._sessionHints=mergeHints2([this._sessionHints,e])??null,this.log(`Session hints merged: ${JSON.stringify(this._sessionHints)}`)}_applyHintsToSources(e,t){let n=e&&t?{...e,_label:t}:e,r=mergeHints2([this._sessionHints,n]);if(r)for(let e of this.sources)e.setEphemeralHints?.(r)}_getSessionControls(){return this._sessionControls||(this._sessionControls={getSessionHints:()=>this.getSessionHints(),setSessionHints:e=>this.setSessionHints(e),mergeSessionHints:e=>this.mergeSessionHints(e),requestReplan:e=>this.requestReplan(e)}),this._sessionControls}_recordEloEvent(e){this._eloLog.length>=_SessionController.MAX_LOGGED_ELO_EVENTS||this._eloLog.push(e)}async _notifyOutcomeObservers(e,t,n){if(this._outcomeObservers.length===0||!isQuestionRecord(e))return;let r={record:e,card:t.card,result:n},a=this._getSessionControls();for(let e of this._outcomeObservers)try{await e(r,a)}catch(e){this.error(`[OutcomeObserver] observer threw; ignoring`,e)}}async _replanUncoalesced(e){let t=this._runReplan(e),n=t.finally(()=>{this._replanPromise===n&&(this._replanPromise=null,this._activeReplanLabel=null)});this._replanPromise=n,await t}normalizeReplanOptions(e){if(!e)return{};let t=[`hints`,`sessionHints`,`limit`,`mode`,`label`,`minFollowUpCards`];return Object.keys(e).some(e=>t.includes(e))?e:{hints:e}}async _executeReplan(e={}){let t=e.limit,n=e.mode??`replace`,r=await this.getWeightedContent({replan:!0,additive:n===`merge`,limit:t});this._recordRuns(e.label??`(auto)`,n),this._wellIndicatedRemaining=r,t!==void 0&&t<this._defaultBatchLimit?(this._suppressQualityReplan=!0,this.log(`[Replan] Burst mode (limit=${t}): suppressing quality-based auto-replan`)):this._suppressQualityReplan=!1,r>=0&&r<_SessionController.MIN_WELL_INDICATED&&this.log(`[Replan] Only ${r}/${_SessionController.MIN_WELL_INDICATED} well-indicated cards after replan`),await this.hydrationService.ensureHydratedCards();let a=e.label?` [${e.label}]`:``;this.log(`Replan complete${a}: supplyQ now has ${this.supplyQ.length} cards (mode=${n})`),snapshotQueues(this.supplyQ.length,this.failedQ.length)}addTime(e){this.endTime=new Date(this.endTime.valueOf()+1e3*e)}get failedCount(){return this.failedQ.length}toString(){return`Session: ${this.supplyQ.length} supply, ${this.failedQ.length} failed`}reportString(){return`${this.supplyQ.dequeueCount} supply, ${this.failedQ.dequeueCount} failed`}getDebugInfo(){let e=this.sources.some(e=>typeof e.getWeightedCards==`function`),extractQueueItems=(e,t=10)=>{let n=[];for(let r=0;r<Math.min(e.length,t);r++){let t=e.peek(r);n.push({courseID:t.courseID||`unknown`,cardID:t.cardID||`unknown`,status:t.status||`unknown`,score:t.score})}return n};return{api:{mode:e?`weighted`:`legacy`,description:e?`Using getWeightedCards() API with scored candidates`:`ERROR: getWeightedCards() not a function.`},supplyQueue:{length:this.supplyQ.length,dequeueCount:this.supplyQ.dequeueCount,items:extractQueueItems(this.supplyQ)},failedQueue:{length:this.failedQ.length,dequeueCount:this.failedQ.dequeueCount,items:extractQueueItems(this.failedQ)},hydratedCache:{count:this.hydrationService.hydratedCount,cardIds:this.hydrationService.getHydratedCardIds()},replan:{inProgress:this._replanPromise!==null,suppressQualityReplan:this._suppressQualityReplan,defaultBatchLimit:this._defaultBatchLimit,minCardsGuarantee:this._minCardsGuarantee}}}async getWeightedContent(e){let t=e?.replan??!1,n=e?.additive??!1,r=e?.limit??this._defaultBatchLimit,a=r;t||this._applyHintsToSources();let o=[];for(let e=0;e<this.sources.length;e++){let n=this.sources[e];try{let t=(await n.getWeightedCards(a)).cards;o.push({sourceIndex:e,weighted:t})}catch(n){if(this.error(`Failed to get content from source ${e}:`,n),this.sources.length===1&&!t)throw Error(`Cannot start session: failed to load content from source ${e}`)}}if(o.length===0){if(t)return this.log(`Replan: no content from any source, keeping existing supplyQ`),-1;throw Error(`Cannot start session: failed to load content from all ${this.sources.length} source(s). Check logs for details.`)}let s=this.mixer.mix(o,a*this.sources.length),c=o.map(e=>e.weighted[0]?.courseId||`source-${e.sourceIndex}`);await Promise.all(c.map(async e=>{if(!this.courseNameCache.has(e))try{let t=await this.dataLayer.getCoursesDB().getCourseConfig(e);this.courseNameCache.set(e,t.name)}catch{}}));let l=c.map(e=>this.courseNameCache.get(e)),u=this.mixer instanceof QuotaRoundRobinMixer?Math.ceil(a*this.sources.length/o.length):void 0;captureMixerRun(this.mixer.constructor.name,o,c,l,a*this.sources.length,u,s);let d=s.filter(e=>!this._servedCardIds.has(e.cardId)),p=d.filter(e=>e.score===1/0),m=d.filter(e=>e.score!==1/0),g=[...p,...m.slice(0,Math.max(0,r-p.length))],_=new Set(p.map(e=>e.cardId)),v=g.filter(e=>e.score>=_SessionController.WELL_INDICATED_SCORE).length,y=t?`Replan content:
|
|
374
336
|
`:`Mixed content session created with:
|
|
375
337
|
`,b=g.map(e=>{let t=getCardOrigin(e),n=Number.isFinite(e.score)?e.score.toFixed(2):`+INF`;return y+=`${t===`review`?`Review`:`New`}: ${e.courseId}::${e.cardId} (score: ${n})
|
|
376
338
|
`,this._buildSupplyItem(e,t)});if(n){let e=this.supplyQ.mergeToFront(b,e=>e.cardID,_);y+=`Additive merge: ${e} cards added to front of supplyQ
|
|
377
|
-
`}else if(t)this.supplyQ.replaceAll(b,e=>e.cardID);else for(let e of b)this.supplyQ.add(e,e.cardID);return this.log(y),v}_buildSupplyItem(e,t=getCardOrigin(e)){let n={cardID:e.cardId,courseID:e.courseId,contentSourceType:`course`,contentSourceID:e.courseId,score:e.score};return t===`review`?{...n,status:`review`,reviewID:e.reviewID}:{...n,status:`new`}}_getItemsToHydrate(){let e=[],t=3,n=2;for(let t=0;t<Math.min(3,this.supplyQ.length);t++)e.push(this.supplyQ.peek(t));for(let t=0;t<Math.min(2,this.failedQ.length);t++)e.push(this.failedQ.peek(t));return e}_selectNextItemToHydrate(){if(this.supplyQ.length===0&&this.failedQ.length===0||this._secondsRemaining<2&&this.failedQ.length===0&&this._minCardsGuarantee<=0)return null;if(this._secondsRemaining<=0&&this._minCardsGuarantee<=0)return this.failedQ.length>0?this.failedQ.peek(0):null;let e=this.supplyQ.length>0?this.supplyQ.peek(0):null;return this._minCardsGuarantee>0&&e?e:this.failedQ.length>0&&this._shouldInterleaveFailed(e!==null)?this.failedQ.peek(0):e||(this.failedQ.length>0?this.failedQ.peek(0):(this.log(`No more cards available for the session!`),null))}_shouldInterleaveFailed(e){return this.failedQ.length===0?!1:!e||this._secondsRemaining-this.estimateCleanupTime()<=_SessionController.FAILED_ENDGAME_SLACK_SECONDS?!0:this._supplyDrawsSinceFailed>=_SessionController.FAILED_INTERLEAVE_EVERY}async nextCard(e=`dismiss-success`){if(this.dismissCurrentCard(e),this._minCardsGuarantee>0&&(this._minCardsGuarantee--,this.log(`[CardGuarantee] ${this._minCardsGuarantee} guaranteed cards remaining`)),this._replanPromise&&this.supplyQ.length===0&&this.failedQ.length===0&&(this.log(`nextCard: queues empty, awaiting in-flight replan before drawing`),await this._replanPromise),this.supplyQ.length<=_SessionController.DEPLETION_PREFETCH_THRESHOLD&&this._secondsRemaining>0&&!this._replanPromise&&(this._suppressQualityReplan=!1,this.log(`[AutoReplan:depletion] supplyQ has ${this.supplyQ.length} card(s) (${this.failedQ.length} failed pending) with ${this._secondsRemaining}s remaining. Triggering background replan.`),this.requestReplan({label:`auto:depletion`,mode:`merge`})),!this._suppressQualityReplan&&this._wellIndicatedRemaining<=3&&this.supplyQ.length>0&&!this._replanPromise&&(this.log(`[AutoReplan:quality] ${this._wellIndicatedRemaining} well-indicated cards remaining (supplyQ: ${this.supplyQ.length}). Triggering background replan.`),this.requestReplan({label:`auto:quality`})),this._secondsRemaining<=0&&this.failedQ.length===0&&this._minCardsGuarantee<=0)return this._currentCard=null,endSessionTracking(),this._terminate(),null;let t=3,n=250,r=0;for(;this._secondsRemaining>0&&this.supplyQ.length===0&&this.failedQ.length===0;)if(this.log(`[WedgeBreaker] All queues empty with ${this._secondsRemaining}s remaining. Running pipeline (attempt ${r+1}/3).`),await this._replanUncoalesced({label:`wedge-breaker`}),this.supplyQ.length===0&&this.failedQ.length===0){if(r++,r>=3){this.log(`[WedgeBreaker] Pipeline returned no content 3 consecutive times. Giving up; session will end.`);break}await new Promise(e=>setTimeout(e,250))}else r=0;let a=20;for(let e=0;e<20;e++){let e=this._selectNextItemToHydrate();if(!e)return this._currentCard=null,endSessionTracking(),this._terminate(),null;let t=this.hydrationService.getHydratedCard(e.cardID);if(t||(t=await this.hydrationService.waitForCard(e.cardID)),this.removeItemFromQueue(e),t){await this.hydrationService.ensureHydratedCards(),this._currentCard=t;let n=e.status===`review`||e.status===`failed-review`?`review`:e.status===`new`||e.status===`failed-new`?`new`:`failed`,r=e.status.startsWith(`failed`)?`failedQ`:`supplyQ`;return recordCardPresentation(e.cardID,e.courseID,this.courseNameCache.get(e.courseID),n,r,e.score),snapshotQueues(this.supplyQ.length,this.failedQ.length),t}this.log(`Skipping card ${e.cardID}: hydration failed, trying next`),isReview(e)&&this.srsService.removeReview(e.reviewID)}return this.log(`Exhausted 20 skip attempts finding a hydratable card`),this._currentCard=null,endSessionTracking(),this._terminate(),null}_terminate(){this.endSession().catch(e=>{logger.warn(`[SessionController] endSession failed: ${e}`)})}async submitResponse(e,t,n,r,a,o,s,c,l){let u={...r.item},d=await this.services.response.processResponse(e,t,u,n,r,a,o,s,c,l);return await this._notifyOutcomeObservers(e,r,d),d}dismissCurrentCard(e=`dismiss-success`){if(this._currentCard)if(e===`dismiss-success`)this.hydrationService.removeCard(this._currentCard.item.cardID);else if(e===`marked-failed`){let e;e=isReview(this._currentCard.item)?{cardID:this._currentCard.item.cardID,courseID:this._currentCard.item.courseID,contentSourceID:this._currentCard.item.contentSourceID,contentSourceType:this._currentCard.item.contentSourceType,status:`failed-review`,reviewID:this._currentCard.item.reviewID}:{cardID:this._currentCard.item.cardID,courseID:this._currentCard.item.courseID,contentSourceID:this._currentCard.item.contentSourceID,contentSourceType:this._currentCard.item.contentSourceType,status:`failed-new`},this.failedQ.add(e,e.cardID),this._supplyDrawsSinceFailed=0}else (e===`dismiss-error`||e===`dismiss-failed`)&&this.hydrationService.removeCard(this._currentCard.item.cardID)}removeItemFromQueue(e){this._clearDurableRequirement(e.cardID),this._servedCardIds.add(e.cardID),this.failedQ.peek(0)?.cardID===e.cardID?(this.failedQ.dequeue(e=>e.cardID),this._supplyDrawsSinceFailed=0):this.supplyQ.peek(0)?.cardID===e.cardID&&(this.supplyQ.dequeue(e=>e.cardID),this._supplyDrawsSinceFailed++,this._wellIndicatedRemaining>0&&this._wellIndicatedRemaining--)}_clearDurableRequirement(e){let t=this._sessionHints?.requireCards;if(!t||t.length===0)return;let n=t.filter(t=>t!==e);n.length!==t.length&&(this._sessionHints={...this._sessionHints,requireCards:n.length>0?n:void 0},this.log(`[Replan] Durable requirement satisfied & cleared on draw: ${e}`))}async endSession(e=`closed`){if(this._sessionClosed||(this._sessionClosed=!0,clearInterval(this._intervalHandle),setDebugSessionId(void 0),await this._closeSessionDoc(e),!this._sessionRecord||this._sessionRecord.length===0))return;let t=this._sessionRecord.flatMap(e=>e.records).filter(e=>e.userAnswer!==void 0);if(t.length===0)return;let n=null,r=[];for(let e of this.sources)if(e.getOrchestrationContext){try{n=await e.getOrchestrationContext(),e.getStrategyIds&&r.push(...e.getStrategyIds())}catch(e){logger.warn(`[SessionController] Failed to get orchestration context: ${e}`)}if(n)break}if(!n){logger.debug(`[SessionController] No orchestration context available, skipping outcome recording`);return}let a=new Date().toISOString(),o=new Date(this.startTime).toISOString();await recordUserOutcome(n,o,a,t,r)}async _closeSessionDoc(e){this._openDocPromise&&await this._openDocPromise;let t=this._sessionDoc;if(!t)return;let n=this._sessionRecord.flatMap(e=>e.records),r=n.filter(isQuestionRecord);try{let a={...t,status:e,endTime:new Date().toISOString(),tally:{cardsPresented:this._sessionRecord.length,responses:n.length,correct:r.filter(e=>e.isCorrect).length,incorrect:r.filter(e=>!e.isCorrect).length,failedQRemaining:this.failedQ.length,secondsRemaining:Math.max(0,this._secondsRemaining)},runs:[...this._runLog],eloEvents:[...this._eloLog],finalHints:this._sessionHints,stateAtEnd:await this._captureState(`end`)};this._sessionDoc=a,await this.dataLayer.getUserDB().putStudySession(a),this.log(`[Session] Session record ${a._id} -> ${e} (${a.tally.cardsPresented} cards, ${a.tally.responses} responses, ${this._runLog.length} pipeline runs)`)}catch(e){logger.warn(`[SessionController] Failed to close session record: ${e}`)}}},_defineProperty(_SessionController2,`MAX_LOGGED_RUNS`,100),_defineProperty(_SessionController2,`MAX_LOGGED_ELO_EVENTS`,2e3),_defineProperty(_SessionController2,`MIN_WELL_INDICATED`,5),_defineProperty(_SessionController2,`WELL_INDICATED_SCORE`,.1),_defineProperty(_SessionController2,`DEPLETION_PREFETCH_THRESHOLD`,3),_defineProperty(_SessionController2,`FAILED_INTERLEAVE_EVERY`,4),_defineProperty(_SessionController2,`FAILED_ENDGAME_SLACK_SECONDS`,20),_SessionController2);init_TagFilteredContentSource(),init_factory(),init_userDBHelpers();export{initializeDataLayer as $,computeSpread as A,snapshotQueues as At,getCardOrigin as B,captureStrategyPressure as C,registerQuestionType as Ct,computeDeviation as D,scoreAccuracyInZone as Dt,clearStrategyPressureDebug as E,removeQuestionType as Et,ensureAppDataDirectory as F,userDBDebugAPI as Ft,getRegisteredNavigatorRole as G,getDbPath as H,getActiveController as I,validateMigration as It,getStrategyPressureDebug as J,getRunsForSession as K,getActivePipeline as L,validateProcessorConfig as Lt,diversityRerank as M,toggleSessionOverlay as Mt,drainCapturedRuns as N,updateLearningState as Nt,computeEffectiveWeight as O,sessionDebugAPI as Ot,endSessionTracking as P,updateStrategyWeight as Pt,initializeDataDirectory as Q,getAppDataDirectory as R,validateStaticCourse as Rt,captureMixerRun as S,registerNavigator as St,clearStaleSessionDebugState as T,removeDataShape as Tt,getRegisteredNavigator as U,getDataLayer as V,getRegisteredNavigatorNames as W,hasRegisteredNavigator as X,getStudySource as Y,importParsedCards as Z,REVIEW_TIME_FORMAT as _,processCustomQuestionsData as _t,DocType as a,isReview as at,areQuestionRecords as b,registerActiveController as bt,FileSystemError as c,makeStudySessionId as ct,Loggable as d,mountPipelineDebugger as dt,initializeNavigatorRegistry as et,NOT_SET as f,mountSessionDebugger as ft,QuotaRoundRobinMixer as g,pipelineDebugAPI as gt,Navigators as h,newSessionId as ht,DIVERSITY_STRENGTH as i,isQuestionTypeRegistered as it,createOrchestrationContext as j,startSessionTracking as jt,computeOutcomeSignal as k,setDebugSessionId as kt,GuestUsername as l,mixerDebugAPI as lt,NavigatorRoles as m,newInterval as mt,CourseLookup as n,isGenerator as nt,DocTypePrefixes as o,log as ot,NavigatorRole as p,mountUserDBDebugger as pt,getSrsBacklogDebug as q,DIVERSITY_FLOOR as r,isQuestionRecord as rt,ENV as s,makeScheduledCardId as st,ContentNavigator as t,isFilter as tt,HYDRATION_MARKER_ID as u,mountMixerDebugger as ut,SessionController as v,recordCardPresentation as vt,clearSrsBacklogDebug as w,registerSeedData as wt,buildStrategyStateId as x,registerDataShape as xt,TagFilteredContentSource as y,recordUserOutcome as yt,getCardHistoryID as z};
|
|
378
|
-
|
|
339
|
+
`}else if(t)this.supplyQ.replaceAll(b,e=>e.cardID);else for(let e of b)this.supplyQ.add(e,e.cardID);return this.log(y),v}_buildSupplyItem(e,t=getCardOrigin(e)){let n={cardID:e.cardId,courseID:e.courseId,contentSourceType:`course`,contentSourceID:e.courseId,score:e.score};return t===`review`?{...n,status:`review`,reviewID:e.reviewID}:{...n,status:`new`}}_getItemsToHydrate(){let e=[],t=3,n=2;for(let t=0;t<Math.min(3,this.supplyQ.length);t++)e.push(this.supplyQ.peek(t));for(let t=0;t<Math.min(2,this.failedQ.length);t++)e.push(this.failedQ.peek(t));return e}_selectNextItemToHydrate(){if(this.supplyQ.length===0&&this.failedQ.length===0||this._secondsRemaining<2&&this.failedQ.length===0&&this._minCardsGuarantee<=0)return null;if(this._secondsRemaining<=0&&this._minCardsGuarantee<=0)return this.failedQ.length>0?this.failedQ.peek(0):null;let e=this.supplyQ.length>0?this.supplyQ.peek(0):null;return this._minCardsGuarantee>0&&e?e:this.failedQ.length>0&&this._shouldInterleaveFailed(e!==null)?this.failedQ.peek(0):e||(this.failedQ.length>0?this.failedQ.peek(0):(this.log(`No more cards available for the session!`),null))}_shouldInterleaveFailed(e){return this.failedQ.length===0?!1:!e||this._secondsRemaining-this.estimateCleanupTime()<=_SessionController.FAILED_ENDGAME_SLACK_SECONDS?!0:this._supplyDrawsSinceFailed>=_SessionController.FAILED_INTERLEAVE_EVERY}async nextCard(e=`dismiss-success`){if(this.dismissCurrentCard(e),this._minCardsGuarantee>0&&(this._minCardsGuarantee--,this.log(`[CardGuarantee] ${this._minCardsGuarantee} guaranteed cards remaining`)),this._replanPromise&&this.supplyQ.length===0&&this.failedQ.length===0&&(this.log(`nextCard: queues empty, awaiting in-flight replan before drawing`),await this._replanPromise),this.supplyQ.length<=_SessionController.DEPLETION_PREFETCH_THRESHOLD&&this._secondsRemaining>0&&!this._replanPromise&&(this._suppressQualityReplan=!1,this.log(`[AutoReplan:depletion] supplyQ has ${this.supplyQ.length} card(s) (${this.failedQ.length} failed pending) with ${this._secondsRemaining}s remaining. Triggering background replan.`),this.requestReplan({label:`auto:depletion`,mode:`merge`})),!this._suppressQualityReplan&&this._wellIndicatedRemaining<=3&&this.supplyQ.length>0&&!this._replanPromise&&(this.log(`[AutoReplan:quality] ${this._wellIndicatedRemaining} well-indicated cards remaining (supplyQ: ${this.supplyQ.length}). Triggering background replan.`),this.requestReplan({label:`auto:quality`})),this._secondsRemaining<=0&&this.failedQ.length===0&&this._minCardsGuarantee<=0)return this._currentCard=null,endSessionTracking(),this._terminate(),null;let t=3,n=250,r=0;for(;this._secondsRemaining>0&&this.supplyQ.length===0&&this.failedQ.length===0;)if(this.log(`[WedgeBreaker] All queues empty with ${this._secondsRemaining}s remaining. Running pipeline (attempt ${r+1}/3).`),await this._replanUncoalesced({label:`wedge-breaker`}),this.supplyQ.length===0&&this.failedQ.length===0){if(r++,r>=3){this.log(`[WedgeBreaker] Pipeline returned no content 3 consecutive times. Giving up; session will end.`);break}await new Promise(e=>setTimeout(e,250))}else r=0;let a=20;for(let e=0;e<20;e++){let e=this._selectNextItemToHydrate();if(!e)return this._currentCard=null,endSessionTracking(),this._terminate(),null;let t=this.hydrationService.getHydratedCard(e.cardID);if(t||(t=await this.hydrationService.waitForCard(e.cardID)),this.removeItemFromQueue(e),t){await this.hydrationService.ensureHydratedCards(),this._currentCard=t;let n=e.status===`review`||e.status===`failed-review`?`review`:e.status===`new`||e.status===`failed-new`?`new`:`failed`,r=e.status.startsWith(`failed`)?`failedQ`:`supplyQ`;return recordCardPresentation(e.cardID,e.courseID,this.courseNameCache.get(e.courseID),n,r,e.score),snapshotQueues(this.supplyQ.length,this.failedQ.length),t}this.log(`Skipping card ${e.cardID}: hydration failed, trying next`),isReview(e)&&this.srsService.removeReview(e.reviewID)}return this.log(`Exhausted 20 skip attempts finding a hydratable card`),this._currentCard=null,endSessionTracking(),this._terminate(),null}_terminate(){this.endSession().catch(e=>{logger.warn(`[SessionController] endSession failed: ${e}`)})}async submitResponse(e,t,n,r,a,o,s,c,l){let u={...r.item},d=await this.services.response.processResponse(e,t,u,n,r,a,o,s,c,l);return await this._notifyOutcomeObservers(e,r,d),d}dismissCurrentCard(e=`dismiss-success`){if(this._currentCard)if(e===`dismiss-success`)this.hydrationService.removeCard(this._currentCard.item.cardID);else if(e===`marked-failed`){let e;e=isReview(this._currentCard.item)?{cardID:this._currentCard.item.cardID,courseID:this._currentCard.item.courseID,contentSourceID:this._currentCard.item.contentSourceID,contentSourceType:this._currentCard.item.contentSourceType,status:`failed-review`,reviewID:this._currentCard.item.reviewID}:{cardID:this._currentCard.item.cardID,courseID:this._currentCard.item.courseID,contentSourceID:this._currentCard.item.contentSourceID,contentSourceType:this._currentCard.item.contentSourceType,status:`failed-new`},this.failedQ.add(e,e.cardID),this._supplyDrawsSinceFailed=0}else (e===`dismiss-error`||e===`dismiss-failed`)&&this.hydrationService.removeCard(this._currentCard.item.cardID)}removeItemFromQueue(e){this._clearDurableRequirement(e.cardID),this._servedCardIds.add(e.cardID),this.failedQ.peek(0)?.cardID===e.cardID?(this.failedQ.dequeue(e=>e.cardID),this._supplyDrawsSinceFailed=0):this.supplyQ.peek(0)?.cardID===e.cardID&&(this.supplyQ.dequeue(e=>e.cardID),this._supplyDrawsSinceFailed++,this._wellIndicatedRemaining>0&&this._wellIndicatedRemaining--)}_clearDurableRequirement(e){let t=this._sessionHints?.requireCards;if(!t||t.length===0)return;let n=t.filter(t=>t!==e);n.length!==t.length&&(this._sessionHints={...this._sessionHints,requireCards:n.length>0?n:void 0},this.log(`[Replan] Durable requirement satisfied & cleared on draw: ${e}`))}async endSession(e=`closed`){if(this._sessionClosed||(this._sessionClosed=!0,clearInterval(this._intervalHandle),setDebugSessionId(void 0),await this._closeSessionDoc(e),!this._sessionRecord||this._sessionRecord.length===0))return;let t=this._sessionRecord.flatMap(e=>e.records).filter(e=>e.userAnswer!==void 0);if(t.length===0)return;let n=null,r=[];for(let e of this.sources)if(e.getOrchestrationContext){try{n=await e.getOrchestrationContext(),e.getStrategyIds&&r.push(...e.getStrategyIds())}catch(e){logger.warn(`[SessionController] Failed to get orchestration context: ${e}`)}if(n)break}if(!n){logger.debug(`[SessionController] No orchestration context available, skipping outcome recording`);return}let a=new Date().toISOString(),o=new Date(this.startTime).toISOString();await recordUserOutcome(n,o,a,t,r)}async _closeSessionDoc(e){this._openDocPromise&&await this._openDocPromise;let t=this._sessionDoc;if(!t)return;let n=this._sessionRecord.flatMap(e=>e.records),r=n.filter(isQuestionRecord);try{let a={...t,status:e,endTime:new Date().toISOString(),tally:{cardsPresented:this._sessionRecord.length,responses:n.length,correct:r.filter(e=>e.isCorrect).length,incorrect:r.filter(e=>!e.isCorrect).length,failedQRemaining:this.failedQ.length,secondsRemaining:Math.max(0,this._secondsRemaining)},runs:[...this._runLog],eloEvents:[...this._eloLog],finalHints:this._sessionHints,stateAtEnd:await this._captureState(`end`)};this._sessionDoc=a,await this.dataLayer.getUserDB().putStudySession(a),this.log(`[Session] Session record ${a._id} -> ${e} (${a.tally.cardsPresented} cards, ${a.tally.responses} responses, ${this._runLog.length} pipeline runs)`)}catch(e){logger.warn(`[SessionController] Failed to close session record: ${e}`)}}},_defineProperty(e,`MAX_LOGGED_RUNS`,100),_defineProperty(e,`MAX_LOGGED_ELO_EVENTS`,2e3),_defineProperty(e,`MIN_WELL_INDICATED`,5),_defineProperty(e,`WELL_INDICATED_SCORE`,.1),_defineProperty(e,`DEPLETION_PREFETCH_THRESHOLD`,3),_defineProperty(e,`FAILED_INTERLEAVE_EVERY`,4),_defineProperty(e,`FAILED_ENDGAME_SLACK_SECONDS`,20),e)}}),TagFilteredContentSource,init_TagFilteredContentSource=__esm({"src/study/TagFilteredContentSource.ts"(){init_courseDB(),init_logger(),TagFilteredContentSource=class{constructor(e,t,n){_defineProperty(this,`courseId`,void 0),_defineProperty(this,`filter`,void 0),_defineProperty(this,`user`,void 0),_defineProperty(this,`resolvedCardIds`,null),this.courseId=e,this.filter=t,this.user=n,logger.info(`[TagFilteredContentSource] Created for course "${e}" with filter:`,JSON.stringify(t))}async resolveFilteredCardIds(){if(this.resolvedCardIds!==null)return this.resolvedCardIds;let e=new Set;if(this.filter.include.length>0)for(let t of this.filter.include)try{(await getTag(this.courseId,t)).taggedCards.forEach(t=>e.add(t))}catch(e){logger.warn(`[TagFilteredContentSource] Could not resolve tag "${t}" for inclusion:`,e)}if(e.size===0&&this.filter.include.length>0)return logger.warn(`[TagFilteredContentSource] No cards found for include tags: ${this.filter.include.join(`, `)}`),this.resolvedCardIds=new Set,this.resolvedCardIds;let t=new Set;if(this.filter.exclude.length>0)for(let e of this.filter.exclude)try{(await getTag(this.courseId,e)).taggedCards.forEach(e=>t.add(e))}catch(t){logger.warn(`[TagFilteredContentSource] Could not resolve tag "${e}" for exclusion:`,t)}let n=new Set;for(let r of e)t.has(r)||n.add(r);return logger.info(`[TagFilteredContentSource] Resolved ${n.size} cards (included: ${e.size}, excluded: ${t.size})`),this.resolvedCardIds=n,n}async getWeightedCards(e){if(!hasActiveFilter(this.filter))return logger.warn(`[TagFilteredContentSource] getWeightedCards called with no active filter`),{cards:[]};let t=await this.resolveFilteredCardIds(),n=await this.user.getActiveCards(),r=new Set(n.map(e=>e.cardID)),a=[];for(let n of t)if(r.has(n)||a.push({cardId:n,courseId:this.courseId,score:1,provenance:[{strategy:`tagFilter`,strategyName:`Tag Filter`,strategyId:`TAG_FILTER`,action:`generated`,score:1,reason:`Tag-filtered new card (tags: ${this.filter.include.join(`, `)})`}]}),a.length>=e)break;logger.info(`[TagFilteredContentSource] Found ${a.length} new cards matching filter`);let o=await this.user.getPendingReviews(this.courseId),s=o.filter(e=>t.has(e.cardId));return logger.info(`[TagFilteredContentSource] Found ${s.length} pending reviews matching filter (of ${o.length} total)`),{cards:[...s.map(e=>({cardId:e.cardId,courseId:e.courseId,score:1,reviewID:e._id,provenance:[{strategy:`tagFilter`,strategyName:`Tag Filter`,strategyId:`TAG_FILTER`,action:`generated`,score:1,reason:`Tag-filtered review (tags: ${this.filter.include.join(`, `)})`}]})),...a].slice(0,e)}}clearCache(){this.resolvedCardIds=null}getCourseId(){return this.courseId}getFilter(){return this.filter}}}}),init_study=__esm({"src/study/index.ts"(){init_SessionController(),init_SourceMixer(),init_SpacedRepetition(),init_TagFilteredContentSource(),init_MixerDebugger(),init_SessionDebugger(),init_SessionOverlay()}});function makeScheduledCardId(e){return DocTypePrefixes.SCHEDULED_CARD+hooks.utc(e).format(REVIEW_TIME_FORMAT2)}function hexEncode(e){let t,n=``;for(let r=0;r<e.length;r++)t=e.charCodeAt(r).toString(16),n+=(`000`+t).slice(3);return n}function filterAllDocsByPrefix2(e,t,n){let r={startkey:t,endkey:t+``,include_docs:!0};return n&&Object.assign(r,n),e.allDocs(r)}function getStartAndEndKeys2(e){return{startkey:e,endkey:e+``}}function updateGuestAccountExpirationDate(e){let t=hooks.utc().add(2,`months`).toISOString(),n=`GuestAccountExpirationDate`;e.get(n).then(r=>e.put({_id:n,_rev:r._rev,date:t})).catch(()=>e.put({_id:n,date:t}))}function getLocalUserDB(e){let t=`userdb-${e}`;return typeof window>`u`?new pouchdb_setup_default(getDbPath(t),{}):new pouchdb_setup_default(t,{})}function scheduleCardReviewLocal(e,t){let n=hooks.utc();logger.info(`Scheduling for review in: ${t.time.diff(n,`h`)/24} days`),e.put({_id:makeScheduledCardId(t.time),cardId:t.card_id,reviewTime:t.time.toISOString(),courseId:t.course_id,scheduledAt:n.toISOString(),scheduledFor:t.scheduledFor,schedulingAgentId:t.schedulingAgentId})}async function removeScheduledCardReviewLocal(e,t){let n=await e.get(t);e.remove(n).then(e=>{e.ok&&log3(`Removed Review Doc: ${t}`)}).catch(e=>{log3(`Failed to remove Review Doc: ${t},
|
|
340
|
+
${JSON.stringify(e)}`)})}var REVIEW_TIME_FORMAT2,log3,init_userDBHelpers=__esm({"src/impl/common/userDBHelpers.ts"(){init_core(),init_logger(),init_pouchdb_setup(),init_dataDirectory(),REVIEW_TIME_FORMAT2=`YYYY-MM-DD--kk:mm:ss-SSS`,log3=e=>{logger.info(e)}}}),UsrCrsData,init_user_course_relDB=__esm({"src/impl/couch/user-course-relDB.ts"(){init_logger(),UsrCrsData=class{constructor(e,t){_defineProperty(this,`user`,void 0),_defineProperty(this,`_courseId`,void 0),this.user=e,this._courseId=t}async getReviewsForcast(e){let t=hooks.utc().add(e,`days`);return this.getReviewstoDate(t)}async getPendingReviews(){let e=hooks.utc();return this.getReviewstoDate(e)}async getScheduledReviewCount(){return(await this.getPendingReviews()).length}async getCourseSettings(){let e=(await this.user.getCourseRegistrationsDoc()).courses.find(e=>e.courseID===this._courseId);return e&&e.settings?e.settings:(logger.warn(`no settings found during lookup on course ${this._courseId}`),{})}updateCourseSettings(e){`updateCourseSettings`in this.user&&this.user.updateCourseSettings(this._courseId,e)}async getStrategyState(e){return this.user.getStrategyState(this._courseId,e)}async putStrategyState(e,t){return this.user.putStrategyState(this._courseId,e,t)}async deleteStrategyState(e){return this.user.deleteStrategyState(this._courseId,e)}async getReviewstoDate(e){let t=await this.user.getPendingReviews(this._courseId);return logger.debug(`Fetching ${this.user.getUsername()}'s scheduled reviews for course ${this._courseId}.`),t.filter(t=>{let n=hooks.utc(t.reviewTime);return e.isAfter(n)})}}}});function withTimeout(e,t,n){let r;return Promise.race([e,new Promise((e,a)=>{r=setTimeout(()=>a(Error(`${n} timed out after ${t}ms`)),t)})]).finally(()=>{r!==void 0&&clearTimeout(r)})}function accomodateGuest(){if(logger.log(`[funnel] accomodateGuest() called`),typeof localStorage>`u`)return logger.log(`[funnel] localStorage not available (Node.js environment), returning default guest`),{username:GuestUsername+`nodejs-test`,firstVisit:!0};let e=`sk-guest-uuid`,t,n=localStorage.getItem(e);if(logger.log(`[funnel] Checking localStorage for key:`,e),logger.log(`[funnel] Existing UUID value:`,n),logger.log(`[funnel] existingUUID !== null:`,n!==null),n!==null)t=!1,logger.log(`[funnel] Returning guest ${n} "logging in".`);else{t=!0,logger.log(`[funnel] No existing UUID, generating new one...`);let n=generateUUID();logger.log(`[funnel] Generated UUID:`,n),logger.log(`[funnel] UUID length:`,n.length);try{localStorage.setItem(e,n),logger.log(`[funnel] Successfully stored UUID in localStorage`);let t=localStorage.getItem(e);logger.log(`[funnel] Verification read from localStorage:`,t)}catch(e){logger.error(`[funnel] ERROR storing UUID:`,e)}logger.log(`[funnel] Accommodating a new guest with account: ${n}`)}let r=localStorage.getItem(e),a=GuestUsername+r;return logger.log(`[funnel] Final UUID from localStorage:`,r),logger.log(`[funnel] GuestUsername constant:`,GuestUsername),logger.log(`[funnel] Final username to return:`,a),{username:a,firstVisit:t};function generateUUID(){if(logger.log(`[funnel] Inside generateUUID()`),typeof crypto<`u`&&typeof crypto.randomUUID==`function`){let e=crypto.randomUUID();return logger.log(`[funnel] Generated UUID using crypto.randomUUID():`,e),e}if(typeof crypto<`u`&&typeof crypto.getRandomValues==`function`){let e=new Uint8Array(16);crypto.getRandomValues(e),e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=[Array.from(e.slice(0,4)).map(e=>e.toString(16).padStart(2,`0`)).join(``),Array.from(e.slice(4,6)).map(e=>e.toString(16).padStart(2,`0`)).join(``),Array.from(e.slice(6,8)).map(e=>e.toString(16).padStart(2,`0`)).join(``),Array.from(e.slice(8,10)).map(e=>e.toString(16).padStart(2,`0`)).join(``),Array.from(e.slice(10,16)).map(e=>e.toString(16).padStart(2,`0`)).join(``)].join(`-`);return logger.log(`[funnel] Generated UUID using crypto.getRandomValues():`,t),t}logger.warn(`[funnel] crypto API not available, using timestamp-based UUID (NOT SECURE)`);let e=new Date().getTime();typeof performance<`u`&&typeof performance.now==`function`&&(e+=performance.now());let t=`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g,t=>{let n=(e+Math.random()*16)%16|0;return e=Math.floor(e/16),(t===`x`?n:n&3|8).toString(16)});return logger.log(`[funnel] Generated UUID (fallback):`,t),t}}async function getOrCreateClassroomRegistrationsDoc(e){let t;try{t=await getLocalUserDB(e).get(userClassroomsDoc)}catch(n){let r=n;if(r.status===404)await getLocalUserDB(e).put({_id:userClassroomsDoc,registrations:[]}),t=await getOrCreateClassroomRegistrationsDoc(e);else{let e={name:r.name,status:r.status,message:r.message,reason:r.reason,error:r.error};throw logger.error(`Database error in getOrCreateClassroomRegistrationsDoc (standalone function):`,e),Error(`Database error accessing classroom registrations: ${r.message||r.name||`Unknown error`} (status: ${r.status})`)}}return t}async function getOrCreateCourseRegistrationsDoc(e){let t;try{t=await getLocalUserDB(e).get(userCoursesDoc)}catch(n){if(n.status===404)await getLocalUserDB(e).put({_id:userCoursesDoc,courses:[],studyWeight:{}}),t=await getOrCreateCourseRegistrationsDoc(e);else throw Error(`Unexpected error ${JSON.stringify(n)} in getOrCreateCourseRegistrationDoc...`)}return t}async function updateUserElo(e,t,n){let r=await getOrCreateCourseRegistrationsDoc(e),a=r.courses.find(e=>e.courseID===t);return a.elo=n,getLocalUserDB(e).put(r)}async function registerUserForClassroom(e,t,n){return log4(`Registering user: ${e} in course: ${t}`),getOrCreateClassroomRegistrationsDoc(e).then(r=>{let a={classID:t,registeredAs:n};return r.registrations.filter(e=>e.classID===a.classID&&e.registeredAs===a.registeredAs).length===0?r.registrations.push(a):log4(`User ${e} is already registered for class ${t}`),getLocalUserDB(e).put(r)})}async function dropUserFromClassroom(e,t){return getOrCreateClassroomRegistrationsDoc(e).then(n=>{let r=-1;for(let e=0;e<n.registrations.length;e++)n.registrations[e].classID===t&&(r=e);return r!==-1&&n.registrations.splice(r,1),getLocalUserDB(e).put(n)})}async function getUserClassrooms(e){return getOrCreateClassroomRegistrationsDoc(e)}var log4,HYDRATION_TIMEOUT_MS,BaseUser,userCoursesDoc,userClassroomsDoc,init_BaseUserDB=__esm({"src/impl/common/BaseUserDB.ts"(){var e;init_core(),init_util(),init_types_legacy(),init_logger(),init_study(),init_userDBHelpers(),init_updateQueue(),init_user_course_relDB(),init_couch(),log4=e=>{logger.info(e)},HYDRATION_TIMEOUT_MS=15e3,BaseUser=(e=class _BaseUser{static Dummy(e){return new _BaseUser(`Me`,e)}getUsername(){return this._username}isLoggedIn(){return!this._username.startsWith(GuestUsername)}remote(){return this.remoteDB}hydrationStatus(){return{...this._hydration}}async awaitHydration(){try{await this._hydrationPromise}catch{}return this.hydrationStatus()}canMaterializeDefaults(){return this._hydration.state!==`failed`&&this._hydration.state!==`hydrating`}async createAccount(e,t){if(!this.syncStrategy.canCreateAccount())throw Error(`Account creation not supported by current sync strategy`);if(!this._username.startsWith(GuestUsername))throw Error(`Cannot create a new account while logged in:
|
|
341
|
+
Currently logged-in as ${this._username}.`);let n=await this.syncStrategy.createAccount(e,t);if(n.status===Status.ok){log4(`Account created successfully, updating username to ${e}`),this._username=e;try{localStorage.removeItem(`sk-guest-uuid`)}catch(e){logger.warn(`localStorage not available (Node.js environment):`,e)}await this.init()}return{status:n.status,error:n.error||``}}async login(e,t){if(!this.syncStrategy.canAuthenticate())throw Error(`Authentication not supported by current sync strategy`);if(!this._username.startsWith(GuestUsername)&&this._username!=e){if(this._username!=e)throw Error(`Cannot change accounts while logged in.
|
|
342
|
+
Log out of account ${this.getUsername()} before logging in as ${e}.`);logger.warn(`User ${this._username} is already logged in, but executing login again.`)}let n=await this.syncStrategy.authenticate(e,t);if(n.ok){log4(`Logged in as ${e}`),this._username=e;try{localStorage.removeItem(`sk-guest-uuid`)}catch(e){logger.warn(`localStorage not available (Node.js environment):`,e)}await this.init()}return n}async adoptSession(e){if(!this.syncStrategy.canAuthenticate()||!this.syncStrategy.adoptSession)throw Error(`Session adoption not supported by current sync strategy`);let t=this._username.startsWith(GuestUsername)?this._username:void 0;if(!t)throw Error(`Cannot adopt a session while logged in.
|
|
343
|
+
Log out of account ${this.getUsername()} first.`);let n=await this.syncStrategy.adoptSession(e.migrateGuestData?t:void 0);if(n.ok&&n.username){log4(`Adopted session for ${n.username}`),this._username=n.username;try{localStorage.removeItem(`sk-guest-uuid`)}catch(e){logger.warn(`localStorage not available (Node.js environment):`,e)}await this.init()}return n}async resetUserData(){if(this.syncStrategy.canAuthenticate())return{status:Status.error,error:`Reset user data is only available for local-only mode. Use logout instead for remote sync.`};try{let e=getLocalUserDB(this._username),t=(await e.allDocs({include_docs:!1})).rows.filter(e=>{let t=e.id;return t.startsWith(DocTypePrefixes.CARDRECORD)||t.startsWith(DocTypePrefixes.SCHEDULED_CARD)||t.startsWith(DocTypePrefixes.STRATEGY_STATE)||t.startsWith(DocTypePrefixes.USER_OUTCOME)||t.startsWith(DocTypePrefixes.STRATEGY_LEARNING_STATE)||t===_BaseUser.DOC_IDS.COURSE_REGISTRATIONS||t===_BaseUser.DOC_IDS.CLASSROOM_REGISTRATIONS||t===_BaseUser.DOC_IDS.CONFIG}).map(e=>({_id:e.id,_rev:e.value.rev,_deleted:!0}));return t.length>0&&await e.bulkDocs(t),await this.init(),{status:Status.ok}}catch(e){return logger.error(`Failed to reset user data:`,e),{status:Status.error,error:e instanceof Error?e.message:`Unknown error during reset`}}}async logout(){if(!this.syncStrategy.canAuthenticate())return this._username=await this.syncStrategy.getCurrentUsername(),await this.init(),{ok:!0};let e=await this.syncStrategy.logout();try{localStorage.removeItem(`sk-guest-uuid`)}catch(e){logger.warn(`localStorage not available (Node.js environment):`,e)}return this._username=await this.syncStrategy.getCurrentUsername(),await this.init(),e}async get(e){return this.localDB.get(e)}update(e,t){return this.updateQueue.update(e,t)}async getCourseRegistrationsDoc(){logger.debug(`Fetching courseRegistrations for ${this.getUsername()}`);let e;try{return await this.localDB.get(_BaseUser.DOC_IDS.COURSE_REGISTRATIONS)}catch(t){if(t.status===404){if(!this.canMaterializeDefaults())throw Error(`Cannot read course registrations for ${this._username}: the local mirror is unavailable (hydration state '${this._hydration.state}'). Refusing to create an empty registration doc \u2014 that would report an existing user as unregistered, and then lose to their real document once sync resumes.`);await this.localDB.put({_id:_BaseUser.DOC_IDS.COURSE_REGISTRATIONS,courses:[],studyWeight:{}}),e=await this.getCourseRegistrationsDoc()}else throw Error(`Unexpected error ${JSON.stringify(t)} in getOrCreateCourseRegistrationDoc...`)}return e}async getActiveCourses(){return(await this.getCourseRegistrationsDoc()).courses.filter(e=>e.status===void 0||e.status===`active`)}async getActiveCards(){let e=getStartAndEndKeys2(DocTypePrefixes.SCHEDULED_CARD);return(await this.remoteDB.allDocs({startkey:e.startkey,endkey:e.endkey,include_docs:!0})).rows.map(e=>({courseID:e.doc.courseId,cardID:e.doc.cardId}))}async getActivityRecords(){try{let e=await this.getHistory(),t=[];if(!Array.isArray(e))return logger.error(`getHistory did not return an array:`,e),t;let n=0;for(let r=0;r<e.length;r++)try{e[r]&&Array.isArray(e[r].records)&&e[r].records.forEach(e=>{try{if(!e.timeStamp)return;let r;if(typeof e.timeStamp==`object`)if(typeof e.timeStamp.toDate==`function`)r=e.timeStamp.toISOString();else if(e.timeStamp instanceof Date)r=e.timeStamp.toISOString();else{n<3&&(logger.warn(`Unknown timestamp object type:`,e.timeStamp),n++);return}else if(typeof e.timeStamp==`string`){let t=new Date(e.timeStamp);if(isNaN(t.getTime()))return;r=e.timeStamp}else if(typeof e.timeStamp==`number`)r=new Date(e.timeStamp).toISOString();else return;t.push({timeStamp:r,courseID:e.courseID||`unknown`,cardID:e.cardID||`unknown`,timeSpent:e.timeSpent||0,type:`card_view`})}catch{}})}catch(e){logger.error(`Error processing history item:`,e)}return logger.debug(`Found ${t.length} activity records`),t}catch(e){return logger.error(`Error in getActivityRecords:`,e),[]}}async getReviewstoDate(e,t){let n=getStartAndEndKeys2(DocTypePrefixes.SCHEDULED_CARD),r=await this.remoteDB.allDocs({startkey:n.startkey,endkey:n.endkey,include_docs:!0});return log4(`Fetching ${this._username}'s scheduled reviews${t?` for course ${t}`:``}.`),r.rows.filter(n=>{if(n.id.startsWith(DocTypePrefixes.SCHEDULED_CARD)){let r=hooks.utc(n.id.substr(DocTypePrefixes.SCHEDULED_CARD.length),REVIEW_TIME_FORMAT2);if(e.isAfter(r)&&(t===void 0||n.doc.courseId===t))return!0}}).map(e=>e.doc)}async getReviewsForcast(e,t){let n=hooks.utc().add(e,`days`);return this.getReviewstoDate(n,t)}async getPendingReviews(e){let t=hooks.utc();return this.getReviewstoDate(t,e)}async getScheduledReviewCount(e){return(await this.getPendingReviews(e)).length}async getRegisteredCourses(){return(await this.getCourseRegistrationsDoc()).courses.filter(e=>!e.status||e.status===`active`||e.status===`maintenance-mode`)}async getCourseRegDoc(e){let t=(await this.getCourseRegistrationsDoc()).courses.find(t=>t.courseID===e);if(t)return t;throw Error(`Course registration not found for course ID: ${e}`)}async registerForCourse(e,t=!1){return this.getCourseRegistrationsDoc().then(n=>{let r=t?`preview`:`active`;logger.debug(`Registering for ${e} with status: ${r}`);let a={status:r,courseID:e,user:!0,admin:!1,moderator:!1,elo:{global:{score:1e3,count:0},tags:{},misc:{}}};return n.courses.filter(e=>e.courseID===a.courseID).length===0?(log4(`It's a new course registration!`),n.courses.push(a),n.studyWeight[e]=1):n.courses.forEach(t=>{log4(`Found the previously registered course!`),t.courseID===e&&(t.status=r)}),this.localDB.put(n)}).catch(e=>{throw log4(`Registration failed because of: ${JSON.stringify(e)}`),e})}async dropCourse(e,t=`dropped`){return this.getCourseRegistrationsDoc().then(n=>{let r=-1;for(let t=0;t<n.courses.length;t++)n.courses[t].courseID===e&&(r=t);if(r!==-1)delete n.studyWeight[e],n.courses[r].status=t;else throw Error(`User ${this.getUsername()} is not currently registered for course ${e}`);return this.localDB.put(n)})}async getCourseInterface(e){return new UsrCrsData(this,e)}async getUserEditableCourses(){let e=[],t=await this.getCourseRegistrationsDoc();return e=e.concat(t.courses.map(e=>e.courseID)),await Promise.all(e.map(async e=>await getCredentialledCourseConfig(e)))}async getConfig(){let e={_id:_BaseUser.DOC_IDS.CONFIG,darkMode:!1,likesConfetti:!1,sessionTimeLimit:5};try{let e=await this.localDB.get(_BaseUser.DOC_IDS.CONFIG);return logger.debug(`Raw config from DB:`,e),e}catch(t){let n=t;if(n.name&&n.name===`not_found`){if(!this.canMaterializeDefaults())throw Error(`Cannot read config for ${this._username}: the local mirror is unavailable (hydration state '${this._hydration.state}'). Refusing to write a default config over what may be an existing one.`);return await this.localDB.put(e),this.getConfig()}else throw logger.error(`Error setting user default config:`,t),Error(`Error returning the user's configuration: ${JSON.stringify(t)}`)}}async setConfig(e){logger.debug(`Setting Config items ${JSON.stringify(e)}`);let t=await this.getConfig(),n=await this.localDB.put({...t,...e});n.ok?logger.debug(`Config items set: ${JSON.stringify(e)}`):logger.error(`Error setting config items: ${JSON.stringify(n)}`)}static async instance(e,t){return t?(_BaseUser._instance=new _BaseUser(t,e),await _BaseUser._instance.init(),_BaseUser._instance):_BaseUser._instance&&_BaseUser._initialized?_BaseUser._instance:_BaseUser._instance?new Promise(e=>{(function waitForUser(){if(_BaseUser._initialized)return e(_BaseUser._instance);setTimeout(waitForUser,50)})()}):(_BaseUser._instance=new _BaseUser(await e.getCurrentUsername(),e),await _BaseUser._instance.init(),_BaseUser._instance)}constructor(e,t){_defineProperty(this,`_username`,void 0),_defineProperty(this,`syncStrategy`,void 0),_defineProperty(this,`localDB`,void 0),_defineProperty(this,`remoteDB`,void 0),_defineProperty(this,`writeDB`,void 0),_defineProperty(this,`updateQueue`,void 0),_defineProperty(this,`_hydration`,{state:`not-required`}),_defineProperty(this,`_hydrationPromise`,null),_defineProperty(this,`_hydratedSeq`,void 0),_BaseUser._initialized=!1,this._username=e,this.syncStrategy=t,this.setDBandQ()}setDBandQ(){this.localDB=getLocalUserDB(this._username),this.remoteDB=this.syncStrategy.setupRemoteDB(this._username),this.writeDB=this.syncStrategy.getWriteDB?this.syncStrategy.getWriteDB(this._username):this.localDB,this.updateQueue=new UpdateQueue(this.localDB,this.writeDB)}async init(){if(_BaseUser._initialized=!1,this._username===`admin`){_BaseUser._initialized=!0;return}this.syncStrategy.stopSync?.(),this.setDBandQ(),this._hydrationPromise=this.hydrateLocalMirror(),await this._hydrationPromise,this.syncStrategy.startSync(this.localDB,this.remoteDB,this._hydratedSeq),this.applyDesignDocs().catch(e=>{log4(`Error in applyDesignDocs background task: ${e}`),e&&typeof e==`object`&&log4(`Full error details in applyDesignDocs: ${JSON.stringify(e)}`)}),this.deduplicateReviews().catch(e=>{log4(`Error in deduplicateReviews background task: ${e}`),e&&typeof e==`object`&&log4(`Full error details in background task: ${JSON.stringify(e)}`)}),_BaseUser._initialized=!0}async hydrateLocalMirror(){if(this._hydratedSeq=void 0,this.localDB.name===this.remoteDB.name||!this.syncStrategy.hydrate){this._hydration={state:`not-required`};return}if(await this.hasHydrationMarker()){this._hydration={state:`stale`};return}this._hydration={state:`hydrating`};let e=Date.now();try{let{docsWritten:t,lastSeq:n}=await withTimeout(this.syncStrategy.hydrate(this.localDB,this.remoteDB),HYDRATION_TIMEOUT_MS,`Hydration of local mirror for ${this._username}`);this._hydratedSeq=n,await this.writeHydrationMarker(),this._hydration={state:`hydrated`,docsWritten:t,durationMs:Date.now()-e},log4(`Hydrated local mirror for ${this._username}: ${t} docs in ${this._hydration.durationMs}ms`)}catch(t){this.syncStrategy.stopSync?.(),this._hydration={state:`failed`,durationMs:Date.now()-e,error:t instanceof Error?t.message:String(t)},logger.error(`Failed to hydrate local mirror for ${this._username}:`,t)}}async hasHydrationMarker(){try{return(await this.localDB.get(HYDRATION_MARKER_ID)).username===this._username}catch{return!1}}async writeHydrationMarker(){try{let e;try{e=(await this.localDB.get(HYDRATION_MARKER_ID))._rev}catch{}await this.localDB.put({_id:HYDRATION_MARKER_ID,_rev:e,username:this._username,hydratedAt:new Date().toISOString()})}catch(e){logger.warn(`Could not write hydration marker for ${this._username}: ${e}`)}}async applyDesignDocs(){if(log4(`Starting applyDesignDocs for user: ${this._username}`),log4(`Remote DB name: ${this.remoteDB.name||`unknown`}`),this._username===`admin`){log4(`Skipping design docs for admin user`);return}log4(`Applying ${_BaseUser.designDocs.length} design docs`);for(let e of _BaseUser.designDocs){log4(`Applying design doc: ${e._id}`);try{try{let t=await this.remoteDB.get(e._id);await this.remoteDB.put({...e,_rev:t._rev})}catch(t){if(t?.name===`not_found`)await this.remoteDB.put(e);else throw t}}catch(t){if(t.name&&t.name===`conflict`)logger.warn(`Design doc ${e._id} update conflict - will retry`),await new Promise(e=>setTimeout(e,1e3)),await this.applyDesignDoc(e);else throw logger.error(`Failed to apply design doc ${e._id}:`,t),t}}}async applyDesignDoc(e,t=3){try{let t=await this.remoteDB.get(e._id);await this.remoteDB.put({...e,_rev:t._rev})}catch(n){if(n?.name===`conflict`&&t>0)return await new Promise(e=>setTimeout(e,1e3)),this.applyDesignDoc(e,t-1);throw n}}async putCardRecord(e){let t=getCardHistoryID(e.courseID,e.cardID);e.timeStamp=hooks.utc(e.timeStamp).toString();try{let n=await this.update(t,function(t){return t.records.push(e),t.bestInterval=t.bestInterval||0,areQuestionRecords(t)?(t.lapses=getLapses(t.records),t.streak=getStreak(t.records)):(t.lapses=t.lapses||0,t.streak=t.streak||0),t});return n.records=n.records.map(e=>{let t={...e};return t.timeStamp=hooks.utc(e.timeStamp),t}),n}catch(n){let r=n;if(r.status===404)try{let n={_id:t,cardID:e.cardID,courseID:e.courseID,records:[e],lapses:0,streak:0,bestInterval:0},r=await this.writeDB.put(n);return{...n,_rev:r.rev}}catch(e){throw Error(`Failed to create CardHistory for ${t}. Reason: ${e}`)}else throw Error(`putCardRecord failed because of:
|
|
344
|
+
name:${r.name}
|
|
345
|
+
error: ${r.error}
|
|
346
|
+
message: ${r.message}`)}}async deduplicateReviews(){try{log4(`Starting deduplication of scheduled reviews...`),log4(`Remote DB name: ${this.remoteDB.name||`unknown`}`),log4(`Write DB name: ${this.writeDB.name||`unknown`}`);let e={},t=[];log4(`Attempting to query remoteDB for reviewCards/reviewCards. Database: ${this.remoteDB.name||`unknown`}`);let n=await this.remoteDB.query(`reviewCards/reviewCards`);if(log4(`Found ${n.rows.length} scheduled reviews to process`),n.rows.forEach(n=>{let r=n.value,a=n.key;e[r]?(log4(`Found duplicate scheduled review for card: ${r}`),log4(`Marking earlier review ${e[r]} for deletion, keeping ${a}`),t.push(e[r]),e[r]=a):e[r]=a}),t.length>0){log4(`Removing ${t.length} duplicate reviews...`);let e=t.map(async e=>{try{let t=await this.remoteDB.get(e);await this.writeDB.remove(t),log4(`Successfully removed duplicate review: ${e}`)}catch(t){log4(`Failed to remove duplicate review ${e}: ${t}`)}});await Promise.all(e),log4(`Deduplication complete. Processed ${t.length} duplicates`)}else log4(`No duplicate reviews found`)}catch(e){log4(`Error during review deduplication: ${e}`),e&&typeof e==`object`&&`status`in e&&e.status===404&&(log4(`Database not found (404) during review deduplication. Database: ${this.remoteDB.name||`unknown`}`),log4(`This might indicate the user database doesn't exist or the reviewCards view isn't available`)),e&&typeof e==`object`&&log4(`Full error details: ${JSON.stringify(e)}`)}}async getSeenCards(e){let t=DocTypePrefixes.CARDRECORD;e&&(t+=`-${e}-`);let n=await filterAllDocsByPrefix2(this.localDB,t,{include_docs:!1}),r=[];return n.rows.forEach(e=>{e.id.startsWith(t)&&r.push(e.id.substr(t.length))}),r}async getHistory(){return(await filterAllDocsByPrefix2(this.remoteDB,DocTypePrefixes.CARDRECORD,{include_docs:!0,attachments:!1})).rows.map(e=>e.doc)}async updateCourseSettings(e,t){this.getCourseRegistrationsDoc().then(n=>{let r=n.courses.find(t=>t.courseID===e);return r&&((r.settings===null||r.settings===void 0)&&(r.settings={}),t.forEach(e=>{r.settings[e.key]=e.value})),this.localDB.put(n)})}async getCourseSettings(e){let t=(await this.getCourseRegistrationsDoc()).courses.find(t=>t.courseID===e);if(t)return t.settings;throw Error(`getCourseSettings Failed:
|
|
347
|
+
User is not registered for course ${e}`)}async getOrCreateClassroomRegistrationsDoc(){let e;try{e=await this.remoteDB.get(_BaseUser.DOC_IDS.CLASSROOM_REGISTRATIONS)}catch(t){let n=t;if(n.status===404)await this.writeDB.put({_id:_BaseUser.DOC_IDS.CLASSROOM_REGISTRATIONS,registrations:[]}),e=await this.getOrCreateClassroomRegistrationsDoc();else{let e={name:n.name,status:n.status,message:n.message,reason:n.reason,error:n.error};throw logger.error(`Database error in getOrCreateClassroomRegistrationsDoc (private method):`,e),Error(`Database error accessing classroom registrations: ${n.message||n.name||`Unknown error`} (status: ${n.status})`)}}return logger.debug(`Returning classroom registrations doc: ${JSON.stringify(e)}`),e}async getActiveClasses(){try{return(await this.getOrCreateClassroomRegistrationsDoc()).registrations.filter(e=>e.registeredAs===`student`).map(e=>e.classID)}catch(e){return logger.warn(`Failed to load classroom registrations, continuing without classroom data:`,e),[]}}async scheduleCardReview(e){return scheduleCardReviewLocal(this.writeDB,e)}async removeScheduledCardReview(e){return removeScheduledCardReviewLocal(this.writeDB,e)}async registerForClassroom(e,t){return registerUserForClassroom(this._username,e,t)}async dropFromClassroom(e){return dropUserFromClassroom(this._username,e)}async getUserClassrooms(){return getUserClassrooms(this._username)}async updateUserElo(e,t){return updateUserElo(this._username,e,t)}async getStrategyState(e,t){let n=buildStrategyStateId(e,t);try{return(await this.localDB.get(n)).data}catch(e){if(e.status===404){if(!this.canMaterializeDefaults())throw Error(`Cannot read strategy state '${t}' for ${this._username}: the local mirror is unavailable (hydration state '${this._hydration.state}').`);return null}throw e}}async putStrategyState(e,t,n){let r=buildStrategyStateId(e,t),a;try{a=(await this.localDB.get(r))._rev}catch(e){if(e.status!==404)throw e}let o={_id:r,_rev:a,docType:`STRATEGY_STATE`,courseId:e,strategyKey:t,data:n,updatedAt:new Date().toISOString()};await this.localDB.put(o)}async putStudySession(e){try{await this.localDB.put(e)}catch(t){if(t.status===409){let t=await this.localDB.get(e._id);await this.localDB.put({...e,_rev:t._rev})}else throw t}}async getStudySessions(e){let t=getStartAndEndKeys2(e?`${DocTypePrefixes.STUDY_SESSION}::${e}::`:`${DocTypePrefixes.STUDY_SESSION}::`);return(await this.localDB.allDocs({startkey:t.startkey,endkey:t.endkey,include_docs:!0})).rows.map(e=>e.doc).filter(e=>!!e).sort((e,t)=>t.startTime.localeCompare(e.startTime))}async putUserOutcome(e){try{await this.localDB.put(e)}catch(t){if(t.status===409)e._rev=(await this.localDB.get(e._id))._rev,await this.localDB.put(e);else throw t}}async deleteStrategyState(e,t){let n=buildStrategyStateId(e,t);try{let e=await this.localDB.get(n);await this.localDB.remove(e)}catch(e){if(e.status===404)return;throw e}}},_defineProperty(e,`_instance`,void 0),_defineProperty(e,`_initialized`,!1),_defineProperty(e,`DOC_IDS`,{CONFIG:`CONFIG`,COURSE_REGISTRATIONS:`CourseRegistrations`,CLASSROOM_REGISTRATIONS:`ClassroomRegistrations`}),_defineProperty(e,`designDocs`,[{_id:`_design/reviewCards`,views:{reviewCards:{map:`function (doc) {
|
|
348
|
+
if (doc._id && doc._id.indexOf('card_review') === 0 && doc.courseId && doc.cardId) {
|
|
349
|
+
emit(doc._id, doc.courseId + '-' + doc.cardId);
|
|
350
|
+
}
|
|
351
|
+
}`}}}]),e),userCoursesDoc=`CourseRegistrations`,userClassroomsDoc=`ClassroomRegistrations`}}),init_common=__esm({"src/impl/common/index.ts"(){init_SyncStrategy(),init_BaseUserDB(),init_userDBHelpers()}}),PouchDataLayerProvider_exports={};__export(PouchDataLayerProvider_exports,{CouchDataLayerProvider:()=>CouchDataLayerProvider});var CouchDataLayerProvider,init_PouchDataLayerProvider=__esm({"src/impl/couch/PouchDataLayerProvider.ts"(){init_logger(),init_dataDirectory(),init_auth(),init_adminDB2(),init_classroomDB2(),init_courseDB(),init_CourseSyncService(),init_common(),init_CouchDBSyncStrategy(),CouchDataLayerProvider=class{constructor(e){_defineProperty(this,`initialized`,!1),_defineProperty(this,`userDB`,void 0),_defineProperty(this,`currentUsername`,``),_defineProperty(this,`_courseIDs`,[]),e&&(this._courseIDs=e)}async initialize(){if(!this.initialized){if(typeof process<`u`&&process.versions!=null&&process.versions.node!=null){logger.info(`CouchDataLayerProvider: Running in Node.js environment, creating guest UserDB for testing.`),await initializeDataDirectory();let e=new CouchDBSyncStrategy;this.userDB=await BaseUser.instance(e)}else{let e=new CouchDBSyncStrategy;this.userDB=await BaseUser.instance(e),this.currentUsername=this.userDB.getUsername(),logger.debug(`Current username: ${this.currentUsername}`)}this.initialized=!0}}async teardown(){this.initialized=!1}getUserDB(){return this.userDB}getCourseDB(e){let t=CourseSyncService.getInstance().getLocalDB(e);return new CourseDB(e,async()=>this.getUserDB(),t??void 0)}async ensureCourseSynced(e,t){return CourseSyncService.getInstance().ensureSynced(e,t)}getCoursesDB(){return new CoursesDB(this._courseIDs)}async getClassroomDB(e,t){return t===`student`?await StudentClassroomDB.factory(e,this.getUserDB()):await TeacherClassroomDB.factory(e)}getAdminDB(){return new AdminDB}async createUserReaderForUser(e){let t=await getLoggedInUsername();if(t!==`admin`)throw Error(`Unauthorized: Only admin users can access other users' data`);logger.info(`Admin user '${t}' requesting UserDBReader for '${e}'`);let n=new CouchDBSyncStrategy;return await BaseUser.instance(n,e)}isReadOnly(){return!1}}}}),pathUtils,nodeFS3,StaticDataUnpacker,init_StaticDataUnpacker=__esm({"src/impl/static/StaticDataUnpacker.ts"(){init_logger(),init_core(),pathUtils={isAbsolute:e=>!!(/^[a-zA-Z]:[\\/]/.test(e)||/^\\\\/.test(e)||e.startsWith(`/`))},nodeFS3=null;try{typeof window>`u`&&typeof process<`u`&&process.versions?.node&&(nodeFS3=eval(`require`)(`fs`))}catch{}StaticDataUnpacker=class{constructor(e,t){_defineProperty(this,`manifest`,void 0),_defineProperty(this,`basePath`,void 0),_defineProperty(this,`documentCache`,new Map),_defineProperty(this,`chunkCache`,new Map),_defineProperty(this,`indexCache`,new Map),this.manifest=e,this.basePath=t}async getDocument(e){if(this.documentCache.has(e)){let t=this.documentCache.get(e);return await this.hydrateAttachments(t)}let t=await this.findChunkForDocument(e);if(!t)throw logger.error(`Document ${e} not found in any chunk. Available chunks:`,this.manifest.chunks.map(e=>`${e.id} (${e.docType}): ${e.startKey} - ${e.endKey}`)),Error(`Document ${e} not found in any chunk`);if(await this.loadChunk(t.id),this.documentCache.has(e)){let t=this.documentCache.get(e);return await this.hydrateAttachments(t)}throw logger.error(`Document ${e} not found in chunk ${t.id}`),Error(`Document ${e} not found in chunk ${t.id}`)}async getAllDocumentsByPrefix(e){let t=this.manifest.chunks.filter(t=>{let n=e+``;return t.startKey<=n&&t.endKey>=e});if(t.length===0)return logger.debug(`[StaticDataUnpacker] No chunks found for prefix: ${e}`),[];await Promise.all(t.map(e=>this.loadChunk(e.id)));let n=[];for(let[t,r]of this.documentCache.entries())t.startsWith(e)&&n.push(await this.hydrateAttachments(r));return logger.debug(`[StaticDataUnpacker] Found ${n.length} documents with prefix: ${e}`),n}async queryByElo(e,t=25){let n=await this.loadIndex(`elo`);if(!n||!n.sorted)return logger.warn(`ELO index not found or malformed, returning empty results`),[];let r=n.sorted,a=0,o=0,s=r.length-1;for(;o<=s;){let t=Math.floor((o+s)/2);r[t].elo<e?o=t+1:s=t-1}a=o;let c=[],l=Math.floor(t/2);for(let e=Math.max(0,a-l);e<a&&c.length<t;e++)c.push(r[e].cardId);for(let e=a;e<r.length&&c.length<t;e++)c.push(r[e].cardId);return c}async getTagsIndex(){try{return await this.loadIndex(`tags`)}catch{return{byCard:{},byTag:{}}}}getDocTypeFromId(e){for(let t in DocTypePrefixes){let n=DocTypePrefixes[t];if(e.startsWith(`${n}-`))return t}}async findChunkForDocument(e){let t=this.getDocTypeFromId(e);if(t){let n=this.manifest.chunks.filter(e=>e.docType===t);for(let t of n)if(e>=t.startKey&&e<=t.endKey&&await this.verifyDocumentInChunk(e,t))return t}else{for(let t of this.manifest.chunks)if(e>=t.startKey&&e<=t.endKey&&await this.verifyDocumentInChunk(e,t))return t;let t=this.manifest.chunks.filter(e=>e.docType!==`CARD`&&e.docType!==`DISPLAYABLE_DATA`&&e.docType!==`TAG`);for(let n of t)if(e>=n.startKey&&e<=n.endKey&&await this.verifyDocumentInChunk(e,n))return n;return}}async verifyDocumentInChunk(e,t){try{return await this.loadChunk(t.id),this.documentCache.has(e)}catch{return!1}}async loadChunk(e){if(this.chunkCache.has(e))return;let t=this.manifest.chunks.find(t=>t.id===e);if(!t)throw Error(`Chunk ${e} not found in manifest`);try{let n=`${this.basePath}/${t.path}`;logger.debug(`Loading chunk from ${n}`);let r;if(this.isLocalPath(n)&&nodeFS3){let e=await nodeFS3.promises.readFile(n,`utf8`);r=JSON.parse(e)}else{let t=await fetch(n);if(!t.ok)throw Error(`Failed to fetch chunk ${e}: ${t.status} ${t.statusText}`);r=await t.json()}this.chunkCache.set(e,r);for(let e of r)e._id&&this.documentCache.set(e._id,e);logger.debug(`Loaded ${r.length} documents from chunk ${e}`)}catch(t){throw logger.error(`Failed to load chunk ${e}:`,t),t}}async loadIndex(e){if(this.indexCache.has(e))return this.indexCache.get(e);let t=this.manifest.indices.find(t=>t.name===e);if(!t)throw Error(`Index ${e} not found in manifest`);try{let n=`${this.basePath}/${t.path}`;logger.debug(`Loading index from ${n}`);let r;if(this.isLocalPath(n)&&nodeFS3){let e=await nodeFS3.promises.readFile(n,`utf8`);r=JSON.parse(e)}else{let t=await fetch(n);if(!t.ok)throw Error(`Failed to fetch index ${e}: ${t.status} ${t.statusText}`);r=await t.json()}return this.indexCache.set(e,r),logger.debug(`Loaded index ${e}`),r}catch(t){throw logger.error(`Failed to load index ${e}:`,t),t}}async getRawDocument(e){if(this.documentCache.has(e))return this.documentCache.get(e);let t=await this.findChunkForDocument(e);if(!t)throw logger.error(`Document ${e} not found in any chunk. Available chunks:`,this.manifest.chunks.map(e=>`${e.id} (${e.docType}): ${e.startKey} - ${e.endKey}`)),Error(`Document ${e} not found in any chunk`);if(await this.loadChunk(t.id),this.documentCache.has(e))return this.documentCache.get(e);throw logger.error(`Document ${e} not found in chunk ${t.id}`),Error(`Document ${e} not found in chunk ${t.id}`)}getAttachmentUrl(e,t){return`${this.basePath}/attachments/${e}/${t}`}async getAttachmentPath(e,t){try{let n=await this.getRawDocument(e);if(n._attachments&&n._attachments[t]){let e=n._attachments[t];if(e.path)return`${this.basePath}/${e.path}`}return null}catch{return null}}async getAttachmentBlob(e,t){let n=await this.getAttachmentPath(e,t);if(!n)return null;try{if(this.isLocalPath(n)&&nodeFS3)return await nodeFS3.promises.readFile(n);{let r=await fetch(n);if(!r.ok)throw Error(`Failed to fetch attachment ${e}/${t}: ${r.status} ${r.statusText}`);return await r.blob()}}catch(n){return logger.error(`Failed to load attachment ${e}/${t}:`,n),null}}async hydrateAttachments(e){let t=e;if(!t._attachments)return e;let n=JSON.parse(JSON.stringify(e));for(let[e,r]of Object.entries(t._attachments)){let a=r;if(a.path)try{let r=await this.getAttachmentBlob(t._id,e);r?typeof window<`u`&&window.URL?n._attachments[e]={...a,data:r,stub:!1}:n._attachments[e]={...a,buffer:r}:logger.warn(`[hydrateAttachments] getAttachmentBlob returned null for ${t._id}/${e}. Skipping hydration for this attachment.`)}catch(n){logger.warn(`[hydrateAttachments] Failed to hydrate attachment ${t._id}/${e}:`,n)}else logger.debug(`[hydrateAttachments] Attachment ${e} for doc ${t._id} has no path. Skipping blob conversion.`)}return n}clearCaches(){this.documentCache.clear(),this.chunkCache.clear(),this.indexCache.clear()}getCacheStats(){return{documents:this.documentCache.size,chunks:this.chunkCache.size,indices:this.indexCache.size}}isLocalPath(e){return!e.startsWith(`http://`)&&!e.startsWith(`https://`)&&(pathUtils.isAbsolute(e)||e.startsWith(`./`)||e.startsWith(`../`))}}}}),StaticCourseDB,init_courseDB2=__esm({"src/impl/static/courseDB.ts"(){init_types_legacy(),init_logger(),init_defaults(),init_PipelineAssembler(),StaticCourseDB=class{constructor(e,t,n,r){_defineProperty(this,`_pendingHints`,null),this.courseId=e,this.unpacker=t,this.userDB=n,this.manifest=r}getCourseID(){return this.courseId}async getCourseConfig(){if(this.manifest.courseConfig!=null)return this.manifest.courseConfig;throw Error(`Course config not found for course ${this.courseId}`)}async updateCourseConfig(e){throw Error(`Cannot update course config in static mode`)}async getCourseInfo(){return{cardCount:this.manifest.chunks.filter(e=>e.docType===`CARD`).reduce((e,t)=>e+t.documentCount,0),registeredUsers:0}}async getCourseDoc(e,t){return this.unpacker.getDocument(e)}async getCourseDocs(e,t){let n=await Promise.all(e.map(async e=>{try{return{id:e,key:e,value:{rev:`1-static`},doc:await this.unpacker.getDocument(e)}}catch{return{key:e,error:`not_found`}}}));return{total_rows:e.length,offset:0,rows:n}}async getCardsByELO(e,t){return(await this.unpacker.queryByElo(e,t||25)).map(e=>{let[t,n,r]=e.split(`-`);return{courseID:t,cardID:n,elo:r?parseInt(r):void 0}})}async getCardEloData(e){return await Promise.all(e.map(async e=>{try{return(await this.unpacker.getDocument(e)).elo||{global:{score:1e3,count:0},tags:{},misc:{}}}catch{return{global:{score:1e3,count:0},tags:{},misc:{}}}}))}async updateCardElo(e,t){return{ok:!0,id:e,rev:`1-static`}}async getCardsCenteredAtELO(e,t){let n=typeof e.elo==`number`?e.elo:1e3;if(e.elo===`user`)try{let e=(await this.userDB.getCourseRegistrationsDoc()).courses.find(e=>e.courseID===this.courseId);e&&typeof e.elo==`object`&&(n=e.elo.global.score)}catch{n=1e3}else e.elo===`random`&&(n=800+Math.random()*400);let r=(await this.unpacker.queryByElo(n,e.limit*2)).map(e=>({cardID:e,courseID:this.courseId}));return t&&(r=r.filter(t)),r.slice(0,e.limit).map(e=>({status:`new`,cardID:e.cardID,contentSourceType:`course`,contentSourceID:this.courseId,courseID:this.courseId}))}async getAppliedTags(e){try{let t=await this.unpacker.getTagsIndex(),n=t.byCard[e]||[],r=await Promise.all(n.map(async n=>{let r=`TAG-${n}`;try{let t=await this.unpacker.getDocument(r);return{id:r,key:e,value:{name:t.name,snippet:t.snippet,count:t.taggedCards?.length||0}}}catch(a){if(a&&a.status===404)logger.warn(`Tag document not found for ${n}, creating stub`);else throw logger.error(`Error getting tag document for ${n}:`,a),a;return{id:r,key:e,value:{name:n,snippet:`Tag: ${n}`,count:t.byTag[n]?.length||0}}}}));return{total_rows:r.length,offset:0,rows:r}}catch(t){return logger.error(`Error getting applied tags for card ${e}:`,t),{total_rows:0,offset:0,rows:[]}}}async getAppliedTagsBatch(e){let t=await this.unpacker.getTagsIndex(),n=new Map;for(let r of e)n.set(r,t.byCard[r]||[]);return n}async getAllCardIds(){let e=await this.unpacker.getTagsIndex();return Object.keys(e.byCard)}async addTagToCard(e,t){throw Error(`Cannot modify tags in static mode`)}async removeTagFromCard(e,t){throw Error(`Cannot modify tags in static mode`)}async createTag(e){throw Error(`Cannot create tags in static mode`)}async getTag(e){return this.unpacker.getDocument(`TAG-${e}`)}async updateTag(e){throw Error(`Cannot update tags in static mode`)}async getCourseTagStubs(){try{let e=await this.unpacker.getTagsIndex();if(!e||!e.byTag)return logger.warn(`Tags index not found or empty`),{total_rows:0,offset:0,rows:[]};let t=Object.keys(e.byTag),n=await Promise.all(t.map(async t=>{let n=e.byTag[t]||[],r=`TAG-${t}`;try{return{id:r,key:r,value:{rev:`1-static`},doc:await this.unpacker.getDocument(r)}}catch(e){if(e&&e.status===404)return logger.warn(`Tag document not found for ${t}, creating stub`),{id:r,key:r,value:{rev:`1-static`},doc:{_id:r,_rev:`1-static`,course:this.courseId,docType:`TAG`,name:t,snippet:`Tag: ${t}`,wiki:``,taggedCards:n,author:`system`}};throw logger.error(`Error getting tag document for ${t}:`,e),e}}));return{total_rows:n.length,offset:0,rows:n}}catch(e){return logger.error(`Failed to get course tag stubs:`,e),{total_rows:0,offset:0,rows:[]}}}async addNote(e,t,n,r,a,o,s){return{status:Status.error,message:`Cannot add notes in static mode`}}async removeCard(e){throw Error(`Cannot remove cards in static mode`)}async getInexperiencedCards(){return[]}async getNavigationStrategy(e){try{return await this.unpacker.getDocument(e)}catch(t){throw logger.error(`[static/courseDB] Strategy ${e} not found: ${t}`),t}}async getAllNavigationStrategies(){let e=DocTypePrefixes.NAVIGATION_STRATEGY;try{return await this.unpacker.getAllDocumentsByPrefix(e)}catch(e){return logger.warn(`[static/courseDB] Error loading navigation strategies: ${e}`),[]}}async addNavigationStrategy(e){throw Error(`Cannot add navigation strategies in static mode`)}async updateNavigationStrategy(e,t){throw Error(`Cannot update navigation strategies in static mode`)}async createNavigator(e){try{let t=await this.getAllNavigationStrategies();if(t.length===0)return logger.debug(`[static/courseDB] No strategy documents found, using default Pipeline(Composite(ELO, SRS), [eloDistanceFilter])`),createDefaultPipeline(e,this);let{pipeline:n,generatorStrategies:r,filterStrategies:a,warnings:o}=await new PipelineAssembler().assemble({strategies:t,user:e,course:this});for(let e of o)logger.warn(`[PipelineAssembler] ${e}`);return n?(logger.debug(`[static/courseDB] Using assembled pipeline with ${r.length} generator(s) and ${a.length} filter(s)`),n):(logger.debug(`[static/courseDB] Pipeline assembly failed, using default pipeline`),createDefaultPipeline(e,this))}catch(e){throw logger.error(`[static/courseDB] Error creating navigator: ${e}`),e}}setEphemeralHints(e){this._pendingHints=e}async getWeightedCards(e){try{let t=await this.createNavigator(this.userDB);return this._pendingHints&&(t.setEphemeralHints(this._pendingHints),this._pendingHints=null),t.getWeightedCards(e)}catch(e){throw logger.error(`[static/courseDB] Error getting weighted cards: ${e}`),e}}getAttachmentUrl(e,t){return this.unpacker.getAttachmentUrl(e,t)}async getAttachmentBlob(e,t){return this.unpacker.getAttachmentBlob(e,t)}async searchCards(e){return[]}async find(e){return{docs:[],warning:`Find operations not supported in static mode`}}}}}),StaticCoursesDB,init_coursesDB=__esm({"src/impl/static/coursesDB.ts"(){init_logger(),StaticCoursesDB=class{constructor(e,t){this.manifests=e,this.dependencyNameToCourseId=t}async getCourseConfig(e){let t=this.manifests[e];if(!t&&this.dependencyNameToCourseId){let n=this.dependencyNameToCourseId.get(e);n&&(t=this.manifests[n])}if(!t)throw logger.warn(`Course manifest for ${e} not found`),Error(`Course ${e} not found`);if(t.courseConfig)return t.courseConfig;throw logger.warn(`Course config not found in manifest for course ${e}`),Error(`Course config not found for course ${e}`)}async getCourseList(){return Object.keys(this.manifests).map(e=>({courseID:e,name:this.manifests[e].courseName}))}async disambiguateCourse(e,t){logger.warn(`Cannot disambiguate courses in static mode`)}}}}),NoOpSyncStrategy,init_NoOpSyncStrategy=__esm({"src/impl/static/NoOpSyncStrategy.ts"(){init_common(),NoOpSyncStrategy=class{constructor(){_defineProperty(this,`currentUsername`,accomodateGuest().username)}setupRemoteDB(e){return getLocalUserDB(e)}getWriteDB(e){return getLocalUserDB(e)}startSync(e,t){}stopSync(){}canCreateAccount(){return!1}canAuthenticate(){return!1}async createAccount(e,t){throw Error(`Account creation not supported in static mode. Use local account switching instead.`)}async authenticate(e,t){throw Error(`Remote authentication not supported in static mode. Use local account switching instead.`)}async logout(){return this.currentUsername=accomodateGuest().username,{ok:!0}}async getCurrentUsername(){return this.currentUsername}setCurrentUsername(e){this.currentUsername=e}}}}),StaticDataLayerProvider_exports={};__export(StaticDataLayerProvider_exports,{StaticDataLayerProvider:()=>StaticDataLayerProvider});var StaticDataLayerProvider,init_StaticDataLayerProvider=__esm({"src/impl/static/StaticDataLayerProvider.ts"(){init_logger(),init_StaticDataUnpacker(),init_courseDB2(),init_coursesDB(),init_common(),init_NoOpSyncStrategy(),StaticDataLayerProvider=class{constructor(e){_defineProperty(this,`config`,void 0),_defineProperty(this,`initialized`,!1),_defineProperty(this,`courseUnpackers`,new Map),_defineProperty(this,`manifests`,{}),_defineProperty(this,`dependencyNameToCourseId`,new Map),this.config={localStoragePrefix:e.localStoragePrefix||`skuilder-static`,rootManifest:e.rootManifest||{dependencies:{}},rootManifestUrl:e.rootManifestUrl||`/`}}async resolveCourseDependencies(){logger.info(`[StaticDataLayerProvider] Starting course dependency resolution...`);let e=this.config.rootManifest;for(let[t,n]of Object.entries(e.dependencies||{}))try{logger.debug(`[StaticDataLayerProvider] Resolving dependency: ${t} from ${n}`);let e=new URL(n,this.config.rootManifestUrl).href,r=await fetch(e);if(!r.ok)throw Error(`Failed to fetch course manifest for ${t}`);let a=await r.json();if(a.content&&a.content.manifest){let n=new URL(`.`,e).href,r=new URL(a.content.manifest,e).href,o=await fetch(r);if(!o.ok)throw Error(`Failed to fetch final content manifest for ${t} at ${r}`);let s=await o.json(),c=s.courseId||s.courseConfig?.courseID;if(!c)throw Error(`Course manifest for ${t} missing courseId`);this.manifests[c]=s;let l=new StaticDataUnpacker(s,n);this.courseUnpackers.set(c,l),this.dependencyNameToCourseId.set(t,c),logger.info(`[StaticDataLayerProvider] Successfully resolved and prepared course: ${t} (courseId: ${c})`)}}catch(e){logger.error(`[StaticDataLayerProvider] Failed to resolve dependency ${t}:`,e)}logger.info(`[StaticDataLayerProvider] Course dependency resolution complete.`)}async initialize(){this.initialized||(logger.info(`Initializing static data layer provider`),await this.resolveCourseDependencies(),this.initialized=!0)}async teardown(){this.courseUnpackers.clear(),this.initialized=!1}getUserDB(){let e=new NoOpSyncStrategy;return BaseUser.Dummy(e)}getCourseDB(e){let t=this.courseUnpackers.get(e),n=e;if(!t){let r=this.dependencyNameToCourseId.get(e);r&&(t=this.courseUnpackers.get(r),n=r)}if(!t)throw Error(`Course ${e} not found or failed to initialize in static data layer.`);let r=this.manifests[n];return new StaticCourseDB(n,t,this.getUserDB(),r)}getCoursesDB(){return new StaticCoursesDB(this.manifests,this.dependencyNameToCourseId)}async getClassroomDB(e,t){throw Error(`Classrooms not supported in static mode`)}getAdminDB(){throw Error(`Admin functions not supported in static mode`)}async createUserReaderForUser(e){return logger.warn(`StaticDataLayerProvider: Multi-user access not supported in static mode`),logger.warn(`Request: trying to access data for ${e}`),logger.warn(`Returning current user's data instead`),this.getUserDB()}isReadOnly(){return!0}}}});async function initializeDataLayer(e){if(dataLayerInstance)return logger.warn(`Data layer already initialized. Returning existing instance.`),dataLayerInstance;if(await initializeNavigatorRegistry(),e.options.localStoragePrefix&&(ENV.LOCAL_STORAGE_PREFIX=e.options.localStoragePrefix),e.type===`couch`){if(!e.options.COUCHDB_SERVER_URL||!e.options.COUCHDB_SERVER_PROTOCOL)throw Error(`Missing CouchDB server URL or protocol`);if(ENV.COUCHDB_SERVER_PROTOCOL=e.options.COUCHDB_SERVER_PROTOCOL,ENV.COUCHDB_SERVER_URL=e.options.COUCHDB_SERVER_URL,ENV.COUCHDB_USERNAME=e.options.COUCHDB_USERNAME,ENV.COUCHDB_PASSWORD=e.options.COUCHDB_PASSWORD,e.options.courseSync){let{CourseSyncService:t}=await Promise.resolve().then(()=>(init_CourseSyncService(),CourseSyncService_exports));t.getInstance().configure(e.options.courseSync)}if(e.options.COUCHDB_PASSWORD&&e.options.COUCHDB_USERNAME&&typeof window<`u`){let{CouchDBSyncStrategy:t}=await Promise.resolve().then(()=>(init_CouchDBSyncStrategy(),CouchDBSyncStrategy_exports)),n=new t,r=await(await BaseUser.instance(n,e.options.COUCHDB_USERNAME)).login(e.options.COUCHDB_USERNAME,e.options.COUCHDB_PASSWORD);r.ok?logger.info(`Successfully authenticated as ${e.options.COUCHDB_USERNAME}`):logger.warn(`Authentication failed: ${r.error}`)}let{CouchDataLayerProvider:t}=await Promise.resolve().then(()=>(init_PouchDataLayerProvider(),PouchDataLayerProvider_exports));dataLayerInstance=new t(e.options.COURSE_IDS)}else if(e.type===`static`){let{StaticDataLayerProvider:t}=await Promise.resolve().then(()=>(init_StaticDataLayerProvider(),StaticDataLayerProvider_exports));dataLayerInstance=new t(e.options)}else throw Error(`Unknown data layer type: ${e.type}`);return await dataLayerInstance.initialize(),dataLayerInstance}function getDataLayer(){if(!dataLayerInstance)throw Error(`Data layer not initialized. Call initializeDataLayer first.`);return dataLayerInstance}async function _resetDataLayer(){dataLayerInstance&&await dataLayerInstance.teardown(),dataLayerInstance=null}var NOT_SET,ENV,dataLayerInstance,init_factory=__esm({"src/factory.ts"(){init_common(),init_logger(),init_navigators(),NOT_SET=`NOT_SET`,ENV={COUCHDB_SERVER_PROTOCOL:NOT_SET,COUCHDB_SERVER_URL:NOT_SET,LOCAL_STORAGE_PREFIX:``},dataLayerInstance=null}});function isReview(e){return e.status===`review`||e.status===`failed-review`||`reviewID`in e}async function getStudySource(e,t){return e.type===`classroom`?await StudentClassroomDB.factory(e.id,t):hasActiveFilter(e.tagFilter)?new TagFilteredContentSource(e.id,e.tagFilter,t):getDataLayer().getCourseDB(e.id)}var init_contentSource=__esm({"src/core/interfaces/contentSource.ts"(){init_factory(),init_classroomDB2(),init_TagFilteredContentSource()}}),init_courseDB3=__esm({"src/core/interfaces/courseDB.ts"(){}}),init_dataLayerProvider=__esm({"src/core/interfaces/dataLayerProvider.ts"(){}}),init_userDB=__esm({"src/core/interfaces/userDB.ts"(){}}),init_interfaces=__esm({"src/core/interfaces/index.ts"(){init_adminDB(),init_classroomDB(),init_contentSource(),init_courseDB3(),init_dataLayerProvider(),init_userDB()}}),init_user=__esm({"src/core/types/user.ts"(){}});function buildStrategyStateId(e,t){return`STRATEGY_STATE::${e}::${t}`}var init_strategyState=__esm({"src/core/types/strategyState.ts"(){}}),init_userOutcome=__esm({"src/core/types/userOutcome.ts"(){}}),HYDRATION_MARKER_ID,init_hydration=__esm({"src/core/types/hydration.ts"(){HYDRATION_MARKER_ID=`_local/hydration`}});async function importParsedCards(e,t,n){let r=[];for(let a of e)try{let e=await processCard(a,t,n);r.push(e)}catch(e){logger.error(`Error processing card:`,e);let t=a.markdown;a.tags&&a.tags.length>0&&(t+=`
|
|
352
|
+
tags: ${a.tags.join(`, `)}`),a.elo!==void 0&&(t+=`
|
|
353
|
+
elo: ${a.elo}`),r.push({originalText:t,status:`error`,message:`Error processing card: ${e instanceof Error?e.message:`Unknown error`}`})}return r}async function processCard(e,t,n){let{markdown:r,tags:a,elo:o}=e,s=r;a.length>0&&(s+=`
|
|
354
|
+
tags: ${a.join(`, `)}`),o!==void 0&&(s+=`
|
|
355
|
+
elo: ${o}`);let c={Input:r,Uploads:[]},l={};for(let e of a)l[e]={score:o||0,count:1};try{let e=await t.addNote(n.courseCode,n.dataShape,c,n.userName,a,void 0,o?{global:{score:o,count:1},tags:l,misc:{}}:void 0);return e.status===Status.ok?{originalText:s,status:`success`,message:`Card added successfully.`,cardId:e.id?e.id:`(unknown)`}:{originalText:s,status:`error`,message:e.message||`Failed to add card to database. Unknown error.`}}catch(e){return logger.error(`Error adding note:`,e),{originalText:s,status:`error`,message:`Error adding card: ${e instanceof Error?e.message:`Unknown error`}`}}}function validateProcessorConfig(e){return e.dataShape?e.courseCode?e.userName?{isValid:!0}:{isValid:!1,errorMessage:`No user name provided for card processing`}:{isValid:!1,errorMessage:`No course code provided for card processing`}:{isValid:!1,errorMessage:`No data shape provided for card processing`}}var init_cardProcessor=__esm({"src/core/bulkImport/cardProcessor.ts"(){init_logger()}}),init_types5=__esm({"src/core/bulkImport/types.ts"(){}}),init_bulkImport=__esm({"src/core/bulkImport/index.ts"(){init_cardProcessor(),init_types5()}});function getUserDB(){try{return getDataLayer().getUserDB()}catch{return logger.info(`[UserDB Debug] Data layer not initialized yet.`),null}}function getRawDB(){let e=getUserDB();return e?e.localDB||(logger.info(`[UserDB Debug] Unable to access raw database instance.`),null):null}function formatTimestamp(e){return new Date(e).toLocaleString()}function mountUserDBDebugger(){if(typeof window>`u`)return;let e=window;e.skuilder=e.skuilder||{},e.skuilder.userdb=userDBDebugAPI}var userDBDebugAPI,init_UserDBDebugger=__esm({"src/core/UserDBDebugger.ts"(){init_logger(),init_factory(),init_types_legacy(),init_userDBHelpers(),userDBDebugAPI={showUser(){let e=getUserDB();e&&(console.group(`👤 User Information`),logger.info(`Username: ${e.getUsername()}`),logger.info(`Logged in: ${e.isLoggedIn()?`Yes ✅`:`No (Guest) ❌`}`),e.getConfig().then(e=>{logger.info(`Configuration:`),logger.info(JSON.stringify(e,null,2))}).catch(e=>{logger.info(`Error loading config: ${e.message}`)}).finally(()=>{console.groupEnd()}))},async showScheduledReviews(e){let t=getUserDB();if(!t){logger.info(`[UserDB Debug] Data layer not available`);return}logger.info(`[UserDB Debug] Fetching pending reviews${e?` for course: ${e}`:``}...`);try{let n=await t.getPendingReviews(e);if(logger.info(`[UserDB Debug] Got ${n.length} reviews`),console.group(`\u{1F4C5} Scheduled Reviews${e?` (${e})`:``}`),logger.info(`Total: ${n.length}`),n.length>0){let e=new Map;for(let t of n)e.has(t.courseId)||e.set(t.courseId,[]),e.get(t.courseId).push(t);for(let[t,n]of e){console.group(`Course: ${t} (${n.length} reviews)`);let e=n.sort((e,t)=>{let n=typeof e.reviewTime==`string`?e.reviewTime:e.reviewTime.toISOString(),r=typeof t.reviewTime==`string`?t.reviewTime:t.reviewTime.toISOString();return new Date(n).getTime()-new Date(r).getTime()});for(let t of e.slice(0,10)){let e=typeof t.reviewTime==`string`?t.reviewTime:t.reviewTime.toISOString();logger.info(` ${t.cardId.slice(0,12)}... @ ${formatTimestamp(e)} [${t.scheduledFor}/${t.schedulingAgentId}]`)}e.length>10&&logger.info(` ... and ${e.length-10} more`),console.groupEnd()}}console.groupEnd()}catch(e){logger.info(`Error loading scheduled reviews: ${e.message}`)}},async showCourseRegistrations(){let e=getUserDB();if(e)try{let t=await e.getActiveCourses();console.group(`📚 Course Registrations`),logger.info(`Total: ${t.length}`),t.length>0&&console.table(t.map(e=>({courseId:e.courseID,status:e.status||`active`,elo:typeof e.elo==`number`?e.elo.toFixed(0):e.elo?.global?.score?.toFixed(0)||`N/A`}))),console.groupEnd()}catch(e){logger.info(`Error loading course registrations: ${e.message}`)}},async showCardHistory(e){let t=getRawDB();if(t)try{let n=(await filterAllDocsByPrefix2(t,DocTypePrefixes.CARDRECORD)).rows.filter(t=>t.doc&&t.doc.cardID===e).map(e=>e.doc);if(console.group(`\u{1F3B4} Card History: ${e}`),logger.info(`Total interactions: ${n.length}`),n.length>0){let e=n.sort((e,t)=>new Date(t.timestamp).getTime()-new Date(e.timestamp).getTime());console.table(e.slice(0,20).map(e=>({time:formatTimestamp(e.timestamp),outcome:e.outcome||`N/A`,duration:e.duration?`${(e.duration/1e3).toFixed(1)}s`:`N/A`,courseId:e.courseId}))),e.length>20&&logger.info(`... and ${e.length-20} more interactions`)}console.groupEnd()}catch(e){logger.info(`Error loading card history: ${e.message}`)}},async queryByType(e,t=50){let n=getRawDB();if(n)try{let r=DocTypePrefixes[DocType[e]];if(!r){logger.info(`Unknown document type: ${e}`);return}let a=await filterAllDocsByPrefix2(n,r);if(console.group(`\u{1F4C4} Documents: ${e}`),logger.info(`Total: ${a.rows.length}`),logger.info(`Prefix: ${r}`),a.rows.length>0){logger.info(`Sample documents:`);let e=a.rows.slice(0,Math.min(t,a.rows.length));for(let t of e)logger.info(`
|
|
356
|
+
${t.id}:`),logger.info(JSON.stringify(t.doc,null,2));a.rows.length>t&&logger.info(`
|
|
357
|
+
... and ${a.rows.length-t} more documents`)}console.groupEnd()}catch(e){logger.info(`Error querying documents: ${e.message}`)}},async dbInfo(){let e=getRawDB();if(e)try{let t=await e.info();console.group(`ℹ️ Database Information`),logger.info(`Database name: ${t.db_name}`),logger.info(`Total documents: ${t.doc_count}`),logger.info(`Update sequence: ${t.update_seq}`),`disk_size`in t&&logger.info(`Disk size: ${(t.disk_size||0)/1024/1024} MB`),logger.info(`
|
|
358
|
+
Document counts by type:`);let n=await e.allDocs({include_docs:!1}),r=new Map;for(let e of n.rows){let t=`other`;for(let[n,r]of Object.entries(DocTypePrefixes))if(e.id.startsWith(r)){t=n;break}r.set(t,(r.get(t)||0)+1)}console.table(Array.from(r.entries()).sort((e,t)=>t[1]-e[1]).map(([e,t])=>({type:e,count:t}))),console.groupEnd()}catch(e){logger.info(`Error getting database info: ${e.message}`)}},listDocTypes(){console.group(`📋 Available Document Types`),logger.info(`Use with queryByType(type):`);for(let[e,t]of Object.entries(DocTypePrefixes))logger.info(` ${e.padEnd(30)} \u2192 prefix: "${t}"`);console.groupEnd()},async export(e=!1){let t=getRawDB(),n=getUserDB();if(!t||!n)return`{}`;try{let r={username:n.getUsername(),loggedIn:n.isLoggedIn(),timestamp:new Date().toISOString()};if(e){let e=await t.allDocs({include_docs:!0});r.documents=e.rows.map(e=>({id:e.id,doc:e.doc})),r.totalDocs=e.rows.length}else{let e=await t.allDocs({include_docs:!1});r.totalDocs=e.rows.length;let n=new Map;for(let t of e.rows){let e=`other`;for(let[n,r]of Object.entries(DocTypePrefixes))if(t.id.startsWith(r)){e=n;break}n.set(e,(n.get(e)||0)+1)}r.docCounts=Object.fromEntries(n)}let a=JSON.stringify(r,null,2);return logger.info(`[UserDB Debug] Database info exported. Copy the returned string or use:`),logger.info(` copy(window.skuilder.userdb.export())`),e||logger.info(` For full content export: window.skuilder.userdb.export(true)`),a}catch(e){return logger.info(`Error exporting database: ${e.message}`),`{}`}},async raw(e){let t=getRawDB();if(t)try{let n=await e(t);logger.info(`[UserDB Debug] Query result:`),logger.info(n)}catch(e){logger.info(`[UserDB Debug] Query error: ${e.message}`)}},help(){logger.info(`
|
|
359
|
+
🔧 UserDB Debug API
|
|
360
|
+
|
|
361
|
+
Commands:
|
|
362
|
+
.showUser() Show current user info and config
|
|
363
|
+
.showScheduledReviews(courseId?) Show scheduled reviews (optionally filter by course)
|
|
364
|
+
.showCourseRegistrations() Show all course registrations
|
|
365
|
+
.showCardHistory(cardId) Show interaction history for a card
|
|
366
|
+
.queryByType(docType, limit?) Query documents by type (e.g., 'SCHEDULED_CARD')
|
|
367
|
+
.listDocTypes() List all available document types
|
|
368
|
+
.dbInfo() Show database info and statistics
|
|
369
|
+
.export(includeContent?) Export database info (true = include all docs)
|
|
370
|
+
.raw(queryFn) Execute raw PouchDB query
|
|
371
|
+
.help() Show this help message
|
|
372
|
+
|
|
373
|
+
Examples:
|
|
374
|
+
window.skuilder.userdb.showUser()
|
|
375
|
+
window.skuilder.userdb.showScheduledReviews('course123')
|
|
376
|
+
window.skuilder.userdb.queryByType('SCHEDULED_CARD', 10)
|
|
377
|
+
window.skuilder.userdb.raw(db => db.allDocs({ limit: 5 }))
|
|
378
|
+
`)}},mountUserDBDebugger()}}),init_core=__esm({"src/core/index.ts"(){init_interfaces(),init_types_legacy(),init_user(),init_strategyState(),init_userOutcome(),init_studySession(),init_hydration(),init_Loggable(),init_util(),init_navigators(),init_bulkImport(),init_orchestration(),init_UserDBDebugger()}});init_core(),init_courseLookupDB(),init_logger();function isDataShapeRegistered(e,t){let n=NameSpacer.getDataShapeString({dataShape:e.name,course:e.course});return t.dataShapes.find(e=>e.name===n)!==void 0}function isDataShapeSchemaAvailable(e,t){let n=NameSpacer.getDataShapeString({dataShape:e.name,course:e.course}),r=t.dataShapes.find(e=>e.name===n);return r!==void 0&&r.serializedZodSchema!==void 0}function isQuestionTypeRegistered(e,t){let n=NameSpacer.getQuestionString({course:e.course,questionType:e.name});return t.questionTypes.some(e=>e.name===n)}function processCustomQuestionsData(e){let t=[],n=[],r=e.courses.map(e=>e.name);return e.questionClasses.forEach(a=>{let o=r.length>0?r[0]:e.meta.packageName;a.dataShapes&&Array.isArray(a.dataShapes)&&a.dataShapes.forEach(e=>{t.push({name:e.name,course:o,dataShape:e})}),n.push({name:a.name,course:o,questionClass:a,dataShapes:a.dataShapes||[],views:a.views||[]})}),{dataShapes:t,questions:n}}function registerDataShape(e,t){let n=NameSpacer.getDataShapeString({dataShape:e.name,course:e.course}),r;try{r=toZodJSON(e.dataShape)}catch(e){logger.warn(`Failed to generate schema for ${n}:`,e),r=void 0}let a=t.dataShapes.findIndex(e=>e.name===n);if(a!==-1){let o=t.dataShapes[a];return o.serializedZodSchema===r?(logger.info(`DataShape '${e.name}' from '${e.course}' already registered with identical schema`),!1):(o.serializedZodSchema?logger.info(`DataShape '${e.name}' from '${e.course}' schema has changed, updating...`):logger.info(`DataShape '${e.name}' from '${e.course}' already registered, but with no schema. Adding schema to existing entry`),t.dataShapes[a]={name:n,questionTypes:o.questionTypes,serializedZodSchema:r},logger.info(`Updated DataShape: ${n}`),!0)}return t.dataShapes.push({name:n,questionTypes:[],serializedZodSchema:r}),logger.info(`Registered DataShape: ${n}`),!0}function registerQuestionType(e,t){if(isQuestionTypeRegistered(e,t))return logger.info(`QuestionType '${e.name}' from '${e.course}' already registered`),!1;let n=NameSpacer.getQuestionString({course:e.course,questionType:e.name}),r=e.views.map(e=>e.name?e.name:`unnamedComponent`),a=e.dataShapes.map(t=>NameSpacer.getDataShapeString({course:e.course,dataShape:t.name}));return t.questionTypes.push({name:n,viewList:r,dataShapeList:a}),e.dataShapes.forEach(r=>{let a=NameSpacer.getDataShapeString({course:e.course,dataShape:r.name});for(let e of t.dataShapes)e.name===a&&e.questionTypes.push(n)}),logger.info(`Registered QuestionType: ${n}`),!0}function removeDataShape(e,t){let n=t.dataShapes.findIndex(t=>t.name===e);return n===-1?(logger.info(`DataShape '${e}' not found in course config`),!1):(t.dataShapes.splice(n,1),t.questionTypes.forEach(t=>{let n=t.dataShapeList.indexOf(e);n!==-1&&t.dataShapeList.splice(n,1)}),logger.info(`Removed DataShape: ${e}`),!0)}function removeQuestionType(e,t){let n=t.questionTypes.findIndex(t=>t.name===e);return n===-1?(logger.info(`QuestionType '${e}' not found in course config`),!1):(t.questionTypes.splice(n,1),t.dataShapes.forEach(t=>{let n=t.questionTypes.indexOf(e);n!==-1&&t.questionTypes.splice(n,1)}),logger.info(`Removed QuestionType: ${e}`),!0)}async function removeCustomQuestionTypes(e,t,n,r){try{logger.info(`Beginning custom question removal`),logger.info(`Removing ${e.length} data shapes and ${t.length} question types`);let a=0;for(let e of t)removeQuestionType(e,n)&&a++;for(let t of e)removeDataShape(t,n)&&a++;logger.info(`Updating course configuration...`);let o=await r.updateCourseConfig(n);if(!o.ok)throw Error(`Failed to update course config: ${JSON.stringify(o)}`);return logger.info(`Custom question removal complete: ${a} items removed`),{success:!0,removedCount:a}}catch(e){let t=e instanceof Error?e.message:String(e);return logger.error(`Custom question removal failed: ${t}`),{success:!1,removedCount:0,errorMessage:t}}}async function registerSeedData(e,t,n){if(e.questionClass.seedData&&Array.isArray(e.questionClass.seedData)){logger.info(`Registering seed data for question: ${e.name}`);try{let r=e.questionClass.seedData.filter(()=>e.dataShapes.length>0).map(r=>t.addNote(e.course,e.dataShapes[0],r,n,[]));await Promise.all(r),logger.info(`Seed data registered for question: ${e.name}`)}catch(t){logger.warn(`Failed to register seed data for question '${e.name}': ${t instanceof Error?t.message:String(t)}`)}}}async function registerBlanksCard(e,t,n,r,a){try{logger.info(`Registering BlanksCard data shapes and question type...`);let o=0,s=`default`;for(let e of t)registerDataShape({name:e.name,course:s,dataShape:e},n)&&o++;let c={name:e.name,course:s,questionClass:{name:e.name,dataShapes:t,views:e.views||[]},dataShapes:t,views:e.views||[]};registerQuestionType(c,n)&&o++,logger.info(`Updating course configuration with BlanksCard...`);let l=await r.updateCourseConfig(n);if(!l.ok)throw Error(`Failed to update course config: ${JSON.stringify(l)}`);return a&&await registerSeedData(c,r,a),logger.info(`BlanksCard registration complete: ${o} items registered`),{success:!0}}catch(e){let t=e instanceof Error?e.message:String(e);return logger.error(`BlanksCard registration failed: ${t}`),{success:!1,errorMessage:t}}}async function registerCustomQuestionTypes(e,t,n,r){try{logger.info(`Beginning custom question registration`),logger.info(`Processing ${e.questionClasses.length} question classes`);let{dataShapes:a,questions:o}=processCustomQuestionsData(e);logger.info(`Found ${a.length} data shapes and ${o.length} questions`);let s=0;logger.info(`Registering data shapes...`);for(let e of a)registerDataShape(e,t)&&s++;logger.info(`Registering question types...`);for(let e of o)registerQuestionType(e,t)&&s++;logger.info(`Updating course configuration...`);let c=await n.updateCourseConfig(t);if(!c.ok)throw Error(`Failed to update course config: ${JSON.stringify(c)}`);if(r){logger.info(`Registering seed data...`);for(let e of o)await registerSeedData(e,n,r)}return logger.info(`Custom question registration complete: ${s} items registered`),{success:!0,registeredCount:s}}catch(e){let t=e instanceof Error?e.message:String(e);return logger.error(`Custom question registration failed: ${t}`),{success:!1,registeredCount:0,errorMessage:t}}}init_study(),init_util2(),init_factory(),init_userDBHelpers();export{getStudySource as $,computeEffectiveWeight as A,removeQuestionType as At,getAppDataDirectory as B,validateMigration as Bt,buildStrategyStateId as C,recordUserOutcome as Ct,clearStaleSessionDebugState as D,registerQuestionType as Dt,clearSrsBacklogDebug as E,registerNavigator as Et,drainCapturedRuns as F,startSessionTracking as Ft,getLapses as G,getCardOrigin as H,validateStaticCourse as Ht,endSessionTracking as I,toggleSessionOverlay as It,getRegisteredNavigatorRole as J,getRegisteredNavigator as K,ensureAppDataDirectory as L,updateLearningState as Lt,computeSpread as M,sessionDebugAPI as Mt,createOrchestrationContext as N,setDebugSessionId as Nt,clearStrategyPressureDebug as O,registerSeedData as Ot,diversityRerank as P,snapshotQueues as Pt,getStreak as Q,getActiveController as R,updateStrategyWeight as Rt,areQuestionRecords as S,recordCardPresentation as St,captureStrategyPressure as T,registerDataShape as Tt,getDataLayer as U,getCardHistoryID as V,validateProcessorConfig as Vt,getDbPath as W,getSrsBacklogDebug as X,getRunsForSession as Y,getStrategyPressureDebug as Z,QuotaRoundRobinMixer as _,mountUserDBDebugger as _t,DIVERSITY_STRENGTH as a,isFilter as at,StaticToCouchDBMigrator as b,pipelineDebugAPI as bt,ENV as c,isQuestionTypeRegistered as ct,HYDRATION_MARKER_ID as d,makeScheduledCardId as dt,hasRegisteredNavigator as et,Loggable as f,makeStudySessionId as ft,Navigators as g,mountSessionDebugger as gt,NavigatorRoles as h,mountPipelineDebugger as ht,DIVERSITY_FLOOR as i,initializeNavigatorRegistry as it,computeOutcomeSignal as j,scoreAccuracyInZone as jt,computeDeviation as k,removeDataShape as kt,FileSystemError as l,isReview as lt,NavigatorRole as m,mountMixerDebugger as mt,CouchDBToStaticPacker as n,initializeDataDirectory as nt,DocType as o,isGenerator as ot,NOT_SET as p,mixerDebugAPI as pt,getRegisteredNavigatorNames as q,CourseLookup as r,initializeDataLayer as rt,DocTypePrefixes as s,isQuestionRecord as st,ContentNavigator as t,importParsedCards as tt,GuestUsername as u,log as ut,REVIEW_TIME_FORMAT2 as v,newInterval as vt,captureMixerRun as w,registerActiveController as wt,TagFilteredContentSource as x,processCustomQuestionsData as xt,SessionController as y,newSessionId as yt,getActivePipeline as z,userDBDebugAPI as zt};
|
|
379
|
+
//# sourceMappingURL=dist-DO_oB9R-.js.map
|