@aiquants/daily-report 0.3.0 → 0.3.1
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.d.mts +5 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.js +4 -4
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +4 -4
- package/dist/server.mjs.map +1 -1
- package/package.json +3 -3
- package/src/server/cache.spec.ts +47 -0
- package/src/server/cache.ts +18 -0
package/dist/server.d.mts
CHANGED
|
@@ -148,6 +148,11 @@ declare class SqlResultCache {
|
|
|
148
148
|
* 指定されたプレフィックスに一致するキャッシュバケットを無効化します。
|
|
149
149
|
*/
|
|
150
150
|
invalidatePrefix: (prefix: string) => void;
|
|
151
|
+
/**
|
|
152
|
+
* Cleans up all expired cache buckets to prevent memory accumulation.
|
|
153
|
+
* メモリー蓄積を防ぐため、期限切れのキャッシュバケットをすべてクリーンアップする処理。
|
|
154
|
+
*/
|
|
155
|
+
private cleanExpired;
|
|
151
156
|
}
|
|
152
157
|
|
|
153
158
|
/**
|
package/dist/server.d.ts
CHANGED
|
@@ -148,6 +148,11 @@ declare class SqlResultCache {
|
|
|
148
148
|
* 指定されたプレフィックスに一致するキャッシュバケットを無効化します。
|
|
149
149
|
*/
|
|
150
150
|
invalidatePrefix: (prefix: string) => void;
|
|
151
|
+
/**
|
|
152
|
+
* Cleans up all expired cache buckets to prevent memory accumulation.
|
|
153
|
+
* メモリー蓄積を防ぐため、期限切れのキャッシュバケットをすべてクリーンアップする処理。
|
|
154
|
+
*/
|
|
155
|
+
private cleanExpired;
|
|
151
156
|
}
|
|
152
157
|
|
|
153
158
|
/**
|
package/dist/server.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
"use strict";var Se=Object.defineProperty;var Ve=Object.getOwnPropertyDescriptor;var Ze=Object.getOwnPropertyNames;var et=Object.prototype.hasOwnProperty;var tt=(r,t)=>{for(var i in t)Se(r,i,{get:t[i],enumerable:!0})},rt=(r,t,i,l)=>{if(t&&typeof t=="object"||typeof t=="function")for(let m of Ze(t))!et.call(r,m)&&m!==i&&Se(r,m,{get:()=>t[m],enumerable:!(l=Ve(t,m))||l.enumerable});return r};var nt=r=>rt(Se({},"__esModule",{value:!0}),r);var gt={};tt(gt,{DailyReportSseReader:()=>pe,SqlResultCache:()=>ce,createDailyReportHandlers:()=>Ne,createDailyReportServer:()=>yt,createDailyReportService:()=>Ee,createEpochStore:()=>Ie,defineDailyReportSchema:()=>mt,generateETag:()=>Re,isStreamIdLte:()=>me,jsonResponseWithETag:()=>Z,transformJsonArray:()=>pt});module.exports=nt(gt);var Ie=r=>({async getEpoch(t){try{let i=await r?.getClient();if(!i)return 0;let l=await i.get(t);return l?Number(l):0}catch{return 0}},async incrementEpoch(t){try{let i=await r?.getClient();if(!i)return;await i.incr(t)}catch{}}}),ce=class{constructor(t,i){this.config=t;this.epochStore=i;this.buckets=new Map;this.inFlight=new Map;this.invalidate=t=>{this.buckets.delete(t),this.inFlight.delete(t)};this.getOrFetch=async t=>{let{cacheKey:i,forceRefresh:l,snapshot:m}=t,f=this.buckets.get(i);if(l&&(this.buckets.delete(i),this.inFlight.delete(i)),!l&&f&&f.expireAt>Date.now())if(t.epochKey){let c=await this.epochStore.getEpoch(t.epochKey);if(f.epoch===c)return m?f.records.map(W=>structuredClone(W)):f.records;this.buckets.delete(i)}else return m?f.records.map(c=>structuredClone(c)):f.records;if(!l&&this.inFlight.has(i)){let c=await this.inFlight.get(i);return m?c.map(W=>structuredClone(W)):c}let O;O=(async()=>{let c=await t.fetcher();if(l||this.inFlight.get(i)===O){let W=Date.now()+(t.ttlMsOverride??this.config.defaultTtlMs),p=t.epochKey?await this.epochStore.getEpoch(t.epochKey):0;this.buckets.set(i,{records:c,expireAt:W,epoch:p})}return c})(),l||this.inFlight.set(i,O);try{let c=await O;return m?c.map(W=>structuredClone(W)):c}finally{this.inFlight.delete(i)}};this.flush=t=>{this.buckets.delete(t),this.inFlight.delete(t)};this.invalidatePrefix=t=>{for(let i of this.buckets.keys())i.startsWith(t)&&this.buckets.delete(i);for(let i of this.inFlight.keys())i.startsWith(t)&&this.inFlight.delete(i)}}};var at=/^\d{4}-\d{2}-\d{2}$/,ot=/^\d{4}\/\d{2}\/\d{2}$/,ke=r=>r<10?`0${r}`:`${r}`,Be=r=>{if(Number.isNaN(r.getTime()))return null;let t=r.getFullYear(),i=ke(r.getMonth()+1),l=ke(r.getDate());return`${t}-${i}-${l}`},G=r=>{if(r==null)return null;if(r instanceof Date)return Be(r);let t=r.trim();if(t==="")return null;if(at.test(t))return t;if(ot.test(t))return t.replaceAll("/","-");let i=new Date(t);return Be(i)};var te=(r,t,i=console)=>{let l=m=>typeof m=="string"?[`${t} ${m}`]:[t,m];return{debug:(m,...f)=>{r<=0&&i.debug(...l(m),...f)},info:(m,...f)=>{r<=1&&i.info(...l(m),...f)},warn:(m,...f)=>{r<=2&&i.warn(...l(m),...f)},error:(m,...f)=>{r<=3&&i.error(...l(m),...f)}}};var s=require("zod"),it=s.z.object({name:s.z.string(),affiliation:s.z.string().nullable()}),st=s.z.object({name:s.z.string().nullable(),text:s.z.string().nullable(),color:s.z.string().nullable()}),lt=s.z.object({id:s.z.number(),name:s.z.string(),color:s.z.string().nullable()}),Ue=s.z.object({id:s.z.number(),userId:s.z.string(),userName:s.z.string(),content:s.z.string(),createdAt:s.z.string(),isMine:s.z.boolean()}),_e=s.z.object({reportHubId:s.z.number(),date:s.z.string().nullable(),createdAt:s.z.string().nullable(),author:s.z.string(),userId:s.z.string(),sourceType:s.z.string().nullable(),employeeName:s.z.string().nullable(),updatedBy:s.z.string().nullable(),updatedAt:s.z.string().nullable(),category:s.z.string().nullable(),creationCategory:s.z.string().nullable(),visitTimeFrom:s.z.string().nullable(),visitTimeTo:s.z.string().nullable(),customerName:s.z.string().nullable(),interviewers:s.z.array(it),subject:s.z.string().nullable(),content:s.z.string().nullable(),comments:s.z.array(st),isRead:s.z.boolean(),isStarred:s.z.boolean(),labels:s.z.array(lt),commentItems:s.z.array(Ue)}),dt=s.z.object({type:s.z.literal("connected")}),he=s.z.object({type:s.z.literal("status-update"),reportHubId:s.z.number(),statusType:s.z.enum(["star","read"]),value:s.z.boolean(),clientTempId:s.z.string(),recipientRawUserId:s.z.number().optional()}),Ce=s.z.object({type:s.z.literal("comment-add"),reportHubId:s.z.number(),comment:Ue,clientTempId:s.z.string()}),Ae=s.z.object({type:s.z.literal("comment-delete"),reportHubId:s.z.number(),commentId:s.z.number(),clientTempId:s.z.string()}),Te=s.z.object({type:s.z.literal("report-create"),reportHubId:s.z.number(),report:_e,clientTempId:s.z.string(),recipientRawUserId:s.z.number().optional()}),Me=s.z.object({type:s.z.literal("report-update"),reportHubId:s.z.number(),report:_e,clientTempId:s.z.string(),recipientRawUserId:s.z.number().optional()}),ve=s.z.object({type:s.z.literal("report-publish"),reportHubId:s.z.number(),report:_e,clientTempId:s.z.string()}),xe=s.z.object({type:s.z.literal("report-delete"),reportHubId:s.z.number(),clientTempId:s.z.string()}),He=s.z.discriminatedUnion("type",[dt,he,Ce,Ae,Te,Me,ve,xe]);var Ye=require("crypto"),Re=r=>{let t=JSON.stringify(r);return`"${(0,Ye.createHash)("sha256").update(t).digest("hex")}"`};var ut=te(1,"[Response]"),Z=(r,t,i,l=200,m=ut)=>{let f=Re(i),O=r.headers.get("If-None-Match");m.info(`[jsonResponseWithETag] ETag: ${f}, If-None-Match: ${O}`);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:f});return t&&c.append("Set-Cookie",t),r.method==="GET"&&l===200&&O===f?new Response(null,{status:304,headers:c}):new Response(JSON.stringify(i),{status:l,headers:c})};var qe=require("events");var me=(r,t)=>{let[i,l]=r.split("-").map(Number),[m,f]=t.split("-").map(Number);return i!==m?i<m:l<=f},pe=class{constructor(t){this.config=t;this._emitter=new qe.EventEmitter;this._state="idle";this._refCount=0;this._lastId="0-0";this._emitter.setMaxListeners(0),this._logger=t.logger??te(1,"[SSE Reader]")}subscribe(t,i){return this._emitter.on("entry",t),i&&this._emitter.on("error",i),this._refCount++,this._refCount===1&&this._startLoop(),()=>{this._emitter.removeListener("entry",t),i&&this._emitter.removeListener("error",i),this._refCount--,this._refCount<=0&&(this._refCount=0,this._stopLoop())}}async destroy(){this._refCount=0,await this._stopLoop(),this._emitter.removeAllListeners(),this._lastId="0-0"}async _startLoop(){for(;this._state==="stopping";)await new Promise(t=>setTimeout(t,50));if(this._state!=="running"){this._state="running";try{this._client=await this.config.redis?.createClient()}catch(t){this._state="idle",this._emitter.emit("error",t instanceof Error?t:new Error("Failed to create Redis client for SSE reader"));return}if(!this._client){this._state="idle",this._emitter.emit("error",new Error("Failed to create Redis client for SSE reader"));return}this._client.on("error",t=>{this._logger.error("Redis client error:",t)});try{for(;this._state==="running"&&this._client?.isOpen;){let t=await this._client.xRead([{key:this.config.streamKey,id:this._lastId}],{BLOCK:5e3,COUNT:100});if(t)for(let i of t)for(let l of i.messages){this._lastId=l.id;try{let m=l.message?.data?JSON.parse(l.message.data):null,f=m?.type;if((f==="report-create"||f==="report-delete"||f==="report-publish")&&this.config.cache.invalidatePrefix("daily-report:ids"),f==="comment-add"||f==="comment-delete"||f==="status-update"){let O=m?.reportHubId;typeof O=="number"&&(this.config.cache.invalidate(`daily-report:detail:${O}`),this.config.cache.invalidatePrefix(`daily-report:detail:${O}:user:`))}}catch{}this._emitter.emit("entry",{id:l.id,message:l.message})}}}catch(t){!(t?.constructor?.name==="ClientClosedError")&&this._state==="running"&&(this._logger.error("xRead loop error:",t),this._emitter.emit("error",t))}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!=="idle";)await new Promise(t=>setTimeout(t,50))}}};var v=(r,t)=>new Response(JSON.stringify(r),{status:t?.status??200,headers:{"Content-Type":"application/json"}});function Ne(r){let{authenticate:t,service:i,encodeUserId:l,redis:m,sseReader:f,streamKey:O}=r,c=r.loginRedirectPath??"/auth/login",W=r.logger??te(3,"[DailyReportAPI]"),p=r.logger??te(1,"[DailyReportSSE]"),g=async({request:A})=>{let{user:k,cookie:_}=await t(A,{failureRedirect:c}),P=new Headers;_&&P.append("Set-Cookie",_);let C=null;k&&(C=await i.getUserIdByExternalId(k.id));let S=C?l(C):null;return{data:{user:k,userId:S},headers:P}},$={"business-date":async(A,k,_,P)=>{let C=G(A.searchParams.get("businessDate")),S=A.searchParams.get("forceRefresh")==="true";if(!C)return Z(_,k,{error:{message:"Invalid business date"}},400);let B=await i.getDailyReportsByBusinessDateByExternalId(C,P.id,{forceRefresh:S});return Z(_,k,{businessDate:C,reports:B},200)},ids:async(A,k,_,P)=>{let C=A.searchParams.get("forceRefresh")==="true",S=await i.getDailyReportIdsByExternalId(P.id,{forceRefresh:C});return Z(_,k,{ids:S},200)},report:async(A,k,_,P)=>{let C=A.searchParams.get("reportHubId"),S=A.searchParams.get("forceRefresh")==="true",B=C?Number.parseInt(C,10):NaN;if(!Number.isFinite(B)||B<=0)return Z(_,k,{error:{message:"Invalid reportHubId"}},400);let x=await i.getDailyReportDetailByIdByExternalId(B,P.id,{snapshot:!0,forceRefresh:S});return x?Z(_,k,{report:x},200):Z(_,k,{error:{message:"Report not found"}},404)}};return{index:{loader:g},api:{loader:async({request:A,params:k})=>{let{user:_,cookie:P}=await t(A,{failureRedirect:null}),C=P??null;if(!_)return Z(A,C,{error:{message:"Unauthorized"}},401);if(A.method!=="GET")return Z(A,C,{error:{message:"Method not allowed"}},405);let S=k.endpoint??"",B=$[S];if(!B)return Z(A,C,{error:{message:"Unknown endpoint"}},404);let x=Date.now();try{let w=new URL(A.url);return await B(w,C,A,_)}catch(w){let q=Date.now()-x,j=w instanceof Error?w:new Error(String(w));return W.error(`500 endpoint=${S} elapsed=${q}ms name=${j.name} code=${"code"in j?j.code:"N/A"} message=${j.message}`),W.error("Stack:",j.stack),Z(A,C,{error:{message:"Internal Server Error"}},500)}},action:async({request:A,params:k})=>{let{user:_}=await t(A,{failureRedirect:null});if(!_)return v({error:"Unauthorized"},{status:401});if(k.endpoint!=="action")return v({error:"Unknown endpoint"},{status:404});let C=await i.getUserIdByExternalId(_.id);if(!C)return v({error:"User not found"},{status:404});let S=await A.formData(),B=S.get("intent"),x=S.get("reportHubId"),w=x?Number(x):NaN,q=S.get("businessDate"),j=Number(S.get("operationTimestamp")),N=S.get("clientTempId");if(!N)return v({error:"clientTempId required"},{status:400});if(B!=="create"&&(!w||Number.isNaN(w)))return v({error:"Invalid reportHubId"},{status:400});switch(B){case"create":{if(!q)return v({error:"businessDate required"},{status:400});let y=await i.createDailyReport(C,q,N);return v({status:"OK",intent:"create",report:y,reportHubId:String(y.reportHubId),clientTempId:N})}case"update":{let y=S.get("title"),L=S.get("content");try{return await i.updateDailyReport(w,C,{title:y,content:L},N),v({status:"OK",intent:"update",reportHubId:String(w),clientTempId:N})}catch(T){if(T instanceof Error){if(T.message==="Unauthorized")return v({error:"Unauthorized"},{status:403});if(T.message==="Not Found")return v({error:"Report not found"},{status:404})}throw T}}case"publish":try{let y=await i.publishDailyReport(w,C,N);return v({status:"OK",intent:"publish",reportHubId:String(w),clientTempId:N,report:y})}catch(y){if(y instanceof Error){if(y.message==="Unauthorized")return v({error:"Unauthorized"},{status:403});if(y.message==="Not Found")return v({error:"Report not found"},{status:404})}throw y}case"delete":try{return await i.deleteDailyReport(w,C,N),v({status:"OK",intent:"delete",reportHubId:String(w),clientTempId:N})}catch(y){if(y instanceof Error){if(y.message==="Unauthorized")return v({error:"Unauthorized"},{status:403});if(y.message==="Not Found")return v({error:"Report not found"},{status:404})}throw y}case"toggleStar":{let y=S.get("isStarred");if(y===null)return v({error:"isStarred required"},{status:400});let L=y==="true",T=await i.setStarStatus(C,w,q,L,N);return v({status:"OK",intent:"toggleStar",updatedStatus:{isStarred:T.isStarred,isRead:T.isRead},operationTimestamp:j,reportHubId:String(w),clientTempId:N})}case"toggleRead":{let y=S.get("isRead");if(y===null)return v({error:"isRead required"},{status:400});let L=y==="true",T=await i.setReadStatus(C,w,q,L,N);return v({status:"OK",intent:"toggleRead",updatedStatus:{isStarred:T.isStarred,isRead:T.isRead},operationTimestamp:j,reportHubId:String(w),clientTempId:N})}case"addComment":{let y=S.get("content");if(!y)return v({error:"Content required"},{status:400});let L=await i.addComment(C,w,y,q,N),T={...L,userId:L.userId};return v({status:"OK",intent:"addComment",newComment:T,reportHubId:String(w),clientTempId:N})}case"deleteComment":{let y=Number(S.get("commentId"));if(!y||Number.isNaN(y))return v({error:"Invalid commentId"},{status:400});try{return await i.deleteComment(C,w,y,q,N),v({status:"OK",reportHubId:String(w),deletedCommentId:String(y),clientTempId:N})}catch(L){if(L instanceof Error){if(L.message==="Unauthorized")return v({error:"Unauthorized"},{status:403});if(L.message==="Not Found")return v({error:"Comment not found"},{status:404})}throw L}}default:return v({error:"Invalid intent"},{status:400})}}},sse:{loader:async({request:A,params:k})=>{let{user:_}=await t(A,{failureRedirect:null});if(!_)return new Response("Unauthorized",{status:401});let P=await i.getUserIdByExternalId(_.id);if(!P)return new Response("Forbidden",{status:403});if(k.endpoint!=="updates")return new Response("Not Found",{status:404});let S=new URL(A.url).searchParams.get("lastEventId")||A.headers.get("Last-Event-ID"),B=new TextEncoder,x=null,w=null,q=null,j=!1,N=()=>{if(!j){if(j=!0,w&&(clearInterval(w),w=null),q&&(q(),q=null),x)try{x.desiredSize!==null&&x.close()}catch{}finally{x=null}j=!1}},y=(T,K)=>{if(K.data)try{let M=JSON.parse(K.data),Q=He.safeParse(M);if(!Q.success){p.error("SSE message validation failed:",Q.error.format());return}let ee=Q.data,ae=typeof M.recipientRawUserId=="number"?M.recipientRawUserId:void 0;if(ee.type==="status-update"){if(ae===void 0||ae!==P)return}else if(ae!==void 0&&ae!==P)return;let se;if("recipientRawUserId"in M){let{recipientRawUserId:$e,...le}=M;se=JSON.stringify(le)}else se=K.data;x&&x.desiredSize!==null&&x.enqueue(B.encode(`id: ${T}
|
|
1
|
+
"use strict";var Se=Object.defineProperty;var Ve=Object.getOwnPropertyDescriptor;var Ze=Object.getOwnPropertyNames;var et=Object.prototype.hasOwnProperty;var tt=(r,t)=>{for(var o in t)Se(r,o,{get:t[o],enumerable:!0})},rt=(r,t,o,l)=>{if(t&&typeof t=="object"||typeof t=="function")for(let m of Ze(t))!et.call(r,m)&&m!==o&&Se(r,m,{get:()=>t[m],enumerable:!(l=Ve(t,m))||l.enumerable});return r};var nt=r=>rt(Se({},"__esModule",{value:!0}),r);var gt={};tt(gt,{DailyReportSseReader:()=>pe,SqlResultCache:()=>ce,createDailyReportHandlers:()=>Ne,createDailyReportServer:()=>yt,createDailyReportService:()=>Ee,createEpochStore:()=>Ie,defineDailyReportSchema:()=>mt,generateETag:()=>Re,isStreamIdLte:()=>me,jsonResponseWithETag:()=>Z,transformJsonArray:()=>pt});module.exports=nt(gt);var Ie=r=>({async getEpoch(t){try{let o=await r?.getClient();if(!o)return 0;let l=await o.get(t);return l?Number(l):0}catch{return 0}},async incrementEpoch(t){try{let o=await r?.getClient();if(!o)return;await o.incr(t)}catch{}}}),ce=class{constructor(t,o){this.config=t;this.epochStore=o;this.buckets=new Map;this.inFlight=new Map;this.invalidate=t=>{this.buckets.delete(t),this.inFlight.delete(t)};this.getOrFetch=async t=>{let{cacheKey:o,forceRefresh:l,snapshot:m}=t,f=this.buckets.get(o);if(l&&(this.buckets.delete(o),this.inFlight.delete(o)),!l&&f&&f.expireAt>Date.now())if(t.epochKey){let c=await this.epochStore.getEpoch(t.epochKey);if(f.epoch===c)return m?f.records.map(W=>structuredClone(W)):f.records;this.buckets.delete(o)}else return m?f.records.map(c=>structuredClone(c)):f.records;if(!l&&this.inFlight.has(o)){let c=await this.inFlight.get(o);return m?c.map(W=>structuredClone(W)):c}let O;O=(async()=>{let c=await t.fetcher();if(l||this.inFlight.get(o)===O){let W=Date.now()+(t.ttlMsOverride??this.config.defaultTtlMs),p=t.epochKey?await this.epochStore.getEpoch(t.epochKey):0;this.buckets.set(o,{records:c,expireAt:W,epoch:p}),this.buckets.size>500&&this.cleanExpired()}return c})(),l||this.inFlight.set(o,O);try{let c=await O;return m?c.map(W=>structuredClone(W)):c}finally{this.inFlight.delete(o)}};this.flush=t=>{this.buckets.delete(t),this.inFlight.delete(t)};this.invalidatePrefix=t=>{for(let o of this.buckets.keys())o.startsWith(t)&&this.buckets.delete(o);for(let o of this.inFlight.keys())o.startsWith(t)&&this.inFlight.delete(o)}}cleanExpired(){let t=Date.now();for(let[o,l]of this.buckets.entries())l.expireAt<=t&&this.buckets.delete(o)}};var at=/^\d{4}-\d{2}-\d{2}$/,ot=/^\d{4}\/\d{2}\/\d{2}$/,Pe=r=>r<10?`0${r}`:`${r}`,Be=r=>{if(Number.isNaN(r.getTime()))return null;let t=r.getFullYear(),o=Pe(r.getMonth()+1),l=Pe(r.getDate());return`${t}-${o}-${l}`},G=r=>{if(r==null)return null;if(r instanceof Date)return Be(r);let t=r.trim();if(t==="")return null;if(at.test(t))return t;if(ot.test(t))return t.replaceAll("/","-");let o=new Date(t);return Be(o)};var te=(r,t,o=console)=>{let l=m=>typeof m=="string"?[`${t} ${m}`]:[t,m];return{debug:(m,...f)=>{r<=0&&o.debug(...l(m),...f)},info:(m,...f)=>{r<=1&&o.info(...l(m),...f)},warn:(m,...f)=>{r<=2&&o.warn(...l(m),...f)},error:(m,...f)=>{r<=3&&o.error(...l(m),...f)}}};var s=require("zod"),it=s.z.object({name:s.z.string(),affiliation:s.z.string().nullable()}),st=s.z.object({name:s.z.string().nullable(),text:s.z.string().nullable(),color:s.z.string().nullable()}),lt=s.z.object({id:s.z.number(),name:s.z.string(),color:s.z.string().nullable()}),Ue=s.z.object({id:s.z.number(),userId:s.z.string(),userName:s.z.string(),content:s.z.string(),createdAt:s.z.string(),isMine:s.z.boolean()}),_e=s.z.object({reportHubId:s.z.number(),date:s.z.string().nullable(),createdAt:s.z.string().nullable(),author:s.z.string(),userId:s.z.string(),sourceType:s.z.string().nullable(),employeeName:s.z.string().nullable(),updatedBy:s.z.string().nullable(),updatedAt:s.z.string().nullable(),category:s.z.string().nullable(),creationCategory:s.z.string().nullable(),visitTimeFrom:s.z.string().nullable(),visitTimeTo:s.z.string().nullable(),customerName:s.z.string().nullable(),interviewers:s.z.array(it),subject:s.z.string().nullable(),content:s.z.string().nullable(),comments:s.z.array(st),isRead:s.z.boolean(),isStarred:s.z.boolean(),labels:s.z.array(lt),commentItems:s.z.array(Ue)}),dt=s.z.object({type:s.z.literal("connected")}),he=s.z.object({type:s.z.literal("status-update"),reportHubId:s.z.number(),statusType:s.z.enum(["star","read"]),value:s.z.boolean(),clientTempId:s.z.string(),recipientRawUserId:s.z.number().optional()}),Ce=s.z.object({type:s.z.literal("comment-add"),reportHubId:s.z.number(),comment:Ue,clientTempId:s.z.string()}),Ae=s.z.object({type:s.z.literal("comment-delete"),reportHubId:s.z.number(),commentId:s.z.number(),clientTempId:s.z.string()}),Te=s.z.object({type:s.z.literal("report-create"),reportHubId:s.z.number(),report:_e,clientTempId:s.z.string(),recipientRawUserId:s.z.number().optional()}),Me=s.z.object({type:s.z.literal("report-update"),reportHubId:s.z.number(),report:_e,clientTempId:s.z.string(),recipientRawUserId:s.z.number().optional()}),ve=s.z.object({type:s.z.literal("report-publish"),reportHubId:s.z.number(),report:_e,clientTempId:s.z.string()}),xe=s.z.object({type:s.z.literal("report-delete"),reportHubId:s.z.number(),clientTempId:s.z.string()}),He=s.z.discriminatedUnion("type",[dt,he,Ce,Ae,Te,Me,ve,xe]);var Ye=require("crypto"),Re=r=>{let t=JSON.stringify(r);return`"${(0,Ye.createHash)("sha256").update(t).digest("hex")}"`};var ut=te(1,"[Response]"),Z=(r,t,o,l=200,m=ut)=>{let f=Re(o),O=r.headers.get("If-None-Match");m.info(`[jsonResponseWithETag] ETag: ${f}, If-None-Match: ${O}`);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:f});return t&&c.append("Set-Cookie",t),r.method==="GET"&&l===200&&O===f?new Response(null,{status:304,headers:c}):new Response(JSON.stringify(o),{status:l,headers:c})};var qe=require("events");var me=(r,t)=>{let[o,l]=r.split("-").map(Number),[m,f]=t.split("-").map(Number);return o!==m?o<m:l<=f},pe=class{constructor(t){this.config=t;this._emitter=new qe.EventEmitter;this._state="idle";this._refCount=0;this._lastId="0-0";this._emitter.setMaxListeners(0),this._logger=t.logger??te(1,"[SSE Reader]")}subscribe(t,o){return this._emitter.on("entry",t),o&&this._emitter.on("error",o),this._refCount++,this._refCount===1&&this._startLoop(),()=>{this._emitter.removeListener("entry",t),o&&this._emitter.removeListener("error",o),this._refCount--,this._refCount<=0&&(this._refCount=0,this._stopLoop())}}async destroy(){this._refCount=0,await this._stopLoop(),this._emitter.removeAllListeners(),this._lastId="0-0"}async _startLoop(){for(;this._state==="stopping";)await new Promise(t=>setTimeout(t,50));if(this._state!=="running"){this._state="running";try{this._client=await this.config.redis?.createClient()}catch(t){this._state="idle",this._emitter.emit("error",t instanceof Error?t:new Error("Failed to create Redis client for SSE reader"));return}if(!this._client){this._state="idle",this._emitter.emit("error",new Error("Failed to create Redis client for SSE reader"));return}this._client.on("error",t=>{this._logger.error("Redis client error:",t)});try{for(;this._state==="running"&&this._client?.isOpen;){let t=await this._client.xRead([{key:this.config.streamKey,id:this._lastId}],{BLOCK:5e3,COUNT:100});if(t)for(let o of t)for(let l of o.messages){this._lastId=l.id;try{let m=l.message?.data?JSON.parse(l.message.data):null,f=m?.type;if((f==="report-create"||f==="report-delete"||f==="report-publish")&&this.config.cache.invalidatePrefix("daily-report:ids"),f==="comment-add"||f==="comment-delete"||f==="status-update"){let O=m?.reportHubId;typeof O=="number"&&(this.config.cache.invalidate(`daily-report:detail:${O}`),this.config.cache.invalidatePrefix(`daily-report:detail:${O}:user:`))}}catch{}this._emitter.emit("entry",{id:l.id,message:l.message})}}}catch(t){!(t?.constructor?.name==="ClientClosedError")&&this._state==="running"&&(this._logger.error("xRead loop error:",t),this._emitter.emit("error",t))}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!=="idle";)await new Promise(t=>setTimeout(t,50))}}};var v=(r,t)=>new Response(JSON.stringify(r),{status:t?.status??200,headers:{"Content-Type":"application/json"}});function Ne(r){let{authenticate:t,service:o,encodeUserId:l,redis:m,sseReader:f,streamKey:O}=r,c=r.loginRedirectPath??"/auth/login",W=r.logger??te(3,"[DailyReportAPI]"),p=r.logger??te(1,"[DailyReportSSE]"),g=async({request:A})=>{let{user:P,cookie:_}=await t(A,{failureRedirect:c}),L=new Headers;_&&L.append("Set-Cookie",_);let C=null;P&&(C=await o.getUserIdByExternalId(P.id));let S=C?l(C):null;return{data:{user:P,userId:S},headers:L}},k={"business-date":async(A,P,_,L)=>{let C=G(A.searchParams.get("businessDate")),S=A.searchParams.get("forceRefresh")==="true";if(!C)return Z(_,P,{error:{message:"Invalid business date"}},400);let B=await o.getDailyReportsByBusinessDateByExternalId(C,L.id,{forceRefresh:S});return Z(_,P,{businessDate:C,reports:B},200)},ids:async(A,P,_,L)=>{let C=A.searchParams.get("forceRefresh")==="true",S=await o.getDailyReportIdsByExternalId(L.id,{forceRefresh:C});return Z(_,P,{ids:S},200)},report:async(A,P,_,L)=>{let C=A.searchParams.get("reportHubId"),S=A.searchParams.get("forceRefresh")==="true",B=C?Number.parseInt(C,10):NaN;if(!Number.isFinite(B)||B<=0)return Z(_,P,{error:{message:"Invalid reportHubId"}},400);let x=await o.getDailyReportDetailByIdByExternalId(B,L.id,{snapshot:!0,forceRefresh:S});return x?Z(_,P,{report:x},200):Z(_,P,{error:{message:"Report not found"}},404)}};return{index:{loader:g},api:{loader:async({request:A,params:P})=>{let{user:_,cookie:L}=await t(A,{failureRedirect:null}),C=L??null;if(!_)return Z(A,C,{error:{message:"Unauthorized"}},401);if(A.method!=="GET")return Z(A,C,{error:{message:"Method not allowed"}},405);let S=P.endpoint??"",B=k[S];if(!B)return Z(A,C,{error:{message:"Unknown endpoint"}},404);let x=Date.now();try{let w=new URL(A.url);return await B(w,C,A,_)}catch(w){let q=Date.now()-x,j=w instanceof Error?w:new Error(String(w));return W.error(`500 endpoint=${S} elapsed=${q}ms name=${j.name} code=${"code"in j?j.code:"N/A"} message=${j.message}`),W.error("Stack:",j.stack),Z(A,C,{error:{message:"Internal Server Error"}},500)}},action:async({request:A,params:P})=>{let{user:_}=await t(A,{failureRedirect:null});if(!_)return v({error:"Unauthorized"},{status:401});if(P.endpoint!=="action")return v({error:"Unknown endpoint"},{status:404});let C=await o.getUserIdByExternalId(_.id);if(!C)return v({error:"User not found"},{status:404});let S=await A.formData(),B=S.get("intent"),x=S.get("reportHubId"),w=x?Number(x):NaN,q=S.get("businessDate"),j=Number(S.get("operationTimestamp")),N=S.get("clientTempId");if(!N)return v({error:"clientTempId required"},{status:400});if(B!=="create"&&(!w||Number.isNaN(w)))return v({error:"Invalid reportHubId"},{status:400});switch(B){case"create":{if(!q)return v({error:"businessDate required"},{status:400});let y=await o.createDailyReport(C,q,N);return v({status:"OK",intent:"create",report:y,reportHubId:String(y.reportHubId),clientTempId:N})}case"update":{let y=S.get("title"),$=S.get("content");try{return await o.updateDailyReport(w,C,{title:y,content:$},N),v({status:"OK",intent:"update",reportHubId:String(w),clientTempId:N})}catch(T){if(T instanceof Error){if(T.message==="Unauthorized")return v({error:"Unauthorized"},{status:403});if(T.message==="Not Found")return v({error:"Report not found"},{status:404})}throw T}}case"publish":try{let y=await o.publishDailyReport(w,C,N);return v({status:"OK",intent:"publish",reportHubId:String(w),clientTempId:N,report:y})}catch(y){if(y instanceof Error){if(y.message==="Unauthorized")return v({error:"Unauthorized"},{status:403});if(y.message==="Not Found")return v({error:"Report not found"},{status:404})}throw y}case"delete":try{return await o.deleteDailyReport(w,C,N),v({status:"OK",intent:"delete",reportHubId:String(w),clientTempId:N})}catch(y){if(y instanceof Error){if(y.message==="Unauthorized")return v({error:"Unauthorized"},{status:403});if(y.message==="Not Found")return v({error:"Report not found"},{status:404})}throw y}case"toggleStar":{let y=S.get("isStarred");if(y===null)return v({error:"isStarred required"},{status:400});let $=y==="true",T=await o.setStarStatus(C,w,q,$,N);return v({status:"OK",intent:"toggleStar",updatedStatus:{isStarred:T.isStarred,isRead:T.isRead},operationTimestamp:j,reportHubId:String(w),clientTempId:N})}case"toggleRead":{let y=S.get("isRead");if(y===null)return v({error:"isRead required"},{status:400});let $=y==="true",T=await o.setReadStatus(C,w,q,$,N);return v({status:"OK",intent:"toggleRead",updatedStatus:{isStarred:T.isStarred,isRead:T.isRead},operationTimestamp:j,reportHubId:String(w),clientTempId:N})}case"addComment":{let y=S.get("content");if(!y)return v({error:"Content required"},{status:400});let $=await o.addComment(C,w,y,q,N),T={...$,userId:$.userId};return v({status:"OK",intent:"addComment",newComment:T,reportHubId:String(w),clientTempId:N})}case"deleteComment":{let y=Number(S.get("commentId"));if(!y||Number.isNaN(y))return v({error:"Invalid commentId"},{status:400});try{return await o.deleteComment(C,w,y,q,N),v({status:"OK",reportHubId:String(w),deletedCommentId:String(y),clientTempId:N})}catch($){if($ instanceof Error){if($.message==="Unauthorized")return v({error:"Unauthorized"},{status:403});if($.message==="Not Found")return v({error:"Comment not found"},{status:404})}throw $}}default:return v({error:"Invalid intent"},{status:400})}}},sse:{loader:async({request:A,params:P})=>{let{user:_}=await t(A,{failureRedirect:null});if(!_)return new Response("Unauthorized",{status:401});let L=await o.getUserIdByExternalId(_.id);if(!L)return new Response("Forbidden",{status:403});if(P.endpoint!=="updates")return new Response("Not Found",{status:404});let S=new URL(A.url).searchParams.get("lastEventId")||A.headers.get("Last-Event-ID"),B=new TextEncoder,x=null,w=null,q=null,j=!1,N=()=>{if(!j){if(j=!0,w&&(clearInterval(w),w=null),q&&(q(),q=null),x)try{x.desiredSize!==null&&x.close()}catch{}finally{x=null}j=!1}},y=(T,K)=>{if(K.data)try{let M=JSON.parse(K.data),Q=He.safeParse(M);if(!Q.success){p.error("SSE message validation failed:",Q.error.format());return}let ee=Q.data,ae=typeof M.recipientRawUserId=="number"?M.recipientRawUserId:void 0;if(ee.type==="status-update"){if(ae===void 0||ae!==L)return}else if(ae!==void 0&&ae!==L)return;let se;if("recipientRawUserId"in M){let{recipientRawUserId:ke,...le}=M;se=JSON.stringify(le)}else se=K.data;x&&x.desiredSize!==null&&x.enqueue(B.encode(`id: ${T}
|
|
2
2
|
data: ${se}
|
|
3
3
|
|
|
4
|
-
`))}catch(M){p.error(`[SSE:${
|
|
4
|
+
`))}catch(M){p.error(`[SSE:${L}] processEntry error:`,M)}},$=new ReadableStream({async start(T){x=T,w=setInterval(()=>{try{x&&x.desiredSize!==null?x.enqueue(B.encode(`: keep-alive
|
|
5
5
|
|
|
6
|
-
`)):N()}catch{N()}},5e3),A.signal.addEventListener("abort",()=>{N()});let K=S||"0-0";if(q=f.subscribe(M=>{me(M.id,K)||(K=M.id,y(M.id,M.message))},M=>{p.error(`[SSE:${
|
|
6
|
+
`)):N()}catch{N()}},5e3),A.signal.addEventListener("abort",()=>{N()});let K=S||"0-0";if(q=f.subscribe(M=>{me(M.id,K)||(K=M.id,y(M.id,M.message))},M=>{p.error(`[SSE:${L}] Fan-Out reader error:`,M),N()}),!S)try{let M=await m?.getClient();if(M){let Q=await M.xRevRange(O,"+","-",{COUNT:1});Q.length>0&&!me(Q[0].id,K)&&(K=Q[0].id)}}catch{}if(x&&x.desiredSize!==null){let M=`data: ${JSON.stringify({type:"connected"})}
|
|
7
7
|
|
|
8
8
|
`,Q=K!=="0-0"?`id: ${K}
|
|
9
|
-
${M}`:M;x.enqueue(B.encode(Q))}if(S)try{let M=await m?.getClient();if(M){let Q=await M.xRange(O,S,"+",{COUNT:1e3});for(let ee of Q)ee.id!==S&&(me(ee.id,K)||(K=ee.id,y(ee.id,ee.message)))}}catch(M){p.error(`[SSE:${P}] catch-up xRange error:`,M)}},cancel(){N()}});return new Response(L,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive"}})}}}}var a=require("drizzle-orm");var ne=r=>(0,a.getColumns)(r);function Ee(r){let{db:t,tables:i,userTable:l,resolveUserId:m,encodeUserId:f,redis:O,cache:c,epochs:W}=r,{hub:p,internal:g,comment:$,label:F,hubLabel:X,userStatus:E}=i,A=r.externalSources??[],k=r.draftLabelName,_=r.logger??te(1,"[DailyReportService]"),P="daily-report:ids",C=r.idsTtlMs??18e4,S="daily-report:ids:epoch",B="daily-report:business-date:",x=r.businessDateTtlMs??3e5,w="daily-report:date-epoch:",q="daily-report:detail-epoch:",j=r.streamKey??"daily-report:sse-stream",N=r.streamMaxLen??1e4,y=e=>W.incrementEpoch(e),L=async(e,n)=>{let d=await O?.getClient();if(!d){_.warn(`[SSE] Redis client unavailable (${n})`);return}let u=Date.now();try{await d.xAdd(j,"*",{data:JSON.stringify(e)},{TRIM:{strategy:"MAXLEN",strategyModifier:"~",threshold:N}});let b=Date.now()-u;b>1e3&&_.warn(`[SSE] Slow publish (${n}): ${b}ms`)}catch(b){_.error(`[SSE] Redis publish failed (${n}):`,b)}},T=(e,n)=>{if(!e)return null;let d=e instanceof Date?e:new Date(e);if(Number.isNaN(d.getTime()))return typeof e=="string"?e:null;let u=n==="YYYY-MM-DD HH:mm:ss"?{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}:{year:"numeric",month:"2-digit",day:"2-digit"};return(n==="YYYY-MM-DD HH:mm:ss"?d.toLocaleString("ja-JP",u):d.toLocaleDateString("ja-JP",u)).replace(/\//g,"-")},K=e=>e==null||e===""?null:/^\d+$/.test(e)?f(Number(e)):e,M=()=>{let e={};for(let n of A)e[`ext_${n.sourceType}`]=ne(n.table);return e},Q=e=>{let n=e;for(let d of A)n=n.leftJoin(d.table,(0,a.and)((0,a.eq)(p.sourceType,d.sourceType),(0,a.eq)(p.sourceIdNum,d.idColumn)));return n},ee=(e,n)=>{let{hub:d,internal:u}=e,b=d.summary,h=[],R=null,I=null,U=null,z=null,H=null,V=null,re=[],J=A.find(D=>D.sourceType===d.sourceType),ie=J?e[`ext_${J.sourceType}`]:void 0;if(J&&ie){let D=J.mapRow(ie);D.content!==void 0&&(b=D.content),D.employeeName!==void 0&&(V=D.employeeName),D.category!==void 0&&(R=D.category),D.creationCategory!==void 0&&(I=D.creationCategory),D.visitTimeFrom!==void 0&&(U=D.visitTimeFrom),D.visitTimeTo!==void 0&&(z=D.visitTimeTo),D.customerName!==void 0&&(H=D.customerName),D.interviewers!==void 0&&(h=D.interviewers),D.comments!==void 0&&(re=D.comments)}else d.sourceType==="Internal"&&u&&(b=u.body);let ue=e.labels??[],Y=e.comments??[];return{reportHubId:d.id,date:T(d.businessDate,"YYYY-MM-DD"),author:e.creatorName??K(d.createdBy)??"",userId:d.userId?f(d.userId):"",sourceType:d.sourceType??"Internal",createdAt:T(d.createdAt,"YYYY-MM-DD HH:mm:ss"),updatedAt:T(d.updatedAt,"YYYY-MM-DD HH:mm:ss"),updatedBy:K(d.updatedBy),employeeName:V??e.creatorName??K(d.createdBy),category:R,creationCategory:I,visitTimeFrom:U,visitTimeTo:z,customerName:H,interviewers:h,subject:d.title,content:b,comments:re,isRead:e.isRead??!1,isStarred:e.isStarred??!1,labels:ue.map(D=>({id:D.id,name:D.name,color:D.color})),commentItems:Y.map(D=>({...D,userId:f(D.userId),isMine:n?D.userId===n:!1}))}},ae=async e=>{let n=(0,a.aliasedTable)(X,"draft_label");return(await t.select({reportHubId:p.id,businessDate:p.businessDate}).from(p).leftJoin(n,(0,a.and)((0,a.eq)(n.hubId,p.id),(0,a.eq)(n.labelId,t.select({id:F.id}).top(1).from(F).where((0,a.eq)(F.name,k))))).where((0,a.and)((0,a.isNull)(p.deletedAt),(0,a.or)((0,a.eq)(p.userId,e),(0,a.isNull)(n.hubId)))).orderBy((0,a.desc)(p.businessDate),(0,a.desc)(p.id))).map(u=>({...u,businessDate:T(u.businessDate,"YYYY-MM-DD")}))},se=async e=>(await Q(t.select({hub:ne(p),internal:ne(g),creatorName:l.displayName,...M()}).from(p)).leftJoin(g,(0,a.eq)(p.id,g.hubId)).leftJoin(l,(0,a.eq)(p.userId,l.id)).where((0,a.and)((0,a.eq)(p.businessDate,a.sql`${e}`),(0,a.isNull)(p.deletedAt))).orderBy((0,a.desc)(p.id))).map(d=>ee(d)),$e=e=>`${B}${e}`,le=new Map,ge=async e=>{if(!r.disableUserIdCache&&le.has(e))return le.get(e)??null;let n=await m(e);return n!==null&&!r.disableUserIdCache&&le.set(e,n),n},Oe=async(e,{forceRefresh:n=!1,snapshot:d=!1,ttlMsOverride:u}={})=>{let b=await ge(e);if(!b)return[];let h=`${P}:user:${b}`;return c.getOrFetch({cacheKey:h,fetcher:async()=>await ae(b),forceRefresh:n,snapshot:d,ttlMsOverride:u??C,epochKey:S})},Fe=(e,{forceRefresh:n=!1,snapshot:d=!1,ttlMsOverride:u}={})=>{let b=G(e);return b?c.getOrFetch({cacheKey:$e(b),fetcher:()=>se(b),forceRefresh:n,snapshot:d,ttlMsOverride:u??x}):Promise.resolve([])},fe=null,oe=async()=>{if(fe!==null)return fe;let[e]=await t.select({id:F.id}).top(1).from(F).where((0,a.eq)(F.name,k));return e?(fe=e.id,fe):null},ze=async(e,n,{forceRefresh:d=!1,snapshot:u=!1,ttlMsOverride:b}={})=>{let h=await ge(n);if(!h)return[];let R=G(e);if(!R)return[];let I=`daily-report:date:${R}:user:${h}`;return c.getOrFetch({cacheKey:I,fetcher:async()=>{let U=await oe(),z=(0,a.aliasedTable)(X,"draft_label"),H=await Q(t.select({hub:ne(p),internal:ne(g),isRead:E.isRead,isStarred:E.isStarred,creatorName:l.displayName,...M()}).from(p)).leftJoin(g,(0,a.eq)(p.id,g.hubId)).leftJoin(E,(0,a.and)((0,a.eq)(p.id,E.hubId),(0,a.eq)(E.userId,h))).leftJoin(z,(0,a.and)((0,a.eq)(z.hubId,p.id),(0,a.eq)(z.labelId,U??-1))).leftJoin(l,(0,a.eq)(p.userId,l.id)).where((0,a.and)((0,a.eq)(p.businessDate,a.sql`${R}`),(0,a.isNull)(p.deletedAt),(0,a.or)((0,a.eq)(p.userId,h),(0,a.isNull)(z.hubId)))).orderBy((0,a.desc)(p.id));if(H.length===0)return[];let V=H.map(Y=>Y.hub.id),re=await t.select({hubId:X.hubId,id:F.id,name:F.name,color:F.color}).from(X).innerJoin(F,(0,a.eq)(X.labelId,F.id)).where((0,a.inArray)(X.hubId,V)),J=await t.select({hubId:$.hubId,id:$.id,body:$.body,createdAt:$.createdAt,userId:$.userId,userName:l.displayName}).from($).leftJoin(l,(0,a.eq)($.userId,l.id)).where((0,a.inArray)($.hubId,V)).orderBy((0,a.asc)($.createdAt)),ie=new Map,ue=new Map;for(let Y of re){let D=ie.get(Y.hubId);D||(D=[],ie.set(Y.hubId,D)),D.push({id:Y.id,name:Y.name,color:Y.color})}for(let Y of J){let D=ue.get(Y.hubId);D||(D=[],ue.set(Y.hubId,D)),D.push({id:Y.id,content:Y.body,createdAt:T(Y.createdAt,"YYYY-MM-DD HH:mm:ss")||"",userId:Y.userId,userName:Y.userName||""})}return H.map(Y=>{let D=Y.hub.id;return ee({...Y,labels:ie.get(D)||[],comments:ue.get(D)||[]},h)})},forceRefresh:d,snapshot:u,ttlMsOverride:b??x,epochKey:`${w}${R}`})},de=async(e,n,{forceRefresh:d=!1,snapshot:u=!1,ttlMsOverride:b}={})=>{let h=`daily-report:detail:${e}:user:${n}`;return(await c.getOrFetch({cacheKey:h,fetcher:async()=>{let I=await Q(t.select({hub:ne(p),internal:ne(g),isRead:E.isRead,isStarred:E.isStarred,creatorName:l.displayName,...M()}).from(p)).leftJoin(g,(0,a.eq)(p.id,g.hubId)).leftJoin(E,(0,a.and)((0,a.eq)(p.id,E.hubId),(0,a.eq)(E.userId,n))).leftJoin(l,(0,a.eq)(p.userId,l.id)).where((0,a.and)((0,a.eq)(p.id,e),(0,a.isNull)(p.deletedAt)));if(I.length===0)return[];let U=I[0].hub.id,z=await t.select({id:F.id,name:F.name,color:F.color}).from(X).innerJoin(F,(0,a.eq)(X.labelId,F.id)).where((0,a.eq)(X.hubId,U)),H=await t.select({id:$.id,body:$.body,createdAt:$.createdAt,userId:$.userId,userName:l.displayName}).from($).leftJoin(l,(0,a.eq)($.userId,l.id)).where((0,a.eq)($.hubId,U)).orderBy((0,a.asc)($.createdAt)),V=z.map(J=>({id:J.id,name:J.name,color:J.color})),re=H.map(J=>({id:J.id,content:J.body,createdAt:T(J.createdAt,"YYYY-MM-DD HH:mm:ss")||"",userId:J.userId,userName:J.userName||""}));return[ee({...I[0],labels:V,comments:re},n)]},forceRefresh:d,snapshot:u,ttlMsOverride:b??x,epochKey:`${q}${e}`}))[0]??null},Ke=async(e,n,d={})=>{let u=await ge(n);return u?de(e,u,d):null},Je=async(e,n,d,u,b)=>{let h=await t.select().top(1).from(E).where((0,a.and)((0,a.eq)(E.hubId,n),(0,a.eq)(E.userId,e))),R;if(h.length>0?h[0].isStarred!==u?R=(await t.update(E).set({isStarred:u,updatedAt:new Date,updatedBy:String(e)}).output().where((0,a.and)((0,a.eq)(E.hubId,n),(0,a.eq)(E.userId,e))))[0]:R=h[0]:R=(await t.insert(E).output().values({hubId:n,userId:e,isStarred:u,isRead:!1,createdAt:new Date,createdBy:String(e),updatedAt:new Date,updatedBy:String(e)}))[0],d){let I=G(d);I&&(c.invalidate(`daily-report:date:${I}:user:${e}`),await y(`${w}${I}`))}return c.invalidate(`daily-report:detail:${n}`),c.invalidate(`daily-report:detail:${n}:user:${e}`),await y(`${q}${n}`),await L(he.parse({type:"status-update",reportHubId:n,recipientRawUserId:e,statusType:"star",value:u,clientTempId:b}),"setStarStatus"),R},je=async(e,n,d,u,b)=>{let h=await t.select().top(1).from(E).where((0,a.and)((0,a.eq)(E.hubId,n),(0,a.eq)(E.userId,e))),R;if(h.length>0?h[0].isRead!==u?R=(await t.update(E).set({isRead:u,updatedAt:new Date,updatedBy:String(e)}).output().where((0,a.and)((0,a.eq)(E.hubId,n),(0,a.eq)(E.userId,e))))[0]:R=h[0]:R=(await t.insert(E).output().values({hubId:n,userId:e,isRead:u,isStarred:!1,createdAt:new Date,createdBy:String(e),updatedAt:new Date,updatedBy:String(e)}))[0],d){let I=G(d);I&&(c.invalidate(`daily-report:date:${I}:user:${e}`),await y(`${w}${I}`))}return c.invalidate(`daily-report:detail:${n}`),c.invalidate(`daily-report:detail:${n}:user:${e}`),await y(`${q}${n}`),await L(he.parse({type:"status-update",reportHubId:n,recipientRawUserId:e,statusType:"read",value:u,clientTempId:b}),"setReadStatus"),R},Qe=async(e,n,d,u,b)=>{let[h]=await t.insert($).output().values({hubId:n,userId:e,body:d,createdAt:new Date,createdBy:String(e),updatedAt:new Date,updatedBy:String(e)}),[R]=await t.select({displayName:l.displayName}).top(1).from(l).where((0,a.eq)(l.id,e)),I=R?.displayName??"Unknown";if(u){let z=G(u);z&&(c.invalidatePrefix(`daily-report:date:${z}:user:`),await y(`${w}${z}`))}c.invalidate(`daily-report:detail:${n}`),c.invalidatePrefix(`daily-report:detail:${n}:user:`),await y(`${q}${n}`);let U={id:h.id,userId:f(h.userId),userName:I,content:h.body,createdAt:T(h.createdAt,"YYYY-MM-DD HH:mm:ss")??"",isMine:!0};return await L(Ce.parse({type:"comment-add",reportHubId:n,comment:U,clientTempId:b}),"addComment"),U},We=async(e,n)=>await e.select().top(1).from($).where((0,a.eq)($.id,n)),Xe=async(e,n,d,u,b)=>{let h=await We(t,d);if(h.length===0)throw new Error("Not Found");if(h[0].userId!==e)throw new Error("Unauthorized");if(await t.delete($).where((0,a.eq)($.id,d)),u){let R=G(u);R&&(c.invalidatePrefix(`daily-report:date:${R}:user:`),await y(`${w}${R}`))}c.invalidate(`daily-report:detail:${n}`),c.invalidatePrefix(`daily-report:detail:${n}:user:`),await y(`${q}${n}`),await L(Ae.parse({type:"comment-delete",reportHubId:n,commentId:d,clientTempId:b}),"deleteComment")},Ge=async(e,n,d)=>{_.info("createDailyReport called",{userId:e,businessDate:n});let[u]=await t.select({displayName:l.displayName}).from(l).where((0,a.eq)(l.id,e)),b=u?.displayName??f(e);try{let h=await t.transaction(async U=>{_.info("Starting transaction");let z=`internal-temp-${Date.now()}-${Math.random()}`,[H]=await U.insert(p).output().values({sourceType:"Internal",sourceId:z,businessDate:new Date(n),userId:e,title:"(\u7121\u984C)",createdAt:new Date,createdBy:String(e),updatedAt:new Date,updatedBy:String(e)});await U.update(p).set({sourceId:String(H.id)}).where((0,a.eq)(p.id,H.id)),_.info("Hub created",H),await U.insert(g).values({hubId:H.id,body:"",createdAt:new Date,createdBy:String(e),updatedAt:new Date,updatedBy:String(e)}),_.info("Internal created"),_.info("Calling getDraftLabelId");let V=await oe();_.info("draftLabelId",V);let re=[];return V&&(await U.insert(X).values({hubId:H.id,labelId:V,createdAt:new Date,createdBy:String(e)}),re.push({id:V,name:k,color:null})),_.info("Label assigned"),{reportHubId:H.id,date:n,createdAt:T(H.createdAt,"YYYY-MM-DD HH:mm:ss"),author:b,userId:f(e),sourceType:"Internal",employeeName:b,updatedBy:f(e),updatedAt:T(H.updatedAt,"YYYY-MM-DD HH:mm:ss"),category:null,creationCategory:null,visitTimeFrom:null,visitTimeTo:null,customerName:null,interviewers:[],subject:H.title,content:"",comments:[],isRead:!0,isStarred:!1,labels:re,commentItems:[]}}),R=G(n);R&&c.invalidate(`daily-report:date:${R}:user:${e}`),c.invalidatePrefix(B),c.invalidate(`${P}:user:${e}`),await y(S),R&&await y(`${w}${R}`);let I=await de(h.reportHubId,e,{forceRefresh:!0});if(I){let U=await oe(),z=U?I.labels.some(H=>H.id===U):!1;await L(Te.parse({type:"report-create",reportHubId:I.reportHubId,report:I,clientTempId:d,recipientRawUserId:z?e:void 0}),"createDailyReport")}return I??h}catch(h){throw _.error("Error in createDailyReport",h),h}},be=async(e,n)=>await e.select().top(1).from(p).where((0,a.eq)(p.id,n)),we=async(e,n,d)=>{await e.update(p).set(d).where((0,a.eq)(p.id,n))},Le=async(e,n,d)=>{await e.update(g).set(d).where((0,a.eq)(g.hubId,n))},Pe=async(e,n,d)=>{await e.delete(X).where((0,a.and)((0,a.eq)(X.hubId,n),(0,a.eq)(X.labelId,d)))};return{streamKey:j,streamMaxLen:N,getUserIdByExternalId:ge,getDailyReportIdsByExternalId:Oe,getDailyReportsByBusinessDate:Fe,getDailyReportsByBusinessDateByExternalId:ze,getDailyReportDetailById:de,getDailyReportDetailByIdByExternalId:Ke,getDraftLabelId:oe,setStarStatus:Je,setReadStatus:je,addComment:Qe,deleteComment:Xe,createDailyReport:Ge,updateDailyReport:async(e,n,d,u)=>{let b=await be(t,e);if(!b.length||b[0].deletedAt)throw new Error("Not Found");if(b[0].userId!==n)throw new Error("Unauthorized");await t.transaction(async R=>{d.title!==void 0&&await we(R,e,{title:d.title,updatedAt:new Date,updatedBy:String(n)}),d.content!==void 0&&await Le(R,e,{body:d.content,updatedAt:new Date,updatedBy:String(n)})}),c.invalidatePrefix(`daily-report:detail:${e}:user:`),c.invalidatePrefix(B);let h=await de(e,n,{forceRefresh:!0});if(h){let R=await oe(),I=R?h.labels.some(U=>U.id===R):!1;await L(Me.parse({type:"report-update",reportHubId:h.reportHubId,report:h,clientTempId:u,recipientRawUserId:I?n:void 0}),"updateDailyReport")}},publishDailyReport:async(e,n,d)=>{let u=await be(t,e);if(!u.length)throw new Error("Not Found");if(u[0].userId!==n)throw new Error("Unauthorized");let b=await oe();if(!b)return null;if(await Pe(t,e,b),c.invalidatePrefix(`daily-report:detail:${e}:user:`),c.invalidatePrefix(B),c.invalidatePrefix(P),await y(S),u[0].businessDate){let I=G(T(u[0].businessDate,"YYYY-MM-DD"));I&&await y(`${w}${I}`)}let h=G(T(u[0].businessDate,"YYYY-MM-DD"));h&&c.invalidate(`daily-report:date:${h}:user:${n}`);let R=await de(e,n,{forceRefresh:!0});return R&&await L(ve.parse({type:"report-publish",reportHubId:R.reportHubId,report:R,clientTempId:d}),"publishDailyReport"),R??null},deleteDailyReport:async(e,n,d)=>{let u=await be(t,e);if(!u.length||u[0].deletedAt)throw new Error("Not Found");if(u[0].userId!==n)throw new Error("Unauthorized");if(await we(t,e,{deletedAt:new Date,deletedBy:String(n),updatedAt:new Date,updatedBy:String(n)}),c.invalidatePrefix(`daily-report:detail:${e}:user:`),c.invalidatePrefix(B),c.invalidatePrefix(P),await y(S),u[0].businessDate){let b=G(T(u[0].businessDate,"YYYY-MM-DD"));b&&await y(`${w}${b}`)}await L(xe.parse({type:"report-delete",reportHubId:e,clientTempId:d}),"deleteDailyReport")},findDailyReportHubById:be,updateDailyReportHub:we,updateDailyReportInternal:Le,deleteDailyReportLabel:Pe}}var ct=te(1,"[DailyReportExternalSource]"),pt=(r,t,i,l=ct)=>{if(!r)return[];try{let m=JSON.parse(r);return Array.isArray(m)?m.map(i).filter(f=>f!==null):(l.warn(`Unexpected ${t} format: not an array`),[])}catch(m){return l.warn(`Failed to parse ${t}:`,m),[]}};var ye=require("drizzle-orm"),o=require("drizzle-orm/mssql-core");function mt(r,t){let i=(0,o.mssqlSchema)(r),l=t.userTable,m=i.table("DailyReportHub",{id:(0,o.bigint)("id",{mode:"number"}).identity().notNull(),sourceType:(0,o.nvarchar)("source_type",{length:20}).notNull(),sourceId:(0,o.nvarchar)("source_id",{length:100}).notNull(),sourceIdNum:(0,o.bigint)("source_id_num",{mode:"number"}).generatedAlwaysAs(ye.sql`TRY_CAST(source_id AS BIGINT)`),businessDate:(0,o.date)("business_date"),userId:(0,o.bigint)("user_id",{mode:"number"}),title:(0,o.nvarchar)("title",{length:200}),summary:(0,o.nvarchar)("summary",{length:"max"}),createdAt:(0,o.datetime2)("created_at").notNull(),createdBy:(0,o.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,o.datetime2)("updated_at").notNull(),updatedBy:(0,o.nvarchar)("updated_by",{length:50}).notNull(),deletedAt:(0,o.datetime2)("deleted_at"),deletedBy:(0,o.nvarchar)("deleted_by",{length:50})},g=>[(0,o.primaryKey)({name:`${r}_DailyReportHub_pk`,columns:[g.id]}),(0,o.foreignKey)({name:`${r}_DailyReportHub_user_id_fk`,columns:[g.userId],foreignColumns:[l.id]}),(0,o.index)(`${r}_DailyReportHub_business_date_index`).on(g.businessDate),(0,o.index)(`${r}_DailyReportHub_updated_at_index`).on(g.updatedAt),(0,o.index)(`${r}_DailyReportHub_source_index`).on(g.sourceType,g.sourceId),(0,o.index)(`${r}_DailyReportHub_user_id_index`).on(g.userId),(0,o.index)(`${r}_DailyReportHub_business_date_id_index`).on((0,ye.desc)(g.businessDate),(0,ye.desc)(g.id)),(0,o.index)(`${r}_DailyReportHub_deleted_at_index`).on(g.deletedAt)]),f=i.table("DailyReportInternal",{hubId:(0,o.bigint)("hub_id",{mode:"number"}).notNull(),body:(0,o.nvarchar)("body",{length:"max"}),metadata:(0,o.nvarchar)("metadata",{length:"max"}),createdAt:(0,o.datetime2)("created_at").notNull(),createdBy:(0,o.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,o.datetime2)("updated_at").notNull(),updatedBy:(0,o.nvarchar)("updated_by",{length:50}).notNull()},g=>[(0,o.primaryKey)({name:`${r}_DailyReportInternal_pk`,columns:[g.hubId]}),(0,o.foreignKey)({name:`${r}_DailyReportInternal_hub_id_fk`,columns:[g.hubId],foreignColumns:[m.id]})]),O=i.table("DailyReportComment",{id:(0,o.bigint)("id",{mode:"number"}).identity().notNull(),hubId:(0,o.bigint)("hub_id",{mode:"number"}).notNull(),userId:(0,o.bigint)("user_id",{mode:"number"}).notNull(),body:(0,o.nvarchar)("body",{length:"max"}).notNull(),createdAt:(0,o.datetime2)("created_at").notNull(),createdBy:(0,o.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,o.datetime2)("updated_at").notNull(),updatedBy:(0,o.nvarchar)("updated_by",{length:50}).notNull()},g=>[(0,o.primaryKey)({name:`${r}_DailyReportComment_pk`,columns:[g.id]}),(0,o.foreignKey)({name:`${r}_DailyReportComment_hub_id_fk`,columns:[g.hubId],foreignColumns:[m.id]}),(0,o.foreignKey)({name:`${r}_DailyReportComment_user_id_fk`,columns:[g.userId],foreignColumns:[l.id]}),(0,o.index)(`${r}_DailyReportComment_hub_id_index`).on(g.hubId)]),c=i.table("DailyReportLabel",{id:(0,o.bigint)("id",{mode:"number"}).identity().notNull(),userId:(0,o.bigint)("user_id",{mode:"number"}),name:(0,o.nvarchar)("name",{length:50}).notNull(),color:(0,o.nvarchar)("color",{length:20}),sortOrder:(0,o.int)("sort_order"),createdAt:(0,o.datetime2)("created_at").notNull(),createdBy:(0,o.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,o.datetime2)("updated_at").notNull(),updatedBy:(0,o.nvarchar)("updated_by",{length:50}).notNull()},g=>[(0,o.primaryKey)({name:`${r}_DailyReportLabel_pk`,columns:[g.id]}),(0,o.foreignKey)({name:`${r}_DailyReportLabel_user_id_fk`,columns:[g.userId],foreignColumns:[l.id]})]),W=i.table("DailyReportHub_Label",{hubId:(0,o.bigint)("hub_id",{mode:"number"}).notNull(),labelId:(0,o.bigint)("label_id",{mode:"number"}).notNull(),createdAt:(0,o.datetime2)("created_at").notNull(),createdBy:(0,o.nvarchar)("created_by",{length:50}).notNull()},g=>[(0,o.primaryKey)({name:`${r}_DailyReportHub_Label_pk`,columns:[g.hubId,g.labelId]}),(0,o.foreignKey)({name:`${r}_DailyReportHub_Label_hub_id_fk`,columns:[g.hubId],foreignColumns:[m.id]}),(0,o.foreignKey)({name:`${r}_DailyReportHub_Label_label_id_fk`,columns:[g.labelId],foreignColumns:[c.id]})]),p=i.table("DailyReportUserStatus",{hubId:(0,o.bigint)("hub_id",{mode:"number"}).notNull(),userId:(0,o.bigint)("user_id",{mode:"number"}).notNull(),isRead:(0,o.bit)("is_read").default(!1).notNull(),isStarred:(0,o.bit)("is_starred").default(!1).notNull(),createdAt:(0,o.datetime2)("created_at").notNull(),createdBy:(0,o.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,o.datetime2)("updated_at").notNull(),updatedBy:(0,o.nvarchar)("updated_by",{length:50}).notNull()},g=>[(0,o.primaryKey)({name:`${r}_DailyReportUserStatus_pk`,columns:[g.hubId,g.userId]}),(0,o.foreignKey)({name:`${r}_DailyReportUserStatus_hub_id_fk`,columns:[g.hubId],foreignColumns:[m.id]}),(0,o.foreignKey)({name:`${r}_DailyReportUserStatus_user_id_fk`,columns:[g.userId],foreignColumns:[l.id]})]);return{hub:m,internal:f,comment:O,label:c,hubLabel:W,userStatus:p}}function yt(r){let t=Ie(r.redis),i=new ce({defaultTtlMs:r.cacheDefaultTtlMs??6e4},t),l=Ee({...r,cache:i,epochs:t}),m=new pe({redis:r.redis,streamKey:l.streamKey,cache:i,logger:r.logger}),f=Ne({authenticate:r.authenticate,service:l,encodeUserId:r.encodeUserId,redis:r.redis,sseReader:m,streamKey:l.streamKey,loginRedirectPath:r.loginRedirectPath,logger:r.logger});return{service:l,cache:i,epochs:t,sseReader:m,streamKey:l.streamKey,...f}}0&&(module.exports={DailyReportSseReader,SqlResultCache,createDailyReportHandlers,createDailyReportServer,createDailyReportService,createEpochStore,defineDailyReportSchema,generateETag,isStreamIdLte,jsonResponseWithETag,transformJsonArray});
|
|
9
|
+
${M}`:M;x.enqueue(B.encode(Q))}if(S)try{let M=await m?.getClient();if(M){let Q=await M.xRange(O,S,"+",{COUNT:1e3});for(let ee of Q)ee.id!==S&&(me(ee.id,K)||(K=ee.id,y(ee.id,ee.message)))}}catch(M){p.error(`[SSE:${L}] catch-up xRange error:`,M)}},cancel(){N()}});return new Response($,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive"}})}}}}var a=require("drizzle-orm");var ne=r=>(0,a.getColumns)(r);function Ee(r){let{db:t,tables:o,userTable:l,resolveUserId:m,encodeUserId:f,redis:O,cache:c,epochs:W}=r,{hub:p,internal:g,comment:k,label:F,hubLabel:X,userStatus:E}=o,A=r.externalSources??[],P=r.draftLabelName,_=r.logger??te(1,"[DailyReportService]"),L="daily-report:ids",C=r.idsTtlMs??18e4,S="daily-report:ids:epoch",B="daily-report:business-date:",x=r.businessDateTtlMs??3e5,w="daily-report:date-epoch:",q="daily-report:detail-epoch:",j=r.streamKey??"daily-report:sse-stream",N=r.streamMaxLen??1e4,y=e=>W.incrementEpoch(e),$=async(e,n)=>{let d=await O?.getClient();if(!d){_.warn(`[SSE] Redis client unavailable (${n})`);return}let u=Date.now();try{await d.xAdd(j,"*",{data:JSON.stringify(e)},{TRIM:{strategy:"MAXLEN",strategyModifier:"~",threshold:N}});let b=Date.now()-u;b>1e3&&_.warn(`[SSE] Slow publish (${n}): ${b}ms`)}catch(b){_.error(`[SSE] Redis publish failed (${n}):`,b)}},T=(e,n)=>{if(!e)return null;let d=e instanceof Date?e:new Date(e);if(Number.isNaN(d.getTime()))return typeof e=="string"?e:null;let u=n==="YYYY-MM-DD HH:mm:ss"?{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}:{year:"numeric",month:"2-digit",day:"2-digit"};return(n==="YYYY-MM-DD HH:mm:ss"?d.toLocaleString("ja-JP",u):d.toLocaleDateString("ja-JP",u)).replace(/\//g,"-")},K=e=>e==null||e===""?null:/^\d+$/.test(e)?f(Number(e)):e,M=()=>{let e={};for(let n of A)e[`ext_${n.sourceType}`]=ne(n.table);return e},Q=e=>{let n=e;for(let d of A)n=n.leftJoin(d.table,(0,a.and)((0,a.eq)(p.sourceType,d.sourceType),(0,a.eq)(p.sourceIdNum,d.idColumn)));return n},ee=(e,n)=>{let{hub:d,internal:u}=e,b=d.summary,h=[],R=null,I=null,U=null,z=null,H=null,V=null,re=[],J=A.find(D=>D.sourceType===d.sourceType),ie=J?e[`ext_${J.sourceType}`]:void 0;if(J&&ie){let D=J.mapRow(ie);D.content!==void 0&&(b=D.content),D.employeeName!==void 0&&(V=D.employeeName),D.category!==void 0&&(R=D.category),D.creationCategory!==void 0&&(I=D.creationCategory),D.visitTimeFrom!==void 0&&(U=D.visitTimeFrom),D.visitTimeTo!==void 0&&(z=D.visitTimeTo),D.customerName!==void 0&&(H=D.customerName),D.interviewers!==void 0&&(h=D.interviewers),D.comments!==void 0&&(re=D.comments)}else d.sourceType==="Internal"&&u&&(b=u.body);let ue=e.labels??[],Y=e.comments??[];return{reportHubId:d.id,date:T(d.businessDate,"YYYY-MM-DD"),author:e.creatorName??K(d.createdBy)??"",userId:d.userId?f(d.userId):"",sourceType:d.sourceType??"Internal",createdAt:T(d.createdAt,"YYYY-MM-DD HH:mm:ss"),updatedAt:T(d.updatedAt,"YYYY-MM-DD HH:mm:ss"),updatedBy:K(d.updatedBy),employeeName:V??e.creatorName??K(d.createdBy),category:R,creationCategory:I,visitTimeFrom:U,visitTimeTo:z,customerName:H,interviewers:h,subject:d.title,content:b,comments:re,isRead:e.isRead??!1,isStarred:e.isStarred??!1,labels:ue.map(D=>({id:D.id,name:D.name,color:D.color})),commentItems:Y.map(D=>({...D,userId:f(D.userId),isMine:n?D.userId===n:!1}))}},ae=async e=>{let n=(0,a.aliasedTable)(X,"draft_label");return(await t.select({reportHubId:p.id,businessDate:p.businessDate}).from(p).leftJoin(n,(0,a.and)((0,a.eq)(n.hubId,p.id),(0,a.eq)(n.labelId,t.select({id:F.id}).top(1).from(F).where((0,a.eq)(F.name,P))))).where((0,a.and)((0,a.isNull)(p.deletedAt),(0,a.or)((0,a.eq)(p.userId,e),(0,a.isNull)(n.hubId)))).orderBy((0,a.desc)(p.businessDate),(0,a.desc)(p.id))).map(u=>({...u,businessDate:T(u.businessDate,"YYYY-MM-DD")}))},se=async e=>(await Q(t.select({hub:ne(p),internal:ne(g),creatorName:l.displayName,...M()}).from(p)).leftJoin(g,(0,a.eq)(p.id,g.hubId)).leftJoin(l,(0,a.eq)(p.userId,l.id)).where((0,a.and)((0,a.eq)(p.businessDate,a.sql`${e}`),(0,a.isNull)(p.deletedAt))).orderBy((0,a.desc)(p.id))).map(d=>ee(d)),ke=e=>`${B}${e}`,le=new Map,ge=async e=>{if(!r.disableUserIdCache&&le.has(e))return le.get(e)??null;let n=await m(e);return n!==null&&!r.disableUserIdCache&&le.set(e,n),n},Oe=async(e,{forceRefresh:n=!1,snapshot:d=!1,ttlMsOverride:u}={})=>{let b=await ge(e);if(!b)return[];let h=`${L}:user:${b}`;return c.getOrFetch({cacheKey:h,fetcher:async()=>await ae(b),forceRefresh:n,snapshot:d,ttlMsOverride:u??C,epochKey:S})},Fe=(e,{forceRefresh:n=!1,snapshot:d=!1,ttlMsOverride:u}={})=>{let b=G(e);return b?c.getOrFetch({cacheKey:ke(b),fetcher:()=>se(b),forceRefresh:n,snapshot:d,ttlMsOverride:u??x}):Promise.resolve([])},fe=null,oe=async()=>{if(fe!==null)return fe;let[e]=await t.select({id:F.id}).top(1).from(F).where((0,a.eq)(F.name,P));return e?(fe=e.id,fe):null},ze=async(e,n,{forceRefresh:d=!1,snapshot:u=!1,ttlMsOverride:b}={})=>{let h=await ge(n);if(!h)return[];let R=G(e);if(!R)return[];let I=`daily-report:date:${R}:user:${h}`;return c.getOrFetch({cacheKey:I,fetcher:async()=>{let U=await oe(),z=(0,a.aliasedTable)(X,"draft_label"),H=await Q(t.select({hub:ne(p),internal:ne(g),isRead:E.isRead,isStarred:E.isStarred,creatorName:l.displayName,...M()}).from(p)).leftJoin(g,(0,a.eq)(p.id,g.hubId)).leftJoin(E,(0,a.and)((0,a.eq)(p.id,E.hubId),(0,a.eq)(E.userId,h))).leftJoin(z,(0,a.and)((0,a.eq)(z.hubId,p.id),(0,a.eq)(z.labelId,U??-1))).leftJoin(l,(0,a.eq)(p.userId,l.id)).where((0,a.and)((0,a.eq)(p.businessDate,a.sql`${R}`),(0,a.isNull)(p.deletedAt),(0,a.or)((0,a.eq)(p.userId,h),(0,a.isNull)(z.hubId)))).orderBy((0,a.desc)(p.id));if(H.length===0)return[];let V=H.map(Y=>Y.hub.id),re=await t.select({hubId:X.hubId,id:F.id,name:F.name,color:F.color}).from(X).innerJoin(F,(0,a.eq)(X.labelId,F.id)).where((0,a.inArray)(X.hubId,V)),J=await t.select({hubId:k.hubId,id:k.id,body:k.body,createdAt:k.createdAt,userId:k.userId,userName:l.displayName}).from(k).leftJoin(l,(0,a.eq)(k.userId,l.id)).where((0,a.inArray)(k.hubId,V)).orderBy((0,a.asc)(k.createdAt)),ie=new Map,ue=new Map;for(let Y of re){let D=ie.get(Y.hubId);D||(D=[],ie.set(Y.hubId,D)),D.push({id:Y.id,name:Y.name,color:Y.color})}for(let Y of J){let D=ue.get(Y.hubId);D||(D=[],ue.set(Y.hubId,D)),D.push({id:Y.id,content:Y.body,createdAt:T(Y.createdAt,"YYYY-MM-DD HH:mm:ss")||"",userId:Y.userId,userName:Y.userName||""})}return H.map(Y=>{let D=Y.hub.id;return ee({...Y,labels:ie.get(D)||[],comments:ue.get(D)||[]},h)})},forceRefresh:d,snapshot:u,ttlMsOverride:b??x,epochKey:`${w}${R}`})},de=async(e,n,{forceRefresh:d=!1,snapshot:u=!1,ttlMsOverride:b}={})=>{let h=`daily-report:detail:${e}:user:${n}`;return(await c.getOrFetch({cacheKey:h,fetcher:async()=>{let I=await Q(t.select({hub:ne(p),internal:ne(g),isRead:E.isRead,isStarred:E.isStarred,creatorName:l.displayName,...M()}).from(p)).leftJoin(g,(0,a.eq)(p.id,g.hubId)).leftJoin(E,(0,a.and)((0,a.eq)(p.id,E.hubId),(0,a.eq)(E.userId,n))).leftJoin(l,(0,a.eq)(p.userId,l.id)).where((0,a.and)((0,a.eq)(p.id,e),(0,a.isNull)(p.deletedAt)));if(I.length===0)return[];let U=I[0].hub.id,z=await t.select({id:F.id,name:F.name,color:F.color}).from(X).innerJoin(F,(0,a.eq)(X.labelId,F.id)).where((0,a.eq)(X.hubId,U)),H=await t.select({id:k.id,body:k.body,createdAt:k.createdAt,userId:k.userId,userName:l.displayName}).from(k).leftJoin(l,(0,a.eq)(k.userId,l.id)).where((0,a.eq)(k.hubId,U)).orderBy((0,a.asc)(k.createdAt)),V=z.map(J=>({id:J.id,name:J.name,color:J.color})),re=H.map(J=>({id:J.id,content:J.body,createdAt:T(J.createdAt,"YYYY-MM-DD HH:mm:ss")||"",userId:J.userId,userName:J.userName||""}));return[ee({...I[0],labels:V,comments:re},n)]},forceRefresh:d,snapshot:u,ttlMsOverride:b??x,epochKey:`${q}${e}`}))[0]??null},Ke=async(e,n,d={})=>{let u=await ge(n);return u?de(e,u,d):null},Je=async(e,n,d,u,b)=>{let h=await t.select().top(1).from(E).where((0,a.and)((0,a.eq)(E.hubId,n),(0,a.eq)(E.userId,e))),R;if(h.length>0?h[0].isStarred!==u?R=(await t.update(E).set({isStarred:u,updatedAt:new Date,updatedBy:String(e)}).output().where((0,a.and)((0,a.eq)(E.hubId,n),(0,a.eq)(E.userId,e))))[0]:R=h[0]:R=(await t.insert(E).output().values({hubId:n,userId:e,isStarred:u,isRead:!1,createdAt:new Date,createdBy:String(e),updatedAt:new Date,updatedBy:String(e)}))[0],d){let I=G(d);I&&(c.invalidate(`daily-report:date:${I}:user:${e}`),await y(`${w}${I}`))}return c.invalidate(`daily-report:detail:${n}`),c.invalidate(`daily-report:detail:${n}:user:${e}`),await y(`${q}${n}`),await $(he.parse({type:"status-update",reportHubId:n,recipientRawUserId:e,statusType:"star",value:u,clientTempId:b}),"setStarStatus"),R},je=async(e,n,d,u,b)=>{let h=await t.select().top(1).from(E).where((0,a.and)((0,a.eq)(E.hubId,n),(0,a.eq)(E.userId,e))),R;if(h.length>0?h[0].isRead!==u?R=(await t.update(E).set({isRead:u,updatedAt:new Date,updatedBy:String(e)}).output().where((0,a.and)((0,a.eq)(E.hubId,n),(0,a.eq)(E.userId,e))))[0]:R=h[0]:R=(await t.insert(E).output().values({hubId:n,userId:e,isRead:u,isStarred:!1,createdAt:new Date,createdBy:String(e),updatedAt:new Date,updatedBy:String(e)}))[0],d){let I=G(d);I&&(c.invalidate(`daily-report:date:${I}:user:${e}`),await y(`${w}${I}`))}return c.invalidate(`daily-report:detail:${n}`),c.invalidate(`daily-report:detail:${n}:user:${e}`),await y(`${q}${n}`),await $(he.parse({type:"status-update",reportHubId:n,recipientRawUserId:e,statusType:"read",value:u,clientTempId:b}),"setReadStatus"),R},Qe=async(e,n,d,u,b)=>{let[h]=await t.insert(k).output().values({hubId:n,userId:e,body:d,createdAt:new Date,createdBy:String(e),updatedAt:new Date,updatedBy:String(e)}),[R]=await t.select({displayName:l.displayName}).top(1).from(l).where((0,a.eq)(l.id,e)),I=R?.displayName??"Unknown";if(u){let z=G(u);z&&(c.invalidatePrefix(`daily-report:date:${z}:user:`),await y(`${w}${z}`))}c.invalidate(`daily-report:detail:${n}`),c.invalidatePrefix(`daily-report:detail:${n}:user:`),await y(`${q}${n}`);let U={id:h.id,userId:f(h.userId),userName:I,content:h.body,createdAt:T(h.createdAt,"YYYY-MM-DD HH:mm:ss")??"",isMine:!0};return await $(Ce.parse({type:"comment-add",reportHubId:n,comment:U,clientTempId:b}),"addComment"),U},We=async(e,n)=>await e.select().top(1).from(k).where((0,a.eq)(k.id,n)),Xe=async(e,n,d,u,b)=>{let h=await We(t,d);if(h.length===0)throw new Error("Not Found");if(h[0].userId!==e)throw new Error("Unauthorized");if(await t.delete(k).where((0,a.eq)(k.id,d)),u){let R=G(u);R&&(c.invalidatePrefix(`daily-report:date:${R}:user:`),await y(`${w}${R}`))}c.invalidate(`daily-report:detail:${n}`),c.invalidatePrefix(`daily-report:detail:${n}:user:`),await y(`${q}${n}`),await $(Ae.parse({type:"comment-delete",reportHubId:n,commentId:d,clientTempId:b}),"deleteComment")},Ge=async(e,n,d)=>{_.info("createDailyReport called",{userId:e,businessDate:n});let[u]=await t.select({displayName:l.displayName}).from(l).where((0,a.eq)(l.id,e)),b=u?.displayName??f(e);try{let h=await t.transaction(async U=>{_.info("Starting transaction");let z=`internal-temp-${Date.now()}-${Math.random()}`,[H]=await U.insert(p).output().values({sourceType:"Internal",sourceId:z,businessDate:new Date(n),userId:e,title:"(\u7121\u984C)",createdAt:new Date,createdBy:String(e),updatedAt:new Date,updatedBy:String(e)});await U.update(p).set({sourceId:String(H.id)}).where((0,a.eq)(p.id,H.id)),_.info("Hub created",H),await U.insert(g).values({hubId:H.id,body:"",createdAt:new Date,createdBy:String(e),updatedAt:new Date,updatedBy:String(e)}),_.info("Internal created"),_.info("Calling getDraftLabelId");let V=await oe();_.info("draftLabelId",V);let re=[];return V&&(await U.insert(X).values({hubId:H.id,labelId:V,createdAt:new Date,createdBy:String(e)}),re.push({id:V,name:P,color:null})),_.info("Label assigned"),{reportHubId:H.id,date:n,createdAt:T(H.createdAt,"YYYY-MM-DD HH:mm:ss"),author:b,userId:f(e),sourceType:"Internal",employeeName:b,updatedBy:f(e),updatedAt:T(H.updatedAt,"YYYY-MM-DD HH:mm:ss"),category:null,creationCategory:null,visitTimeFrom:null,visitTimeTo:null,customerName:null,interviewers:[],subject:H.title,content:"",comments:[],isRead:!0,isStarred:!1,labels:re,commentItems:[]}}),R=G(n);R&&c.invalidate(`daily-report:date:${R}:user:${e}`),c.invalidatePrefix(B),c.invalidate(`${L}:user:${e}`),await y(S),R&&await y(`${w}${R}`);let I=await de(h.reportHubId,e,{forceRefresh:!0});if(I){let U=await oe(),z=U?I.labels.some(H=>H.id===U):!1;await $(Te.parse({type:"report-create",reportHubId:I.reportHubId,report:I,clientTempId:d,recipientRawUserId:z?e:void 0}),"createDailyReport")}return I??h}catch(h){throw _.error("Error in createDailyReport",h),h}},be=async(e,n)=>await e.select().top(1).from(p).where((0,a.eq)(p.id,n)),we=async(e,n,d)=>{await e.update(p).set(d).where((0,a.eq)(p.id,n))},$e=async(e,n,d)=>{await e.update(g).set(d).where((0,a.eq)(g.hubId,n))},Le=async(e,n,d)=>{await e.delete(X).where((0,a.and)((0,a.eq)(X.hubId,n),(0,a.eq)(X.labelId,d)))};return{streamKey:j,streamMaxLen:N,getUserIdByExternalId:ge,getDailyReportIdsByExternalId:Oe,getDailyReportsByBusinessDate:Fe,getDailyReportsByBusinessDateByExternalId:ze,getDailyReportDetailById:de,getDailyReportDetailByIdByExternalId:Ke,getDraftLabelId:oe,setStarStatus:Je,setReadStatus:je,addComment:Qe,deleteComment:Xe,createDailyReport:Ge,updateDailyReport:async(e,n,d,u)=>{let b=await be(t,e);if(!b.length||b[0].deletedAt)throw new Error("Not Found");if(b[0].userId!==n)throw new Error("Unauthorized");await t.transaction(async R=>{d.title!==void 0&&await we(R,e,{title:d.title,updatedAt:new Date,updatedBy:String(n)}),d.content!==void 0&&await $e(R,e,{body:d.content,updatedAt:new Date,updatedBy:String(n)})}),c.invalidatePrefix(`daily-report:detail:${e}:user:`),c.invalidatePrefix(B);let h=await de(e,n,{forceRefresh:!0});if(h){let R=await oe(),I=R?h.labels.some(U=>U.id===R):!1;await $(Me.parse({type:"report-update",reportHubId:h.reportHubId,report:h,clientTempId:u,recipientRawUserId:I?n:void 0}),"updateDailyReport")}},publishDailyReport:async(e,n,d)=>{let u=await be(t,e);if(!u.length)throw new Error("Not Found");if(u[0].userId!==n)throw new Error("Unauthorized");let b=await oe();if(!b)return null;if(await Le(t,e,b),c.invalidatePrefix(`daily-report:detail:${e}:user:`),c.invalidatePrefix(B),c.invalidatePrefix(L),await y(S),u[0].businessDate){let I=G(T(u[0].businessDate,"YYYY-MM-DD"));I&&await y(`${w}${I}`)}let h=G(T(u[0].businessDate,"YYYY-MM-DD"));h&&c.invalidate(`daily-report:date:${h}:user:${n}`);let R=await de(e,n,{forceRefresh:!0});return R&&await $(ve.parse({type:"report-publish",reportHubId:R.reportHubId,report:R,clientTempId:d}),"publishDailyReport"),R??null},deleteDailyReport:async(e,n,d)=>{let u=await be(t,e);if(!u.length||u[0].deletedAt)throw new Error("Not Found");if(u[0].userId!==n)throw new Error("Unauthorized");if(await we(t,e,{deletedAt:new Date,deletedBy:String(n),updatedAt:new Date,updatedBy:String(n)}),c.invalidatePrefix(`daily-report:detail:${e}:user:`),c.invalidatePrefix(B),c.invalidatePrefix(L),await y(S),u[0].businessDate){let b=G(T(u[0].businessDate,"YYYY-MM-DD"));b&&await y(`${w}${b}`)}await $(xe.parse({type:"report-delete",reportHubId:e,clientTempId:d}),"deleteDailyReport")},findDailyReportHubById:be,updateDailyReportHub:we,updateDailyReportInternal:$e,deleteDailyReportLabel:Le}}var ct=te(1,"[DailyReportExternalSource]"),pt=(r,t,o,l=ct)=>{if(!r)return[];try{let m=JSON.parse(r);return Array.isArray(m)?m.map(o).filter(f=>f!==null):(l.warn(`Unexpected ${t} format: not an array`),[])}catch(m){return l.warn(`Failed to parse ${t}:`,m),[]}};var ye=require("drizzle-orm"),i=require("drizzle-orm/mssql-core");function mt(r,t){let o=(0,i.mssqlSchema)(r),l=t.userTable,m=o.table("DailyReportHub",{id:(0,i.bigint)("id",{mode:"number"}).identity().notNull(),sourceType:(0,i.nvarchar)("source_type",{length:20}).notNull(),sourceId:(0,i.nvarchar)("source_id",{length:100}).notNull(),sourceIdNum:(0,i.bigint)("source_id_num",{mode:"number"}).generatedAlwaysAs(ye.sql`TRY_CAST(source_id AS BIGINT)`),businessDate:(0,i.date)("business_date"),userId:(0,i.bigint)("user_id",{mode:"number"}),title:(0,i.nvarchar)("title",{length:200}),summary:(0,i.nvarchar)("summary",{length:"max"}),createdAt:(0,i.datetime2)("created_at").notNull(),createdBy:(0,i.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,i.datetime2)("updated_at").notNull(),updatedBy:(0,i.nvarchar)("updated_by",{length:50}).notNull(),deletedAt:(0,i.datetime2)("deleted_at"),deletedBy:(0,i.nvarchar)("deleted_by",{length:50})},g=>[(0,i.primaryKey)({name:`${r}_DailyReportHub_pk`,columns:[g.id]}),(0,i.foreignKey)({name:`${r}_DailyReportHub_user_id_fk`,columns:[g.userId],foreignColumns:[l.id]}),(0,i.index)(`${r}_DailyReportHub_business_date_index`).on(g.businessDate),(0,i.index)(`${r}_DailyReportHub_updated_at_index`).on(g.updatedAt),(0,i.index)(`${r}_DailyReportHub_source_index`).on(g.sourceType,g.sourceId),(0,i.index)(`${r}_DailyReportHub_user_id_index`).on(g.userId),(0,i.index)(`${r}_DailyReportHub_business_date_id_index`).on((0,ye.desc)(g.businessDate),(0,ye.desc)(g.id)),(0,i.index)(`${r}_DailyReportHub_deleted_at_index`).on(g.deletedAt)]),f=o.table("DailyReportInternal",{hubId:(0,i.bigint)("hub_id",{mode:"number"}).notNull(),body:(0,i.nvarchar)("body",{length:"max"}),metadata:(0,i.nvarchar)("metadata",{length:"max"}),createdAt:(0,i.datetime2)("created_at").notNull(),createdBy:(0,i.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,i.datetime2)("updated_at").notNull(),updatedBy:(0,i.nvarchar)("updated_by",{length:50}).notNull()},g=>[(0,i.primaryKey)({name:`${r}_DailyReportInternal_pk`,columns:[g.hubId]}),(0,i.foreignKey)({name:`${r}_DailyReportInternal_hub_id_fk`,columns:[g.hubId],foreignColumns:[m.id]})]),O=o.table("DailyReportComment",{id:(0,i.bigint)("id",{mode:"number"}).identity().notNull(),hubId:(0,i.bigint)("hub_id",{mode:"number"}).notNull(),userId:(0,i.bigint)("user_id",{mode:"number"}).notNull(),body:(0,i.nvarchar)("body",{length:"max"}).notNull(),createdAt:(0,i.datetime2)("created_at").notNull(),createdBy:(0,i.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,i.datetime2)("updated_at").notNull(),updatedBy:(0,i.nvarchar)("updated_by",{length:50}).notNull()},g=>[(0,i.primaryKey)({name:`${r}_DailyReportComment_pk`,columns:[g.id]}),(0,i.foreignKey)({name:`${r}_DailyReportComment_hub_id_fk`,columns:[g.hubId],foreignColumns:[m.id]}),(0,i.foreignKey)({name:`${r}_DailyReportComment_user_id_fk`,columns:[g.userId],foreignColumns:[l.id]}),(0,i.index)(`${r}_DailyReportComment_hub_id_index`).on(g.hubId)]),c=o.table("DailyReportLabel",{id:(0,i.bigint)("id",{mode:"number"}).identity().notNull(),userId:(0,i.bigint)("user_id",{mode:"number"}),name:(0,i.nvarchar)("name",{length:50}).notNull(),color:(0,i.nvarchar)("color",{length:20}),sortOrder:(0,i.int)("sort_order"),createdAt:(0,i.datetime2)("created_at").notNull(),createdBy:(0,i.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,i.datetime2)("updated_at").notNull(),updatedBy:(0,i.nvarchar)("updated_by",{length:50}).notNull()},g=>[(0,i.primaryKey)({name:`${r}_DailyReportLabel_pk`,columns:[g.id]}),(0,i.foreignKey)({name:`${r}_DailyReportLabel_user_id_fk`,columns:[g.userId],foreignColumns:[l.id]})]),W=o.table("DailyReportHub_Label",{hubId:(0,i.bigint)("hub_id",{mode:"number"}).notNull(),labelId:(0,i.bigint)("label_id",{mode:"number"}).notNull(),createdAt:(0,i.datetime2)("created_at").notNull(),createdBy:(0,i.nvarchar)("created_by",{length:50}).notNull()},g=>[(0,i.primaryKey)({name:`${r}_DailyReportHub_Label_pk`,columns:[g.hubId,g.labelId]}),(0,i.foreignKey)({name:`${r}_DailyReportHub_Label_hub_id_fk`,columns:[g.hubId],foreignColumns:[m.id]}),(0,i.foreignKey)({name:`${r}_DailyReportHub_Label_label_id_fk`,columns:[g.labelId],foreignColumns:[c.id]})]),p=o.table("DailyReportUserStatus",{hubId:(0,i.bigint)("hub_id",{mode:"number"}).notNull(),userId:(0,i.bigint)("user_id",{mode:"number"}).notNull(),isRead:(0,i.bit)("is_read").default(!1).notNull(),isStarred:(0,i.bit)("is_starred").default(!1).notNull(),createdAt:(0,i.datetime2)("created_at").notNull(),createdBy:(0,i.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,i.datetime2)("updated_at").notNull(),updatedBy:(0,i.nvarchar)("updated_by",{length:50}).notNull()},g=>[(0,i.primaryKey)({name:`${r}_DailyReportUserStatus_pk`,columns:[g.hubId,g.userId]}),(0,i.foreignKey)({name:`${r}_DailyReportUserStatus_hub_id_fk`,columns:[g.hubId],foreignColumns:[m.id]}),(0,i.foreignKey)({name:`${r}_DailyReportUserStatus_user_id_fk`,columns:[g.userId],foreignColumns:[l.id]})]);return{hub:m,internal:f,comment:O,label:c,hubLabel:W,userStatus:p}}function yt(r){let t=Ie(r.redis),o=new ce({defaultTtlMs:r.cacheDefaultTtlMs??6e4},t),l=Ee({...r,cache:o,epochs:t}),m=new pe({redis:r.redis,streamKey:l.streamKey,cache:o,logger:r.logger}),f=Ne({authenticate:r.authenticate,service:l,encodeUserId:r.encodeUserId,redis:r.redis,sseReader:m,streamKey:l.streamKey,loginRedirectPath:r.loginRedirectPath,logger:r.logger});return{service:l,cache:o,epochs:t,sseReader:m,streamKey:l.streamKey,...f}}0&&(module.exports={DailyReportSseReader,SqlResultCache,createDailyReportHandlers,createDailyReportServer,createDailyReportService,createEpochStore,defineDailyReportSchema,generateETag,isStreamIdLte,jsonResponseWithETag,transformJsonArray});
|
|
10
10
|
//# sourceMappingURL=server.js.map
|