mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2026-09-24 09:02:00 +00:00
* Implement round-trip encoding/decoding for UTF-8 values in header functions. * Update encodeHeaderValue and decodeHeaderValue to use base64 utility functions. * Add tests for UTF-8 header value handling. * Update Vite config to externalize base64 utility.
1 line
11 KiB
JavaScript
1 line
11 KiB
JavaScript
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("uuid"),t=require("@warkypublic/artemis-kit/base64");function n(...e){let t={};for(let n of e)for(let[e,r]of Object.entries(n)){for(let n of Object.keys(t))n.toLowerCase()===e.toLowerCase()&&delete t[n];Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0})}return t}function r(e){return n({"Content-Type":`application/json`},e.headers??{},e.token?{Authorization:`Bearer ${e.token}`}:{})}function i(e){let t=Object.entries(r(e)).map(([e,t])=>[e.toLowerCase(),t]).sort(([e],[t])=>e.localeCompare(t));return JSON.stringify([e.baseUrl,t])}var a=new Map;function o(e){let t=i(e),n=a.get(t);return n||(n=new s(e),a.set(t,n)),n}var s=class{constructor(e){this.config={...e,headers:{...e.headers}}}buildUrl(e,t,n){let r=`${this.config.baseUrl}/${e}/${t}`;return n&&(r+=`/${n}`),r}baseHeaders(){return r(this.config)}async fetchWithError(e,t){let n=await fetch(e,t),r=await n.json();if(!n.ok)throw Error(r.error?.message||`An error occurred`);return r}async getMetadata(e,t){let n=this.buildUrl(e,t);return this.fetchWithError(n,{method:`GET`,headers:this.baseHeaders()})}async read(e,t,n,r){let i=typeof n==`number`||typeof n==`string`?String(n):void 0,a=this.buildUrl(e,t,i),o={operation:`read`,id:Array.isArray(n)?n:void 0,options:r};return this.fetchWithError(a,{method:`POST`,headers:this.baseHeaders(),body:JSON.stringify(o)})}async create(e,t,n,r){let i=this.buildUrl(e,t),a={operation:`create`,data:n,options:r};return this.fetchWithError(i,{method:`POST`,headers:this.baseHeaders(),body:JSON.stringify(a)})}async update(e,t,n,r,i){let a=typeof r==`number`||typeof r==`string`?String(r):void 0,o=this.buildUrl(e,t,a),s={operation:`update`,id:Array.isArray(r)?r:void 0,data:n,options:i};return this.fetchWithError(o,{method:`POST`,headers:this.baseHeaders(),body:JSON.stringify(s)})}async delete(e,t,n){let r=this.buildUrl(e,t,String(n));return this.fetchWithError(r,{method:`POST`,headers:this.baseHeaders(),body:JSON.stringify({operation:`delete`})})}},c=new Map;function l(e){let t=e.url,n=c.get(t);return n||(n=new u(e),c.set(t,n)),n}var u=class{constructor(e){this.ws=null,this.messageHandlers=new Map,this.subscriptions=new Map,this.eventListeners={},this.state=`disconnected`,this.reconnectAttempts=0,this.reconnectTimer=null,this.heartbeatTimer=null,this.isManualClose=!1,this.config={url:e.url,reconnect:e.reconnect??!0,reconnectInterval:e.reconnectInterval??3e3,maxReconnectAttempts:e.maxReconnectAttempts??10,heartbeatInterval:e.heartbeatInterval??3e4,debug:e.debug??!1}}async connect(){if(this.ws?.readyState===WebSocket.OPEN){this.log(`Already connected`);return}return this.isManualClose=!1,this.setState(`connecting`),new Promise((e,t)=>{try{this.ws=new WebSocket(this.config.url),this.ws.onopen=()=>{this.log(`Connected to WebSocket server`),this.setState(`connected`),this.reconnectAttempts=0,this.startHeartbeat(),this.emit(`connect`),e()},this.ws.onmessage=e=>{this.handleMessage(e.data)},this.ws.onerror=e=>{this.log(`WebSocket error:`,e);let n=Error(`WebSocket connection error`);this.emit(`error`,n),t(n)},this.ws.onclose=e=>{this.log(`WebSocket closed:`,e.code,e.reason),this.stopHeartbeat(),this.setState(`disconnected`),this.emit(`disconnect`,e),this.config.reconnect&&!this.isManualClose&&this.reconnectAttempts<this.config.maxReconnectAttempts&&(this.reconnectAttempts++,this.log(`Reconnection attempt ${this.reconnectAttempts}/${this.config.maxReconnectAttempts}`),this.setState(`reconnecting`),this.reconnectTimer=setTimeout(()=>{this.connect().catch(e=>{this.log(`Reconnection failed:`,e)})},this.config.reconnectInterval))}}catch(e){t(e)}})}disconnect(){this.isManualClose=!0,this.reconnectTimer&&=(clearTimeout(this.reconnectTimer),null),this.stopHeartbeat(),this.ws&&=(this.setState(`disconnecting`),this.ws.close(),null),this.setState(`disconnected`),this.messageHandlers.clear()}async request(t,n,r){this.ensureConnected();let i=(0,e.v4)(),a={id:i,type:`request`,operation:t,entity:n,schema:r?.schema,record_id:r?.record_id,data:r?.data,options:r?.options};return new Promise((e,t)=>{this.messageHandlers.set(i,n=>{n.success?e(n.data):t(Error(n.error?.message||`Request failed`))}),this.send(a),setTimeout(()=>{this.messageHandlers.has(i)&&(this.messageHandlers.delete(i),t(Error(`Request timeout`)))},3e4)})}async read(e,t){return this.request(`read`,e,{schema:t?.schema,record_id:t?.record_id,options:{filters:t?.filters,columns:t?.columns,sort:t?.sort,preload:t?.preload,limit:t?.limit,offset:t?.offset}})}async create(e,t,n){return this.request(`create`,e,{schema:n?.schema,data:t})}async update(e,t,n,r){return this.request(`update`,e,{schema:r?.schema,record_id:t,data:n})}async delete(e,t,n){await this.request(`delete`,e,{schema:n?.schema,record_id:t})}async meta(e,t){return this.request(`meta`,e,{schema:t?.schema})}async subscribe(t,n,r){this.ensureConnected();let i=(0,e.v4)(),a={id:i,type:`subscription`,operation:`subscribe`,entity:t,schema:r?.schema,options:{filters:r?.filters}};return new Promise((e,o)=>{this.messageHandlers.set(i,i=>{if(i.success&&i.data?.subscription_id){let a=i.data.subscription_id;this.subscriptions.set(a,{id:a,entity:t,schema:r?.schema,options:{filters:r?.filters},callback:n}),this.log(`Subscribed to ${t} with ID: ${a}`),e(a)}else o(Error(i.error?.message||`Subscription failed`))}),this.send(a),setTimeout(()=>{this.messageHandlers.has(i)&&(this.messageHandlers.delete(i),o(Error(`Subscription timeout`)))},1e4)})}async unsubscribe(t){this.ensureConnected();let n=(0,e.v4)(),r={id:n,type:`subscription`,operation:`unsubscribe`,subscription_id:t};return new Promise((e,i)=>{this.messageHandlers.set(n,n=>{n.success?(this.subscriptions.delete(t),this.log(`Unsubscribed from ${t}`),e()):i(Error(n.error?.message||`Unsubscribe failed`))}),this.send(r),setTimeout(()=>{this.messageHandlers.has(n)&&(this.messageHandlers.delete(n),i(Error(`Unsubscribe timeout`)))},1e4)})}getSubscriptions(){return Array.from(this.subscriptions.values())}getState(){return this.state}isConnected(){return this.ws?.readyState===WebSocket.OPEN}on(e,t){this.eventListeners[e]=t}off(e){delete this.eventListeners[e]}handleMessage(e){try{let t=JSON.parse(e);switch(this.log(`Received message:`,t),this.emit(`message`,t),t.type){case`response`:this.handleResponse(t);break;case`notification`:this.handleNotification(t);break;case`pong`:break;default:this.log(`Unknown message type:`,t.type)}}catch(e){this.log(`Error parsing message:`,e)}}handleResponse(e){let t=this.messageHandlers.get(e.id);t&&(t(e),this.messageHandlers.delete(e.id))}handleNotification(e){let t=this.subscriptions.get(e.subscription_id);t?.callback&&t.callback(e)}send(e){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)throw Error(`WebSocket is not connected`);let t=JSON.stringify(e);this.log(`Sending message:`,e),this.ws.send(t)}startHeartbeat(){this.heartbeatTimer||=setInterval(()=>{if(this.isConnected()){let t={id:(0,e.v4)(),type:`ping`};this.send(t)}},this.config.heartbeatInterval)}stopHeartbeat(){this.heartbeatTimer&&=(clearInterval(this.heartbeatTimer),null)}setState(e){this.state!==e&&(this.state=e,this.emit(`stateChange`,e))}ensureConnected(){if(!this.isConnected())throw Error(`WebSocket is not connected. Call connect() first.`)}emit(e,...t){let n=this.eventListeners[e];n&&n(...t)}log(...e){this.config.debug&&console.log(`[WebSocketClient]`,...e)}};function d(e){return`ZIP_`+(0,t.b64EncodeUnicode)(e)}function f(e){let t=e;return t.startsWith(`ZIP_`)?(t=t.slice(4).replace(/[\n\r ]/g,``),t=p(t)):t.startsWith(`__`)&&(t=t.slice(2).replace(/[\n\r ]/g,``),t=p(t)),(t.startsWith(`ZIP_`)||t.startsWith(`__`))&&(t=f(t)),t}function p(e){return(0,t.b64DecodeUnicode)(e)}function m(e){let t={};if(e.columns?.length&&(t[`X-Select-Fields`]=e.columns.join(`,`)),e.omit_columns?.length&&(t[`X-Not-Select-Fields`]=e.omit_columns.join(`,`)),e.filters?.length)for(let n of e.filters){let e=n.logic_operator??`AND`,r=h(n.operator),i=g(n);n.operator===`eq`&&e===`AND`?t[`X-FieldFilter-${n.column}`]=i:e===`OR`?t[`X-SearchOr-${r}-${n.column}`]=i:t[`X-SearchOp-${r}-${n.column}`]=i}if(e.sort?.length&&(t[`X-Sort`]=e.sort.map(e=>e.direction.toUpperCase()===`DESC`?`-${e.column}`:`+${e.column}`).join(`,`)),e.limit!==void 0&&(t[`X-Limit`]=String(e.limit)),e.offset!==void 0&&(t[`X-Offset`]=String(e.offset)),e.cursor_forward&&(t[`X-Cursor-Forward`]=e.cursor_forward),e.cursor_backward&&(t[`X-Cursor-Backward`]=e.cursor_backward),e.preload?.length&&(t[`X-Preload`]=e.preload.map(e=>e.columns?.length?`${e.relation}:${e.columns.join(`,`)}`:e.relation).join(`|`)),e.fetch_row_number&&(t[`X-Fetch-RowNumber`]=e.fetch_row_number),e.computedColumns?.length)for(let n of e.computedColumns)t[`X-CQL-SEL-${n.name}`]=n.expression;return e.customOperators?.length&&(t[`X-Custom-SQL-W`]=e.customOperators.map(e=>e.sql).join(` AND `)),t}function h(e){switch(e){case`eq`:return`equals`;case`neq`:return`notequals`;case`gt`:return`greaterthan`;case`gte`:return`greaterthanorequal`;case`lt`:return`lessthan`;case`lte`:return`lessthanorequal`;case`like`:case`ilike`:case`contains`:return`contains`;case`startswith`:return`beginswith`;case`endswith`:return`endswith`;case`in`:return`in`;case`between`:return`between`;case`between_inclusive`:return`betweeninclusive`;case`is_null`:return`empty`;case`is_not_null`:return`notempty`;default:return e}}function g(e){return e.value===null||e.value===void 0?``:Array.isArray(e.value)?e.value.join(`,`):String(e.value)}var _=new Map;function v(e){let t=i(e),n=_.get(t);return n||(n=new y(e),_.set(t,n)),n}var y=class{constructor(e){this.config={...e,headers:{...e.headers}}}buildUrl(e,t,n){let r=`${this.config.baseUrl}/${e}/${t}`;return n&&(r+=`/${n}`),r}baseHeaders(){return r(this.config)}async fetchWithError(e,t){let n=await fetch(e,t),r=await n.json();if(!n.ok)throw Error(r.error?.message||`${n.statusText} (${n.status})`);return{data:r,success:!0,error:r.error?r.error:void 0,metadata:{count:n.headers.get(`content-range`)?Number(n.headers.get(`content-range`)?.split(`/`)[1]):0,total:n.headers.get(`content-range`)?Number(n.headers.get(`content-range`)?.split(`/`)[1]):0,filtered:n.headers.get(`content-range`)?Number(n.headers.get(`content-range`)?.split(`/`)[1]):0,offset:n.headers.get(`content-range`)?Number(n.headers.get(`content-range`)?.split(`/`)[0].split(`-`)[0]):0,limit:n.headers.get(`x-limit`)?Number(n.headers.get(`x-limit`)):0}}}async read(e,t,r,i){let a=this.buildUrl(e,t,r),o=i?m(i):{};return this.fetchWithError(a,{method:`GET`,headers:n(this.baseHeaders(),o)})}async create(e,t,r,i){let a=this.buildUrl(e,t),o=i?m(i):{};return this.fetchWithError(a,{method:`POST`,headers:n(this.baseHeaders(),o),body:JSON.stringify(r)})}async update(e,t,r,i,a){let o=this.buildUrl(e,t,r),s=a?m(a):{};return this.fetchWithError(o,{method:`PUT`,headers:n(this.baseHeaders(),s),body:JSON.stringify(i)})}async delete(e,t,n){let r=this.buildUrl(e,t,n);return this.fetchWithError(r,{method:`DELETE`,headers:this.baseHeaders()})}};exports.HeaderSpecClient=y,exports.ResolveSpecClient=s,exports.WebSocketClient=u,exports.buildHeaders=m,exports.decodeHeaderValue=f,exports.encodeHeaderValue=d,exports.getHeaderSpecClient=v,exports.getResolveSpecClient=o,exports.getWebSocketClient=l; |