entity-client 1.0.26 → 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/base.js +1 -1
- package/dist/client/base.js.map +3 -3
- package/dist/client/request.d.ts +12 -0
- package/dist/client/request.js +1 -1
- package/dist/client/request.js.map +3 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +3 -3
- package/dist/react.js +1 -1
- package/dist/react.js.map +3 -3
- package/dist/types.d.ts +8 -1
- package/package.json +1 -1
package/dist/client/base.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readEnv as m}from"./utils.js";import{derivePacketKey as u,parseRequestBody as f}from"./packet.js";import{entityRequest as l}from"./request.js";const c="/v1/realtime";class T{baseUrl;token;anonymousPacketToken;apiKey;hmacSecret;encryptRequests;debugPlainSecret;csrfEnabled;csrfHeaderName;csrfCookieName;csrfRefresher=null;requestAbortControllers=new Map;activeTxId=null;initialHealthFired=!1;keepSession;refreshBuffer;onTokenRefreshed;onSessionExpired;onHealthChange;sessionRefreshToken=null;refreshTimer=null;healthTickTimer=null;healthTickPromise=null;realtimeEnabled;realtimePath;realtimeAutoReconnect;realtimeReconnectDelayMs;realtimeStatus;realtimeSocket=null;realtimeConnectPromise=null;realtimeReconnectTimer=null;realtimeShouldReconnect=!1;realtimeMessageListeners=new Set;realtimeStatusListeners=new Set;realtimeEventListeners=new Map;constructor(e={}){const t=m("VITE_ENTITY_SERVER_URL");this.baseUrl=(e.baseUrl??t??"").replace(/\/$/,""),this.token=e.token??"",this.anonymousPacketToken=e.anonymousPacketToken??"",this.apiKey=e.apiKey??"",this.hmacSecret=e.hmacSecret??"",this.encryptRequests=e.encryptRequests??!1,this.debugPlainSecret=e.debugPlainSecret??"",this.csrfEnabled=e.csrfEnabled??!1,this.csrfHeaderName=e.csrfHeaderName??"x-csrf-token",this.csrfCookieName=e.csrfCookieName??"_csrf",this.keepSession=e.keepSession??!1,this.refreshBuffer=e.refreshBuffer??60,this.onTokenRefreshed=e.onTokenRefreshed,this.onSessionExpired=e.onSessionExpired,this.onHealthChange=e.onHealthChange,this.realtimeEnabled=!1,this.realtimePath=c,this.realtimeAutoReconnect=!0,this.realtimeReconnectDelayMs=3e3,this.realtimeStatus="idle",this.applyRealtimeOptions(e.realtime),typeof e.healthTickInterval=="number"&&e.healthTickInterval>0&&Promise.resolve().then(()=>this.startHealthTick(e.healthTickInterval,!1)),this.fireInitialHealth()}configure(e){typeof e.baseUrl=="string"&&(this.baseUrl=e.baseUrl.replace(/\/$/,"")),typeof e.token=="string"&&(this.token=e.token),typeof e.anonymousPacketToken=="string"&&(this.anonymousPacketToken=e.anonymousPacketToken),typeof e.encryptRequests=="boolean"&&(this.encryptRequests=e.encryptRequests),typeof e.debugPlainSecret=="string"&&(this.debugPlainSecret=e.debugPlainSecret),typeof e.csrfEnabled=="boolean"&&(this.csrfEnabled=e.csrfEnabled),typeof e.csrfHeaderName=="string"&&(this.csrfHeaderName=e.csrfHeaderName),typeof e.csrfCookieName=="string"&&(this.csrfCookieName=e.csrfCookieName),typeof e.apiKey=="string"&&(this.apiKey=e.apiKey),typeof e.hmacSecret=="string"&&(this.hmacSecret=e.hmacSecret),typeof e.keepSession=="boolean"&&(this.keepSession=e.keepSession),typeof e.refreshBuffer=="number"&&(this.refreshBuffer=e.refreshBuffer),e.onTokenRefreshed&&(this.onTokenRefreshed=e.onTokenRefreshed),e.onSessionExpired&&(this.onSessionExpired=e.onSessionExpired),e.onHealthChange&&(this.onHealthChange=e.onHealthChange),typeof e.realtime<"u"&&this.applyRealtimeOptions(e.realtime),typeof e.healthTickInterval=="number"&&e.healthTickInterval>0&&Promise.resolve().then(()=>this.startHealthTick(e.healthTickInterval,!1)),this.fireInitialHealth()}fireInitialHealth(){if(this.initialHealthFired||typeof document>"u"||!this.baseUrl)return;this.initialHealthFired=!0;const e=this;typeof e.checkHealth=="function"&&Promise.resolve().then(()=>e.checkHealth(!1).catch(()=>{}))}setToken(e){this.token=e,this.syncRealtimeWithToken()}setAccessTokenFromResponse(e){this.token=e,this.syncRealtimeWithToken()}syncRealtimeWithToken(){if(!this.token){this.disconnectRealtime("token_cleared");return}!this.realtimeEnabled||typeof WebSocket>"u"||this.connectRealtime().catch(()=>{})}setAnonymousPacketToken(e){this.anonymousPacketToken=e}setApiKey(e){this.apiKey=e}setHmacSecret(e){this.hmacSecret=e}setEncryptRequests(e){this.encryptRequests=e}setCsrfEnabled(e){this.csrfEnabled=e}addRealtimeListener(e){this.realtimeMessageListeners.add(e)}removeRealtimeListener(e){this.realtimeMessageListeners.delete(e)}addRealtimeStatusListener(e){this.realtimeStatusListeners.add(e)}removeRealtimeStatusListener(e){this.realtimeStatusListeners.delete(e)}addRealtimeEventListener(e,t){const i=String(e).trim();i&&(this.realtimeEventListeners.has(i)||this.realtimeEventListeners.set(i,new Set),this.realtimeEventListeners.get(i).add(t))}removeRealtimeEventListener(e,t){const i=String(e).trim();if(!i)return;const s=this.realtimeEventListeners.get(i);s&&(s.delete(t),s.size===0&&this.realtimeEventListeners.delete(i))}async connectRealtime(){if(!this.realtimeEnabled){this.setRealtimeStatus("disabled","realtime_disabled");return}if(!this.token)throw new Error("Cannot open realtime connection without access token.");if(typeof WebSocket>"u")throw new Error("WebSocket is not available in this environment.");if(this.realtimeSocket&&this.realtimeSocket.readyState===WebSocket.OPEN)return;if(this.realtimeSocket&&this.realtimeSocket.readyState===WebSocket.CONNECTING&&this.realtimeConnectPromise)return this.realtimeConnectPromise;this.clearRealtimeReconnectTimer(),this.realtimeShouldReconnect=this.realtimeAutoReconnect,this.setRealtimeStatus("connecting","connect_requested");const e=new WebSocket(this.buildRealtimeUrl());return this.realtimeSocket=e,this.realtimeConnectPromise=new Promise((t,i)=>{let s=!1;const r=()=>{s||(s=!0,this.realtimeConnectPromise=null,t())},n=a=>{s||(s=!0,this.realtimeConnectPromise=null,i(a))};e.addEventListener("open",()=>{this.setRealtimeStatus("open","socket_open"),r()}),e.addEventListener("message",a=>{this.handleRealtimeMessage(a.data)}),e.addEventListener("error",()=>{this.setRealtimeStatus("closed","socket_error",new Error("Realtime socket error."))}),e.addEventListener("close",a=>{this.realtimeSocket===e&&(this.realtimeSocket=null);const o=a.reason||"socket_closed",h=new Error(`Realtime socket closed (${a.code}${a.reason?`: ${a.reason}`:""}).`);this.setRealtimeStatus("closed",o,h),s||n(h),this.realtimeShouldReconnect&&this.realtimeEnabled&&this.realtimeAutoReconnect&&this.token&&this.scheduleRealtimeReconnect(o)})}),this.realtimeConnectPromise}disconnectRealtime(e="client_disconnect"){if(this.realtimeShouldReconnect=!1,this.clearRealtimeReconnectTimer(),this.realtimeSocket){const t=this.realtimeSocket;this.realtimeSocket=null;try{(t.readyState===WebSocket.OPEN||t.readyState===WebSocket.CONNECTING)&&t.close(1e3,e)}catch{}}this.realtimeConnectPromise=null,this.setRealtimeStatus(this.realtimeEnabled?"idle":"disabled",e)}sendRealtime(e){return!this.realtimeSocket||this.realtimeSocket.readyState!==WebSocket.OPEN?!1:(this.realtimeSocket.send(JSON.stringify(e)),!0)}subscribeRealtime(e){return this.sendRealtime({type:"subscribe",channel:"session",event:"session.subscribe",data:{subscriptions:e}})}unsubscribeRealtime(e){return this.sendRealtime({type:"unsubscribe",channel:"session",event:"session.unsubscribe",data:{subscriptions:e}})}startHealthTick(e=300*1e3,t=!0){this.stopHealthTick();const i=()=>{this.healthTickPromise||(this.healthTickPromise=(this.csrfRefresher?this.csrfRefresher():Promise.resolve()).then(()=>{this.onHealthChange?.(!0)}).catch(()=>{this.onHealthChange?.(!1)}).finally(()=>{this.healthTickPromise=null}))};t&&i(),this.healthTickTimer=setInterval(i,e)}stopHealthTick(){this.healthTickTimer!==null&&(clearInterval(this.healthTickTimer),this.healthTickTimer=null),this.healthTickPromise=null}scheduleKeepSession(e,t,i){this.clearRefreshTimer(),this.sessionRefreshToken=e;const s=Math.max((t-this.refreshBuffer)*1e3,0);this.refreshTimer=setTimeout(async()=>{if(this.sessionRefreshToken)try{const r=await i(this.sessionRefreshToken);this.onTokenRefreshed?.(r.access_token,r.expires_in),this.scheduleKeepSession(this.sessionRefreshToken,r.expires_in,i)}catch(r){this.clearRefreshTimer(),this.onSessionExpired?.(r instanceof Error?r:new Error(String(r)))}},s)}clearRefreshTimer(){this.refreshTimer!==null&&(clearTimeout(this.refreshTimer),this.refreshTimer=null)}stopKeepSession(){this.clearRefreshTimer(),this.sessionRefreshToken=null}applyRealtimeOptions(e){const t=typeof e=="boolean"?{enabled:e}:e??{};if(this.realtimeEnabled=t.enabled??!1,this.realtimePath=String(t.path??c).trim()||c,this.realtimeAutoReconnect=t.autoReconnect??!0,this.realtimeReconnectDelayMs=Math.max(250,t.reconnectDelayMs??3e3),!this.realtimeEnabled){this.disconnectRealtime("realtime_disabled");return}this.setRealtimeStatus("idle","realtime_enabled")}buildRealtimeUrl(){const e=this.baseUrl||m("VITE_ENTITY_SERVER_URL")||"",t=typeof window<"u"?window.location.origin:"",i=e||t;if(!i)throw new Error("Realtime connection requires baseUrl.");const s=new URL(i,t||void 0),r=s.pathname==="/"?"":s.pathname.replace(/\/+$/,""),n=`/${this.realtimePath.replace(/^\/+/,"")}`;return s.pathname=`${r}${n}`||n,s.search="",s.hash="",s.protocol=s.protocol==="https:"?"wss:":"ws:",s.searchParams.set("access_token",this.token),s.toString()}handleRealtimeMessage(e){if(typeof e!="string")return;let t;try{t=JSON.parse(e)}catch{return}for(const s of this.realtimeMessageListeners)s(t);const i=this.realtimeEventListeners.get(t.event);if(i)for(const s of i)s(t)}scheduleRealtimeReconnect(e){this.clearRealtimeReconnectTimer(),this.realtimeReconnectTimer=setTimeout(()=>{this.realtimeReconnectTimer=null,!(!this.realtimeEnabled||!this.token)&&(this.setRealtimeStatus("connecting",`${e}:reconnect`),this.connectRealtime().catch(()=>{}))},this.realtimeReconnectDelayMs)}clearRealtimeReconnectTimer(){this.realtimeReconnectTimer!==null&&(clearTimeout(this.realtimeReconnectTimer),this.realtimeReconnectTimer=null)}setRealtimeStatus(e,t,i){const s=this.realtimeStatus;if(!(s===e&&typeof t>"u"&&typeof i>"u")){this.realtimeStatus=e;for(const r of this.realtimeStatusListeners)r({status:e,previousStatus:s,...t?{reason:t}:{},...i?{error:i}:{}})}}applyCsrfHealth(){if(!(typeof document>"u")){for(const e of document.cookie.split(";")){const t=e.indexOf("=");if(!(t<0)&&e.substring(0,t).trim()===this.csrfCookieName){this.csrfEnabled=!!e.substring(t+1).trim();return}}this.csrfEnabled=!1}}readRequestBody(e,t="application/json",i=!1){const s=u(this.hmacSecret,this.token||this.anonymousPacketToken);return f(e,t,i,s)}get reqOpts(){return{baseUrl:this.baseUrl,token:this.token,anonymousPacketToken:this.anonymousPacketToken,apiKey:this.apiKey,hmacSecret:this.hmacSecret,encryptRequests:this.encryptRequests,csrfEnabled:this.csrfEnabled,csrfHeaderName:this.csrfHeaderName,csrfCookieName:this.csrfCookieName,refreshCsrfCookie:this.csrfEnabled?this.csrfRefresher:null,requestAbortControllers:this.requestAbortControllers,debugPlainSecret:this.debugPlainSecret,onAccessToken:e=>{this.setAccessTokenFromResponse(e)}}}prepareRequest(e){return Promise.resolve()}get http(){const e=this;return{get(t,i=!0,s,r){return e.prepareRequest(i).then(()=>l(e.reqOpts,"GET",t,void 0,i,s,r??!0))},post(t,i,s=!0,r,n){return e.prepareRequest(s).then(()=>l(e.reqOpts,"POST",t,i,s,r,n??!0))},put(t,i,s=!0,r,n){return e.prepareRequest(s).then(()=>l(e.reqOpts,"PUT",t,i,s,r,n??!0))},patch(t,i,s=!0,r,n){return e.prepareRequest(s).then(()=>l(e.reqOpts,"PATCH",t,i,s,r,n??!0))},delete(t,i,s=!0,r,n){return e.prepareRequest(s).then(()=>l(e.reqOpts,"DELETE",t,i,s,r,n??!0))}}}request(e,t,i,s=!0,r,n){return this.prepareRequest(s).then(()=>l(this.reqOpts,e,t,i,s,r,n??!0))}async requestBinary(e,t,i,s=!0){await this.prepareRequest(s);const r={"Content-Type":"application/json"};s&&this.token&&(r.Authorization=`Bearer ${this.token}`),this.apiKey&&(r["X-API-Key"]=this.apiKey);const n=await fetch(this.baseUrl+t,{method:e,headers:r,...i!=null?{body:JSON.stringify(i)}:{},credentials:"include"});if(!n.ok){const a=await n.text(),o=new Error(`HTTP ${n.status}: ${a}`);throw o.status=n.status,o}return n.arrayBuffer()}async requestForm(e,t,i,s=!0){const r={};s&&this.token&&(r.Authorization=`Bearer ${this.token}`),this.apiKey&&(r["X-API-Key"]=this.apiKey);const n=await fetch(this.baseUrl+t,{method:e,headers:r,body:i,credentials:"include"}),a=await n.json();if(!a.ok){const o=new Error(a.message??`EntityServer error (HTTP ${n.status})`);throw o.status=n.status,o}return a}async requestFormBinary(e,t,i,s=!0){const r={};s&&this.token&&(r.Authorization=`Bearer ${this.token}`),this.apiKey&&(r["X-API-Key"]=this.apiKey);const n=await fetch(this.baseUrl+t,{method:e,headers:r,body:i,credentials:"include"});if(!n.ok){const a=await n.text(),o=new Error(`HTTP ${n.status}: ${a}`);throw o.status=n.status,o}return n.arrayBuffer()}}export{T as EntityServerClientBase};
|
|
1
|
+
import{readEnv as m}from"./utils.js";import{derivePacketKey as u,parseRequestBody as f}from"./packet.js";import{entityRequest as l,requestFormData as d}from"./request.js";const c="/v1/realtime";class g{baseUrl;token;anonymousPacketToken;apiKey;hmacSecret;encryptRequests;debugPlainSecret;csrfEnabled;csrfHeaderName;csrfCookieName;csrfRefresher=null;requestAbortControllers=new Map;activeTxId=null;initialHealthFired=!1;keepSession;refreshBuffer;onTokenRefreshed;onSessionExpired;onHealthChange;sessionRefreshToken=null;refreshTimer=null;healthTickTimer=null;healthTickPromise=null;realtimeEnabled;realtimePath;realtimeAutoReconnect;realtimeReconnectDelayMs;realtimeStatus;realtimeSocket=null;realtimeConnectPromise=null;realtimeReconnectTimer=null;realtimeShouldReconnect=!1;realtimeMessageListeners=new Set;realtimeStatusListeners=new Set;realtimeEventListeners=new Map;constructor(e={}){const t=m("VITE_ENTITY_SERVER_URL");this.baseUrl=(e.baseUrl??t??"").replace(/\/$/,""),this.token=e.token??"",this.anonymousPacketToken=e.anonymousPacketToken??"",this.apiKey=e.apiKey??"",this.hmacSecret=e.hmacSecret??"",this.encryptRequests=e.encryptRequests??!1,this.debugPlainSecret=e.debugPlainSecret??"",this.csrfEnabled=e.csrfEnabled??!1,this.csrfHeaderName=e.csrfHeaderName??"x-csrf-token",this.csrfCookieName=e.csrfCookieName??"_csrf",this.keepSession=e.keepSession??!1,this.refreshBuffer=e.refreshBuffer??60,this.onTokenRefreshed=e.onTokenRefreshed,this.onSessionExpired=e.onSessionExpired,this.onHealthChange=e.onHealthChange,this.realtimeEnabled=!1,this.realtimePath=c,this.realtimeAutoReconnect=!0,this.realtimeReconnectDelayMs=3e3,this.realtimeStatus="idle",this.applyRealtimeOptions(e.realtime),typeof e.healthTickInterval=="number"&&e.healthTickInterval>0&&Promise.resolve().then(()=>this.startHealthTick(e.healthTickInterval,!1)),this.fireInitialHealth()}configure(e){typeof e.baseUrl=="string"&&(this.baseUrl=e.baseUrl.replace(/\/$/,"")),typeof e.token=="string"&&(this.token=e.token),typeof e.anonymousPacketToken=="string"&&(this.anonymousPacketToken=e.anonymousPacketToken),typeof e.encryptRequests=="boolean"&&(this.encryptRequests=e.encryptRequests),typeof e.debugPlainSecret=="string"&&(this.debugPlainSecret=e.debugPlainSecret),typeof e.csrfEnabled=="boolean"&&(this.csrfEnabled=e.csrfEnabled),typeof e.csrfHeaderName=="string"&&(this.csrfHeaderName=e.csrfHeaderName),typeof e.csrfCookieName=="string"&&(this.csrfCookieName=e.csrfCookieName),typeof e.apiKey=="string"&&(this.apiKey=e.apiKey),typeof e.hmacSecret=="string"&&(this.hmacSecret=e.hmacSecret),typeof e.keepSession=="boolean"&&(this.keepSession=e.keepSession),typeof e.refreshBuffer=="number"&&(this.refreshBuffer=e.refreshBuffer),e.onTokenRefreshed&&(this.onTokenRefreshed=e.onTokenRefreshed),e.onSessionExpired&&(this.onSessionExpired=e.onSessionExpired),e.onHealthChange&&(this.onHealthChange=e.onHealthChange),typeof e.realtime<"u"&&this.applyRealtimeOptions(e.realtime),typeof e.healthTickInterval=="number"&&e.healthTickInterval>0&&Promise.resolve().then(()=>this.startHealthTick(e.healthTickInterval,!1)),this.fireInitialHealth()}fireInitialHealth(){if(this.initialHealthFired||typeof document>"u"||!this.baseUrl)return;this.initialHealthFired=!0;const e=this;typeof e.checkHealth=="function"&&Promise.resolve().then(()=>e.checkHealth(!1).catch(()=>{}))}setToken(e){this.token=e,this.syncRealtimeWithToken()}setAccessTokenFromResponse(e){this.token=e,this.syncRealtimeWithToken()}syncRealtimeWithToken(){if(!this.token){this.disconnectRealtime("token_cleared");return}!this.realtimeEnabled||typeof WebSocket>"u"||this.connectRealtime().catch(()=>{})}setAnonymousPacketToken(e){this.anonymousPacketToken=e}setApiKey(e){this.apiKey=e}setHmacSecret(e){this.hmacSecret=e}setEncryptRequests(e){this.encryptRequests=e}setCsrfEnabled(e){this.csrfEnabled=e}addRealtimeListener(e){this.realtimeMessageListeners.add(e)}removeRealtimeListener(e){this.realtimeMessageListeners.delete(e)}addRealtimeStatusListener(e){this.realtimeStatusListeners.add(e)}removeRealtimeStatusListener(e){this.realtimeStatusListeners.delete(e)}addRealtimeEventListener(e,t){const s=String(e).trim();s&&(this.realtimeEventListeners.has(s)||this.realtimeEventListeners.set(s,new Set),this.realtimeEventListeners.get(s).add(t))}removeRealtimeEventListener(e,t){const s=String(e).trim();if(!s)return;const i=this.realtimeEventListeners.get(s);i&&(i.delete(t),i.size===0&&this.realtimeEventListeners.delete(s))}async connectRealtime(){if(!this.realtimeEnabled){this.setRealtimeStatus("disabled","realtime_disabled");return}if(!this.token)throw new Error("Cannot open realtime connection without access token.");if(typeof WebSocket>"u")throw new Error("WebSocket is not available in this environment.");if(this.realtimeSocket&&this.realtimeSocket.readyState===WebSocket.OPEN)return;if(this.realtimeSocket&&this.realtimeSocket.readyState===WebSocket.CONNECTING&&this.realtimeConnectPromise)return this.realtimeConnectPromise;this.clearRealtimeReconnectTimer(),this.realtimeShouldReconnect=this.realtimeAutoReconnect,this.setRealtimeStatus("connecting","connect_requested");const e=new WebSocket(this.buildRealtimeUrl());return this.realtimeSocket=e,this.realtimeConnectPromise=new Promise((t,s)=>{let i=!1;const r=()=>{i||(i=!0,this.realtimeConnectPromise=null,t())},n=a=>{i||(i=!0,this.realtimeConnectPromise=null,s(a))};e.addEventListener("open",()=>{this.setRealtimeStatus("open","socket_open"),r()}),e.addEventListener("message",a=>{this.handleRealtimeMessage(a.data)}),e.addEventListener("error",()=>{this.setRealtimeStatus("closed","socket_error",new Error("Realtime socket error."))}),e.addEventListener("close",a=>{this.realtimeSocket===e&&(this.realtimeSocket=null);const o=a.reason||"socket_closed",h=new Error(`Realtime socket closed (${a.code}${a.reason?`: ${a.reason}`:""}).`);this.setRealtimeStatus("closed",o,h),i||n(h),this.realtimeShouldReconnect&&this.realtimeEnabled&&this.realtimeAutoReconnect&&this.token&&this.scheduleRealtimeReconnect(o)})}),this.realtimeConnectPromise}disconnectRealtime(e="client_disconnect"){if(this.realtimeShouldReconnect=!1,this.clearRealtimeReconnectTimer(),this.realtimeSocket){const t=this.realtimeSocket;this.realtimeSocket=null;try{(t.readyState===WebSocket.OPEN||t.readyState===WebSocket.CONNECTING)&&t.close(1e3,e)}catch{}}this.realtimeConnectPromise=null,this.setRealtimeStatus(this.realtimeEnabled?"idle":"disabled",e)}sendRealtime(e){return!this.realtimeSocket||this.realtimeSocket.readyState!==WebSocket.OPEN?!1:(this.realtimeSocket.send(JSON.stringify(e)),!0)}subscribeRealtime(e){return this.sendRealtime({type:"subscribe",channel:"session",event:"session.subscribe",data:{subscriptions:e}})}unsubscribeRealtime(e){return this.sendRealtime({type:"unsubscribe",channel:"session",event:"session.unsubscribe",data:{subscriptions:e}})}startHealthTick(e=300*1e3,t=!0){this.stopHealthTick();const s=()=>{this.healthTickPromise||(this.healthTickPromise=(this.csrfRefresher?this.csrfRefresher():Promise.resolve()).then(()=>{this.onHealthChange?.(!0)}).catch(()=>{this.onHealthChange?.(!1)}).finally(()=>{this.healthTickPromise=null}))};t&&s(),this.healthTickTimer=setInterval(s,e)}stopHealthTick(){this.healthTickTimer!==null&&(clearInterval(this.healthTickTimer),this.healthTickTimer=null),this.healthTickPromise=null}scheduleKeepSession(e,t,s){this.clearRefreshTimer(),this.sessionRefreshToken=e;const i=Math.max((t-this.refreshBuffer)*1e3,0);this.refreshTimer=setTimeout(async()=>{if(this.sessionRefreshToken)try{const r=await s(this.sessionRefreshToken);this.onTokenRefreshed?.(r.access_token,r.expires_in),this.scheduleKeepSession(this.sessionRefreshToken,r.expires_in,s)}catch(r){this.clearRefreshTimer(),this.onSessionExpired?.(r instanceof Error?r:new Error(String(r)))}},i)}clearRefreshTimer(){this.refreshTimer!==null&&(clearTimeout(this.refreshTimer),this.refreshTimer=null)}stopKeepSession(){this.clearRefreshTimer(),this.sessionRefreshToken=null}applyRealtimeOptions(e){const t=typeof e=="boolean"?{enabled:e}:e??{};if(this.realtimeEnabled=t.enabled??!1,this.realtimePath=String(t.path??c).trim()||c,this.realtimeAutoReconnect=t.autoReconnect??!0,this.realtimeReconnectDelayMs=Math.max(250,t.reconnectDelayMs??3e3),!this.realtimeEnabled){this.disconnectRealtime("realtime_disabled");return}this.setRealtimeStatus("idle","realtime_enabled")}buildRealtimeUrl(){const e=this.baseUrl||m("VITE_ENTITY_SERVER_URL")||"",t=typeof window<"u"?window.location.origin:"",s=e||t;if(!s)throw new Error("Realtime connection requires baseUrl.");const i=new URL(s,t||void 0),r=i.pathname==="/"?"":i.pathname.replace(/\/+$/,""),n=`/${this.realtimePath.replace(/^\/+/,"")}`;return i.pathname=`${r}${n}`||n,i.search="",i.hash="",i.protocol=i.protocol==="https:"?"wss:":"ws:",i.searchParams.set("access_token",this.token),i.toString()}handleRealtimeMessage(e){if(typeof e!="string")return;let t;try{t=JSON.parse(e)}catch{return}for(const i of this.realtimeMessageListeners)i(t);const s=this.realtimeEventListeners.get(t.event);if(s)for(const i of s)i(t)}scheduleRealtimeReconnect(e){this.clearRealtimeReconnectTimer(),this.realtimeReconnectTimer=setTimeout(()=>{this.realtimeReconnectTimer=null,!(!this.realtimeEnabled||!this.token)&&(this.setRealtimeStatus("connecting",`${e}:reconnect`),this.connectRealtime().catch(()=>{}))},this.realtimeReconnectDelayMs)}clearRealtimeReconnectTimer(){this.realtimeReconnectTimer!==null&&(clearTimeout(this.realtimeReconnectTimer),this.realtimeReconnectTimer=null)}setRealtimeStatus(e,t,s){const i=this.realtimeStatus;if(!(i===e&&typeof t>"u"&&typeof s>"u")){this.realtimeStatus=e;for(const r of this.realtimeStatusListeners)r({status:e,previousStatus:i,...t?{reason:t}:{},...s?{error:s}:{}})}}applyCsrfHealth(){if(!(typeof document>"u")){for(const e of document.cookie.split(";")){const t=e.indexOf("=");if(!(t<0)&&e.substring(0,t).trim()===this.csrfCookieName){this.csrfEnabled=!!e.substring(t+1).trim();return}}this.csrfEnabled=!1}}readRequestBody(e,t="application/json",s=!1){const i=u(this.hmacSecret,this.token||this.anonymousPacketToken);return f(e,t,s,i)}get reqOpts(){return{baseUrl:this.baseUrl,token:this.token,anonymousPacketToken:this.anonymousPacketToken,apiKey:this.apiKey,hmacSecret:this.hmacSecret,encryptRequests:this.encryptRequests,csrfEnabled:this.csrfEnabled,csrfHeaderName:this.csrfHeaderName,csrfCookieName:this.csrfCookieName,refreshCsrfCookie:this.csrfEnabled?this.csrfRefresher:null,requestAbortControllers:this.requestAbortControllers,debugPlainSecret:this.debugPlainSecret,onAccessToken:e=>{this.setAccessTokenFromResponse(e)}}}prepareRequest(e){return Promise.resolve()}get http(){const e=this;return{get(t,s=!0,i,r){return e.prepareRequest(s).then(()=>l(e.reqOpts,"GET",t,void 0,s,i,r??!0))},post(t,s,i=!0,r,n){return e.prepareRequest(i).then(()=>l(e.reqOpts,"POST",t,s,i,r,n??!0))},put(t,s,i=!0,r,n){return e.prepareRequest(i).then(()=>l(e.reqOpts,"PUT",t,s,i,r,n??!0))},patch(t,s,i=!0,r,n){return e.prepareRequest(i).then(()=>l(e.reqOpts,"PATCH",t,s,i,r,n??!0))},delete(t,s,i=!0,r,n){return e.prepareRequest(i).then(()=>l(e.reqOpts,"DELETE",t,s,i,r,n??!0))}}}request(e,t,s,i=!0,r,n){return this.prepareRequest(i).then(()=>l(this.reqOpts,e,t,s,i,r,n??!0))}async requestBinary(e,t,s,i=!0){await this.prepareRequest(i);const r={"Content-Type":"application/json"};i&&this.token&&(r.Authorization=`Bearer ${this.token}`),this.apiKey&&(r["X-API-Key"]=this.apiKey);const n=await fetch(this.baseUrl+t,{method:e,headers:r,...s!=null?{body:JSON.stringify(s)}:{},credentials:"include"});if(!n.ok){const a=await n.text(),o=new Error(`HTTP ${n.status}: ${a}`);throw o.status=n.status,o}return n.arrayBuffer()}async requestForm(e,t,s,i=!0){return await this.prepareRequest(i),d(this.reqOpts,e,t,s,i)}async requestFormBinary(e,t,s,i=!0){const r={};i&&this.token&&(r.Authorization=`Bearer ${this.token}`),this.apiKey&&(r["X-API-Key"]=this.apiKey);const n=await fetch(this.baseUrl+t,{method:e,headers:r,body:s,credentials:"include"});if(!n.ok){const a=await n.text(),o=new Error(`HTTP ${n.status}: ${a}`);throw o.status=n.status,o}return n.arrayBuffer()}}export{g as EntityServerClientBase};
|
|
2
2
|
//# sourceMappingURL=base.js.map
|
package/dist/client/base.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/client/base.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n EntityServerClientOptions,\n RealtimeClientOptions,\n RealtimeConnectionStatus,\n RealtimeEnvelope,\n RealtimeMessageListener,\n RealtimeStatusListener,\n} from \"../types.js\";\nimport { readEnv } from \"./utils.js\";\nimport { derivePacketKey, parseRequestBody } from \"./packet.js\";\nimport {\n entityRequest,\n type EntityRequestConfig,\n type RequestOptions,\n} from \"./request.js\";\n\nconst REALTIME_DEFAULT_PATH = \"/v1/realtime\";\n\n// mixin \uD5EC\uD37C \uD0C0\uC785\nexport type GConstructor<T = object> = new (...args: any[]) => T;\n\nexport class EntityServerClientBase {\n baseUrl: string;\n token: string;\n anonymousPacketToken: string;\n apiKey: string;\n hmacSecret: string;\n encryptRequests: boolean;\n /** dev \uB514\uBC84\uADF8 \uD3C9\uBB38 \uC2DC\uD06C\uB9BF. \uC124\uC815 \uC2DC \uC694\uCCAD\uC744 \uD3C9\uBB38 \uC804\uC1A1\uD558\uACE0 `X-Debug-Plain` \uD5E4\uB354\uB97C \uBCF4\uB0B8\uB2E4. */\n debugPlainSecret: string;\n csrfEnabled: boolean;\n csrfHeaderName: string;\n csrfCookieName: string;\n /** @internal health \uC7AC\uD638\uCD9C\uB85C CSRF \uCFE0\uD0A4 \uAC31\uC2E0 (AuthMixin\uC5D0\uC11C \uC124\uC815) */\n csrfRefresher: (() => Promise<void>) | null = null;\n requestAbortControllers = new Map<string, AbortController>();\n activeTxId: string | null = null;\n /** @internal \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uCCAB \uAD6C\uC131 \uC2DC health 1\uD68C \uC790\uB3D9 \uD638\uCD9C\uD588\uB294\uC9C0 \uC5EC\uBD80 */\n initialHealthFired = false;\n\n // \uC138\uC158 \uC720\uC9C0 \uAD00\uB828\n keepSession: boolean;\n refreshBuffer: number;\n onTokenRefreshed?: (accessToken: string, expiresIn: number) => void;\n onSessionExpired?: (error: Error) => void;\n onHealthChange?: (online: boolean) => void;\n sessionRefreshToken: string | null = null;\n refreshTimer: ReturnType<typeof setTimeout> | null = null;\n healthTickTimer: ReturnType<typeof setInterval> | null = null;\n healthTickPromise: Promise<unknown> | null = null;\n realtimeEnabled: boolean;\n realtimePath: string;\n realtimeAutoReconnect: boolean;\n realtimeReconnectDelayMs: number;\n realtimeStatus: RealtimeConnectionStatus;\n realtimeSocket: WebSocket | null = null;\n realtimeConnectPromise: Promise<void> | null = null;\n realtimeReconnectTimer: ReturnType<typeof setTimeout> | null = null;\n realtimeShouldReconnect = false;\n realtimeMessageListeners = new Set<RealtimeMessageListener>();\n realtimeStatusListeners = new Set<RealtimeStatusListener>();\n realtimeEventListeners = new Map<string, Set<RealtimeMessageListener>>();\n // \u2500\u2500\u2500 \uCD08\uAE30\uD654 & \uC124\uC815 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * EntityServerClient \uC778\uC2A4\uD134\uC2A4\uB97C \uC0DD\uC131\uD569\uB2C8\uB2E4.\n *\n * \uAE30\uBCF8\uAC12:\n * - `baseUrl`: `VITE_ENTITY_SERVER_URL` \uB610\uB294 \uC0C1\uB300 \uACBD\uB85C(`\"\"`)\n */\n constructor(options: EntityServerClientOptions = {}) {\n const envBaseUrl = readEnv(\"VITE_ENTITY_SERVER_URL\");\n\n this.baseUrl = (options.baseUrl ?? envBaseUrl ?? \"\").replace(/\\/$/, \"\");\n this.token = options.token ?? \"\";\n this.anonymousPacketToken = options.anonymousPacketToken ?? \"\";\n this.apiKey = options.apiKey ?? \"\";\n this.hmacSecret = options.hmacSecret ?? \"\";\n this.encryptRequests = options.encryptRequests ?? false;\n this.debugPlainSecret = options.debugPlainSecret ?? \"\";\n this.csrfEnabled = options.csrfEnabled ?? false;\n this.csrfHeaderName = options.csrfHeaderName ?? \"x-csrf-token\";\n this.csrfCookieName = options.csrfCookieName ?? \"_csrf\";\n this.keepSession = options.keepSession ?? false;\n this.refreshBuffer = options.refreshBuffer ?? 60;\n this.onTokenRefreshed = options.onTokenRefreshed;\n this.onSessionExpired = options.onSessionExpired;\n this.onHealthChange = options.onHealthChange;\n this.realtimeEnabled = false;\n this.realtimePath = REALTIME_DEFAULT_PATH;\n this.realtimeAutoReconnect = true;\n this.realtimeReconnectDelayMs = 3000;\n this.realtimeStatus = \"idle\";\n this.applyRealtimeOptions(options.realtime);\n if (\n typeof options.healthTickInterval === \"number\" &&\n options.healthTickInterval > 0\n ) {\n // csrfRefresher\uB294 AuthMixin\uC5D0\uC11C \uC124\uC815\uB418\uBBC0\uB85C \uB2E4\uC74C tick\uC5D0 \uC2DC\uC791\n Promise.resolve().then(() =>\n this.startHealthTick(options.healthTickInterval, false),\n );\n }\n\n // baseUrl \uC774 \uC0DD\uC131 \uC2DC\uC810\uC5D0 \uC815\uD574\uC9C4 \uACBD\uC6B0(env \uB4F1) \uCCAB health \uB97C \uBCF4\uC7A5\uD55C\uB2E4.\n this.fireInitialHealth();\n }\n\n /** baseUrl, token, encryptRequests \uAC12\uC744 \uB7F0\uD0C0\uC784\uC5D0 \uAC31\uC2E0\uD569\uB2C8\uB2E4. */\n configure(options: Partial<EntityServerClientOptions>): void {\n if (typeof options.baseUrl === \"string\") {\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n }\n if (typeof options.token === \"string\") this.token = options.token;\n if (typeof options.anonymousPacketToken === \"string\") {\n this.anonymousPacketToken = options.anonymousPacketToken;\n }\n if (typeof options.encryptRequests === \"boolean\")\n this.encryptRequests = options.encryptRequests;\n if (typeof options.debugPlainSecret === \"string\")\n this.debugPlainSecret = options.debugPlainSecret;\n if (typeof options.csrfEnabled === \"boolean\") {\n this.csrfEnabled = options.csrfEnabled;\n }\n if (typeof options.csrfHeaderName === \"string\") {\n this.csrfHeaderName = options.csrfHeaderName;\n }\n if (typeof options.csrfCookieName === \"string\") {\n this.csrfCookieName = options.csrfCookieName;\n }\n if (typeof options.apiKey === \"string\") this.apiKey = options.apiKey;\n if (typeof options.hmacSecret === \"string\")\n this.hmacSecret = options.hmacSecret;\n if (typeof options.keepSession === \"boolean\")\n this.keepSession = options.keepSession;\n if (typeof options.refreshBuffer === \"number\")\n this.refreshBuffer = options.refreshBuffer;\n if (options.onTokenRefreshed)\n this.onTokenRefreshed = options.onTokenRefreshed;\n if (options.onSessionExpired)\n this.onSessionExpired = options.onSessionExpired;\n if (options.onHealthChange)\n this.onHealthChange = options.onHealthChange;\n if (typeof options.realtime !== \"undefined\") {\n this.applyRealtimeOptions(options.realtime);\n }\n if (\n typeof options.healthTickInterval === \"number\" &&\n options.healthTickInterval > 0\n ) {\n Promise.resolve().then(() =>\n this.startHealthTick(options.healthTickInterval, false),\n );\n }\n\n // \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C baseUrl \uC774 \uC815\uD574\uC9C0\uBA74 \uCCAB \uB9C8\uC6B4\uD2B8 \uC2DC health \uB97C 1\uD68C \uC790\uB3D9 \uD638\uCD9C\uD55C\uB2E4.\n this.fireInitialHealth();\n }\n\n /**\n * \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uD074\uB77C\uC774\uC5B8\uD2B8\uAC00 \uCC98\uC74C \uAD6C\uC131\uB420 \uB54C `/v1/health` \uB97C 1\uD68C \uC790\uB3D9 \uD638\uCD9C\uD55C\uB2E4.\n *\n * CSRF\u00B7anon \uCFE0\uD0A4 \uBC1C\uAE09\uACFC \uD328\uD0B7 \uC554\uD638\uD654 \uD611\uC0C1(`X-Packet-Encryption`)\uC744 \uC571 \uC9C4\uC785 \uC989\uC2DC \uC120\uBC18\uC601\uD574,\n * \uD504\uB7F0\uD2B8 \uB77C\uC6B0\uD2B8(`/login` \uB4F1)\uC640 \uBB34\uAD00\uD558\uAC8C \uD56D\uC0C1 health \uAC00 \uCD5C\uC18C 1\uD68C \uB3CC\uB3C4\uB85D \uBCF4\uC7A5\uD55C\uB2E4.\n *\n * @internal\n */\n fireInitialHealth(): void {\n if (this.initialHealthFired) return;\n if (typeof document === \"undefined\") return;\n if (!this.baseUrl) return;\n this.initialHealthFired = true;\n const self = this as unknown as {\n checkHealth?: (bootstrapAuth?: boolean) => Promise<unknown>;\n };\n if (typeof self.checkHealth !== \"function\") return;\n Promise.resolve().then(() => self.checkHealth!(false).catch(() => {}));\n }\n\n /** \uC778\uC99D \uC694\uCCAD\uC5D0 \uC0AC\uC6A9\uD560 JWT Access Token\uC744 \uC124\uC815\uD569\uB2C8\uB2E4. */\n setToken(token: string): void {\n this.token = token;\n this.syncRealtimeWithToken();\n }\n\n /** \uC751\uB2F5 \uD5E4\uB354\uB85C \uBC1B\uC740 access token \uAC31\uC2E0\uC744 \uBC18\uC601\uD55C\uB2E4. */\n setAccessTokenFromResponse(token: string): void {\n this.token = token;\n this.syncRealtimeWithToken();\n }\n\n /** \uD1A0\uD070 \uBCC0\uACBD \uD6C4 realtime \uC5F0\uACB0 \uC0C1\uD0DC\uB97C \uB3D9\uAE30\uD654\uD55C\uB2E4. */\n syncRealtimeWithToken(): void {\n if (!this.token) {\n this.disconnectRealtime(\"token_cleared\");\n return;\n }\n\n if (!this.realtimeEnabled || typeof WebSocket === \"undefined\") {\n return;\n }\n\n void this.connectRealtime().catch(() => {});\n }\n\n /** \uC775\uBA85 \uD328\uD0B7 \uC554\uD638\uD654\uC6A9 \uD1A0\uD070\uC744 \uC124\uC815\uD569\uB2C8\uB2E4. */\n setAnonymousPacketToken(token: string): void {\n this.anonymousPacketToken = token;\n }\n\n /** HMAC \uC778\uC99D\uC6A9 API Key\uB97C \uC124\uC815\uD569\uB2C8\uB2E4. */\n setApiKey(apiKey: string): void {\n this.apiKey = apiKey;\n }\n\n /** HMAC \uC778\uC99D\uC6A9 \uC2DC\uD06C\uB9BF\uC744 \uC124\uC815\uD569\uB2C8\uB2E4. */\n setHmacSecret(secret: string): void {\n this.hmacSecret = secret;\n }\n\n /** \uC554\uD638\uD654 \uC694\uCCAD \uD65C\uC131\uD654 \uC5EC\uBD80\uB97C \uC124\uC815\uD569\uB2C8\uB2E4. */\n setEncryptRequests(value: boolean): void {\n this.encryptRequests = value;\n }\n\n setCsrfEnabled(enabled: boolean): void {\n this.csrfEnabled = enabled;\n }\n\n addRealtimeListener(listener: RealtimeMessageListener): void {\n this.realtimeMessageListeners.add(listener);\n }\n\n removeRealtimeListener(listener: RealtimeMessageListener): void {\n this.realtimeMessageListeners.delete(listener);\n }\n\n addRealtimeStatusListener(listener: RealtimeStatusListener): void {\n this.realtimeStatusListeners.add(listener);\n }\n\n removeRealtimeStatusListener(listener: RealtimeStatusListener): void {\n this.realtimeStatusListeners.delete(listener);\n }\n\n addRealtimeEventListener(\n eventName: string,\n listener: RealtimeMessageListener,\n ): void {\n const key = String(eventName).trim();\n if (!key) {\n return;\n }\n if (!this.realtimeEventListeners.has(key)) {\n this.realtimeEventListeners.set(key, new Set());\n }\n this.realtimeEventListeners.get(key)!.add(listener);\n }\n\n removeRealtimeEventListener(\n eventName: string,\n listener: RealtimeMessageListener,\n ): void {\n const key = String(eventName).trim();\n if (!key) {\n return;\n }\n const listeners = this.realtimeEventListeners.get(key);\n if (!listeners) {\n return;\n }\n listeners.delete(listener);\n if (listeners.size === 0) {\n this.realtimeEventListeners.delete(key);\n }\n }\n\n async connectRealtime(): Promise<void> {\n if (!this.realtimeEnabled) {\n this.setRealtimeStatus(\"disabled\", \"realtime_disabled\");\n return;\n }\n\n if (!this.token) {\n throw new Error(\n \"Cannot open realtime connection without access token.\",\n );\n }\n\n if (typeof WebSocket === \"undefined\") {\n throw new Error(\"WebSocket is not available in this environment.\");\n }\n\n if (\n this.realtimeSocket &&\n this.realtimeSocket.readyState === WebSocket.OPEN\n ) {\n return;\n }\n\n if (\n this.realtimeSocket &&\n this.realtimeSocket.readyState === WebSocket.CONNECTING &&\n this.realtimeConnectPromise\n ) {\n return this.realtimeConnectPromise;\n }\n\n this.clearRealtimeReconnectTimer();\n this.realtimeShouldReconnect = this.realtimeAutoReconnect;\n this.setRealtimeStatus(\"connecting\", \"connect_requested\");\n\n const socket = new WebSocket(this.buildRealtimeUrl());\n this.realtimeSocket = socket;\n\n this.realtimeConnectPromise = new Promise<void>((resolve, reject) => {\n let settled = false;\n\n const finalizeResolve = () => {\n if (settled) {\n return;\n }\n settled = true;\n this.realtimeConnectPromise = null;\n resolve();\n };\n\n const finalizeReject = (error: Error) => {\n if (settled) {\n return;\n }\n settled = true;\n this.realtimeConnectPromise = null;\n reject(error);\n };\n\n socket.addEventListener(\"open\", () => {\n this.setRealtimeStatus(\"open\", \"socket_open\");\n finalizeResolve();\n });\n\n socket.addEventListener(\"message\", (event) => {\n this.handleRealtimeMessage(event.data);\n });\n\n socket.addEventListener(\"error\", () => {\n this.setRealtimeStatus(\n \"closed\",\n \"socket_error\",\n new Error(\"Realtime socket error.\"),\n );\n });\n\n socket.addEventListener(\"close\", (event) => {\n if (this.realtimeSocket === socket) {\n this.realtimeSocket = null;\n }\n\n const reason = event.reason || \"socket_closed\";\n const error = new Error(\n `Realtime socket closed (${event.code}${event.reason ? `: ${event.reason}` : \"\"}).`,\n );\n\n this.setRealtimeStatus(\"closed\", reason, error);\n if (!settled) {\n finalizeReject(error);\n }\n\n if (\n this.realtimeShouldReconnect &&\n this.realtimeEnabled &&\n this.realtimeAutoReconnect &&\n this.token\n ) {\n this.scheduleRealtimeReconnect(reason);\n }\n });\n });\n\n return this.realtimeConnectPromise;\n }\n\n disconnectRealtime(reason = \"client_disconnect\"): void {\n this.realtimeShouldReconnect = false;\n this.clearRealtimeReconnectTimer();\n\n if (this.realtimeSocket) {\n const socket = this.realtimeSocket;\n this.realtimeSocket = null;\n try {\n if (\n socket.readyState === WebSocket.OPEN ||\n socket.readyState === WebSocket.CONNECTING\n ) {\n socket.close(1000, reason);\n }\n } catch {\n // ignore close errors\n }\n }\n\n this.realtimeConnectPromise = null;\n this.setRealtimeStatus(\n this.realtimeEnabled ? \"idle\" : \"disabled\",\n reason,\n );\n }\n\n sendRealtime(message: RealtimeEnvelope | Record<string, unknown>): boolean {\n if (\n !this.realtimeSocket ||\n this.realtimeSocket.readyState !== WebSocket.OPEN\n ) {\n return false;\n }\n\n this.realtimeSocket.send(JSON.stringify(message));\n return true;\n }\n\n subscribeRealtime(subscriptions: string[]): boolean {\n return this.sendRealtime({\n type: \"subscribe\",\n channel: \"session\",\n event: \"session.subscribe\",\n data: { subscriptions },\n });\n }\n\n unsubscribeRealtime(subscriptions: string[]): boolean {\n return this.sendRealtime({\n type: \"unsubscribe\",\n channel: \"session\",\n event: \"session.unsubscribe\",\n data: { subscriptions },\n });\n }\n\n /**\n * \uC8FC\uAE30\uC801\uC73C\uB85C health \uCCB4\uD06C\uB97C \uC2E4\uD589\uD569\uB2C8\uB2E4.\n * CSRF \uCFE0\uD0A4 \uAC31\uC2E0\uACFC \uC11C\uBC84 \uC0C1\uD0DC \uD655\uC778\uC744 \uC790\uB3D9\uD654\uD569\uB2C8\uB2E4.\n * keepSession=true \uC774\uBA74 \uAC01 tick\uC5D0\uC11C \uC138\uC158 \uBD80\uD2B8\uC2A4\uD2B8\uB7A9\uB3C4 \uD568\uAED8 \uC2DC\uB3C4\uD569\uB2C8\uB2E4.\n *\n * @param intervalMs \uD638\uCD9C \uC8FC\uAE30(ms). \uAE30\uBCF8\uAC12: 5\uBD84\n * @param runImmediately true\uBA74 \uC2DC\uC791 \uC9C1\uD6C4 \uCCAB tick\uC744 \uC989\uC2DC \uC2E4\uD589\uD569\uB2C8\uB2E4.\n */\n startHealthTick(\n intervalMs: number = 5 * 60 * 1000,\n runImmediately = true,\n ): void {\n this.stopHealthTick();\n const tick = (): void => {\n if (this.healthTickPromise) return;\n this.healthTickPromise = (\n this.csrfRefresher ? this.csrfRefresher() : Promise.resolve()\n )\n .then(() => {\n this.onHealthChange?.(true);\n })\n .catch(() => {\n this.onHealthChange?.(false);\n })\n .finally(() => {\n this.healthTickPromise = null;\n });\n };\n if (runImmediately) {\n tick();\n }\n this.healthTickTimer = setInterval(tick, intervalMs);\n }\n\n /** health tick \uD0C0\uC774\uBA38\uB97C \uC911\uC9C0\uD569\uB2C8\uB2E4. */\n stopHealthTick(): void {\n if (this.healthTickTimer !== null) {\n clearInterval(this.healthTickTimer);\n this.healthTickTimer = null;\n }\n this.healthTickPromise = null;\n }\n\n // \u2500\u2500\u2500 \uC138\uC158 \uC720\uC9C0 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** @deprecated \uC138\uC158 \uC5F0\uC7A5\uC740 health tick \uAE30\uBC18 \uBD80\uD2B8\uC2A4\uD2B8\uB7A9\uC73C\uB85C \uB300\uCCB4\uB418\uC5C8\uC2B5\uB2C8\uB2E4. */\n scheduleKeepSession(\n refreshToken: string,\n expiresIn: number,\n refreshFn: (\n rt: string,\n ) => Promise<{ access_token: string; expires_in: number }>,\n ): void {\n this.clearRefreshTimer();\n this.sessionRefreshToken = refreshToken;\n const delayMs = Math.max((expiresIn - this.refreshBuffer) * 1000, 0);\n this.refreshTimer = setTimeout(async () => {\n if (!this.sessionRefreshToken) return;\n try {\n const result = await refreshFn(this.sessionRefreshToken);\n this.onTokenRefreshed?.(result.access_token, result.expires_in);\n this.scheduleKeepSession(\n this.sessionRefreshToken,\n result.expires_in,\n refreshFn,\n );\n } catch (err) {\n this.clearRefreshTimer();\n this.onSessionExpired?.(\n err instanceof Error ? err : new Error(String(err)),\n );\n }\n }, delayMs);\n }\n\n /** @deprecated \uC138\uC158 \uC5F0\uC7A5\uC740 health tick \uAE30\uBC18 \uBD80\uD2B8\uC2A4\uD2B8\uB7A9\uC73C\uB85C \uB300\uCCB4\uB418\uC5C8\uC2B5\uB2C8\uB2E4. */\n clearRefreshTimer(): void {\n if (this.refreshTimer !== null) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n /**\n * \uC138\uC158 \uC790\uB3D9 \uC5F0\uC7A5\uC744 \uC911\uC9C0\uD569\uB2C8\uB2E4.\n * `logout()` \uD638\uCD9C \uC2DC \uC790\uB3D9\uC73C\uB85C \uC911\uC9C0\uB418\uBA70, \uC9C1\uC811 \uD638\uCD9C\uC774 \uD544\uC694\uD55C \uACBD\uC6B0\uB294 \uB4DC\uBB45\uB2C8\uB2E4.\n */\n stopKeepSession(): void {\n this.clearRefreshTimer();\n this.sessionRefreshToken = null;\n }\n\n applyRealtimeOptions(options?: boolean | RealtimeClientOptions): void {\n const normalized: RealtimeClientOptions =\n typeof options === \"boolean\"\n ? { enabled: options }\n : (options ?? {});\n\n this.realtimeEnabled = normalized.enabled ?? false;\n this.realtimePath =\n String(normalized.path ?? REALTIME_DEFAULT_PATH).trim() ||\n REALTIME_DEFAULT_PATH;\n this.realtimeAutoReconnect = normalized.autoReconnect ?? true;\n this.realtimeReconnectDelayMs = Math.max(\n 250,\n normalized.reconnectDelayMs ?? 3000,\n );\n\n if (!this.realtimeEnabled) {\n this.disconnectRealtime(\"realtime_disabled\");\n return;\n }\n\n this.setRealtimeStatus(\"idle\", \"realtime_enabled\");\n }\n\n buildRealtimeUrl(): string {\n const rawBaseUrl =\n this.baseUrl || readEnv(\"VITE_ENTITY_SERVER_URL\") || \"\";\n const origin =\n typeof window !== \"undefined\" ? window.location.origin : \"\";\n const baseUrl = rawBaseUrl || origin;\n\n if (!baseUrl) {\n throw new Error(\"Realtime connection requires baseUrl.\");\n }\n\n const url = new URL(baseUrl, origin || undefined);\n const basePath =\n url.pathname === \"/\" ? \"\" : url.pathname.replace(/\\/+$/, \"\");\n const realtimePath = `/${this.realtimePath.replace(/^\\/+/, \"\")}`;\n\n url.pathname = `${basePath}${realtimePath}` || realtimePath;\n url.search = \"\";\n url.hash = \"\";\n url.protocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n url.searchParams.set(\"access_token\", this.token);\n return url.toString();\n }\n\n handleRealtimeMessage(payload: unknown): void {\n if (typeof payload !== \"string\") {\n return;\n }\n\n let envelope: RealtimeEnvelope;\n try {\n envelope = JSON.parse(payload) as RealtimeEnvelope;\n } catch {\n return;\n }\n\n for (const listener of this.realtimeMessageListeners) {\n listener(envelope);\n }\n\n const listeners = this.realtimeEventListeners.get(envelope.event);\n if (listeners) {\n for (const listener of listeners) {\n listener(envelope);\n }\n }\n }\n\n scheduleRealtimeReconnect(reason: string): void {\n this.clearRealtimeReconnectTimer();\n this.realtimeReconnectTimer = setTimeout(() => {\n this.realtimeReconnectTimer = null;\n if (!this.realtimeEnabled || !this.token) {\n return;\n }\n this.setRealtimeStatus(\"connecting\", `${reason}:reconnect`);\n void this.connectRealtime().catch(() => {});\n }, this.realtimeReconnectDelayMs);\n }\n\n clearRealtimeReconnectTimer(): void {\n if (this.realtimeReconnectTimer !== null) {\n clearTimeout(this.realtimeReconnectTimer);\n this.realtimeReconnectTimer = null;\n }\n }\n\n setRealtimeStatus(\n status: RealtimeConnectionStatus,\n reason?: string,\n error?: Error,\n ): void {\n const previousStatus = this.realtimeStatus;\n if (\n previousStatus === status &&\n typeof reason === \"undefined\" &&\n typeof error === \"undefined\"\n ) {\n return;\n }\n\n this.realtimeStatus = status;\n for (const listener of this.realtimeStatusListeners) {\n listener({\n status,\n previousStatus,\n ...(reason ? { reason } : {}),\n ...(error ? { error } : {}),\n });\n }\n }\n\n applyCsrfHealth(): void {\n if (typeof document === \"undefined\") return;\n for (const chunk of document.cookie.split(\";\")) {\n const idx = chunk.indexOf(\"=\");\n if (idx < 0) continue;\n if (chunk.substring(0, idx).trim() === this.csrfCookieName) {\n this.csrfEnabled = !!chunk.substring(idx + 1).trim();\n return;\n }\n }\n this.csrfEnabled = false;\n }\n\n // \u2500\u2500\u2500 \uC694\uCCAD \uBCF8\uBB38 \uD30C\uC2F1 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * \uC694\uCCAD \uBC14\uB514\uB97C \uD30C\uC2F1\uD569\uB2C8\uB2E4.\n * `application/octet-stream`\uC774\uBA74 XChaCha20-Poly1305 \uBCF5\uD638\uD654, \uADF8 \uC678\uB294 JSON \uD30C\uC2F1\uD569\uB2C8\uB2E4.\n *\n * @param requireEncrypted `true`\uC774\uBA74 \uC554\uD638\uD654\uB41C \uC694\uCCAD\uB9CC \uD5C8\uC6A9\uD569\uB2C8\uB2E4.\n */\n readRequestBody<T = Record<string, unknown>>(\n body: ArrayBuffer | Uint8Array | string | T | null | undefined,\n contentType = \"application/json\",\n requireEncrypted = false,\n ): T {\n const key = derivePacketKey(\n this.hmacSecret,\n this.token || this.anonymousPacketToken,\n );\n return parseRequestBody<T>(body, contentType, requireEncrypted, key);\n }\n\n // \u2500\u2500\u2500 \uB0B4\uBD80 \uD5EC\uD37C \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n get reqOpts(): RequestOptions {\n return {\n baseUrl: this.baseUrl,\n token: this.token,\n anonymousPacketToken: this.anonymousPacketToken,\n apiKey: this.apiKey,\n hmacSecret: this.hmacSecret,\n encryptRequests: this.encryptRequests,\n csrfEnabled: this.csrfEnabled,\n csrfHeaderName: this.csrfHeaderName,\n csrfCookieName: this.csrfCookieName,\n refreshCsrfCookie: this.csrfEnabled ? this.csrfRefresher : null,\n requestAbortControllers: this.requestAbortControllers,\n debugPlainSecret: this.debugPlainSecret,\n onAccessToken: (token) => {\n this.setAccessTokenFromResponse(token);\n },\n };\n }\n\n // \uC778\uC99D \uC694\uCCAD \uC804\uC5D0 \uD544\uC694\uD55C \uD074\uB77C\uC774\uC5B8\uD2B8 \uC900\uBE44 \uC791\uC5C5\uC744 \uC218\uD589\uD569\uB2C8\uB2E4.\n prepareRequest(_withAuth: boolean): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * \uCEE4\uC2A4\uD140 \uB77C\uC6B0\uD2B8 \uC9C1\uC811 \uD638\uCD9C\uC6A9 HTTP \uB124\uC784\uC2A4\uD398\uC774\uC2A4.\n * \uC778\uC99D\u00B7\uC554\uD638\uD654\u00B7HMAC \uB4F1 SDK \uC635\uC158\uC774 \uADF8\uB300\uB85C \uC801\uC6A9\uB429\uB2C8\uB2E4.\n *\n * @example\n * const res = await client.http.get<{ version: string }>(\"/api/v1/status\", false);\n * const res = await client.http.post<MyResponse>(\"/api/v1/custom\", { key: \"value\" });\n */\n get http() {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n return {\n get<T>(\n path: string,\n withAuth = true,\n extraHeaders?: Record<string, string>,\n requestConfig?: EntityRequestConfig,\n ): Promise<T> {\n return self\n .prepareRequest(withAuth)\n .then(() =>\n entityRequest<T>(\n self.reqOpts,\n \"GET\",\n path,\n undefined,\n withAuth,\n extraHeaders,\n requestConfig ?? true,\n ),\n );\n },\n post<T>(\n path: string,\n body?: unknown,\n withAuth = true,\n extraHeaders?: Record<string, string>,\n requestConfig?: EntityRequestConfig,\n ): Promise<T> {\n return self\n .prepareRequest(withAuth)\n .then(() =>\n entityRequest<T>(\n self.reqOpts,\n \"POST\",\n path,\n body,\n withAuth,\n extraHeaders,\n requestConfig ?? true,\n ),\n );\n },\n put<T>(\n path: string,\n body?: unknown,\n withAuth = true,\n extraHeaders?: Record<string, string>,\n requestConfig?: EntityRequestConfig,\n ): Promise<T> {\n return self\n .prepareRequest(withAuth)\n .then(() =>\n entityRequest<T>(\n self.reqOpts,\n \"PUT\",\n path,\n body,\n withAuth,\n extraHeaders,\n requestConfig ?? true,\n ),\n );\n },\n patch<T>(\n path: string,\n body?: unknown,\n withAuth = true,\n extraHeaders?: Record<string, string>,\n requestConfig?: EntityRequestConfig,\n ): Promise<T> {\n return self\n .prepareRequest(withAuth)\n .then(() =>\n entityRequest<T>(\n self.reqOpts,\n \"PATCH\",\n path,\n body,\n withAuth,\n extraHeaders,\n requestConfig ?? true,\n ),\n );\n },\n delete<T>(\n path: string,\n body?: unknown,\n withAuth = true,\n extraHeaders?: Record<string, string>,\n requestConfig?: EntityRequestConfig,\n ): Promise<T> {\n return self\n .prepareRequest(withAuth)\n .then(() =>\n entityRequest<T>(\n self.reqOpts,\n \"DELETE\",\n path,\n body,\n withAuth,\n extraHeaders,\n requestConfig ?? true,\n ),\n );\n },\n };\n }\n\n request<T>(\n method: string,\n path: string,\n body?: unknown,\n withAuth = true,\n extraHeaders?: Record<string, string>,\n requestConfig?: EntityRequestConfig,\n ): Promise<T> {\n return this.prepareRequest(withAuth).then(() =>\n entityRequest<T>(\n this.reqOpts,\n method,\n path,\n body,\n withAuth,\n extraHeaders,\n requestConfig ?? true,\n ),\n );\n }\n\n /** PNG/\uBC14\uC774\uB108\uB9AC \uC751\uB2F5\uC744 ArrayBuffer\uB85C \uBC18\uD658\uD569\uB2C8\uB2E4. (QR, \uBC14\uCF54\uB4DC \uB4F1) */\n async requestBinary(\n method: string,\n path: string,\n body?: unknown,\n withAuth = true,\n ): Promise<ArrayBuffer> {\n await this.prepareRequest(withAuth);\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (withAuth && this.token)\n headers[\"Authorization\"] = `Bearer ${this.token}`;\n if (this.apiKey) headers[\"X-API-Key\"] = this.apiKey;\n\n const res = await fetch(this.baseUrl + path, {\n method,\n headers,\n ...(body != null ? { body: JSON.stringify(body) } : {}),\n credentials: \"include\",\n });\n\n if (!res.ok) {\n const text = await res.text();\n const err = new Error(`HTTP ${res.status}: ${text}`);\n (err as { status?: number }).status = res.status;\n throw err;\n }\n\n return res.arrayBuffer();\n }\n\n /** multipart/form-data \uC694\uCCAD\uC744 \uBCF4\uB0C5\uB2C8\uB2E4. (\uD30C\uC77C \uC5C5\uB85C\uB4DC \uB4F1) */\n async requestForm<T>(\n method: string,\n path: string,\n form: FormData,\n withAuth = true,\n ): Promise<T> {\n const headers: Record<string, string> = {};\n if (withAuth && this.token)\n headers[\"Authorization\"] = `Bearer ${this.token}`;\n if (this.apiKey) headers[\"X-API-Key\"] = this.apiKey;\n\n const res = await fetch(this.baseUrl + path, {\n method,\n headers,\n body: form,\n credentials: \"include\",\n });\n\n const data = (await res.json()) as { ok?: boolean; message?: string };\n if (!data.ok) {\n const err = new Error(\n data.message ?? `EntityServer error (HTTP ${res.status})`,\n );\n (err as { status?: number }).status = res.status;\n throw err;\n }\n return data as T;\n }\n\n /** multipart/form-data \uC694\uCCAD\uC744 \uBCF4\uB0B4\uACE0 \uBC14\uC774\uB108\uB9AC(ArrayBuffer)\uB97C \uBC18\uD658\uD569\uB2C8\uB2E4. */\n async requestFormBinary(\n method: string,\n path: string,\n form: FormData,\n withAuth = true,\n ): Promise<ArrayBuffer> {\n const headers: Record<string, string> = {};\n if (withAuth && this.token)\n headers[\"Authorization\"] = `Bearer ${this.token}`;\n if (this.apiKey) headers[\"X-API-Key\"] = this.apiKey;\n\n const res = await fetch(this.baseUrl + path, {\n method,\n headers,\n body: form,\n credentials: \"include\",\n });\n\n if (!res.ok) {\n const text = await res.text();\n const err = new Error(`HTTP ${res.status}: ${text}`);\n (err as { status?: number }).status = res.status;\n throw err;\n }\n\n return res.arrayBuffer();\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["readEnv", "derivePacketKey", "parseRequestBody", "entityRequest", "REALTIME_DEFAULT_PATH", "EntityServerClientBase", "options", "envBaseUrl", "self", "token", "apiKey", "secret", "value", "enabled", "listener", "eventName", "key", "listeners", "socket", "resolve", "reject", "settled", "finalizeResolve", "finalizeReject", "error", "event", "reason", "message", "subscriptions", "intervalMs", "runImmediately", "tick", "refreshToken", "expiresIn", "refreshFn", "delayMs", "result", "err", "normalized", "rawBaseUrl", "origin", "baseUrl", "url", "basePath", "realtimePath", "payload", "envelope", "status", "previousStatus", "chunk", "idx", "body", "contentType", "requireEncrypted", "_withAuth", "path", "withAuth", "extraHeaders", "requestConfig", "method", "headers", "res", "text", "form"
|
|
4
|
+
"sourcesContent": ["import type {\n EntityServerClientOptions,\n RealtimeClientOptions,\n RealtimeConnectionStatus,\n RealtimeEnvelope,\n RealtimeMessageListener,\n RealtimeStatusListener,\n} from \"../types.js\";\nimport { readEnv } from \"./utils.js\";\nimport { derivePacketKey, parseRequestBody } from \"./packet.js\";\nimport {\n entityRequest,\n requestFormData,\n type EntityRequestConfig,\n type RequestOptions,\n} from \"./request.js\";\n\nconst REALTIME_DEFAULT_PATH = \"/v1/realtime\";\n\n// mixin \uD5EC\uD37C \uD0C0\uC785\nexport type GConstructor<T = object> = new (...args: any[]) => T;\n\nexport class EntityServerClientBase {\n baseUrl: string;\n token: string;\n anonymousPacketToken: string;\n apiKey: string;\n hmacSecret: string;\n encryptRequests: boolean;\n /** dev \uB514\uBC84\uADF8 \uD3C9\uBB38 \uC2DC\uD06C\uB9BF. \uC124\uC815 \uC2DC \uC694\uCCAD\uC744 \uD3C9\uBB38 \uC804\uC1A1\uD558\uACE0 `X-Debug-Plain` \uD5E4\uB354\uB97C \uBCF4\uB0B8\uB2E4. */\n debugPlainSecret: string;\n csrfEnabled: boolean;\n csrfHeaderName: string;\n csrfCookieName: string;\n /** @internal health \uC7AC\uD638\uCD9C\uB85C CSRF \uCFE0\uD0A4 \uAC31\uC2E0 (AuthMixin\uC5D0\uC11C \uC124\uC815) */\n csrfRefresher: (() => Promise<void>) | null = null;\n requestAbortControllers = new Map<string, AbortController>();\n activeTxId: string | null = null;\n /** @internal \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uCCAB \uAD6C\uC131 \uC2DC health 1\uD68C \uC790\uB3D9 \uD638\uCD9C\uD588\uB294\uC9C0 \uC5EC\uBD80 */\n initialHealthFired = false;\n\n // \uC138\uC158 \uC720\uC9C0 \uAD00\uB828\n keepSession: boolean;\n refreshBuffer: number;\n onTokenRefreshed?: (accessToken: string, expiresIn: number) => void;\n onSessionExpired?: (error: Error) => void;\n onHealthChange?: (online: boolean) => void;\n sessionRefreshToken: string | null = null;\n refreshTimer: ReturnType<typeof setTimeout> | null = null;\n healthTickTimer: ReturnType<typeof setInterval> | null = null;\n healthTickPromise: Promise<unknown> | null = null;\n realtimeEnabled: boolean;\n realtimePath: string;\n realtimeAutoReconnect: boolean;\n realtimeReconnectDelayMs: number;\n realtimeStatus: RealtimeConnectionStatus;\n realtimeSocket: WebSocket | null = null;\n realtimeConnectPromise: Promise<void> | null = null;\n realtimeReconnectTimer: ReturnType<typeof setTimeout> | null = null;\n realtimeShouldReconnect = false;\n realtimeMessageListeners = new Set<RealtimeMessageListener>();\n realtimeStatusListeners = new Set<RealtimeStatusListener>();\n realtimeEventListeners = new Map<string, Set<RealtimeMessageListener>>();\n // \u2500\u2500\u2500 \uCD08\uAE30\uD654 & \uC124\uC815 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * EntityServerClient \uC778\uC2A4\uD134\uC2A4\uB97C \uC0DD\uC131\uD569\uB2C8\uB2E4.\n *\n * \uAE30\uBCF8\uAC12:\n * - `baseUrl`: `VITE_ENTITY_SERVER_URL` \uB610\uB294 \uC0C1\uB300 \uACBD\uB85C(`\"\"`)\n */\n constructor(options: EntityServerClientOptions = {}) {\n const envBaseUrl = readEnv(\"VITE_ENTITY_SERVER_URL\");\n\n this.baseUrl = (options.baseUrl ?? envBaseUrl ?? \"\").replace(/\\/$/, \"\");\n this.token = options.token ?? \"\";\n this.anonymousPacketToken = options.anonymousPacketToken ?? \"\";\n this.apiKey = options.apiKey ?? \"\";\n this.hmacSecret = options.hmacSecret ?? \"\";\n this.encryptRequests = options.encryptRequests ?? false;\n this.debugPlainSecret = options.debugPlainSecret ?? \"\";\n this.csrfEnabled = options.csrfEnabled ?? false;\n this.csrfHeaderName = options.csrfHeaderName ?? \"x-csrf-token\";\n this.csrfCookieName = options.csrfCookieName ?? \"_csrf\";\n this.keepSession = options.keepSession ?? false;\n this.refreshBuffer = options.refreshBuffer ?? 60;\n this.onTokenRefreshed = options.onTokenRefreshed;\n this.onSessionExpired = options.onSessionExpired;\n this.onHealthChange = options.onHealthChange;\n this.realtimeEnabled = false;\n this.realtimePath = REALTIME_DEFAULT_PATH;\n this.realtimeAutoReconnect = true;\n this.realtimeReconnectDelayMs = 3000;\n this.realtimeStatus = \"idle\";\n this.applyRealtimeOptions(options.realtime);\n if (\n typeof options.healthTickInterval === \"number\" &&\n options.healthTickInterval > 0\n ) {\n // csrfRefresher\uB294 AuthMixin\uC5D0\uC11C \uC124\uC815\uB418\uBBC0\uB85C \uB2E4\uC74C tick\uC5D0 \uC2DC\uC791\n Promise.resolve().then(() =>\n this.startHealthTick(options.healthTickInterval, false),\n );\n }\n\n // baseUrl \uC774 \uC0DD\uC131 \uC2DC\uC810\uC5D0 \uC815\uD574\uC9C4 \uACBD\uC6B0(env \uB4F1) \uCCAB health \uB97C \uBCF4\uC7A5\uD55C\uB2E4.\n this.fireInitialHealth();\n }\n\n /** baseUrl, token, encryptRequests \uAC12\uC744 \uB7F0\uD0C0\uC784\uC5D0 \uAC31\uC2E0\uD569\uB2C8\uB2E4. */\n configure(options: Partial<EntityServerClientOptions>): void {\n if (typeof options.baseUrl === \"string\") {\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n }\n if (typeof options.token === \"string\") this.token = options.token;\n if (typeof options.anonymousPacketToken === \"string\") {\n this.anonymousPacketToken = options.anonymousPacketToken;\n }\n if (typeof options.encryptRequests === \"boolean\")\n this.encryptRequests = options.encryptRequests;\n if (typeof options.debugPlainSecret === \"string\")\n this.debugPlainSecret = options.debugPlainSecret;\n if (typeof options.csrfEnabled === \"boolean\") {\n this.csrfEnabled = options.csrfEnabled;\n }\n if (typeof options.csrfHeaderName === \"string\") {\n this.csrfHeaderName = options.csrfHeaderName;\n }\n if (typeof options.csrfCookieName === \"string\") {\n this.csrfCookieName = options.csrfCookieName;\n }\n if (typeof options.apiKey === \"string\") this.apiKey = options.apiKey;\n if (typeof options.hmacSecret === \"string\")\n this.hmacSecret = options.hmacSecret;\n if (typeof options.keepSession === \"boolean\")\n this.keepSession = options.keepSession;\n if (typeof options.refreshBuffer === \"number\")\n this.refreshBuffer = options.refreshBuffer;\n if (options.onTokenRefreshed)\n this.onTokenRefreshed = options.onTokenRefreshed;\n if (options.onSessionExpired)\n this.onSessionExpired = options.onSessionExpired;\n if (options.onHealthChange)\n this.onHealthChange = options.onHealthChange;\n if (typeof options.realtime !== \"undefined\") {\n this.applyRealtimeOptions(options.realtime);\n }\n if (\n typeof options.healthTickInterval === \"number\" &&\n options.healthTickInterval > 0\n ) {\n Promise.resolve().then(() =>\n this.startHealthTick(options.healthTickInterval, false),\n );\n }\n\n // \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C baseUrl \uC774 \uC815\uD574\uC9C0\uBA74 \uCCAB \uB9C8\uC6B4\uD2B8 \uC2DC health \uB97C 1\uD68C \uC790\uB3D9 \uD638\uCD9C\uD55C\uB2E4.\n this.fireInitialHealth();\n }\n\n /**\n * \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uD074\uB77C\uC774\uC5B8\uD2B8\uAC00 \uCC98\uC74C \uAD6C\uC131\uB420 \uB54C `/v1/health` \uB97C 1\uD68C \uC790\uB3D9 \uD638\uCD9C\uD55C\uB2E4.\n *\n * CSRF\u00B7anon \uCFE0\uD0A4 \uBC1C\uAE09\uACFC \uD328\uD0B7 \uC554\uD638\uD654 \uD611\uC0C1(`X-Packet-Encryption`)\uC744 \uC571 \uC9C4\uC785 \uC989\uC2DC \uC120\uBC18\uC601\uD574,\n * \uD504\uB7F0\uD2B8 \uB77C\uC6B0\uD2B8(`/login` \uB4F1)\uC640 \uBB34\uAD00\uD558\uAC8C \uD56D\uC0C1 health \uAC00 \uCD5C\uC18C 1\uD68C \uB3CC\uB3C4\uB85D \uBCF4\uC7A5\uD55C\uB2E4.\n *\n * @internal\n */\n fireInitialHealth(): void {\n if (this.initialHealthFired) return;\n if (typeof document === \"undefined\") return;\n if (!this.baseUrl) return;\n this.initialHealthFired = true;\n const self = this as unknown as {\n checkHealth?: (bootstrapAuth?: boolean) => Promise<unknown>;\n };\n if (typeof self.checkHealth !== \"function\") return;\n Promise.resolve().then(() => self.checkHealth!(false).catch(() => {}));\n }\n\n /** \uC778\uC99D \uC694\uCCAD\uC5D0 \uC0AC\uC6A9\uD560 JWT Access Token\uC744 \uC124\uC815\uD569\uB2C8\uB2E4. */\n setToken(token: string): void {\n this.token = token;\n this.syncRealtimeWithToken();\n }\n\n /** \uC751\uB2F5 \uD5E4\uB354\uB85C \uBC1B\uC740 access token \uAC31\uC2E0\uC744 \uBC18\uC601\uD55C\uB2E4. */\n setAccessTokenFromResponse(token: string): void {\n this.token = token;\n this.syncRealtimeWithToken();\n }\n\n /** \uD1A0\uD070 \uBCC0\uACBD \uD6C4 realtime \uC5F0\uACB0 \uC0C1\uD0DC\uB97C \uB3D9\uAE30\uD654\uD55C\uB2E4. */\n syncRealtimeWithToken(): void {\n if (!this.token) {\n this.disconnectRealtime(\"token_cleared\");\n return;\n }\n\n if (!this.realtimeEnabled || typeof WebSocket === \"undefined\") {\n return;\n }\n\n void this.connectRealtime().catch(() => {});\n }\n\n /** \uC775\uBA85 \uD328\uD0B7 \uC554\uD638\uD654\uC6A9 \uD1A0\uD070\uC744 \uC124\uC815\uD569\uB2C8\uB2E4. */\n setAnonymousPacketToken(token: string): void {\n this.anonymousPacketToken = token;\n }\n\n /** HMAC \uC778\uC99D\uC6A9 API Key\uB97C \uC124\uC815\uD569\uB2C8\uB2E4. */\n setApiKey(apiKey: string): void {\n this.apiKey = apiKey;\n }\n\n /** HMAC \uC778\uC99D\uC6A9 \uC2DC\uD06C\uB9BF\uC744 \uC124\uC815\uD569\uB2C8\uB2E4. */\n setHmacSecret(secret: string): void {\n this.hmacSecret = secret;\n }\n\n /** \uC554\uD638\uD654 \uC694\uCCAD \uD65C\uC131\uD654 \uC5EC\uBD80\uB97C \uC124\uC815\uD569\uB2C8\uB2E4. */\n setEncryptRequests(value: boolean): void {\n this.encryptRequests = value;\n }\n\n setCsrfEnabled(enabled: boolean): void {\n this.csrfEnabled = enabled;\n }\n\n addRealtimeListener(listener: RealtimeMessageListener): void {\n this.realtimeMessageListeners.add(listener);\n }\n\n removeRealtimeListener(listener: RealtimeMessageListener): void {\n this.realtimeMessageListeners.delete(listener);\n }\n\n addRealtimeStatusListener(listener: RealtimeStatusListener): void {\n this.realtimeStatusListeners.add(listener);\n }\n\n removeRealtimeStatusListener(listener: RealtimeStatusListener): void {\n this.realtimeStatusListeners.delete(listener);\n }\n\n addRealtimeEventListener(\n eventName: string,\n listener: RealtimeMessageListener,\n ): void {\n const key = String(eventName).trim();\n if (!key) {\n return;\n }\n if (!this.realtimeEventListeners.has(key)) {\n this.realtimeEventListeners.set(key, new Set());\n }\n this.realtimeEventListeners.get(key)!.add(listener);\n }\n\n removeRealtimeEventListener(\n eventName: string,\n listener: RealtimeMessageListener,\n ): void {\n const key = String(eventName).trim();\n if (!key) {\n return;\n }\n const listeners = this.realtimeEventListeners.get(key);\n if (!listeners) {\n return;\n }\n listeners.delete(listener);\n if (listeners.size === 0) {\n this.realtimeEventListeners.delete(key);\n }\n }\n\n async connectRealtime(): Promise<void> {\n if (!this.realtimeEnabled) {\n this.setRealtimeStatus(\"disabled\", \"realtime_disabled\");\n return;\n }\n\n if (!this.token) {\n throw new Error(\n \"Cannot open realtime connection without access token.\",\n );\n }\n\n if (typeof WebSocket === \"undefined\") {\n throw new Error(\"WebSocket is not available in this environment.\");\n }\n\n if (\n this.realtimeSocket &&\n this.realtimeSocket.readyState === WebSocket.OPEN\n ) {\n return;\n }\n\n if (\n this.realtimeSocket &&\n this.realtimeSocket.readyState === WebSocket.CONNECTING &&\n this.realtimeConnectPromise\n ) {\n return this.realtimeConnectPromise;\n }\n\n this.clearRealtimeReconnectTimer();\n this.realtimeShouldReconnect = this.realtimeAutoReconnect;\n this.setRealtimeStatus(\"connecting\", \"connect_requested\");\n\n const socket = new WebSocket(this.buildRealtimeUrl());\n this.realtimeSocket = socket;\n\n this.realtimeConnectPromise = new Promise<void>((resolve, reject) => {\n let settled = false;\n\n const finalizeResolve = () => {\n if (settled) {\n return;\n }\n settled = true;\n this.realtimeConnectPromise = null;\n resolve();\n };\n\n const finalizeReject = (error: Error) => {\n if (settled) {\n return;\n }\n settled = true;\n this.realtimeConnectPromise = null;\n reject(error);\n };\n\n socket.addEventListener(\"open\", () => {\n this.setRealtimeStatus(\"open\", \"socket_open\");\n finalizeResolve();\n });\n\n socket.addEventListener(\"message\", (event) => {\n this.handleRealtimeMessage(event.data);\n });\n\n socket.addEventListener(\"error\", () => {\n this.setRealtimeStatus(\n \"closed\",\n \"socket_error\",\n new Error(\"Realtime socket error.\"),\n );\n });\n\n socket.addEventListener(\"close\", (event) => {\n if (this.realtimeSocket === socket) {\n this.realtimeSocket = null;\n }\n\n const reason = event.reason || \"socket_closed\";\n const error = new Error(\n `Realtime socket closed (${event.code}${event.reason ? `: ${event.reason}` : \"\"}).`,\n );\n\n this.setRealtimeStatus(\"closed\", reason, error);\n if (!settled) {\n finalizeReject(error);\n }\n\n if (\n this.realtimeShouldReconnect &&\n this.realtimeEnabled &&\n this.realtimeAutoReconnect &&\n this.token\n ) {\n this.scheduleRealtimeReconnect(reason);\n }\n });\n });\n\n return this.realtimeConnectPromise;\n }\n\n disconnectRealtime(reason = \"client_disconnect\"): void {\n this.realtimeShouldReconnect = false;\n this.clearRealtimeReconnectTimer();\n\n if (this.realtimeSocket) {\n const socket = this.realtimeSocket;\n this.realtimeSocket = null;\n try {\n if (\n socket.readyState === WebSocket.OPEN ||\n socket.readyState === WebSocket.CONNECTING\n ) {\n socket.close(1000, reason);\n }\n } catch {\n // ignore close errors\n }\n }\n\n this.realtimeConnectPromise = null;\n this.setRealtimeStatus(\n this.realtimeEnabled ? \"idle\" : \"disabled\",\n reason,\n );\n }\n\n sendRealtime(message: RealtimeEnvelope | Record<string, unknown>): boolean {\n if (\n !this.realtimeSocket ||\n this.realtimeSocket.readyState !== WebSocket.OPEN\n ) {\n return false;\n }\n\n this.realtimeSocket.send(JSON.stringify(message));\n return true;\n }\n\n subscribeRealtime(subscriptions: string[]): boolean {\n return this.sendRealtime({\n type: \"subscribe\",\n channel: \"session\",\n event: \"session.subscribe\",\n data: { subscriptions },\n });\n }\n\n unsubscribeRealtime(subscriptions: string[]): boolean {\n return this.sendRealtime({\n type: \"unsubscribe\",\n channel: \"session\",\n event: \"session.unsubscribe\",\n data: { subscriptions },\n });\n }\n\n /**\n * \uC8FC\uAE30\uC801\uC73C\uB85C health \uCCB4\uD06C\uB97C \uC2E4\uD589\uD569\uB2C8\uB2E4.\n * CSRF \uCFE0\uD0A4 \uAC31\uC2E0\uACFC \uC11C\uBC84 \uC0C1\uD0DC \uD655\uC778\uC744 \uC790\uB3D9\uD654\uD569\uB2C8\uB2E4.\n * keepSession=true \uC774\uBA74 \uAC01 tick\uC5D0\uC11C \uC138\uC158 \uBD80\uD2B8\uC2A4\uD2B8\uB7A9\uB3C4 \uD568\uAED8 \uC2DC\uB3C4\uD569\uB2C8\uB2E4.\n *\n * @param intervalMs \uD638\uCD9C \uC8FC\uAE30(ms). \uAE30\uBCF8\uAC12: 5\uBD84\n * @param runImmediately true\uBA74 \uC2DC\uC791 \uC9C1\uD6C4 \uCCAB tick\uC744 \uC989\uC2DC \uC2E4\uD589\uD569\uB2C8\uB2E4.\n */\n startHealthTick(\n intervalMs: number = 5 * 60 * 1000,\n runImmediately = true,\n ): void {\n this.stopHealthTick();\n const tick = (): void => {\n if (this.healthTickPromise) return;\n this.healthTickPromise = (\n this.csrfRefresher ? this.csrfRefresher() : Promise.resolve()\n )\n .then(() => {\n this.onHealthChange?.(true);\n })\n .catch(() => {\n this.onHealthChange?.(false);\n })\n .finally(() => {\n this.healthTickPromise = null;\n });\n };\n if (runImmediately) {\n tick();\n }\n this.healthTickTimer = setInterval(tick, intervalMs);\n }\n\n /** health tick \uD0C0\uC774\uBA38\uB97C \uC911\uC9C0\uD569\uB2C8\uB2E4. */\n stopHealthTick(): void {\n if (this.healthTickTimer !== null) {\n clearInterval(this.healthTickTimer);\n this.healthTickTimer = null;\n }\n this.healthTickPromise = null;\n }\n\n // \u2500\u2500\u2500 \uC138\uC158 \uC720\uC9C0 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** @deprecated \uC138\uC158 \uC5F0\uC7A5\uC740 health tick \uAE30\uBC18 \uBD80\uD2B8\uC2A4\uD2B8\uB7A9\uC73C\uB85C \uB300\uCCB4\uB418\uC5C8\uC2B5\uB2C8\uB2E4. */\n scheduleKeepSession(\n refreshToken: string,\n expiresIn: number,\n refreshFn: (\n rt: string,\n ) => Promise<{ access_token: string; expires_in: number }>,\n ): void {\n this.clearRefreshTimer();\n this.sessionRefreshToken = refreshToken;\n const delayMs = Math.max((expiresIn - this.refreshBuffer) * 1000, 0);\n this.refreshTimer = setTimeout(async () => {\n if (!this.sessionRefreshToken) return;\n try {\n const result = await refreshFn(this.sessionRefreshToken);\n this.onTokenRefreshed?.(result.access_token, result.expires_in);\n this.scheduleKeepSession(\n this.sessionRefreshToken,\n result.expires_in,\n refreshFn,\n );\n } catch (err) {\n this.clearRefreshTimer();\n this.onSessionExpired?.(\n err instanceof Error ? err : new Error(String(err)),\n );\n }\n }, delayMs);\n }\n\n /** @deprecated \uC138\uC158 \uC5F0\uC7A5\uC740 health tick \uAE30\uBC18 \uBD80\uD2B8\uC2A4\uD2B8\uB7A9\uC73C\uB85C \uB300\uCCB4\uB418\uC5C8\uC2B5\uB2C8\uB2E4. */\n clearRefreshTimer(): void {\n if (this.refreshTimer !== null) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n /**\n * \uC138\uC158 \uC790\uB3D9 \uC5F0\uC7A5\uC744 \uC911\uC9C0\uD569\uB2C8\uB2E4.\n * `logout()` \uD638\uCD9C \uC2DC \uC790\uB3D9\uC73C\uB85C \uC911\uC9C0\uB418\uBA70, \uC9C1\uC811 \uD638\uCD9C\uC774 \uD544\uC694\uD55C \uACBD\uC6B0\uB294 \uB4DC\uBB45\uB2C8\uB2E4.\n */\n stopKeepSession(): void {\n this.clearRefreshTimer();\n this.sessionRefreshToken = null;\n }\n\n applyRealtimeOptions(options?: boolean | RealtimeClientOptions): void {\n const normalized: RealtimeClientOptions =\n typeof options === \"boolean\"\n ? { enabled: options }\n : (options ?? {});\n\n this.realtimeEnabled = normalized.enabled ?? false;\n this.realtimePath =\n String(normalized.path ?? REALTIME_DEFAULT_PATH).trim() ||\n REALTIME_DEFAULT_PATH;\n this.realtimeAutoReconnect = normalized.autoReconnect ?? true;\n this.realtimeReconnectDelayMs = Math.max(\n 250,\n normalized.reconnectDelayMs ?? 3000,\n );\n\n if (!this.realtimeEnabled) {\n this.disconnectRealtime(\"realtime_disabled\");\n return;\n }\n\n this.setRealtimeStatus(\"idle\", \"realtime_enabled\");\n }\n\n buildRealtimeUrl(): string {\n const rawBaseUrl =\n this.baseUrl || readEnv(\"VITE_ENTITY_SERVER_URL\") || \"\";\n const origin =\n typeof window !== \"undefined\" ? window.location.origin : \"\";\n const baseUrl = rawBaseUrl || origin;\n\n if (!baseUrl) {\n throw new Error(\"Realtime connection requires baseUrl.\");\n }\n\n const url = new URL(baseUrl, origin || undefined);\n const basePath =\n url.pathname === \"/\" ? \"\" : url.pathname.replace(/\\/+$/, \"\");\n const realtimePath = `/${this.realtimePath.replace(/^\\/+/, \"\")}`;\n\n url.pathname = `${basePath}${realtimePath}` || realtimePath;\n url.search = \"\";\n url.hash = \"\";\n url.protocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n url.searchParams.set(\"access_token\", this.token);\n return url.toString();\n }\n\n handleRealtimeMessage(payload: unknown): void {\n if (typeof payload !== \"string\") {\n return;\n }\n\n let envelope: RealtimeEnvelope;\n try {\n envelope = JSON.parse(payload) as RealtimeEnvelope;\n } catch {\n return;\n }\n\n for (const listener of this.realtimeMessageListeners) {\n listener(envelope);\n }\n\n const listeners = this.realtimeEventListeners.get(envelope.event);\n if (listeners) {\n for (const listener of listeners) {\n listener(envelope);\n }\n }\n }\n\n scheduleRealtimeReconnect(reason: string): void {\n this.clearRealtimeReconnectTimer();\n this.realtimeReconnectTimer = setTimeout(() => {\n this.realtimeReconnectTimer = null;\n if (!this.realtimeEnabled || !this.token) {\n return;\n }\n this.setRealtimeStatus(\"connecting\", `${reason}:reconnect`);\n void this.connectRealtime().catch(() => {});\n }, this.realtimeReconnectDelayMs);\n }\n\n clearRealtimeReconnectTimer(): void {\n if (this.realtimeReconnectTimer !== null) {\n clearTimeout(this.realtimeReconnectTimer);\n this.realtimeReconnectTimer = null;\n }\n }\n\n setRealtimeStatus(\n status: RealtimeConnectionStatus,\n reason?: string,\n error?: Error,\n ): void {\n const previousStatus = this.realtimeStatus;\n if (\n previousStatus === status &&\n typeof reason === \"undefined\" &&\n typeof error === \"undefined\"\n ) {\n return;\n }\n\n this.realtimeStatus = status;\n for (const listener of this.realtimeStatusListeners) {\n listener({\n status,\n previousStatus,\n ...(reason ? { reason } : {}),\n ...(error ? { error } : {}),\n });\n }\n }\n\n applyCsrfHealth(): void {\n if (typeof document === \"undefined\") return;\n for (const chunk of document.cookie.split(\";\")) {\n const idx = chunk.indexOf(\"=\");\n if (idx < 0) continue;\n if (chunk.substring(0, idx).trim() === this.csrfCookieName) {\n this.csrfEnabled = !!chunk.substring(idx + 1).trim();\n return;\n }\n }\n this.csrfEnabled = false;\n }\n\n // \u2500\u2500\u2500 \uC694\uCCAD \uBCF8\uBB38 \uD30C\uC2F1 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * \uC694\uCCAD \uBC14\uB514\uB97C \uD30C\uC2F1\uD569\uB2C8\uB2E4.\n * `application/octet-stream`\uC774\uBA74 XChaCha20-Poly1305 \uBCF5\uD638\uD654, \uADF8 \uC678\uB294 JSON \uD30C\uC2F1\uD569\uB2C8\uB2E4.\n *\n * @param requireEncrypted `true`\uC774\uBA74 \uC554\uD638\uD654\uB41C \uC694\uCCAD\uB9CC \uD5C8\uC6A9\uD569\uB2C8\uB2E4.\n */\n readRequestBody<T = Record<string, unknown>>(\n body: ArrayBuffer | Uint8Array | string | T | null | undefined,\n contentType = \"application/json\",\n requireEncrypted = false,\n ): T {\n const key = derivePacketKey(\n this.hmacSecret,\n this.token || this.anonymousPacketToken,\n );\n return parseRequestBody<T>(body, contentType, requireEncrypted, key);\n }\n\n // \u2500\u2500\u2500 \uB0B4\uBD80 \uD5EC\uD37C \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n get reqOpts(): RequestOptions {\n return {\n baseUrl: this.baseUrl,\n token: this.token,\n anonymousPacketToken: this.anonymousPacketToken,\n apiKey: this.apiKey,\n hmacSecret: this.hmacSecret,\n encryptRequests: this.encryptRequests,\n csrfEnabled: this.csrfEnabled,\n csrfHeaderName: this.csrfHeaderName,\n csrfCookieName: this.csrfCookieName,\n refreshCsrfCookie: this.csrfEnabled ? this.csrfRefresher : null,\n requestAbortControllers: this.requestAbortControllers,\n debugPlainSecret: this.debugPlainSecret,\n onAccessToken: (token) => {\n this.setAccessTokenFromResponse(token);\n },\n };\n }\n\n // \uC778\uC99D \uC694\uCCAD \uC804\uC5D0 \uD544\uC694\uD55C \uD074\uB77C\uC774\uC5B8\uD2B8 \uC900\uBE44 \uC791\uC5C5\uC744 \uC218\uD589\uD569\uB2C8\uB2E4.\n prepareRequest(_withAuth: boolean): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * \uCEE4\uC2A4\uD140 \uB77C\uC6B0\uD2B8 \uC9C1\uC811 \uD638\uCD9C\uC6A9 HTTP \uB124\uC784\uC2A4\uD398\uC774\uC2A4.\n * \uC778\uC99D\u00B7\uC554\uD638\uD654\u00B7HMAC \uB4F1 SDK \uC635\uC158\uC774 \uADF8\uB300\uB85C \uC801\uC6A9\uB429\uB2C8\uB2E4.\n *\n * @example\n * const res = await client.http.get<{ version: string }>(\"/api/v1/status\", false);\n * const res = await client.http.post<MyResponse>(\"/api/v1/custom\", { key: \"value\" });\n */\n get http() {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n return {\n get<T>(\n path: string,\n withAuth = true,\n extraHeaders?: Record<string, string>,\n requestConfig?: EntityRequestConfig,\n ): Promise<T> {\n return self\n .prepareRequest(withAuth)\n .then(() =>\n entityRequest<T>(\n self.reqOpts,\n \"GET\",\n path,\n undefined,\n withAuth,\n extraHeaders,\n requestConfig ?? true,\n ),\n );\n },\n post<T>(\n path: string,\n body?: unknown,\n withAuth = true,\n extraHeaders?: Record<string, string>,\n requestConfig?: EntityRequestConfig,\n ): Promise<T> {\n return self\n .prepareRequest(withAuth)\n .then(() =>\n entityRequest<T>(\n self.reqOpts,\n \"POST\",\n path,\n body,\n withAuth,\n extraHeaders,\n requestConfig ?? true,\n ),\n );\n },\n put<T>(\n path: string,\n body?: unknown,\n withAuth = true,\n extraHeaders?: Record<string, string>,\n requestConfig?: EntityRequestConfig,\n ): Promise<T> {\n return self\n .prepareRequest(withAuth)\n .then(() =>\n entityRequest<T>(\n self.reqOpts,\n \"PUT\",\n path,\n body,\n withAuth,\n extraHeaders,\n requestConfig ?? true,\n ),\n );\n },\n patch<T>(\n path: string,\n body?: unknown,\n withAuth = true,\n extraHeaders?: Record<string, string>,\n requestConfig?: EntityRequestConfig,\n ): Promise<T> {\n return self\n .prepareRequest(withAuth)\n .then(() =>\n entityRequest<T>(\n self.reqOpts,\n \"PATCH\",\n path,\n body,\n withAuth,\n extraHeaders,\n requestConfig ?? true,\n ),\n );\n },\n delete<T>(\n path: string,\n body?: unknown,\n withAuth = true,\n extraHeaders?: Record<string, string>,\n requestConfig?: EntityRequestConfig,\n ): Promise<T> {\n return self\n .prepareRequest(withAuth)\n .then(() =>\n entityRequest<T>(\n self.reqOpts,\n \"DELETE\",\n path,\n body,\n withAuth,\n extraHeaders,\n requestConfig ?? true,\n ),\n );\n },\n };\n }\n\n request<T>(\n method: string,\n path: string,\n body?: unknown,\n withAuth = true,\n extraHeaders?: Record<string, string>,\n requestConfig?: EntityRequestConfig,\n ): Promise<T> {\n return this.prepareRequest(withAuth).then(() =>\n entityRequest<T>(\n this.reqOpts,\n method,\n path,\n body,\n withAuth,\n extraHeaders,\n requestConfig ?? true,\n ),\n );\n }\n\n /** PNG/\uBC14\uC774\uB108\uB9AC \uC751\uB2F5\uC744 ArrayBuffer\uB85C \uBC18\uD658\uD569\uB2C8\uB2E4. (QR, \uBC14\uCF54\uB4DC \uB4F1) */\n async requestBinary(\n method: string,\n path: string,\n body?: unknown,\n withAuth = true,\n ): Promise<ArrayBuffer> {\n await this.prepareRequest(withAuth);\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (withAuth && this.token)\n headers[\"Authorization\"] = `Bearer ${this.token}`;\n if (this.apiKey) headers[\"X-API-Key\"] = this.apiKey;\n\n const res = await fetch(this.baseUrl + path, {\n method,\n headers,\n ...(body != null ? { body: JSON.stringify(body) } : {}),\n credentials: \"include\",\n });\n\n if (!res.ok) {\n const text = await res.text();\n const err = new Error(`HTTP ${res.status}: ${text}`);\n (err as { status?: number }).status = res.status;\n throw err;\n }\n\n return res.arrayBuffer();\n }\n\n /** multipart/form-data \uC694\uCCAD\uC744 \uBCF4\uB0C5\uB2C8\uB2E4. (\uD30C\uC77C \uC5C5\uB85C\uB4DC \uB4F1) */\n async requestForm<T>(\n method: string,\n path: string,\n form: FormData,\n withAuth = true,\n ): Promise<T> {\n // \uD328\uD0B7 \uC554\uD638\uD654\uAC00 \uCF1C\uC9C4 \uC11C\uBC84\uB294 \uC751\uB2F5\uC744 octet-stream \uC73C\uB85C \uC554\uD638\uD654\uD574 \uB0B4\uB824\uC904 \uC218 \uC788\uC73C\uBBC0\uB85C,\n // \uC77C\uBC18 \uC694\uCCAD\uACFC \uB3D9\uC77C\uD55C \uD5E4\uB354(X-Debug-Plain/X-Packet-Token/HMAC)\uC640 \uC751\uB2F5 \uBCF5\uD638\uD654 \uCC98\uB9AC\uB97C \uACF5\uC720\uD55C\uB2E4.\n await this.prepareRequest(withAuth);\n return requestFormData<T>(this.reqOpts, method, path, form, withAuth);\n }\n\n /** multipart/form-data \uC694\uCCAD\uC744 \uBCF4\uB0B4\uACE0 \uBC14\uC774\uB108\uB9AC(ArrayBuffer)\uB97C \uBC18\uD658\uD569\uB2C8\uB2E4. */\n async requestFormBinary(\n method: string,\n path: string,\n form: FormData,\n withAuth = true,\n ): Promise<ArrayBuffer> {\n const headers: Record<string, string> = {};\n if (withAuth && this.token)\n headers[\"Authorization\"] = `Bearer ${this.token}`;\n if (this.apiKey) headers[\"X-API-Key\"] = this.apiKey;\n\n const res = await fetch(this.baseUrl + path, {\n method,\n headers,\n body: form,\n credentials: \"include\",\n });\n\n if (!res.ok) {\n const text = await res.text();\n const err = new Error(`HTTP ${res.status}: ${text}`);\n (err as { status?: number }).status = res.status;\n throw err;\n }\n\n return res.arrayBuffer();\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["readEnv", "derivePacketKey", "parseRequestBody", "entityRequest", "requestFormData", "REALTIME_DEFAULT_PATH", "EntityServerClientBase", "options", "envBaseUrl", "self", "token", "apiKey", "secret", "value", "enabled", "listener", "eventName", "key", "listeners", "socket", "resolve", "reject", "settled", "finalizeResolve", "finalizeReject", "error", "event", "reason", "message", "subscriptions", "intervalMs", "runImmediately", "tick", "refreshToken", "expiresIn", "refreshFn", "delayMs", "result", "err", "normalized", "rawBaseUrl", "origin", "baseUrl", "url", "basePath", "realtimePath", "payload", "envelope", "status", "previousStatus", "chunk", "idx", "body", "contentType", "requireEncrypted", "_withAuth", "path", "withAuth", "extraHeaders", "requestConfig", "method", "headers", "res", "text", "form"]
|
|
7
7
|
}
|
package/dist/client/request.d.ts
CHANGED
|
@@ -37,3 +37,15 @@ export interface EntityRequestError extends Error {
|
|
|
37
37
|
* - JSON 응답의 `ok`가 false이면 에러를 던집니다.
|
|
38
38
|
*/
|
|
39
39
|
export declare function entityRequest<T>(opts: RequestOptions, method: string, path: string, body?: unknown, withAuth?: boolean, extraHeaders?: Record<string, string>, config?: boolean | EntityRequestConfig): Promise<T>;
|
|
40
|
+
/**
|
|
41
|
+
* multipart/form-data(파일 업로드) 요청을 패킷 암호화와 무관하게 보낸다.
|
|
42
|
+
*
|
|
43
|
+
* 파일 업로드는 요청 본문(FormData)을 암호화하지 않는다. 서버가 multipart 를 그대로 파싱하기 때문이다.
|
|
44
|
+
* 다만 패킷 암호화가 켜진 서버는 **응답**을 `application/octet-stream` 으로 암호화해 내려줄 수 있으므로,
|
|
45
|
+
* 일반 `entityRequest` 와 동일하게 `X-Debug-Plain`/`X-Packet-Token`/HMAC 헤더를 실어 보내고
|
|
46
|
+
* 응답 Content-Type 에 따라 (octet-stream 이면 복호화, 아니면 JSON) 자동 처리한다.
|
|
47
|
+
*
|
|
48
|
+
* 기존 raw `fetch + res.json()` 방식은 암호화 응답을 복호화하지 못해
|
|
49
|
+
* `Unexpected token '...' is not valid JSON` 으로 깨졌다. (HTTP 200 이어도)
|
|
50
|
+
*/
|
|
51
|
+
export declare function requestFormData<T>(opts: RequestOptions, method: string, path: string, form: FormData, withAuth?: boolean): Promise<T>;
|
package/dist/client/request.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{derivePacketKey as
|
|
1
|
+
import{derivePacketKey as M,encryptPacket as W,decryptPacket as z}from"./packet.js";import{buildHmacHeaders as Y}from"./hmac.js";function Z(e){switch(e.toUpperCase()){case"POST":case"PUT":case"PATCH":case"DELETE":return!0;default:return!1}}function ee(e,t,n){if(n.autoAbortKey===!1)return null;if(typeof n.autoAbortKey=="string"){const o=n.autoAbortKey.trim();return o||null}return typeof window>"u"?null:Z(e)?`${e.toUpperCase()} ${t}`:null}function te(e){const t=e.filter(s=>!!s);if(t.length===0)return;if(t.length===1)return t[0];if(typeof AbortSignal.any=="function")return AbortSignal.any(t);const n=new AbortController,o=()=>n.abort();for(const s of t){if(s.aborted){n.abort();break}s.addEventListener("abort",o,{once:!0})}return n.signal}function ne(e,t,n,o){const s=ee(t,n,o);if(!s)return{signal:o.signal,abortKey:null,controller:null};e.requestAbortControllers.get(s)?.abort();const b=new AbortController;return e.requestAbortControllers.set(s,b),{signal:te([o.signal,b.signal]),abortKey:s,controller:b}}function re(e,t,n){!t||!n||e.requestAbortControllers.get(t)===n&&e.requestAbortControllers.delete(t)}function oe(e){return e.hmacSecret||e.token||e.anonymousPacketToken}function F(e,t,n){return e.hmacSecret?e.hmacSecret:t&&e.token||n}function se(e){return e?e.length<=8?`${e.slice(0,2)}...${e.slice(-2)}`:`${e.slice(0,4)}...${e.slice(-4)}`:""}function G(e){typeof console>"u"||typeof console.error!="function"||console.error("[entity-client] packet decrypt failed",{method:e.method,path:e.path,withAuth:e.withAuth,status:e.status,contentType:e.contentType,responsePacketSource:se(e.responsePacketSource),tokenPresent:e.tokenPresent,anonymousPacketTokenPresent:e.anonymousPacketTokenPresent,hmacEnabled:e.hmacEnabled,error:e.error instanceof Error?{name:e.error.name,message:e.error.message,stack:e.error.stack}:e.error})}function J(e){return e!=="GET"&&e!=="HEAD"&&e!=="OPTIONS"}function k(e){if(typeof document>"u")return"";for(const t of document.cookie.split(";")){const n=t.indexOf("=");if(!(n<0)&&t.substring(0,n).trim()===e)return decodeURIComponent(t.substring(n+1).trim())}return""}function _(e,t){return e===403&&/csrf/i.test(t)?!0:/csrf/i.test(t)&&/expired|token validation failed/i.test(t)}function ae(e,t){return e===401&&/nonce already used/i.test(t)}async function j(e){if((e.headers.get("Content-Type")??"").includes("application/json")){const o=await e.json().catch(()=>null);if(o?.error)return{message:o.error,code:o.code,body:o};if(o?.message)return{message:o.message,code:o.code,body:o}}return{message:await e.text().catch(()=>"")||`HTTP ${e.status}`}}function X(e,t){const n=new Error(t.message);return n.status=e,t.code&&(n.code=t.code),t.body&&(n.details=t.body),n}async function ue(e,t,n,o,s=!0,b={},m=!0){const p=typeof m=="boolean"?{requireOkShape:m}:m,h=p.requireOkShape??!0,C=new Set(p.allowStatuses??[]),q=ne(e,t,n,p),R=q.signal,{baseUrl:E,token:T,apiKey:H,hmacSecret:l,encryptRequests:P,csrfEnabled:U,csrfHeaderName:S,csrfCookieName:O,refreshCsrfCookie:f,onAccessToken:B,debugPlainSecret:w}=e,a=e.anonymousPacketToken||k("anon_token"),g=s&&!!(H&&l),$=oe(e),A=F(e,s,a),u=U&&J(t)&&!g;let i=u?k(O):"",x="application/json";const N=!g&&!!a;let d=null;if(o!=null)if(!w&&P&&!!$&&s&&t!=="GET"&&t!=="HEAD"){const c=M(l,T||a);d=W(new TextEncoder().encode(JSON.stringify(o)),c),x="application/octet-stream"}else d=JSON.stringify(o);const Q=r=>{const c={...b},D=Object.keys(c).some(y=>y.toLowerCase()==="content-type");if(d!=null&&!D&&(c["Content-Type"]=x),!g&&s&&T&&(c.Authorization=`Bearer ${T}`),N&&(c["X-Packet-Token"]=a),w&&(c["X-Debug-Plain"]=w),u&&r&&(c[S]=r),g){const y=d instanceof Uint8Array?d:typeof d=="string"?new TextEncoder().encode(d):new Uint8Array(0);Object.assign(c,Y(t,n,y,H,l))}return c};u&&!i&&f&&(await f(),i=k(O));const v=r=>fetch(E+n,{method:t,headers:Q(r),...d!=null?{body:d}:{},credentials:"include",signal:R});try{let r=await v(i);if(!r.ok){const K=await j(r.clone());if(g&&ae(r.status,K.message))r=await v(i);else if(u&&f&&_(r.status,K.message))await f(),i=k(O),r=await v(i);else if(!C.has(r.status))throw X(r.status,K)}if(!r.ok&&!C.has(r.status))throw X(r.status,await j(r));const c=r.headers.get("X-Access-Token")?.trim()??"",D=r.headers.get("Content-Type")??"";if(D.includes("application/octet-stream")){const K=M(l,A),V=await r.arrayBuffer();let I;try{I=z(V,K)}catch(L){throw G({method:t,path:n,withAuth:s,status:r.status,contentType:D,responsePacketSource:A,tokenPresent:!!T,anonymousPacketTokenPresent:!!a,hmacEnabled:!!l,error:L}),L}return c&&B?.(c),I}if(c&&B?.(c),!D.includes("application/json"))return await r.text();const y=await r.json();if(h&&!y.ok&&!C.has(r.status))throw X(r.status,{message:y.message??`EntityServer error (HTTP ${r.status})`,code:y.code,body:y});return y}finally{re(e,q.abortKey,q.controller)}}async function le(e,t,n,o,s=!0){const{baseUrl:b,token:m,apiKey:p,hmacSecret:h,csrfEnabled:C,csrfHeaderName:q,csrfCookieName:R,refreshCsrfCookie:E,onAccessToken:T,debugPlainSecret:H}=e,l=e.anonymousPacketToken||k("anon_token"),P=s&&!!(p&&h),U=F(e,s,l),S=C&&J(t)&&!P,O=!P&&!!l;let f=S?k(R):"";S&&!f&&E&&(await E(),f=k(R));const B=u=>{const i={};return!P&&s&&m&&(i.Authorization=`Bearer ${m}`),P&&p&&(i["X-API-Key"]=p),O&&(i["X-Packet-Token"]=l),H&&(i["X-Debug-Plain"]=H),S&&u&&(i[q]=u),i},w=u=>fetch(b+n,{method:t,headers:B(u),body:o,credentials:"include"});let a=await w(f);if(!a.ok&&S&&E&&_(a.status,(await j(a.clone())).message)&&(await E(),f=k(R),a=await w(f)),!a.ok)throw X(a.status,await j(a));const g=a.headers.get("X-Access-Token")?.trim()??"",$=a.headers.get("Content-Type")??"";if($.includes("application/octet-stream")){const u=M(h,U),i=await a.arrayBuffer();let x;try{x=z(i,u)}catch(N){throw G({method:t,path:n,withAuth:s,status:a.status,contentType:$,responsePacketSource:U,tokenPresent:!!m,anonymousPacketTokenPresent:!!l,hmacEnabled:!!h,error:N}),N}return g&&T?.(g),x}g&&T?.(g);const A=await a.json();if(!A.ok){const u=new Error(A.message??`EntityServer error (HTTP ${a.status})`);throw u.status=a.status,u}return A}export{ue as entityRequest,le as requestFormData};
|
|
2
2
|
//# sourceMappingURL=request.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/client/request.ts"],
|
|
4
|
-
"sourcesContent": ["import { derivePacketKey, encryptPacket, decryptPacket } from \"./packet.js\";\nimport { buildHmacHeaders } from \"./hmac.js\";\n\nexport interface RequestOptions {\n baseUrl: string;\n token: string;\n anonymousPacketToken: string;\n apiKey: string;\n hmacSecret: string;\n encryptRequests: boolean;\n csrfEnabled: boolean;\n csrfHeaderName: string;\n csrfCookieName: string;\n refreshCsrfCookie: (() => Promise<void>) | null;\n onAccessToken?: (token: string) => void;\n requestAbortControllers: Map<string, AbortController>;\n /**\n * dev \uB514\uBC84\uADF8 \uD3C9\uBB38 \uC2DC\uD06C\uB9BF. \uC124\uC815\uB418\uBA74 \uC694\uCCAD\uC744 \uC554\uD638\uD654\uD558\uC9C0 \uC54A\uACE0(\uD3C9\uBB38),\n * `X-Debug-Plain` \uD5E4\uB354\uB85C \uC804\uC1A1\uD55C\uB2E4. \uC11C\uBC84\uC758 `DEBUG_PLAIN_SECRET` \uACFC \uC77C\uCE58\uD558\uBA74\n * \uC11C\uBC84\uB3C4 \uD574\uB2F9 \uC694\uCCAD/\uC751\uB2F5\uC744 \uD3C9\uBB38\uC73C\uB85C \uCC98\uB9AC\uD55C\uB2E4(\uD328\uD0B7 \uC554\uD638\uD654 \uC6B0\uD68C).\n */\n debugPlainSecret?: string;\n}\n\nexport interface EntityRequestConfig {\n requireOkShape?: boolean;\n allowStatuses?: number[];\n signal?: AbortSignal;\n autoAbortKey?: string | false;\n}\n\nexport interface EntityRequestError extends Error {\n status?: number;\n code?: string;\n details?: unknown;\n}\n\ninterface EntityErrorBody {\n error?: string;\n message?: string;\n code?: string;\n [key: string]: unknown;\n}\n\ninterface EntityErrorDetails {\n message: string;\n code?: string;\n body?: EntityErrorBody;\n}\n\n// isAutoAbortableMethod\uB294 \uAE30\uBCF8 \uC790\uB3D9 \uCDE8\uC18C \uD0A4\uB97C \uD5C8\uC6A9\uD558\uB294 \uC4F0\uAE30 \uBA54\uC11C\uB4DC\uC778\uC9C0 \uD655\uC778\uD569\uB2C8\uB2E4.\nfunction isAutoAbortableMethod(method: string): boolean {\n switch (method.toUpperCase()) {\n case \"POST\":\n case \"PUT\":\n case \"PATCH\":\n case \"DELETE\":\n return true;\n default:\n return false;\n }\n}\n\n// resolveAutoAbortKey\uB294 \uC694\uCCAD\uBCC4 \uC790\uB3D9 \uCDE8\uC18C \uD0A4\uB97C \uACC4\uC0B0\uD569\uB2C8\uB2E4.\nfunction resolveAutoAbortKey(\n method: string,\n path: string,\n config: EntityRequestConfig,\n): string | null {\n if (config.autoAbortKey === false) {\n return null;\n }\n\n if (typeof config.autoAbortKey === \"string\") {\n const trimmed = config.autoAbortKey.trim();\n return trimmed ? trimmed : null;\n }\n\n if (isAutoAbortableMethod(method)) {\n return `${method.toUpperCase()} ${path}`;\n }\n\n return null;\n}\n\n// composeAbortSignal\uC740 \uC678\uBD80 signal\uACFC \uB0B4\uBD80 \uCDE8\uC18C signal\uC744 \uD558\uB098\uB85C \uD569\uCE69\uB2C8\uB2E4.\nfunction composeAbortSignal(\n signals: Array<AbortSignal | undefined>,\n): AbortSignal | undefined {\n const activeSignals = signals.filter(\n (signal): signal is AbortSignal => !!signal,\n );\n if (activeSignals.length === 0) {\n return undefined;\n }\n if (activeSignals.length === 1) {\n return activeSignals[0];\n }\n if (typeof AbortSignal.any === \"function\") {\n return AbortSignal.any(activeSignals);\n }\n\n const controller = new AbortController();\n const abort = () => controller.abort();\n for (const signal of activeSignals) {\n if (signal.aborted) {\n controller.abort();\n break;\n }\n signal.addEventListener(\"abort\", abort, { once: true });\n }\n return controller.signal;\n}\n\n// createManagedAbortSignal\uC740 \uAC19\uC740 \uD0A4\uC758 \uC774\uC804 \uC694\uCCAD\uC744 \uCDE8\uC18C\uD558\uACE0 \uD604\uC7AC \uC694\uCCAD signal\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4.\nfunction createManagedAbortSignal(\n opts: RequestOptions,\n method: string,\n path: string,\n requestConfig: EntityRequestConfig,\n): {\n signal?: AbortSignal;\n abortKey: string | null;\n controller: AbortController | null;\n} {\n const abortKey = resolveAutoAbortKey(method, path, requestConfig);\n if (!abortKey) {\n return {\n signal: requestConfig.signal,\n abortKey: null,\n controller: null,\n };\n }\n\n opts.requestAbortControllers.get(abortKey)?.abort();\n\n const controller = new AbortController();\n opts.requestAbortControllers.set(abortKey, controller);\n\n return {\n signal: composeAbortSignal([requestConfig.signal, controller.signal]),\n abortKey,\n controller,\n };\n}\n\n// clearManagedAbortSignal\uC740 \uD604\uC7AC \uC694\uCCAD\uC774 \uB4F1\uB85D\uD55C \uCDE8\uC18C \uD0A4\uB9CC \uC548\uC804\uD558\uAC8C \uC815\uB9AC\uD569\uB2C8\uB2E4.\nfunction clearManagedAbortSignal(\n opts: RequestOptions,\n abortKey: string | null,\n controller: AbortController | null,\n): void {\n if (!abortKey || !controller) {\n return;\n }\n if (opts.requestAbortControllers.get(abortKey) === controller) {\n opts.requestAbortControllers.delete(abortKey);\n }\n}\n\nfunction resolvePacketSource(opts: RequestOptions): string {\n return opts.hmacSecret || opts.token || opts.anonymousPacketToken;\n}\n\nfunction resolveResponsePacketSource(\n opts: RequestOptions,\n withAuth: boolean,\n anonymousPacketToken: string,\n): string {\n if (opts.hmacSecret) {\n return opts.hmacSecret;\n }\n\n if (!withAuth) {\n return anonymousPacketToken;\n }\n\n return opts.token || anonymousPacketToken;\n}\n\nfunction maskPacketSource(value: string): string {\n if (!value) {\n return \"\";\n }\n\n if (value.length <= 8) {\n return `${value.slice(0, 2)}...${value.slice(-2)}`;\n }\n\n return `${value.slice(0, 4)}...${value.slice(-4)}`;\n}\n\nfunction logPacketDecryptError(details: {\n method: string;\n path: string;\n withAuth: boolean;\n status: number;\n contentType: string;\n responsePacketSource: string;\n tokenPresent: boolean;\n anonymousPacketTokenPresent: boolean;\n hmacEnabled: boolean;\n error: unknown;\n}): void {\n if (typeof console === \"undefined\" || typeof console.error !== \"function\") {\n return;\n }\n\n console.error(\"[entity-client] packet decrypt failed\", {\n method: details.method,\n path: details.path,\n withAuth: details.withAuth,\n status: details.status,\n contentType: details.contentType,\n responsePacketSource: maskPacketSource(details.responsePacketSource),\n tokenPresent: details.tokenPresent,\n anonymousPacketTokenPresent: details.anonymousPacketTokenPresent,\n hmacEnabled: details.hmacEnabled,\n error:\n details.error instanceof Error\n ? {\n name: details.error.name,\n message: details.error.message,\n stack: details.error.stack,\n }\n : details.error,\n });\n}\n\nfunction requiresCsrf(method: string): boolean {\n return method !== \"GET\" && method !== \"HEAD\" && method !== \"OPTIONS\";\n}\n\nfunction readCsrfCookie(name: string): string {\n if (typeof document === \"undefined\") return \"\";\n for (const chunk of document.cookie.split(\";\")) {\n const idx = chunk.indexOf(\"=\");\n if (idx < 0) continue;\n if (chunk.substring(0, idx).trim() === name) {\n return decodeURIComponent(chunk.substring(idx + 1).trim());\n }\n }\n return \"\";\n}\n\nfunction isCsrfError(status: number, message: string): boolean {\n if (status === 403 && /csrf/i.test(message)) {\n return true;\n }\n\n return (\n /csrf/i.test(message) &&\n /expired|token validation failed/i.test(message)\n );\n}\n\n// HMAC nonce \uC7AC\uC0AC\uC6A9 \uC751\uB2F5\uC778\uC9C0 \uD655\uC778\uD569\uB2C8\uB2E4.\nfunction isHmacNonceReuseError(status: number, message: string): boolean {\n return status === 401 && /nonce already used/i.test(message);\n}\n\n// readErrorDetails\uB294 \uC5D0\uB7EC \uC751\uB2F5 \uBCF8\uBB38\uC5D0\uC11C \uBA54\uC2DC\uC9C0\uC640 \uCF54\uB4DC\uB97C \uCD94\uCD9C\uD569\uB2C8\uB2E4.\nasync function readErrorDetails(res: Response): Promise<EntityErrorDetails> {\n const contentType = res.headers.get(\"Content-Type\") ?? \"\";\n if (contentType.includes(\"application/json\")) {\n const data = (await res\n .json()\n .catch(() => null)) as EntityErrorBody | null;\n if (data?.error)\n return { message: data.error, code: data.code, body: data };\n if (data?.message)\n return { message: data.message, code: data.code, body: data };\n }\n\n const text = await res.text().catch(() => \"\");\n return { message: text || `HTTP ${res.status}` };\n}\n\n// createEntityRequestError\uB294 HTTP \uC5D0\uB7EC \uC815\uBCF4\uB97C Error \uAC1D\uCCB4\uC5D0 \uBCF4\uC874\uD569\uB2C8\uB2E4.\nfunction createEntityRequestError(\n status: number,\n details: EntityErrorDetails,\n): EntityRequestError {\n const err = new Error(details.message) as EntityRequestError;\n err.status = status;\n if (details.code) {\n err.code = details.code;\n }\n if (details.body) {\n err.details = details.body;\n }\n return err;\n}\n\n/**\n * Entity Server\uC5D0 HTTP \uC694\uCCAD\uC744 \uBCF4\uB0C5\uB2C8\uB2E4.\n *\n * - `encryptRequests` \uD65C\uC131\uD654 \uC2DC \uC778\uC99D\uB41C POST \uBC14\uB514\uB97C \uC790\uB3D9 \uC554\uD638\uD654\uD569\uB2C8\uB2E4.\n * - \uC751\uB2F5\uC774 `application/octet-stream`\uC774\uBA74 \uC790\uB3D9 \uBCF5\uD638\uD654\uD569\uB2C8\uB2E4.\n * - JSON \uC751\uB2F5\uC758 `ok`\uAC00 false\uC774\uBA74 \uC5D0\uB7EC\uB97C \uB358\uC9D1\uB2C8\uB2E4.\n */\nexport async function entityRequest<T>(\n opts: RequestOptions,\n method: string,\n path: string,\n body?: unknown,\n withAuth = true,\n extraHeaders: Record<string, string> = {},\n config: boolean | EntityRequestConfig = true,\n): Promise<T> {\n const requestConfig: EntityRequestConfig =\n typeof config === \"boolean\" ? { requireOkShape: config } : config;\n const requireOkShape = requestConfig.requireOkShape ?? true;\n const allowStatuses = new Set(requestConfig.allowStatuses ?? []);\n const managedAbort = createManagedAbortSignal(\n opts,\n method,\n path,\n requestConfig,\n );\n const signal = managedAbort.signal;\n\n const {\n baseUrl,\n token,\n apiKey,\n hmacSecret,\n encryptRequests,\n csrfEnabled,\n csrfHeaderName,\n csrfCookieName,\n refreshCsrfCookie,\n onAccessToken,\n debugPlainSecret,\n } = opts;\n // checkHealth()\uAC00 \uC644\uB8CC\uB418\uAE30 \uC804 race condition\uC744 \uB9C9\uAE30 \uC704\uD574 anon_token \uCFE0\uD0A4\uB97C \uC9C1\uC811 fallback\uC73C\uB85C \uC77D\uC74C\n const anonymousPacketToken =\n opts.anonymousPacketToken || readCsrfCookie(\"anon_token\");\n const isHmacMode = withAuth && !!(apiKey && hmacSecret);\n const packetSource = resolvePacketSource(opts);\n const responsePacketSource = resolveResponsePacketSource(\n opts,\n withAuth,\n anonymousPacketToken,\n );\n const shouldUseCsrf = csrfEnabled && requiresCsrf(method) && !isHmacMode;\n let csrfToken = shouldUseCsrf ? readCsrfCookie(csrfCookieName) : \"\";\n let requestContentType = \"application/json\";\n const includeAnonymousPacketHeader = !isHmacMode && !!anonymousPacketToken;\n\n let fetchBody: string | Uint8Array | null = null;\n if (body != null) {\n const shouldEncrypt =\n !debugPlainSecret &&\n encryptRequests &&\n !!packetSource &&\n withAuth &&\n method !== \"GET\" &&\n method !== \"HEAD\";\n\n if (shouldEncrypt) {\n const key = derivePacketKey(\n hmacSecret,\n token || anonymousPacketToken,\n );\n fetchBody = encryptPacket(\n new TextEncoder().encode(JSON.stringify(body)),\n key,\n );\n requestContentType = \"application/octet-stream\";\n } else {\n fetchBody = JSON.stringify(body);\n }\n }\n\n const buildHeaders = (\n resolvedCsrfToken: string,\n ): Record<string, string> => {\n const headers: Record<string, string> = { ...extraHeaders };\n const hasExplicitContentType = Object.keys(headers).some(\n (key) => key.toLowerCase() === \"content-type\",\n );\n if (fetchBody != null && !hasExplicitContentType) {\n headers[\"Content-Type\"] = requestContentType;\n }\n if (!isHmacMode && withAuth && token) {\n headers.Authorization = `Bearer ${token}`;\n }\n if (includeAnonymousPacketHeader) {\n headers[\"X-Packet-Token\"] = anonymousPacketToken;\n }\n // dev \uB514\uBC84\uADF8 \uBC14\uC774\uD328\uC2A4: \uC11C\uBC84\uAC00 \uD3C9\uBB38 \uCC98\uB9AC\uD558\uB3C4\uB85D \uC2DC\uD06C\uB9BF \uD5E4\uB354\uB97C \uBCF4\uB0B8\uB2E4.\n if (debugPlainSecret) {\n headers[\"X-Debug-Plain\"] = debugPlainSecret;\n }\n if (shouldUseCsrf && resolvedCsrfToken) {\n headers[csrfHeaderName] = resolvedCsrfToken;\n }\n if (isHmacMode) {\n const bodyBytes =\n fetchBody instanceof Uint8Array\n ? fetchBody\n : typeof fetchBody === \"string\"\n ? new TextEncoder().encode(fetchBody)\n : new Uint8Array(0);\n Object.assign(\n headers,\n buildHmacHeaders(method, path, bodyBytes, apiKey, hmacSecret),\n );\n }\n return headers;\n };\n\n if (shouldUseCsrf && !csrfToken && refreshCsrfCookie) {\n await refreshCsrfCookie();\n csrfToken = readCsrfCookie(csrfCookieName);\n }\n\n const executeRequest = (resolvedCsrfToken: string): Promise<Response> =>\n fetch(baseUrl + path, {\n method,\n headers: buildHeaders(resolvedCsrfToken),\n ...(fetchBody != null\n ? { body: fetchBody as RequestInit[\"body\"] }\n : {}),\n credentials: \"include\",\n signal,\n });\n\n try {\n let res = await executeRequest(csrfToken);\n\n if (!res.ok) {\n const details = await readErrorDetails(res.clone());\n if (\n isHmacMode &&\n isHmacNonceReuseError(res.status, details.message)\n ) {\n res = await executeRequest(csrfToken);\n } else if (\n shouldUseCsrf &&\n refreshCsrfCookie &&\n isCsrfError(res.status, details.message)\n ) {\n await refreshCsrfCookie();\n csrfToken = readCsrfCookie(csrfCookieName);\n res = await executeRequest(csrfToken);\n } else if (!allowStatuses.has(res.status)) {\n throw createEntityRequestError(res.status, details);\n } else {\n // \uD5C8\uC6A9\uB41C \uBE44\uC815\uC0C1 \uC0C1\uD0DC\uB294 \uBCF8\uBB38\uC744 \uADF8\uB300\uB85C \uD30C\uC2F1\uD574 \uD638\uCD9C\uC790\uC5D0\uAC8C \uB118\uAE41\uB2C8\uB2E4.\n }\n }\n\n if (!res.ok && !allowStatuses.has(res.status)) {\n throw createEntityRequestError(\n res.status,\n await readErrorDetails(res),\n );\n }\n\n const accessTokenHeader =\n res.headers.get(\"X-Access-Token\")?.trim() ?? \"\";\n\n const contentType = res.headers.get(\"Content-Type\") ?? \"\";\n if (contentType.includes(\"application/octet-stream\")) {\n const key = derivePacketKey(hmacSecret, responsePacketSource);\n const encryptedBody = await res.arrayBuffer();\n let decrypted: T;\n\n try {\n decrypted = decryptPacket<T>(encryptedBody, key);\n } catch (error) {\n logPacketDecryptError({\n method,\n path,\n withAuth,\n status: res.status,\n contentType,\n responsePacketSource,\n tokenPresent: !!token,\n anonymousPacketTokenPresent: !!anonymousPacketToken,\n hmacEnabled: !!hmacSecret,\n error,\n });\n throw error;\n }\n\n if (accessTokenHeader) {\n onAccessToken?.(accessTokenHeader);\n }\n return decrypted;\n }\n\n if (accessTokenHeader) {\n onAccessToken?.(accessTokenHeader);\n }\n\n if (!contentType.includes(\"application/json\")) {\n return (await res.text()) as T;\n }\n\n const data = (await res.json()) as {\n ok?: boolean;\n message?: string;\n code?: string;\n };\n if (requireOkShape && !data.ok && !allowStatuses.has(res.status)) {\n throw createEntityRequestError(res.status, {\n message:\n data.message ?? `EntityServer error (HTTP ${res.status})`,\n code: data.code,\n body: data,\n });\n } else {\n return data as T;\n }\n } finally {\n clearManagedAbortSignal(\n opts,\n managedAbort.abortKey,\n managedAbort.controller,\n );\n }\n}\n"],
|
|
5
|
-
"mappings": "AAAA,OAAS,mBAAAA,EAAiB,iBAAAC,EAAe,iBAAAC,MAAqB,cAC9D,OAAS,oBAAAC,MAAwB,YAkDjC,SAASC,EAAsBC,EAAyB,CACpD,OAAQA,EAAO,YAAY,EAAG,CAC1B,IAAK,OACL,IAAK,MACL,IAAK,QACL,IAAK,SACD,MAAO,GACX,QACI,MAAO,EACf,CACJ,CAGA,SAASC,
|
|
6
|
-
"names": ["derivePacketKey", "encryptPacket", "decryptPacket", "buildHmacHeaders", "isAutoAbortableMethod", "method", "resolveAutoAbortKey", "path", "config", "trimmed", "composeAbortSignal", "signals", "activeSignals", "signal", "controller", "abort", "createManagedAbortSignal", "opts", "requestConfig", "abortKey", "clearManagedAbortSignal", "resolvePacketSource", "resolveResponsePacketSource", "withAuth", "anonymousPacketToken", "maskPacketSource", "value", "logPacketDecryptError", "details", "requiresCsrf", "readCsrfCookie", "name", "chunk", "idx", "isCsrfError", "status", "message", "isHmacNonceReuseError", "readErrorDetails", "res", "data", "createEntityRequestError", "err", "entityRequest", "body", "extraHeaders", "requireOkShape", "allowStatuses", "managedAbort", "baseUrl", "token", "apiKey", "hmacSecret", "encryptRequests", "csrfEnabled", "csrfHeaderName", "csrfCookieName", "refreshCsrfCookie", "onAccessToken", "debugPlainSecret", "isHmacMode", "packetSource", "responsePacketSource", "shouldUseCsrf", "csrfToken", "requestContentType", "includeAnonymousPacketHeader", "fetchBody", "key", "buildHeaders", "resolvedCsrfToken", "headers", "hasExplicitContentType", "bodyBytes", "executeRequest", "accessTokenHeader", "contentType", "encryptedBody", "decrypted", "error"]
|
|
4
|
+
"sourcesContent": ["import { derivePacketKey, encryptPacket, decryptPacket } from \"./packet.js\";\nimport { buildHmacHeaders } from \"./hmac.js\";\n\nexport interface RequestOptions {\n baseUrl: string;\n token: string;\n anonymousPacketToken: string;\n apiKey: string;\n hmacSecret: string;\n encryptRequests: boolean;\n csrfEnabled: boolean;\n csrfHeaderName: string;\n csrfCookieName: string;\n refreshCsrfCookie: (() => Promise<void>) | null;\n onAccessToken?: (token: string) => void;\n requestAbortControllers: Map<string, AbortController>;\n /**\n * dev \uB514\uBC84\uADF8 \uD3C9\uBB38 \uC2DC\uD06C\uB9BF. \uC124\uC815\uB418\uBA74 \uC694\uCCAD\uC744 \uC554\uD638\uD654\uD558\uC9C0 \uC54A\uACE0(\uD3C9\uBB38),\n * `X-Debug-Plain` \uD5E4\uB354\uB85C \uC804\uC1A1\uD55C\uB2E4. \uC11C\uBC84\uC758 `DEBUG_PLAIN_SECRET` \uACFC \uC77C\uCE58\uD558\uBA74\n * \uC11C\uBC84\uB3C4 \uD574\uB2F9 \uC694\uCCAD/\uC751\uB2F5\uC744 \uD3C9\uBB38\uC73C\uB85C \uCC98\uB9AC\uD55C\uB2E4(\uD328\uD0B7 \uC554\uD638\uD654 \uC6B0\uD68C).\n */\n debugPlainSecret?: string;\n}\n\nexport interface EntityRequestConfig {\n requireOkShape?: boolean;\n allowStatuses?: number[];\n signal?: AbortSignal;\n autoAbortKey?: string | false;\n}\n\nexport interface EntityRequestError extends Error {\n status?: number;\n code?: string;\n details?: unknown;\n}\n\ninterface EntityErrorBody {\n error?: string;\n message?: string;\n code?: string;\n [key: string]: unknown;\n}\n\ninterface EntityErrorDetails {\n message: string;\n code?: string;\n body?: EntityErrorBody;\n}\n\n// isAutoAbortableMethod\uB294 \uAE30\uBCF8 \uC790\uB3D9 \uCDE8\uC18C \uD0A4\uB97C \uD5C8\uC6A9\uD558\uB294 \uC4F0\uAE30 \uBA54\uC11C\uB4DC\uC778\uC9C0 \uD655\uC778\uD569\uB2C8\uB2E4.\nfunction isAutoAbortableMethod(method: string): boolean {\n switch (method.toUpperCase()) {\n case \"POST\":\n case \"PUT\":\n case \"PATCH\":\n case \"DELETE\":\n return true;\n default:\n return false;\n }\n}\n\n// resolveAutoAbortKey\uB294 \uC694\uCCAD\uBCC4 \uC790\uB3D9 \uCDE8\uC18C \uD0A4\uB97C \uACC4\uC0B0\uD569\uB2C8\uB2E4.\nfunction resolveAutoAbortKey(\n method: string,\n path: string,\n config: EntityRequestConfig,\n): string | null {\n if (config.autoAbortKey === false) {\n return null;\n }\n\n if (typeof config.autoAbortKey === \"string\") {\n const trimmed = config.autoAbortKey.trim();\n return trimmed ? trimmed : null;\n }\n\n // \uC790\uB3D9 \uCDE8\uC18C(\uAC19\uC740 \uACBD\uB85C \uC911\uBCF5 \uC694\uCCAD \uCDE8\uC18C)\uB294 \uBE0C\uB77C\uC6B0\uC800 UX \uCD5C\uC801\uD654\uB2E4. \uC11C\uBC84(Node)\uC5D0\uC11C\uB294\n // \uB3D9\uC2DC \uC694\uCCAD\uC774 \uC815\uC0C1 \uB3D9\uC791\uC774\uBBC0\uB85C \uAE30\uBCF8 \uC790\uB3D9 \uCDE8\uC18C\uB97C \uC801\uC6A9\uD558\uC9C0 \uC54A\uB294\uB2E4 \u2014 \uAC19\uC740 \uACBD\uB85C \uB3D9\uC2DC \uD638\uCD9C\uC774\n // \uC11C\uB85C\uB97C AbortError \uB85C \uCDE8\uC18C\uD558\uB294 \uBB38\uC81C(\uC608: \uD55C \uD578\uB4E4\uB7EC\uC5D0\uC11C \uAC19\uC740 \uC5D4\uD2F0\uD2F0 list 2\uAC1C\uB97C Promise.all \uB85C\n // \uB3D9\uC2DC \uD638\uCD9C, \uB610\uB294 \uD3F4\uB9C1\uC73C\uB85C \uB3D9\uC2DC \uC694\uCCAD\uC774 \uACB9\uCE58\uB294 \uACBD\uC6B0)\uB97C \uB9C9\uB294\uB2E4.\n // \uBA85\uC2DC\uC801 autoAbortKey(\uBB38\uC790\uC5F4/false)\uB294 \uC11C\uBC84\uC5D0\uC11C\uB3C4 \uC704\uC5D0\uC11C \uADF8\uB300\uB85C \uC874\uC911\uD55C\uB2E4.\n if (typeof window === \"undefined\") {\n return null;\n }\n\n if (isAutoAbortableMethod(method)) {\n return `${method.toUpperCase()} ${path}`;\n }\n\n return null;\n}\n\n// composeAbortSignal\uC740 \uC678\uBD80 signal\uACFC \uB0B4\uBD80 \uCDE8\uC18C signal\uC744 \uD558\uB098\uB85C \uD569\uCE69\uB2C8\uB2E4.\nfunction composeAbortSignal(\n signals: Array<AbortSignal | undefined>,\n): AbortSignal | undefined {\n const activeSignals = signals.filter(\n (signal): signal is AbortSignal => !!signal,\n );\n if (activeSignals.length === 0) {\n return undefined;\n }\n if (activeSignals.length === 1) {\n return activeSignals[0];\n }\n if (typeof AbortSignal.any === \"function\") {\n return AbortSignal.any(activeSignals);\n }\n\n const controller = new AbortController();\n const abort = () => controller.abort();\n for (const signal of activeSignals) {\n if (signal.aborted) {\n controller.abort();\n break;\n }\n signal.addEventListener(\"abort\", abort, { once: true });\n }\n return controller.signal;\n}\n\n// createManagedAbortSignal\uC740 \uAC19\uC740 \uD0A4\uC758 \uC774\uC804 \uC694\uCCAD\uC744 \uCDE8\uC18C\uD558\uACE0 \uD604\uC7AC \uC694\uCCAD signal\uC744 \uBC18\uD658\uD569\uB2C8\uB2E4.\nfunction createManagedAbortSignal(\n opts: RequestOptions,\n method: string,\n path: string,\n requestConfig: EntityRequestConfig,\n): {\n signal?: AbortSignal;\n abortKey: string | null;\n controller: AbortController | null;\n} {\n const abortKey = resolveAutoAbortKey(method, path, requestConfig);\n if (!abortKey) {\n return {\n signal: requestConfig.signal,\n abortKey: null,\n controller: null,\n };\n }\n\n opts.requestAbortControllers.get(abortKey)?.abort();\n\n const controller = new AbortController();\n opts.requestAbortControllers.set(abortKey, controller);\n\n return {\n signal: composeAbortSignal([requestConfig.signal, controller.signal]),\n abortKey,\n controller,\n };\n}\n\n// clearManagedAbortSignal\uC740 \uD604\uC7AC \uC694\uCCAD\uC774 \uB4F1\uB85D\uD55C \uCDE8\uC18C \uD0A4\uB9CC \uC548\uC804\uD558\uAC8C \uC815\uB9AC\uD569\uB2C8\uB2E4.\nfunction clearManagedAbortSignal(\n opts: RequestOptions,\n abortKey: string | null,\n controller: AbortController | null,\n): void {\n if (!abortKey || !controller) {\n return;\n }\n if (opts.requestAbortControllers.get(abortKey) === controller) {\n opts.requestAbortControllers.delete(abortKey);\n }\n}\n\nfunction resolvePacketSource(opts: RequestOptions): string {\n return opts.hmacSecret || opts.token || opts.anonymousPacketToken;\n}\n\nfunction resolveResponsePacketSource(\n opts: RequestOptions,\n withAuth: boolean,\n anonymousPacketToken: string,\n): string {\n if (opts.hmacSecret) {\n return opts.hmacSecret;\n }\n\n if (!withAuth) {\n return anonymousPacketToken;\n }\n\n return opts.token || anonymousPacketToken;\n}\n\nfunction maskPacketSource(value: string): string {\n if (!value) {\n return \"\";\n }\n\n if (value.length <= 8) {\n return `${value.slice(0, 2)}...${value.slice(-2)}`;\n }\n\n return `${value.slice(0, 4)}...${value.slice(-4)}`;\n}\n\nfunction logPacketDecryptError(details: {\n method: string;\n path: string;\n withAuth: boolean;\n status: number;\n contentType: string;\n responsePacketSource: string;\n tokenPresent: boolean;\n anonymousPacketTokenPresent: boolean;\n hmacEnabled: boolean;\n error: unknown;\n}): void {\n if (typeof console === \"undefined\" || typeof console.error !== \"function\") {\n return;\n }\n\n console.error(\"[entity-client] packet decrypt failed\", {\n method: details.method,\n path: details.path,\n withAuth: details.withAuth,\n status: details.status,\n contentType: details.contentType,\n responsePacketSource: maskPacketSource(details.responsePacketSource),\n tokenPresent: details.tokenPresent,\n anonymousPacketTokenPresent: details.anonymousPacketTokenPresent,\n hmacEnabled: details.hmacEnabled,\n error:\n details.error instanceof Error\n ? {\n name: details.error.name,\n message: details.error.message,\n stack: details.error.stack,\n }\n : details.error,\n });\n}\n\nfunction requiresCsrf(method: string): boolean {\n return method !== \"GET\" && method !== \"HEAD\" && method !== \"OPTIONS\";\n}\n\nfunction readCsrfCookie(name: string): string {\n if (typeof document === \"undefined\") return \"\";\n for (const chunk of document.cookie.split(\";\")) {\n const idx = chunk.indexOf(\"=\");\n if (idx < 0) continue;\n if (chunk.substring(0, idx).trim() === name) {\n return decodeURIComponent(chunk.substring(idx + 1).trim());\n }\n }\n return \"\";\n}\n\nfunction isCsrfError(status: number, message: string): boolean {\n if (status === 403 && /csrf/i.test(message)) {\n return true;\n }\n\n return (\n /csrf/i.test(message) &&\n /expired|token validation failed/i.test(message)\n );\n}\n\n// HMAC nonce \uC7AC\uC0AC\uC6A9 \uC751\uB2F5\uC778\uC9C0 \uD655\uC778\uD569\uB2C8\uB2E4.\nfunction isHmacNonceReuseError(status: number, message: string): boolean {\n return status === 401 && /nonce already used/i.test(message);\n}\n\n// readErrorDetails\uB294 \uC5D0\uB7EC \uC751\uB2F5 \uBCF8\uBB38\uC5D0\uC11C \uBA54\uC2DC\uC9C0\uC640 \uCF54\uB4DC\uB97C \uCD94\uCD9C\uD569\uB2C8\uB2E4.\nasync function readErrorDetails(res: Response): Promise<EntityErrorDetails> {\n const contentType = res.headers.get(\"Content-Type\") ?? \"\";\n if (contentType.includes(\"application/json\")) {\n const data = (await res\n .json()\n .catch(() => null)) as EntityErrorBody | null;\n if (data?.error)\n return { message: data.error, code: data.code, body: data };\n if (data?.message)\n return { message: data.message, code: data.code, body: data };\n }\n\n const text = await res.text().catch(() => \"\");\n return { message: text || `HTTP ${res.status}` };\n}\n\n// createEntityRequestError\uB294 HTTP \uC5D0\uB7EC \uC815\uBCF4\uB97C Error \uAC1D\uCCB4\uC5D0 \uBCF4\uC874\uD569\uB2C8\uB2E4.\nfunction createEntityRequestError(\n status: number,\n details: EntityErrorDetails,\n): EntityRequestError {\n const err = new Error(details.message) as EntityRequestError;\n err.status = status;\n if (details.code) {\n err.code = details.code;\n }\n if (details.body) {\n err.details = details.body;\n }\n return err;\n}\n\n/**\n * Entity Server\uC5D0 HTTP \uC694\uCCAD\uC744 \uBCF4\uB0C5\uB2C8\uB2E4.\n *\n * - `encryptRequests` \uD65C\uC131\uD654 \uC2DC \uC778\uC99D\uB41C POST \uBC14\uB514\uB97C \uC790\uB3D9 \uC554\uD638\uD654\uD569\uB2C8\uB2E4.\n * - \uC751\uB2F5\uC774 `application/octet-stream`\uC774\uBA74 \uC790\uB3D9 \uBCF5\uD638\uD654\uD569\uB2C8\uB2E4.\n * - JSON \uC751\uB2F5\uC758 `ok`\uAC00 false\uC774\uBA74 \uC5D0\uB7EC\uB97C \uB358\uC9D1\uB2C8\uB2E4.\n */\nexport async function entityRequest<T>(\n opts: RequestOptions,\n method: string,\n path: string,\n body?: unknown,\n withAuth = true,\n extraHeaders: Record<string, string> = {},\n config: boolean | EntityRequestConfig = true,\n): Promise<T> {\n const requestConfig: EntityRequestConfig =\n typeof config === \"boolean\" ? { requireOkShape: config } : config;\n const requireOkShape = requestConfig.requireOkShape ?? true;\n const allowStatuses = new Set(requestConfig.allowStatuses ?? []);\n const managedAbort = createManagedAbortSignal(\n opts,\n method,\n path,\n requestConfig,\n );\n const signal = managedAbort.signal;\n\n const {\n baseUrl,\n token,\n apiKey,\n hmacSecret,\n encryptRequests,\n csrfEnabled,\n csrfHeaderName,\n csrfCookieName,\n refreshCsrfCookie,\n onAccessToken,\n debugPlainSecret,\n } = opts;\n // checkHealth()\uAC00 \uC644\uB8CC\uB418\uAE30 \uC804 race condition\uC744 \uB9C9\uAE30 \uC704\uD574 anon_token \uCFE0\uD0A4\uB97C \uC9C1\uC811 fallback\uC73C\uB85C \uC77D\uC74C\n const anonymousPacketToken =\n opts.anonymousPacketToken || readCsrfCookie(\"anon_token\");\n const isHmacMode = withAuth && !!(apiKey && hmacSecret);\n const packetSource = resolvePacketSource(opts);\n const responsePacketSource = resolveResponsePacketSource(\n opts,\n withAuth,\n anonymousPacketToken,\n );\n const shouldUseCsrf = csrfEnabled && requiresCsrf(method) && !isHmacMode;\n let csrfToken = shouldUseCsrf ? readCsrfCookie(csrfCookieName) : \"\";\n let requestContentType = \"application/json\";\n const includeAnonymousPacketHeader = !isHmacMode && !!anonymousPacketToken;\n\n let fetchBody: string | Uint8Array | null = null;\n if (body != null) {\n const shouldEncrypt =\n !debugPlainSecret &&\n encryptRequests &&\n !!packetSource &&\n withAuth &&\n method !== \"GET\" &&\n method !== \"HEAD\";\n\n if (shouldEncrypt) {\n const key = derivePacketKey(\n hmacSecret,\n token || anonymousPacketToken,\n );\n fetchBody = encryptPacket(\n new TextEncoder().encode(JSON.stringify(body)),\n key,\n );\n requestContentType = \"application/octet-stream\";\n } else {\n fetchBody = JSON.stringify(body);\n }\n }\n\n const buildHeaders = (\n resolvedCsrfToken: string,\n ): Record<string, string> => {\n const headers: Record<string, string> = { ...extraHeaders };\n const hasExplicitContentType = Object.keys(headers).some(\n (key) => key.toLowerCase() === \"content-type\",\n );\n if (fetchBody != null && !hasExplicitContentType) {\n headers[\"Content-Type\"] = requestContentType;\n }\n if (!isHmacMode && withAuth && token) {\n headers.Authorization = `Bearer ${token}`;\n }\n if (includeAnonymousPacketHeader) {\n headers[\"X-Packet-Token\"] = anonymousPacketToken;\n }\n // dev \uB514\uBC84\uADF8 \uBC14\uC774\uD328\uC2A4: \uC11C\uBC84\uAC00 \uD3C9\uBB38 \uCC98\uB9AC\uD558\uB3C4\uB85D \uC2DC\uD06C\uB9BF \uD5E4\uB354\uB97C \uBCF4\uB0B8\uB2E4.\n if (debugPlainSecret) {\n headers[\"X-Debug-Plain\"] = debugPlainSecret;\n }\n if (shouldUseCsrf && resolvedCsrfToken) {\n headers[csrfHeaderName] = resolvedCsrfToken;\n }\n if (isHmacMode) {\n const bodyBytes =\n fetchBody instanceof Uint8Array\n ? fetchBody\n : typeof fetchBody === \"string\"\n ? new TextEncoder().encode(fetchBody)\n : new Uint8Array(0);\n Object.assign(\n headers,\n buildHmacHeaders(method, path, bodyBytes, apiKey, hmacSecret),\n );\n }\n return headers;\n };\n\n if (shouldUseCsrf && !csrfToken && refreshCsrfCookie) {\n await refreshCsrfCookie();\n csrfToken = readCsrfCookie(csrfCookieName);\n }\n\n const executeRequest = (resolvedCsrfToken: string): Promise<Response> =>\n fetch(baseUrl + path, {\n method,\n headers: buildHeaders(resolvedCsrfToken),\n ...(fetchBody != null\n ? { body: fetchBody as RequestInit[\"body\"] }\n : {}),\n credentials: \"include\",\n signal,\n });\n\n try {\n let res = await executeRequest(csrfToken);\n\n if (!res.ok) {\n const details = await readErrorDetails(res.clone());\n if (\n isHmacMode &&\n isHmacNonceReuseError(res.status, details.message)\n ) {\n res = await executeRequest(csrfToken);\n } else if (\n shouldUseCsrf &&\n refreshCsrfCookie &&\n isCsrfError(res.status, details.message)\n ) {\n await refreshCsrfCookie();\n csrfToken = readCsrfCookie(csrfCookieName);\n res = await executeRequest(csrfToken);\n } else if (!allowStatuses.has(res.status)) {\n throw createEntityRequestError(res.status, details);\n } else {\n // \uD5C8\uC6A9\uB41C \uBE44\uC815\uC0C1 \uC0C1\uD0DC\uB294 \uBCF8\uBB38\uC744 \uADF8\uB300\uB85C \uD30C\uC2F1\uD574 \uD638\uCD9C\uC790\uC5D0\uAC8C \uB118\uAE41\uB2C8\uB2E4.\n }\n }\n\n if (!res.ok && !allowStatuses.has(res.status)) {\n throw createEntityRequestError(\n res.status,\n await readErrorDetails(res),\n );\n }\n\n const accessTokenHeader =\n res.headers.get(\"X-Access-Token\")?.trim() ?? \"\";\n\n const contentType = res.headers.get(\"Content-Type\") ?? \"\";\n if (contentType.includes(\"application/octet-stream\")) {\n const key = derivePacketKey(hmacSecret, responsePacketSource);\n const encryptedBody = await res.arrayBuffer();\n let decrypted: T;\n\n try {\n decrypted = decryptPacket<T>(encryptedBody, key);\n } catch (error) {\n logPacketDecryptError({\n method,\n path,\n withAuth,\n status: res.status,\n contentType,\n responsePacketSource,\n tokenPresent: !!token,\n anonymousPacketTokenPresent: !!anonymousPacketToken,\n hmacEnabled: !!hmacSecret,\n error,\n });\n throw error;\n }\n\n if (accessTokenHeader) {\n onAccessToken?.(accessTokenHeader);\n }\n return decrypted;\n }\n\n if (accessTokenHeader) {\n onAccessToken?.(accessTokenHeader);\n }\n\n if (!contentType.includes(\"application/json\")) {\n return (await res.text()) as T;\n }\n\n const data = (await res.json()) as {\n ok?: boolean;\n message?: string;\n code?: string;\n };\n if (requireOkShape && !data.ok && !allowStatuses.has(res.status)) {\n throw createEntityRequestError(res.status, {\n message:\n data.message ?? `EntityServer error (HTTP ${res.status})`,\n code: data.code,\n body: data,\n });\n } else {\n return data as T;\n }\n } finally {\n clearManagedAbortSignal(\n opts,\n managedAbort.abortKey,\n managedAbort.controller,\n );\n }\n}\n\n/**\n * multipart/form-data(\uD30C\uC77C \uC5C5\uB85C\uB4DC) \uC694\uCCAD\uC744 \uD328\uD0B7 \uC554\uD638\uD654\uC640 \uBB34\uAD00\uD558\uAC8C \uBCF4\uB0B8\uB2E4.\n *\n * \uD30C\uC77C \uC5C5\uB85C\uB4DC\uB294 \uC694\uCCAD \uBCF8\uBB38(FormData)\uC744 \uC554\uD638\uD654\uD558\uC9C0 \uC54A\uB294\uB2E4. \uC11C\uBC84\uAC00 multipart \uB97C \uADF8\uB300\uB85C \uD30C\uC2F1\uD558\uAE30 \uB54C\uBB38\uC774\uB2E4.\n * \uB2E4\uB9CC \uD328\uD0B7 \uC554\uD638\uD654\uAC00 \uCF1C\uC9C4 \uC11C\uBC84\uB294 **\uC751\uB2F5**\uC744 `application/octet-stream` \uC73C\uB85C \uC554\uD638\uD654\uD574 \uB0B4\uB824\uC904 \uC218 \uC788\uC73C\uBBC0\uB85C,\n * \uC77C\uBC18 `entityRequest` \uC640 \uB3D9\uC77C\uD558\uAC8C `X-Debug-Plain`/`X-Packet-Token`/HMAC \uD5E4\uB354\uB97C \uC2E4\uC5B4 \uBCF4\uB0B4\uACE0\n * \uC751\uB2F5 Content-Type \uC5D0 \uB530\uB77C (octet-stream \uC774\uBA74 \uBCF5\uD638\uD654, \uC544\uB2C8\uBA74 JSON) \uC790\uB3D9 \uCC98\uB9AC\uD55C\uB2E4.\n *\n * \uAE30\uC874 raw `fetch + res.json()` \uBC29\uC2DD\uC740 \uC554\uD638\uD654 \uC751\uB2F5\uC744 \uBCF5\uD638\uD654\uD558\uC9C0 \uBABB\uD574\n * `Unexpected token '...' is not valid JSON` \uC73C\uB85C \uAE68\uC84C\uB2E4. (HTTP 200 \uC774\uC5B4\uB3C4)\n */\nexport async function requestFormData<T>(\n opts: RequestOptions,\n method: string,\n path: string,\n form: FormData,\n withAuth = true,\n): Promise<T> {\n const {\n baseUrl,\n token,\n apiKey,\n hmacSecret,\n csrfEnabled,\n csrfHeaderName,\n csrfCookieName,\n refreshCsrfCookie,\n onAccessToken,\n debugPlainSecret,\n } = opts;\n\n const anonymousPacketToken =\n opts.anonymousPacketToken || readCsrfCookie(\"anon_token\");\n const isHmacMode = withAuth && !!(apiKey && hmacSecret);\n const responsePacketSource = resolveResponsePacketSource(\n opts,\n withAuth,\n anonymousPacketToken,\n );\n const shouldUseCsrf = csrfEnabled && requiresCsrf(method) && !isHmacMode;\n const includeAnonymousPacketHeader = !isHmacMode && !!anonymousPacketToken;\n let csrfToken = shouldUseCsrf ? readCsrfCookie(csrfCookieName) : \"\";\n\n if (shouldUseCsrf && !csrfToken && refreshCsrfCookie) {\n await refreshCsrfCookie();\n csrfToken = readCsrfCookie(csrfCookieName);\n }\n\n // multipart \uB294 Content-Type(boundary)\uC744 fetch \uAC00 \uC790\uB3D9 \uC124\uC815\uD558\uB3C4\uB85D \uB450\uACE0, \uC6B0\uB9AC\uB294 \uC778\uC99D/\uD328\uD0B7 \uD5E4\uB354\uB9CC \uB354\uD55C\uB2E4.\n // HMAC \uBAA8\uB4DC\uB294 \uBCF8\uBB38 \uBC14\uC774\uD2B8 \uC11C\uBA85\uC774 \uD544\uC694\uD558\uBBC0\uB85C multipart \uC5C5\uB85C\uB4DC(\uBE0C\uB77C\uC6B0\uC800 \uC2A4\uD2B8\uB9BC \uBC14\uB514)\uC5D0\uB294 \uC801\uC6A9\uD558\uC9C0 \uC54A\uB294\uB2E4.\n const buildHeaders = (resolvedCsrfToken: string): Record<string, string> => {\n const headers: Record<string, string> = {};\n if (!isHmacMode && withAuth && token) {\n headers.Authorization = `Bearer ${token}`;\n }\n if (isHmacMode && apiKey) {\n headers[\"X-API-Key\"] = apiKey;\n }\n if (includeAnonymousPacketHeader) {\n headers[\"X-Packet-Token\"] = anonymousPacketToken;\n }\n if (debugPlainSecret) {\n headers[\"X-Debug-Plain\"] = debugPlainSecret;\n }\n if (shouldUseCsrf && resolvedCsrfToken) {\n headers[csrfHeaderName] = resolvedCsrfToken;\n }\n return headers;\n };\n\n const executeRequest = (resolvedCsrfToken: string): Promise<Response> =>\n fetch(baseUrl + path, {\n method,\n headers: buildHeaders(resolvedCsrfToken),\n body: form,\n credentials: \"include\",\n });\n\n let res = await executeRequest(csrfToken);\n\n if (\n !res.ok &&\n shouldUseCsrf &&\n refreshCsrfCookie &&\n isCsrfError(res.status, (await readErrorDetails(res.clone())).message)\n ) {\n await refreshCsrfCookie();\n csrfToken = readCsrfCookie(csrfCookieName);\n res = await executeRequest(csrfToken);\n }\n\n if (!res.ok) {\n throw createEntityRequestError(res.status, await readErrorDetails(res));\n }\n\n const accessTokenHeader = res.headers.get(\"X-Access-Token\")?.trim() ?? \"\";\n const contentType = res.headers.get(\"Content-Type\") ?? \"\";\n\n if (contentType.includes(\"application/octet-stream\")) {\n const key = derivePacketKey(hmacSecret, responsePacketSource);\n const encryptedBody = await res.arrayBuffer();\n let decrypted: T;\n try {\n decrypted = decryptPacket<T>(encryptedBody, key);\n } catch (error) {\n logPacketDecryptError({\n method,\n path,\n withAuth,\n status: res.status,\n contentType,\n responsePacketSource,\n tokenPresent: !!token,\n anonymousPacketTokenPresent: !!anonymousPacketToken,\n hmacEnabled: !!hmacSecret,\n error,\n });\n throw error;\n }\n if (accessTokenHeader) {\n onAccessToken?.(accessTokenHeader);\n }\n return decrypted;\n }\n\n if (accessTokenHeader) {\n onAccessToken?.(accessTokenHeader);\n }\n\n const data = (await res.json()) as { ok?: boolean; message?: string };\n if (!data.ok) {\n const err = new Error(\n data.message ?? `EntityServer error (HTTP ${res.status})`,\n );\n (err as { status?: number }).status = res.status;\n throw err;\n }\n return data as T;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["derivePacketKey", "encryptPacket", "decryptPacket", "buildHmacHeaders", "isAutoAbortableMethod", "method", "resolveAutoAbortKey", "path", "config", "trimmed", "composeAbortSignal", "signals", "activeSignals", "signal", "controller", "abort", "createManagedAbortSignal", "opts", "requestConfig", "abortKey", "clearManagedAbortSignal", "resolvePacketSource", "resolveResponsePacketSource", "withAuth", "anonymousPacketToken", "maskPacketSource", "value", "logPacketDecryptError", "details", "requiresCsrf", "readCsrfCookie", "name", "chunk", "idx", "isCsrfError", "status", "message", "isHmacNonceReuseError", "readErrorDetails", "res", "data", "createEntityRequestError", "err", "entityRequest", "body", "extraHeaders", "requireOkShape", "allowStatuses", "managedAbort", "baseUrl", "token", "apiKey", "hmacSecret", "encryptRequests", "csrfEnabled", "csrfHeaderName", "csrfCookieName", "refreshCsrfCookie", "onAccessToken", "debugPlainSecret", "isHmacMode", "packetSource", "responsePacketSource", "shouldUseCsrf", "csrfToken", "requestContentType", "includeAnonymousPacketHeader", "fetchBody", "key", "buildHeaders", "resolvedCsrfToken", "headers", "hasExplicitContentType", "bodyBytes", "executeRequest", "accessTokenHeader", "contentType", "encryptedBody", "decrypted", "error", "requestFormData", "form"]
|
|
7
7
|
}
|