@aiquants/daily-report 0.18.0 → 0.18.2
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/README.md +2 -2
- package/dist/client.d.mts +6 -3
- package/dist/client.d.ts +6 -3
- package/dist/client.js +5 -5
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +5 -5
- package/dist/client.mjs.map +1 -1
- package/dist/server.d.mts +17 -7
- package/dist/server.d.ts +17 -7
- package/dist/server.js +10 -10
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +10 -10
- package/dist/server.mjs.map +1 -1
- package/dist/styles/daily-report.standalone.css +1 -1
- package/package.json +6 -4
- package/src/client/components/daily-report-list.tsx +199 -80
- package/src/client/components/daily-report-resize-panels.spec.tsx +305 -0
- package/src/client/hooks/use-responsive-layout.ts +34 -27
- package/src/server/handlers.ts +218 -176
- package/src/server/handlers.unauthorized-cookie.spec.ts +187 -0
- package/src/server/ports.ts +6 -1
- package/src/server/service.spec.ts +1 -1
- package/src/server/test-helpers/handlers-config.ts +16 -3
- package/src/server.spec.ts +7 -7
package/dist/server.d.mts
CHANGED
|
@@ -68,11 +68,21 @@ type DailyReportAuthResult = {
|
|
|
68
68
|
* `failureRedirect` が文字列の場合、未認証時は実装側で redirect を throw すること。
|
|
69
69
|
* null の場合は throw せず `user` 無しで解決する。
|
|
70
70
|
*/
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
})
|
|
71
|
+
interface DailyReportAuthenticate {
|
|
72
|
+
/** 失敗時は必ずリダイレクトを throw するため、正常復帰時の `user` は常に存在する。 */
|
|
73
|
+
(request: Request, options: {
|
|
74
|
+
failureRedirect: string;
|
|
75
|
+
}): Promise<{
|
|
76
|
+
user: {
|
|
77
|
+
id: string;
|
|
78
|
+
};
|
|
79
|
+
cookie?: string;
|
|
80
|
+
}>;
|
|
81
|
+
/** リダイレクトを発生させないモード。未認証では `user` を持たない結果が返る。 */
|
|
82
|
+
(request: Request, options: {
|
|
83
|
+
failureRedirect: null;
|
|
84
|
+
}): Promise<DailyReportAuthResult>;
|
|
85
|
+
}
|
|
76
86
|
/**
|
|
77
87
|
* Per-dimension visible source types (report body vs. comments).
|
|
78
88
|
* 次元ごとの可視 sourceType (本文とコメント)。
|
|
@@ -2174,7 +2184,7 @@ declare function createDailyReportHandlers(config: DailyReportHandlersConfig): {
|
|
|
2174
2184
|
data: {
|
|
2175
2185
|
user: {
|
|
2176
2186
|
id: string;
|
|
2177
|
-
}
|
|
2187
|
+
};
|
|
2178
2188
|
userId: string | null;
|
|
2179
2189
|
};
|
|
2180
2190
|
headers: Headers;
|
|
@@ -2256,7 +2266,7 @@ declare function createDailyReportServer(config: DailyReportServerConfig): {
|
|
|
2256
2266
|
data: {
|
|
2257
2267
|
user: {
|
|
2258
2268
|
id: string;
|
|
2259
|
-
}
|
|
2269
|
+
};
|
|
2260
2270
|
userId: string | null;
|
|
2261
2271
|
};
|
|
2262
2272
|
headers: Headers;
|
package/dist/server.d.ts
CHANGED
|
@@ -68,11 +68,21 @@ type DailyReportAuthResult = {
|
|
|
68
68
|
* `failureRedirect` が文字列の場合、未認証時は実装側で redirect を throw すること。
|
|
69
69
|
* null の場合は throw せず `user` 無しで解決する。
|
|
70
70
|
*/
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
})
|
|
71
|
+
interface DailyReportAuthenticate {
|
|
72
|
+
/** 失敗時は必ずリダイレクトを throw するため、正常復帰時の `user` は常に存在する。 */
|
|
73
|
+
(request: Request, options: {
|
|
74
|
+
failureRedirect: string;
|
|
75
|
+
}): Promise<{
|
|
76
|
+
user: {
|
|
77
|
+
id: string;
|
|
78
|
+
};
|
|
79
|
+
cookie?: string;
|
|
80
|
+
}>;
|
|
81
|
+
/** リダイレクトを発生させないモード。未認証では `user` を持たない結果が返る。 */
|
|
82
|
+
(request: Request, options: {
|
|
83
|
+
failureRedirect: null;
|
|
84
|
+
}): Promise<DailyReportAuthResult>;
|
|
85
|
+
}
|
|
76
86
|
/**
|
|
77
87
|
* Per-dimension visible source types (report body vs. comments).
|
|
78
88
|
* 次元ごとの可視 sourceType (本文とコメント)。
|
|
@@ -2174,7 +2184,7 @@ declare function createDailyReportHandlers(config: DailyReportHandlersConfig): {
|
|
|
2174
2184
|
data: {
|
|
2175
2185
|
user: {
|
|
2176
2186
|
id: string;
|
|
2177
|
-
}
|
|
2187
|
+
};
|
|
2178
2188
|
userId: string | null;
|
|
2179
2189
|
};
|
|
2180
2190
|
headers: Headers;
|
|
@@ -2256,7 +2266,7 @@ declare function createDailyReportServer(config: DailyReportServerConfig): {
|
|
|
2256
2266
|
data: {
|
|
2257
2267
|
user: {
|
|
2258
2268
|
id: string;
|
|
2259
|
-
}
|
|
2269
|
+
};
|
|
2260
2270
|
userId: string | null;
|
|
2261
2271
|
};
|
|
2262
2272
|
headers: Headers;
|
package/dist/server.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
"use strict";var et=Object.defineProperty;var Zt=Object.getOwnPropertyDescriptor;var er=Object.getOwnPropertyNames;var tr=Object.prototype.hasOwnProperty;var It=t=>{throw TypeError(t)};var rr=(t,e)=>{for(var r in e)et(t,r,{get:e[r],enumerable:!0})},nr=(t,e,r,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let d of er(e))!tr.call(t,d)&&d!==r&&et(t,d,{get:()=>e[d],enumerable:!(i=Zt(e,d))||i.enumerable});return t};var ar=t=>nr(et({},"__esModule",{value:!0}),t);var At=(t,e,r)=>e.has(t)||It("Cannot "+r);var $e=(t,e,r)=>(At(t,e,"read from private field"),r?r.call(t):e.get(t)),tt=(t,e,r)=>e.has(t)?It("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,r),rt=(t,e,r,i)=>(At(t,e,"write to private field"),i?i.call(t,r):e.set(t,r),r);var Kr={};rr(Kr,{DailyReportSseReader:()=>Ue,DailyReportViewerScope:()=>ce,SqlResultCache:()=>Be,asciiFallbackFileName:()=>Ut,buildVisibleSourceTypeCondition:()=>ht,computeSourceTypeDigest:()=>yt,computeViewerScopeDigest:()=>ke,createDailyReportHandlers:()=>bt,createDailyReportServer:()=>Vr,createDailyReportService:()=>gt,createEpochStore:()=>nt,defineDailyReportAuthzResources:()=>Ht,defineDailyReportSchema:()=>zr,deniesEverySourceType:()=>ge,encodeRfc8187:()=>Bt,formatDateValue:()=>ne,generateETag:()=>je,isSourceTypeVisible:()=>ye,isStreamIdLte:()=>xe,jsonResponseWithETag:()=>de,normalizeVisibleSourceTypes:()=>mt,sanitizeMediaType:()=>ft,seedDailyReportAuthzResources:()=>Yr,transformJsonArray:()=>qr});module.exports=ar(Kr);var nt=t=>({async getEpoch(e){try{let r=await t?.getClient();if(!r)return null;let i=await r.get(e);return i?Number(i):0}catch{return null}},async incrementEpoch(e){try{let r=await t?.getClient();if(!r)return;await r.incr(e)}catch{}}}),Be=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,d=this.buckets.get(i);if(!d)return;let c=e.ttlMsOverride??this.config.defaultTtlMs;if(c-(d.expireAt-Date.now())<c*r||this.inFlight.has(i))return;let y;y=(async()=>{let N=e.epochKey?await this.epochStore.getEpoch(e.epochKey):null,u=await e.fetcher();return this.inFlight.get(i)===y&&this.buckets.set(i,{records:u,expireAt:Date.now()+c,epoch:N}),u})(),this.inFlight.set(i,y),y.catch(()=>{}).finally(()=>{this.inFlight.get(i)===y&&this.inFlight.delete(i)})};this.getOrFetch=async e=>{let{cacheKey:r,forceRefresh:i,snapshot:d}=e,c=this.buckets.get(r);if(i&&(this.buckets.delete(r),this.inFlight.delete(r)),!i&&c&&c.expireAt>Date.now())if(e.epochKey){let y=await this.epochStore.getEpoch(e.epochKey);if(y===null||c.epoch===y)return this.maybeRefreshAhead(e),d?c.records.map(N=>structuredClone(N)):c.records;this.buckets.delete(r)}else return this.maybeRefreshAhead(e),d?c.records.map(y=>structuredClone(y)):c.records;if(!i&&this.inFlight.has(r)){let y=await this.inFlight.get(r);return d?y.map(N=>structuredClone(N)):y}let R;R=(async()=>{let y=e.epochKey?await this.epochStore.getEpoch(e.epochKey):null;e.onFetchStart?.();let N=await e.fetcher();if(i||this.inFlight.get(r)===R){let u=Date.now()+(e.ttlMsOverride??this.config.defaultTtlMs);this.buckets.set(r,{records:N,expireAt:u,epoch:y}),this.buckets.size>500&&this.cleanExpired()}return N})(),i||this.inFlight.set(r,R);try{let y=await R;return d?y.map(N=>structuredClone(N)):y}finally{this.inFlight.get(r)===R&&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 ir=/^\d{4}-\d{2}-\d{2}$/,sr=/^\d{4}\/\d{2}\/\d{2}$/,Tt=t=>t<10?`0${t}`:`${t}`,Ct=t=>{if(Number.isNaN(t.getTime()))return null;let e=t.getFullYear(),r=Tt(t.getMonth()+1),i=Tt(t.getDate());return`${e}-${r}-${i}`};var le=t=>{if(t==null)return null;if(t instanceof Date)return Ct(t);let e=t.trim();if(e==="")return null;if(ir.test(e))return e;if(sr.test(e))return e.replaceAll("/","-");let r=new Date(e);return Ct(r)};var at=t=>{let e=2166136261,r=-624069552;for(let i of t){let d=i.reportHubId;e^=d&255,e=Math.imul(e,16777619),e^=d>>>8&255,e=Math.imul(e,16777619),e^=d>>>16&255,e=Math.imul(e,16777619),e^=d>>>24&255,e=Math.imul(e,16777619),r^=d>>>24&255,r=Math.imul(r,16777619),r^=d>>>16&255,r=Math.imul(r,16777619),r^=d>>>8&255,r=Math.imul(r,16777619),r^=d&255,r=Math.imul(r,16777619);let c=i.businessDate;if(c===null)e^=1,e=Math.imul(e,16777619),r^=1,r=Math.imul(r,16777619);else for(let R=0;R<c.length;R++){let y=c.charCodeAt(R);e^=y&255,e=Math.imul(e,16777619),r^=y&255,r=Math.imul(r,16777619)}}return e^=t.length,e=Math.imul(e,16777619),r^=t.length,r=Math.imul(r,16777619),((e>>>0).toString(16).padStart(8,"0")+(r>>>0).toString(16).padStart(8,"0")).replace(/^0+(?=.)/,"")},Ve=(t,e)=>t.businessDate!==e.businessDate?t.businessDate===null?1:e.businessDate===null||t.businessDate>e.businessDate?-1:1:e.reportHubId-t.reportHubId,_t=t=>{for(let e=1;e<t.length;e++)if(Ve(t[e-1],t[e])>0)return!1;return!0};var vt=(t,e)=>{let r=t.findIndex(i=>Ve({businessDate:i.businessDate,reportHubId:i.reportHubId},e)>0);return r===-1?t.length:r};var ue=(t,e,r=console)=>{let i=d=>typeof d=="string"?[`${e} ${d}`]:[e,d];return{debug:(d,...c)=>{t<=0&&r.debug(...i(d),...c)},info:(d,...c)=>{t<=1&&r.info(...i(d),...c)},warn:(d,...c)=>{t<=2&&r.warn(...i(d),...c)},error:(d,...c)=>{t<=3&&r.error(...i(d),...c)}}};var m=require("zod"),or=m.z.object({name:m.z.string().nullish(),affiliation:m.z.string().nullish()}),lr=m.z.object({name:m.z.string().nullish(),text:m.z.string().nullish(),color:m.z.string().nullish()}),ur=m.z.object({id:m.z.number(),name:m.z.string().nullish(),color:m.z.string().nullish()}),xt=m.z.object({id:m.z.number(),userId:m.z.string().nullish(),userName:m.z.string().nullish(),content:m.z.string().nullish(),createdAt:m.z.string().nullish(),isMine:m.z.boolean()}),dr=m.z.object({id:m.z.string(),fileName:m.z.string(),fileType:m.z.string().nullable(),fileSize:m.z.number().nullable(),createdAt:m.z.string().nullable(),state:m.z.enum(["present","absent","unknown"])}),it=m.z.object({reportHubId:m.z.number(),date:m.z.string().nullish(),createdAt:m.z.string().nullish(),author:m.z.string().nullish(),userId:m.z.string().nullish(),sourceType:m.z.string().nullish(),employeeName:m.z.string().nullish(),updatedBy:m.z.string().nullish(),updatedAt:m.z.string().nullish(),category:m.z.string().nullish(),creationCategory:m.z.string().nullish(),visitTimeFrom:m.z.string().nullish(),visitTimeTo:m.z.string().nullish(),customerName:m.z.string().nullish(),interviewers:m.z.array(or),subject:m.z.string().nullish(),content:m.z.string().nullish(),externalComments:m.z.array(lr),isRead:m.z.boolean(),isStarred:m.z.boolean(),labels:m.z.array(ur),postedComments:m.z.array(xt),attachments:m.z.array(dr).default([])}),cr=m.z.object({type:m.z.literal("connected")}),Ke=m.z.object({type:m.z.literal("status-update"),reportHubId:m.z.number(),statusType:m.z.enum(["star","read"]),value:m.z.boolean(),clientTempId:m.z.string(),recipientRawUserId:m.z.number().optional()}),st=m.z.string().optional(),ot=m.z.object({type:m.z.literal("comment-add"),reportHubId:m.z.number(),comment:xt,clientTempId:m.z.string(),recipientRawUserId:m.z.number().optional(),sourceType:st}),lt=m.z.object({type:m.z.literal("comment-delete"),reportHubId:m.z.number(),commentId:m.z.number(),clientTempId:m.z.string(),recipientRawUserId:m.z.number().optional(),sourceType:st}),ut=m.z.object({type:m.z.literal("report-create"),reportHubId:m.z.number(),report:it,clientTempId:m.z.string(),recipientRawUserId:m.z.number().optional()}),dt=m.z.object({type:m.z.literal("report-update"),reportHubId:m.z.number(),report:it,clientTempId:m.z.string(),recipientRawUserId:m.z.number().optional()}),ct=m.z.object({type:m.z.literal("report-publish"),reportHubId:m.z.number(),report:it,clientTempId:m.z.string(),recipientRawUserId:m.z.number().optional()}),pt=m.z.object({type:m.z.literal("report-delete"),reportHubId:m.z.number(),clientTempId:m.z.string(),sourceType:st}),Mt=m.z.discriminatedUnion("type",[cr,Ke,ot,lt,ut,dt,ct,pt]);var Et=require("crypto"),je=t=>{let e=JSON.stringify(t);return`"${(0,Et.createHash)("sha256").update(e).digest("hex")}"`};var pr=ue(1,"[Response]"),de=(t,e,r,i=200,d=pr)=>{let c=je(r),R=t.headers.get("If-None-Match");d.info(`[jsonResponseWithETag] ETag: ${c}, If-None-Match: ${R}`);let y=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:c});return e&&y.append("Set-Cookie",e),t.method==="GET"&&i===200&&R===c?new Response(null,{status:304,headers:y}):new Response(JSON.stringify(r),{status:i,headers:y})};var kt=require("events");var xe=(t,e)=>{let[r,i]=t.split("-").map(Number),[d,c]=e.split("-").map(Number);return r!==d?r<d:i<=c},Ue=class{constructor(e){this.config=e;this._emitter=new kt.EventEmitter;this._state="idle";this._refCount=0;this._lastId="$";this._emitter.setMaxListeners(0),this._logger=e.logger??ue(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 d=i.message?.data?JSON.parse(i.message.data):null,c=d?.type;if((c==="report-create"||c==="report-delete"||c==="report-publish")&&this.config.cache.invalidatePrefix("daily-report:ids"),c==="comment-add"||c==="comment-delete"||c==="status-update"){let R=d?.reportHubId;typeof R=="number"&&(this.config.cache.invalidate(`daily-report:detail:${R}`),this.config.cache.invalidatePrefix(`daily-report:detail:${R}: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)}};var Oe=require("drizzle-orm");var mr="",yr=64,hr=t=>t.toLowerCase(),fr=t=>t.trim().toLowerCase();function mt(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=fr(r);i.length>0&&e.add(i)}return e}function ye(t,e){return t===null?!0:e==null?!1:t.has(hr(e))}function ge(t){return t!==null&&t.size===0}function ht(t,e){if(e!==null)return e.size===0?Oe.sql`1 = 0`:(0,Oe.inArray)(Oe.sql`LOWER(${t})`,[...e])}var Me,Ee,He=class He{constructor(e,r){tt(this,Me);tt(this,Ee);rt(this,Me,e),rt(this,Ee,r)}get visible(){return $e(this,Me)===null?null:new Set($e(this,Me))}get commentable(){return $e(this,Ee)===null?null:new Set($e(this,Ee))}static restrictTo(e){let r=typeof e=="object"&&e!==null&&"read"in e,i=mt(r?e.read:e),d=r?e.comment:void 0;if(d===void 0)return new He(i,i);let c=mt(d),R=new Set;for(let y of c??[])i.has(y)&&R.add(y);return new He(i,R)}static unrestricted(e){return new He(null,null)}};Me=new WeakMap,Ee=new WeakMap;var ce=He;function ke(t){let e=yt(t.visible),r=yt(t.commentable);return e===r?e:`d:${e.length}:${e}${r}`}function yt(t){if(t===null)return"all";if(t.size===0)return"none";let e=[...t].sort().map(i=>`${i.length}:${i}`).join(mr);if(e.length<=yr)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 U=(t,e)=>new Response(JSON.stringify(t),{status:e?.status??200,headers:{"Content-Type":"application/json"}}),Ge=30,$t=4e3,br="stream interrupted by server error",gr=/^\d{4}-\d{2}-\d{2}$/,Rr=15e3,Nt=Symbol("ids-stream-heartbeat"),Dr=12,wr=/^[0-9a-f]{1,16}$/,Sr=t=>{let e=t.searchParams.get("cursor_report_hub_id"),r=t.searchParams.get("cursor_business_date"),i=t.searchParams.get("cursor_snapshot"),d=i!==null&&wr.test(i)?i:null;if(e===null)return r===null?{cursor:null,snapshot:d}:{invalid:!0};let c=Number.parseInt(e,10);return!Number.isSafeInteger(c)||String(c)!==e||c<=0?{invalid:!0}:r===null?{cursor:{businessDate:null,reportHubId:c},snapshot:d}:gr.test(r)?{cursor:{businessDate:r,reportHubId:c},snapshot:d}:{invalid:!0}};async function*Lt(t,e,r,i){let d=e?vt(t,e):0,c=!0;for(;;){let R=t.slice(d,d+(c?r:$t));d+=R.length;let y=d>=t.length,N=R[R.length-1];if(yield{kind:"chunk",items:R,nextCursor:y||!N?null:{businessDate:N.businessDate,reportHubId:N.reportHubId},isLast:y,...c?{total:t.length}:{},snapshot:i.snapshot,...c&&i.restarted?{restarted:!0}:{}},c=!1,y)return}}var Pt=(t,e,r,i)=>{let d=new TextEncoder,c=!1,R=null,y=new ReadableStream({async pull(u){if(c||r.signal.aborted){await e.return(void 0).catch(()=>{});try{u.close()}catch{}return}let H=null;try{R===null&&(R=e.next());let h=new Promise(pe=>{H=setTimeout(()=>pe(Nt),Rr)}),z=await Promise.race([R,h]);if(H!==null&&(clearTimeout(H),H=null),z===Nt){if(c||r.signal.aborted){await e.return(void 0).catch(()=>{});try{u.close()}catch{}return}u.enqueue(d.encode(`
|
|
2
|
-
`));return}
|
|
3
|
-
`))}catch(h){if(H!==null&&clearTimeout(H),
|
|
4
|
-
`)),u.close()}catch{}}},cancel(){c=!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(y,{status:200,headers:N})},Ir=32*1024*1024,Ar=60,Tr=4,Cr=12e4,_r=1024,vr=60,xr=5,Mr=new Set(["image/png","image/jpeg","image/gif","image/webp","application/pdf","text/plain"]),Er=/^[\x20-\x7E]+$/,kr=/^[\w.+-]+\/[\w.+-]+/,ft=t=>t&&Er.test(t)&&kr.test(t)?t:null,Bt=t=>encodeURIComponent(t).replace(/['()*]/g,e=>`%${e.charCodeAt(0).toString(16).toUpperCase()}`),Ut=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"},Pr=t=>{let e=new Map;return(r,i)=>{let d=e.get(r);d&&e.delete(r);let c=d??{tokens:t,lastRefillMs:i},R=Math.max(0,i-c.lastRefillMs);R>0&&(c.tokens=Math.min(t,c.tokens+R*t/6e4),c.lastRefillMs=i);let y=c.tokens>=1;for(y&&(c.tokens-=1),e.set(r,c);e.size>_r;){let N=e.keys().next();if(N.done)break;e.delete(N.value)}return y}},$r=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 d=()=>{clearTimeout(i),e()},c=!1;return new ReadableStream({pull(R){if(c){R.close(),d();return}c=!0,R.enqueue(t)},cancel(){d()}})},Ur=(t,e,r,i)=>{if(r===null&&i===null)return!0;let d=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 ye(r,t.report.sourceType);case"comment-add":case"comment-delete":return ye(i,d??"Internal");case"report-delete":return ye(r,d)}},Hr=["externalComments","postedComments"],Or=(t,e,r)=>{if(r===null||t.type!=="report-create"&&t.type!=="report-update"&&t.type!=="report-publish"||ye(r,t.report.sourceType))return!1;let i=e.report;if(typeof i!="object"||i===null)return!1;let d=i;for(let c of Hr)d[c]=[];return!0};function bt(t){let{authenticate:e,service:r,encodeUserId:i,redis:d,sseReader:c,streamKey:R}=t,y=t.loginRedirectPath??"/auth/login",N=t.logger??ue(3,"[DailyReportAPI]"),u=t.logger??ue(3,"[DailyReportVisibility]"),H=t.logger??ue(1,"[DailyReportSSE]"),h=t.logger??ue(1,"[DailyReportAttachment]"),z=t.attachmentMaxBytes??Ir,V=Pr(t.attachmentRateLimitPerMinute??Ar),O=$r(t.attachmentConcurrency??Tr),pe=async(S,Y="initial")=>{let C=t.resolveVisibleSourceTypes;if(!C)return ce.unrestricted("no visibility port injected: this deployment does not restrict by source type");try{let A=await C(S,{reason:Y});return A==null?ce.unrestricted("visibility port returned null/undefined: this deployment opts out of source-type filtering"):ce.restrictTo(A)}catch(A){return u.error("resolveVisibleSourceTypes threw; failing closed (deny all)",A),ce.restrictTo([])}},Ne=async({request:S})=>{let{user:Y,cookie:C}=await e(S,{failureRedirect:y}),A=new Headers;C&&A.append("Set-Cookie",C);let _=null;Y&&(_=await r.getUserIdByExternalId(Y.id));let L=_?i(_):null;return{data:{user:Y,userId:L},headers:A}},Le={"business-date":async(S,Y,C,A,_)=>{let L=le(S.searchParams.get("businessDate")),P=S.searchParams.get("forceRefresh")==="true";if(!L)return de(C,Y,{error:{message:"Invalid business date"}},400);let T=await r.getDailyReportsByBusinessDateByExternalId(_,L,A.id,{forceRefresh:P});return de(C,Y,{businessDate:L,reports:T},200)},"ids-stream":async(S,Y,C,A,_)=>{let L=Sr(S);if("invalid"in L)return de(C,Y,{error:{message:"Invalid cursor"}},400);let P=S.searchParams.get("forceRefresh")==="true",T=!1,q=null,v=null,k=new Promise((F,D)=>{q=F,v=D});k.catch(()=>{});let ae=r.getDailyReportIdsByExternalId(_,A.id,{forceRefresh:P,onFetchStart:L.cursor?void 0:()=>{T=!0,r.getDailyReportIdsFirstPageByExternalId(_,A.id,Ge).then(F=>q?.(F),F=>v?.(F))}});if(ae.catch(()=>{}),L.cursor){let F=await ae,D=at(F),M=L.snapshot!==null&&L.snapshot===D;return Pt(Y,Lt(F,M?L.cursor:null,Ge,{snapshot:D,restarted:!M}),C,N)}let w=(async function*(){let F=await Promise.race([ae.then(E=>({kind:"full",items:E}),E=>({kind:"full-error",error:E})),k.then(E=>({kind:"page",items:E}),()=>({kind:"page-error"}))]),D=null,M=!1;if(F.kind==="full")D=F.items;else if(F.kind==="page"){let E=F.items;if(E.length<Ge){yield{kind:"chunk",items:E,nextCursor:null,isLast:!0,total:E.length};return}yield{kind:"chunk",items:E,nextCursor:null,isLast:!1,provisional:!0},M=!0}else if(F.kind==="full-error"&&T){let E=await k.catch(()=>null);E&&E.length>0&&(yield{kind:"chunk",items:E,nextCursor:null,isLast:!1,provisional:!0})}D===null&&(D=await ae),yield*Lt(D,null,M?$t:Ge,{snapshot:at(D)})})();return Pt(Y,w,C,N)},report:async(S,Y,C,A,_)=>{let L=S.searchParams.get("reportHubId"),P=S.searchParams.get("forceRefresh")==="true",T=L?Number.parseInt(L,10):NaN;if(!Number.isFinite(T)||T<=0)return de(C,Y,{error:{message:"Invalid reportHubId"}},400);let q=await r.getDailyReportDetailByIdByExternalId(_,T,A.id,{snapshot:!0,forceRefresh:P});return q?de(C,Y,{report:q},200):de(C,Y,{error:{message:"Report not found"}},404)}};return{index:{loader:Ne},api:{loader:async({request:S,params:Y})=>{let{user:C,cookie:A}=await e(S,{failureRedirect:null}),_=A??null;if(!C)return de(S,_,{error:{message:"Unauthorized"}},401);if(S.method!=="GET")return de(S,_,{error:{message:"Method not allowed"}},405);let L=Y.endpoint??"",P=Le[L];if(!P)return de(S,_,{error:{message:"Unknown endpoint"}},404);let T=Date.now();try{let q=new URL(S.url),v=await pe(S);return await P(q,_,S,C,v)}catch(q){let v=Date.now()-T,k=q instanceof Error?q:new Error(String(q));return N.error(`500 endpoint=${L} elapsed=${v}ms name=${k.name} code=${"code"in k?k.code:"N/A"} message=${k.message}`),N.error("Stack:",k.stack),de(S,_,{error:{message:"Internal Server Error"}},500)}},action:async({request:S,params:Y})=>{let{user:C}=await e(S,{failureRedirect:null});if(!C)return U({error:"Unauthorized"},{status:401});if(Y.endpoint!=="action")return U({error:"Unknown endpoint"},{status:404});let _=await r.getUserIdByExternalId(C.id);if(!_)return U({error:"User not found"},{status:404});let L=await pe(S),P=await S.formData(),T=P.get("intent"),q=P.get("reportHubId"),v=q?Number(q):NaN,k=P.get("businessDate"),ae=Number(P.get("operationTimestamp")),w=P.get("clientTempId");if(T==="clearCache")return t.enableDevCacheClear?(await r.clearCache(),U({status:"OK",intent:"clearCache"})):U({error:"Invalid intent"},{status:400});if(!w)return U({error:"clientTempId required"},{status:400});if(T!=="create"&&(!v||Number.isNaN(v)))return U({error:"Invalid reportHubId"},{status:400});let F=async(D,M,E)=>{let Z=P.get(M);if(Z===null)return U({error:`${M} required`},{status:400});try{let re=await E(Z==="true");return U({status:"OK",intent:D,updatedStatus:{isStarred:re.isStarred,isRead:re.isRead},operationTimestamp:ae,reportHubId:String(v),clientTempId:w})}catch(re){if(re instanceof Error&&re.message==="Not Found")return U({error:"Report not found"},{status:404});throw re}};switch(T){case"create":{if(!k)return U({error:"businessDate required"},{status:400});let D=await r.createDailyReport(_,k,w);return U({status:"OK",intent:"create",report:D,reportHubId:String(D.reportHubId),clientTempId:w})}case"update":{let D=P.get("title"),M=P.get("content");try{return await r.updateDailyReport(v,_,{title:D,content:M},w),U({status:"OK",intent:"update",reportHubId:String(v),clientTempId:w})}catch(E){if(E instanceof Error){if(E.message==="Unauthorized")return U({error:"Unauthorized"},{status:403});if(E.message==="Not Found")return U({error:"Report not found"},{status:404})}throw E}}case"publish":try{let D=await r.publishDailyReport(v,_,w);return U({status:"OK",intent:"publish",reportHubId:String(v),clientTempId:w,report:D})}catch(D){if(D instanceof Error){if(D.message==="Unauthorized")return U({error:"Unauthorized"},{status:403});if(D.message==="Not Found")return U({error:"Report not found"},{status:404})}throw D}case"delete":try{return await r.deleteDailyReport(v,_,w),U({status:"OK",intent:"delete",reportHubId:String(v),clientTempId:w})}catch(D){if(D instanceof Error){if(D.message==="Unauthorized")return U({error:"Unauthorized"},{status:403});if(D.message==="Not Found")return U({error:"Report not found"},{status:404})}throw D}case"toggleStar":return await F("toggleStar","isStarred",D=>r.setStarStatus(L,_,v,k,D,w));case"toggleRead":return await F("toggleRead","isRead",D=>r.setReadStatus(L,_,v,k,D,w));case"addComment":{let D=P.get("content");if(!D)return U({error:"Content required"},{status:400});try{let M=await r.addComment(L,_,v,D,k,w),E={...M,userId:M.userId};return U({status:"OK",intent:"addComment",newComment:E,reportHubId:String(v),clientTempId:w})}catch(M){if(M instanceof Error){if(M.message==="Not Found")return U({error:"Report not found"},{status:404});if(M.message.startsWith("Comments are restricted"))return U({error:"Comments are restricted for this report"},{status:403})}throw M}}case"deleteComment":{let D=Number(P.get("commentId"));if(!D||Number.isNaN(D))return U({error:"Invalid commentId"},{status:400});try{return await r.deleteComment(L,_,v,D,k,w),U({status:"OK",reportHubId:String(v),deletedCommentId:String(D),clientTempId:w})}catch(M){if(M instanceof Error){if(M.message==="Unauthorized")return U({error:"Unauthorized"},{status:403});if(M.message==="Not Found")return U({error:"Comment not found"},{status:404})}throw M}}default:return U({error:"Invalid intent"},{status:400})}}},sse:{loader:async({request:S,params:Y})=>{let{user:C}=await e(S,{failureRedirect:null});if(!C)return new Response("Unauthorized",{status:401});let A=await r.getUserIdByExternalId(C.id);if(!A)return new Response("Forbidden",{status:403});if(Y.endpoint!=="updates")return new Response("Not Found",{status:404});let _=await pe(S),L=_.visible,P=_.commentable,T=0,q=0,k=new URL(S.url).searchParams.get("lastEventId")||S.headers.get("Last-Event-ID"),ae=new TextEncoder,w=null,F=null,D=null,M=!1,E=()=>{if(!M){if(M=!0,F&&(clearInterval(F),F=null),D&&(D(),D=null),w)try{w.desiredSize!==null&&w.close()}catch{}finally{w=null}M=!1}},Z=me=>{w&&w.desiredSize!==null&&w.enqueue(ae.encode(`id: ${me}
|
|
1
|
+
"use strict";var Ze=Object.defineProperty;var Wt=Object.getOwnPropertyDescriptor;var Zt=Object.getOwnPropertyNames;var er=Object.prototype.hasOwnProperty;var St=t=>{throw TypeError(t)};var tr=(t,e)=>{for(var r in e)Ze(t,r,{get:e[r],enumerable:!0})},rr=(t,e,r,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let d of Zt(e))!er.call(t,d)&&d!==r&&Ze(t,d,{get:()=>e[d],enumerable:!(s=Wt(e,d))||s.enumerable});return t};var nr=t=>rr(Ze({},"__esModule",{value:!0}),t);var It=(t,e,r)=>e.has(t)||St("Cannot "+r);var $e=(t,e,r)=>(It(t,e,"read from private field"),r?r.call(t):e.get(t)),et=(t,e,r)=>e.has(t)?St("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(t):e.set(t,r),tt=(t,e,r,s)=>(It(t,e,"write to private field"),s?s.call(t,r):e.set(t,r),r);var Kr={};tr(Kr,{DailyReportSseReader:()=>Ue,DailyReportViewerScope:()=>me,SqlResultCache:()=>Be,asciiFallbackFileName:()=>Bt,buildVisibleSourceTypeCondition:()=>yt,computeSourceTypeDigest:()=>mt,computeViewerScopeDigest:()=>Ee,createDailyReportHandlers:()=>ft,createDailyReportServer:()=>Vr,createDailyReportService:()=>bt,createEpochStore:()=>rt,defineDailyReportAuthzResources:()=>Ut,defineDailyReportSchema:()=>zr,deniesEverySourceType:()=>Se,encodeRfc8187:()=>$t,formatDateValue:()=>re,generateETag:()=>je,isSourceTypeVisible:()=>he,isStreamIdLte:()=>ve,jsonResponseWithETag:()=>pe,normalizeVisibleSourceTypes:()=>pt,sanitizeMediaType:()=>ht,seedDailyReportAuthzResources:()=>Yr,transformJsonArray:()=>qr});module.exports=nr(Kr);var rt=t=>({async getEpoch(e){try{let r=await t?.getClient();if(!r)return null;let s=await r.get(e);return s?Number(s):0}catch{return null}},async incrementEpoch(e){try{let r=await t?.getClient();if(!r)return;await r.incr(e)}catch{}}}),Be=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:s}=e,d=this.buckets.get(s);if(!d)return;let c=e.ttlMsOverride??this.config.defaultTtlMs;if(c-(d.expireAt-Date.now())<c*r||this.inFlight.has(s))return;let y;y=(async()=>{let k=e.epochKey?await this.epochStore.getEpoch(e.epochKey):null,u=await e.fetcher();return this.inFlight.get(s)===y&&this.buckets.set(s,{records:u,expireAt:Date.now()+c,epoch:k}),u})(),this.inFlight.set(s,y),y.catch(()=>{}).finally(()=>{this.inFlight.get(s)===y&&this.inFlight.delete(s)})};this.getOrFetch=async e=>{let{cacheKey:r,forceRefresh:s,snapshot:d}=e,c=this.buckets.get(r);if(s&&(this.buckets.delete(r),this.inFlight.delete(r)),!s&&c&&c.expireAt>Date.now())if(e.epochKey){let y=await this.epochStore.getEpoch(e.epochKey);if(y===null||c.epoch===y)return this.maybeRefreshAhead(e),d?c.records.map(k=>structuredClone(k)):c.records;this.buckets.delete(r)}else return this.maybeRefreshAhead(e),d?c.records.map(y=>structuredClone(y)):c.records;if(!s&&this.inFlight.has(r)){let y=await this.inFlight.get(r);return d?y.map(k=>structuredClone(k)):y}let w;w=(async()=>{let y=e.epochKey?await this.epochStore.getEpoch(e.epochKey):null;e.onFetchStart?.();let k=await e.fetcher();if(s||this.inFlight.get(r)===w){let u=Date.now()+(e.ttlMsOverride??this.config.defaultTtlMs);this.buckets.set(r,{records:k,expireAt:u,epoch:y}),this.buckets.size>500&&this.cleanExpired()}return k})(),s||this.inFlight.set(r,w);try{let y=await w;return d?y.map(k=>structuredClone(k)):y}finally{this.inFlight.get(r)===w&&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,s]of this.buckets.entries())s.expireAt<=e&&this.buckets.delete(r)}};var ar=/^\d{4}-\d{2}-\d{2}$/,sr=/^\d{4}\/\d{2}\/\d{2}$/,At=t=>t<10?`0${t}`:`${t}`,Tt=t=>{if(Number.isNaN(t.getTime()))return null;let e=t.getFullYear(),r=At(t.getMonth()+1),s=At(t.getDate());return`${e}-${r}-${s}`};var ie=t=>{if(t==null)return null;if(t instanceof Date)return Tt(t);let e=t.trim();if(e==="")return null;if(ar.test(e))return e;if(sr.test(e))return e.replaceAll("/","-");let r=new Date(e);return Tt(r)};var nt=t=>{let e=2166136261,r=-624069552;for(let s of t){let d=s.reportHubId;e^=d&255,e=Math.imul(e,16777619),e^=d>>>8&255,e=Math.imul(e,16777619),e^=d>>>16&255,e=Math.imul(e,16777619),e^=d>>>24&255,e=Math.imul(e,16777619),r^=d>>>24&255,r=Math.imul(r,16777619),r^=d>>>16&255,r=Math.imul(r,16777619),r^=d>>>8&255,r=Math.imul(r,16777619),r^=d&255,r=Math.imul(r,16777619);let c=s.businessDate;if(c===null)e^=1,e=Math.imul(e,16777619),r^=1,r=Math.imul(r,16777619);else for(let w=0;w<c.length;w++){let y=c.charCodeAt(w);e^=y&255,e=Math.imul(e,16777619),r^=y&255,r=Math.imul(r,16777619)}}return e^=t.length,e=Math.imul(e,16777619),r^=t.length,r=Math.imul(r,16777619),((e>>>0).toString(16).padStart(8,"0")+(r>>>0).toString(16).padStart(8,"0")).replace(/^0+(?=.)/,"")},Ve=(t,e)=>t.businessDate!==e.businessDate?t.businessDate===null?1:e.businessDate===null||t.businessDate>e.businessDate?-1:1:e.reportHubId-t.reportHubId,Ct=t=>{for(let e=1;e<t.length;e++)if(Ve(t[e-1],t[e])>0)return!1;return!0};var _t=(t,e)=>{let r=t.findIndex(s=>Ve({businessDate:s.businessDate,reportHubId:s.reportHubId},e)>0);return r===-1?t.length:r};var de=(t,e,r=console)=>{let s=d=>typeof d=="string"?[`${e} ${d}`]:[e,d];return{debug:(d,...c)=>{t<=0&&r.debug(...s(d),...c)},info:(d,...c)=>{t<=1&&r.info(...s(d),...c)},warn:(d,...c)=>{t<=2&&r.warn(...s(d),...c)},error:(d,...c)=>{t<=3&&r.error(...s(d),...c)}}};var m=require("zod"),or=m.z.object({name:m.z.string().nullish(),affiliation:m.z.string().nullish()}),ir=m.z.object({name:m.z.string().nullish(),text:m.z.string().nullish(),color:m.z.string().nullish()}),lr=m.z.object({id:m.z.number(),name:m.z.string().nullish(),color:m.z.string().nullish()}),vt=m.z.object({id:m.z.number(),userId:m.z.string().nullish(),userName:m.z.string().nullish(),content:m.z.string().nullish(),createdAt:m.z.string().nullish(),isMine:m.z.boolean()}),ur=m.z.object({id:m.z.string(),fileName:m.z.string(),fileType:m.z.string().nullable(),fileSize:m.z.number().nullable(),createdAt:m.z.string().nullable(),state:m.z.enum(["present","absent","unknown"])}),at=m.z.object({reportHubId:m.z.number(),date:m.z.string().nullish(),createdAt:m.z.string().nullish(),author:m.z.string().nullish(),userId:m.z.string().nullish(),sourceType:m.z.string().nullish(),employeeName:m.z.string().nullish(),updatedBy:m.z.string().nullish(),updatedAt:m.z.string().nullish(),category:m.z.string().nullish(),creationCategory:m.z.string().nullish(),visitTimeFrom:m.z.string().nullish(),visitTimeTo:m.z.string().nullish(),customerName:m.z.string().nullish(),interviewers:m.z.array(or),subject:m.z.string().nullish(),content:m.z.string().nullish(),externalComments:m.z.array(ir),isRead:m.z.boolean(),isStarred:m.z.boolean(),labels:m.z.array(lr),postedComments:m.z.array(vt),attachments:m.z.array(ur).default([])}),dr=m.z.object({type:m.z.literal("connected")}),Ke=m.z.object({type:m.z.literal("status-update"),reportHubId:m.z.number(),statusType:m.z.enum(["star","read"]),value:m.z.boolean(),clientTempId:m.z.string(),recipientRawUserId:m.z.number().optional()}),st=m.z.string().optional(),ot=m.z.object({type:m.z.literal("comment-add"),reportHubId:m.z.number(),comment:vt,clientTempId:m.z.string(),recipientRawUserId:m.z.number().optional(),sourceType:st}),it=m.z.object({type:m.z.literal("comment-delete"),reportHubId:m.z.number(),commentId:m.z.number(),clientTempId:m.z.string(),recipientRawUserId:m.z.number().optional(),sourceType:st}),lt=m.z.object({type:m.z.literal("report-create"),reportHubId:m.z.number(),report:at,clientTempId:m.z.string(),recipientRawUserId:m.z.number().optional()}),ut=m.z.object({type:m.z.literal("report-update"),reportHubId:m.z.number(),report:at,clientTempId:m.z.string(),recipientRawUserId:m.z.number().optional()}),dt=m.z.object({type:m.z.literal("report-publish"),reportHubId:m.z.number(),report:at,clientTempId:m.z.string(),recipientRawUserId:m.z.number().optional()}),ct=m.z.object({type:m.z.literal("report-delete"),reportHubId:m.z.number(),clientTempId:m.z.string(),sourceType:st}),xt=m.z.discriminatedUnion("type",[dr,Ke,ot,it,lt,ut,dt,ct]);var kt=require("crypto"),je=t=>{let e=JSON.stringify(t);return`"${(0,kt.createHash)("sha256").update(e).digest("hex")}"`};var cr=de(1,"[Response]"),pe=(t,e,r,s=200,d=cr)=>{let c=je(r),w=t.headers.get("If-None-Match");d.info(`[jsonResponseWithETag] ETag: ${c}, If-None-Match: ${w}`);let y=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:c});return e&&y.append("Set-Cookie",e),t.method==="GET"&&s===200&&w===c?new Response(null,{status:304,headers:y}):new Response(JSON.stringify(r),{status:s,headers:y})};var Et=require("events");var ve=(t,e)=>{let[r,s]=t.split("-").map(Number),[d,c]=e.split("-").map(Number);return r!==d?r<d:s<=c},Ue=class{constructor(e){this.config=e;this._emitter=new Et.EventEmitter;this._state="idle";this._refCount=0;this._lastId="$";this._emitter.setMaxListeners(0),this._logger=e.logger??de(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 s of r.messages){this._lastId=s.id;try{let d=s.message?.data?JSON.parse(s.message.data):null,c=d?.type;if((c==="report-create"||c==="report-delete"||c==="report-publish")&&this.config.cache.invalidatePrefix("daily-report:ids"),c==="comment-add"||c==="comment-delete"||c==="status-update"){let w=d?.reportHubId;typeof w=="number"&&(this.config.cache.invalidate(`daily-report:detail:${w}`),this.config.cache.invalidatePrefix(`daily-report:detail:${w}: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)}};var Oe=require("drizzle-orm");var pr="",mr=64,yr=t=>t.toLowerCase(),hr=t=>t.trim().toLowerCase();function pt(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 s=hr(r);s.length>0&&e.add(s)}return e}function he(t,e){return t===null?!0:e==null?!1:t.has(yr(e))}function Se(t){return t!==null&&t.size===0}function yt(t,e){if(e!==null)return e.size===0?Oe.sql`1 = 0`:(0,Oe.inArray)(Oe.sql`LOWER(${t})`,[...e])}var xe,ke,He=class He{constructor(e,r){et(this,xe);et(this,ke);tt(this,xe,e),tt(this,ke,r)}get visible(){return $e(this,xe)===null?null:new Set($e(this,xe))}get commentable(){return $e(this,ke)===null?null:new Set($e(this,ke))}static restrictTo(e){let r=typeof e=="object"&&e!==null&&"read"in e,s=pt(r?e.read:e),d=r?e.comment:void 0;if(d===void 0)return new He(s,s);let c=pt(d),w=new Set;for(let y of c??[])s.has(y)&&w.add(y);return new He(s,w)}static unrestricted(e){return new He(null,null)}};xe=new WeakMap,ke=new WeakMap;var me=He;function Ee(t){let e=mt(t.visible),r=mt(t.commentable);return e===r?e:`d:${e.length}:${e}${r}`}function mt(t){if(t===null)return"all";if(t.size===0)return"none";let e=[...t].sort().map(s=>`${s.length}:${s}`).join(pr);if(e.length<=mr)return`s:${e}`;let r=2166136261;for(let s=0;s<e.length;s++)r^=e.charCodeAt(s),r=Math.imul(r,16777619);return`sh:${(r>>>0).toString(16)}`}var fr=(t,e)=>{let r=new Headers({"Content-Type":"application/json"});return e?.setCookie&&r.append("Set-Cookie",e.setCookie),new Response(JSON.stringify(t),{status:e?.status??200,headers:r})},Ge=30,Pt=4e3,br="stream interrupted by server error",gr=/^\d{4}-\d{2}-\d{2}$/,Rr=15e3,Mt=Symbol("ids-stream-heartbeat"),Dr=12,wr=/^[0-9a-f]{1,16}$/,Sr=t=>{let e=t.searchParams.get("cursor_report_hub_id"),r=t.searchParams.get("cursor_business_date"),s=t.searchParams.get("cursor_snapshot"),d=s!==null&&wr.test(s)?s:null;if(e===null)return r===null?{cursor:null,snapshot:d}:{invalid:!0};let c=Number.parseInt(e,10);return!Number.isSafeInteger(c)||String(c)!==e||c<=0?{invalid:!0}:r===null?{cursor:{businessDate:null,reportHubId:c},snapshot:d}:gr.test(r)?{cursor:{businessDate:r,reportHubId:c},snapshot:d}:{invalid:!0}};async function*Nt(t,e,r,s){let d=e?_t(t,e):0,c=!0;for(;;){let w=t.slice(d,d+(c?r:Pt));d+=w.length;let y=d>=t.length,k=w[w.length-1];if(yield{kind:"chunk",items:w,nextCursor:y||!k?null:{businessDate:k.businessDate,reportHubId:k.reportHubId},isLast:y,...c?{total:t.length}:{},snapshot:s.snapshot,...c&&s.restarted?{restarted:!0}:{}},c=!1,y)return}}var Lt=(t,e,r,s)=>{let d=new TextEncoder,c=!1,w=null,y=new ReadableStream({async pull(u){if(c||r.signal.aborted){await e.return(void 0).catch(()=>{});try{u.close()}catch{}return}let H=null;try{w===null&&(w=e.next());let h=new Promise(ye=>{H=setTimeout(()=>ye(Mt),Rr)}),V=await Promise.race([w,h]);if(H!==null&&(clearTimeout(H),H=null),V===Mt){if(c||r.signal.aborted){await e.return(void 0).catch(()=>{});try{u.close()}catch{}return}u.enqueue(d.encode(`
|
|
2
|
+
`));return}w=null;let{value:K,done:O}=V;if(O){u.close();return}if(c||r.signal.aborted){await e.return(void 0).catch(()=>{});try{u.close()}catch{}return}u.enqueue(d.encode(`${JSON.stringify(K)}
|
|
3
|
+
`))}catch(h){if(H!==null&&clearTimeout(H),w=null,c||r.signal.aborted)return;s.error(`ids-stream emission failed: ${h instanceof Error?h.message:String(h)}`);try{let V={kind:"error",error:br};u.enqueue(d.encode(`${JSON.stringify(V)}
|
|
4
|
+
`)),u.close()}catch{}}},cancel(){c=!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(y,{status:200,headers:k})},Ir=32*1024*1024,Ar=60,Tr=4,Cr=12e4,_r=1024,vr=60,xr=5,kr=new Set(["image/png","image/jpeg","image/gif","image/webp","application/pdf","text/plain"]),Er=/^[\x20-\x7E]+$/,Mr=/^[\w.+-]+\/[\w.+-]+/,ht=t=>t&&Er.test(t)&&Mr.test(t)?t:null,$t=t=>encodeURIComponent(t).replace(/['()*]/g,e=>`%${e.charCodeAt(0).toString(16).toUpperCase()}`),Bt=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"},Pr=t=>{let e=new Map;return(r,s)=>{let d=e.get(r);d&&e.delete(r);let c=d??{tokens:t,lastRefillMs:s},w=Math.max(0,s-c.lastRefillMs);w>0&&(c.tokens=Math.min(t,c.tokens+w*t/6e4),c.lastRefillMs=s);let y=c.tokens>=1;for(y&&(c.tokens-=1),e.set(r,c);e.size>_r;){let k=e.keys().next();if(k.done)break;e.delete(k.value)}return y}},$r=t=>{let e=0;return{tryAcquire:()=>e>=t?!1:(e+=1,!0),release:()=>{e>0&&(e-=1)}}},Br=(t,e,r)=>{let s=setTimeout(e,r);s.unref?.();let d=()=>{clearTimeout(s),e()},c=!1;return new ReadableStream({pull(w){if(c){w.close(),d();return}c=!0,w.enqueue(t)},cancel(){d()}})},Ur=(t,e,r,s)=>{if(r===null&&s===null)return!0;let d=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 he(r,t.report.sourceType);case"comment-add":case"comment-delete":return he(s,d??"Internal");case"report-delete":return he(r,d)}},Hr=["externalComments","postedComments"],Or=(t,e,r)=>{if(r===null||t.type!=="report-create"&&t.type!=="report-update"&&t.type!=="report-publish"||he(r,t.report.sourceType))return!1;let s=e.report;if(typeof s!="object"||s===null)return!1;let d=s;for(let c of Hr)d[c]=[];return!0};function ft(t){let{authenticate:e,service:r,encodeUserId:s,redis:d,sseReader:c,streamKey:w}=t,y=t.loginRedirectPath??"/auth/login",k=t.logger??de(3,"[DailyReportAPI]"),u=t.logger??de(3,"[DailyReportVisibility]"),H=t.logger??de(1,"[DailyReportSSE]"),h=t.logger??de(1,"[DailyReportAttachment]"),V=t.attachmentMaxBytes??Ir,K=Pr(t.attachmentRateLimitPerMinute??Ar),O=$r(t.attachmentConcurrency??Tr),ye=async(I,z="initial")=>{let T=t.resolveVisibleSourceTypes;if(!T)return me.unrestricted("no visibility port injected: this deployment does not restrict by source type");try{let C=await T(I,{reason:z});return C==null?me.unrestricted("visibility port returned null/undefined: this deployment opts out of source-type filtering"):me.restrictTo(C)}catch(C){return u.error("resolveVisibleSourceTypes threw; failing closed (deny all)",C),me.restrictTo([])}},Me=async({request:I})=>{let{user:z,cookie:T}=await e(I,{failureRedirect:y}),C=new Headers;T&&C.append("Set-Cookie",T);let b=await r.getUserIdByExternalId(z.id),L=b?s(b):null;return{data:{user:z,userId:L},headers:C}},Ne={"business-date":async(I,z,T,C,b)=>{let L=ie(I.searchParams.get("businessDate")),Y=I.searchParams.get("forceRefresh")==="true";if(!L)return pe(T,z,{error:{message:"Invalid business date"}},400);let R=await r.getDailyReportsByBusinessDateByExternalId(b,L,C.id,{forceRefresh:Y});return pe(T,z,{businessDate:L,reports:R},200)},"ids-stream":async(I,z,T,C,b)=>{let L=Sr(I);if("invalid"in L)return pe(T,z,{error:{message:"Invalid cursor"}},400);let Y=I.searchParams.get("forceRefresh")==="true",R=!1,P=null,E=null,F=new Promise((B,N)=>{P=B,E=N});F.catch(()=>{});let ce=r.getDailyReportIdsByExternalId(b,C.id,{forceRefresh:Y,onFetchStart:L.cursor?void 0:()=>{R=!0,r.getDailyReportIdsFirstPageByExternalId(b,C.id,Ge).then(B=>P?.(B),B=>E?.(B))}});if(ce.catch(()=>{}),L.cursor){let B=await ce,N=nt(B),v=L.snapshot!==null&&L.snapshot===N;return Lt(z,Nt(B,v?L.cursor:null,Ge,{snapshot:N,restarted:!v}),T,k)}let M=(async function*(){let B=await Promise.race([ce.then(q=>({kind:"full",items:q}),q=>({kind:"full-error",error:q})),F.then(q=>({kind:"page",items:q}),()=>({kind:"page-error"}))]),N=null,v=!1;if(B.kind==="full")N=B.items;else if(B.kind==="page"){let q=B.items;if(q.length<Ge){yield{kind:"chunk",items:q,nextCursor:null,isLast:!0,total:q.length};return}yield{kind:"chunk",items:q,nextCursor:null,isLast:!1,provisional:!0},v=!0}else if(B.kind==="full-error"&&R){let q=await F.catch(()=>null);q&&q.length>0&&(yield{kind:"chunk",items:q,nextCursor:null,isLast:!1,provisional:!0})}N===null&&(N=await ce),yield*Nt(N,null,v?Pt:Ge,{snapshot:nt(N)})})();return Lt(z,M,T,k)},report:async(I,z,T,C,b)=>{let L=I.searchParams.get("reportHubId"),Y=I.searchParams.get("forceRefresh")==="true",R=L?Number.parseInt(L,10):NaN;if(!Number.isFinite(R)||R<=0)return pe(T,z,{error:{message:"Invalid reportHubId"}},400);let P=await r.getDailyReportDetailByIdByExternalId(b,R,C.id,{snapshot:!0,forceRefresh:Y});return P?pe(T,z,{report:P},200):pe(T,z,{error:{message:"Report not found"}},404)}};return{index:{loader:Me},api:{loader:async({request:I,params:z})=>{let{user:T,cookie:C}=await e(I,{failureRedirect:null}),b=C??null;if(!T)return pe(I,b,{error:{message:"Unauthorized"}},401);if(I.method!=="GET")return pe(I,b,{error:{message:"Method not allowed"}},405);let L=z.endpoint??"",Y=Ne[L];if(!Y)return pe(I,b,{error:{message:"Unknown endpoint"}},404);let R=Date.now();try{let P=new URL(I.url),E=await ye(I);return await Y(P,b,I,T,E)}catch(P){let E=Date.now()-R,F=P instanceof Error?P:new Error(String(P));return k.error(`500 endpoint=${L} elapsed=${E}ms name=${F.name} code=${"code"in F?F.code:"N/A"} message=${F.message}`),k.error("Stack:",F.stack),pe(I,b,{error:{message:"Internal Server Error"}},500)}},action:async({request:I,params:z})=>{let{user:T,cookie:C}=await e(I,{failureRedirect:null}),b=(Y,R)=>fr(Y,{...R,setCookie:C});if(!T)return b({error:"Unauthorized"},{status:401});let L=Date.now();try{if(z.endpoint!=="action")return b({error:"Unknown endpoint"},{status:404});let R=await r.getUserIdByExternalId(T.id);if(!R)return b({error:"User not found"},{status:404});let P=await ye(I),E=await I.formData(),F=E.get("intent"),ce=E.get("reportHubId"),M=ce?Number(ce):NaN,B=E.get("businessDate"),N=Number(E.get("operationTimestamp")),v=E.get("clientTempId");if(F==="clearCache")return t.enableDevCacheClear?(await r.clearCache(),b({status:"OK",intent:"clearCache"})):b({error:"Invalid intent"},{status:400});if(!v)return b({error:"clientTempId required"},{status:400});if(F!=="create"&&(!M||Number.isNaN(M)))return b({error:"Invalid reportHubId"},{status:400});let q=async(S,U,Z)=>{let fe=E.get(U);if(fe===null)return b({error:`${U} required`},{status:400});try{let le=await Z(fe==="true");return b({status:"OK",intent:S,updatedStatus:{isStarred:le.isStarred,isRead:le.isRead},operationTimestamp:N,reportHubId:String(M),clientTempId:v})}catch(le){if(le instanceof Error&&le.message==="Not Found")return b({error:"Report not found"},{status:404});throw le}};switch(F){case"create":{if(!B)return b({error:"businessDate required"},{status:400});let S=await r.createDailyReport(R,B,v);return b({status:"OK",intent:"create",report:S,reportHubId:String(S.reportHubId),clientTempId:v})}case"update":{let S=E.get("title"),U=E.get("content");try{return await r.updateDailyReport(M,R,{title:S,content:U},v),b({status:"OK",intent:"update",reportHubId:String(M),clientTempId:v})}catch(Z){if(Z instanceof Error){if(Z.message==="Unauthorized")return b({error:"Unauthorized"},{status:403});if(Z.message==="Not Found")return b({error:"Report not found"},{status:404})}throw Z}}case"publish":try{let S=await r.publishDailyReport(M,R,v);return b({status:"OK",intent:"publish",reportHubId:String(M),clientTempId:v,report:S})}catch(S){if(S instanceof Error){if(S.message==="Unauthorized")return b({error:"Unauthorized"},{status:403});if(S.message==="Not Found")return b({error:"Report not found"},{status:404})}throw S}case"delete":try{return await r.deleteDailyReport(M,R,v),b({status:"OK",intent:"delete",reportHubId:String(M),clientTempId:v})}catch(S){if(S instanceof Error){if(S.message==="Unauthorized")return b({error:"Unauthorized"},{status:403});if(S.message==="Not Found")return b({error:"Report not found"},{status:404})}throw S}case"toggleStar":return await q("toggleStar","isStarred",S=>r.setStarStatus(P,R,M,B,S,v));case"toggleRead":return await q("toggleRead","isRead",S=>r.setReadStatus(P,R,M,B,S,v));case"addComment":{let S=E.get("content");if(!S)return b({error:"Content required"},{status:400});try{let U=await r.addComment(P,R,M,S,B,v),Z={...U,userId:U.userId};return b({status:"OK",intent:"addComment",newComment:Z,reportHubId:String(M),clientTempId:v})}catch(U){if(U instanceof Error){if(U.message==="Not Found")return b({error:"Report not found"},{status:404});if(U.message.startsWith("Comments are restricted"))return b({error:"Comments are restricted for this report"},{status:403})}throw U}}case"deleteComment":{let S=Number(E.get("commentId"));if(!S||Number.isNaN(S))return b({error:"Invalid commentId"},{status:400});try{return await r.deleteComment(P,R,M,S,B,v),b({status:"OK",reportHubId:String(M),deletedCommentId:String(S),clientTempId:v})}catch(U){if(U instanceof Error){if(U.message==="Unauthorized")return b({error:"Unauthorized"},{status:403});if(U.message==="Not Found")return b({error:"Comment not found"},{status:404})}throw U}}default:return b({error:"Invalid intent"},{status:400})}}catch(Y){if(Y instanceof Response)throw Y;let R=Date.now()-L,P=Y instanceof Error?Y:new Error(String(Y));return k.error(`500 action elapsed=${R}ms name=${P.name} message=${P.message}`),k.error("Stack:",P.stack),b({error:"Internal Server Error"},{status:500})}}},sse:{loader:async({request:I,params:z})=>{let{user:T,cookie:C}=await e(I,{failureRedirect:null}),b=ne=>C===void 0?ne:{...ne??{},"Set-Cookie":C};if(!T)return new Response("Unauthorized",{status:401,headers:b()});let L=await r.getUserIdByExternalId(T.id);if(!L)return new Response("Forbidden",{status:403,headers:b()});if(z.endpoint!=="updates")return new Response("Not Found",{status:404,headers:b()});let Y=await ye(I),R=Y.visible,P=Y.commentable,E=0,F=0,M=new URL(I.url).searchParams.get("lastEventId")||I.headers.get("Last-Event-ID"),B=new TextEncoder,N=null,v=null,q=null,S=!1,U=()=>{if(!S){if(S=!0,v&&(clearInterval(v),v=null),q&&(q(),q=null),N)try{N.desiredSize!==null&&N.close()}catch{}finally{N=null}S=!1}},Z=ne=>{N&&N.desiredSize!==null&&N.enqueue(B.encode(`id: ${ne}
|
|
5
5
|
data: ${JSON.stringify({type:"connected"})}
|
|
6
6
|
|
|
7
|
-
`))},
|
|
8
|
-
data: ${
|
|
7
|
+
`))},fe=(ne,ee)=>{if(ee.data)try{let J=JSON.parse(ee.data),x=xt.safeParse(J);if(!x.success){H.error("SSE message validation failed:",x.error.format());return}let X=x.data,ue=typeof J.recipientRawUserId=="number"?J.recipientRawUserId:void 0;if(X.type==="status-update"){if(ue===void 0||ue!==L)return}else if(ue!==void 0&&ue!==L)return;if(!Ur(X,J,R,P)){Z(ne);return}let Re=Or(X,J,P),be;if("recipientRawUserId"in J){let{recipientRawUserId:De,...Le}=J;be=JSON.stringify(Le)}else Re?be=JSON.stringify(J):be=ee.data;N&&N.desiredSize!==null&&N.enqueue(B.encode(`id: ${ne}
|
|
8
|
+
data: ${be}
|
|
9
9
|
|
|
10
|
-
`))}catch(
|
|
10
|
+
`))}catch(J){H.error(`[SSE:${L}] processEntry error:`,J)}},le=new ReadableStream({async start(ne){N=ne,v=setInterval(()=>{try{if(N&&N.desiredSize!==null){if(N.enqueue(B.encode(`: keep-alive
|
|
11
11
|
|
|
12
|
-
`)),++
|
|
12
|
+
`)),++E%Dr===0){let x=++F;ye(I,"refresh").then(X=>{x===F&&(R=X.visible,P=X.commentable)})}}else U()}catch{U()}},5e3),I.signal.addEventListener("abort",()=>{U()});let ee=M||"0-0",J=null;if(q=c.subscribe(x=>{ve(x.id,ee)||(J===null&&(J=x.id),ee=x.id,fe(x.id,x.message))},x=>{H.error(`[SSE:${L}] Fan-Out reader error:`,x),U()}),!M)try{let x=await d?.getClient();if(x){let X=await x.xRevRange(w,"+","-",{COUNT:1});X.length>0&&!ve(X[0].id,ee)&&(ee=X[0].id)}}catch{}if(N&&N.desiredSize!==null){let x=`data: ${JSON.stringify({type:"connected"})}
|
|
13
13
|
|
|
14
|
-
`,
|
|
15
|
-
${B}`:B;w.enqueue(ae.encode(J))}if(k)try{let B=await d?.getClient();if(B){let J=await B.xRange(R,k,"+",{COUNT:1e3});for(let j of J)j.id!==k&&(X!==null&&xe(X,j.id)||(xe(j.id,ee)||(ee=j.id),re(j.id,j.message)))}}catch(B){H.error(`[SSE:${A}] catch-up xRange error:`,B)}},cancel(){E()}});return new Response(fe,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive"}})}},attachment:{loader:async({request:S,params:Y})=>{let C=null,A=(_,L,P)=>{let T=new Headers({"Content-Type":"application/json"});return P!==void 0&&T.set("Retry-After",String(P)),C&&T.append("Set-Cookie",C),new Response(JSON.stringify({error:{message:L}}),{status:_,headers:T})};try{let{user:_,cookie:L}=await e(S,{failureRedirect:null});if(C=L??null,!_)return A(401,"Unauthorized");if(S.method!=="GET"&&S.method!=="HEAD")return A(405,"Method not allowed");let P=t.attachmentIdCodec,T=t.readAttachment;if(!(P&&T))return A(404,"Attachment not found");let q=Y.token??"",v=P.decode(q);if(v===null||!Number.isSafeInteger(v)||v<=0)return A(400,"Invalid attachment token");let k=await r.getUserIdByExternalId(_.id);if(!k)return A(403,"Forbidden");if(!V(k,Date.now()))return h.error(`429 attachment=${v} viewer=${k} reason=rate_limit`),A(429,"Too many requests",vr);let ae=await pe(S),w=await r.getAttachmentForUser(ae,v,k);if(!w)return h.error(`404 attachment=${v} viewer=${k} reason=not_visible`),A(404,"Attachment not found");if(w.fileSize!=null&&w.fileSize>z)return h.error(`413 attachment=${v} viewer=${k} reason=db_size`),A(413,"Attachment too large");if(!O.tryAcquire())return h.error(`503 attachment=${v} viewer=${k} reason=concurrency`),A(503,"Too many concurrent downloads",xr);let F=!1,D=()=>{F||(F=!0,O.release())},M=!1;try{let E=S.method==="HEAD",Z=await T(w.filePath,{maxBytes:z,head:E,principal:i(k)});if(!Z.ok){let j=Nr(Z.reason);return Z.reason==="not_found"&&r.markAttachmentMissing(v).catch(Ae=>{h.error(`markAttachmentMissing failed attachment=${v} message=${Ae instanceof Error?Ae.message:"unknown"}`)}),h.error(`${j} attachment=${v} viewer=${k} reason=${Z.reason} code=${Z.code??"-"}`),A(j,Lr[j]??"Attachment storage unavailable")}let re=ft(w.fileType)??ft(Z.contentType)??"application/octet-stream",fe=Mr.has(re),me=new URL(S.url).searchParams.get("download")==="1",ee=fe?re:"application/octet-stream",X=fe&&!me?"inline":"attachment",B=Z.size??Z.bytes.byteLength,J=new Headers({"Content-Type":ee,"Content-Length":String(B),"Content-Disposition":`${X}; filename="${Ut(w.fileName)}"; filename*=UTF-8''${Bt(w.fileName)}`,"Cache-Control":"private, no-store","X-Content-Type-Options":"nosniff","Content-Security-Policy":"default-src 'none'; sandbox","X-Frame-Options":"SAMEORIGIN"});return C&&J.append("Set-Cookie",C),r.markAttachmentPresent(v).catch(j=>{h.error(`markAttachmentPresent failed attachment=${v} message=${j instanceof Error?j.message:"unknown"}`)}),h.info(`200 attachment=${v} viewer=${k} type=${ee} disposition=${X} bytes=${B}`),E?new Response(null,{status:200,headers:J}):(M=!0,new Response(Br(Z.bytes,D,Cr),{status:200,headers:J}))}finally{M||D()}}catch(_){if(_ instanceof Response)throw _;return h.error(`500 attachment=? viewer=? reason=unexpected message=${_ instanceof Error?_.message:"unknown"}`),A(500,"Attachment request failed")}}}}}var a=require("drizzle-orm");var Se=t=>(0,a.getColumns)(t),ne=(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(),d=i<0?`-${String(-i).padStart(4,"0")}`:String(i).padStart(4,"0"),c=String(r.getMonth()+1).padStart(2,"0"),R=String(r.getDate()).padStart(2,"0");if(e==="YYYY-MM-DD")return`${d}-${c}-${R}`;let y=String(r.getHours()).padStart(2,"0"),N=String(r.getMinutes()).padStart(2,"0"),u=String(r.getSeconds()).padStart(2,"0");return`${d}-${c}-${R} ${y}:${N}:${u}`};function gt(t){let{db:e,tables:r,userTable:i,resolveUserId:d,encodeUserId:c,redis:R,cache:y,epochs:N}=t,{hub:u,internal:H,comment:h,label:z,hubLabel:V,userStatus:O}=r,pe=t.externalSources??[],Ne=t.draftLabelNames&&t.draftLabelNames.length>0?t.draftLabelNames:[t.draftLabelName??"\u4E0B\u66F8\u304D"],Le=Ne[0]??"\u4E0B\u66F8\u304D",te=t.logger??ue(1,"[DailyReportService]"),Ie="daily-report:ids",Rt=t.idsTtlMs??18e4,Re="daily-report:ids:epoch",S="daily-report:business-date:",Y=t.businessDateTtlMs??3e5,C="daily-report:date-epoch:",A="daily-report:detail-epoch:",L=`${t.streamKey??"daily-report:sse-stream"}:v2`,P=t.streamMaxLen??1e4,T=n=>N.incrementEpoch(n),q=n=>ht(u.sourceType,n),v=(n,s)=>`${Ie}:user:${n}:st:${s}`,k=n=>`${Ie}:user:${n}:`,ae=(n,s,o)=>`daily-report:date:${n}:user:${s}:st:${o}`,w=(n,s)=>`daily-report:date:${n}:user:${s}:`,F=(n,s,o)=>`daily-report:detail:${n}:user:${s}:st:${o}`,D=(n,s)=>`daily-report:detail:${n}:user:${s}:`,M=async(n,s)=>{let o=await R?.getClient();if(!o){te.warn(`[SSE] Redis client unavailable (${s})`);return}let p=Date.now();try{await o.xAdd(L,"*",{data:JSON.stringify(n)},{TRIM:{strategy:"MAXLEN",strategyModifier:"~",threshold:P}});let f=Date.now()-p;f>1e3&&te.warn(`[SSE] Slow publish (${s}): ${f}ms`)}catch(f){te.error(`[SSE] Redis publish failed (${s}):`,f)}},E=n=>n==null||n===""?null:/^\d+$/.test(n)?c(Number(n)):n,Z=()=>{let n={};for(let s of pe)n[`ext_${s.sourceType}`]=Se(s.table);return n},re=n=>{let s=n;for(let o of pe)s=s.leftJoin(o.table,(0,a.and)((0,a.eq)(u.sourceType,o.sourceType),(0,a.eq)(u.sourceIdNum,o.idColumn)));return s},fe=(n,s,o)=>{let{hub:p,internal:f}=s,b=p.summary,g=[],I=null,x=null,G=null,K=null,W=null,ie=null,_e=[],be=pe.find($=>$.sourceType===p.sourceType),ve=be?s[`ext_${be.sourceType}`]:void 0;if(be&&ve){let $=be.mapRow(ve);$.content!==void 0&&(b=$.content),$.employeeName!==void 0&&(ie=$.employeeName),$.category!==void 0&&(I=$.category),$.creationCategory!==void 0&&(x=$.creationCategory),$.visitTimeFrom!==void 0&&(G=$.visitTimeFrom),$.visitTimeTo!==void 0&&(K=$.visitTimeTo),$.customerName!==void 0&&(W=$.customerName),$.interviewers!==void 0&&(g=$.interviewers),$.externalComments!==void 0&&(_e=$.externalComments)}else p.sourceType==="Internal"&&f&&(b=f.body);let he=(s.labels??[]).map($=>({id:$.id,name:$.name,color:$.color})),se=s.postedCommentRows??[],Q=ye(n.commentable,p.sourceType),oe=x?Ne.includes(x):!1,Ze=De?.[0]??null;return oe&&Ze&&!he.some($=>$.id===Ze)&&he.push({id:Ze,name:Le,color:null}),{reportHubId:p.id,date:ne(p.businessDate,"YYYY-MM-DD"),author:s.creatorName??E(p.createdBy)??"",userId:p.userId?c(p.userId):"",sourceType:p.sourceType??"Internal",createdAt:ne(p.createdAt,"YYYY-MM-DD HH:mm:ss"),updatedAt:ne(p.updatedAt,"YYYY-MM-DD HH:mm:ss"),updatedBy:E(p.updatedBy),employeeName:ie??s.creatorName??E(p.createdBy),category:I,creationCategory:x,visitTimeFrom:G,visitTimeTo:K,customerName:W,interviewers:g,subject:p.title,content:b,externalComments:Q?_e:[],isRead:s.isRead??!1,isStarred:s.isStarred??!1,labels:he,postedComments:se.filter($=>Q||o!==void 0&&$.userId===o).map($=>({...$,userId:c($.userId),isMine:o?$.userId===o:!1})),attachments:s.attachments}},me=async(n,s)=>{let o=(0,a.aliasedTable)(V,"draft_label"),p=await we();return(await e.select({reportHubId:u.id,businessDate:u.businessDate,sourceType:u.sourceType}).from(u).leftJoin(o,(0,a.and)((0,a.eq)(o.hubId,u.id),(0,a.inArray)(o.labelId,p))).where((0,a.and)((0,a.isNull)(u.deletedAt),(0,a.or)((0,a.eq)(u.userId,s),(0,a.isNull)(u.userId),(0,a.isNull)(o.hubId)),q(n.visible))).orderBy((0,a.desc)(u.businessDate),(0,a.desc)(u.id))).map(b=>({...b,businessDate:ne(b.businessDate,"YYYY-MM-DD")}))},ee=async(n,s,o)=>{let p=await j(s);if(!p)return[];if(ge(n.visible))return[];let f=(0,a.aliasedTable)(V,"draft_label"),b=await we();return(await e.select({reportHubId:u.id,businessDate:u.businessDate,sourceType:u.sourceType}).top(o).from(u).leftJoin(f,(0,a.and)((0,a.eq)(f.hubId,u.id),(0,a.inArray)(f.labelId,b))).where((0,a.and)((0,a.isNull)(u.deletedAt),(0,a.or)((0,a.eq)(u.userId,p),(0,a.isNull)(u.userId),(0,a.isNull)(f.hubId)),q(n.visible))).orderBy((0,a.desc)(u.businessDate),(0,a.desc)(u.id))).map(I=>({...I,businessDate:ne(I.businessDate,"YYYY-MM-DD")}))},X=async(n,s)=>{let o=await re(e.select({hub:Se(u),internal:Se(H),creatorName:i.displayName,...Z()}).from(u)).leftJoin(H,(0,a.eq)(u.id,H.hubId)).leftJoin(i,(0,a.eq)(u.userId,i.id)).where((0,a.and)((0,a.eq)(u.businessDate,a.sql`${s}`),(0,a.isNull)(u.deletedAt),q(n.visible))).orderBy((0,a.desc)(u.id)),p=await qe(o.map(f=>f.hub.id));return o.map(f=>fe(n,{...f,attachments:p.get(f.hub.id)??[]}))},B=n=>`${S}${n}`,J=new Map,j=async n=>{if(!t.disableUserIdCache&&J.has(n))return J.get(n)??null;let s=await d(n);return s!==null&&!t.disableUserIdCache&&J.set(n,s),s},Ae=async(n,s,{forceRefresh:o=!1,snapshot:p=!1,ttlMsOverride:f,onFetchStart:b}={})=>{let g=await j(s);if(!g)return[];if(ge(n.visible))return[];let I=v(g,ke(n));return y.getOrFetch({cacheKey:I,fetcher:async()=>{let x=await me(n,g);return _t(x)?x:(te.warn("[DailyReportService] ids array is not in stream order; re-sorting (check SQL ORDER BY vs compareIdsStreamOrder, or concurrent row movement during the scan)"),[...x].sort(Ve))},onFetchStart:b,forceRefresh:o,snapshot:p,ttlMsOverride:f??Rt,epochKey:Re,refreshAheadRatio:.5})},Te=(n,s,{forceRefresh:o=!1,snapshot:p=!1,ttlMsOverride:f}={})=>{let b=le(s);return b?ge(n.visible)?Promise.resolve([]):y.getOrFetch({cacheKey:`${B(b)}:st:${ke(n)}`,fetcher:()=>X(n,b),forceRefresh:o,snapshot:p,ttlMsOverride:f??Y}):Promise.resolve([])},De=null,Ce=async()=>(De!==null||(De=(await e.select({id:z.id}).from(z).where((0,a.inArray)(z.name,Ne)).orderBy(z.id)).map(s=>s.id)),De),we=async()=>{let n=await Ce();return n.length>0?n:[-1]},Qe=async()=>{let n=await Ce();if(n.length===0)return null;let[s]=await e.select({id:z.id}).top(1).from(z).where((0,a.eq)(z.name,Le));return s?.id??n[0]},Ot=(n,s)=>s!=null?"absent":n!=null?"present":"unknown",qe=async n=>{let s=new Map,o=r.attachment,p=t.attachmentIdCodec;if(n.length===0||!o||!p)return s;let f=await e.select({id:o.id,hubId:o.hubId,fileName:o.fileName,fileType:o.fileType,fileSize:o.fileSize,createdAt:o.createdAt,objectCheckedAt:o.objectCheckedAt,objectMissingAt:o.objectMissingAt}).from(o).where((0,a.inArray)(o.hubId,n)).orderBy((0,a.asc)(o.createdAt),(0,a.asc)(o.id));for(let b of f){let g={id:p.encode(Number(b.id)),fileName:String(b.fileName),fileType:b.fileType?String(b.fileType):null,fileSize:b.fileSize!=null?Number(b.fileSize):null,createdAt:ne(b.createdAt,"YYYY-MM-DD HH:mm:ss"),state:Ot(b.objectCheckedAt,b.objectMissingAt)},I=s.get(Number(b.hubId));I?I.push(g):s.set(Number(b.hubId),[g])}return s},Yt=async(n,s,o)=>{let p=r.attachment;if(!p||ge(n.visible))return null;let f=await we(),b=(0,a.aliasedTable)(V,"draft_label");return(await e.select({fileName:p.fileName,filePath:p.filePath,fileType:p.fileType,fileSize:p.fileSize}).top(1).from(p).innerJoin(u,(0,a.eq)(u.id,p.hubId)).leftJoin(b,(0,a.and)((0,a.eq)(b.hubId,u.id),(0,a.inArray)(b.labelId,f))).where((0,a.and)((0,a.eq)(p.id,s),(0,a.isNull)(u.deletedAt),(0,a.or)((0,a.eq)(u.userId,o),(0,a.isNull)(b.hubId)),q(n.visible))))[0]??null},Ft=async n=>{let s=r.attachment;if(!s)return;let o=new Date;try{await e.update(s).set({objectCheckedAt:o,objectMissingAt:o,updatedAt:o}).where((0,a.eq)(s.id,n))}catch(p){te.error("markAttachmentMissing failed",p)}},qt=async n=>{let s=r.attachment;if(!s)return;let o=new Date;try{await e.update(s).set({objectCheckedAt:o,objectMissingAt:null,updatedAt:o}).where((0,a.eq)(s.id,n))}catch(p){te.error("markAttachmentPresent failed",p)}},zt=async(n,s,o,{forceRefresh:p=!1,snapshot:f=!1,ttlMsOverride:b}={})=>{let g=await j(o);if(!g)return[];let I=le(s);if(!I)return[];if(ge(n.visible))return[];let x=ae(I,g,ke(n));return y.getOrFetch({cacheKey:x,fetcher:async()=>{let G=await we(),K=(0,a.aliasedTable)(V,"draft_label"),W=await re(e.select({hub:Se(u),internal:Se(H),isRead:O.isRead,isStarred:O.isStarred,creatorName:i.displayName,...Z()}).from(u)).leftJoin(H,(0,a.eq)(u.id,H.hubId)).leftJoin(O,(0,a.and)((0,a.eq)(u.id,O.hubId),(0,a.eq)(O.userId,g))).leftJoin(K,(0,a.and)((0,a.eq)(K.hubId,u.id),(0,a.inArray)(K.labelId,G))).leftJoin(i,(0,a.eq)(u.userId,i.id)).where((0,a.and)((0,a.eq)(u.businessDate,a.sql`${I}`),(0,a.isNull)(u.deletedAt),(0,a.or)((0,a.eq)(u.userId,g),(0,a.isNull)(K.hubId)),q(n.visible))).orderBy((0,a.desc)(u.id));if(W.length===0)return[];let ie=W.map(Q=>Q.hub.id),_e=await e.select({hubId:V.hubId,id:z.id,name:z.name,color:z.color}).from(V).innerJoin(z,(0,a.eq)(V.labelId,z.id)).where((0,a.inArray)(V.hubId,ie)),be=await e.select({hubId:h.hubId,id:h.id,body:h.body,createdAt:h.createdAt,userId:h.userId,userName:i.displayName}).from(h).leftJoin(i,(0,a.eq)(h.userId,i.id)).where((0,a.inArray)(h.hubId,ie)).orderBy((0,a.asc)(h.createdAt)),ve=await qe(ie),he=new Map,se=new Map;for(let Q of _e){let oe=he.get(Q.hubId);oe||(oe=[],he.set(Q.hubId,oe)),oe.push({id:Q.id,name:Q.name,color:Q.color})}for(let Q of be){let oe=se.get(Q.hubId);oe||(oe=[],se.set(Q.hubId,oe)),oe.push({id:Q.id,content:Q.body,createdAt:ne(Q.createdAt,"YYYY-MM-DD HH:mm:ss")||"",userId:Q.userId,userName:Q.userName||""})}return W.map(Q=>{let oe=Q.hub.id;return fe(n,{...Q,attachments:ve.get(oe)??[],labels:he.get(oe)||[],postedCommentRows:se.get(oe)||[]},g)})},forceRefresh:p,snapshot:f,ttlMsOverride:b??Y,epochKey:`${C}${I}`})},Pe=async(n,s,o,{forceRefresh:p=!1,snapshot:f=!1,ttlMsOverride:b}={})=>{if(ge(n.visible))return null;let g=F(s,o,ke(n));return(await y.getOrFetch({cacheKey:g,fetcher:async()=>{let x=await we(),G=(0,a.aliasedTable)(V,"draft_label"),K=await re(e.select({hub:Se(u),internal:Se(H),isRead:O.isRead,isStarred:O.isStarred,creatorName:i.displayName,...Z()}).from(u)).leftJoin(H,(0,a.eq)(u.id,H.hubId)).leftJoin(O,(0,a.and)((0,a.eq)(u.id,O.hubId),(0,a.eq)(O.userId,o))).leftJoin(G,(0,a.and)((0,a.eq)(G.hubId,u.id),(0,a.inArray)(G.labelId,x))).leftJoin(i,(0,a.eq)(u.userId,i.id)).where((0,a.and)((0,a.eq)(u.id,s),(0,a.isNull)(u.deletedAt),(0,a.or)((0,a.eq)(u.userId,o),(0,a.isNull)(G.hubId)),q(n.visible)));if(K.length===0)return[];let W=K[0].hub.id,ie=await e.select({id:z.id,name:z.name,color:z.color}).from(V).innerJoin(z,(0,a.eq)(V.labelId,z.id)).where((0,a.eq)(V.hubId,W)),_e=await e.select({id:h.id,body:h.body,createdAt:h.createdAt,userId:h.userId,userName:i.displayName}).from(h).leftJoin(i,(0,a.eq)(h.userId,i.id)).where((0,a.eq)(h.hubId,W)).orderBy((0,a.asc)(h.createdAt)),be=await qe([W]),ve=ie.map(se=>({id:se.id,name:se.name,color:se.color})),he=_e.map(se=>({id:se.id,content:se.body,createdAt:ne(se.createdAt,"YYYY-MM-DD HH:mm:ss")||"",userId:se.userId,userName:se.userName||""}));return[fe(n,{...K[0],attachments:be.get(W)??[],labels:ve,postedCommentRows:he},o)]},forceRefresh:p,snapshot:f,ttlMsOverride:b??Y,epochKey:`${A}${s}`}))[0]??null},Vt=async(n,s,o,p={})=>{let f=await j(o);return f?Pe(n,s,f,p):null},Kt=async(n,s)=>{let o=await we(),p=(0,a.aliasedTable)(V,"draft_label"),[f]=await e.select({sourceType:u.sourceType,deletedAt:u.deletedAt}).top(1).from(u).leftJoin(p,(0,a.and)((0,a.eq)(p.hubId,u.id),(0,a.inArray)(p.labelId,o))).where((0,a.and)((0,a.eq)(u.id,n),(0,a.or)((0,a.eq)(u.userId,s),(0,a.isNull)(p.hubId))));return f??null},Xe=async(n,s,o)=>{let p=await Kt(s,o);if(!p||p.deletedAt||!ye(n.visible,p.sourceType))throw new Error("Not Found")},jt=async(n,s,o,p,f,b)=>{await Xe(n,o,s);let g=await e.select().top(1).from(O).where((0,a.and)((0,a.eq)(O.hubId,o),(0,a.eq)(O.userId,s))),I;if(g.length>0?g[0].isStarred!==f?I=(await e.update(O).set({isStarred:f,updatedAt:new Date,updatedBy:String(s)}).output().where((0,a.and)((0,a.eq)(O.hubId,o),(0,a.eq)(O.userId,s))))[0]:I=g[0]:I=(await e.insert(O).output().values({hubId:o,userId:s,isStarred:f,isRead:!1,createdAt:new Date,createdBy:String(s),updatedAt:new Date,updatedBy:String(s)}))[0],p){let x=le(p);x&&(y.invalidatePrefix(w(x,s)),await T(`${C}${x}`))}return y.invalidate(`daily-report:detail:${o}`),y.invalidatePrefix(D(o,s)),await T(`${A}${o}`),await M(Ke.parse({type:"status-update",reportHubId:o,recipientRawUserId:s,statusType:"star",value:f,clientTempId:b}),"setStarStatus"),I},Jt=async(n,s,o,p,f,b)=>{await Xe(n,o,s);let g=await e.select().top(1).from(O).where((0,a.and)((0,a.eq)(O.hubId,o),(0,a.eq)(O.userId,s))),I;if(g.length>0?g[0].isRead!==f?I=(await e.update(O).set({isRead:f,updatedAt:new Date,updatedBy:String(s)}).output().where((0,a.and)((0,a.eq)(O.hubId,o),(0,a.eq)(O.userId,s))))[0]:I=g[0]:I=(await e.insert(O).output().values({hubId:o,userId:s,isRead:f,isStarred:!1,createdAt:new Date,createdBy:String(s),updatedAt:new Date,updatedBy:String(s)}))[0],p){let x=le(p);x&&(y.invalidatePrefix(w(x,s)),await T(`${C}${x}`))}return y.invalidate(`daily-report:detail:${o}`),y.invalidatePrefix(D(o,s)),await T(`${A}${o}`),await M(Ke.parse({type:"status-update",reportHubId:o,recipientRawUserId:s,statusType:"read",value:f,clientTempId:b}),"setReadStatus"),I},Dt=async(n,s)=>{if(s===null)return;let o=await we(),[p]=await e.select({hubId:V.hubId}).top(1).from(V).where((0,a.and)((0,a.eq)(V.hubId,n),(0,a.inArray)(V.labelId,o)));return p?s:void 0},Gt=async(n,s,o,p,f,b)=>{let[g]=await e.select({sourceType:u.sourceType,deletedAt:u.deletedAt,userId:u.userId}).top(1).from(u).where((0,a.eq)(u.id,o));if(!g||g.deletedAt)throw new Error("Not Found");if(await Xe(n,o,s),!ye(n.commentable,g.sourceType))throw new Error("Comments are restricted by the viewer's comment permission");if(g.sourceType.toLowerCase()!=="internal")throw new Error("Comments are restricted for external daily report sources");let I=await Dt(o,g.userId),[x]=await e.insert(h).output().values({hubId:o,userId:s,body:p,createdAt:new Date,createdBy:String(s),updatedAt:new Date,updatedBy:String(s)}),[G]=await e.select({displayName:i.displayName}).top(1).from(i).where((0,a.eq)(i.id,s)),K=G?.displayName??"Unknown";if(f){let ie=le(f);ie&&(y.invalidatePrefix(`daily-report:date:${ie}:user:`),await T(`${C}${ie}`))}y.invalidate(`daily-report:detail:${o}`),y.invalidatePrefix(`daily-report:detail:${o}:user:`),await T(`${A}${o}`);let W={id:x.id,userId:c(x.userId),userName:K,content:x.body,createdAt:ne(x.createdAt,"YYYY-MM-DD HH:mm:ss")??"",isMine:!0};return await M(ot.parse({type:"comment-add",reportHubId:o,comment:W,clientTempId:b,recipientRawUserId:I,sourceType:g.sourceType}),"addComment"),W},Qt=async(n,s)=>await n.select().top(1).from(h).where((0,a.eq)(h.id,s)),Xt=async(n,s,o,p,f,b)=>{let g=await Qt(e,p);if(g.length===0)throw new Error("Not Found");if(g[0].hubId!==o)throw new Error("Not Found");let[I]=await e.select({userId:u.userId,sourceType:u.sourceType}).top(1).from(u).where((0,a.eq)(u.id,g[0].hubId));if(!(I&&ye(n.visible,I.sourceType)))throw new Error("Not Found");if(g[0].userId!==s)throw new Error("Unauthorized");let x=await Dt(o,I.userId);if(await e.delete(h).where((0,a.eq)(h.id,p)),f){let G=le(f);G&&(y.invalidatePrefix(`daily-report:date:${G}:user:`),await T(`${C}${G}`))}y.invalidate(`daily-report:detail:${o}`),y.invalidatePrefix(`daily-report:detail:${o}:user:`),await T(`${A}${o}`),await M(lt.parse({type:"comment-delete",reportHubId:o,commentId:p,clientTempId:b,recipientRawUserId:x,sourceType:I?.sourceType}),"deleteComment")},Wt=async(n,s,o)=>{te.info("createDailyReport called",{userId:n,businessDate:s});let[p]=await e.select({displayName:i.displayName}).from(i).where((0,a.eq)(i.id,n)),f=p?.displayName??c(n);try{let b=await e.transaction(async x=>{te.info("Starting transaction");let G=`internal-temp-${Date.now()}-${Math.random()}`,[K]=await x.insert(u).output().values({sourceType:"Internal",sourceId:G,businessDate:new Date(s),userId:n,title:"(\u7121\u984C)",createdAt:new Date,createdBy:String(n),updatedAt:new Date,updatedBy:String(n)});await x.update(u).set({sourceId:String(K.id)}).where((0,a.eq)(u.id,K.id)),te.info("Hub created",K),await x.insert(H).values({hubId:K.id,body:"",createdAt:new Date,createdBy:String(n),updatedAt:new Date,updatedBy:String(n)}),te.info("Internal created"),te.info("Calling getDraftLabelId");let W=await Qe();te.info("draftLabelId",W);let ie=[];return W&&(await x.insert(V).values({hubId:K.id,labelId:W,createdAt:new Date,createdBy:String(n)}),ie.push({id:W,name:Le,color:null})),te.info("Label assigned"),{reportHubId:K.id,date:s,createdAt:ne(K.createdAt,"YYYY-MM-DD HH:mm:ss"),author:f,userId:c(n),sourceType:"Internal",employeeName:f,updatedBy:c(n),updatedAt:ne(K.updatedAt,"YYYY-MM-DD HH:mm:ss"),category:null,creationCategory:null,visitTimeFrom:null,visitTimeTo:null,customerName:null,interviewers:[],subject:K.title,content:"",externalComments:[],isRead:!0,isStarred:!1,labels:ie,postedComments:[],attachments:[]}}),g=le(s);g&&y.invalidatePrefix(w(g,n)),y.invalidatePrefix(S),y.invalidatePrefix(k(n)),await T(Re),g&&await T(`${C}${g}`);let I=await Pe(ce.unrestricted("post-write self read: the writer always sees the row they just wrote"),b.reportHubId,n,{forceRefresh:!0});if(I){let x=await Ce(),G=I.labels.some(K=>x.includes(K.id));await M(ut.parse({type:"report-create",reportHubId:I.reportHubId,report:I,clientTempId:o,recipientRawUserId:G?n:void 0}),"createDailyReport")}return I??b}catch(b){throw te.error("Error in createDailyReport",b),b}},ze=async(n,s)=>await n.select().top(1).from(u).where((0,a.eq)(u.id,s)),We=async(n,s,o)=>{await n.update(u).set(o).where((0,a.eq)(u.id,s))},wt=async(n,s,o)=>{await n.update(H).set(o).where((0,a.eq)(H.hubId,s))},St=async(n,s,o)=>{await n.delete(V).where((0,a.and)((0,a.eq)(V.hubId,s),(0,a.eq)(V.labelId,o)))};return{streamKey:L,streamMaxLen:P,clearCache:async()=>{y.clearAll(),J.clear(),De=null,N&&await T(Re),te.info("[DailyReportService] Server-side DB/SQL caches cleared successfully.")},invalidateHubReadCaches:async(n,s)=>{y.invalidatePrefix(S),y.invalidatePrefix(Ie),await T(Re);for(let o of new Set(n))y.invalidatePrefix(`daily-report:detail:${o}:user:`),await T(`${A}${o}`);for(let o of new Set(s)){let p=le(o);p&&await T(`${C}${p}`)}},getUserIdByExternalId:j,getDailyReportIdsByExternalId:Ae,getDailyReportIdsFirstPageByExternalId:ee,getDailyReportsByBusinessDate:Te,getDailyReportsByBusinessDateByExternalId:zt,getDailyReportDetailById:Pe,getDailyReportDetailByIdByExternalId:Vt,getDraftLabelId:Qe,getAttachmentsByHubIds:qe,getAttachmentForUser:Yt,markAttachmentMissing:Ft,markAttachmentPresent:qt,setStarStatus:jt,setReadStatus:Jt,addComment:Gt,deleteComment:Xt,createDailyReport:Wt,updateDailyReport:async(n,s,o,p)=>{let f=await ze(e,n);if(!f.length||f[0].deletedAt)throw new Error("Not Found");if(f[0].userId!==s)throw new Error("Unauthorized");await e.transaction(async I=>{o.title!==void 0&&await We(I,n,{title:o.title,updatedAt:new Date,updatedBy:String(s)}),o.content!==void 0&&await wt(I,n,{body:o.content,updatedAt:new Date,updatedBy:String(s)})}),y.invalidate(`daily-report:detail:${n}`),y.invalidatePrefix(`daily-report:detail:${n}:user:`),y.invalidatePrefix(S),await T(`${A}${n}`);let b=le(ne(f[0].businessDate,"YYYY-MM-DD"));b&&(y.invalidatePrefix(`daily-report:date:${b}:user:`),await T(`${C}${b}`));let g=await Pe(ce.unrestricted("post-write self read: the writer always sees the row they just wrote"),n,s,{forceRefresh:!0});if(g){let I=await Ce(),x=g.labels.some(G=>I.includes(G.id));await M(dt.parse({type:"report-update",reportHubId:g.reportHubId,report:g,clientTempId:p,recipientRawUserId:x?s:void 0}),"updateDailyReport")}},publishDailyReport:async(n,s,o)=>{let p=await ze(e,n);if(!p.length)throw new Error("Not Found");if(p[0].userId!==s)throw new Error("Unauthorized");let f=await Qe();if(!f)return null;if(await St(e,n,f),y.invalidatePrefix(`daily-report:detail:${n}:user:`),y.invalidatePrefix(S),y.invalidatePrefix(Ie),await T(Re),p[0].businessDate){let I=le(ne(p[0].businessDate,"YYYY-MM-DD"));I&&await T(`${C}${I}`)}let b=le(ne(p[0].businessDate,"YYYY-MM-DD"));b&&y.invalidatePrefix(w(b,s));let g=await Pe(ce.unrestricted("post-write self read: the writer always sees the row they just wrote"),n,s,{forceRefresh:!0});return g&&await M(ct.parse({type:"report-publish",reportHubId:g.reportHubId,report:g,clientTempId:o}),"publishDailyReport"),g??null},deleteDailyReport:async(n,s,o)=>{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 We(e,n,{deletedAt:new Date,deletedBy:String(s),updatedAt:new Date,updatedBy:String(s)}),y.invalidatePrefix(`daily-report:detail:${n}:user:`),y.invalidatePrefix(S),y.invalidatePrefix(Ie),await T(Re),p[0].businessDate){let f=le(ne(p[0].businessDate,"YYYY-MM-DD"));f&&await T(`${C}${f}`)}await M(pt.parse({type:"report-delete",reportHubId:n,clientTempId:o,sourceType:p[0].sourceType}),"deleteDailyReport")},findDailyReportHubById:ze,updateDailyReportHub:We,updateDailyReportInternal:wt,deleteDailyReportLabel:St}}var Ye=require("drizzle-orm");function Ht(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 c=`daily_report_${i.key.toLowerCase().replace(/[^a-z0-9_]/g,"_")}`;e.push({resourceKey:c,name:i.name,description:i.description??`${i.name} daily report access`}),i.includeCommentResource!==!1&&e.push({resourceKey:`${c}_comment`,name:`${i.name} Comment`,description:`${i.name} daily report comment access`})}return e}async function Yr(t,e,r){let i=t,d=e.TMResource,c=r.appKey,R=r.actor??"system:daily-report",y=new Date,N=r.resources??Ht(r.sources);for(let u of N){let H=await i.select().from(d).where((0,Ye.and)((0,Ye.eq)(d.appKey,c),(0,Ye.eq)(d.resourceKey,u.resourceKey)));(!H||H.length===0)&&await i.insert(d).values({appKey:c,resourceKey:u.resourceKey,name:u.name,description:u.description??null,createdAt:y,createdBy:R,updatedAt:y,updatedBy:R})}}var Fr=ue(1,"[DailyReportExternalSource]"),qr=(t,e,r,i=Fr)=>{if(!t)return[];try{let d=JSON.parse(t);return Array.isArray(d)?d.map(r).filter(c=>c!==null):(i.warn(`Unexpected ${e} format: not an array`),[])}catch(d){return i.warn(`Failed to parse ${e}:`,d),[]}};var Fe=require("drizzle-orm"),l=require("drizzle-orm/mssql-core");function zr(t,e){let r=(0,l.mssqlSchema)(t),i=e.userTable,d=r.table("DailyReportHub",{id:(0,l.bigint)("id",{mode:"number"}).identity().notNull(),sourceType:(0,l.nvarchar)("source_type",{length:20}).notNull(),sourceId:(0,l.nvarchar)("source_id",{length:100}).notNull(),sourceIdNum:(0,l.bigint)("source_id_num",{mode:"number"}).generatedAlwaysAs(Fe.sql`TRY_CAST(source_id AS BIGINT)`),businessDate:(0,l.date)("business_date"),userId:(0,l.bigint)("user_id",{mode:"number"}),title:(0,l.nvarchar)("title",{length:200}),summary:(0,l.nvarchar)("summary",{length:"max"}),createdAt:(0,l.datetime2)("created_at").notNull(),createdBy:(0,l.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,l.datetime2)("updated_at").notNull(),updatedBy:(0,l.nvarchar)("updated_by",{length:50}).notNull(),deletedAt:(0,l.datetime2)("deleted_at"),deletedBy:(0,l.nvarchar)("deleted_by",{length:50})},h=>[(0,l.primaryKey)({name:`${t}_DailyReportHub_pk`,columns:[h.id]}),(0,l.foreignKey)({name:`${t}_DailyReportHub_user_id_fk`,columns:[h.userId],foreignColumns:[i.id]}),(0,l.index)(`${t}_DailyReportHub_business_date_index`).on(h.businessDate),(0,l.index)(`${t}_DailyReportHub_updated_at_index`).on(h.updatedAt),(0,l.index)(`${t}_DailyReportHub_source_index`).on(h.sourceType,h.sourceId),(0,l.index)(`${t}_DailyReportHub_user_id_index`).on(h.userId),(0,l.index)(`${t}_DailyReportHub_business_date_id_index`).on((0,Fe.desc)(h.businessDate),(0,Fe.desc)(h.id)),(0,l.index)(`${t}_DailyReportHub_deleted_at_index`).on(h.deletedAt)]),c=r.table("DailyReportInternal",{hubId:(0,l.bigint)("hub_id",{mode:"number"}).notNull(),body:(0,l.nvarchar)("body",{length:"max"}),metadata:(0,l.nvarchar)("metadata",{length:"max"}),createdAt:(0,l.datetime2)("created_at").notNull(),createdBy:(0,l.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,l.datetime2)("updated_at").notNull(),updatedBy:(0,l.nvarchar)("updated_by",{length:50}).notNull()},h=>[(0,l.primaryKey)({name:`${t}_DailyReportInternal_pk`,columns:[h.hubId]}),(0,l.foreignKey)({name:`${t}_DailyReportInternal_hub_id_fk`,columns:[h.hubId],foreignColumns:[d.id]})]),R=r.table("DailyReportComment",{id:(0,l.bigint)("id",{mode:"number"}).identity().notNull(),hubId:(0,l.bigint)("hub_id",{mode:"number"}).notNull(),userId:(0,l.bigint)("user_id",{mode:"number"}).notNull(),body:(0,l.nvarchar)("body",{length:"max"}).notNull(),createdAt:(0,l.datetime2)("created_at").notNull(),createdBy:(0,l.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,l.datetime2)("updated_at").notNull(),updatedBy:(0,l.nvarchar)("updated_by",{length:50}).notNull()},h=>[(0,l.primaryKey)({name:`${t}_DailyReportComment_pk`,columns:[h.id]}),(0,l.foreignKey)({name:`${t}_DailyReportComment_hub_id_fk`,columns:[h.hubId],foreignColumns:[d.id]}),(0,l.foreignKey)({name:`${t}_DailyReportComment_user_id_fk`,columns:[h.userId],foreignColumns:[i.id]}),(0,l.index)(`${t}_DailyReportComment_hub_id_index`).on(h.hubId)]),y=r.table("DailyReportLabel",{id:(0,l.bigint)("id",{mode:"number"}).identity().notNull(),userId:(0,l.bigint)("user_id",{mode:"number"}),name:(0,l.nvarchar)("name",{length:50}).notNull(),color:(0,l.nvarchar)("color",{length:20}),sortOrder:(0,l.int)("sort_order"),createdAt:(0,l.datetime2)("created_at").notNull(),createdBy:(0,l.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,l.datetime2)("updated_at").notNull(),updatedBy:(0,l.nvarchar)("updated_by",{length:50}).notNull()},h=>[(0,l.primaryKey)({name:`${t}_DailyReportLabel_pk`,columns:[h.id]}),(0,l.foreignKey)({name:`${t}_DailyReportLabel_user_id_fk`,columns:[h.userId],foreignColumns:[i.id]})]),N=r.table("DailyReportHub_Label",{hubId:(0,l.bigint)("hub_id",{mode:"number"}).notNull(),labelId:(0,l.bigint)("label_id",{mode:"number"}).notNull(),createdAt:(0,l.datetime2)("created_at").notNull(),createdBy:(0,l.nvarchar)("created_by",{length:50}).notNull()},h=>[(0,l.primaryKey)({name:`${t}_DailyReportHub_Label_pk`,columns:[h.hubId,h.labelId]}),(0,l.foreignKey)({name:`${t}_DailyReportHub_Label_hub_id_fk`,columns:[h.hubId],foreignColumns:[d.id]}),(0,l.foreignKey)({name:`${t}_DailyReportHub_Label_label_id_fk`,columns:[h.labelId],foreignColumns:[y.id]})]),u=r.table("DailyReportUserStatus",{hubId:(0,l.bigint)("hub_id",{mode:"number"}).notNull(),userId:(0,l.bigint)("user_id",{mode:"number"}).notNull(),isRead:(0,l.bit)("is_read").default(!1).notNull(),isStarred:(0,l.bit)("is_starred").default(!1).notNull(),createdAt:(0,l.datetime2)("created_at").notNull(),createdBy:(0,l.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,l.datetime2)("updated_at").notNull(),updatedBy:(0,l.nvarchar)("updated_by",{length:50}).notNull()},h=>[(0,l.primaryKey)({name:`${t}_DailyReportUserStatus_pk`,columns:[h.hubId,h.userId]}),(0,l.foreignKey)({name:`${t}_DailyReportUserStatus_hub_id_fk`,columns:[h.hubId],foreignColumns:[d.id]}),(0,l.foreignKey)({name:`${t}_DailyReportUserStatus_user_id_fk`,columns:[h.userId],foreignColumns:[i.id]})]),H=r.table("DailyReportAttachment",{id:(0,l.bigint)("id",{mode:"number"}).identity().notNull(),hubId:(0,l.bigint)("hub_id",{mode:"number"}).notNull(),uploadedBy:(0,l.bigint)("uploaded_by",{mode:"number"}),sourceKey:(0,l.nvarchar)("source_key",{length:200}).notNull(),fileName:(0,l.nvarchar)("file_name",{length:255}).notNull(),filePath:(0,l.nvarchar)("file_path",{length:"max"}).notNull(),fileType:(0,l.nvarchar)("file_type",{length:100}),fileSize:(0,l.bigint)("file_size",{mode:"number"}),objectCheckedAt:(0,l.datetime2)("object_checked_at"),objectMissingAt:(0,l.datetime2)("object_missing_at"),createdAt:(0,l.datetime2)("created_at").notNull(),createdBy:(0,l.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,l.datetime2)("updated_at").notNull(),updatedBy:(0,l.nvarchar)("updated_by",{length:50}).notNull()},h=>[(0,l.primaryKey)({name:`${t}_DailyReportAttachment_pk`,columns:[h.id]}),(0,l.foreignKey)({name:`${t}_DailyReportAttachment_hub_id_fk`,columns:[h.hubId],foreignColumns:[d.id]}),(0,l.foreignKey)({name:`${t}_DailyReportAttachment_uploaded_by_fk`,columns:[h.uploadedBy],foreignColumns:[i.id]}),(0,l.uniqueIndex)(`${t}_DailyReportAttachment_source_unique`).on(h.hubId,h.sourceKey),(0,l.index)(`${t}_DailyReportAttachment_hub_id_index`).on(h.hubId,h.createdAt)]);return{hub:d,internal:c,comment:R,attachment:H,label:y,hubLabel:N,userStatus:u}}function Vr(t){t.redis||(t.logger??console).warn("[DailyReport] redis provider is not injected: cross-worker cache invalidation is disabled (staleness is bounded only by TTL) and SSE publishing is skipped.");let e=nt(t.redis),r=new Be({defaultTtlMs:t.cacheDefaultTtlMs??6e4},e),i=gt({...t,cache:r,epochs:e}),d=new Ue({redis:t.redis,streamKey:i.streamKey,cache:r,logger:t.logger}),c=bt({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:d,streamKey:i.streamKey,loginRedirectPath:t.loginRedirectPath,enableDevCacheClear:t.enableDevCacheClear,logger:t.logger});return{service:i,cache:r,epochs:e,sseReader:d,streamKey:i.streamKey,knownSourceTypes:[...new Set(["Internal",...(t.externalSources??[]).map(R=>R.sourceType)])],...c}}0&&(module.exports={DailyReportSseReader,DailyReportViewerScope,SqlResultCache,asciiFallbackFileName,buildVisibleSourceTypeCondition,computeSourceTypeDigest,computeViewerScopeDigest,createDailyReportHandlers,createDailyReportServer,createDailyReportService,createEpochStore,defineDailyReportAuthzResources,defineDailyReportSchema,deniesEverySourceType,encodeRfc8187,formatDateValue,generateETag,isSourceTypeVisible,isStreamIdLte,jsonResponseWithETag,normalizeVisibleSourceTypes,sanitizeMediaType,seedDailyReportAuthzResources,transformJsonArray});
|
|
14
|
+
`,X=ee!=="0-0"?`id: ${ee}
|
|
15
|
+
${x}`:x;N.enqueue(B.encode(X))}if(M)try{let x=await d?.getClient();if(x){let X=await x.xRange(w,M,"+",{COUNT:1e3});for(let ue of X)ue.id!==M&&(J!==null&&ve(J,ue.id)||(ve(ue.id,ee)||(ee=ue.id),fe(ue.id,ue.message)))}}catch(x){H.error(`[SSE:${L}] catch-up xRange error:`,x)}},cancel(){U()}});return new Response(le,{headers:b({"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive"})})}},attachment:{loader:async({request:I,params:z})=>{let T=null,C=(b,L,Y)=>{let R=new Headers({"Content-Type":"application/json"});return Y!==void 0&&R.set("Retry-After",String(Y)),T&&R.append("Set-Cookie",T),new Response(JSON.stringify({error:{message:L}}),{status:b,headers:R})};try{let{user:b,cookie:L}=await e(I,{failureRedirect:null});if(T=L??null,!b)return C(401,"Unauthorized");if(I.method!=="GET"&&I.method!=="HEAD")return C(405,"Method not allowed");let Y=t.attachmentIdCodec,R=t.readAttachment;if(!(Y&&R))return C(404,"Attachment not found");let P=z.token??"",E=Y.decode(P);if(E===null||!Number.isSafeInteger(E)||E<=0)return C(400,"Invalid attachment token");let F=await r.getUserIdByExternalId(b.id);if(!F)return C(403,"Forbidden");if(!K(F,Date.now()))return h.error(`429 attachment=${E} viewer=${F} reason=rate_limit`),C(429,"Too many requests",vr);let ce=await ye(I),M=await r.getAttachmentForUser(ce,E,F);if(!M)return h.error(`404 attachment=${E} viewer=${F} reason=not_visible`),C(404,"Attachment not found");if(M.fileSize!=null&&M.fileSize>V)return h.error(`413 attachment=${E} viewer=${F} reason=db_size`),C(413,"Attachment too large");if(!O.tryAcquire())return h.error(`503 attachment=${E} viewer=${F} reason=concurrency`),C(503,"Too many concurrent downloads",xr);let B=!1,N=()=>{B||(B=!0,O.release())},v=!1;try{let q=I.method==="HEAD",S=await R(M.filePath,{maxBytes:V,head:q,principal:s(F)});if(!S.ok){let x=Nr(S.reason);return S.reason==="not_found"&&r.markAttachmentMissing(E).catch(X=>{h.error(`markAttachmentMissing failed attachment=${E} message=${X instanceof Error?X.message:"unknown"}`)}),h.error(`${x} attachment=${E} viewer=${F} reason=${S.reason} code=${S.code??"-"}`),C(x,Lr[x]??"Attachment storage unavailable")}let U=ht(M.fileType)??ht(S.contentType)??"application/octet-stream",Z=kr.has(U),fe=new URL(I.url).searchParams.get("download")==="1",le=Z?U:"application/octet-stream",ne=Z&&!fe?"inline":"attachment",ee=S.size??S.bytes.byteLength,J=new Headers({"Content-Type":le,"Content-Length":String(ee),"Content-Disposition":`${ne}; filename="${Bt(M.fileName)}"; filename*=UTF-8''${$t(M.fileName)}`,"Cache-Control":"private, no-store","X-Content-Type-Options":"nosniff","Content-Security-Policy":"default-src 'none'; sandbox","X-Frame-Options":"SAMEORIGIN"});return T&&J.append("Set-Cookie",T),r.markAttachmentPresent(E).catch(x=>{h.error(`markAttachmentPresent failed attachment=${E} message=${x instanceof Error?x.message:"unknown"}`)}),h.info(`200 attachment=${E} viewer=${F} type=${le} disposition=${ne} bytes=${ee}`),q?new Response(null,{status:200,headers:J}):(v=!0,new Response(Br(S.bytes,N,Cr),{status:200,headers:J}))}finally{v||N()}}catch(b){if(b instanceof Response)throw b;return h.error(`500 attachment=? viewer=? reason=unexpected message=${b instanceof Error?b.message:"unknown"}`),C(500,"Attachment request failed")}}}}}var a=require("drizzle-orm");var Ae=t=>(0,a.getColumns)(t),re=(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 s=r.getFullYear(),d=s<0?`-${String(-s).padStart(4,"0")}`:String(s).padStart(4,"0"),c=String(r.getMonth()+1).padStart(2,"0"),w=String(r.getDate()).padStart(2,"0");if(e==="YYYY-MM-DD")return`${d}-${c}-${w}`;let y=String(r.getHours()).padStart(2,"0"),k=String(r.getMinutes()).padStart(2,"0"),u=String(r.getSeconds()).padStart(2,"0");return`${d}-${c}-${w} ${y}:${k}:${u}`};function bt(t){let{db:e,tables:r,userTable:s,resolveUserId:d,encodeUserId:c,redis:w,cache:y,epochs:k}=t,{hub:u,internal:H,comment:h,label:V,hubLabel:K,userStatus:O}=r,ye=t.externalSources??[],Me=t.draftLabelNames&&t.draftLabelNames.length>0?t.draftLabelNames:[t.draftLabelName??"\u4E0B\u66F8\u304D"],Ne=Me[0]??"\u4E0B\u66F8\u304D",te=t.logger??de(1,"[DailyReportService]"),Te="daily-report:ids",gt=t.idsTtlMs??18e4,Ie="daily-report:ids:epoch",I="daily-report:business-date:",z=t.businessDateTtlMs??3e5,T="daily-report:date-epoch:",C="daily-report:detail-epoch:",L=`${t.streamKey??"daily-report:sse-stream"}:v2`,Y=t.streamMaxLen??1e4,R=n=>k.incrementEpoch(n),P=n=>yt(u.sourceType,n),E=(n,o)=>`${Te}:user:${n}:st:${o}`,F=n=>`${Te}:user:${n}:`,ce=(n,o,i)=>`daily-report:date:${n}:user:${o}:st:${i}`,M=(n,o)=>`daily-report:date:${n}:user:${o}:`,B=(n,o,i)=>`daily-report:detail:${n}:user:${o}:st:${i}`,N=(n,o)=>`daily-report:detail:${n}:user:${o}:`,v=async(n,o)=>{let i=await w?.getClient();if(!i){te.warn(`[SSE] Redis client unavailable (${o})`);return}let p=Date.now();try{await i.xAdd(L,"*",{data:JSON.stringify(n)},{TRIM:{strategy:"MAXLEN",strategyModifier:"~",threshold:Y}});let f=Date.now()-p;f>1e3&&te.warn(`[SSE] Slow publish (${o}): ${f}ms`)}catch(f){te.error(`[SSE] Redis publish failed (${o}):`,f)}},q=n=>n==null||n===""?null:/^\d+$/.test(n)?c(Number(n)):n,S=()=>{let n={};for(let o of ye)n[`ext_${o.sourceType}`]=Ae(o.table);return n},U=n=>{let o=n;for(let i of ye)o=o.leftJoin(i.table,(0,a.and)((0,a.eq)(u.sourceType,i.sourceType),(0,a.eq)(u.sourceIdNum,i.idColumn)));return o},Z=(n,o,i)=>{let{hub:p,internal:f}=o,g=p.summary,D=[],A=null,_=null,G=null,j=null,W=null,ae=null,Ce=[],we=ye.find($=>$.sourceType===p.sourceType),_e=we?o[`ext_${we.sourceType}`]:void 0;if(we&&_e){let $=we.mapRow(_e);$.content!==void 0&&(g=$.content),$.employeeName!==void 0&&(ae=$.employeeName),$.category!==void 0&&(A=$.category),$.creationCategory!==void 0&&(_=$.creationCategory),$.visitTimeFrom!==void 0&&(G=$.visitTimeFrom),$.visitTimeTo!==void 0&&(j=$.visitTimeTo),$.customerName!==void 0&&(W=$.customerName),$.interviewers!==void 0&&(D=$.interviewers),$.externalComments!==void 0&&(Ce=$.externalComments)}else p.sourceType==="Internal"&&f&&(g=f.body);let ge=(o.labels??[]).map($=>({id:$.id,name:$.name,color:$.color})),se=o.postedCommentRows??[],Q=he(n.commentable,p.sourceType),oe=_?Me.includes(_):!1,We=Re?.[0]??null;return oe&&We&&!ge.some($=>$.id===We)&&ge.push({id:We,name:Ne,color:null}),{reportHubId:p.id,date:re(p.businessDate,"YYYY-MM-DD"),author:o.creatorName??q(p.createdBy)??"",userId:p.userId?c(p.userId):"",sourceType:p.sourceType??"Internal",createdAt:re(p.createdAt,"YYYY-MM-DD HH:mm:ss"),updatedAt:re(p.updatedAt,"YYYY-MM-DD HH:mm:ss"),updatedBy:q(p.updatedBy),employeeName:ae??o.creatorName??q(p.createdBy),category:A,creationCategory:_,visitTimeFrom:G,visitTimeTo:j,customerName:W,interviewers:D,subject:p.title,content:g,externalComments:Q?Ce:[],isRead:o.isRead??!1,isStarred:o.isStarred??!1,labels:ge,postedComments:se.filter($=>Q||i!==void 0&&$.userId===i).map($=>({...$,userId:c($.userId),isMine:i?$.userId===i:!1})),attachments:o.attachments}},fe=async(n,o)=>{let i=(0,a.aliasedTable)(K,"draft_label"),p=await De();return(await e.select({reportHubId:u.id,businessDate:u.businessDate,sourceType:u.sourceType}).from(u).leftJoin(i,(0,a.and)((0,a.eq)(i.hubId,u.id),(0,a.inArray)(i.labelId,p))).where((0,a.and)((0,a.isNull)(u.deletedAt),(0,a.or)((0,a.eq)(u.userId,o),(0,a.isNull)(u.userId),(0,a.isNull)(i.hubId)),P(n.visible))).orderBy((0,a.desc)(u.businessDate),(0,a.desc)(u.id))).map(g=>({...g,businessDate:re(g.businessDate,"YYYY-MM-DD")}))},le=async(n,o,i)=>{let p=await x(o);if(!p)return[];if(Se(n.visible))return[];let f=(0,a.aliasedTable)(K,"draft_label"),g=await De();return(await e.select({reportHubId:u.id,businessDate:u.businessDate,sourceType:u.sourceType}).top(i).from(u).leftJoin(f,(0,a.and)((0,a.eq)(f.hubId,u.id),(0,a.inArray)(f.labelId,g))).where((0,a.and)((0,a.isNull)(u.deletedAt),(0,a.or)((0,a.eq)(u.userId,p),(0,a.isNull)(u.userId),(0,a.isNull)(f.hubId)),P(n.visible))).orderBy((0,a.desc)(u.businessDate),(0,a.desc)(u.id))).map(A=>({...A,businessDate:re(A.businessDate,"YYYY-MM-DD")}))},ne=async(n,o)=>{let i=await U(e.select({hub:Ae(u),internal:Ae(H),creatorName:s.displayName,...S()}).from(u)).leftJoin(H,(0,a.eq)(u.id,H.hubId)).leftJoin(s,(0,a.eq)(u.userId,s.id)).where((0,a.and)((0,a.eq)(u.businessDate,a.sql`${o}`),(0,a.isNull)(u.deletedAt),P(n.visible))).orderBy((0,a.desc)(u.id)),p=await qe(i.map(f=>f.hub.id));return i.map(f=>Z(n,{...f,attachments:p.get(f.hub.id)??[]}))},ee=n=>`${I}${n}`,J=new Map,x=async n=>{if(!t.disableUserIdCache&&J.has(n))return J.get(n)??null;let o=await d(n);return o!==null&&!t.disableUserIdCache&&J.set(n,o),o},X=async(n,o,{forceRefresh:i=!1,snapshot:p=!1,ttlMsOverride:f,onFetchStart:g}={})=>{let D=await x(o);if(!D)return[];if(Se(n.visible))return[];let A=E(D,Ee(n));return y.getOrFetch({cacheKey:A,fetcher:async()=>{let _=await fe(n,D);return Ct(_)?_:(te.warn("[DailyReportService] ids array is not in stream order; re-sorting (check SQL ORDER BY vs compareIdsStreamOrder, or concurrent row movement during the scan)"),[..._].sort(Ve))},onFetchStart:g,forceRefresh:i,snapshot:p,ttlMsOverride:f??gt,epochKey:Ie,refreshAheadRatio:.5})},ue=(n,o,{forceRefresh:i=!1,snapshot:p=!1,ttlMsOverride:f}={})=>{let g=ie(o);return g?Se(n.visible)?Promise.resolve([]):y.getOrFetch({cacheKey:`${ee(g)}:st:${Ee(n)}`,fetcher:()=>ne(n,g),forceRefresh:i,snapshot:p,ttlMsOverride:f??z}):Promise.resolve([])},Re=null,be=async()=>(Re!==null||(Re=(await e.select({id:V.id}).from(V).where((0,a.inArray)(V.name,Me)).orderBy(V.id)).map(o=>o.id)),Re),De=async()=>{let n=await be();return n.length>0?n:[-1]},Le=async()=>{let n=await be();if(n.length===0)return null;let[o]=await e.select({id:V.id}).top(1).from(V).where((0,a.eq)(V.name,Ne));return o?.id??n[0]},Ht=(n,o)=>o!=null?"absent":n!=null?"present":"unknown",qe=async n=>{let o=new Map,i=r.attachment,p=t.attachmentIdCodec;if(n.length===0||!i||!p)return o;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((0,a.inArray)(i.hubId,n)).orderBy((0,a.asc)(i.createdAt),(0,a.asc)(i.id));for(let g of f){let D={id:p.encode(Number(g.id)),fileName:String(g.fileName),fileType:g.fileType?String(g.fileType):null,fileSize:g.fileSize!=null?Number(g.fileSize):null,createdAt:re(g.createdAt,"YYYY-MM-DD HH:mm:ss"),state:Ht(g.objectCheckedAt,g.objectMissingAt)},A=o.get(Number(g.hubId));A?A.push(D):o.set(Number(g.hubId),[D])}return o},Ot=async(n,o,i)=>{let p=r.attachment;if(!p||Se(n.visible))return null;let f=await De(),g=(0,a.aliasedTable)(K,"draft_label");return(await e.select({fileName:p.fileName,filePath:p.filePath,fileType:p.fileType,fileSize:p.fileSize}).top(1).from(p).innerJoin(u,(0,a.eq)(u.id,p.hubId)).leftJoin(g,(0,a.and)((0,a.eq)(g.hubId,u.id),(0,a.inArray)(g.labelId,f))).where((0,a.and)((0,a.eq)(p.id,o),(0,a.isNull)(u.deletedAt),(0,a.or)((0,a.eq)(u.userId,i),(0,a.isNull)(g.hubId)),P(n.visible))))[0]??null},Yt=async n=>{let o=r.attachment;if(!o)return;let i=new Date;try{await e.update(o).set({objectCheckedAt:i,objectMissingAt:i,updatedAt:i}).where((0,a.eq)(o.id,n))}catch(p){te.error("markAttachmentMissing failed",p)}},Ft=async n=>{let o=r.attachment;if(!o)return;let i=new Date;try{await e.update(o).set({objectCheckedAt:i,objectMissingAt:null,updatedAt:i}).where((0,a.eq)(o.id,n))}catch(p){te.error("markAttachmentPresent failed",p)}},qt=async(n,o,i,{forceRefresh:p=!1,snapshot:f=!1,ttlMsOverride:g}={})=>{let D=await x(i);if(!D)return[];let A=ie(o);if(!A)return[];if(Se(n.visible))return[];let _=ce(A,D,Ee(n));return y.getOrFetch({cacheKey:_,fetcher:async()=>{let G=await De(),j=(0,a.aliasedTable)(K,"draft_label"),W=await U(e.select({hub:Ae(u),internal:Ae(H),isRead:O.isRead,isStarred:O.isStarred,creatorName:s.displayName,...S()}).from(u)).leftJoin(H,(0,a.eq)(u.id,H.hubId)).leftJoin(O,(0,a.and)((0,a.eq)(u.id,O.hubId),(0,a.eq)(O.userId,D))).leftJoin(j,(0,a.and)((0,a.eq)(j.hubId,u.id),(0,a.inArray)(j.labelId,G))).leftJoin(s,(0,a.eq)(u.userId,s.id)).where((0,a.and)((0,a.eq)(u.businessDate,a.sql`${A}`),(0,a.isNull)(u.deletedAt),(0,a.or)((0,a.eq)(u.userId,D),(0,a.isNull)(j.hubId)),P(n.visible))).orderBy((0,a.desc)(u.id));if(W.length===0)return[];let ae=W.map(Q=>Q.hub.id),Ce=await e.select({hubId:K.hubId,id:V.id,name:V.name,color:V.color}).from(K).innerJoin(V,(0,a.eq)(K.labelId,V.id)).where((0,a.inArray)(K.hubId,ae)),we=await e.select({hubId:h.hubId,id:h.id,body:h.body,createdAt:h.createdAt,userId:h.userId,userName:s.displayName}).from(h).leftJoin(s,(0,a.eq)(h.userId,s.id)).where((0,a.inArray)(h.hubId,ae)).orderBy((0,a.asc)(h.createdAt)),_e=await qe(ae),ge=new Map,se=new Map;for(let Q of Ce){let oe=ge.get(Q.hubId);oe||(oe=[],ge.set(Q.hubId,oe)),oe.push({id:Q.id,name:Q.name,color:Q.color})}for(let Q of we){let oe=se.get(Q.hubId);oe||(oe=[],se.set(Q.hubId,oe)),oe.push({id:Q.id,content:Q.body,createdAt:re(Q.createdAt,"YYYY-MM-DD HH:mm:ss")||"",userId:Q.userId,userName:Q.userName||""})}return W.map(Q=>{let oe=Q.hub.id;return Z(n,{...Q,attachments:_e.get(oe)??[],labels:ge.get(oe)||[],postedCommentRows:se.get(oe)||[]},D)})},forceRefresh:p,snapshot:f,ttlMsOverride:g??z,epochKey:`${T}${A}`})},Pe=async(n,o,i,{forceRefresh:p=!1,snapshot:f=!1,ttlMsOverride:g}={})=>{if(Se(n.visible))return null;let D=B(o,i,Ee(n));return(await y.getOrFetch({cacheKey:D,fetcher:async()=>{let _=await De(),G=(0,a.aliasedTable)(K,"draft_label"),j=await U(e.select({hub:Ae(u),internal:Ae(H),isRead:O.isRead,isStarred:O.isStarred,creatorName:s.displayName,...S()}).from(u)).leftJoin(H,(0,a.eq)(u.id,H.hubId)).leftJoin(O,(0,a.and)((0,a.eq)(u.id,O.hubId),(0,a.eq)(O.userId,i))).leftJoin(G,(0,a.and)((0,a.eq)(G.hubId,u.id),(0,a.inArray)(G.labelId,_))).leftJoin(s,(0,a.eq)(u.userId,s.id)).where((0,a.and)((0,a.eq)(u.id,o),(0,a.isNull)(u.deletedAt),(0,a.or)((0,a.eq)(u.userId,i),(0,a.isNull)(G.hubId)),P(n.visible)));if(j.length===0)return[];let W=j[0].hub.id,ae=await e.select({id:V.id,name:V.name,color:V.color}).from(K).innerJoin(V,(0,a.eq)(K.labelId,V.id)).where((0,a.eq)(K.hubId,W)),Ce=await e.select({id:h.id,body:h.body,createdAt:h.createdAt,userId:h.userId,userName:s.displayName}).from(h).leftJoin(s,(0,a.eq)(h.userId,s.id)).where((0,a.eq)(h.hubId,W)).orderBy((0,a.asc)(h.createdAt)),we=await qe([W]),_e=ae.map(se=>({id:se.id,name:se.name,color:se.color})),ge=Ce.map(se=>({id:se.id,content:se.body,createdAt:re(se.createdAt,"YYYY-MM-DD HH:mm:ss")||"",userId:se.userId,userName:se.userName||""}));return[Z(n,{...j[0],attachments:we.get(W)??[],labels:_e,postedCommentRows:ge},i)]},forceRefresh:p,snapshot:f,ttlMsOverride:g??z,epochKey:`${C}${o}`}))[0]??null},zt=async(n,o,i,p={})=>{let f=await x(i);return f?Pe(n,o,f,p):null},Vt=async(n,o)=>{let i=await De(),p=(0,a.aliasedTable)(K,"draft_label"),[f]=await e.select({sourceType:u.sourceType,deletedAt:u.deletedAt}).top(1).from(u).leftJoin(p,(0,a.and)((0,a.eq)(p.hubId,u.id),(0,a.inArray)(p.labelId,i))).where((0,a.and)((0,a.eq)(u.id,n),(0,a.or)((0,a.eq)(u.userId,o),(0,a.isNull)(p.hubId))));return f??null},Qe=async(n,o,i)=>{let p=await Vt(o,i);if(!p||p.deletedAt||!he(n.visible,p.sourceType))throw new Error("Not Found")},Kt=async(n,o,i,p,f,g)=>{await Qe(n,i,o);let D=await e.select().top(1).from(O).where((0,a.and)((0,a.eq)(O.hubId,i),(0,a.eq)(O.userId,o))),A;if(D.length>0?D[0].isStarred!==f?A=(await e.update(O).set({isStarred:f,updatedAt:new Date,updatedBy:String(o)}).output().where((0,a.and)((0,a.eq)(O.hubId,i),(0,a.eq)(O.userId,o))))[0]:A=D[0]:A=(await e.insert(O).output().values({hubId:i,userId:o,isStarred:f,isRead:!1,createdAt:new Date,createdBy:String(o),updatedAt:new Date,updatedBy:String(o)}))[0],p){let _=ie(p);_&&(y.invalidatePrefix(M(_,o)),await R(`${T}${_}`))}return y.invalidate(`daily-report:detail:${i}`),y.invalidatePrefix(N(i,o)),await R(`${C}${i}`),await v(Ke.parse({type:"status-update",reportHubId:i,recipientRawUserId:o,statusType:"star",value:f,clientTempId:g}),"setStarStatus"),A},jt=async(n,o,i,p,f,g)=>{await Qe(n,i,o);let D=await e.select().top(1).from(O).where((0,a.and)((0,a.eq)(O.hubId,i),(0,a.eq)(O.userId,o))),A;if(D.length>0?D[0].isRead!==f?A=(await e.update(O).set({isRead:f,updatedAt:new Date,updatedBy:String(o)}).output().where((0,a.and)((0,a.eq)(O.hubId,i),(0,a.eq)(O.userId,o))))[0]:A=D[0]:A=(await e.insert(O).output().values({hubId:i,userId:o,isRead:f,isStarred:!1,createdAt:new Date,createdBy:String(o),updatedAt:new Date,updatedBy:String(o)}))[0],p){let _=ie(p);_&&(y.invalidatePrefix(M(_,o)),await R(`${T}${_}`))}return y.invalidate(`daily-report:detail:${i}`),y.invalidatePrefix(N(i,o)),await R(`${C}${i}`),await v(Ke.parse({type:"status-update",reportHubId:i,recipientRawUserId:o,statusType:"read",value:f,clientTempId:g}),"setReadStatus"),A},Rt=async(n,o)=>{if(o===null)return;let i=await De(),[p]=await e.select({hubId:K.hubId}).top(1).from(K).where((0,a.and)((0,a.eq)(K.hubId,n),(0,a.inArray)(K.labelId,i)));return p?o:void 0},Jt=async(n,o,i,p,f,g)=>{let[D]=await e.select({sourceType:u.sourceType,deletedAt:u.deletedAt,userId:u.userId}).top(1).from(u).where((0,a.eq)(u.id,i));if(!D||D.deletedAt)throw new Error("Not Found");if(await Qe(n,i,o),!he(n.commentable,D.sourceType))throw new Error("Comments are restricted by the viewer's comment permission");if(D.sourceType.toLowerCase()!=="internal")throw new Error("Comments are restricted for external daily report sources");let A=await Rt(i,D.userId),[_]=await e.insert(h).output().values({hubId:i,userId:o,body:p,createdAt:new Date,createdBy:String(o),updatedAt:new Date,updatedBy:String(o)}),[G]=await e.select({displayName:s.displayName}).top(1).from(s).where((0,a.eq)(s.id,o)),j=G?.displayName??"Unknown";if(f){let ae=ie(f);ae&&(y.invalidatePrefix(`daily-report:date:${ae}:user:`),await R(`${T}${ae}`))}y.invalidate(`daily-report:detail:${i}`),y.invalidatePrefix(`daily-report:detail:${i}:user:`),await R(`${C}${i}`);let W={id:_.id,userId:c(_.userId),userName:j,content:_.body,createdAt:re(_.createdAt,"YYYY-MM-DD HH:mm:ss")??"",isMine:!0};return await v(ot.parse({type:"comment-add",reportHubId:i,comment:W,clientTempId:g,recipientRawUserId:A,sourceType:D.sourceType}),"addComment"),W},Gt=async(n,o)=>await n.select().top(1).from(h).where((0,a.eq)(h.id,o)),Qt=async(n,o,i,p,f,g)=>{let D=await Gt(e,p);if(D.length===0)throw new Error("Not Found");if(D[0].hubId!==i)throw new Error("Not Found");let[A]=await e.select({userId:u.userId,sourceType:u.sourceType}).top(1).from(u).where((0,a.eq)(u.id,D[0].hubId));if(!(A&&he(n.visible,A.sourceType)))throw new Error("Not Found");if(D[0].userId!==o)throw new Error("Unauthorized");let _=await Rt(i,A.userId);if(await e.delete(h).where((0,a.eq)(h.id,p)),f){let G=ie(f);G&&(y.invalidatePrefix(`daily-report:date:${G}:user:`),await R(`${T}${G}`))}y.invalidate(`daily-report:detail:${i}`),y.invalidatePrefix(`daily-report:detail:${i}:user:`),await R(`${C}${i}`),await v(it.parse({type:"comment-delete",reportHubId:i,commentId:p,clientTempId:g,recipientRawUserId:_,sourceType:A?.sourceType}),"deleteComment")},Xt=async(n,o,i)=>{te.info("createDailyReport called",{userId:n,businessDate:o});let[p]=await e.select({displayName:s.displayName}).from(s).where((0,a.eq)(s.id,n)),f=p?.displayName??c(n);try{let g=await e.transaction(async _=>{te.info("Starting transaction");let G=`internal-temp-${Date.now()}-${Math.random()}`,[j]=await _.insert(u).output().values({sourceType:"Internal",sourceId:G,businessDate:new Date(o),userId:n,title:"(\u7121\u984C)",createdAt:new Date,createdBy:String(n),updatedAt:new Date,updatedBy:String(n)});await _.update(u).set({sourceId:String(j.id)}).where((0,a.eq)(u.id,j.id)),te.info("Hub created",j),await _.insert(H).values({hubId:j.id,body:"",createdAt:new Date,createdBy:String(n),updatedAt:new Date,updatedBy:String(n)}),te.info("Internal created"),te.info("Calling getDraftLabelId");let W=await Le();te.info("draftLabelId",W);let ae=[];return W&&(await _.insert(K).values({hubId:j.id,labelId:W,createdAt:new Date,createdBy:String(n)}),ae.push({id:W,name:Ne,color:null})),te.info("Label assigned"),{reportHubId:j.id,date:o,createdAt:re(j.createdAt,"YYYY-MM-DD HH:mm:ss"),author:f,userId:c(n),sourceType:"Internal",employeeName:f,updatedBy:c(n),updatedAt:re(j.updatedAt,"YYYY-MM-DD HH:mm:ss"),category:null,creationCategory:null,visitTimeFrom:null,visitTimeTo:null,customerName:null,interviewers:[],subject:j.title,content:"",externalComments:[],isRead:!0,isStarred:!1,labels:ae,postedComments:[],attachments:[]}}),D=ie(o);D&&y.invalidatePrefix(M(D,n)),y.invalidatePrefix(I),y.invalidatePrefix(F(n)),await R(Ie),D&&await R(`${T}${D}`);let A=await Pe(me.unrestricted("post-write self read: the writer always sees the row they just wrote"),g.reportHubId,n,{forceRefresh:!0});if(A){let _=await be(),G=A.labels.some(j=>_.includes(j.id));await v(lt.parse({type:"report-create",reportHubId:A.reportHubId,report:A,clientTempId:i,recipientRawUserId:G?n:void 0}),"createDailyReport")}return A??g}catch(g){throw te.error("Error in createDailyReport",g),g}},ze=async(n,o)=>await n.select().top(1).from(u).where((0,a.eq)(u.id,o)),Xe=async(n,o,i)=>{await n.update(u).set(i).where((0,a.eq)(u.id,o))},Dt=async(n,o,i)=>{await n.update(H).set(i).where((0,a.eq)(H.hubId,o))},wt=async(n,o,i)=>{await n.delete(K).where((0,a.and)((0,a.eq)(K.hubId,o),(0,a.eq)(K.labelId,i)))};return{streamKey:L,streamMaxLen:Y,clearCache:async()=>{y.clearAll(),J.clear(),Re=null,k&&await R(Ie),te.info("[DailyReportService] Server-side DB/SQL caches cleared successfully.")},invalidateHubReadCaches:async(n,o)=>{y.invalidatePrefix(I),y.invalidatePrefix(Te),await R(Ie);for(let i of new Set(n))y.invalidatePrefix(`daily-report:detail:${i}:user:`),await R(`${C}${i}`);for(let i of new Set(o)){let p=ie(i);p&&await R(`${T}${p}`)}},getUserIdByExternalId:x,getDailyReportIdsByExternalId:X,getDailyReportIdsFirstPageByExternalId:le,getDailyReportsByBusinessDate:ue,getDailyReportsByBusinessDateByExternalId:qt,getDailyReportDetailById:Pe,getDailyReportDetailByIdByExternalId:zt,getDraftLabelId:Le,getAttachmentsByHubIds:qe,getAttachmentForUser:Ot,markAttachmentMissing:Yt,markAttachmentPresent:Ft,setStarStatus:Kt,setReadStatus:jt,addComment:Jt,deleteComment:Qt,createDailyReport:Xt,updateDailyReport:async(n,o,i,p)=>{let f=await ze(e,n);if(!f.length||f[0].deletedAt)throw new Error("Not Found");if(f[0].userId!==o)throw new Error("Unauthorized");await e.transaction(async A=>{i.title!==void 0&&await Xe(A,n,{title:i.title,updatedAt:new Date,updatedBy:String(o)}),i.content!==void 0&&await Dt(A,n,{body:i.content,updatedAt:new Date,updatedBy:String(o)})}),y.invalidate(`daily-report:detail:${n}`),y.invalidatePrefix(`daily-report:detail:${n}:user:`),y.invalidatePrefix(I),await R(`${C}${n}`);let g=ie(re(f[0].businessDate,"YYYY-MM-DD"));g&&(y.invalidatePrefix(`daily-report:date:${g}:user:`),await R(`${T}${g}`));let D=await Pe(me.unrestricted("post-write self read: the writer always sees the row they just wrote"),n,o,{forceRefresh:!0});if(D){let A=await be(),_=D.labels.some(G=>A.includes(G.id));await v(ut.parse({type:"report-update",reportHubId:D.reportHubId,report:D,clientTempId:p,recipientRawUserId:_?o:void 0}),"updateDailyReport")}},publishDailyReport:async(n,o,i)=>{let p=await ze(e,n);if(!p.length)throw new Error("Not Found");if(p[0].userId!==o)throw new Error("Unauthorized");let f=await Le();if(!f)return null;if(await wt(e,n,f),y.invalidatePrefix(`daily-report:detail:${n}:user:`),y.invalidatePrefix(I),y.invalidatePrefix(Te),await R(Ie),p[0].businessDate){let A=ie(re(p[0].businessDate,"YYYY-MM-DD"));A&&await R(`${T}${A}`)}let g=ie(re(p[0].businessDate,"YYYY-MM-DD"));g&&y.invalidatePrefix(M(g,o));let D=await Pe(me.unrestricted("post-write self read: the writer always sees the row they just wrote"),n,o,{forceRefresh:!0});return D&&await v(dt.parse({type:"report-publish",reportHubId:D.reportHubId,report:D,clientTempId:i}),"publishDailyReport"),D??null},deleteDailyReport:async(n,o,i)=>{let p=await ze(e,n);if(!p.length||p[0].deletedAt)throw new Error("Not Found");if(p[0].userId!==o)throw new Error("Unauthorized");if(await Xe(e,n,{deletedAt:new Date,deletedBy:String(o),updatedAt:new Date,updatedBy:String(o)}),y.invalidatePrefix(`daily-report:detail:${n}:user:`),y.invalidatePrefix(I),y.invalidatePrefix(Te),await R(Ie),p[0].businessDate){let f=ie(re(p[0].businessDate,"YYYY-MM-DD"));f&&await R(`${T}${f}`)}await v(ct.parse({type:"report-delete",reportHubId:n,clientTempId:i,sourceType:p[0].sourceType}),"deleteDailyReport")},findDailyReportHubById:ze,updateDailyReportHub:Xe,updateDailyReportInternal:Dt,deleteDailyReportLabel:wt}}var Ye=require("drizzle-orm");function Ut(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 s of r){let c=`daily_report_${s.key.toLowerCase().replace(/[^a-z0-9_]/g,"_")}`;e.push({resourceKey:c,name:s.name,description:s.description??`${s.name} daily report access`}),s.includeCommentResource!==!1&&e.push({resourceKey:`${c}_comment`,name:`${s.name} Comment`,description:`${s.name} daily report comment access`})}return e}async function Yr(t,e,r){let s=t,d=e.TMResource,c=r.appKey,w=r.actor??"system:daily-report",y=new Date,k=r.resources??Ut(r.sources);for(let u of k){let H=await s.select().from(d).where((0,Ye.and)((0,Ye.eq)(d.appKey,c),(0,Ye.eq)(d.resourceKey,u.resourceKey)));(!H||H.length===0)&&await s.insert(d).values({appKey:c,resourceKey:u.resourceKey,name:u.name,description:u.description??null,createdAt:y,createdBy:w,updatedAt:y,updatedBy:w})}}var Fr=de(1,"[DailyReportExternalSource]"),qr=(t,e,r,s=Fr)=>{if(!t)return[];try{let d=JSON.parse(t);return Array.isArray(d)?d.map(r).filter(c=>c!==null):(s.warn(`Unexpected ${e} format: not an array`),[])}catch(d){return s.warn(`Failed to parse ${e}:`,d),[]}};var Fe=require("drizzle-orm"),l=require("drizzle-orm/mssql-core");function zr(t,e){let r=(0,l.mssqlSchema)(t),s=e.userTable,d=r.table("DailyReportHub",{id:(0,l.bigint)("id",{mode:"number"}).identity().notNull(),sourceType:(0,l.nvarchar)("source_type",{length:20}).notNull(),sourceId:(0,l.nvarchar)("source_id",{length:100}).notNull(),sourceIdNum:(0,l.bigint)("source_id_num",{mode:"number"}).generatedAlwaysAs(Fe.sql`TRY_CAST(source_id AS BIGINT)`),businessDate:(0,l.date)("business_date"),userId:(0,l.bigint)("user_id",{mode:"number"}),title:(0,l.nvarchar)("title",{length:200}),summary:(0,l.nvarchar)("summary",{length:"max"}),createdAt:(0,l.datetime2)("created_at").notNull(),createdBy:(0,l.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,l.datetime2)("updated_at").notNull(),updatedBy:(0,l.nvarchar)("updated_by",{length:50}).notNull(),deletedAt:(0,l.datetime2)("deleted_at"),deletedBy:(0,l.nvarchar)("deleted_by",{length:50})},h=>[(0,l.primaryKey)({name:`${t}_DailyReportHub_pk`,columns:[h.id]}),(0,l.foreignKey)({name:`${t}_DailyReportHub_user_id_fk`,columns:[h.userId],foreignColumns:[s.id]}),(0,l.index)(`${t}_DailyReportHub_business_date_index`).on(h.businessDate),(0,l.index)(`${t}_DailyReportHub_updated_at_index`).on(h.updatedAt),(0,l.index)(`${t}_DailyReportHub_source_index`).on(h.sourceType,h.sourceId),(0,l.index)(`${t}_DailyReportHub_user_id_index`).on(h.userId),(0,l.index)(`${t}_DailyReportHub_business_date_id_index`).on((0,Fe.desc)(h.businessDate),(0,Fe.desc)(h.id)),(0,l.index)(`${t}_DailyReportHub_deleted_at_index`).on(h.deletedAt)]),c=r.table("DailyReportInternal",{hubId:(0,l.bigint)("hub_id",{mode:"number"}).notNull(),body:(0,l.nvarchar)("body",{length:"max"}),metadata:(0,l.nvarchar)("metadata",{length:"max"}),createdAt:(0,l.datetime2)("created_at").notNull(),createdBy:(0,l.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,l.datetime2)("updated_at").notNull(),updatedBy:(0,l.nvarchar)("updated_by",{length:50}).notNull()},h=>[(0,l.primaryKey)({name:`${t}_DailyReportInternal_pk`,columns:[h.hubId]}),(0,l.foreignKey)({name:`${t}_DailyReportInternal_hub_id_fk`,columns:[h.hubId],foreignColumns:[d.id]})]),w=r.table("DailyReportComment",{id:(0,l.bigint)("id",{mode:"number"}).identity().notNull(),hubId:(0,l.bigint)("hub_id",{mode:"number"}).notNull(),userId:(0,l.bigint)("user_id",{mode:"number"}).notNull(),body:(0,l.nvarchar)("body",{length:"max"}).notNull(),createdAt:(0,l.datetime2)("created_at").notNull(),createdBy:(0,l.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,l.datetime2)("updated_at").notNull(),updatedBy:(0,l.nvarchar)("updated_by",{length:50}).notNull()},h=>[(0,l.primaryKey)({name:`${t}_DailyReportComment_pk`,columns:[h.id]}),(0,l.foreignKey)({name:`${t}_DailyReportComment_hub_id_fk`,columns:[h.hubId],foreignColumns:[d.id]}),(0,l.foreignKey)({name:`${t}_DailyReportComment_user_id_fk`,columns:[h.userId],foreignColumns:[s.id]}),(0,l.index)(`${t}_DailyReportComment_hub_id_index`).on(h.hubId)]),y=r.table("DailyReportLabel",{id:(0,l.bigint)("id",{mode:"number"}).identity().notNull(),userId:(0,l.bigint)("user_id",{mode:"number"}),name:(0,l.nvarchar)("name",{length:50}).notNull(),color:(0,l.nvarchar)("color",{length:20}),sortOrder:(0,l.int)("sort_order"),createdAt:(0,l.datetime2)("created_at").notNull(),createdBy:(0,l.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,l.datetime2)("updated_at").notNull(),updatedBy:(0,l.nvarchar)("updated_by",{length:50}).notNull()},h=>[(0,l.primaryKey)({name:`${t}_DailyReportLabel_pk`,columns:[h.id]}),(0,l.foreignKey)({name:`${t}_DailyReportLabel_user_id_fk`,columns:[h.userId],foreignColumns:[s.id]})]),k=r.table("DailyReportHub_Label",{hubId:(0,l.bigint)("hub_id",{mode:"number"}).notNull(),labelId:(0,l.bigint)("label_id",{mode:"number"}).notNull(),createdAt:(0,l.datetime2)("created_at").notNull(),createdBy:(0,l.nvarchar)("created_by",{length:50}).notNull()},h=>[(0,l.primaryKey)({name:`${t}_DailyReportHub_Label_pk`,columns:[h.hubId,h.labelId]}),(0,l.foreignKey)({name:`${t}_DailyReportHub_Label_hub_id_fk`,columns:[h.hubId],foreignColumns:[d.id]}),(0,l.foreignKey)({name:`${t}_DailyReportHub_Label_label_id_fk`,columns:[h.labelId],foreignColumns:[y.id]})]),u=r.table("DailyReportUserStatus",{hubId:(0,l.bigint)("hub_id",{mode:"number"}).notNull(),userId:(0,l.bigint)("user_id",{mode:"number"}).notNull(),isRead:(0,l.bit)("is_read").default(!1).notNull(),isStarred:(0,l.bit)("is_starred").default(!1).notNull(),createdAt:(0,l.datetime2)("created_at").notNull(),createdBy:(0,l.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,l.datetime2)("updated_at").notNull(),updatedBy:(0,l.nvarchar)("updated_by",{length:50}).notNull()},h=>[(0,l.primaryKey)({name:`${t}_DailyReportUserStatus_pk`,columns:[h.hubId,h.userId]}),(0,l.foreignKey)({name:`${t}_DailyReportUserStatus_hub_id_fk`,columns:[h.hubId],foreignColumns:[d.id]}),(0,l.foreignKey)({name:`${t}_DailyReportUserStatus_user_id_fk`,columns:[h.userId],foreignColumns:[s.id]})]),H=r.table("DailyReportAttachment",{id:(0,l.bigint)("id",{mode:"number"}).identity().notNull(),hubId:(0,l.bigint)("hub_id",{mode:"number"}).notNull(),uploadedBy:(0,l.bigint)("uploaded_by",{mode:"number"}),sourceKey:(0,l.nvarchar)("source_key",{length:200}).notNull(),fileName:(0,l.nvarchar)("file_name",{length:255}).notNull(),filePath:(0,l.nvarchar)("file_path",{length:"max"}).notNull(),fileType:(0,l.nvarchar)("file_type",{length:100}),fileSize:(0,l.bigint)("file_size",{mode:"number"}),objectCheckedAt:(0,l.datetime2)("object_checked_at"),objectMissingAt:(0,l.datetime2)("object_missing_at"),createdAt:(0,l.datetime2)("created_at").notNull(),createdBy:(0,l.nvarchar)("created_by",{length:50}).notNull(),updatedAt:(0,l.datetime2)("updated_at").notNull(),updatedBy:(0,l.nvarchar)("updated_by",{length:50}).notNull()},h=>[(0,l.primaryKey)({name:`${t}_DailyReportAttachment_pk`,columns:[h.id]}),(0,l.foreignKey)({name:`${t}_DailyReportAttachment_hub_id_fk`,columns:[h.hubId],foreignColumns:[d.id]}),(0,l.foreignKey)({name:`${t}_DailyReportAttachment_uploaded_by_fk`,columns:[h.uploadedBy],foreignColumns:[s.id]}),(0,l.uniqueIndex)(`${t}_DailyReportAttachment_source_unique`).on(h.hubId,h.sourceKey),(0,l.index)(`${t}_DailyReportAttachment_hub_id_index`).on(h.hubId,h.createdAt)]);return{hub:d,internal:c,comment:w,attachment:H,label:y,hubLabel:k,userStatus:u}}function Vr(t){t.redis||(t.logger??console).warn("[DailyReport] redis provider is not injected: cross-worker cache invalidation is disabled (staleness is bounded only by TTL) and SSE publishing is skipped.");let e=rt(t.redis),r=new Be({defaultTtlMs:t.cacheDefaultTtlMs??6e4},e),s=bt({...t,cache:r,epochs:e}),d=new Ue({redis:t.redis,streamKey:s.streamKey,cache:r,logger:t.logger}),c=ft({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:d,streamKey:s.streamKey,loginRedirectPath:t.loginRedirectPath,enableDevCacheClear:t.enableDevCacheClear,logger:t.logger});return{service:s,cache:r,epochs:e,sseReader:d,streamKey:s.streamKey,knownSourceTypes:[...new Set(["Internal",...(t.externalSources??[]).map(w=>w.sourceType)])],...c}}0&&(module.exports={DailyReportSseReader,DailyReportViewerScope,SqlResultCache,asciiFallbackFileName,buildVisibleSourceTypeCondition,computeSourceTypeDigest,computeViewerScopeDigest,createDailyReportHandlers,createDailyReportServer,createDailyReportService,createEpochStore,defineDailyReportAuthzResources,defineDailyReportSchema,deniesEverySourceType,encodeRfc8187,formatDateValue,generateETag,isSourceTypeVisible,isStreamIdLte,jsonResponseWithETag,normalizeVisibleSourceTypes,sanitizeMediaType,seedDailyReportAuthzResources,transformJsonArray});
|
|
16
16
|
//# sourceMappingURL=server.js.map
|