@aiquants/daily-report 0.18.2 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -186,6 +186,14 @@ resolveVisibleSourceTypes: async (request, { reason }) => {
186
186
  - **Writing to external sources remains impossible regardless** — `addComment` rejects any non-`Internal` source type outright, so for external categories the comment dimension effectively controls *reading*.
187
187
  - **Cache**: the dimension is folded into the cache-key digest, so revoking only the comment grant invalidates immediately. When `comment` follows `read` (the default) the digest is byte-identical to before, so existing deployments see no cache churn.
188
188
 
189
+ ### Transactions
190
+
191
+ 日報の作成と編集はそれぞれ 1 トランザクションで書き切る。入口は `createDailyReportService` 内の `inTransaction` 1 つに限り、**デッドロックの犠牲になったトランザクションだけをやり直す** (判定は [`@aiquants/mssql`](../mssql/README.md) が持ち、閉包は `capture` で包んで ORM が原因を消す前に押さえる)。鍵の範囲が重なる並行操作はデッドロックしうるため、犠牲になった側は従来 500 になって書いた内容が消えていた。
192
+
193
+ - 設定は `createDailyReportService({ transactionRetry })`。既定 3 回・倍化 + ゆらぎ。`{ attempts: 1 }` で無効。
194
+ - **閉包は DB の外へ副作用を持たせない。** 再実行は毎回はじめから走る。キャッシュ無効化・epoch 更新・SSE 配信はいずれもトランザクションの**後**に置いてある。
195
+ - `createDailyReport` の閉包内には `logger.info` が在るため、やり直した回だけ行が重複する。これは「実際に 2 度開いた」という事実の記録であり、抑えない。
196
+
189
197
  ## Client wiring
190
198
 
191
199
  ```tsx
package/dist/server.d.mts CHANGED
@@ -2,6 +2,7 @@ import { f as DailyReportInterviewer, e as DailyReportExternalComment, a as Dail
2
2
  import * as drizzle_orm_mssql_core from 'drizzle-orm/mssql-core';
3
3
  import { AnyMsSqlColumn } from 'drizzle-orm/mssql-core';
4
4
  import { D as DailyReportLogger } from './logger-D3krZrNK.mjs';
5
+ import { TransactionRetryOptions } from '@aiquants/mssql';
5
6
  import { SQL } from 'drizzle-orm';
6
7
 
7
8
  /**
@@ -1782,6 +1783,13 @@ declare function computeViewerScopeDigest(scope: DailyReportViewerScope): string
1782
1783
  */
1783
1784
  declare function computeSourceTypeDigest(set: VisibleSourceTypeSet): string;
1784
1785
 
1786
+ /**
1787
+ * Data-access service for daily reports (drizzle mssql), fully DI-configured.
1788
+ * 日報データアクセスサービス (drizzle mssql)。依存はすべて DI で注入する。
1789
+ *
1790
+ * キャッシュキー・無効化順序・SSE publish 順序を含むデータアクセスロジックの中核。
1791
+ */
1792
+
1785
1793
  /** DailyReportHub の行型。 */
1786
1794
  type DailyReportHubRow = {
1787
1795
  id: number;
@@ -1884,6 +1892,15 @@ type DailyReportServiceConfig = {
1884
1892
  cache: SqlResultCache;
1885
1893
  /** クロスワーカー epoch ストア (facade が生成して注入)。 */
1886
1894
  epochs: EpochStore;
1895
+ /**
1896
+ * Retry policy for transactions SQL Server chose as the deadlock victim. See `@aiquants/mssql`.
1897
+ * サーバがロールバックしたトランザクションの再試行方針。
1898
+ *
1899
+ * 鍵の範囲が重なる並行操作はデッドロックしうる。犠牲に選ばれた側はサーバによって
1900
+ * ロールバックされる — 何もコミットされていないので、書き直す再実行が正しい。既定で 3 回試す。
1901
+ * `{ attempts: 1 }` で再試行しない。
1902
+ */
1903
+ transactionRetry?: TransactionRetryOptions;
1887
1904
  /**
1888
1905
  * 下書きラベル名 (単一または配列で指定可能)。
1889
1906
  * 消費アプリ側で自 DB のラベル名や作成区分の候補名 ("下書き", "DRAFT" など) を注入できる。
package/dist/server.d.ts CHANGED
@@ -2,6 +2,7 @@ import { f as DailyReportInterviewer, e as DailyReportExternalComment, a as Dail
2
2
  import * as drizzle_orm_mssql_core from 'drizzle-orm/mssql-core';
3
3
  import { AnyMsSqlColumn } from 'drizzle-orm/mssql-core';
4
4
  import { D as DailyReportLogger } from './logger-D3krZrNK.js';
5
+ import { TransactionRetryOptions } from '@aiquants/mssql';
5
6
  import { SQL } from 'drizzle-orm';
6
7
 
7
8
  /**
@@ -1782,6 +1783,13 @@ declare function computeViewerScopeDigest(scope: DailyReportViewerScope): string
1782
1783
  */
1783
1784
  declare function computeSourceTypeDigest(set: VisibleSourceTypeSet): string;
1784
1785
 
1786
+ /**
1787
+ * Data-access service for daily reports (drizzle mssql), fully DI-configured.
1788
+ * 日報データアクセスサービス (drizzle mssql)。依存はすべて DI で注入する。
1789
+ *
1790
+ * キャッシュキー・無効化順序・SSE publish 順序を含むデータアクセスロジックの中核。
1791
+ */
1792
+
1785
1793
  /** DailyReportHub の行型。 */
1786
1794
  type DailyReportHubRow = {
1787
1795
  id: number;
@@ -1884,6 +1892,15 @@ type DailyReportServiceConfig = {
1884
1892
  cache: SqlResultCache;
1885
1893
  /** クロスワーカー epoch ストア (facade が生成して注入)。 */
1886
1894
  epochs: EpochStore;
1895
+ /**
1896
+ * Retry policy for transactions SQL Server chose as the deadlock victim. See `@aiquants/mssql`.
1897
+ * サーバがロールバックしたトランザクションの再試行方針。
1898
+ *
1899
+ * 鍵の範囲が重なる並行操作はデッドロックしうる。犠牲に選ばれた側はサーバによって
1900
+ * ロールバックされる — 何もコミットされていないので、書き直す再実行が正しい。既定で 3 回試す。
1901
+ * `{ attempts: 1 }` で再試行しない。
1902
+ */
1903
+ transactionRetry?: TransactionRetryOptions;
1887
1904
  /**
1888
1905
  * 下書きラベル名 (単一または配列で指定可能)。
1889
1906
  * 消費アプリ側で自 DB のラベル名や作成区分の候補名 ("下書き", "DRAFT" など) を注入できる。
package/dist/server.js CHANGED
@@ -1,16 +1,16 @@
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}
1
+ "use strict";var et=Object.defineProperty;var er=Object.getOwnPropertyDescriptor;var tr=Object.getOwnPropertyNames;var rr=Object.prototype.hasOwnProperty;var It=t=>{throw TypeError(t)};var nr=(t,e)=>{for(var r in e)et(t,r,{get:e[r],enumerable:!0})},ar=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let d of tr(e))!rr.call(t,d)&&d!==r&&et(t,d,{get:()=>e[d],enumerable:!(o=er(e,d))||o.enumerable});return t};var sr=t=>ar(et({},"__esModule",{value:!0}),t);var Tt=(t,e,r)=>e.has(t)||It("Cannot "+r);var Le=(t,e,r)=>(Tt(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,o)=>(Tt(t,e,"write to private field"),o?o.call(t,r):e.set(t,r),r);var Jr={};nr(Jr,{DailyReportSseReader:()=>$e,DailyReportViewerScope:()=>me,SqlResultCache:()=>Pe,asciiFallbackFileName:()=>Ut,buildVisibleSourceTypeCondition:()=>ht,computeSourceTypeDigest:()=>yt,computeViewerScopeDigest:()=>xe,createDailyReportHandlers:()=>bt,createDailyReportServer:()=>jr,createDailyReportService:()=>gt,createEpochStore:()=>nt,defineDailyReportAuthzResources:()=>Ot,defineDailyReportSchema:()=>Kr,deniesEverySourceType:()=>we,encodeRfc8187:()=>Bt,formatDateValue:()=>re,generateETag:()=>Ve,isSourceTypeVisible:()=>be,isStreamIdLte:()=>Ce,jsonResponseWithETag:()=>pe,normalizeVisibleSourceTypes:()=>mt,sanitizeMediaType:()=>ft,seedDailyReportAuthzResources:()=>qr,transformJsonArray:()=>Vr});module.exports=sr(Jr);var nt=t=>({async getEpoch(e){try{let r=await t?.getClient();if(!r)return null;let o=await r.get(e);return o?Number(o):0}catch{return null}},async incrementEpoch(e){try{let r=await t?.getClient();if(!r)return;await r.incr(e)}catch{}}}),Pe=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:o}=e,d=this.buckets.get(o);if(!d)return;let c=e.ttlMsOverride??this.config.defaultTtlMs;if(c-(d.expireAt-Date.now())<c*r||this.inFlight.has(o))return;let y;y=(async()=>{let k=e.epochKey?await this.epochStore.getEpoch(e.epochKey):null,u=await e.fetcher();return this.inFlight.get(o)===y&&this.buckets.set(o,{records:u,expireAt:Date.now()+c,epoch:k}),u})(),this.inFlight.set(o,y),y.catch(()=>{}).finally(()=>{this.inFlight.get(o)===y&&this.inFlight.delete(o)})};this.getOrFetch=async e=>{let{cacheKey:r,forceRefresh:o,snapshot:d}=e,c=this.buckets.get(r);if(o&&(this.buckets.delete(r),this.inFlight.delete(r)),!o&&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(!o&&this.inFlight.has(r)){let y=await this.inFlight.get(r);return d?y.map(k=>structuredClone(k)):y}let D;D=(async()=>{let y=e.epochKey?await this.epochStore.getEpoch(e.epochKey):null;e.onFetchStart?.();let k=await e.fetcher();if(o||this.inFlight.get(r)===D){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})(),o||this.inFlight.set(r,D);try{let y=await D;return d?y.map(k=>structuredClone(k)):y}finally{this.inFlight.get(r)===D&&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,o]of this.buckets.entries())o.expireAt<=e&&this.buckets.delete(r)}};var or=/^\d{4}-\d{2}-\d{2}$/,ir=/^\d{4}\/\d{2}\/\d{2}$/,At=t=>t<10?`0${t}`:`${t}`,Ct=t=>{if(Number.isNaN(t.getTime()))return null;let e=t.getFullYear(),r=At(t.getMonth()+1),o=At(t.getDate());return`${e}-${r}-${o}`};var ie=t=>{if(t==null)return null;if(t instanceof Date)return Ct(t);let e=t.trim();if(e==="")return null;if(or.test(e))return e;if(ir.test(e))return e.replaceAll("/","-");let r=new Date(e);return Ct(r)};var at=t=>{let e=2166136261,r=-624069552;for(let o of t){let d=o.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=o.businessDate;if(c===null)e^=1,e=Math.imul(e,16777619),r^=1,r=Math.imul(r,16777619);else for(let D=0;D<c.length;D++){let y=c.charCodeAt(D);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+(?=.)/,"")},qe=(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(qe(t[e-1],t[e])>0)return!1;return!0};var vt=(t,e)=>{let r=t.findIndex(o=>qe({businessDate:o.businessDate,reportHubId:o.reportHubId},e)>0);return r===-1?t.length:r};var de=(t,e,r=console)=>{let o=d=>typeof d=="string"?[`${e} ${d}`]:[e,d];return{debug:(d,...c)=>{t<=0&&r.debug(...o(d),...c)},info:(d,...c)=>{t<=1&&r.info(...o(d),...c)},warn:(d,...c)=>{t<=2&&r.warn(...o(d),...c)},error:(d,...c)=>{t<=3&&r.error(...o(d),...c)}}};var m=require("zod"),lr=m.z.object({name:m.z.string().nullish(),affiliation:m.z.string().nullish()}),ur=m.z.object({name:m.z.string().nullish(),text:m.z.string().nullish(),color:m.z.string().nullish()}),dr=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()}),cr=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"])}),st=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(lr),subject:m.z.string().nullish(),content:m.z.string().nullish(),externalComments:m.z.array(ur),isRead:m.z.boolean(),isStarred:m.z.boolean(),labels:m.z.array(dr),postedComments:m.z.array(xt),attachments:m.z.array(cr).default([])}),pr=m.z.object({type:m.z.literal("connected")}),ze=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()}),ot=m.z.string().optional(),it=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:ot}),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:ot}),ut=m.z.object({type:m.z.literal("report-create"),reportHubId:m.z.number(),report:st,clientTempId:m.z.string(),recipientRawUserId:m.z.number().optional()}),dt=m.z.object({type:m.z.literal("report-update"),reportHubId:m.z.number(),report:st,clientTempId:m.z.string(),recipientRawUserId:m.z.number().optional()}),ct=m.z.object({type:m.z.literal("report-publish"),reportHubId:m.z.number(),report:st,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:ot}),kt=m.z.discriminatedUnion("type",[pr,ze,it,lt,ut,dt,ct,pt]);var Et=require("crypto"),Ve=t=>{let e=JSON.stringify(t);return`"${(0,Et.createHash)("sha256").update(e).digest("hex")}"`};var mr=de(1,"[Response]"),pe=(t,e,r,o=200,d=mr)=>{let c=Ve(r),D=t.headers.get("If-None-Match");d.info(`[jsonResponseWithETag] ETag: ${c}, If-None-Match: ${D}`);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"&&o===200&&D===c?new Response(null,{status:304,headers:y}):new Response(JSON.stringify(r),{status:o,headers:y})};var Mt=require("events");var Ce=(t,e)=>{let[r,o]=t.split("-").map(Number),[d,c]=e.split("-").map(Number);return r!==d?r<d:o<=c},$e=class{constructor(e){this.config=e;this._emitter=new Mt.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 o of r.messages){this._lastId=o.id;try{let d=o.message?.data?JSON.parse(o.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 D=d?.reportHubId;typeof D=="number"&&(this.config.cache.invalidate(`daily-report:detail:${D}`),this.config.cache.invalidatePrefix(`daily-report:detail:${D}:user:`))}}catch{}this._emitter.emit("entry",{id:o.id,message:o.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 Ue=require("drizzle-orm");var yr="",hr=64,fr=t=>t.toLowerCase(),br=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 o=br(r);o.length>0&&e.add(o)}return e}function be(t,e){return t===null?!0:e==null?!1:t.has(fr(e))}function we(t){return t!==null&&t.size===0}function ht(t,e){if(e!==null)return e.size===0?Ue.sql`1 = 0`:(0,Ue.inArray)(Ue.sql`LOWER(${t})`,[...e])}var _e,ve,Be=class Be{constructor(e,r){tt(this,_e);tt(this,ve);rt(this,_e,e),rt(this,ve,r)}get visible(){return Le(this,_e)===null?null:new Set(Le(this,_e))}get commentable(){return Le(this,ve)===null?null:new Set(Le(this,ve))}static restrictTo(e){let r=typeof e=="object"&&e!==null&&"read"in e,o=mt(r?e.read:e),d=r?e.comment:void 0;if(d===void 0)return new Be(o,o);let c=mt(d),D=new Set;for(let y of c??[])o.has(y)&&D.add(y);return new Be(o,D)}static unrestricted(e){return new Be(null,null)}};_e=new WeakMap,ve=new WeakMap;var me=Be;function xe(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(o=>`${o.length}:${o}`).join(yr);if(e.length<=hr)return`s:${e}`;let r=2166136261;for(let o=0;o<e.length;o++)r^=e.charCodeAt(o),r=Math.imul(r,16777619);return`sh:${(r>>>0).toString(16)}`}var gr=(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})},je=30,$t=4e3,Rr="stream interrupted by server error",Dr=/^\d{4}-\d{2}-\d{2}$/,wr=15e3,Nt=Symbol("ids-stream-heartbeat"),Sr=12,Ir=/^[0-9a-f]{1,16}$/,Tr=t=>{let e=t.searchParams.get("cursor_report_hub_id"),r=t.searchParams.get("cursor_business_date"),o=t.searchParams.get("cursor_snapshot"),d=o!==null&&Ir.test(o)?o: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}:Dr.test(r)?{cursor:{businessDate:r,reportHubId:c},snapshot:d}:{invalid:!0}};async function*Lt(t,e,r,o){let d=e?vt(t,e):0,c=!0;for(;;){let D=t.slice(d,d+(c?r:$t));d+=D.length;let y=d>=t.length,k=D[D.length-1];if(yield{kind:"chunk",items:D,nextCursor:y||!k?null:{businessDate:k.businessDate,reportHubId:k.reportHubId},isLast:y,...c?{total:t.length}:{},snapshot:o.snapshot,...c&&o.restarted?{restarted:!0}:{}},c=!1,y)return}}var Pt=(t,e,r,o)=>{let d=new TextEncoder,c=!1,D=null,y=new ReadableStream({async pull(u){if(c||r.signal.aborted){await e.return(void 0).catch(()=>{});try{u.close()}catch{}return}let Y=null;try{D===null&&(D=e.next());let h=new Promise(ye=>{Y=setTimeout(()=>ye(Nt),wr)}),V=await Promise.race([D,h]);if(Y!==null&&(clearTimeout(Y),Y=null),V===Nt){if(c||r.signal.aborted){await e.return(void 0).catch(()=>{});try{u.close()}catch{}return}u.enqueue(d.encode(`
2
+ `));return}D=null;let{value:K,done:F}=V;if(F){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(Y!==null&&clearTimeout(Y),D=null,c||r.signal.aborted)return;o.error(`ids-stream emission failed: ${h instanceof Error?h.message:String(h)}`);try{let V={kind:"error",error:Rr};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})},Ar=32*1024*1024,Cr=60,_r=4,vr=12e4,xr=1024,kr=60,Er=5,Mr=new Set(["image/png","image/jpeg","image/gif","image/webp","application/pdf","text/plain"]),Nr=/^[\x20-\x7E]+$/,Lr=/^[\w.+-]+\/[\w.+-]+/,ft=t=>t&&Nr.test(t)&&Lr.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,"_"),Pr=t=>{switch(t){case"not_found":case"denied":case"invalid_path":return 404;case"too_large":return 413;default:return 502}},$r={404:"Attachment not found",413:"Attachment too large",502:"Attachment storage unavailable"},Br=t=>{let e=new Map;return(r,o)=>{let d=e.get(r);d&&e.delete(r);let c=d??{tokens:t,lastRefillMs:o},D=Math.max(0,o-c.lastRefillMs);D>0&&(c.tokens=Math.min(t,c.tokens+D*t/6e4),c.lastRefillMs=o);let y=c.tokens>=1;for(y&&(c.tokens-=1),e.set(r,c);e.size>xr;){let k=e.keys().next();if(k.done)break;e.delete(k.value)}return y}},Ur=t=>{let e=0;return{tryAcquire:()=>e>=t?!1:(e+=1,!0),release:()=>{e>0&&(e-=1)}}},Hr=(t,e,r)=>{let o=setTimeout(e,r);o.unref?.();let d=()=>{clearTimeout(o),e()},c=!1;return new ReadableStream({pull(D){if(c){D.close(),d();return}c=!0,D.enqueue(t)},cancel(){d()}})},Or=(t,e,r,o)=>{if(r===null&&o===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 be(r,t.report.sourceType);case"comment-add":case"comment-delete":return be(o,d??"Internal");case"report-delete":return be(r,d)}},Yr=["externalComments","postedComments"],Fr=(t,e,r)=>{if(r===null||t.type!=="report-create"&&t.type!=="report-update"&&t.type!=="report-publish"||be(r,t.report.sourceType))return!1;let o=e.report;if(typeof o!="object"||o===null)return!1;let d=o;for(let c of Yr)d[c]=[];return!0};function bt(t){let{authenticate:e,service:r,encodeUserId:o,redis:d,sseReader:c,streamKey:D}=t,y=t.loginRedirectPath??"/auth/login",k=t.logger??de(3,"[DailyReportAPI]"),u=t.logger??de(3,"[DailyReportVisibility]"),Y=t.logger??de(1,"[DailyReportSSE]"),h=t.logger??de(1,"[DailyReportAttachment]"),V=t.attachmentMaxBytes??Ar,K=Br(t.attachmentRateLimitPerMinute??Cr),F=Ur(t.attachmentConcurrency??_r),ye=async(S,H="initial")=>{let E=t.resolveVisibleSourceTypes;if(!E)return me.unrestricted("no visibility port injected: this deployment does not restrict by source type");try{let A=await E(S,{reason:H});return A==null?me.unrestricted("visibility port returned null/undefined: this deployment opts out of source-type filtering"):me.restrictTo(A)}catch(A){return u.error("resolveVisibleSourceTypes threw; failing closed (deny all)",A),me.restrictTo([])}},ke=async({request:S})=>{let{user:H,cookie:E}=await e(S,{failureRedirect:y}),A=new Headers;E&&A.append("Set-Cookie",E);let f=await r.getUserIdByExternalId(H.id),B=f?o(f):null;return{data:{user:H,userId:B},headers:A}},Ee={"business-date":async(S,H,E,A,f)=>{let B=ie(S.searchParams.get("businessDate")),q=S.searchParams.get("forceRefresh")==="true";if(!B)return pe(E,H,{error:{message:"Invalid business date"}},400);let v=await r.getDailyReportsByBusinessDateByExternalId(f,B,A.id,{forceRefresh:q});return pe(E,H,{businessDate:B,reports:v},200)},"ids-stream":async(S,H,E,A,f)=>{let B=Tr(S);if("invalid"in B)return pe(E,H,{error:{message:"Invalid cursor"}},400);let q=S.searchParams.get("forceRefresh")==="true",v=!1,I=null,C=null,z=new Promise((N,M)=>{I=N,C=M});z.catch(()=>{});let ce=r.getDailyReportIdsByExternalId(f,A.id,{forceRefresh:q,onFetchStart:B.cursor?void 0:()=>{v=!0,r.getDailyReportIdsFirstPageByExternalId(f,A.id,je).then(N=>I?.(N),N=>C?.(N))}});if(ce.catch(()=>{}),B.cursor){let N=await ce,M=at(N),$=B.snapshot!==null&&B.snapshot===M;return Pt(H,Lt(N,$?B.cursor:null,je,{snapshot:M,restarted:!$}),E,k)}let P=(async function*(){let N=await Promise.race([ce.then(L=>({kind:"full",items:L}),L=>({kind:"full-error",error:L})),z.then(L=>({kind:"page",items:L}),()=>({kind:"page-error"}))]),M=null,$=!1;if(N.kind==="full")M=N.items;else if(N.kind==="page"){let L=N.items;if(L.length<je){yield{kind:"chunk",items:L,nextCursor:null,isLast:!0,total:L.length};return}yield{kind:"chunk",items:L,nextCursor:null,isLast:!1,provisional:!0},$=!0}else if(N.kind==="full-error"&&v){let L=await z.catch(()=>null);L&&L.length>0&&(yield{kind:"chunk",items:L,nextCursor:null,isLast:!1,provisional:!0})}M===null&&(M=await ce),yield*Lt(M,null,$?$t:je,{snapshot:at(M)})})();return Pt(H,P,E,k)},report:async(S,H,E,A,f)=>{let B=S.searchParams.get("reportHubId"),q=S.searchParams.get("forceRefresh")==="true",v=B?Number.parseInt(B,10):NaN;if(!Number.isFinite(v)||v<=0)return pe(E,H,{error:{message:"Invalid reportHubId"}},400);let I=await r.getDailyReportDetailByIdByExternalId(f,v,A.id,{snapshot:!0,forceRefresh:q});return I?pe(E,H,{report:I},200):pe(E,H,{error:{message:"Report not found"}},404)}};return{index:{loader:ke},api:{loader:async({request:S,params:H})=>{let{user:E,cookie:A}=await e(S,{failureRedirect:null}),f=A??null;if(!E)return pe(S,f,{error:{message:"Unauthorized"}},401);if(S.method!=="GET")return pe(S,f,{error:{message:"Method not allowed"}},405);let B=H.endpoint??"",q=Ee[B];if(!q)return pe(S,f,{error:{message:"Unknown endpoint"}},404);let v=Date.now();try{let I=new URL(S.url),C=await ye(S);return await q(I,f,S,E,C)}catch(I){let C=Date.now()-v,z=I instanceof Error?I:new Error(String(I));return k.error(`500 endpoint=${B} elapsed=${C}ms name=${z.name} code=${"code"in z?z.code:"N/A"} message=${z.message}`),k.error("Stack:",z.stack),pe(S,f,{error:{message:"Internal Server Error"}},500)}},action:async({request:S,params:H})=>{let{user:E,cookie:A}=await e(S,{failureRedirect:null}),f=(q,v)=>gr(q,{...v,setCookie:A});if(!E)return f({error:"Unauthorized"},{status:401});let B=Date.now();try{if(H.endpoint!=="action")return f({error:"Unknown endpoint"},{status:404});let v=await r.getUserIdByExternalId(E.id);if(!v)return f({error:"User not found"},{status:404});let I=await ye(S),C=await S.formData(),z=C.get("intent"),ce=C.get("reportHubId"),P=ce?Number(ce):NaN,N=C.get("businessDate"),M=Number(C.get("operationTimestamp")),$=C.get("clientTempId");if(z==="clearCache")return t.enableDevCacheClear?(await r.clearCache(),f({status:"OK",intent:"clearCache"})):f({error:"Invalid intent"},{status:400});if(!$)return f({error:"clientTempId required"},{status:400});if(z!=="create"&&(!P||Number.isNaN(P)))return f({error:"Invalid reportHubId"},{status:400});let L=async(w,O,Z)=>{let he=C.get(O);if(he===null)return f({error:`${O} required`},{status:400});try{let le=await Z(he==="true");return f({status:"OK",intent:w,updatedStatus:{isStarred:le.isStarred,isRead:le.isRead},operationTimestamp:M,reportHubId:String(P),clientTempId:$})}catch(le){if(le instanceof Error&&le.message==="Not Found")return f({error:"Report not found"},{status:404});throw le}};switch(z){case"create":{if(!N)return f({error:"businessDate required"},{status:400});let w=await r.createDailyReport(v,N,$);return f({status:"OK",intent:"create",report:w,reportHubId:String(w.reportHubId),clientTempId:$})}case"update":{let w=C.get("title"),O=C.get("content");try{return await r.updateDailyReport(P,v,{title:w,content:O},$),f({status:"OK",intent:"update",reportHubId:String(P),clientTempId:$})}catch(Z){if(Z instanceof Error){if(Z.message==="Unauthorized")return f({error:"Unauthorized"},{status:403});if(Z.message==="Not Found")return f({error:"Report not found"},{status:404})}throw Z}}case"publish":try{let w=await r.publishDailyReport(P,v,$);return f({status:"OK",intent:"publish",reportHubId:String(P),clientTempId:$,report:w})}catch(w){if(w instanceof Error){if(w.message==="Unauthorized")return f({error:"Unauthorized"},{status:403});if(w.message==="Not Found")return f({error:"Report not found"},{status:404})}throw w}case"delete":try{return await r.deleteDailyReport(P,v,$),f({status:"OK",intent:"delete",reportHubId:String(P),clientTempId:$})}catch(w){if(w instanceof Error){if(w.message==="Unauthorized")return f({error:"Unauthorized"},{status:403});if(w.message==="Not Found")return f({error:"Report not found"},{status:404})}throw w}case"toggleStar":return await L("toggleStar","isStarred",w=>r.setStarStatus(I,v,P,N,w,$));case"toggleRead":return await L("toggleRead","isRead",w=>r.setReadStatus(I,v,P,N,w,$));case"addComment":{let w=C.get("content");if(!w)return f({error:"Content required"},{status:400});try{let O=await r.addComment(I,v,P,w,N,$),Z={...O,userId:O.userId};return f({status:"OK",intent:"addComment",newComment:Z,reportHubId:String(P),clientTempId:$})}catch(O){if(O instanceof Error){if(O.message==="Not Found")return f({error:"Report not found"},{status:404});if(O.message.startsWith("Comments are restricted"))return f({error:"Comments are restricted for this report"},{status:403})}throw O}}case"deleteComment":{let w=Number(C.get("commentId"));if(!w||Number.isNaN(w))return f({error:"Invalid commentId"},{status:400});try{return await r.deleteComment(I,v,P,w,N,$),f({status:"OK",reportHubId:String(P),deletedCommentId:String(w),clientTempId:$})}catch(O){if(O instanceof Error){if(O.message==="Unauthorized")return f({error:"Unauthorized"},{status:403});if(O.message==="Not Found")return f({error:"Comment not found"},{status:404})}throw O}}default:return f({error:"Invalid intent"},{status:400})}}catch(q){if(q instanceof Response)throw q;let v=Date.now()-B,I=q instanceof Error?q:new Error(String(q));return k.error(`500 action elapsed=${v}ms name=${I.name} message=${I.message}`),k.error("Stack:",I.stack),f({error:"Internal Server Error"},{status:500})}}},sse:{loader:async({request:S,params:H})=>{let{user:E,cookie:A}=await e(S,{failureRedirect:null}),f=ne=>A===void 0?ne:{...ne??{},"Set-Cookie":A};if(!E)return new Response("Unauthorized",{status:401,headers:f()});let B=await r.getUserIdByExternalId(E.id);if(!B)return new Response("Forbidden",{status:403,headers:f()});if(H.endpoint!=="updates")return new Response("Not Found",{status:404,headers:f()});let q=await ye(S),v=q.visible,I=q.commentable,C=0,z=0,P=new URL(S.url).searchParams.get("lastEventId")||S.headers.get("Last-Event-ID"),N=new TextEncoder,M=null,$=null,L=null,w=!1,O=()=>{if(!w){if(w=!0,$&&(clearInterval($),$=null),L&&(L(),L=null),M)try{M.desiredSize!==null&&M.close()}catch{}finally{M=null}w=!1}},Z=ne=>{M&&M.desiredSize!==null&&M.enqueue(N.encode(`id: ${ne}
5
5
  data: ${JSON.stringify({type:"connected"})}
6
6
 
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}
7
+ `))},he=(ne,ee)=>{if(ee.data)try{let G=JSON.parse(ee.data),x=kt.safeParse(G);if(!x.success){Y.error("SSE message validation failed:",x.error.format());return}let J=x.data,ue=typeof G.recipientRawUserId=="number"?G.recipientRawUserId:void 0;if(J.type==="status-update"){if(ue===void 0||ue!==B)return}else if(ue!==void 0&&ue!==B)return;if(!Or(J,G,v,I)){Z(ne);return}let Ge=Fr(J,G,I),fe;if("recipientRawUserId"in G){let{recipientRawUserId:Me,...ge}=G;fe=JSON.stringify(ge)}else Ge?fe=JSON.stringify(G):fe=ee.data;M&&M.desiredSize!==null&&M.enqueue(N.encode(`id: ${ne}
8
+ data: ${fe}
9
9
 
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
10
+ `))}catch(G){Y.error(`[SSE:${B}] processEntry error:`,G)}},le=new ReadableStream({async start(ne){M=ne,$=setInterval(()=>{try{if(M&&M.desiredSize!==null){if(M.enqueue(N.encode(`: keep-alive
11
11
 
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"})}
12
+ `)),++C%Sr===0){let x=++z;ye(S,"refresh").then(J=>{x===z&&(v=J.visible,I=J.commentable)})}}else O()}catch{O()}},5e3),S.signal.addEventListener("abort",()=>{O()});let ee=P||"0-0",G=null;if(L=c.subscribe(x=>{Ce(x.id,ee)||(G===null&&(G=x.id),ee=x.id,he(x.id,x.message))},x=>{Y.error(`[SSE:${B}] Fan-Out reader error:`,x),O()}),!P)try{let x=await d?.getClient();if(x){let J=await x.xRevRange(D,"+","-",{COUNT:1});J.length>0&&!Ce(J[0].id,ee)&&(ee=J[0].id)}}catch{}if(M&&M.desiredSize!==null){let x=`data: ${JSON.stringify({type:"connected"})}
13
13
 
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});
14
+ `,J=ee!=="0-0"?`id: ${ee}
15
+ ${x}`:x;M.enqueue(N.encode(J))}if(P)try{let x=await d?.getClient();if(x){let J=await x.xRange(D,P,"+",{COUNT:1e3});for(let ue of J)ue.id!==P&&(G!==null&&Ce(G,ue.id)||(Ce(ue.id,ee)||(ee=ue.id),he(ue.id,ue.message)))}}catch(x){Y.error(`[SSE:${B}] catch-up xRange error:`,x)}},cancel(){O()}});return new Response(le,{headers:f({"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive"})})}},attachment:{loader:async({request:S,params:H})=>{let E=null,A=(f,B,q)=>{let v=new Headers({"Content-Type":"application/json"});return q!==void 0&&v.set("Retry-After",String(q)),E&&v.append("Set-Cookie",E),new Response(JSON.stringify({error:{message:B}}),{status:f,headers:v})};try{let{user:f,cookie:B}=await e(S,{failureRedirect:null});if(E=B??null,!f)return A(401,"Unauthorized");if(S.method!=="GET"&&S.method!=="HEAD")return A(405,"Method not allowed");let q=t.attachmentIdCodec,v=t.readAttachment;if(!(q&&v))return A(404,"Attachment not found");let I=H.token??"",C=q.decode(I);if(C===null||!Number.isSafeInteger(C)||C<=0)return A(400,"Invalid attachment token");let z=await r.getUserIdByExternalId(f.id);if(!z)return A(403,"Forbidden");if(!K(z,Date.now()))return h.error(`429 attachment=${C} viewer=${z} reason=rate_limit`),A(429,"Too many requests",kr);let ce=await ye(S),P=await r.getAttachmentForUser(ce,C,z);if(!P)return h.error(`404 attachment=${C} viewer=${z} reason=not_visible`),A(404,"Attachment not found");if(P.fileSize!=null&&P.fileSize>V)return h.error(`413 attachment=${C} viewer=${z} reason=db_size`),A(413,"Attachment too large");if(!F.tryAcquire())return h.error(`503 attachment=${C} viewer=${z} reason=concurrency`),A(503,"Too many concurrent downloads",Er);let N=!1,M=()=>{N||(N=!0,F.release())},$=!1;try{let L=S.method==="HEAD",w=await v(P.filePath,{maxBytes:V,head:L,principal:o(z)});if(!w.ok){let x=Pr(w.reason);return w.reason==="not_found"&&r.markAttachmentMissing(C).catch(J=>{h.error(`markAttachmentMissing failed attachment=${C} message=${J instanceof Error?J.message:"unknown"}`)}),h.error(`${x} attachment=${C} viewer=${z} reason=${w.reason} code=${w.code??"-"}`),A(x,$r[x]??"Attachment storage unavailable")}let O=ft(P.fileType)??ft(w.contentType)??"application/octet-stream",Z=Mr.has(O),he=new URL(S.url).searchParams.get("download")==="1",le=Z?O:"application/octet-stream",ne=Z&&!he?"inline":"attachment",ee=w.size??w.bytes.byteLength,G=new Headers({"Content-Type":le,"Content-Length":String(ee),"Content-Disposition":`${ne}; filename="${Ut(P.fileName)}"; filename*=UTF-8''${Bt(P.fileName)}`,"Cache-Control":"private, no-store","X-Content-Type-Options":"nosniff","Content-Security-Policy":"default-src 'none'; sandbox","X-Frame-Options":"SAMEORIGIN"});return E&&G.append("Set-Cookie",E),r.markAttachmentPresent(C).catch(x=>{h.error(`markAttachmentPresent failed attachment=${C} message=${x instanceof Error?x.message:"unknown"}`)}),h.info(`200 attachment=${C} viewer=${z} type=${le} disposition=${ne} bytes=${ee}`),L?new Response(null,{status:200,headers:G}):($=!0,new Response(Hr(w.bytes,M,vr),{status:200,headers:G}))}finally{$||M()}}catch(f){if(f instanceof Response)throw f;return h.error(`500 attachment=? viewer=? reason=unexpected message=${f instanceof Error?f.message:"unknown"}`),A(500,"Attachment request failed")}}}}}var Ht=require("@aiquants/mssql"),s=require("drizzle-orm");var Se=t=>(0,s.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 o=r.getFullYear(),d=o<0?`-${String(-o).padStart(4,"0")}`:String(o).padStart(4,"0"),c=String(r.getMonth()+1).padStart(2,"0"),D=String(r.getDate()).padStart(2,"0");if(e==="YYYY-MM-DD")return`${d}-${c}-${D}`;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}-${D} ${y}:${k}:${u}`};function gt(t){let{db:e,tables:r,userTable:o,resolveUserId:d,encodeUserId:c,redis:D,cache:y,epochs:k}=t,{hub:u,internal:Y,comment:h,label:V,hubLabel:K,userStatus:F}=r,ye=t.externalSources??[],ke=t.draftLabelNames&&t.draftLabelNames.length>0?t.draftLabelNames:[t.draftLabelName??"\u4E0B\u66F8\u304D"],Ee=ke[0]??"\u4E0B\u66F8\u304D",te=t.logger??de(1,"[DailyReportService]"),Je=n=>(0,Ht.runWithTransactionRetry)(a=>e.transaction(i=>a(()=>n(i))),t.transactionRetry),Ie="daily-report:ids",Rt=t.idsTtlMs??18e4,S="daily-report:ids:epoch",H="daily-report:business-date:",E=t.businessDateTtlMs??3e5,A="daily-report:date-epoch:",f="daily-report:detail-epoch:",q=`${t.streamKey??"daily-report:sse-stream"}:v2`,v=t.streamMaxLen??1e4,I=n=>k.incrementEpoch(n),C=n=>ht(u.sourceType,n),z=(n,a)=>`${Ie}:user:${n}:st:${a}`,ce=n=>`${Ie}:user:${n}:`,P=(n,a,i)=>`daily-report:date:${n}:user:${a}:st:${i}`,N=(n,a)=>`daily-report:date:${n}:user:${a}:`,M=(n,a,i)=>`daily-report:detail:${n}:user:${a}:st:${i}`,$=(n,a)=>`daily-report:detail:${n}:user:${a}:`,L=async(n,a)=>{let i=await D?.getClient();if(!i){te.warn(`[SSE] Redis client unavailable (${a})`);return}let p=Date.now();try{await i.xAdd(q,"*",{data:JSON.stringify(n)},{TRIM:{strategy:"MAXLEN",strategyModifier:"~",threshold:v}});let b=Date.now()-p;b>1e3&&te.warn(`[SSE] Slow publish (${a}): ${b}ms`)}catch(b){te.error(`[SSE] Redis publish failed (${a}):`,b)}},w=n=>n==null||n===""?null:/^\d+$/.test(n)?c(Number(n)):n,O=()=>{let n={};for(let a of ye)n[`ext_${a.sourceType}`]=Se(a.table);return n},Z=n=>{let a=n;for(let i of ye)a=a.leftJoin(i.table,(0,s.and)((0,s.eq)(u.sourceType,i.sourceType),(0,s.eq)(u.sourceIdNum,i.idColumn)));return a},he=(n,a,i)=>{let{hub:p,internal:b}=a,g=p.summary,R=[],T=null,_=null,Q=null,j=null,W=null,ae=null,Te=[],De=ye.find(U=>U.sourceType===p.sourceType),Ae=De?a[`ext_${De.sourceType}`]:void 0;if(De&&Ae){let U=De.mapRow(Ae);U.content!==void 0&&(g=U.content),U.employeeName!==void 0&&(ae=U.employeeName),U.category!==void 0&&(T=U.category),U.creationCategory!==void 0&&(_=U.creationCategory),U.visitTimeFrom!==void 0&&(Q=U.visitTimeFrom),U.visitTimeTo!==void 0&&(j=U.visitTimeTo),U.customerName!==void 0&&(W=U.customerName),U.interviewers!==void 0&&(R=U.interviewers),U.externalComments!==void 0&&(Te=U.externalComments)}else p.sourceType==="Internal"&&b&&(g=b.body);let Re=(a.labels??[]).map(U=>({id:U.id,name:U.name,color:U.color})),se=a.postedCommentRows??[],X=be(n.commentable,p.sourceType),oe=_?ke.includes(_):!1,Ze=fe?.[0]??null;return oe&&Ze&&!Re.some(U=>U.id===Ze)&&Re.push({id:Ze,name:Ee,color:null}),{reportHubId:p.id,date:re(p.businessDate,"YYYY-MM-DD"),author:a.creatorName??w(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:w(p.updatedBy),employeeName:ae??a.creatorName??w(p.createdBy),category:T,creationCategory:_,visitTimeFrom:Q,visitTimeTo:j,customerName:W,interviewers:R,subject:p.title,content:g,externalComments:X?Te:[],isRead:a.isRead??!1,isStarred:a.isStarred??!1,labels:Re,postedComments:se.filter(U=>X||i!==void 0&&U.userId===i).map(U=>({...U,userId:c(U.userId),isMine:i?U.userId===i:!1})),attachments:a.attachments}},le=async(n,a)=>{let i=(0,s.aliasedTable)(K,"draft_label"),p=await ge();return(await e.select({reportHubId:u.id,businessDate:u.businessDate,sourceType:u.sourceType}).from(u).leftJoin(i,(0,s.and)((0,s.eq)(i.hubId,u.id),(0,s.inArray)(i.labelId,p))).where((0,s.and)((0,s.isNull)(u.deletedAt),(0,s.or)((0,s.eq)(u.userId,a),(0,s.isNull)(u.userId),(0,s.isNull)(i.hubId)),C(n.visible))).orderBy((0,s.desc)(u.businessDate),(0,s.desc)(u.id))).map(g=>({...g,businessDate:re(g.businessDate,"YYYY-MM-DD")}))},ne=async(n,a,i)=>{let p=await J(a);if(!p)return[];if(we(n.visible))return[];let b=(0,s.aliasedTable)(K,"draft_label"),g=await ge();return(await e.select({reportHubId:u.id,businessDate:u.businessDate,sourceType:u.sourceType}).top(i).from(u).leftJoin(b,(0,s.and)((0,s.eq)(b.hubId,u.id),(0,s.inArray)(b.labelId,g))).where((0,s.and)((0,s.isNull)(u.deletedAt),(0,s.or)((0,s.eq)(u.userId,p),(0,s.isNull)(u.userId),(0,s.isNull)(b.hubId)),C(n.visible))).orderBy((0,s.desc)(u.businessDate),(0,s.desc)(u.id))).map(T=>({...T,businessDate:re(T.businessDate,"YYYY-MM-DD")}))},ee=async(n,a)=>{let i=await Z(e.select({hub:Se(u),internal:Se(Y),creatorName:o.displayName,...O()}).from(u)).leftJoin(Y,(0,s.eq)(u.id,Y.hubId)).leftJoin(o,(0,s.eq)(u.userId,o.id)).where((0,s.and)((0,s.eq)(u.businessDate,s.sql`${a}`),(0,s.isNull)(u.deletedAt),C(n.visible))).orderBy((0,s.desc)(u.id)),p=await Ye(i.map(b=>b.hub.id));return i.map(b=>he(n,{...b,attachments:p.get(b.hub.id)??[]}))},G=n=>`${H}${n}`,x=new Map,J=async n=>{if(!t.disableUserIdCache&&x.has(n))return x.get(n)??null;let a=await d(n);return a!==null&&!t.disableUserIdCache&&x.set(n,a),a},ue=async(n,a,{forceRefresh:i=!1,snapshot:p=!1,ttlMsOverride:b,onFetchStart:g}={})=>{let R=await J(a);if(!R)return[];if(we(n.visible))return[];let T=z(R,xe(n));return y.getOrFetch({cacheKey:T,fetcher:async()=>{let _=await le(n,R);return _t(_)?_:(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(qe))},onFetchStart:g,forceRefresh:i,snapshot:p,ttlMsOverride:b??Rt,epochKey:S,refreshAheadRatio:.5})},Ge=(n,a,{forceRefresh:i=!1,snapshot:p=!1,ttlMsOverride:b}={})=>{let g=ie(a);return g?we(n.visible)?Promise.resolve([]):y.getOrFetch({cacheKey:`${G(g)}:st:${xe(n)}`,fetcher:()=>ee(n,g),forceRefresh:i,snapshot:p,ttlMsOverride:b??E}):Promise.resolve([])},fe=null,Me=async()=>(fe!==null||(fe=(await e.select({id:V.id}).from(V).where((0,s.inArray)(V.name,ke)).orderBy(V.id)).map(a=>a.id)),fe),ge=async()=>{let n=await Me();return n.length>0?n:[-1]},Qe=async()=>{let n=await Me();if(n.length===0)return null;let[a]=await e.select({id:V.id}).top(1).from(V).where((0,s.eq)(V.name,Ee));return a?.id??n[0]},Yt=(n,a)=>a!=null?"absent":n!=null?"present":"unknown",Ye=async n=>{let a=new Map,i=r.attachment,p=t.attachmentIdCodec;if(n.length===0||!i||!p)return a;let b=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,s.inArray)(i.hubId,n)).orderBy((0,s.asc)(i.createdAt),(0,s.asc)(i.id));for(let g of b){let R={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:Yt(g.objectCheckedAt,g.objectMissingAt)},T=a.get(Number(g.hubId));T?T.push(R):a.set(Number(g.hubId),[R])}return a},Ft=async(n,a,i)=>{let p=r.attachment;if(!p||we(n.visible))return null;let b=await ge(),g=(0,s.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,s.eq)(u.id,p.hubId)).leftJoin(g,(0,s.and)((0,s.eq)(g.hubId,u.id),(0,s.inArray)(g.labelId,b))).where((0,s.and)((0,s.eq)(p.id,a),(0,s.isNull)(u.deletedAt),(0,s.or)((0,s.eq)(u.userId,i),(0,s.isNull)(g.hubId)),C(n.visible))))[0]??null},qt=async n=>{let a=r.attachment;if(!a)return;let i=new Date;try{await e.update(a).set({objectCheckedAt:i,objectMissingAt:i,updatedAt:i}).where((0,s.eq)(a.id,n))}catch(p){te.error("markAttachmentMissing failed",p)}},zt=async n=>{let a=r.attachment;if(!a)return;let i=new Date;try{await e.update(a).set({objectCheckedAt:i,objectMissingAt:null,updatedAt:i}).where((0,s.eq)(a.id,n))}catch(p){te.error("markAttachmentPresent failed",p)}},Vt=async(n,a,i,{forceRefresh:p=!1,snapshot:b=!1,ttlMsOverride:g}={})=>{let R=await J(i);if(!R)return[];let T=ie(a);if(!T)return[];if(we(n.visible))return[];let _=P(T,R,xe(n));return y.getOrFetch({cacheKey:_,fetcher:async()=>{let Q=await ge(),j=(0,s.aliasedTable)(K,"draft_label"),W=await Z(e.select({hub:Se(u),internal:Se(Y),isRead:F.isRead,isStarred:F.isStarred,creatorName:o.displayName,...O()}).from(u)).leftJoin(Y,(0,s.eq)(u.id,Y.hubId)).leftJoin(F,(0,s.and)((0,s.eq)(u.id,F.hubId),(0,s.eq)(F.userId,R))).leftJoin(j,(0,s.and)((0,s.eq)(j.hubId,u.id),(0,s.inArray)(j.labelId,Q))).leftJoin(o,(0,s.eq)(u.userId,o.id)).where((0,s.and)((0,s.eq)(u.businessDate,s.sql`${T}`),(0,s.isNull)(u.deletedAt),(0,s.or)((0,s.eq)(u.userId,R),(0,s.isNull)(j.hubId)),C(n.visible))).orderBy((0,s.desc)(u.id));if(W.length===0)return[];let ae=W.map(X=>X.hub.id),Te=await e.select({hubId:K.hubId,id:V.id,name:V.name,color:V.color}).from(K).innerJoin(V,(0,s.eq)(K.labelId,V.id)).where((0,s.inArray)(K.hubId,ae)),De=await e.select({hubId:h.hubId,id:h.id,body:h.body,createdAt:h.createdAt,userId:h.userId,userName:o.displayName}).from(h).leftJoin(o,(0,s.eq)(h.userId,o.id)).where((0,s.inArray)(h.hubId,ae)).orderBy((0,s.asc)(h.createdAt)),Ae=await Ye(ae),Re=new Map,se=new Map;for(let X of Te){let oe=Re.get(X.hubId);oe||(oe=[],Re.set(X.hubId,oe)),oe.push({id:X.id,name:X.name,color:X.color})}for(let X of De){let oe=se.get(X.hubId);oe||(oe=[],se.set(X.hubId,oe)),oe.push({id:X.id,content:X.body,createdAt:re(X.createdAt,"YYYY-MM-DD HH:mm:ss")||"",userId:X.userId,userName:X.userName||""})}return W.map(X=>{let oe=X.hub.id;return he(n,{...X,attachments:Ae.get(oe)??[],labels:Re.get(oe)||[],postedCommentRows:se.get(oe)||[]},R)})},forceRefresh:p,snapshot:b,ttlMsOverride:g??E,epochKey:`${A}${T}`})},Ne=async(n,a,i,{forceRefresh:p=!1,snapshot:b=!1,ttlMsOverride:g}={})=>{if(we(n.visible))return null;let R=M(a,i,xe(n));return(await y.getOrFetch({cacheKey:R,fetcher:async()=>{let _=await ge(),Q=(0,s.aliasedTable)(K,"draft_label"),j=await Z(e.select({hub:Se(u),internal:Se(Y),isRead:F.isRead,isStarred:F.isStarred,creatorName:o.displayName,...O()}).from(u)).leftJoin(Y,(0,s.eq)(u.id,Y.hubId)).leftJoin(F,(0,s.and)((0,s.eq)(u.id,F.hubId),(0,s.eq)(F.userId,i))).leftJoin(Q,(0,s.and)((0,s.eq)(Q.hubId,u.id),(0,s.inArray)(Q.labelId,_))).leftJoin(o,(0,s.eq)(u.userId,o.id)).where((0,s.and)((0,s.eq)(u.id,a),(0,s.isNull)(u.deletedAt),(0,s.or)((0,s.eq)(u.userId,i),(0,s.isNull)(Q.hubId)),C(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,s.eq)(K.labelId,V.id)).where((0,s.eq)(K.hubId,W)),Te=await e.select({id:h.id,body:h.body,createdAt:h.createdAt,userId:h.userId,userName:o.displayName}).from(h).leftJoin(o,(0,s.eq)(h.userId,o.id)).where((0,s.eq)(h.hubId,W)).orderBy((0,s.asc)(h.createdAt)),De=await Ye([W]),Ae=ae.map(se=>({id:se.id,name:se.name,color:se.color})),Re=Te.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[he(n,{...j[0],attachments:De.get(W)??[],labels:Ae,postedCommentRows:Re},i)]},forceRefresh:p,snapshot:b,ttlMsOverride:g??E,epochKey:`${f}${a}`}))[0]??null},Kt=async(n,a,i,p={})=>{let b=await J(i);return b?Ne(n,a,b,p):null},jt=async(n,a)=>{let i=await ge(),p=(0,s.aliasedTable)(K,"draft_label"),[b]=await e.select({sourceType:u.sourceType,deletedAt:u.deletedAt}).top(1).from(u).leftJoin(p,(0,s.and)((0,s.eq)(p.hubId,u.id),(0,s.inArray)(p.labelId,i))).where((0,s.and)((0,s.eq)(u.id,n),(0,s.or)((0,s.eq)(u.userId,a),(0,s.isNull)(p.hubId))));return b??null},Xe=async(n,a,i)=>{let p=await jt(a,i);if(!p||p.deletedAt||!be(n.visible,p.sourceType))throw new Error("Not Found")},Jt=async(n,a,i,p,b,g)=>{await Xe(n,i,a);let R=await e.select().top(1).from(F).where((0,s.and)((0,s.eq)(F.hubId,i),(0,s.eq)(F.userId,a))),T;if(R.length>0?R[0].isStarred!==b?T=(await e.update(F).set({isStarred:b,updatedAt:new Date,updatedBy:String(a)}).output().where((0,s.and)((0,s.eq)(F.hubId,i),(0,s.eq)(F.userId,a))))[0]:T=R[0]:T=(await e.insert(F).output().values({hubId:i,userId:a,isStarred:b,isRead:!1,createdAt:new Date,createdBy:String(a),updatedAt:new Date,updatedBy:String(a)}))[0],p){let _=ie(p);_&&(y.invalidatePrefix(N(_,a)),await I(`${A}${_}`))}return y.invalidate(`daily-report:detail:${i}`),y.invalidatePrefix($(i,a)),await I(`${f}${i}`),await L(ze.parse({type:"status-update",reportHubId:i,recipientRawUserId:a,statusType:"star",value:b,clientTempId:g}),"setStarStatus"),T},Gt=async(n,a,i,p,b,g)=>{await Xe(n,i,a);let R=await e.select().top(1).from(F).where((0,s.and)((0,s.eq)(F.hubId,i),(0,s.eq)(F.userId,a))),T;if(R.length>0?R[0].isRead!==b?T=(await e.update(F).set({isRead:b,updatedAt:new Date,updatedBy:String(a)}).output().where((0,s.and)((0,s.eq)(F.hubId,i),(0,s.eq)(F.userId,a))))[0]:T=R[0]:T=(await e.insert(F).output().values({hubId:i,userId:a,isRead:b,isStarred:!1,createdAt:new Date,createdBy:String(a),updatedAt:new Date,updatedBy:String(a)}))[0],p){let _=ie(p);_&&(y.invalidatePrefix(N(_,a)),await I(`${A}${_}`))}return y.invalidate(`daily-report:detail:${i}`),y.invalidatePrefix($(i,a)),await I(`${f}${i}`),await L(ze.parse({type:"status-update",reportHubId:i,recipientRawUserId:a,statusType:"read",value:b,clientTempId:g}),"setReadStatus"),T},Dt=async(n,a)=>{if(a===null)return;let i=await ge(),[p]=await e.select({hubId:K.hubId}).top(1).from(K).where((0,s.and)((0,s.eq)(K.hubId,n),(0,s.inArray)(K.labelId,i)));return p?a:void 0},Qt=async(n,a,i,p,b,g)=>{let[R]=await e.select({sourceType:u.sourceType,deletedAt:u.deletedAt,userId:u.userId}).top(1).from(u).where((0,s.eq)(u.id,i));if(!R||R.deletedAt)throw new Error("Not Found");if(await Xe(n,i,a),!be(n.commentable,R.sourceType))throw new Error("Comments are restricted by the viewer's comment permission");if(R.sourceType.toLowerCase()!=="internal")throw new Error("Comments are restricted for external daily report sources");let T=await Dt(i,R.userId),[_]=await e.insert(h).output().values({hubId:i,userId:a,body:p,createdAt:new Date,createdBy:String(a),updatedAt:new Date,updatedBy:String(a)}),[Q]=await e.select({displayName:o.displayName}).top(1).from(o).where((0,s.eq)(o.id,a)),j=Q?.displayName??"Unknown";if(b){let ae=ie(b);ae&&(y.invalidatePrefix(`daily-report:date:${ae}:user:`),await I(`${A}${ae}`))}y.invalidate(`daily-report:detail:${i}`),y.invalidatePrefix(`daily-report:detail:${i}:user:`),await I(`${f}${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 L(it.parse({type:"comment-add",reportHubId:i,comment:W,clientTempId:g,recipientRawUserId:T,sourceType:R.sourceType}),"addComment"),W},Xt=async(n,a)=>await n.select().top(1).from(h).where((0,s.eq)(h.id,a)),Wt=async(n,a,i,p,b,g)=>{let R=await Xt(e,p);if(R.length===0)throw new Error("Not Found");if(R[0].hubId!==i)throw new Error("Not Found");let[T]=await e.select({userId:u.userId,sourceType:u.sourceType}).top(1).from(u).where((0,s.eq)(u.id,R[0].hubId));if(!(T&&be(n.visible,T.sourceType)))throw new Error("Not Found");if(R[0].userId!==a)throw new Error("Unauthorized");let _=await Dt(i,T.userId);if(await e.delete(h).where((0,s.eq)(h.id,p)),b){let Q=ie(b);Q&&(y.invalidatePrefix(`daily-report:date:${Q}:user:`),await I(`${A}${Q}`))}y.invalidate(`daily-report:detail:${i}`),y.invalidatePrefix(`daily-report:detail:${i}:user:`),await I(`${f}${i}`),await L(lt.parse({type:"comment-delete",reportHubId:i,commentId:p,clientTempId:g,recipientRawUserId:_,sourceType:T?.sourceType}),"deleteComment")},Zt=async(n,a,i)=>{te.info("createDailyReport called",{userId:n,businessDate:a});let[p]=await e.select({displayName:o.displayName}).from(o).where((0,s.eq)(o.id,n)),b=p?.displayName??c(n);try{let g=await Je(async _=>{te.info("Starting transaction");let Q=`internal-temp-${Date.now()}-${Math.random()}`,[j]=await _.insert(u).output().values({sourceType:"Internal",sourceId:Q,businessDate:new Date(a),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,s.eq)(u.id,j.id)),te.info("Hub created",j),await _.insert(Y).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 Qe();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:Ee,color:null})),te.info("Label assigned"),{reportHubId:j.id,date:a,createdAt:re(j.createdAt,"YYYY-MM-DD HH:mm:ss"),author:b,userId:c(n),sourceType:"Internal",employeeName:b,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:[]}}),R=ie(a);R&&y.invalidatePrefix(N(R,n)),y.invalidatePrefix(H),y.invalidatePrefix(ce(n)),await I(S),R&&await I(`${A}${R}`);let T=await Ne(me.unrestricted("post-write self read: the writer always sees the row they just wrote"),g.reportHubId,n,{forceRefresh:!0});if(T){let _=await Me(),Q=T.labels.some(j=>_.includes(j.id));await L(ut.parse({type:"report-create",reportHubId:T.reportHubId,report:T,clientTempId:i,recipientRawUserId:Q?n:void 0}),"createDailyReport")}return T??g}catch(g){throw te.error("Error in createDailyReport",g),g}},Fe=async(n,a)=>await n.select().top(1).from(u).where((0,s.eq)(u.id,a)),We=async(n,a,i)=>{await n.update(u).set(i).where((0,s.eq)(u.id,a))},wt=async(n,a,i)=>{await n.update(Y).set(i).where((0,s.eq)(Y.hubId,a))},St=async(n,a,i)=>{await n.delete(K).where((0,s.and)((0,s.eq)(K.hubId,a),(0,s.eq)(K.labelId,i)))};return{streamKey:q,streamMaxLen:v,clearCache:async()=>{y.clearAll(),x.clear(),fe=null,k&&await I(S),te.info("[DailyReportService] Server-side DB/SQL caches cleared successfully.")},invalidateHubReadCaches:async(n,a)=>{y.invalidatePrefix(H),y.invalidatePrefix(Ie),await I(S);for(let i of new Set(n))y.invalidatePrefix(`daily-report:detail:${i}:user:`),await I(`${f}${i}`);for(let i of new Set(a)){let p=ie(i);p&&await I(`${A}${p}`)}},getUserIdByExternalId:J,getDailyReportIdsByExternalId:ue,getDailyReportIdsFirstPageByExternalId:ne,getDailyReportsByBusinessDate:Ge,getDailyReportsByBusinessDateByExternalId:Vt,getDailyReportDetailById:Ne,getDailyReportDetailByIdByExternalId:Kt,getDraftLabelId:Qe,getAttachmentsByHubIds:Ye,getAttachmentForUser:Ft,markAttachmentMissing:qt,markAttachmentPresent:zt,setStarStatus:Jt,setReadStatus:Gt,addComment:Qt,deleteComment:Wt,createDailyReport:Zt,updateDailyReport:async(n,a,i,p)=>{let b=await Fe(e,n);if(!b.length||b[0].deletedAt)throw new Error("Not Found");if(b[0].userId!==a)throw new Error("Unauthorized");await Je(async T=>{i.title!==void 0&&await We(T,n,{title:i.title,updatedAt:new Date,updatedBy:String(a)}),i.content!==void 0&&await wt(T,n,{body:i.content,updatedAt:new Date,updatedBy:String(a)})}),y.invalidate(`daily-report:detail:${n}`),y.invalidatePrefix(`daily-report:detail:${n}:user:`),y.invalidatePrefix(H),await I(`${f}${n}`);let g=ie(re(b[0].businessDate,"YYYY-MM-DD"));g&&(y.invalidatePrefix(`daily-report:date:${g}:user:`),await I(`${A}${g}`));let R=await Ne(me.unrestricted("post-write self read: the writer always sees the row they just wrote"),n,a,{forceRefresh:!0});if(R){let T=await Me(),_=R.labels.some(Q=>T.includes(Q.id));await L(dt.parse({type:"report-update",reportHubId:R.reportHubId,report:R,clientTempId:p,recipientRawUserId:_?a:void 0}),"updateDailyReport")}},publishDailyReport:async(n,a,i)=>{let p=await Fe(e,n);if(!p.length)throw new Error("Not Found");if(p[0].userId!==a)throw new Error("Unauthorized");let b=await Qe();if(!b)return null;if(await St(e,n,b),y.invalidatePrefix(`daily-report:detail:${n}:user:`),y.invalidatePrefix(H),y.invalidatePrefix(Ie),await I(S),p[0].businessDate){let T=ie(re(p[0].businessDate,"YYYY-MM-DD"));T&&await I(`${A}${T}`)}let g=ie(re(p[0].businessDate,"YYYY-MM-DD"));g&&y.invalidatePrefix(N(g,a));let R=await Ne(me.unrestricted("post-write self read: the writer always sees the row they just wrote"),n,a,{forceRefresh:!0});return R&&await L(ct.parse({type:"report-publish",reportHubId:R.reportHubId,report:R,clientTempId:i}),"publishDailyReport"),R??null},deleteDailyReport:async(n,a,i)=>{let p=await Fe(e,n);if(!p.length||p[0].deletedAt)throw new Error("Not Found");if(p[0].userId!==a)throw new Error("Unauthorized");if(await We(e,n,{deletedAt:new Date,deletedBy:String(a),updatedAt:new Date,updatedBy:String(a)}),y.invalidatePrefix(`daily-report:detail:${n}:user:`),y.invalidatePrefix(H),y.invalidatePrefix(Ie),await I(S),p[0].businessDate){let b=ie(re(p[0].businessDate,"YYYY-MM-DD"));b&&await I(`${A}${b}`)}await L(pt.parse({type:"report-delete",reportHubId:n,clientTempId:i,sourceType:p[0].sourceType}),"deleteDailyReport")},findDailyReportHubById:Fe,updateDailyReportHub:We,updateDailyReportInternal:wt,deleteDailyReportLabel:St}}var He=require("drizzle-orm");function Ot(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 o of r){let c=`daily_report_${o.key.toLowerCase().replace(/[^a-z0-9_]/g,"_")}`;e.push({resourceKey:c,name:o.name,description:o.description??`${o.name} daily report access`}),o.includeCommentResource!==!1&&e.push({resourceKey:`${c}_comment`,name:`${o.name} Comment`,description:`${o.name} daily report comment access`})}return e}async function qr(t,e,r){let o=t,d=e.TMResource,c=r.appKey,D=r.actor??"system:daily-report",y=new Date,k=r.resources??Ot(r.sources);for(let u of k){let Y=await o.select().from(d).where((0,He.and)((0,He.eq)(d.appKey,c),(0,He.eq)(d.resourceKey,u.resourceKey)));(!Y||Y.length===0)&&await o.insert(d).values({appKey:c,resourceKey:u.resourceKey,name:u.name,description:u.description??null,createdAt:y,createdBy:D,updatedAt:y,updatedBy:D})}}var zr=de(1,"[DailyReportExternalSource]"),Vr=(t,e,r,o=zr)=>{if(!t)return[];try{let d=JSON.parse(t);return Array.isArray(d)?d.map(r).filter(c=>c!==null):(o.warn(`Unexpected ${e} format: not an array`),[])}catch(d){return o.warn(`Failed to parse ${e}:`,d),[]}};var Oe=require("drizzle-orm"),l=require("drizzle-orm/mssql-core");function Kr(t,e){let r=(0,l.mssqlSchema)(t),o=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(Oe.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:[o.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,Oe.desc)(h.businessDate),(0,Oe.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]})]),D=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:[o.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:[o.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:[o.id]})]),Y=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:[o.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:D,attachment:Y,label:y,hubLabel:k,userStatus:u}}function jr(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 Pe({defaultTtlMs:t.cacheDefaultTtlMs??6e4},e),o=gt({...t,cache:r,epochs:e}),d=new $e({redis:t.redis,streamKey:o.streamKey,cache:r,logger:t.logger}),c=bt({authenticate:t.authenticate,resolveVisibleSourceTypes:t.resolveVisibleSourceTypes,service:o,encodeUserId:t.encodeUserId,attachmentIdCodec:t.attachmentIdCodec,readAttachment:t.readAttachment,attachmentMaxBytes:t.attachmentMaxBytes,attachmentRateLimitPerMinute:t.attachmentRateLimitPerMinute,attachmentConcurrency:t.attachmentConcurrency,redis:t.redis,sseReader:d,streamKey:o.streamKey,loginRedirectPath:t.loginRedirectPath,enableDevCacheClear:t.enableDevCacheClear,logger:t.logger});return{service:o,cache:r,epochs:e,sseReader:d,streamKey:o.streamKey,knownSourceTypes:[...new Set(["Internal",...(t.externalSources??[]).map(D=>D.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