@aiquants/daily-report 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.mjs CHANGED
@@ -1,16 +1,16 @@
1
- var pt=t=>({async getEpoch(e){try{let n=await t?.getClient();if(!n)return 0;let s=await n.get(e);return s?Number(s):0}catch{return 0}},async incrementEpoch(e){try{let n=await t?.getClient();if(!n)return;await n.incr(e)}catch{}}}),Fe=class{constructor(e,n){this.config=e;this.epochStore=n;this.buckets=new Map;this.inFlight=new Map;this.invalidate=e=>{this.buckets.delete(e),this.inFlight.delete(e)};this.maybeRefreshAhead=e=>{let n=e.refreshAheadRatio;if(n===void 0)return;let{cacheKey:s}=e,m=this.buckets.get(s);if(!m)return;let u=e.ttlMsOverride??this.config.defaultTtlMs;if(u-(m.expireAt-Date.now())<u*n||this.inFlight.has(s))return;let p;p=(async()=>{let k=e.epochKey?await this.epochStore.getEpoch(e.epochKey):0,o=await e.fetcher();return this.inFlight.get(s)===p&&this.buckets.set(s,{records:o,expireAt:Date.now()+u,epoch:k}),o})(),this.inFlight.set(s,p),p.catch(()=>{}).finally(()=>{this.inFlight.get(s)===p&&this.inFlight.delete(s)})};this.getOrFetch=async e=>{let{cacheKey:n,forceRefresh:s,snapshot:m}=e,u=this.buckets.get(n);if(s&&(this.buckets.delete(n),this.inFlight.delete(n)),!s&&u&&u.expireAt>Date.now())if(e.epochKey){let p=await this.epochStore.getEpoch(e.epochKey);if(u.epoch===p)return this.maybeRefreshAhead(e),m?u.records.map(k=>structuredClone(k)):u.records;this.buckets.delete(n)}else return this.maybeRefreshAhead(e),m?u.records.map(p=>structuredClone(p)):u.records;if(!s&&this.inFlight.has(n)){let p=await this.inFlight.get(n);return m?p.map(k=>structuredClone(k)):p}let I;I=(async()=>{let p=e.epochKey?await this.epochStore.getEpoch(e.epochKey):0,k=await e.fetcher();if(s||this.inFlight.get(n)===I){let o=Date.now()+(e.ttlMsOverride??this.config.defaultTtlMs);this.buckets.set(n,{records:k,expireAt:o,epoch:p}),this.buckets.size>500&&this.cleanExpired()}return k})(),s||this.inFlight.set(n,I);try{let p=await I;return m?p.map(k=>structuredClone(k)):p}finally{this.inFlight.get(n)===I&&this.inFlight.delete(n)}};this.flush=e=>{this.buckets.delete(e),this.inFlight.delete(e)};this.clearAll=()=>{this.buckets.clear(),this.inFlight.clear()};this.invalidatePrefix=e=>{for(let n of this.buckets.keys())n.startsWith(e)&&this.buckets.delete(n);for(let n of this.inFlight.keys())n.startsWith(e)&&this.inFlight.delete(n)}}cleanExpired(){let e=Date.now();for(let[n,s]of this.buckets.entries())s.expireAt<=e&&this.buckets.delete(n)}};var Kt=/^\d{4}-\d{2}-\d{2}$/,Vt=/^\d{4}\/\d{2}\/\d{2}$/,mt=t=>t<10?`0${t}`:`${t}`,yt=t=>{if(Number.isNaN(t.getTime()))return null;let e=t.getFullYear(),n=mt(t.getMonth()+1),s=mt(t.getDate());return`${e}-${n}-${s}`};var oe=t=>{if(t==null)return null;if(t instanceof Date)return yt(t);let e=t.trim();if(e==="")return null;if(Kt.test(e))return e;if(Vt.test(e))return e.replaceAll("/","-");let n=new Date(e);return yt(n)};var jt=(t,e)=>t.businessDate!==e.businessDate?t.businessDate===null?1:e.businessDate===null||t.businessDate>e.businessDate?-1:1:e.reportHubId-t.reportHubId;var ht=(t,e)=>{let n=t.findIndex(s=>jt({businessDate:s.businessDate,reportHubId:s.reportHubId},e)>0);return n===-1?t.length:n};var ce=(t,e,n=console)=>{let s=m=>typeof m=="string"?[`${e} ${m}`]:[e,m];return{debug:(m,...u)=>{t<=0&&n.debug(...s(m),...u)},info:(m,...u)=>{t<=1&&n.info(...s(m),...u)},warn:(m,...u)=>{t<=2&&n.warn(...s(m),...u)},error:(m,...u)=>{t<=3&&n.error(...s(m),...u)}}};import{z as l}from"zod";var Jt=l.object({name:l.string().nullish(),affiliation:l.string().nullish()}),Gt=l.object({name:l.string().nullish(),text:l.string().nullish(),color:l.string().nullish()}),Qt=l.object({id:l.number(),name:l.string().nullish(),color:l.string().nullish()}),ft=l.object({id:l.number(),userId:l.string().nullish(),userName:l.string().nullish(),content:l.string().nullish(),createdAt:l.string().nullish(),isMine:l.boolean()}),Xt=l.object({id:l.string(),fileName:l.string(),fileType:l.string().nullable(),fileSize:l.number().nullable(),createdAt:l.string().nullable(),state:l.enum(["present","absent","unknown"])}),We=l.object({reportHubId:l.number(),date:l.string().nullish(),createdAt:l.string().nullish(),author:l.string().nullish(),userId:l.string().nullish(),sourceType:l.string().nullish(),employeeName:l.string().nullish(),updatedBy:l.string().nullish(),updatedAt:l.string().nullish(),category:l.string().nullish(),creationCategory:l.string().nullish(),visitTimeFrom:l.string().nullish(),visitTimeTo:l.string().nullish(),customerName:l.string().nullish(),interviewers:l.array(Jt),subject:l.string().nullish(),content:l.string().nullish(),comments:l.array(Gt),isRead:l.boolean(),isStarred:l.boolean(),labels:l.array(Qt),commentItems:l.array(ft),attachments:l.array(Xt).default([])}),Wt=l.object({type:l.literal("connected")}),qe=l.object({type:l.literal("status-update"),reportHubId:l.number(),statusType:l.enum(["star","read"]),value:l.boolean(),clientTempId:l.string(),recipientRawUserId:l.number().optional()}),Ze=l.string().optional(),et=l.object({type:l.literal("comment-add"),reportHubId:l.number(),comment:ft,clientTempId:l.string(),recipientRawUserId:l.number().optional(),sourceType:Ze}),tt=l.object({type:l.literal("comment-delete"),reportHubId:l.number(),commentId:l.number(),clientTempId:l.string(),recipientRawUserId:l.number().optional(),sourceType:Ze}),rt=l.object({type:l.literal("report-create"),reportHubId:l.number(),report:We,clientTempId:l.string(),recipientRawUserId:l.number().optional()}),nt=l.object({type:l.literal("report-update"),reportHubId:l.number(),report:We,clientTempId:l.string(),recipientRawUserId:l.number().optional()}),at=l.object({type:l.literal("report-publish"),reportHubId:l.number(),report:We,clientTempId:l.string(),recipientRawUserId:l.number().optional()}),st=l.object({type:l.literal("report-delete"),reportHubId:l.number(),clientTempId:l.string(),sourceType:Ze}),bt=l.discriminatedUnion("type",[Wt,qe,et,tt,rt,nt,at,st]);import{createHash as Zt}from"crypto";var it=t=>{let e=JSON.stringify(t);return`"${Zt("sha256").update(e).digest("hex")}"`};var er=ce(1,"[Response]"),he=(t,e,n,s=200,m=er)=>{let u=it(n),I=t.headers.get("If-None-Match");m.info(`[jsonResponseWithETag] ETag: ${u}, If-None-Match: ${I}`);let p=new Headers({"Content-Type":"application/json","Cache-Control":"private, max-age=0, must-revalidate","X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","Content-Security-Policy":"default-src 'none'",ETag:u});return e&&p.append("Set-Cookie",e),t.method==="GET"&&s===200&&I===u?new Response(null,{status:304,headers:p}):new Response(JSON.stringify(n),{status:s,headers:p})};import{EventEmitter as tr}from"events";var Ve=(t,e)=>{let[n,s]=t.split("-").map(Number),[m,u]=e.split("-").map(Number);return n!==m?n<m:s<=u},Ke=class{constructor(e){this.config=e;this._emitter=new tr;this._state="idle";this._refCount=0;this._lastId="$";this._emitter.setMaxListeners(0),this._logger=e.logger??ce(1,"[SSE Reader]")}subscribe(e,n){return this._emitter.on("entry",e),n&&this._emitter.on("error",n),this._refCount++,this._refCount===1&&this._startLoop(),()=>{this._emitter.removeListener("entry",e),n&&this._emitter.removeListener("error",n),this._refCount--,this._refCount<=0&&(this._refCount=0,this._stopLoop())}}async destroy(){this._refCount=0,await this._stopLoop(),this._emitter.removeAllListeners(),this._lastId="$"}async _startLoop(){for(;this._state==="stopping";)await new Promise(e=>setTimeout(e,50));if(this._state!=="running"&&this._refCount!==0){this._state="running";try{this._client=await this.config.redis?.createClient()}catch(e){this._state="idle",this._emitError(e instanceof Error?e:new Error("Failed to create Redis client for SSE reader"));return}if(!this._client){this._state="idle",this._emitError(new Error("Failed to create Redis client for SSE reader"));return}if(this._client.on("error",e=>{this._logger.error("Redis client error:",e)}),this._lastId==="$")try{let e=await this.config.redis?.getClient();if(e){let n=await e.xRevRange(this.config.streamKey,"+","-",{COUNT:1});this._lastId=n.length>0?n[0].id:"0-0"}}catch(e){this._logger.warn("Failed to resolve stream tail anchor; falling back to $:",e)}try{for(;this._state==="running"&&this._client?.isOpen;){let e=await this._client.xRead([{key:this.config.streamKey,id:this._lastId}],{BLOCK:5e3,COUNT:100});if(e)for(let n of e)for(let s of n.messages){this._lastId=s.id;try{let m=s.message?.data?JSON.parse(s.message.data):null,u=m?.type;if((u==="report-create"||u==="report-delete"||u==="report-publish")&&this.config.cache.invalidatePrefix("daily-report:ids"),u==="comment-add"||u==="comment-delete"||u==="status-update"){let I=m?.reportHubId;typeof I=="number"&&(this.config.cache.invalidate(`daily-report:detail:${I}`),this.config.cache.invalidatePrefix(`daily-report:detail:${I}:user:`))}}catch{}this._emitter.emit("entry",{id:s.id,message:s.message})}}}catch(e){!(e?.constructor?.name==="ClientClosedError")&&this._state==="running"&&(this._logger.error("xRead loop error:",e),this._emitError(e instanceof Error?e:new Error(String(e))))}finally{if(this._client?.isOpen)try{await this._client.quit()}catch{}this._client=void 0,this._state="idle",this._refCount>0&&this._startLoop()}}}async _stopLoop(){if(this._state==="running"){if(this._state="stopping",this._client?.isOpen)try{await this._client.quit()}catch{}for(;this._state==="stopping";)await new Promise(e=>setTimeout(e,50))}}_emitError(e){this._emitter.listenerCount("error")>0?this._emitter.emit("error",e):this._logger.error("SSE reader error (no error listeners):",e)}};import{inArray as rr,sql as gt}from"drizzle-orm";var nr="",ar=64,sr=t=>t.toLowerCase(),ir=t=>t.trim().toLowerCase();function Rt(t){if(t==null)return null;if(!Array.isArray(t))return new Set;let e=new Set;for(let n of t){if(typeof n!="string")continue;let s=ir(n);s.length>0&&e.add(s)}return e}function De(t,e){return t===null?!0:e==null?!1:t.has(sr(e))}function xe(t){return t!==null&&t.size===0}function Dt(t,e){if(e!==null)return e.size===0?gt`1 = 0`:rr(gt`LOWER(${t})`,[...e])}function je(t){if(t===null)return"all";if(t.size===0)return"none";let e=[...t].sort().join(nr);if(e.length<=ar)return e;let n=2166136261;for(let s=0;s<e.length;s++)n^=e.charCodeAt(s),n=Math.imul(n,16777619);return`h:${(n>>>0).toString(16)}`}var L=(t,e)=>new Response(JSON.stringify(t),{status:e?.status??200,headers:{"Content-Type":"application/json"}}),Je=200,Tt=4e3,or="stream interrupted by server error",lr=/^\d{4}-\d{2}-\d{2}$/,ur=15e3,St=Symbol("ids-stream-heartbeat"),dr=12,cr=t=>{let e=t.searchParams.get("cursor_report_hub_id"),n=t.searchParams.get("cursor_business_date");if(e===null)return n===null?{cursor:null}:{invalid:!0};let s=Number.parseInt(e,10);return!Number.isSafeInteger(s)||String(s)!==e||s<=0?{invalid:!0}:n===null?{cursor:{businessDate:null,reportHubId:s}}:lr.test(n)?{cursor:{businessDate:n,reportHubId:s}}:{invalid:!0}};async function*wt(t,e,n=Je){let s=e?ht(t,e):0,m=!0;for(;;){let u=t.slice(s,s+(m?n:Tt));s+=u.length;let I=s>=t.length,p=u[u.length-1];if(yield{items:u,nextCursor:I||!p?null:{businessDate:p.businessDate,reportHubId:p.reportHubId},isLast:I,...m?{total:t.length}:{}},m=!1,I)return}}var It=(t,e,n,s)=>{let m=new TextEncoder,u=!1,I=null,p=new ReadableStream({async pull(o){if(u||n.signal.aborted){await e.return(void 0).catch(()=>{});try{o.close()}catch{}return}let $=null;try{I===null&&(I=e.next());let d=new Promise(ye=>{$=setTimeout(()=>ye(St),ur)}),K=await Promise.race([I,d]);if($!==null&&(clearTimeout($),$=null),K===St){if(u||n.signal.aborted){await e.return(void 0).catch(()=>{});try{o.close()}catch{}return}o.enqueue(m.encode(`
2
- `));return}I=null;let{value:z,done:P}=K;if(P){o.close();return}if(u||n.signal.aborted){await e.return(void 0).catch(()=>{});try{o.close()}catch{}return}o.enqueue(m.encode(`${JSON.stringify(z)}
3
- `))}catch(d){if($!==null&&clearTimeout($),I=null,u||n.signal.aborted)return;s.error(`ids-stream emission failed: ${d instanceof Error?d.message:String(d)}`);try{o.enqueue(m.encode(`${JSON.stringify({error:or})}
4
- `)),o.close()}catch{}}},cancel(){u=!0,e.return(void 0).catch(()=>{})}}),k=new Headers({"Content-Type":"application/x-ndjson; charset=utf-8","Cache-Control":"private, no-cache, no-transform","X-Content-Type-Options":"nosniff"});return t&&k.append("Set-Cookie",t),new Response(p,{status:200,headers:k})},pr=32*1024*1024,mr=60,yr=4,hr=12e4,fr=1024,br=60,gr=5,Rr=new Set(["image/png","image/jpeg","image/gif","image/webp","application/pdf","text/plain"]),Dr=/^[\x20-\x7E]+$/,Sr=/^[\w.+-]+\/[\w.+-]+/,At=t=>t&&Dr.test(t)&&Sr.test(t)?t:null,wr=t=>encodeURIComponent(t).replace(/['()*]/g,e=>`%${e.charCodeAt(0).toString(16).toUpperCase()}`),Ir=t=>t.replace(/[^\x20-\x7E]/g,"_").replace(/["\\]/g,"_"),Ar=t=>{switch(t){case"not_found":case"denied":case"invalid_path":return 404;case"too_large":return 413;default:return 502}},Tr={404:"Attachment not found",413:"Attachment too large",502:"Attachment storage unavailable"},Cr=t=>{let e=new Map;return(n,s)=>{let m=e.get(n);m&&e.delete(n);let u=m??{tokens:t,lastRefillMs:s},I=Math.max(0,s-u.lastRefillMs);I>0&&(u.tokens=Math.min(t,u.tokens+I*t/6e4),u.lastRefillMs=s);let p=u.tokens>=1;for(p&&(u.tokens-=1),e.set(n,u);e.size>fr;){let k=e.keys().next();if(k.done)break;e.delete(k.value)}return p}},_r=t=>{let e=0;return{tryAcquire:()=>e>=t?!1:(e+=1,!0),release:()=>{e>0&&(e-=1)}}},Mr=(t,e,n)=>{let s=setTimeout(e,n);s.unref?.();let m=()=>{clearTimeout(s),e()},u=!1;return new ReadableStream({pull(I){if(u){I.close(),m();return}u=!0,I.enqueue(t)},cancel(){m()}})},Er=(t,e,n)=>{if(n===null)return!0;let s=typeof e.sourceType=="string"?e.sourceType:void 0;switch(t.type){case"connected":case"status-update":return!0;case"report-create":case"report-update":case"report-publish":return De(n,t.report.sourceType);case"comment-add":case"comment-delete":return De(n,s??"Internal");case"report-delete":return De(n,s)}};function Ct(t){let{authenticate:e,service:n,encodeUserId:s,redis:m,sseReader:u,streamKey:I}=t,p=t.loginRedirectPath??"/auth/login",k=t.logger??ce(3,"[DailyReportAPI]"),o=t.logger??ce(3,"[DailyReportVisibility]"),$=t.logger??ce(1,"[DailyReportSSE]"),d=t.logger??ce(1,"[DailyReportAttachment]"),K=t.attachmentMaxBytes??pr,z=Cr(t.attachmentRateLimitPerMinute??mr),P=_r(t.attachmentConcurrency??yr),ye=async(w,U="initial")=>{let C=t.resolveVisibleSourceTypes;if(!C)return null;try{return Rt(await C(w,{reason:U}))}catch(M){return o.error("resolveVisibleSourceTypes threw; failing closed (deny all)",M),new Set}},Ne=async({request:w})=>{let{user:U,cookie:C}=await e(w,{failureRedirect:p}),M=new Headers;C&&M.append("Set-Cookie",C);let _=null;U&&(_=await n.getUserIdByExternalId(U.id));let B=_?s(_):null;return{data:{user:U,userId:B},headers:M}},Le={"business-date":async(w,U,C,M,_)=>{let B=oe(w.searchParams.get("businessDate")),D=w.searchParams.get("forceRefresh")==="true";if(!B)return he(C,U,{error:{message:"Invalid business date"}},400);let N=await n.getDailyReportsByBusinessDateByExternalId(B,M.id,{forceRefresh:D},_);return he(C,U,{businessDate:B,reports:N},200)},"ids-stream":async(w,U,C,M,_)=>{let B=cr(w);if("invalid"in B)return he(C,U,{error:{message:"Invalid cursor"}},400);let D=w.searchParams.get("forceRefresh")==="true",N=n.getDailyReportIdsByExternalId(M.id,{forceRefresh:D},_);if(N.catch(()=>{}),B.cursor)return It(U,wt(await N,B.cursor),C,k);let Y=n.getDailyReportIdsFirstPageByExternalId(M.id,Je,_);Y.catch(()=>{});let T=(async function*(){let R=await Promise.race([N.then(F=>({kind:"full",items:F}),F=>({kind:"full-error",error:F})),Y.then(F=>({kind:"page",items:F}),()=>({kind:"page-error"}))]),X=null,E=null;if(R.kind==="full")E=R.items;else if(R.kind==="page"||R.kind==="full-error"){let F=R.kind==="page"?R.items:await Y;if(F.length<Je){yield{items:F,nextCursor:null,isLast:!0,total:F.length};return}let g=F[F.length-1];X={businessDate:g.businessDate,reportHubId:g.reportHubId},yield{items:F,nextCursor:X,isLast:!1}}E===null&&(E=await N),yield*wt(E,X,X?Tt:Je)})();return It(U,T,C,k)},report:async(w,U,C,M,_)=>{let B=w.searchParams.get("reportHubId"),D=w.searchParams.get("forceRefresh")==="true",N=B?Number.parseInt(B,10):NaN;if(!Number.isFinite(N)||N<=0)return he(C,U,{error:{message:"Invalid reportHubId"}},400);let Y=await n.getDailyReportDetailByIdByExternalId(N,M.id,{snapshot:!0,forceRefresh:D},_);return Y?he(C,U,{report:Y},200):he(C,U,{error:{message:"Report not found"}},404)}};return{index:{loader:Ne},api:{loader:async({request:w,params:U})=>{let{user:C,cookie:M}=await e(w,{failureRedirect:null}),_=M??null;if(!C)return he(w,_,{error:{message:"Unauthorized"}},401);if(w.method!=="GET")return he(w,_,{error:{message:"Method not allowed"}},405);let B=U.endpoint??"",D=Le[B];if(!D)return he(w,_,{error:{message:"Unknown endpoint"}},404);let N=Date.now();try{let Y=new URL(w.url),T=await ye(w);return await D(Y,_,w,C,T)}catch(Y){let T=Date.now()-N,R=Y instanceof Error?Y:new Error(String(Y));return k.error(`500 endpoint=${B} elapsed=${T}ms name=${R.name} code=${"code"in R?R.code:"N/A"} message=${R.message}`),k.error("Stack:",R.stack),he(w,_,{error:{message:"Internal Server Error"}},500)}},action:async({request:w,params:U})=>{let{user:C}=await e(w,{failureRedirect:null});if(!C)return L({error:"Unauthorized"},{status:401});if(U.endpoint!=="action")return L({error:"Unknown endpoint"},{status:404});let _=await n.getUserIdByExternalId(C.id);if(!_)return L({error:"User not found"},{status:404});let B=await ye(w),D=await w.formData(),N=D.get("intent"),Y=D.get("reportHubId"),T=Y?Number(Y):NaN,R=D.get("businessDate"),X=Number(D.get("operationTimestamp")),E=D.get("clientTempId");if(N==="clearCache")return t.enableDevCacheClear?(await n.clearCache(),L({status:"OK",intent:"clearCache"})):L({error:"Invalid intent"},{status:400});if(!E)return L({error:"clientTempId required"},{status:400});if(N!=="create"&&(!T||Number.isNaN(T)))return L({error:"Invalid reportHubId"},{status:400});let F=async(g,O,W)=>{let Z=D.get(O);if(Z===null)return L({error:`${O} required`},{status:400});try{let j=await W(Z==="true");return L({status:"OK",intent:g,updatedStatus:{isStarred:j.isStarred,isRead:j.isRead},operationTimestamp:X,reportHubId:String(T),clientTempId:E})}catch(j){if(j instanceof Error&&j.message==="Not Found")return L({error:"Report not found"},{status:404});throw j}};switch(N){case"create":{if(!R)return L({error:"businessDate required"},{status:400});let g=await n.createDailyReport(_,R,E);return L({status:"OK",intent:"create",report:g,reportHubId:String(g.reportHubId),clientTempId:E})}case"update":{let g=D.get("title"),O=D.get("content");try{return await n.updateDailyReport(T,_,{title:g,content:O},E),L({status:"OK",intent:"update",reportHubId:String(T),clientTempId:E})}catch(W){if(W instanceof Error){if(W.message==="Unauthorized")return L({error:"Unauthorized"},{status:403});if(W.message==="Not Found")return L({error:"Report not found"},{status:404})}throw W}}case"publish":try{let g=await n.publishDailyReport(T,_,E);return L({status:"OK",intent:"publish",reportHubId:String(T),clientTempId:E,report:g})}catch(g){if(g instanceof Error){if(g.message==="Unauthorized")return L({error:"Unauthorized"},{status:403});if(g.message==="Not Found")return L({error:"Report not found"},{status:404})}throw g}case"delete":try{return await n.deleteDailyReport(T,_,E),L({status:"OK",intent:"delete",reportHubId:String(T),clientTempId:E})}catch(g){if(g instanceof Error){if(g.message==="Unauthorized")return L({error:"Unauthorized"},{status:403});if(g.message==="Not Found")return L({error:"Report not found"},{status:404})}throw g}case"toggleStar":return await F("toggleStar","isStarred",g=>n.setStarStatus(_,T,R,g,E,B));case"toggleRead":return await F("toggleRead","isRead",g=>n.setReadStatus(_,T,R,g,E,B));case"addComment":{let g=D.get("content");if(!g)return L({error:"Content required"},{status:400});try{let O=await n.addComment(_,T,g,R,E,B),W={...O,userId:O.userId};return L({status:"OK",intent:"addComment",newComment:W,reportHubId:String(T),clientTempId:E})}catch(O){if(O instanceof Error){if(O.message==="Not Found")return L({error:"Report not found"},{status:404});if(O.message.startsWith("Comments are restricted"))return L({error:"Comments are restricted for this report"},{status:403})}throw O}}case"deleteComment":{let g=Number(D.get("commentId"));if(!g||Number.isNaN(g))return L({error:"Invalid commentId"},{status:400});try{return await n.deleteComment(_,T,g,R,E,B),L({status:"OK",reportHubId:String(T),deletedCommentId:String(g),clientTempId:E})}catch(O){if(O instanceof Error){if(O.message==="Unauthorized")return L({error:"Unauthorized"},{status:403});if(O.message==="Not Found")return L({error:"Comment not found"},{status:404})}throw O}}default:return L({error:"Invalid intent"},{status:400})}}},sse:{loader:async({request:w,params:U})=>{let{user:C}=await e(w,{failureRedirect:null});if(!C)return new Response("Unauthorized",{status:401});let M=await n.getUserIdByExternalId(C.id);if(!M)return new Response("Forbidden",{status:403});if(U.endpoint!=="updates")return new Response("Not Found",{status:404});let _=await ye(w),B=0,D=0,Y=new URL(w.url).searchParams.get("lastEventId")||w.headers.get("Last-Event-ID"),T=new TextEncoder,R=null,X=null,E=null,F=!1,g=()=>{if(!F){if(F=!0,X&&(clearInterval(X),X=null),E&&(E(),E=null),R)try{R.desiredSize!==null&&R.close()}catch{}finally{R=null}F=!1}},O=j=>{R&&R.desiredSize!==null&&R.enqueue(T.encode(`id: ${j}
1
+ var ft=t=>{throw TypeError(t)};var bt=(t,e,r)=>e.has(t)||ft("Cannot "+r);var tt=(t,e,r)=>(bt(t,e,"read from private field"),r?r.call(t):e.get(t)),gt=(t,e,r)=>e.has(t)?ft("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,r),Rt=(t,e,r,i)=>(bt(t,e,"write to private field"),i?i.call(t,r):e.set(t,r),r);var Dt=t=>({async getEpoch(e){try{let r=await t?.getClient();if(!r)return 0;let i=await r.get(e);return i?Number(i):0}catch{return 0}},async incrementEpoch(e){try{let r=await t?.getClient();if(!r)return;await r.incr(e)}catch{}}}),Ke=class{constructor(e,r){this.config=e;this.epochStore=r;this.buckets=new Map;this.inFlight=new Map;this.invalidate=e=>{this.buckets.delete(e),this.inFlight.delete(e)};this.maybeRefreshAhead=e=>{let r=e.refreshAheadRatio;if(r===void 0)return;let{cacheKey:i}=e,m=this.buckets.get(i);if(!m)return;let u=e.ttlMsOverride??this.config.defaultTtlMs;if(u-(m.expireAt-Date.now())<u*r||this.inFlight.has(i))return;let c;c=(async()=>{let N=e.epochKey?await this.epochStore.getEpoch(e.epochKey):0,o=await e.fetcher();return this.inFlight.get(i)===c&&this.buckets.set(i,{records:o,expireAt:Date.now()+u,epoch:N}),o})(),this.inFlight.set(i,c),c.catch(()=>{}).finally(()=>{this.inFlight.get(i)===c&&this.inFlight.delete(i)})};this.getOrFetch=async e=>{let{cacheKey:r,forceRefresh:i,snapshot:m}=e,u=this.buckets.get(r);if(i&&(this.buckets.delete(r),this.inFlight.delete(r)),!i&&u&&u.expireAt>Date.now())if(e.epochKey){let c=await this.epochStore.getEpoch(e.epochKey);if(u.epoch===c)return this.maybeRefreshAhead(e),m?u.records.map(N=>structuredClone(N)):u.records;this.buckets.delete(r)}else return this.maybeRefreshAhead(e),m?u.records.map(c=>structuredClone(c)):u.records;if(!i&&this.inFlight.has(r)){let c=await this.inFlight.get(r);return m?c.map(N=>structuredClone(N)):c}let I;I=(async()=>{let c=e.epochKey?await this.epochStore.getEpoch(e.epochKey):0,N=await e.fetcher();if(i||this.inFlight.get(r)===I){let o=Date.now()+(e.ttlMsOverride??this.config.defaultTtlMs);this.buckets.set(r,{records:N,expireAt:o,epoch:c}),this.buckets.size>500&&this.cleanExpired()}return N})(),i||this.inFlight.set(r,I);try{let c=await I;return m?c.map(N=>structuredClone(N)):c}finally{this.inFlight.get(r)===I&&this.inFlight.delete(r)}};this.flush=e=>{this.buckets.delete(e),this.inFlight.delete(e)};this.clearAll=()=>{this.buckets.clear(),this.inFlight.clear()};this.invalidatePrefix=e=>{for(let r of this.buckets.keys())r.startsWith(e)&&this.buckets.delete(r);for(let r of this.inFlight.keys())r.startsWith(e)&&this.inFlight.delete(r)}}cleanExpired(){let e=Date.now();for(let[r,i]of this.buckets.entries())i.expireAt<=e&&this.buckets.delete(r)}};var Wt=/^\d{4}-\d{2}-\d{2}$/,Zt=/^\d{4}\/\d{2}\/\d{2}$/,wt=t=>t<10?`0${t}`:`${t}`,St=t=>{if(Number.isNaN(t.getTime()))return null;let e=t.getFullYear(),r=wt(t.getMonth()+1),i=wt(t.getDate());return`${e}-${r}-${i}`};var oe=t=>{if(t==null)return null;if(t instanceof Date)return St(t);let e=t.trim();if(e==="")return null;if(Wt.test(e))return e;if(Zt.test(e))return e.replaceAll("/","-");let r=new Date(e);return St(r)};var er=(t,e)=>t.businessDate!==e.businessDate?t.businessDate===null?1:e.businessDate===null||t.businessDate>e.businessDate?-1:1:e.reportHubId-t.reportHubId;var It=(t,e)=>{let r=t.findIndex(i=>er({businessDate:i.businessDate,reportHubId:i.reportHubId},e)>0);return r===-1?t.length:r};var ce=(t,e,r=console)=>{let i=m=>typeof m=="string"?[`${e} ${m}`]:[e,m];return{debug:(m,...u)=>{t<=0&&r.debug(...i(m),...u)},info:(m,...u)=>{t<=1&&r.info(...i(m),...u)},warn:(m,...u)=>{t<=2&&r.warn(...i(m),...u)},error:(m,...u)=>{t<=3&&r.error(...i(m),...u)}}};import{z as l}from"zod";var tr=l.object({name:l.string().nullish(),affiliation:l.string().nullish()}),rr=l.object({name:l.string().nullish(),text:l.string().nullish(),color:l.string().nullish()}),nr=l.object({id:l.number(),name:l.string().nullish(),color:l.string().nullish()}),At=l.object({id:l.number(),userId:l.string().nullish(),userName:l.string().nullish(),content:l.string().nullish(),createdAt:l.string().nullish(),isMine:l.boolean()}),ar=l.object({id:l.string(),fileName:l.string(),fileType:l.string().nullable(),fileSize:l.number().nullable(),createdAt:l.string().nullable(),state:l.enum(["present","absent","unknown"])}),rt=l.object({reportHubId:l.number(),date:l.string().nullish(),createdAt:l.string().nullish(),author:l.string().nullish(),userId:l.string().nullish(),sourceType:l.string().nullish(),employeeName:l.string().nullish(),updatedBy:l.string().nullish(),updatedAt:l.string().nullish(),category:l.string().nullish(),creationCategory:l.string().nullish(),visitTimeFrom:l.string().nullish(),visitTimeTo:l.string().nullish(),customerName:l.string().nullish(),interviewers:l.array(tr),subject:l.string().nullish(),content:l.string().nullish(),comments:l.array(rr),isRead:l.boolean(),isStarred:l.boolean(),labels:l.array(nr),commentItems:l.array(At),attachments:l.array(ar).default([])}),sr=l.object({type:l.literal("connected")}),Ve=l.object({type:l.literal("status-update"),reportHubId:l.number(),statusType:l.enum(["star","read"]),value:l.boolean(),clientTempId:l.string(),recipientRawUserId:l.number().optional()}),nt=l.string().optional(),at=l.object({type:l.literal("comment-add"),reportHubId:l.number(),comment:At,clientTempId:l.string(),recipientRawUserId:l.number().optional(),sourceType:nt}),st=l.object({type:l.literal("comment-delete"),reportHubId:l.number(),commentId:l.number(),clientTempId:l.string(),recipientRawUserId:l.number().optional(),sourceType:nt}),it=l.object({type:l.literal("report-create"),reportHubId:l.number(),report:rt,clientTempId:l.string(),recipientRawUserId:l.number().optional()}),ot=l.object({type:l.literal("report-update"),reportHubId:l.number(),report:rt,clientTempId:l.string(),recipientRawUserId:l.number().optional()}),lt=l.object({type:l.literal("report-publish"),reportHubId:l.number(),report:rt,clientTempId:l.string(),recipientRawUserId:l.number().optional()}),ut=l.object({type:l.literal("report-delete"),reportHubId:l.number(),clientTempId:l.string(),sourceType:nt}),Tt=l.discriminatedUnion("type",[sr,Ve,at,st,it,ot,lt,ut]);import{createHash as ir}from"crypto";var dt=t=>{let e=JSON.stringify(t);return`"${ir("sha256").update(e).digest("hex")}"`};var or=ce(1,"[Response]"),he=(t,e,r,i=200,m=or)=>{let u=dt(r),I=t.headers.get("If-None-Match");m.info(`[jsonResponseWithETag] ETag: ${u}, If-None-Match: ${I}`);let c=new Headers({"Content-Type":"application/json","Cache-Control":"private, max-age=0, must-revalidate","X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","Content-Security-Policy":"default-src 'none'",ETag:u});return e&&c.append("Set-Cookie",e),t.method==="GET"&&i===200&&I===u?new Response(null,{status:304,headers:c}):new Response(JSON.stringify(r),{status:i,headers:c})};import{EventEmitter as lr}from"events";var Ge=(t,e)=>{let[r,i]=t.split("-").map(Number),[m,u]=e.split("-").map(Number);return r!==m?r<m:i<=u},Je=class{constructor(e){this.config=e;this._emitter=new lr;this._state="idle";this._refCount=0;this._lastId="$";this._emitter.setMaxListeners(0),this._logger=e.logger??ce(1,"[SSE Reader]")}subscribe(e,r){return this._emitter.on("entry",e),r&&this._emitter.on("error",r),this._refCount++,this._refCount===1&&this._startLoop(),()=>{this._emitter.removeListener("entry",e),r&&this._emitter.removeListener("error",r),this._refCount--,this._refCount<=0&&(this._refCount=0,this._stopLoop())}}async destroy(){this._refCount=0,await this._stopLoop(),this._emitter.removeAllListeners(),this._lastId="$"}async _startLoop(){for(;this._state==="stopping";)await new Promise(e=>setTimeout(e,50));if(this._state!=="running"&&this._refCount!==0){this._state="running";try{this._client=await this.config.redis?.createClient()}catch(e){this._state="idle",this._emitError(e instanceof Error?e:new Error("Failed to create Redis client for SSE reader"));return}if(!this._client){this._state="idle",this._emitError(new Error("Failed to create Redis client for SSE reader"));return}if(this._client.on("error",e=>{this._logger.error("Redis client error:",e)}),this._lastId==="$")try{let e=await this.config.redis?.getClient();if(e){let r=await e.xRevRange(this.config.streamKey,"+","-",{COUNT:1});this._lastId=r.length>0?r[0].id:"0-0"}}catch(e){this._logger.warn("Failed to resolve stream tail anchor; falling back to $:",e)}try{for(;this._state==="running"&&this._client?.isOpen;){let e=await this._client.xRead([{key:this.config.streamKey,id:this._lastId}],{BLOCK:5e3,COUNT:100});if(e)for(let r of e)for(let i of r.messages){this._lastId=i.id;try{let m=i.message?.data?JSON.parse(i.message.data):null,u=m?.type;if((u==="report-create"||u==="report-delete"||u==="report-publish")&&this.config.cache.invalidatePrefix("daily-report:ids"),u==="comment-add"||u==="comment-delete"||u==="status-update"){let I=m?.reportHubId;typeof I=="number"&&(this.config.cache.invalidate(`daily-report:detail:${I}`),this.config.cache.invalidatePrefix(`daily-report:detail:${I}:user:`))}}catch{}this._emitter.emit("entry",{id:i.id,message:i.message})}}}catch(e){!(e?.constructor?.name==="ClientClosedError")&&this._state==="running"&&(this._logger.error("xRead loop error:",e),this._emitError(e instanceof Error?e:new Error(String(e))))}finally{if(this._client?.isOpen)try{await this._client.quit()}catch{}this._client=void 0,this._state="idle",this._refCount>0&&this._startLoop()}}}async _stopLoop(){if(this._state==="running"){if(this._state="stopping",this._client?.isOpen)try{await this._client.quit()}catch{}for(;this._state==="stopping";)await new Promise(e=>setTimeout(e,50))}}_emitError(e){this._emitter.listenerCount("error")>0?this._emitter.emit("error",e):this._logger.error("SSE reader error (no error listeners):",e)}};import{inArray as ur,sql as Ct}from"drizzle-orm";var dr="",cr=64,pr=t=>t.toLowerCase(),mr=t=>t.trim().toLowerCase();function yr(t){if(t==null)return null;if(!Array.isArray(t))return new Set;let e=new Set;for(let r of t){if(typeof r!="string")continue;let i=mr(r);i.length>0&&e.add(i)}return e}function we(t,e){return t===null?!0:e==null?!1:t.has(pr(e))}function Te(t){return t!==null&&t.size===0}function _t(t,e){if(e!==null)return e.size===0?Ct`1 = 0`:ur(Ct`LOWER(${t})`,[...e])}var Ne,Qe=class Qe{constructor(e){gt(this,Ne);Rt(this,Ne,e)}get visible(){return tt(this,Ne)===null?null:new Set(tt(this,Ne))}static restrictTo(e){return new Qe(yr(e))}static unrestricted(e){return new Qe(null)}};Ne=new WeakMap;var fe=Qe;function He(t){return hr(t.visible)}function hr(t){if(t===null)return"all";if(t.size===0)return"none";let e=[...t].sort().map(i=>`${i.length}:${i}`).join(dr);if(e.length<=cr)return`s:${e}`;let r=2166136261;for(let i=0;i<e.length;i++)r^=e.charCodeAt(i),r=Math.imul(r,16777619);return`sh:${(r>>>0).toString(16)}`}var L=(t,e)=>new Response(JSON.stringify(t),{status:e?.status??200,headers:{"Content-Type":"application/json"}}),Xe=200,kt=4e3,fr="stream interrupted by server error",br=/^\d{4}-\d{2}-\d{2}$/,gr=15e3,vt=Symbol("ids-stream-heartbeat"),Rr=12,Dr=t=>{let e=t.searchParams.get("cursor_report_hub_id"),r=t.searchParams.get("cursor_business_date");if(e===null)return r===null?{cursor:null}:{invalid:!0};let i=Number.parseInt(e,10);return!Number.isSafeInteger(i)||String(i)!==e||i<=0?{invalid:!0}:r===null?{cursor:{businessDate:null,reportHubId:i}}:br.test(r)?{cursor:{businessDate:r,reportHubId:i}}:{invalid:!0}};async function*Mt(t,e,r=Xe){let i=e?It(t,e):0,m=!0;for(;;){let u=t.slice(i,i+(m?r:kt));i+=u.length;let I=i>=t.length,c=u[u.length-1];if(yield{items:u,nextCursor:I||!c?null:{businessDate:c.businessDate,reportHubId:c.reportHubId},isLast:I,...m?{total:t.length}:{}},m=!1,I)return}}var Et=(t,e,r,i)=>{let m=new TextEncoder,u=!1,I=null,c=new ReadableStream({async pull(o){if(u||r.signal.aborted){await e.return(void 0).catch(()=>{});try{o.close()}catch{}return}let $=null;try{I===null&&(I=e.next());let d=new Promise(ye=>{$=setTimeout(()=>ye(vt),gr)}),K=await Promise.race([I,d]);if($!==null&&(clearTimeout($),$=null),K===vt){if(u||r.signal.aborted){await e.return(void 0).catch(()=>{});try{o.close()}catch{}return}o.enqueue(m.encode(`
2
+ `));return}I=null;let{value:z,done:P}=K;if(P){o.close();return}if(u||r.signal.aborted){await e.return(void 0).catch(()=>{});try{o.close()}catch{}return}o.enqueue(m.encode(`${JSON.stringify(z)}
3
+ `))}catch(d){if($!==null&&clearTimeout($),I=null,u||r.signal.aborted)return;i.error(`ids-stream emission failed: ${d instanceof Error?d.message:String(d)}`);try{o.enqueue(m.encode(`${JSON.stringify({error:fr})}
4
+ `)),o.close()}catch{}}},cancel(){u=!0,e.return(void 0).catch(()=>{})}}),N=new Headers({"Content-Type":"application/x-ndjson; charset=utf-8","Cache-Control":"private, no-cache, no-transform","X-Content-Type-Options":"nosniff"});return t&&N.append("Set-Cookie",t),new Response(c,{status:200,headers:N})},wr=32*1024*1024,Sr=60,Ir=4,Ar=12e4,Tr=1024,Cr=60,_r=5,vr=new Set(["image/png","image/jpeg","image/gif","image/webp","application/pdf","text/plain"]),Mr=/^[\x20-\x7E]+$/,Er=/^[\w.+-]+\/[\w.+-]+/,xt=t=>t&&Mr.test(t)&&Er.test(t)?t:null,xr=t=>encodeURIComponent(t).replace(/['()*]/g,e=>`%${e.charCodeAt(0).toString(16).toUpperCase()}`),kr=t=>t.replace(/[^\x20-\x7E]/g,"_").replace(/["\\]/g,"_"),Nr=t=>{switch(t){case"not_found":case"denied":case"invalid_path":return 404;case"too_large":return 413;default:return 502}},Lr={404:"Attachment not found",413:"Attachment too large",502:"Attachment storage unavailable"},$r=t=>{let e=new Map;return(r,i)=>{let m=e.get(r);m&&e.delete(r);let u=m??{tokens:t,lastRefillMs:i},I=Math.max(0,i-u.lastRefillMs);I>0&&(u.tokens=Math.min(t,u.tokens+I*t/6e4),u.lastRefillMs=i);let c=u.tokens>=1;for(c&&(u.tokens-=1),e.set(r,u);e.size>Tr;){let N=e.keys().next();if(N.done)break;e.delete(N.value)}return c}},Pr=t=>{let e=0;return{tryAcquire:()=>e>=t?!1:(e+=1,!0),release:()=>{e>0&&(e-=1)}}},Br=(t,e,r)=>{let i=setTimeout(e,r);i.unref?.();let m=()=>{clearTimeout(i),e()},u=!1;return new ReadableStream({pull(I){if(u){I.close(),m();return}u=!0,I.enqueue(t)},cancel(){m()}})},Ur=(t,e,r)=>{if(r===null)return!0;let i=typeof e.sourceType=="string"?e.sourceType:void 0;switch(t.type){case"connected":case"status-update":return!0;case"report-create":case"report-update":case"report-publish":return we(r,t.report.sourceType);case"comment-add":case"comment-delete":return we(r,i??"Internal");case"report-delete":return we(r,i)}};function Nt(t){let{authenticate:e,service:r,encodeUserId:i,redis:m,sseReader:u,streamKey:I}=t,c=t.loginRedirectPath??"/auth/login",N=t.logger??ce(3,"[DailyReportAPI]"),o=t.logger??ce(3,"[DailyReportVisibility]"),$=t.logger??ce(1,"[DailyReportSSE]"),d=t.logger??ce(1,"[DailyReportAttachment]"),K=t.attachmentMaxBytes??wr,z=$r(t.attachmentRateLimitPerMinute??Sr),P=Pr(t.attachmentConcurrency??Ir),ye=async(S,U="initial")=>{let _=t.resolveVisibleSourceTypes;if(!_)return fe.unrestricted("no visibility port injected: this deployment does not restrict by source type");try{let A=await _(S,{reason:U});return A==null?fe.unrestricted("visibility port returned null/undefined: this deployment opts out of source-type filtering"):fe.restrictTo(A)}catch(A){return o.error("resolveVisibleSourceTypes threw; failing closed (deny all)",A),fe.restrictTo([])}},$e=async({request:S})=>{let{user:U,cookie:_}=await e(S,{failureRedirect:c}),A=new Headers;_&&A.append("Set-Cookie",_);let v=null;U&&(v=await r.getUserIdByExternalId(U.id));let B=v?i(v):null;return{data:{user:U,userId:B},headers:A}},Pe={"business-date":async(S,U,_,A,v)=>{let B=oe(S.searchParams.get("businessDate")),D=S.searchParams.get("forceRefresh")==="true";if(!B)return he(_,U,{error:{message:"Invalid business date"}},400);let k=await r.getDailyReportsByBusinessDateByExternalId(v,B,A.id,{forceRefresh:D});return he(_,U,{businessDate:B,reports:k},200)},"ids-stream":async(S,U,_,A,v)=>{let B=Dr(S);if("invalid"in B)return he(_,U,{error:{message:"Invalid cursor"}},400);let D=S.searchParams.get("forceRefresh")==="true",k=r.getDailyReportIdsByExternalId(v,A.id,{forceRefresh:D});if(k.catch(()=>{}),B.cursor)return Et(U,Mt(await k,B.cursor),_,N);let Y=r.getDailyReportIdsFirstPageByExternalId(v,A.id,Xe);Y.catch(()=>{});let C=(async function*(){let R=await Promise.race([k.then(F=>({kind:"full",items:F}),F=>({kind:"full-error",error:F})),Y.then(F=>({kind:"page",items:F}),()=>({kind:"page-error"}))]),X=null,M=null;if(R.kind==="full")M=R.items;else if(R.kind==="page"||R.kind==="full-error"){let F=R.kind==="page"?R.items:await Y;if(F.length<Xe){yield{items:F,nextCursor:null,isLast:!0,total:F.length};return}let g=F[F.length-1];X={businessDate:g.businessDate,reportHubId:g.reportHubId},yield{items:F,nextCursor:X,isLast:!1}}M===null&&(M=await k),yield*Mt(M,X,X?kt:Xe)})();return Et(U,C,_,N)},report:async(S,U,_,A,v)=>{let B=S.searchParams.get("reportHubId"),D=S.searchParams.get("forceRefresh")==="true",k=B?Number.parseInt(B,10):NaN;if(!Number.isFinite(k)||k<=0)return he(_,U,{error:{message:"Invalid reportHubId"}},400);let Y=await r.getDailyReportDetailByIdByExternalId(v,k,A.id,{snapshot:!0,forceRefresh:D});return Y?he(_,U,{report:Y},200):he(_,U,{error:{message:"Report not found"}},404)}};return{index:{loader:$e},api:{loader:async({request:S,params:U})=>{let{user:_,cookie:A}=await e(S,{failureRedirect:null}),v=A??null;if(!_)return he(S,v,{error:{message:"Unauthorized"}},401);if(S.method!=="GET")return he(S,v,{error:{message:"Method not allowed"}},405);let B=U.endpoint??"",D=Pe[B];if(!D)return he(S,v,{error:{message:"Unknown endpoint"}},404);let k=Date.now();try{let Y=new URL(S.url),C=await ye(S);return await D(Y,v,S,_,C)}catch(Y){let C=Date.now()-k,R=Y instanceof Error?Y:new Error(String(Y));return N.error(`500 endpoint=${B} elapsed=${C}ms name=${R.name} code=${"code"in R?R.code:"N/A"} message=${R.message}`),N.error("Stack:",R.stack),he(S,v,{error:{message:"Internal Server Error"}},500)}},action:async({request:S,params:U})=>{let{user:_}=await e(S,{failureRedirect:null});if(!_)return L({error:"Unauthorized"},{status:401});if(U.endpoint!=="action")return L({error:"Unknown endpoint"},{status:404});let v=await r.getUserIdByExternalId(_.id);if(!v)return L({error:"User not found"},{status:404});let B=await ye(S),D=await S.formData(),k=D.get("intent"),Y=D.get("reportHubId"),C=Y?Number(Y):NaN,R=D.get("businessDate"),X=Number(D.get("operationTimestamp")),M=D.get("clientTempId");if(k==="clearCache")return t.enableDevCacheClear?(await r.clearCache(),L({status:"OK",intent:"clearCache"})):L({error:"Invalid intent"},{status:400});if(!M)return L({error:"clientTempId required"},{status:400});if(k!=="create"&&(!C||Number.isNaN(C)))return L({error:"Invalid reportHubId"},{status:400});let F=async(g,O,W)=>{let Z=D.get(O);if(Z===null)return L({error:`${O} required`},{status:400});try{let j=await W(Z==="true");return L({status:"OK",intent:g,updatedStatus:{isStarred:j.isStarred,isRead:j.isRead},operationTimestamp:X,reportHubId:String(C),clientTempId:M})}catch(j){if(j instanceof Error&&j.message==="Not Found")return L({error:"Report not found"},{status:404});throw j}};switch(k){case"create":{if(!R)return L({error:"businessDate required"},{status:400});let g=await r.createDailyReport(v,R,M);return L({status:"OK",intent:"create",report:g,reportHubId:String(g.reportHubId),clientTempId:M})}case"update":{let g=D.get("title"),O=D.get("content");try{return await r.updateDailyReport(C,v,{title:g,content:O},M),L({status:"OK",intent:"update",reportHubId:String(C),clientTempId:M})}catch(W){if(W instanceof Error){if(W.message==="Unauthorized")return L({error:"Unauthorized"},{status:403});if(W.message==="Not Found")return L({error:"Report not found"},{status:404})}throw W}}case"publish":try{let g=await r.publishDailyReport(C,v,M);return L({status:"OK",intent:"publish",reportHubId:String(C),clientTempId:M,report:g})}catch(g){if(g instanceof Error){if(g.message==="Unauthorized")return L({error:"Unauthorized"},{status:403});if(g.message==="Not Found")return L({error:"Report not found"},{status:404})}throw g}case"delete":try{return await r.deleteDailyReport(C,v,M),L({status:"OK",intent:"delete",reportHubId:String(C),clientTempId:M})}catch(g){if(g instanceof Error){if(g.message==="Unauthorized")return L({error:"Unauthorized"},{status:403});if(g.message==="Not Found")return L({error:"Report not found"},{status:404})}throw g}case"toggleStar":return await F("toggleStar","isStarred",g=>r.setStarStatus(B,v,C,R,g,M));case"toggleRead":return await F("toggleRead","isRead",g=>r.setReadStatus(B,v,C,R,g,M));case"addComment":{let g=D.get("content");if(!g)return L({error:"Content required"},{status:400});try{let O=await r.addComment(B,v,C,g,R,M),W={...O,userId:O.userId};return L({status:"OK",intent:"addComment",newComment:W,reportHubId:String(C),clientTempId:M})}catch(O){if(O instanceof Error){if(O.message==="Not Found")return L({error:"Report not found"},{status:404});if(O.message.startsWith("Comments are restricted"))return L({error:"Comments are restricted for this report"},{status:403})}throw O}}case"deleteComment":{let g=Number(D.get("commentId"));if(!g||Number.isNaN(g))return L({error:"Invalid commentId"},{status:400});try{return await r.deleteComment(B,v,C,g,R,M),L({status:"OK",reportHubId:String(C),deletedCommentId:String(g),clientTempId:M})}catch(O){if(O instanceof Error){if(O.message==="Unauthorized")return L({error:"Unauthorized"},{status:403});if(O.message==="Not Found")return L({error:"Comment not found"},{status:404})}throw O}}default:return L({error:"Invalid intent"},{status:400})}}},sse:{loader:async({request:S,params:U})=>{let{user:_}=await e(S,{failureRedirect:null});if(!_)return new Response("Unauthorized",{status:401});let A=await r.getUserIdByExternalId(_.id);if(!A)return new Response("Forbidden",{status:403});if(U.endpoint!=="updates")return new Response("Not Found",{status:404});let v=await ye(S),B=0,D=0,Y=new URL(S.url).searchParams.get("lastEventId")||S.headers.get("Last-Event-ID"),C=new TextEncoder,R=null,X=null,M=null,F=!1,g=()=>{if(!F){if(F=!0,X&&(clearInterval(X),X=null),M&&(M(),M=null),R)try{R.desiredSize!==null&&R.close()}catch{}finally{R=null}F=!1}},O=j=>{R&&R.desiredSize!==null&&R.enqueue(C.encode(`id: ${j}
5
5
  data: ${JSON.stringify({type:"connected"})}
6
6
 
7
- `))},W=(j,te)=>{if(te.data)try{let x=JSON.parse(te.data),ee=bt.safeParse(x);if(!ee.success){$.error("SSE message validation failed:",ee.error.format());return}let ue=ee.data,me=typeof x.recipientRawUserId=="number"?x.recipientRawUserId:void 0;if(ue.type==="status-update"){if(me===void 0||me!==M)return}else if(me!==void 0&&me!==M)return;if(!Er(ue,x,_)){O(j);return}let de;if("recipientRawUserId"in x){let{recipientRawUserId:ge,..._e}=x;de=JSON.stringify(_e)}else de=te.data;R&&R.desiredSize!==null&&R.enqueue(T.encode(`id: ${j}
7
+ `))},W=(j,te)=>{if(te.data)try{let x=JSON.parse(te.data),ee=Tt.safeParse(x);if(!ee.success){$.error("SSE message validation failed:",ee.error.format());return}let ue=ee.data,me=typeof x.recipientRawUserId=="number"?x.recipientRawUserId:void 0;if(ue.type==="status-update"){if(me===void 0||me!==A)return}else if(me!==void 0&&me!==A)return;if(!Ur(ue,x,v.visible)){O(j);return}let de;if("recipientRawUserId"in x){let{recipientRawUserId:Re,...Me}=x;de=JSON.stringify(Me)}else de=te.data;R&&R.desiredSize!==null&&R.enqueue(C.encode(`id: ${j}
8
8
  data: ${de}
9
9
 
10
- `))}catch(x){$.error(`[SSE:${M}] processEntry error:`,x)}},Z=new ReadableStream({async start(j){R=j,X=setInterval(()=>{try{if(R&&R.desiredSize!==null){if(R.enqueue(T.encode(`: keep-alive
10
+ `))}catch(x){$.error(`[SSE:${A}] processEntry error:`,x)}},Z=new ReadableStream({async start(j){R=j,X=setInterval(()=>{try{if(R&&R.desiredSize!==null){if(R.enqueue(C.encode(`: keep-alive
11
11
 
12
- `)),++B%dr===0){let x=++D;ye(w,"refresh").then(ee=>{x===D&&(_=ee)})}}else g()}catch{g()}},5e3),w.signal.addEventListener("abort",()=>{g()});let te=Y||"0-0";if(E=u.subscribe(x=>{Ve(x.id,te)||(te=x.id,W(x.id,x.message))},x=>{$.error(`[SSE:${M}] Fan-Out reader error:`,x),g()}),!Y)try{let x=await m?.getClient();if(x){let ee=await x.xRevRange(I,"+","-",{COUNT:1});ee.length>0&&!Ve(ee[0].id,te)&&(te=ee[0].id)}}catch{}if(R&&R.desiredSize!==null){let x=`data: ${JSON.stringify({type:"connected"})}
12
+ `)),++B%Rr===0){let x=++D;ye(S,"refresh").then(ee=>{x===D&&(v=ee)})}}else g()}catch{g()}},5e3),S.signal.addEventListener("abort",()=>{g()});let te=Y||"0-0";if(M=u.subscribe(x=>{Ge(x.id,te)||(te=x.id,W(x.id,x.message))},x=>{$.error(`[SSE:${A}] Fan-Out reader error:`,x),g()}),!Y)try{let x=await m?.getClient();if(x){let ee=await x.xRevRange(I,"+","-",{COUNT:1});ee.length>0&&!Ge(ee[0].id,te)&&(te=ee[0].id)}}catch{}if(R&&R.desiredSize!==null){let x=`data: ${JSON.stringify({type:"connected"})}
13
13
 
14
14
  `,ee=te!=="0-0"?`id: ${te}
15
- ${x}`:x;R.enqueue(T.encode(ee))}if(Y)try{let x=await m?.getClient();if(x){let ee=await x.xRange(I,Y,"+",{COUNT:1e3});for(let ue of ee)ue.id!==Y&&(Ve(ue.id,te)||(te=ue.id,W(ue.id,ue.message)))}}catch(x){$.error(`[SSE:${M}] catch-up xRange error:`,x)}},cancel(){g()}});return new Response(Z,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive"}})}},attachment:{loader:async({request:w,params:U})=>{let C=null,M=(_,B,D)=>{let N=new Headers({"Content-Type":"application/json"});return D!==void 0&&N.set("Retry-After",String(D)),C&&N.append("Set-Cookie",C),new Response(JSON.stringify({error:{message:B}}),{status:_,headers:N})};try{let{user:_,cookie:B}=await e(w,{failureRedirect:null});if(C=B??null,!_)return M(401,"Unauthorized");if(w.method!=="GET"&&w.method!=="HEAD")return M(405,"Method not allowed");let D=t.attachmentIdCodec,N=t.readAttachment;if(!(D&&N))return M(404,"Attachment not found");let Y=U.token??"",T=D.decode(Y);if(T===null||!Number.isSafeInteger(T)||T<=0)return M(400,"Invalid attachment token");let R=await n.getUserIdByExternalId(_.id);if(!R)return M(403,"Forbidden");if(!z(R,Date.now()))return d.error(`429 attachment=${T} viewer=${R} reason=rate_limit`),M(429,"Too many requests",br);let X=await ye(w),E=await n.getAttachmentForUser(T,R,X);if(!E)return d.error(`404 attachment=${T} viewer=${R} reason=not_visible`),M(404,"Attachment not found");if(E.fileSize!=null&&E.fileSize>K)return d.error(`413 attachment=${T} viewer=${R} reason=db_size`),M(413,"Attachment too large");if(!P.tryAcquire())return d.error(`503 attachment=${T} viewer=${R} reason=concurrency`),M(503,"Too many concurrent downloads",gr);let F=!1,g=()=>{F||(F=!0,P.release())},O=!1;try{let W=w.method==="HEAD",Z=await N(E.filePath,{maxBytes:K,head:W,principal:s(R)});if(!Z.ok){let ge=Ar(Z.reason);return Z.reason==="not_found"&&n.markAttachmentMissing(T).catch(_e=>{d.error(`markAttachmentMissing failed attachment=${T} message=${_e instanceof Error?_e.message:"unknown"}`)}),d.error(`${ge} attachment=${T} viewer=${R} reason=${Z.reason} code=${Z.code??"-"}`),M(ge,Tr[ge]??"Attachment storage unavailable")}let j=At(E.fileType)??At(Z.contentType)??"application/octet-stream",te=Rr.has(j),x=new URL(w.url).searchParams.get("download")==="1",ee=te?j:"application/octet-stream",ue=te&&!x?"inline":"attachment",me=Z.size??Z.bytes.byteLength,de=new Headers({"Content-Type":ee,"Content-Length":String(me),"Content-Disposition":`${ue}; filename="${Ir(E.fileName)}"; filename*=UTF-8''${wr(E.fileName)}`,"Cache-Control":"private, no-store","X-Content-Type-Options":"nosniff","Content-Security-Policy":"default-src 'none'; sandbox","X-Frame-Options":"SAMEORIGIN"});return C&&de.append("Set-Cookie",C),n.markAttachmentPresent(T).catch(ge=>{d.error(`markAttachmentPresent failed attachment=${T} message=${ge instanceof Error?ge.message:"unknown"}`)}),d.info(`200 attachment=${T} viewer=${R} type=${ee} disposition=${ue} bytes=${me}`),W?new Response(null,{status:200,headers:de}):(O=!0,new Response(Mr(Z.bytes,g,hr),{status:200,headers:de}))}finally{O||g()}}catch(_){if(_ instanceof Response)throw _;return d.error(`500 attachment=? viewer=? reason=unexpected message=${_ instanceof Error?_.message:"unknown"}`),M(500,"Attachment request failed")}}}}}import{aliasedTable as Be,and as G,asc as Ge,desc as ke,eq as y,getColumns as vr,inArray as be,isNull as pe,or as Ue,sql as _t}from"drizzle-orm";var Ae=t=>vr(t),le=(t,e)=>{if(!t)return null;let n=t instanceof Date?t:new Date(t);if(Number.isNaN(n.getTime()))return typeof t=="string"?t:null;let s=n.getFullYear(),m=s<0?`-${String(-s).padStart(4,"0")}`:String(s).padStart(4,"0"),u=String(n.getMonth()+1).padStart(2,"0"),I=String(n.getDate()).padStart(2,"0");if(e==="YYYY-MM-DD")return`${m}-${u}-${I}`;let p=String(n.getHours()).padStart(2,"0"),k=String(n.getMinutes()).padStart(2,"0"),o=String(n.getSeconds()).padStart(2,"0");return`${m}-${u}-${I} ${p}:${k}:${o}`};function Mt(t){let{db:e,tables:n,userTable:s,resolveUserId:m,encodeUserId:u,redis:I,cache:p,epochs:k}=t,{hub:o,internal:$,comment:d,label:K,hubLabel:z,userStatus:P}=n,ye=t.externalSources??[],Ne=t.draftLabelNames&&t.draftLabelNames.length>0?t.draftLabelNames:[t.draftLabelName??"\u4E0B\u66F8\u304D"],Le=Ne[0]??"\u4E0B\u66F8\u304D",ae=t.logger??ce(1,"[DailyReportService]"),$e="daily-report:ids",ot=t.idsTtlMs??18e4,Ce="daily-report:ids:epoch",w="daily-report:business-date:",U=t.businessDateTtlMs??3e5,C="daily-report:date-epoch:",M="daily-report:detail-epoch:",_=t.streamKey??"daily-report:sse-stream",B=t.streamMaxLen??1e4,D=r=>k.incrementEpoch(r),N=r=>Dt(o.sourceType,r),Y=(r,a)=>`${$e}:user:${r}:st:${a}`,T=r=>`${$e}:user:${r}:`,R=(r,a,i)=>`daily-report:date:${r}:user:${a}:st:${i}`,X=(r,a)=>`daily-report:date:${r}:user:${a}:`,E=(r,a,i)=>`daily-report:detail:${r}:user:${a}:st:${i}`,F=(r,a)=>`daily-report:detail:${r}:user:${a}:`,g=async(r,a)=>{let i=await I?.getClient();if(!i){ae.warn(`[SSE] Redis client unavailable (${a})`);return}let c=Date.now();try{await i.xAdd(_,"*",{data:JSON.stringify(r)},{TRIM:{strategy:"MAXLEN",strategyModifier:"~",threshold:B}});let f=Date.now()-c;f>1e3&&ae.warn(`[SSE] Slow publish (${a}): ${f}ms`)}catch(f){ae.error(`[SSE] Redis publish failed (${a}):`,f)}},O=r=>r==null||r===""?null:/^\d+$/.test(r)?u(Number(r)):r,W=()=>{let r={};for(let a of ye)r[`ext_${a.sourceType}`]=Ae(a.table);return r},Z=r=>{let a=r;for(let i of ye)a=a.leftJoin(i.table,G(y(o.sourceType,i.sourceType),y(o.sourceIdNum,i.idColumn)));return a},j=(r,a)=>{let{hub:i,internal:c}=r,f=i.summary,h=[],b=null,S=null,v=null,J=null,q=null,Q=null,se=[],Re=ye.find(A=>A.sourceType===i.sourceType),ve=Re?r[`ext_${Re.sourceType}`]:void 0;if(Re&&ve){let A=Re.mapRow(ve);A.content!==void 0&&(f=A.content),A.employeeName!==void 0&&(Q=A.employeeName),A.category!==void 0&&(b=A.category),A.creationCategory!==void 0&&(S=A.creationCategory),A.visitTimeFrom!==void 0&&(v=A.visitTimeFrom),A.visitTimeTo!==void 0&&(J=A.visitTimeTo),A.customerName!==void 0&&(q=A.customerName),A.interviewers!==void 0&&(h=A.interviewers),A.comments!==void 0&&(se=A.comments)}else i.sourceType==="Internal"&&c&&(f=c.body);let we=(r.labels??[]).map(A=>({id:A.id,name:A.name,color:A.color})),Ie=r.comments??[],ie=S?Ne.includes(S):!1,V=Me?.[0]??null;return ie&&V&&!we.some(A=>A.id===V)&&we.push({id:V,name:Le,color:null}),{reportHubId:i.id,date:le(i.businessDate,"YYYY-MM-DD"),author:r.creatorName??O(i.createdBy)??"",userId:i.userId?u(i.userId):"",sourceType:i.sourceType??"Internal",createdAt:le(i.createdAt,"YYYY-MM-DD HH:mm:ss"),updatedAt:le(i.updatedAt,"YYYY-MM-DD HH:mm:ss"),updatedBy:O(i.updatedBy),employeeName:Q??r.creatorName??O(i.createdBy),category:b,creationCategory:S,visitTimeFrom:v,visitTimeTo:J,customerName:q,interviewers:h,subject:i.title,content:f,comments:se,isRead:r.isRead??!1,isStarred:r.isStarred??!1,labels:we,commentItems:Ie.map(A=>({...A,userId:u(A.userId),isMine:a?A.userId===a:!1})),attachments:r.attachments}},te=async(r,a)=>{let i=Be(z,"draft_label"),c=await Ee();return(await e.select({reportHubId:o.id,businessDate:o.businessDate,sourceType:o.sourceType}).from(o).leftJoin(i,G(y(i.hubId,o.id),be(i.labelId,c))).where(G(pe(o.deletedAt),Ue(y(o.userId,r),pe(o.userId),pe(i.hubId)),N(a))).orderBy(ke(o.businessDate),ke(o.id))).map(h=>({...h,businessDate:le(h.businessDate,"YYYY-MM-DD")}))},x=async(r,a,i)=>{let c=await de(r);if(!c)return[];if(xe(i))return[];let f=Be(z,"draft_label"),h=await Ee();return(await e.select({reportHubId:o.id,businessDate:o.businessDate,sourceType:o.sourceType}).top(a).from(o).leftJoin(f,G(y(f.hubId,o.id),be(f.labelId,h))).where(G(pe(o.deletedAt),Ue(y(o.userId,c),pe(o.userId),pe(f.hubId)),N(i))).orderBy(ke(o.businessDate),ke(o.id))).map(S=>({...S,businessDate:le(S.businessDate,"YYYY-MM-DD")}))},ee=async r=>{let a=await Z(e.select({hub:Ae(o),internal:Ae($),creatorName:s.displayName,...W()}).from(o)).leftJoin($,y(o.id,$.hubId)).leftJoin(s,y(o.userId,s.id)).where(G(y(o.businessDate,_t`${r}`),pe(o.deletedAt))).orderBy(ke(o.id)),i=await Oe(a.map(c=>c.hub.id));return a.map(c=>j({...c,attachments:i.get(c.hub.id)??[]}))},ue=r=>`${w}${r}`,me=new Map,de=async r=>{if(!t.disableUserIdCache&&me.has(r))return me.get(r)??null;let a=await m(r);return a!==null&&!t.disableUserIdCache&&me.set(r,a),a},ge=async(r,{forceRefresh:a=!1,snapshot:i=!1,ttlMsOverride:c}={},f)=>{let h=await de(r);if(!h)return[];if(xe(f))return[];let b=Y(h,je(f));return p.getOrFetch({cacheKey:b,fetcher:async()=>await te(h,f),forceRefresh:a,snapshot:i,ttlMsOverride:c??ot,epochKey:Ce,refreshAheadRatio:.5})},_e=(r,{forceRefresh:a=!1,snapshot:i=!1,ttlMsOverride:c}={})=>{let f=oe(r);return f?p.getOrFetch({cacheKey:ue(f),fetcher:()=>ee(f),forceRefresh:a,snapshot:i,ttlMsOverride:c??U}):Promise.resolve([])},Me=null,He=async()=>(Me!==null||(Me=(await e.select({id:K.id}).from(K).where(be(K.name,Ne)).orderBy(K.id)).map(a=>a.id)),Me),Ee=async()=>{let r=await He();return r.length>0?r:[-1]},Qe=async()=>{let r=await He();if(r.length===0)return null;let[a]=await e.select({id:K.id}).top(1).from(K).where(y(K.name,Le));return a?.id??r[0]},kt=(r,a)=>a!=null?"absent":r!=null?"present":"unknown",Oe=async r=>{let a=new Map,i=n.attachment,c=t.attachmentIdCodec;if(r.length===0||!i||!c)return a;let f=await e.select({id:i.id,hubId:i.hubId,fileName:i.fileName,fileType:i.fileType,fileSize:i.fileSize,createdAt:i.createdAt,objectCheckedAt:i.objectCheckedAt,objectMissingAt:i.objectMissingAt}).from(i).where(be(i.hubId,r)).orderBy(Ge(i.createdAt),Ge(i.id));for(let h of f){let b={id:c.encode(Number(h.id)),fileName:String(h.fileName),fileType:h.fileType?String(h.fileType):null,fileSize:h.fileSize!=null?Number(h.fileSize):null,createdAt:le(h.createdAt,"YYYY-MM-DD HH:mm:ss"),state:kt(h.objectCheckedAt,h.objectMissingAt)},S=a.get(Number(h.hubId));S?S.push(b):a.set(Number(h.hubId),[b])}return a},Nt=async(r,a,i)=>{let c=n.attachment;if(!c||xe(i))return null;let f=await Ee(),h=Be(z,"draft_label");return(await e.select({fileName:c.fileName,filePath:c.filePath,fileType:c.fileType,fileSize:c.fileSize}).top(1).from(c).innerJoin(o,y(o.id,c.hubId)).leftJoin(h,G(y(h.hubId,o.id),be(h.labelId,f))).where(G(y(c.id,r),pe(o.deletedAt),Ue(y(o.userId,a),pe(h.hubId)),N(i))))[0]??null},Lt=async r=>{let a=n.attachment;if(!a)return;let i=new Date;try{await e.update(a).set({objectCheckedAt:i,objectMissingAt:i,updatedAt:i}).where(y(a.id,r))}catch(c){ae.error("markAttachmentMissing failed",c)}},$t=async r=>{let a=n.attachment;if(!a)return;let i=new Date;try{await e.update(a).set({objectCheckedAt:i,objectMissingAt:null,updatedAt:i}).where(y(a.id,r))}catch(c){ae.error("markAttachmentPresent failed",c)}},Pt=async(r,a,{forceRefresh:i=!1,snapshot:c=!1,ttlMsOverride:f}={},h)=>{let b=await de(a);if(!b)return[];let S=oe(r);if(!S)return[];if(xe(h))return[];let v=R(S,b,je(h));return p.getOrFetch({cacheKey:v,fetcher:async()=>{let J=await Ee(),q=Be(z,"draft_label"),Q=await Z(e.select({hub:Ae(o),internal:Ae($),isRead:P.isRead,isStarred:P.isStarred,creatorName:s.displayName,...W()}).from(o)).leftJoin($,y(o.id,$.hubId)).leftJoin(P,G(y(o.id,P.hubId),y(P.userId,b))).leftJoin(q,G(y(q.hubId,o.id),be(q.labelId,J))).leftJoin(s,y(o.userId,s.id)).where(G(y(o.businessDate,_t`${S}`),pe(o.deletedAt),Ue(y(o.userId,b),pe(q.hubId)),N(h))).orderBy(ke(o.id));if(Q.length===0)return[];let se=Q.map(V=>V.hub.id),Re=await e.select({hubId:z.hubId,id:K.id,name:K.name,color:K.color}).from(z).innerJoin(K,y(z.labelId,K.id)).where(be(z.hubId,se)),ve=await e.select({hubId:d.hubId,id:d.id,body:d.body,createdAt:d.createdAt,userId:d.userId,userName:s.displayName}).from(d).leftJoin(s,y(d.userId,s.id)).where(be(d.hubId,se)).orderBy(Ge(d.createdAt)),we=await Oe(se),Ie=new Map,ie=new Map;for(let V of Re){let A=Ie.get(V.hubId);A||(A=[],Ie.set(V.hubId,A)),A.push({id:V.id,name:V.name,color:V.color})}for(let V of ve){let A=ie.get(V.hubId);A||(A=[],ie.set(V.hubId,A)),A.push({id:V.id,content:V.body,createdAt:le(V.createdAt,"YYYY-MM-DD HH:mm:ss")||"",userId:V.userId,userName:V.userName||""})}return Q.map(V=>{let A=V.hub.id;return j({...V,attachments:we.get(A)??[],labels:Ie.get(A)||[],comments:ie.get(A)||[]},b)})},forceRefresh:i,snapshot:c,ttlMsOverride:f??U,epochKey:`${C}${S}`})},Pe=async(r,a,{forceRefresh:i=!1,snapshot:c=!1,ttlMsOverride:f}={},h)=>{if(xe(h))return null;let b=E(r,a,je(h));return(await p.getOrFetch({cacheKey:b,fetcher:async()=>{let v=await Ee(),J=Be(z,"draft_label"),q=await Z(e.select({hub:Ae(o),internal:Ae($),isRead:P.isRead,isStarred:P.isStarred,creatorName:s.displayName,...W()}).from(o)).leftJoin($,y(o.id,$.hubId)).leftJoin(P,G(y(o.id,P.hubId),y(P.userId,a))).leftJoin(J,G(y(J.hubId,o.id),be(J.labelId,v))).leftJoin(s,y(o.userId,s.id)).where(G(y(o.id,r),pe(o.deletedAt),Ue(y(o.userId,a),pe(J.hubId)),N(h)));if(q.length===0)return[];let Q=q[0].hub.id,se=await e.select({id:K.id,name:K.name,color:K.color}).from(z).innerJoin(K,y(z.labelId,K.id)).where(y(z.hubId,Q)),Re=await e.select({id:d.id,body:d.body,createdAt:d.createdAt,userId:d.userId,userName:s.displayName}).from(d).leftJoin(s,y(d.userId,s.id)).where(y(d.hubId,Q)).orderBy(Ge(d.createdAt)),ve=await Oe([Q]),we=se.map(ie=>({id:ie.id,name:ie.name,color:ie.color})),Ie=Re.map(ie=>({id:ie.id,content:ie.body,createdAt:le(ie.createdAt,"YYYY-MM-DD HH:mm:ss")||"",userId:ie.userId,userName:ie.userName||""}));return[j({...q[0],attachments:ve.get(Q)??[],labels:we,comments:Ie},a)]},forceRefresh:i,snapshot:c,ttlMsOverride:f??U,epochKey:`${M}${r}`}))[0]??null},Bt=async(r,a,i={},c)=>{let f=await de(a);return f?Pe(r,f,i,c):null},Ut=async r=>{let[a]=await e.select({sourceType:o.sourceType,deletedAt:o.deletedAt}).top(1).from(o).where(y(o.id,r));return a??null},lt=async(r,a)=>{let i=await Ut(r);if(!i||i.deletedAt||!De(a,i.sourceType))throw new Error("Not Found")},Ht=async(r,a,i,c,f,h)=>{await lt(a,h);let b=await e.select().top(1).from(P).where(G(y(P.hubId,a),y(P.userId,r))),S;if(b.length>0?b[0].isStarred!==c?S=(await e.update(P).set({isStarred:c,updatedAt:new Date,updatedBy:String(r)}).output().where(G(y(P.hubId,a),y(P.userId,r))))[0]:S=b[0]:S=(await e.insert(P).output().values({hubId:a,userId:r,isStarred:c,isRead:!1,createdAt:new Date,createdBy:String(r),updatedAt:new Date,updatedBy:String(r)}))[0],i){let v=oe(i);v&&(p.invalidatePrefix(X(v,r)),await D(`${C}${v}`))}return p.invalidate(`daily-report:detail:${a}`),p.invalidatePrefix(F(a,r)),await D(`${M}${a}`),await g(qe.parse({type:"status-update",reportHubId:a,recipientRawUserId:r,statusType:"star",value:c,clientTempId:f}),"setStarStatus"),S},Ot=async(r,a,i,c,f,h)=>{await lt(a,h);let b=await e.select().top(1).from(P).where(G(y(P.hubId,a),y(P.userId,r))),S;if(b.length>0?b[0].isRead!==c?S=(await e.update(P).set({isRead:c,updatedAt:new Date,updatedBy:String(r)}).output().where(G(y(P.hubId,a),y(P.userId,r))))[0]:S=b[0]:S=(await e.insert(P).output().values({hubId:a,userId:r,isRead:c,isStarred:!1,createdAt:new Date,createdBy:String(r),updatedAt:new Date,updatedBy:String(r)}))[0],i){let v=oe(i);v&&(p.invalidatePrefix(X(v,r)),await D(`${C}${v}`))}return p.invalidate(`daily-report:detail:${a}`),p.invalidatePrefix(F(a,r)),await D(`${M}${a}`),await g(qe.parse({type:"status-update",reportHubId:a,recipientRawUserId:r,statusType:"read",value:c,clientTempId:f}),"setReadStatus"),S},ut=async(r,a)=>{if(a===null)return;let i=await Ee(),[c]=await e.select({hubId:z.hubId}).top(1).from(z).where(G(y(z.hubId,r),be(z.labelId,i)));return c?a:void 0},Yt=async(r,a,i,c,f,h)=>{let[b]=await e.select({sourceType:o.sourceType,deletedAt:o.deletedAt,userId:o.userId}).top(1).from(o).where(y(o.id,a));if(!b||b.deletedAt)throw new Error("Not Found");if(!De(h,b.sourceType))throw new Error("Not Found");if(b.sourceType.toLowerCase()!=="internal")throw new Error("Comments are restricted for external daily report sources");let S=await ut(a,b.userId),[v]=await e.insert(d).output().values({hubId:a,userId:r,body:i,createdAt:new Date,createdBy:String(r),updatedAt:new Date,updatedBy:String(r)}),[J]=await e.select({displayName:s.displayName}).top(1).from(s).where(y(s.id,r)),q=J?.displayName??"Unknown";if(c){let se=oe(c);se&&(p.invalidatePrefix(`daily-report:date:${se}:user:`),await D(`${C}${se}`))}p.invalidate(`daily-report:detail:${a}`),p.invalidatePrefix(`daily-report:detail:${a}:user:`),await D(`${M}${a}`);let Q={id:v.id,userId:u(v.userId),userName:q,content:v.body,createdAt:le(v.createdAt,"YYYY-MM-DD HH:mm:ss")??"",isMine:!0};return await g(et.parse({type:"comment-add",reportHubId:a,comment:Q,clientTempId:f,recipientRawUserId:S,sourceType:b.sourceType}),"addComment"),Q},Ft=async(r,a)=>await r.select().top(1).from(d).where(y(d.id,a)),qt=async(r,a,i,c,f,h)=>{let b=await Ft(e,i);if(b.length===0)throw new Error("Not Found");if(b[0].hubId!==a)throw new Error("Not Found");let[S]=await e.select({userId:o.userId,sourceType:o.sourceType}).top(1).from(o).where(y(o.id,b[0].hubId));if(!(S&&De(h,S.sourceType)))throw new Error("Not Found");if(b[0].userId!==r)throw new Error("Unauthorized");let v=await ut(a,S.userId);if(await e.delete(d).where(y(d.id,i)),c){let J=oe(c);J&&(p.invalidatePrefix(`daily-report:date:${J}:user:`),await D(`${C}${J}`))}p.invalidate(`daily-report:detail:${a}`),p.invalidatePrefix(`daily-report:detail:${a}:user:`),await D(`${M}${a}`),await g(tt.parse({type:"comment-delete",reportHubId:a,commentId:i,clientTempId:f,recipientRawUserId:v,sourceType:S?.sourceType}),"deleteComment")},zt=async(r,a,i)=>{ae.info("createDailyReport called",{userId:r,businessDate:a});let[c]=await e.select({displayName:s.displayName}).from(s).where(y(s.id,r)),f=c?.displayName??u(r);try{let h=await e.transaction(async v=>{ae.info("Starting transaction");let J=`internal-temp-${Date.now()}-${Math.random()}`,[q]=await v.insert(o).output().values({sourceType:"Internal",sourceId:J,businessDate:new Date(a),userId:r,title:"(\u7121\u984C)",createdAt:new Date,createdBy:String(r),updatedAt:new Date,updatedBy:String(r)});await v.update(o).set({sourceId:String(q.id)}).where(y(o.id,q.id)),ae.info("Hub created",q),await v.insert($).values({hubId:q.id,body:"",createdAt:new Date,createdBy:String(r),updatedAt:new Date,updatedBy:String(r)}),ae.info("Internal created"),ae.info("Calling getDraftLabelId");let Q=await Qe();ae.info("draftLabelId",Q);let se=[];return Q&&(await v.insert(z).values({hubId:q.id,labelId:Q,createdAt:new Date,createdBy:String(r)}),se.push({id:Q,name:Le,color:null})),ae.info("Label assigned"),{reportHubId:q.id,date:a,createdAt:le(q.createdAt,"YYYY-MM-DD HH:mm:ss"),author:f,userId:u(r),sourceType:"Internal",employeeName:f,updatedBy:u(r),updatedAt:le(q.updatedAt,"YYYY-MM-DD HH:mm:ss"),category:null,creationCategory:null,visitTimeFrom:null,visitTimeTo:null,customerName:null,interviewers:[],subject:q.title,content:"",comments:[],isRead:!0,isStarred:!1,labels:se,commentItems:[],attachments:[]}}),b=oe(a);b&&p.invalidatePrefix(X(b,r)),p.invalidatePrefix(w),p.invalidatePrefix(T(r)),await D(Ce),b&&await D(`${C}${b}`);let S=await Pe(h.reportHubId,r,{forceRefresh:!0},null);if(S){let v=await He(),J=S.labels.some(q=>v.includes(q.id));await g(rt.parse({type:"report-create",reportHubId:S.reportHubId,report:S,clientTempId:i,recipientRawUserId:J?r:void 0}),"createDailyReport")}return S??h}catch(h){throw ae.error("Error in createDailyReport",h),h}},Ye=async(r,a)=>await r.select().top(1).from(o).where(y(o.id,a)),Xe=async(r,a,i)=>{await r.update(o).set(i).where(y(o.id,a))},dt=async(r,a,i)=>{await r.update($).set(i).where(y($.hubId,a))},ct=async(r,a,i)=>{await r.delete(z).where(G(y(z.hubId,a),y(z.labelId,i)))};return{streamKey:_,streamMaxLen:B,clearCache:async()=>{p.clearAll(),me.clear(),Me=null,k&&await D(Ce),ae.info("[DailyReportService] Server-side DB/SQL caches cleared successfully.")},invalidateHubReadCaches:async(r,a)=>{p.invalidatePrefix(w);for(let i of new Set(r))p.invalidatePrefix(`daily-report:detail:${i}:user:`),await D(`${M}${i}`);for(let i of new Set(a)){let c=oe(i);c&&await D(`${C}${c}`)}},getUserIdByExternalId:de,getDailyReportIdsByExternalId:ge,getDailyReportIdsFirstPageByExternalId:x,getDailyReportsByBusinessDate:_e,getDailyReportsByBusinessDateByExternalId:Pt,getDailyReportDetailById:Pe,getDailyReportDetailByIdByExternalId:Bt,getDraftLabelId:Qe,getAttachmentsByHubIds:Oe,getAttachmentForUser:Nt,markAttachmentMissing:Lt,markAttachmentPresent:$t,setStarStatus:Ht,setReadStatus:Ot,addComment:Yt,deleteComment:qt,createDailyReport:zt,updateDailyReport:async(r,a,i,c)=>{let f=await Ye(e,r);if(!f.length||f[0].deletedAt)throw new Error("Not Found");if(f[0].userId!==a)throw new Error("Unauthorized");await e.transaction(async S=>{i.title!==void 0&&await Xe(S,r,{title:i.title,updatedAt:new Date,updatedBy:String(a)}),i.content!==void 0&&await dt(S,r,{body:i.content,updatedAt:new Date,updatedBy:String(a)})}),p.invalidate(`daily-report:detail:${r}`),p.invalidatePrefix(`daily-report:detail:${r}:user:`),p.invalidatePrefix(w),await D(`${M}${r}`);let h=oe(le(f[0].businessDate,"YYYY-MM-DD"));h&&(p.invalidatePrefix(`daily-report:date:${h}:user:`),await D(`${C}${h}`));let b=await Pe(r,a,{forceRefresh:!0},null);if(b){let S=await He(),v=b.labels.some(J=>S.includes(J.id));await g(nt.parse({type:"report-update",reportHubId:b.reportHubId,report:b,clientTempId:c,recipientRawUserId:v?a:void 0}),"updateDailyReport")}},publishDailyReport:async(r,a,i)=>{let c=await Ye(e,r);if(!c.length)throw new Error("Not Found");if(c[0].userId!==a)throw new Error("Unauthorized");let f=await Qe();if(!f)return null;if(await ct(e,r,f),p.invalidatePrefix(`daily-report:detail:${r}:user:`),p.invalidatePrefix(w),p.invalidatePrefix($e),await D(Ce),c[0].businessDate){let S=oe(le(c[0].businessDate,"YYYY-MM-DD"));S&&await D(`${C}${S}`)}let h=oe(le(c[0].businessDate,"YYYY-MM-DD"));h&&p.invalidatePrefix(X(h,a));let b=await Pe(r,a,{forceRefresh:!0},null);return b&&await g(at.parse({type:"report-publish",reportHubId:b.reportHubId,report:b,clientTempId:i}),"publishDailyReport"),b??null},deleteDailyReport:async(r,a,i)=>{let c=await Ye(e,r);if(!c.length||c[0].deletedAt)throw new Error("Not Found");if(c[0].userId!==a)throw new Error("Unauthorized");if(await Xe(e,r,{deletedAt:new Date,deletedBy:String(a),updatedAt:new Date,updatedBy:String(a)}),p.invalidatePrefix(`daily-report:detail:${r}:user:`),p.invalidatePrefix(w),p.invalidatePrefix($e),await D(Ce),c[0].businessDate){let f=oe(le(c[0].businessDate,"YYYY-MM-DD"));f&&await D(`${C}${f}`)}await g(st.parse({type:"report-delete",reportHubId:r,clientTempId:i,sourceType:c[0].sourceType}),"deleteDailyReport")},findDailyReportHubById:Ye,updateDailyReportHub:Xe,updateDailyReportInternal:dt,deleteDailyReportLabel:ct}}import{and as xr,eq as Et}from"drizzle-orm";function kr(t){let e=[],n=t&&t.length>0?t:[{key:"internal",name:"Internal",description:"Internal daily reports"},{key:"external",name:"External",description:"External daily reports"}];for(let s of n){let u=`daily_report_${s.key.toLowerCase().replace(/[^a-z0-9_]/g,"_")}`;e.push({resourceKey:u,name:s.name,description:s.description??`${s.name} daily report access`}),s.includeCommentResource!==!1&&e.push({resourceKey:`${u}_comment`,name:`${s.name} Comment`,description:`${s.name} daily report comment access`})}return e}async function wn(t,e,n){let s=t,m=e.TMResource,u=n.appKey,I=n.actor??"system:daily-report",p=new Date,k=n.resources??kr(n.sources);for(let o of k){let $=await s.select().from(m).where(xr(Et(m.appKey,u),Et(m.resourceKey,o.resourceKey)));(!$||$.length===0)&&await s.insert(m).values({appKey:u,resourceKey:o.resourceKey,name:o.name,description:o.description??null,createdAt:p,createdBy:I,updatedAt:p,updatedBy:I})}}var Nr=ce(1,"[DailyReportExternalSource]"),Tn=(t,e,n,s=Nr)=>{if(!t)return[];try{let m=JSON.parse(t);return Array.isArray(m)?m.map(n).filter(u=>u!==null):(s.warn(`Unexpected ${e} format: not an array`),[])}catch(m){return s.warn(`Failed to parse ${e}:`,m),[]}};import{desc as vt,sql as Lr}from"drizzle-orm";import{bigint as re,bit as xt,date as $r,datetime2 as ne,foreignKey as fe,index as Se,int as Pr,mssqlSchema as Br,nvarchar as H,primaryKey as Te,uniqueIndex as Ur}from"drizzle-orm/mssql-core";function En(t,e){let n=Br(t),s=e.userTable,m=n.table("DailyReportHub",{id:re("id",{mode:"number"}).identity().notNull(),sourceType:H("source_type",{length:20}).notNull(),sourceId:H("source_id",{length:100}).notNull(),sourceIdNum:re("source_id_num",{mode:"number"}).generatedAlwaysAs(Lr`TRY_CAST(source_id AS BIGINT)`),businessDate:$r("business_date"),userId:re("user_id",{mode:"number"}),title:H("title",{length:200}),summary:H("summary",{length:"max"}),createdAt:ne("created_at").notNull(),createdBy:H("created_by",{length:50}).notNull(),updatedAt:ne("updated_at").notNull(),updatedBy:H("updated_by",{length:50}).notNull(),deletedAt:ne("deleted_at"),deletedBy:H("deleted_by",{length:50})},d=>[Te({name:`${t}_DailyReportHub_pk`,columns:[d.id]}),fe({name:`${t}_DailyReportHub_user_id_fk`,columns:[d.userId],foreignColumns:[s.id]}),Se(`${t}_DailyReportHub_business_date_index`).on(d.businessDate),Se(`${t}_DailyReportHub_updated_at_index`).on(d.updatedAt),Se(`${t}_DailyReportHub_source_index`).on(d.sourceType,d.sourceId),Se(`${t}_DailyReportHub_user_id_index`).on(d.userId),Se(`${t}_DailyReportHub_business_date_id_index`).on(vt(d.businessDate),vt(d.id)),Se(`${t}_DailyReportHub_deleted_at_index`).on(d.deletedAt)]),u=n.table("DailyReportInternal",{hubId:re("hub_id",{mode:"number"}).notNull(),body:H("body",{length:"max"}),metadata:H("metadata",{length:"max"}),createdAt:ne("created_at").notNull(),createdBy:H("created_by",{length:50}).notNull(),updatedAt:ne("updated_at").notNull(),updatedBy:H("updated_by",{length:50}).notNull()},d=>[Te({name:`${t}_DailyReportInternal_pk`,columns:[d.hubId]}),fe({name:`${t}_DailyReportInternal_hub_id_fk`,columns:[d.hubId],foreignColumns:[m.id]})]),I=n.table("DailyReportComment",{id:re("id",{mode:"number"}).identity().notNull(),hubId:re("hub_id",{mode:"number"}).notNull(),userId:re("user_id",{mode:"number"}).notNull(),body:H("body",{length:"max"}).notNull(),createdAt:ne("created_at").notNull(),createdBy:H("created_by",{length:50}).notNull(),updatedAt:ne("updated_at").notNull(),updatedBy:H("updated_by",{length:50}).notNull()},d=>[Te({name:`${t}_DailyReportComment_pk`,columns:[d.id]}),fe({name:`${t}_DailyReportComment_hub_id_fk`,columns:[d.hubId],foreignColumns:[m.id]}),fe({name:`${t}_DailyReportComment_user_id_fk`,columns:[d.userId],foreignColumns:[s.id]}),Se(`${t}_DailyReportComment_hub_id_index`).on(d.hubId)]),p=n.table("DailyReportLabel",{id:re("id",{mode:"number"}).identity().notNull(),userId:re("user_id",{mode:"number"}),name:H("name",{length:50}).notNull(),color:H("color",{length:20}),sortOrder:Pr("sort_order"),createdAt:ne("created_at").notNull(),createdBy:H("created_by",{length:50}).notNull(),updatedAt:ne("updated_at").notNull(),updatedBy:H("updated_by",{length:50}).notNull()},d=>[Te({name:`${t}_DailyReportLabel_pk`,columns:[d.id]}),fe({name:`${t}_DailyReportLabel_user_id_fk`,columns:[d.userId],foreignColumns:[s.id]})]),k=n.table("DailyReportHub_Label",{hubId:re("hub_id",{mode:"number"}).notNull(),labelId:re("label_id",{mode:"number"}).notNull(),createdAt:ne("created_at").notNull(),createdBy:H("created_by",{length:50}).notNull()},d=>[Te({name:`${t}_DailyReportHub_Label_pk`,columns:[d.hubId,d.labelId]}),fe({name:`${t}_DailyReportHub_Label_hub_id_fk`,columns:[d.hubId],foreignColumns:[m.id]}),fe({name:`${t}_DailyReportHub_Label_label_id_fk`,columns:[d.labelId],foreignColumns:[p.id]})]),o=n.table("DailyReportUserStatus",{hubId:re("hub_id",{mode:"number"}).notNull(),userId:re("user_id",{mode:"number"}).notNull(),isRead:xt("is_read").default(!1).notNull(),isStarred:xt("is_starred").default(!1).notNull(),createdAt:ne("created_at").notNull(),createdBy:H("created_by",{length:50}).notNull(),updatedAt:ne("updated_at").notNull(),updatedBy:H("updated_by",{length:50}).notNull()},d=>[Te({name:`${t}_DailyReportUserStatus_pk`,columns:[d.hubId,d.userId]}),fe({name:`${t}_DailyReportUserStatus_hub_id_fk`,columns:[d.hubId],foreignColumns:[m.id]}),fe({name:`${t}_DailyReportUserStatus_user_id_fk`,columns:[d.userId],foreignColumns:[s.id]})]),$=n.table("DailyReportAttachment",{id:re("id",{mode:"number"}).identity().notNull(),hubId:re("hub_id",{mode:"number"}).notNull(),uploadedBy:re("uploaded_by",{mode:"number"}),sourceKey:H("source_key",{length:200}).notNull(),fileName:H("file_name",{length:255}).notNull(),filePath:H("file_path",{length:"max"}).notNull(),fileType:H("file_type",{length:100}),fileSize:re("file_size",{mode:"number"}),objectCheckedAt:ne("object_checked_at"),objectMissingAt:ne("object_missing_at"),createdAt:ne("created_at").notNull(),createdBy:H("created_by",{length:50}).notNull(),updatedAt:ne("updated_at").notNull(),updatedBy:H("updated_by",{length:50}).notNull()},d=>[Te({name:`${t}_DailyReportAttachment_pk`,columns:[d.id]}),fe({name:`${t}_DailyReportAttachment_hub_id_fk`,columns:[d.hubId],foreignColumns:[m.id]}),fe({name:`${t}_DailyReportAttachment_uploaded_by_fk`,columns:[d.uploadedBy],foreignColumns:[s.id]}),Ur(`${t}_DailyReportAttachment_source_unique`).on(d.hubId,d.sourceKey),Se(`${t}_DailyReportAttachment_hub_id_index`).on(d.hubId,d.createdAt)]);return{hub:m,internal:u,comment:I,attachment:$,label:p,hubLabel:k,userStatus:o}}function $n(t){let e=pt(t.redis),n=new Fe({defaultTtlMs:t.cacheDefaultTtlMs??6e4},e),s=Mt({...t,cache:n,epochs:e}),m=new Ke({redis:t.redis,streamKey:s.streamKey,cache:n,logger:t.logger}),u=Ct({authenticate:t.authenticate,resolveVisibleSourceTypes:t.resolveVisibleSourceTypes,service:s,encodeUserId:t.encodeUserId,attachmentIdCodec:t.attachmentIdCodec,readAttachment:t.readAttachment,attachmentMaxBytes:t.attachmentMaxBytes,attachmentRateLimitPerMinute:t.attachmentRateLimitPerMinute,attachmentConcurrency:t.attachmentConcurrency,redis:t.redis,sseReader:m,streamKey:s.streamKey,loginRedirectPath:t.loginRedirectPath,enableDevCacheClear:t.enableDevCacheClear,logger:t.logger});return{service:s,cache:n,epochs:e,sseReader:m,streamKey:s.streamKey,knownSourceTypes:[...new Set(["Internal",...(t.externalSources??[]).map(I=>I.sourceType)])],...u}}export{Ke as DailyReportSseReader,Fe as SqlResultCache,Ir as asciiFallbackFileName,Dt as buildVisibleSourceTypeCondition,je as computeSourceTypeDigest,Ct as createDailyReportHandlers,$n as createDailyReportServer,Mt as createDailyReportService,pt as createEpochStore,kr as defineDailyReportAuthzResources,En as defineDailyReportSchema,xe as deniesEverySourceType,wr as encodeRfc8187,le as formatDateValue,it as generateETag,De as isSourceTypeVisible,Ve as isStreamIdLte,he as jsonResponseWithETag,Rt as normalizeVisibleSourceTypes,At as sanitizeMediaType,wn as seedDailyReportAuthzResources,Tn as transformJsonArray};
15
+ ${x}`:x;R.enqueue(C.encode(ee))}if(Y)try{let x=await m?.getClient();if(x){let ee=await x.xRange(I,Y,"+",{COUNT:1e3});for(let ue of ee)ue.id!==Y&&(Ge(ue.id,te)||(te=ue.id,W(ue.id,ue.message)))}}catch(x){$.error(`[SSE:${A}] catch-up xRange error:`,x)}},cancel(){g()}});return new Response(Z,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive"}})}},attachment:{loader:async({request:S,params:U})=>{let _=null,A=(v,B,D)=>{let k=new Headers({"Content-Type":"application/json"});return D!==void 0&&k.set("Retry-After",String(D)),_&&k.append("Set-Cookie",_),new Response(JSON.stringify({error:{message:B}}),{status:v,headers:k})};try{let{user:v,cookie:B}=await e(S,{failureRedirect:null});if(_=B??null,!v)return A(401,"Unauthorized");if(S.method!=="GET"&&S.method!=="HEAD")return A(405,"Method not allowed");let D=t.attachmentIdCodec,k=t.readAttachment;if(!(D&&k))return A(404,"Attachment not found");let Y=U.token??"",C=D.decode(Y);if(C===null||!Number.isSafeInteger(C)||C<=0)return A(400,"Invalid attachment token");let R=await r.getUserIdByExternalId(v.id);if(!R)return A(403,"Forbidden");if(!z(R,Date.now()))return d.error(`429 attachment=${C} viewer=${R} reason=rate_limit`),A(429,"Too many requests",Cr);let X=await ye(S),M=await r.getAttachmentForUser(X,C,R);if(!M)return d.error(`404 attachment=${C} viewer=${R} reason=not_visible`),A(404,"Attachment not found");if(M.fileSize!=null&&M.fileSize>K)return d.error(`413 attachment=${C} viewer=${R} reason=db_size`),A(413,"Attachment too large");if(!P.tryAcquire())return d.error(`503 attachment=${C} viewer=${R} reason=concurrency`),A(503,"Too many concurrent downloads",_r);let F=!1,g=()=>{F||(F=!0,P.release())},O=!1;try{let W=S.method==="HEAD",Z=await k(M.filePath,{maxBytes:K,head:W,principal:i(R)});if(!Z.ok){let Re=Nr(Z.reason);return Z.reason==="not_found"&&r.markAttachmentMissing(C).catch(Me=>{d.error(`markAttachmentMissing failed attachment=${C} message=${Me instanceof Error?Me.message:"unknown"}`)}),d.error(`${Re} attachment=${C} viewer=${R} reason=${Z.reason} code=${Z.code??"-"}`),A(Re,Lr[Re]??"Attachment storage unavailable")}let j=xt(M.fileType)??xt(Z.contentType)??"application/octet-stream",te=vr.has(j),x=new URL(S.url).searchParams.get("download")==="1",ee=te?j:"application/octet-stream",ue=te&&!x?"inline":"attachment",me=Z.size??Z.bytes.byteLength,de=new Headers({"Content-Type":ee,"Content-Length":String(me),"Content-Disposition":`${ue}; filename="${kr(M.fileName)}"; filename*=UTF-8''${xr(M.fileName)}`,"Cache-Control":"private, no-store","X-Content-Type-Options":"nosniff","Content-Security-Policy":"default-src 'none'; sandbox","X-Frame-Options":"SAMEORIGIN"});return _&&de.append("Set-Cookie",_),r.markAttachmentPresent(C).catch(Re=>{d.error(`markAttachmentPresent failed attachment=${C} message=${Re instanceof Error?Re.message:"unknown"}`)}),d.info(`200 attachment=${C} viewer=${R} type=${ee} disposition=${ue} bytes=${me}`),W?new Response(null,{status:200,headers:de}):(O=!0,new Response(Br(Z.bytes,g,Ar),{status:200,headers:de}))}finally{O||g()}}catch(v){if(v instanceof Response)throw v;return d.error(`500 attachment=? viewer=? reason=unexpected message=${v instanceof Error?v.message:"unknown"}`),A(500,"Attachment request failed")}}}}}import{aliasedTable as Oe,and as G,asc as We,desc as Le,eq as h,getColumns as Hr,inArray as ge,isNull as pe,or as Ye,sql as Lt}from"drizzle-orm";var Ce=t=>Hr(t),le=(t,e)=>{if(!t)return null;let r=t instanceof Date?t:new Date(t);if(Number.isNaN(r.getTime()))return typeof t=="string"?t:null;let i=r.getFullYear(),m=i<0?`-${String(-i).padStart(4,"0")}`:String(i).padStart(4,"0"),u=String(r.getMonth()+1).padStart(2,"0"),I=String(r.getDate()).padStart(2,"0");if(e==="YYYY-MM-DD")return`${m}-${u}-${I}`;let c=String(r.getHours()).padStart(2,"0"),N=String(r.getMinutes()).padStart(2,"0"),o=String(r.getSeconds()).padStart(2,"0");return`${m}-${u}-${I} ${c}:${N}:${o}`};function $t(t){let{db:e,tables:r,userTable:i,resolveUserId:m,encodeUserId:u,redis:I,cache:c,epochs:N}=t,{hub:o,internal:$,comment:d,label:K,hubLabel:z,userStatus:P}=r,ye=t.externalSources??[],$e=t.draftLabelNames&&t.draftLabelNames.length>0?t.draftLabelNames:[t.draftLabelName??"\u4E0B\u66F8\u304D"],Pe=$e[0]??"\u4E0B\u66F8\u304D",ae=t.logger??ce(1,"[DailyReportService]"),Be="daily-report:ids",ct=t.idsTtlMs??18e4,ve="daily-report:ids:epoch",S="daily-report:business-date:",U=t.businessDateTtlMs??3e5,_="daily-report:date-epoch:",A="daily-report:detail-epoch:",v=t.streamKey??"daily-report:sse-stream",B=t.streamMaxLen??1e4,D=n=>N.incrementEpoch(n),k=n=>_t(o.sourceType,n),Y=(n,s)=>`${Be}:user:${n}:st:${s}`,C=n=>`${Be}:user:${n}:`,R=(n,s,a)=>`daily-report:date:${n}:user:${s}:st:${a}`,X=(n,s)=>`daily-report:date:${n}:user:${s}:`,M=(n,s,a)=>`daily-report:detail:${n}:user:${s}:st:${a}`,F=(n,s)=>`daily-report:detail:${n}:user:${s}:`,g=async(n,s)=>{let a=await I?.getClient();if(!a){ae.warn(`[SSE] Redis client unavailable (${s})`);return}let p=Date.now();try{await a.xAdd(v,"*",{data:JSON.stringify(n)},{TRIM:{strategy:"MAXLEN",strategyModifier:"~",threshold:B}});let y=Date.now()-p;y>1e3&&ae.warn(`[SSE] Slow publish (${s}): ${y}ms`)}catch(y){ae.error(`[SSE] Redis publish failed (${s}):`,y)}},O=n=>n==null||n===""?null:/^\d+$/.test(n)?u(Number(n)):n,W=()=>{let n={};for(let s of ye)n[`ext_${s.sourceType}`]=Ce(s.table);return n},Z=n=>{let s=n;for(let a of ye)s=s.leftJoin(a.table,G(h(o.sourceType,a.sourceType),h(o.sourceIdNum,a.idColumn)));return s},j=(n,s)=>{let{hub:a,internal:p}=n,y=a.summary,f=[],b=null,w=null,E=null,J=null,q=null,Q=null,se=[],De=ye.find(T=>T.sourceType===a.sourceType),ke=De?n[`ext_${De.sourceType}`]:void 0;if(De&&ke){let T=De.mapRow(ke);T.content!==void 0&&(y=T.content),T.employeeName!==void 0&&(Q=T.employeeName),T.category!==void 0&&(b=T.category),T.creationCategory!==void 0&&(w=T.creationCategory),T.visitTimeFrom!==void 0&&(E=T.visitTimeFrom),T.visitTimeTo!==void 0&&(J=T.visitTimeTo),T.customerName!==void 0&&(q=T.customerName),T.interviewers!==void 0&&(f=T.interviewers),T.comments!==void 0&&(se=T.comments)}else a.sourceType==="Internal"&&p&&(y=p.body);let Ie=(n.labels??[]).map(T=>({id:T.id,name:T.name,color:T.color})),Ae=n.comments??[],ie=w?$e.includes(w):!1,V=Ee?.[0]??null;return ie&&V&&!Ie.some(T=>T.id===V)&&Ie.push({id:V,name:Pe,color:null}),{reportHubId:a.id,date:le(a.businessDate,"YYYY-MM-DD"),author:n.creatorName??O(a.createdBy)??"",userId:a.userId?u(a.userId):"",sourceType:a.sourceType??"Internal",createdAt:le(a.createdAt,"YYYY-MM-DD HH:mm:ss"),updatedAt:le(a.updatedAt,"YYYY-MM-DD HH:mm:ss"),updatedBy:O(a.updatedBy),employeeName:Q??n.creatorName??O(a.createdBy),category:b,creationCategory:w,visitTimeFrom:E,visitTimeTo:J,customerName:q,interviewers:f,subject:a.title,content:y,comments:se,isRead:n.isRead??!1,isStarred:n.isStarred??!1,labels:Ie,commentItems:Ae.map(T=>({...T,userId:u(T.userId),isMine:s?T.userId===s:!1})),attachments:n.attachments}},te=async(n,s)=>{let a=Oe(z,"draft_label"),p=await xe();return(await e.select({reportHubId:o.id,businessDate:o.businessDate,sourceType:o.sourceType}).from(o).leftJoin(a,G(h(a.hubId,o.id),ge(a.labelId,p))).where(G(pe(o.deletedAt),Ye(h(o.userId,s),pe(o.userId),pe(a.hubId)),k(n.visible))).orderBy(Le(o.businessDate),Le(o.id))).map(f=>({...f,businessDate:le(f.businessDate,"YYYY-MM-DD")}))},x=async(n,s,a)=>{let p=await de(s);if(!p)return[];if(Te(n.visible))return[];let y=Oe(z,"draft_label"),f=await xe();return(await e.select({reportHubId:o.id,businessDate:o.businessDate,sourceType:o.sourceType}).top(a).from(o).leftJoin(y,G(h(y.hubId,o.id),ge(y.labelId,f))).where(G(pe(o.deletedAt),Ye(h(o.userId,p),pe(o.userId),pe(y.hubId)),k(n.visible))).orderBy(Le(o.businessDate),Le(o.id))).map(w=>({...w,businessDate:le(w.businessDate,"YYYY-MM-DD")}))},ee=async(n,s)=>{let a=await Z(e.select({hub:Ce(o),internal:Ce($),creatorName:i.displayName,...W()}).from(o)).leftJoin($,h(o.id,$.hubId)).leftJoin(i,h(o.userId,i.id)).where(G(h(o.businessDate,Lt`${s}`),pe(o.deletedAt),k(n.visible))).orderBy(Le(o.id)),p=await qe(a.map(y=>y.hub.id));return a.map(y=>j({...y,attachments:p.get(y.hub.id)??[]}))},ue=n=>`${S}${n}`,me=new Map,de=async n=>{if(!t.disableUserIdCache&&me.has(n))return me.get(n)??null;let s=await m(n);return s!==null&&!t.disableUserIdCache&&me.set(n,s),s},Re=async(n,s,{forceRefresh:a=!1,snapshot:p=!1,ttlMsOverride:y}={})=>{let f=await de(s);if(!f)return[];if(Te(n.visible))return[];let b=Y(f,He(n));return c.getOrFetch({cacheKey:b,fetcher:async()=>await te(n,f),forceRefresh:a,snapshot:p,ttlMsOverride:y??ct,epochKey:ve,refreshAheadRatio:.5})},Me=(n,s,{forceRefresh:a=!1,snapshot:p=!1,ttlMsOverride:y}={})=>{let f=oe(s);return f?Te(n.visible)?Promise.resolve([]):c.getOrFetch({cacheKey:`${ue(f)}:st:${He(n)}`,fetcher:()=>ee(n,f),forceRefresh:a,snapshot:p,ttlMsOverride:y??U}):Promise.resolve([])},Ee=null,Fe=async()=>(Ee!==null||(Ee=(await e.select({id:K.id}).from(K).where(ge(K.name,$e)).orderBy(K.id)).map(s=>s.id)),Ee),xe=async()=>{let n=await Fe();return n.length>0?n:[-1]},Ze=async()=>{let n=await Fe();if(n.length===0)return null;let[s]=await e.select({id:K.id}).top(1).from(K).where(h(K.name,Pe));return s?.id??n[0]},Ht=(n,s)=>s!=null?"absent":n!=null?"present":"unknown",qe=async n=>{let s=new Map,a=r.attachment,p=t.attachmentIdCodec;if(n.length===0||!a||!p)return s;let y=await e.select({id:a.id,hubId:a.hubId,fileName:a.fileName,fileType:a.fileType,fileSize:a.fileSize,createdAt:a.createdAt,objectCheckedAt:a.objectCheckedAt,objectMissingAt:a.objectMissingAt}).from(a).where(ge(a.hubId,n)).orderBy(We(a.createdAt),We(a.id));for(let f of y){let b={id:p.encode(Number(f.id)),fileName:String(f.fileName),fileType:f.fileType?String(f.fileType):null,fileSize:f.fileSize!=null?Number(f.fileSize):null,createdAt:le(f.createdAt,"YYYY-MM-DD HH:mm:ss"),state:Ht(f.objectCheckedAt,f.objectMissingAt)},w=s.get(Number(f.hubId));w?w.push(b):s.set(Number(f.hubId),[b])}return s},Ot=async(n,s,a)=>{let p=r.attachment;if(!p||Te(n.visible))return null;let y=await xe(),f=Oe(z,"draft_label");return(await e.select({fileName:p.fileName,filePath:p.filePath,fileType:p.fileType,fileSize:p.fileSize}).top(1).from(p).innerJoin(o,h(o.id,p.hubId)).leftJoin(f,G(h(f.hubId,o.id),ge(f.labelId,y))).where(G(h(p.id,s),pe(o.deletedAt),Ye(h(o.userId,a),pe(f.hubId)),k(n.visible))))[0]??null},Yt=async n=>{let s=r.attachment;if(!s)return;let a=new Date;try{await e.update(s).set({objectCheckedAt:a,objectMissingAt:a,updatedAt:a}).where(h(s.id,n))}catch(p){ae.error("markAttachmentMissing failed",p)}},Ft=async n=>{let s=r.attachment;if(!s)return;let a=new Date;try{await e.update(s).set({objectCheckedAt:a,objectMissingAt:null,updatedAt:a}).where(h(s.id,n))}catch(p){ae.error("markAttachmentPresent failed",p)}},qt=async(n,s,a,{forceRefresh:p=!1,snapshot:y=!1,ttlMsOverride:f}={})=>{let b=await de(a);if(!b)return[];let w=oe(s);if(!w)return[];if(Te(n.visible))return[];let E=R(w,b,He(n));return c.getOrFetch({cacheKey:E,fetcher:async()=>{let J=await xe(),q=Oe(z,"draft_label"),Q=await Z(e.select({hub:Ce(o),internal:Ce($),isRead:P.isRead,isStarred:P.isStarred,creatorName:i.displayName,...W()}).from(o)).leftJoin($,h(o.id,$.hubId)).leftJoin(P,G(h(o.id,P.hubId),h(P.userId,b))).leftJoin(q,G(h(q.hubId,o.id),ge(q.labelId,J))).leftJoin(i,h(o.userId,i.id)).where(G(h(o.businessDate,Lt`${w}`),pe(o.deletedAt),Ye(h(o.userId,b),pe(q.hubId)),k(n.visible))).orderBy(Le(o.id));if(Q.length===0)return[];let se=Q.map(V=>V.hub.id),De=await e.select({hubId:z.hubId,id:K.id,name:K.name,color:K.color}).from(z).innerJoin(K,h(z.labelId,K.id)).where(ge(z.hubId,se)),ke=await e.select({hubId:d.hubId,id:d.id,body:d.body,createdAt:d.createdAt,userId:d.userId,userName:i.displayName}).from(d).leftJoin(i,h(d.userId,i.id)).where(ge(d.hubId,se)).orderBy(We(d.createdAt)),Ie=await qe(se),Ae=new Map,ie=new Map;for(let V of De){let T=Ae.get(V.hubId);T||(T=[],Ae.set(V.hubId,T)),T.push({id:V.id,name:V.name,color:V.color})}for(let V of ke){let T=ie.get(V.hubId);T||(T=[],ie.set(V.hubId,T)),T.push({id:V.id,content:V.body,createdAt:le(V.createdAt,"YYYY-MM-DD HH:mm:ss")||"",userId:V.userId,userName:V.userName||""})}return Q.map(V=>{let T=V.hub.id;return j({...V,attachments:Ie.get(T)??[],labels:Ae.get(T)||[],comments:ie.get(T)||[]},b)})},forceRefresh:p,snapshot:y,ttlMsOverride:f??U,epochKey:`${_}${w}`})},Ue=async(n,s,a,{forceRefresh:p=!1,snapshot:y=!1,ttlMsOverride:f}={})=>{if(Te(n.visible))return null;let b=M(s,a,He(n));return(await c.getOrFetch({cacheKey:b,fetcher:async()=>{let E=await xe(),J=Oe(z,"draft_label"),q=await Z(e.select({hub:Ce(o),internal:Ce($),isRead:P.isRead,isStarred:P.isStarred,creatorName:i.displayName,...W()}).from(o)).leftJoin($,h(o.id,$.hubId)).leftJoin(P,G(h(o.id,P.hubId),h(P.userId,a))).leftJoin(J,G(h(J.hubId,o.id),ge(J.labelId,E))).leftJoin(i,h(o.userId,i.id)).where(G(h(o.id,s),pe(o.deletedAt),Ye(h(o.userId,a),pe(J.hubId)),k(n.visible)));if(q.length===0)return[];let Q=q[0].hub.id,se=await e.select({id:K.id,name:K.name,color:K.color}).from(z).innerJoin(K,h(z.labelId,K.id)).where(h(z.hubId,Q)),De=await e.select({id:d.id,body:d.body,createdAt:d.createdAt,userId:d.userId,userName:i.displayName}).from(d).leftJoin(i,h(d.userId,i.id)).where(h(d.hubId,Q)).orderBy(We(d.createdAt)),ke=await qe([Q]),Ie=se.map(ie=>({id:ie.id,name:ie.name,color:ie.color})),Ae=De.map(ie=>({id:ie.id,content:ie.body,createdAt:le(ie.createdAt,"YYYY-MM-DD HH:mm:ss")||"",userId:ie.userId,userName:ie.userName||""}));return[j({...q[0],attachments:ke.get(Q)??[],labels:Ie,comments:Ae},a)]},forceRefresh:p,snapshot:y,ttlMsOverride:f??U,epochKey:`${A}${s}`}))[0]??null},zt=async(n,s,a,p={})=>{let y=await de(a);return y?Ue(n,s,y,p):null},Kt=async n=>{let[s]=await e.select({sourceType:o.sourceType,deletedAt:o.deletedAt}).top(1).from(o).where(h(o.id,n));return s??null},pt=async(n,s)=>{let a=await Kt(s);if(!a||a.deletedAt||!we(n.visible,a.sourceType))throw new Error("Not Found")},Vt=async(n,s,a,p,y,f)=>{await pt(n,a);let b=await e.select().top(1).from(P).where(G(h(P.hubId,a),h(P.userId,s))),w;if(b.length>0?b[0].isStarred!==y?w=(await e.update(P).set({isStarred:y,updatedAt:new Date,updatedBy:String(s)}).output().where(G(h(P.hubId,a),h(P.userId,s))))[0]:w=b[0]:w=(await e.insert(P).output().values({hubId:a,userId:s,isStarred:y,isRead:!1,createdAt:new Date,createdBy:String(s),updatedAt:new Date,updatedBy:String(s)}))[0],p){let E=oe(p);E&&(c.invalidatePrefix(X(E,s)),await D(`${_}${E}`))}return c.invalidate(`daily-report:detail:${a}`),c.invalidatePrefix(F(a,s)),await D(`${A}${a}`),await g(Ve.parse({type:"status-update",reportHubId:a,recipientRawUserId:s,statusType:"star",value:y,clientTempId:f}),"setStarStatus"),w},jt=async(n,s,a,p,y,f)=>{await pt(n,a);let b=await e.select().top(1).from(P).where(G(h(P.hubId,a),h(P.userId,s))),w;if(b.length>0?b[0].isRead!==y?w=(await e.update(P).set({isRead:y,updatedAt:new Date,updatedBy:String(s)}).output().where(G(h(P.hubId,a),h(P.userId,s))))[0]:w=b[0]:w=(await e.insert(P).output().values({hubId:a,userId:s,isRead:y,isStarred:!1,createdAt:new Date,createdBy:String(s),updatedAt:new Date,updatedBy:String(s)}))[0],p){let E=oe(p);E&&(c.invalidatePrefix(X(E,s)),await D(`${_}${E}`))}return c.invalidate(`daily-report:detail:${a}`),c.invalidatePrefix(F(a,s)),await D(`${A}${a}`),await g(Ve.parse({type:"status-update",reportHubId:a,recipientRawUserId:s,statusType:"read",value:y,clientTempId:f}),"setReadStatus"),w},mt=async(n,s)=>{if(s===null)return;let a=await xe(),[p]=await e.select({hubId:z.hubId}).top(1).from(z).where(G(h(z.hubId,n),ge(z.labelId,a)));return p?s:void 0},Jt=async(n,s,a,p,y,f)=>{let[b]=await e.select({sourceType:o.sourceType,deletedAt:o.deletedAt,userId:o.userId}).top(1).from(o).where(h(o.id,a));if(!b||b.deletedAt)throw new Error("Not Found");if(!we(n.visible,b.sourceType))throw new Error("Not Found");if(b.sourceType.toLowerCase()!=="internal")throw new Error("Comments are restricted for external daily report sources");let w=await mt(a,b.userId),[E]=await e.insert(d).output().values({hubId:a,userId:s,body:p,createdAt:new Date,createdBy:String(s),updatedAt:new Date,updatedBy:String(s)}),[J]=await e.select({displayName:i.displayName}).top(1).from(i).where(h(i.id,s)),q=J?.displayName??"Unknown";if(y){let se=oe(y);se&&(c.invalidatePrefix(`daily-report:date:${se}:user:`),await D(`${_}${se}`))}c.invalidate(`daily-report:detail:${a}`),c.invalidatePrefix(`daily-report:detail:${a}:user:`),await D(`${A}${a}`);let Q={id:E.id,userId:u(E.userId),userName:q,content:E.body,createdAt:le(E.createdAt,"YYYY-MM-DD HH:mm:ss")??"",isMine:!0};return await g(at.parse({type:"comment-add",reportHubId:a,comment:Q,clientTempId:f,recipientRawUserId:w,sourceType:b.sourceType}),"addComment"),Q},Gt=async(n,s)=>await n.select().top(1).from(d).where(h(d.id,s)),Qt=async(n,s,a,p,y,f)=>{let b=await Gt(e,p);if(b.length===0)throw new Error("Not Found");if(b[0].hubId!==a)throw new Error("Not Found");let[w]=await e.select({userId:o.userId,sourceType:o.sourceType}).top(1).from(o).where(h(o.id,b[0].hubId));if(!(w&&we(n.visible,w.sourceType)))throw new Error("Not Found");if(b[0].userId!==s)throw new Error("Unauthorized");let E=await mt(a,w.userId);if(await e.delete(d).where(h(d.id,p)),y){let J=oe(y);J&&(c.invalidatePrefix(`daily-report:date:${J}:user:`),await D(`${_}${J}`))}c.invalidate(`daily-report:detail:${a}`),c.invalidatePrefix(`daily-report:detail:${a}:user:`),await D(`${A}${a}`),await g(st.parse({type:"comment-delete",reportHubId:a,commentId:p,clientTempId:f,recipientRawUserId:E,sourceType:w?.sourceType}),"deleteComment")},Xt=async(n,s,a)=>{ae.info("createDailyReport called",{userId:n,businessDate:s});let[p]=await e.select({displayName:i.displayName}).from(i).where(h(i.id,n)),y=p?.displayName??u(n);try{let f=await e.transaction(async E=>{ae.info("Starting transaction");let J=`internal-temp-${Date.now()}-${Math.random()}`,[q]=await E.insert(o).output().values({sourceType:"Internal",sourceId:J,businessDate:new Date(s),userId:n,title:"(\u7121\u984C)",createdAt:new Date,createdBy:String(n),updatedAt:new Date,updatedBy:String(n)});await E.update(o).set({sourceId:String(q.id)}).where(h(o.id,q.id)),ae.info("Hub created",q),await E.insert($).values({hubId:q.id,body:"",createdAt:new Date,createdBy:String(n),updatedAt:new Date,updatedBy:String(n)}),ae.info("Internal created"),ae.info("Calling getDraftLabelId");let Q=await Ze();ae.info("draftLabelId",Q);let se=[];return Q&&(await E.insert(z).values({hubId:q.id,labelId:Q,createdAt:new Date,createdBy:String(n)}),se.push({id:Q,name:Pe,color:null})),ae.info("Label assigned"),{reportHubId:q.id,date:s,createdAt:le(q.createdAt,"YYYY-MM-DD HH:mm:ss"),author:y,userId:u(n),sourceType:"Internal",employeeName:y,updatedBy:u(n),updatedAt:le(q.updatedAt,"YYYY-MM-DD HH:mm:ss"),category:null,creationCategory:null,visitTimeFrom:null,visitTimeTo:null,customerName:null,interviewers:[],subject:q.title,content:"",comments:[],isRead:!0,isStarred:!1,labels:se,commentItems:[],attachments:[]}}),b=oe(s);b&&c.invalidatePrefix(X(b,n)),c.invalidatePrefix(S),c.invalidatePrefix(C(n)),await D(ve),b&&await D(`${_}${b}`);let w=await Ue(fe.unrestricted("post-write self read: the writer always sees the row they just wrote"),f.reportHubId,n,{forceRefresh:!0});if(w){let E=await Fe(),J=w.labels.some(q=>E.includes(q.id));await g(it.parse({type:"report-create",reportHubId:w.reportHubId,report:w,clientTempId:a,recipientRawUserId:J?n:void 0}),"createDailyReport")}return w??f}catch(f){throw ae.error("Error in createDailyReport",f),f}},ze=async(n,s)=>await n.select().top(1).from(o).where(h(o.id,s)),et=async(n,s,a)=>{await n.update(o).set(a).where(h(o.id,s))},yt=async(n,s,a)=>{await n.update($).set(a).where(h($.hubId,s))},ht=async(n,s,a)=>{await n.delete(z).where(G(h(z.hubId,s),h(z.labelId,a)))};return{streamKey:v,streamMaxLen:B,clearCache:async()=>{c.clearAll(),me.clear(),Ee=null,N&&await D(ve),ae.info("[DailyReportService] Server-side DB/SQL caches cleared successfully.")},invalidateHubReadCaches:async(n,s)=>{c.invalidatePrefix(S);for(let a of new Set(n))c.invalidatePrefix(`daily-report:detail:${a}:user:`),await D(`${A}${a}`);for(let a of new Set(s)){let p=oe(a);p&&await D(`${_}${p}`)}},getUserIdByExternalId:de,getDailyReportIdsByExternalId:Re,getDailyReportIdsFirstPageByExternalId:x,getDailyReportsByBusinessDate:Me,getDailyReportsByBusinessDateByExternalId:qt,getDailyReportDetailById:Ue,getDailyReportDetailByIdByExternalId:zt,getDraftLabelId:Ze,getAttachmentsByHubIds:qe,getAttachmentForUser:Ot,markAttachmentMissing:Yt,markAttachmentPresent:Ft,setStarStatus:Vt,setReadStatus:jt,addComment:Jt,deleteComment:Qt,createDailyReport:Xt,updateDailyReport:async(n,s,a,p)=>{let y=await ze(e,n);if(!y.length||y[0].deletedAt)throw new Error("Not Found");if(y[0].userId!==s)throw new Error("Unauthorized");await e.transaction(async w=>{a.title!==void 0&&await et(w,n,{title:a.title,updatedAt:new Date,updatedBy:String(s)}),a.content!==void 0&&await yt(w,n,{body:a.content,updatedAt:new Date,updatedBy:String(s)})}),c.invalidate(`daily-report:detail:${n}`),c.invalidatePrefix(`daily-report:detail:${n}:user:`),c.invalidatePrefix(S),await D(`${A}${n}`);let f=oe(le(y[0].businessDate,"YYYY-MM-DD"));f&&(c.invalidatePrefix(`daily-report:date:${f}:user:`),await D(`${_}${f}`));let b=await Ue(fe.unrestricted("post-write self read: the writer always sees the row they just wrote"),n,s,{forceRefresh:!0});if(b){let w=await Fe(),E=b.labels.some(J=>w.includes(J.id));await g(ot.parse({type:"report-update",reportHubId:b.reportHubId,report:b,clientTempId:p,recipientRawUserId:E?s:void 0}),"updateDailyReport")}},publishDailyReport:async(n,s,a)=>{let p=await ze(e,n);if(!p.length)throw new Error("Not Found");if(p[0].userId!==s)throw new Error("Unauthorized");let y=await Ze();if(!y)return null;if(await ht(e,n,y),c.invalidatePrefix(`daily-report:detail:${n}:user:`),c.invalidatePrefix(S),c.invalidatePrefix(Be),await D(ve),p[0].businessDate){let w=oe(le(p[0].businessDate,"YYYY-MM-DD"));w&&await D(`${_}${w}`)}let f=oe(le(p[0].businessDate,"YYYY-MM-DD"));f&&c.invalidatePrefix(X(f,s));let b=await Ue(fe.unrestricted("post-write self read: the writer always sees the row they just wrote"),n,s,{forceRefresh:!0});return b&&await g(lt.parse({type:"report-publish",reportHubId:b.reportHubId,report:b,clientTempId:a}),"publishDailyReport"),b??null},deleteDailyReport:async(n,s,a)=>{let p=await ze(e,n);if(!p.length||p[0].deletedAt)throw new Error("Not Found");if(p[0].userId!==s)throw new Error("Unauthorized");if(await et(e,n,{deletedAt:new Date,deletedBy:String(s),updatedAt:new Date,updatedBy:String(s)}),c.invalidatePrefix(`daily-report:detail:${n}:user:`),c.invalidatePrefix(S),c.invalidatePrefix(Be),await D(ve),p[0].businessDate){let y=oe(le(p[0].businessDate,"YYYY-MM-DD"));y&&await D(`${_}${y}`)}await g(ut.parse({type:"report-delete",reportHubId:n,clientTempId:a,sourceType:p[0].sourceType}),"deleteDailyReport")},findDailyReportHubById:ze,updateDailyReportHub:et,updateDailyReportInternal:yt,deleteDailyReportLabel:ht}}import{and as Or,eq as Pt}from"drizzle-orm";function Yr(t){let e=[],r=t&&t.length>0?t:[{key:"internal",name:"Internal",description:"Internal daily reports"},{key:"external",name:"External",description:"External daily reports"}];for(let i of r){let u=`daily_report_${i.key.toLowerCase().replace(/[^a-z0-9_]/g,"_")}`;e.push({resourceKey:u,name:i.name,description:i.description??`${i.name} daily report access`}),i.includeCommentResource!==!1&&e.push({resourceKey:`${u}_comment`,name:`${i.name} Comment`,description:`${i.name} daily report comment access`})}return e}async function Nn(t,e,r){let i=t,m=e.TMResource,u=r.appKey,I=r.actor??"system:daily-report",c=new Date,N=r.resources??Yr(r.sources);for(let o of N){let $=await i.select().from(m).where(Or(Pt(m.appKey,u),Pt(m.resourceKey,o.resourceKey)));(!$||$.length===0)&&await i.insert(m).values({appKey:u,resourceKey:o.resourceKey,name:o.name,description:o.description??null,createdAt:c,createdBy:I,updatedAt:c,updatedBy:I})}}var Fr=ce(1,"[DailyReportExternalSource]"),Pn=(t,e,r,i=Fr)=>{if(!t)return[];try{let m=JSON.parse(t);return Array.isArray(m)?m.map(r).filter(u=>u!==null):(i.warn(`Unexpected ${e} format: not an array`),[])}catch(m){return i.warn(`Failed to parse ${e}:`,m),[]}};import{desc as Bt,sql as qr}from"drizzle-orm";import{bigint as re,bit as Ut,date as zr,datetime2 as ne,foreignKey as be,index as Se,int as Kr,mssqlSchema as Vr,nvarchar as H,primaryKey as _e,uniqueIndex as jr}from"drizzle-orm/mssql-core";function On(t,e){let r=Vr(t),i=e.userTable,m=r.table("DailyReportHub",{id:re("id",{mode:"number"}).identity().notNull(),sourceType:H("source_type",{length:20}).notNull(),sourceId:H("source_id",{length:100}).notNull(),sourceIdNum:re("source_id_num",{mode:"number"}).generatedAlwaysAs(qr`TRY_CAST(source_id AS BIGINT)`),businessDate:zr("business_date"),userId:re("user_id",{mode:"number"}),title:H("title",{length:200}),summary:H("summary",{length:"max"}),createdAt:ne("created_at").notNull(),createdBy:H("created_by",{length:50}).notNull(),updatedAt:ne("updated_at").notNull(),updatedBy:H("updated_by",{length:50}).notNull(),deletedAt:ne("deleted_at"),deletedBy:H("deleted_by",{length:50})},d=>[_e({name:`${t}_DailyReportHub_pk`,columns:[d.id]}),be({name:`${t}_DailyReportHub_user_id_fk`,columns:[d.userId],foreignColumns:[i.id]}),Se(`${t}_DailyReportHub_business_date_index`).on(d.businessDate),Se(`${t}_DailyReportHub_updated_at_index`).on(d.updatedAt),Se(`${t}_DailyReportHub_source_index`).on(d.sourceType,d.sourceId),Se(`${t}_DailyReportHub_user_id_index`).on(d.userId),Se(`${t}_DailyReportHub_business_date_id_index`).on(Bt(d.businessDate),Bt(d.id)),Se(`${t}_DailyReportHub_deleted_at_index`).on(d.deletedAt)]),u=r.table("DailyReportInternal",{hubId:re("hub_id",{mode:"number"}).notNull(),body:H("body",{length:"max"}),metadata:H("metadata",{length:"max"}),createdAt:ne("created_at").notNull(),createdBy:H("created_by",{length:50}).notNull(),updatedAt:ne("updated_at").notNull(),updatedBy:H("updated_by",{length:50}).notNull()},d=>[_e({name:`${t}_DailyReportInternal_pk`,columns:[d.hubId]}),be({name:`${t}_DailyReportInternal_hub_id_fk`,columns:[d.hubId],foreignColumns:[m.id]})]),I=r.table("DailyReportComment",{id:re("id",{mode:"number"}).identity().notNull(),hubId:re("hub_id",{mode:"number"}).notNull(),userId:re("user_id",{mode:"number"}).notNull(),body:H("body",{length:"max"}).notNull(),createdAt:ne("created_at").notNull(),createdBy:H("created_by",{length:50}).notNull(),updatedAt:ne("updated_at").notNull(),updatedBy:H("updated_by",{length:50}).notNull()},d=>[_e({name:`${t}_DailyReportComment_pk`,columns:[d.id]}),be({name:`${t}_DailyReportComment_hub_id_fk`,columns:[d.hubId],foreignColumns:[m.id]}),be({name:`${t}_DailyReportComment_user_id_fk`,columns:[d.userId],foreignColumns:[i.id]}),Se(`${t}_DailyReportComment_hub_id_index`).on(d.hubId)]),c=r.table("DailyReportLabel",{id:re("id",{mode:"number"}).identity().notNull(),userId:re("user_id",{mode:"number"}),name:H("name",{length:50}).notNull(),color:H("color",{length:20}),sortOrder:Kr("sort_order"),createdAt:ne("created_at").notNull(),createdBy:H("created_by",{length:50}).notNull(),updatedAt:ne("updated_at").notNull(),updatedBy:H("updated_by",{length:50}).notNull()},d=>[_e({name:`${t}_DailyReportLabel_pk`,columns:[d.id]}),be({name:`${t}_DailyReportLabel_user_id_fk`,columns:[d.userId],foreignColumns:[i.id]})]),N=r.table("DailyReportHub_Label",{hubId:re("hub_id",{mode:"number"}).notNull(),labelId:re("label_id",{mode:"number"}).notNull(),createdAt:ne("created_at").notNull(),createdBy:H("created_by",{length:50}).notNull()},d=>[_e({name:`${t}_DailyReportHub_Label_pk`,columns:[d.hubId,d.labelId]}),be({name:`${t}_DailyReportHub_Label_hub_id_fk`,columns:[d.hubId],foreignColumns:[m.id]}),be({name:`${t}_DailyReportHub_Label_label_id_fk`,columns:[d.labelId],foreignColumns:[c.id]})]),o=r.table("DailyReportUserStatus",{hubId:re("hub_id",{mode:"number"}).notNull(),userId:re("user_id",{mode:"number"}).notNull(),isRead:Ut("is_read").default(!1).notNull(),isStarred:Ut("is_starred").default(!1).notNull(),createdAt:ne("created_at").notNull(),createdBy:H("created_by",{length:50}).notNull(),updatedAt:ne("updated_at").notNull(),updatedBy:H("updated_by",{length:50}).notNull()},d=>[_e({name:`${t}_DailyReportUserStatus_pk`,columns:[d.hubId,d.userId]}),be({name:`${t}_DailyReportUserStatus_hub_id_fk`,columns:[d.hubId],foreignColumns:[m.id]}),be({name:`${t}_DailyReportUserStatus_user_id_fk`,columns:[d.userId],foreignColumns:[i.id]})]),$=r.table("DailyReportAttachment",{id:re("id",{mode:"number"}).identity().notNull(),hubId:re("hub_id",{mode:"number"}).notNull(),uploadedBy:re("uploaded_by",{mode:"number"}),sourceKey:H("source_key",{length:200}).notNull(),fileName:H("file_name",{length:255}).notNull(),filePath:H("file_path",{length:"max"}).notNull(),fileType:H("file_type",{length:100}),fileSize:re("file_size",{mode:"number"}),objectCheckedAt:ne("object_checked_at"),objectMissingAt:ne("object_missing_at"),createdAt:ne("created_at").notNull(),createdBy:H("created_by",{length:50}).notNull(),updatedAt:ne("updated_at").notNull(),updatedBy:H("updated_by",{length:50}).notNull()},d=>[_e({name:`${t}_DailyReportAttachment_pk`,columns:[d.id]}),be({name:`${t}_DailyReportAttachment_hub_id_fk`,columns:[d.hubId],foreignColumns:[m.id]}),be({name:`${t}_DailyReportAttachment_uploaded_by_fk`,columns:[d.uploadedBy],foreignColumns:[i.id]}),jr(`${t}_DailyReportAttachment_source_unique`).on(d.hubId,d.sourceKey),Se(`${t}_DailyReportAttachment_hub_id_index`).on(d.hubId,d.createdAt)]);return{hub:m,internal:u,comment:I,attachment:$,label:c,hubLabel:N,userStatus:o}}function Vn(t){let e=Dt(t.redis),r=new Ke({defaultTtlMs:t.cacheDefaultTtlMs??6e4},e),i=$t({...t,cache:r,epochs:e}),m=new Je({redis:t.redis,streamKey:i.streamKey,cache:r,logger:t.logger}),u=Nt({authenticate:t.authenticate,resolveVisibleSourceTypes:t.resolveVisibleSourceTypes,service:i,encodeUserId:t.encodeUserId,attachmentIdCodec:t.attachmentIdCodec,readAttachment:t.readAttachment,attachmentMaxBytes:t.attachmentMaxBytes,attachmentRateLimitPerMinute:t.attachmentRateLimitPerMinute,attachmentConcurrency:t.attachmentConcurrency,redis:t.redis,sseReader:m,streamKey:i.streamKey,loginRedirectPath:t.loginRedirectPath,enableDevCacheClear:t.enableDevCacheClear,logger:t.logger});return{service:i,cache:r,epochs:e,sseReader:m,streamKey:i.streamKey,knownSourceTypes:[...new Set(["Internal",...(t.externalSources??[]).map(I=>I.sourceType)])],...u}}export{Je as DailyReportSseReader,fe as DailyReportViewerScope,Ke as SqlResultCache,kr as asciiFallbackFileName,_t as buildVisibleSourceTypeCondition,hr as computeSourceTypeDigest,He as computeViewerScopeDigest,Nt as createDailyReportHandlers,Vn as createDailyReportServer,$t as createDailyReportService,Dt as createEpochStore,Yr as defineDailyReportAuthzResources,On as defineDailyReportSchema,Te as deniesEverySourceType,xr as encodeRfc8187,le as formatDateValue,dt as generateETag,we as isSourceTypeVisible,Ge as isStreamIdLte,he as jsonResponseWithETag,yr as normalizeVisibleSourceTypes,xt as sanitizeMediaType,Nn as seedDailyReportAuthzResources,Pn as transformJsonArray};
16
16
  //# sourceMappingURL=server.mjs.map