@wavehouse/sdk 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -4
- package/dist/cli/codegen.js +63 -12
- package/dist/index.cjs +183 -86
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +147 -72
- package/dist/index.d.ts +147 -72
- package/dist/index.global.js +11 -11
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +182 -85
- package/dist/index.js.map +1 -1
- package/package.json +12 -6
package/dist/index.global.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
"use strict";var WaveHouse=(()=>{var z=Object.defineProperty;var
|
|
2
|
-
`)===-1&&l.indexOf("\r")===-1){
|
|
3
|
-
`,
|
|
4
|
-
`,
|
|
5
|
-
`,
|
|
6
|
-
${
|
|
7
|
-
`,
|
|
8
|
-
`,
|
|
9
|
-
${
|
|
10
|
-
${i}`,f++;break;case"id":i.includes("\0")||(R=i);break;case"retry":/^\d+$/.test(i)?r(parseInt(i,10)):t(new I(`Invalid \`retry\` value: "${i}"`,{type:"invalid-retry",value:i,line:c}));break;default:t(new I(`Unknown field "${l.length>20?`${l.slice(0,20)}\u2026`:l}"`,{type:"unknown-field",field:l,value:i,line:c}));break}}function de(){f>0&&e({id:R,event:S,data:g}),R=void 0,g="",f=0,S=void 0}function me(l={}){if(l.consume&&a.length>0){let i=a.join("");W(i,0,i.length)}u=!0,R=void 0,g="",f=0,S=void 0,a.length=0,d=0,w=!1}return{feed:Q,reset:me}}function ie(n,e,t){return t===100&&n.charCodeAt(e+1)===97&&n.charCodeAt(e+2)===116&&n.charCodeAt(e+3)===97&&n.charCodeAt(e+4)===58}function ae(n,e,t){return t===101&&n.charCodeAt(e+1)===118&&n.charCodeAt(e+2)===101&&n.charCodeAt(e+3)===110&&n.charCodeAt(e+4)===116&&n.charCodeAt(e+5)===58}var N=0,ve=5,Te=16*1024*1024,ue=3e4,xe=3e3;function Ee(n,e){let t=Math.max(e,Math.min(1e3*2**n,ue)),r=Math.max(e,t/2);return r+Math.random()*(t-r)}function V(n){n.body&&!n.body.locked&&n.body.cancel().catch(()=>{})}var $=class{_opts;_abort=null;_closed=!1;_started=!1;_counted=!1;_lastEventId=null;_retryFloorMs=0;_wake=null;onEvent=null;onStatus=null;onError=null;constructor(e){this._opts=e}connect(){if(!(this._closed||this._started)){if(this._started=!0,!this._opts.fetch&&typeof fetch>"u")throw new Error("[wavehouse] global fetch is not available in this environment. Upgrade to Node 22+ or supply one via `options.fetch`.");N++,this._counted=!0,N>ve&&console.warn(`[wavehouse] ${N} SSE connections open. Browsers limit HTTP/1.1 to 6 connections per domain.`),this._run().catch(e=>{this._emitError({status:0,code:"SSE_CONNECT_ERROR",message:e instanceof Error?e.message:String(e),retryable:!1}),this.disconnect()})}}disconnect(){if(!this._closed){this._closed=!0,this._abort?.abort(),this._abort=null,this._wake?.(),this._counted&&(N=Math.max(0,N-1),this._counted=!1);try{this.onStatus?.("closed")}catch(e){console.error("[wavehouse] SSE status handler threw:",e)}}}async _run(){await Promise.resolve();let e=0;for(;!this._closed;){let{liveMs:t,terminal:r}=await this._attempt();if(this._closed)return;if(r){this.disconnect();return}t>=xe&&(e=0),this._emitStatus("reconnecting"),await this._sleep(Ee(e,this._retryFloorMs)),e++}}async _attempt(){let e=new AbortController;this._abort=e;let t;try{t=this._url()}catch(u){return this._emitError({status:0,code:"SSE_CONNECT_ERROR",message:u instanceof Error?u.message:String(u),retryable:!1}),{liveMs:0,terminal:!0}}let r;try{r=await this._init(e.signal)}catch(u){return this._closed?{liveMs:0,terminal:!0}:(this._emitError({status:0,code:"SSE_AUTH_ERROR",message:u instanceof Error?u.message:String(u),retryable:!0}),{liveMs:0,terminal:!1})}let s;try{let u=this._opts.fetch;s=u?await u(t,r):await fetch(t,r)}catch(u){return this._closed?{liveMs:0,terminal:!0}:(this._emitError({status:0,code:"SSE_NETWORK_ERROR",message:u instanceof Error?u.message:String(u),retryable:!0}),{liveMs:0,terminal:!1})}if(s.type==="opaqueredirect"||s.status>=300&&s.status<400)return this._emitError({status:s.status,code:"SSE_REDIRECT",message:"The stream endpoint redirected and the SDK did not follow it. Redirects are refused when the request carries a credential \u2014 an `auth` token or configured `headers` \u2014 because a cross-origin hop strips the Authorization header, and this endpoint answers an unauthenticated caller with a reduced view instead of an error, while forwarding any configured headers to wherever the redirect points. If this request carries neither, `fetch` was left to follow the redirect itself, so arriving here means a response it will not follow (a 304, or a 3xx with no Location header) or an `options.fetch` that returned the redirect verbatim. Either way, set `baseURL` to the final URL; most often this is an http\u2192https upgrade or a canonical-host redirect at a proxy. To follow a credentialed redirect anyway, supply an `options.fetch` that overrides `redirect`.",retryable:!1}),V(s),{liveMs:0,terminal:!0};if(!s.ok){let u=await F(s);return this._emitError(u),{liveMs:0,terminal:!u.retryable}}let o=s.headers.get("content-type")??"";if(!o.toLowerCase().split(";")[0].trim().startsWith("text/event-stream"))return this._emitError({status:s.status,code:"SSE_BAD_CONTENT_TYPE",message:`Expected \`text/event-stream\`, got \`${o||"(none)"}\`. Something between the client and WaveHouse answered this request \u2014 an auth gateway's login page is the usual cause.`,retryable:!1}),V(s),{liveMs:0,terminal:!0};let a=s.body;if(!a||typeof a.getReader!="function"||a.locked||s.bodyUsed)return this._emitError({status:s.status,code:"SSE_NO_STREAM_BODY",message:"Streaming requires a response with a readable body. The configured `options.fetch` returned one whose body is absent or already read \u2014 an implementation that buffers or consumes the response cannot be used for `.stream()` or `.liveQuery()`.",retryable:!1}),V(s),{liveMs:0,terminal:!0};this._emitStatus("live");let d=Date.now();return await this._pump(a),{liveMs:Date.now()-d,terminal:!1}}_url(){let e=j(this._opts.baseURL,"/v1/stream");if(e.protocol!=="http:"&&e.protocol!=="https:")throw new Error(`baseURL must use http or https, got "${e.protocol}". Streaming is plain HTTP \u2014 there is no WebSocket endpoint.`);return e.searchParams.set("table",this._opts.table),this._opts.since&&e.searchParams.set("since",this._opts.since),e.toString()}async _init(e){let t={Accept:"text/event-stream"};if(this._opts.auth){let o=await this._opts.auth();o&&(t.Authorization=`Bearer ${o}`)}this._lastEventId&&(t["Last-Event-ID"]=this._lastEventId);let r=t.Authorization!==void 0||Object.keys(this._opts.headers??{}).length>0,s={...this._opts.fetchOptions,method:"GET",headers:G(t,this._opts.headers),signal:e,cache:"no-store",redirect:r?"manual":"follow",body:void 0};return"window"in globalThis||delete s.credentials,s}async _pump(e){let t=!1,r=le({onEvent:a=>{a.id&&(this._lastEventId=a.id),a.data&&this._dispatch(a.data)},onRetry:a=>{this._retryFloorMs=Math.min(Math.max(a,0),ue)},onError:a=>{a.type==="max-buffer-size-exceeded"&&(t=!0),this._emitError({status:0,code:"SSE_PARSE_ERROR",message:a.message,retryable:!0})},maxBufferSize:Te}),s=e.getReader(),o=new TextDecoder;try{for(;;){let{done:a,value:d}=await s.read();if(a||(r.feed(o.decode(d,{stream:!0})),t))return}}catch(a){if(this._closed)return;this._emitError({status:0,code:"SSE_READ_ERROR",message:a instanceof Error?a.message:String(a),retryable:!0})}finally{s.cancel().catch(()=>{})}}_dispatch(e){if(this._closed)return;let t;try{let r=JSON.parse(e);t={table:r.table_name,timestamp:r.received_timestamp,data:r.data}}catch{console.warn("[wavehouse] SSE received malformed message:",e);return}try{this.onEvent?.(t)}catch(r){console.error("[wavehouse] SSE event handler threw:",r)}}_emitError(e){if(!this._closed)try{this.onError?.(e)}catch(t){console.error("[wavehouse] SSE error handler threw:",t)}}_emitStatus(e){if(!this._closed)try{this.onStatus?.(e)}catch(t){console.error("[wavehouse] SSE status handler threw:",t)}}_sleep(e){return this._closed?Promise.resolve():new Promise(t=>{let r=setTimeout(()=>{this._wake=null,t()},e);this._wake=()=>{clearTimeout(r),this._wake=null,t()}})}};var B=class{_ctx;constructor(e){this._ctx=e}async health(e){let{error:t}=await p(this._ctx,{method:"GET",path:"/v1/health",signal:e?.signal});return t?m(t):h(void 0)}};var D=class{_stream;_subscriber;_buffer=[];_buffering=!0;_unsubStream=null;_closed=!1;constructor(e,t,r,s){this._stream=e,this._subscriber=r,this._unsubStream=e.subscribe({next:o=>{this._closed||(this._buffering?this._buffer.push(o):r.next(o))},status:o=>r.status?.(o),error:o=>r.error?.(o)}),this._runBackfill(t)}async _runBackfill(e){try{let t=await e();if(this._closed)return;if(this._subscriber.initial?.(t),t.error){this._buffering=!1;return}let r=t.data,s;r.length>0&&(s=r[r.length-1]?.received_timestamp),this._buffering=!1;for(let o of this._buffer){if(this._closed)break;s&&o.timestamp<=s||this._subscriber.next(o)}this._buffer=[]}catch{this._buffering=!1,this._buffer=[]}}close(){this._closed=!0,this._buffering=!1,this._buffer=[],this._unsubStream?.(),this._stream.close()}};var Ce={"=":"eq","!=":"neq",">":"gt",">=":"gte","<":"lt","<=":"lte",in:"in",like:"like",not_like:"not_like"},k=class n{_state;_ctx;_createStream;constructor(e,t,r){this._ctx=e,this._state=Object.freeze({...t}),this._createStream=r}select(...e){return this._clone({columns:[...this._state.columns,...e]})}selectAll(){return this._clone({selectAll:!0})}where(e,t,r){let s={column:e,op:Ce[t],value:r};return this._clone({filters:[...this._state.filters,s]})}count(e="*",t="count"){return this._addAgg("count",e,t)}sum(e,t=`sum_${e}`){return this._addAgg("sum",e,t)}avg(e,t=`avg_${e}`){return this._addAgg("avg",e,t)}min(e,t=`min_${e}`){return this._addAgg("min",e,t)}max(e,t=`max_${e}`){return this._addAgg("max",e,t)}countDistinct(e,t=`count_distinct_${e}`){return this._addAgg("countDistinct",e,t)}aggregate(e,t,r){return this._addAgg(e,t,r)}groupBy(...e){return this._clone({groupBy:[...this._state.groupBy,...e]})}orderBy(e,t="asc"){return this._clone({orderBy:[...this._state.orderBy,{column:e,dir:t}]})}limit(e){return this._clone({limit:e})}timeRange(e,t,r){return this._clone({timeRange:{column:e,since:t,until:r}})}cacheTTL(e){return this._clone({cacheTTL:e})}static DEFAULT_LIMIT=1e3;async fetch(e){let t=e?.limit??this._state.limit??n.DEFAULT_LIMIT,r=this._buildAST(t),{data:s,error:o}=await p(this._ctx,{method:"POST",path:`/v1/query?table=${encodeURIComponent(this._state.table)}`,body:r,signal:e?.signal});if(o)return m(o);let a=s,d=t!=null&&a.length>=t;return d&&this._state.orderBy.length>0?L(a,!0,()=>this._fetchNext(a,t,e)):L(a,d)}stream(e){let t=this._createStream(this._state.table,e),r=this._state.filters,s=this._state.columns;return r.length===0&&s.length===0?t:new Y(t,r,s)}liveQuery(e,t){let r=this.stream(t),s=()=>this.fetch();return new D(r,s,e,this._state.filters)}then(e,t){return this.fetch().then(e,t)}_clone(e){return new n(this._ctx,{...this._state,...e},this._createStream)}_addAgg(e,t,r){let s={fn:e,column:t,alias:r};return this._clone({aggregations:[...this._state.aggregations,s]})}_buildAST(e){let t={},r=this._state.columns.length>0,s=this._state.aggregations.length>0;return this._state.selectAll?t.select_all=!0:r?t.columns=this._state.columns:s||(t.select_all=!0),s&&(t.aggregations=this._state.aggregations),this._state.filters.length>0&&(t.filters=this._state.filters),this._state.groupBy.length>0&&(t.group_by=this._state.groupBy),this._state.orderBy.length>0&&(t.order_by=this._state.orderBy),e!=null&&(t.limit=e),this._state.timeRange&&(t.time_range=this._state.timeRange),t}async _fetchNext(e,t,r){let s=this._state.orderBy[0];if(s==null)return L([],!1);let{column:o,dir:a}=s,u=e[e.length-1]?.[o];if(u===void 0)return L([],!1);let g={column:o,op:a==="desc"?"lt":"gt",value:u};return this._clone({filters:[...this._state.filters,g],orderBy:this._state.orderBy}).fetch(r)}},Y=class extends v{constructor(e,t,r){let s={onEvent:null,onStatus:null,onError:null,connect(){e.subscribe({next:o=>{if(!Ae(o.data,t))return;let a=r.length>0?{...o,data:Oe(o.data,r)}:o;this.onEvent?.(a)},status:o=>this.onStatus?.(o),error:o=>this.onError?.(o)})},disconnect(){e.close()}};super(s)}};function Ae(n,e){for(let t of e){let r=n[t.column];if(!Pe(r,t.op,t.value))return!1}return!0}function Pe(n,e,t){switch(e){case"eq":return n===t;case"neq":return n!==t;case"gt":return U(n,t,(r,s)=>r>s);case"gte":return U(n,t,(r,s)=>r>=s);case"lt":return U(n,t,(r,s)=>r<s);case"lte":return U(n,t,(r,s)=>r<=s);case"in":return Array.isArray(t)&&t.includes(n);case"like":{if(typeof n!="string"||typeof t!="string")return!1;let s=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/%/g,".*").replace(/_/g,".");return new RegExp(`^${s}$`,"i").test(n)}case"not_like":{if(typeof n!="string"||typeof t!="string")return!1;let s=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/%/g,".*").replace(/_/g,".");return!new RegExp(`^${s}$`,"i").test(n)}default:return!0}}function U(n,e,t){return typeof n=="number"&&typeof e=="number"||typeof n=="string"&&typeof e=="string"?t(n,e):!1}function Oe(n,e){let t={};for(let r of e)r in n&&(t[r]=n[r]);return t}var Be="application/x-ndjson";async function De(n){return typeof n=="string"?n:n instanceof Uint8Array?new TextDecoder().decode(n):new Response(n).text()}var H=class{_ctx;_table;_createStream;constructor(e,t,r){this._ctx=e,this._table=t,this._createStream=r}async fetch(e){return this.select().limit(e?.limit??1e3).fetch(e)}select(...e){return new k(this._ctx,{table:this._table,columns:e,aggregations:[],filters:[],groupBy:[],orderBy:[]},this._createStream)}selectAll(){return this.select().selectAll()}async insert(e,t){if(Array.isArray(e)){if(e.length===0)return h({ok:!0,total:0,succeeded:0,failed:0,duplicates:0,results:[]});let a=e.map(d=>JSON.stringify(d)).join(`
|
|
11
|
-
`);return this._sendNDJSON(
|
|
1
|
+
"use strict";var WaveHouse=(()=>{var z=Object.defineProperty;var _e=Object.getOwnPropertyDescriptor;var Re=Object.getOwnPropertyNames;var we=Object.prototype.hasOwnProperty;var ye=(n,e)=>{for(var t in e)z(n,t,{get:e[t],enumerable:!0})},Se=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Re(e))!we.call(n,s)&&s!==t&&z(n,s,{get:()=>e[s],enumerable:!(r=_e(e,s))||r.enumerable});return n};var be=n=>Se(z({},"__esModule",{value:!0}),n);var He={};ye(He,{DLQNamespace:()=>O,LiveQuery:()=>D,PipeRef:()=>C,PipesNamespace:()=>P,QueryBuilder:()=>k,SchemaNamespace:()=>A,SettingsNamespace:()=>B,StreamController:()=>T,SysNamespace:()=>q,TableRef:()=>H,WaveHouseClient:()=>F,createClient:()=>de});async function j(n){let e;try{e=await n.json()}catch{e=void 0}let t=typeof e?.error=="string"?e.error:typeof e?.message=="string"?e.message:n.statusText,r=typeof e?.code=="string"&&e.code!==""?e.code:`HTTP_${n.status}`,s=typeof e?.retryable=="boolean"?e.retryable:n.status>=500;return{status:n.status,code:r,message:t,details:e,retryable:s}}function re(n){return{status:0,code:"NETWORK_ERROR",message:n instanceof Error?n.message:String(n),retryable:!0}}function g(n){return{ok:!0,data:n,error:null}}function L(n,e,t){return{ok:!0,data:n,error:null,hasMore:e,next:t}}function p(n){return{ok:!1,data:null,error:n}}function $(n,e,t){let r=new URL(n);r.search="",r.hash="",r.pathname.endsWith("/")||(r.pathname+="/");let s=new URL(e.replace(/^\/+/,""),r);if(t)for(let[o,i]of Object.entries(t))s.searchParams.set(o,i);return s}function K(n,e){if(!e)return n;let t=new Set(Object.keys(n).map(o=>o.toLowerCase())),r={...n},s=new Map;for(let[o,i]of Object.entries(e)){let d=o.toLowerCase();if(t.has(d))continue;let u=s.get(d);u!==void 0&&delete r[u],r[o]=i,s.set(d,o)}return r}function S(n){return n?.tenant===void 0?void 0:{tenant:n.tenant}}function se(){return{data:null,error:{status:0,code:"ABORTED",message:"Request aborted",retryable:!1},headers:new Headers}}async function h(n,e){let t=$(n.baseURL,e.path,e.params).toString(),r={"Content-Type":e.contentType??"application/json",Accept:"application/json"},s=e.rawBody!==void 0?e.rawBody:e.body!==void 0?JSON.stringify(e.body):void 0;if(n.auth){let u=await n.auth();u&&(r.Authorization=`Bearer ${u}`)}let o=K(r,n.options.headers),i=null,d=n.options.maxRetries+1;for(let u=0;u<d;u++)try{let w={...n.options.fetchOptions,method:e.method,headers:o,body:s,signal:e.signal},f=n.options.fetch,m=f?await f(t,w):await fetch(t,w);if(m.ok){let b=await m.text();return{data:b?JSON.parse(b):void 0,error:null,headers:m.headers}}let y=await j(m);if(m.status===503){let b=m.headers.get("Retry-After");if(b&&u<d-1){let Q=parseInt(b,10)*1e3||3e4;await G(Q,e.signal),i=y;continue}}if(y.retryable&&u<d-1){await G(ne(u),e.signal),i=y;continue}return{data:null,error:y,headers:m.headers}}catch(w){if(e.signal?.aborted)return se();if(i=re(w),u<d-1)try{await G(ne(u),e.signal)}catch(f){if(e.signal?.aborted)return se();throw f}}return{data:null,error:i,headers:new Headers}}function ne(n){return Math.min(1e3*2**n,3e4)}function G(n,e){return new Promise((t,r)=>{if(e?.aborted){r(new DOMException("Aborted","AbortError"));return}let s=setTimeout(t,n);e?.addEventListener("abort",()=>{clearTimeout(s),r(new DOMException("Aborted","AbortError"))},{once:!0})})}var O=class{_ctx;_createStream;constructor(e,t){this._ctx=e,this._createStream=t}async list(e){let{data:t,error:r}=await h(this._ctx,{method:"GET",path:"/v1/ops/dlq/stats",params:S(e),signal:e?.signal});return r?p(r):g(t)}async table(e,t){let{data:r,error:s}=await h(this._ctx,{method:"GET",path:"/v1/ops/dlq/stats",params:{table:e,...S(t)},signal:t?.signal});return s?p(s):g(r)}stream(e){return this._createStream("dlq",e)}};var C=class{_ctx;_name;_params;_createStream;constructor(e,t,r,s){this._ctx=e,this._name=t,this._params=r,this._createStream=s}async fetch(e){let{data:t,error:r}=await h(this._ctx,{method:"POST",path:`/v1/pipes/${encodeURIComponent(this._name)}`,body:this._params??{},signal:e?.signal});return r?p(r):g(t)}stream(e){return this._createStream(this._name,e)}then(e,t){return this.fetch().then(e,t)}},P=class{_ctx;constructor(e){this._ctx=e}async list(e){let{data:t,error:r}=await h(this._ctx,{method:"GET",path:"/v1/ops/pipes",params:S(e),signal:e?.signal});return r?p(r):g(t)}async get(e,t){let{data:r,error:s}=await h(this._ctx,{method:"GET",path:`/v1/ops/pipes/${encodeURIComponent(e)}`,params:S(t),signal:t?.signal});return s?p(s):g(r)}};var A=class{_ctx;constructor(e){this._ctx=e}async list(e){let{data:t,error:r}=await h(this._ctx,{method:"GET",path:"/v1/ops/schema",params:S(e),signal:e?.signal});if(r)return p(r);let s;if(Array.isArray(t)){s={};for(let o of t)o&&typeof o=="object"&&"name"in o&&(s[o.name]=o)}else s=t;return g(s)}async refresh(e){let{error:t}=await h(this._ctx,{method:"POST",path:"/v1/ops/schema/refresh",params:S(e),signal:e?.signal});return t?p(t):g(void 0)}};var B=class{_ctx;constructor(e){this._ctx=e}async reload(e){let{data:t,error:r}=await h(this._ctx,{method:"POST",path:"/v1/ops/settings/reload",params:S(e),signal:e?.signal});return r?p(r):g(t)}};async function oe(n,e,t){let{data:r,error:s}=await h(n,{method:"POST",path:"/v1/ops/query",params:S(t),body:{sql:e},signal:t?.signal});return s?p(s):g(r)}var T=class{_transport;_subscribers=new Set;_status="connecting";_buffer=[];_waiters=[];_done=!1;constructor(e){this._transport=e,this._transport.onEvent=t=>{for(let s of this._subscribers)s.next(t);let r=this._waiters.shift();r?r.resolve({value:t,done:!1}):this._buffer.push(t)},this._transport.onStatus=t=>{if(t!==this._status){this._status=t;for(let r of this._subscribers)r.status?.(t);if(t==="closed"){this._done=!0;for(let r of this._waiters)r.resolve({value:void 0,done:!0});this._waiters=[]}}},this._transport.onError=t=>{for(let r of this._subscribers)r.error?.(t)},this._transport.connect()}get status(){return this._status}connected(e=5e3){return this._status==="live"?Promise.resolve():this._status==="closed"?Promise.reject(new Error("Stream is closed")):this._done?Promise.reject(new Error("Stream closed before connecting")):new Promise((t,r)=>{let s=!1,o=setTimeout(()=>{s||(s=!0,this._subscribers.delete(i),r(new Error(`Stream did not connect within ${e}ms`)))},e),i={next:()=>{},status:d=>{if(d==="live"){if(s)return;s=!0,clearTimeout(o),this._subscribers.delete(i),t()}else if(d==="closed"){if(s)return;s=!0,clearTimeout(o),this._subscribers.delete(i),r(new Error("Stream closed before connecting"))}}};this._subscribers.add(i)})}subscribe(e){return this._subscribers.add(e),e.status?.(this._status),()=>{this._subscribers.delete(e),this._subscribers.size===0&&this._waiters.length===0&&this.close()}}attachSignal(e){if(e.aborted){this.close();return}e.addEventListener("abort",()=>this.close(),{once:!0})}close(){if(this._transport.disconnect(),this._status!=="closed"){this._status="closed";for(let e of this._subscribers)e.status?.("closed")}this._done=!0;for(let e of this._waiters)e.resolve({value:void 0,done:!0});this._waiters=[]}[Symbol.asyncIterator](){let e=this;return{next(){return e._buffer.length>0?Promise.resolve({value:e._buffer.shift(),done:!1}):e._done?Promise.resolve({value:void 0,done:!0}):new Promise(t=>{e._waiters.push({resolve:t})})},return(){return e.close(),Promise.resolve({value:void 0,done:!0})},[Symbol.asyncIterator](){return this}}}};var I=class extends Error{constructor(e,t){super(e),this.name="ParseError",this.type=t.type,this.field=t.field,this.value=t.value,this.line=t.line}},ie=10,ve=13,x=32;function Y(n){}function ue(n){if(typeof n=="function")throw new TypeError("`config` must be an object, got a function instead. Did you mean `createParser({onEvent: fn})`?");let{onEvent:e=Y,onError:t=Y,onRetry:r=Y,onComment:s,maxBufferSize:o}=n,i=[],d=0,u=!0,w,f="",m=0,y,b=!1;function Q(l){if(b)throw new Error("Cannot feed parser: it was terminated after exceeding the configured max buffer size. Call `reset()` to resume parsing.");if(u&&(u=!1,l.charCodeAt(0)===239&&l.charCodeAt(1)===187&&l.charCodeAt(2)===191&&(l=l.slice(3))),i.length===0){let _=Z(l);_!==""&&(i.push(_),d=_.length),W();return}if(l.indexOf(`
|
|
2
|
+
`)===-1&&l.indexOf("\r")===-1){i.push(l),d+=l.length,W();return}i.push(l);let a=i.join("");i.length=0,d=0;let c=Z(a);c!==""&&(i.push(c),d=c.length),W()}function W(){o!==void 0&&(d+f.length<=o||(b=!0,i.length=0,d=0,w=void 0,f="",m=0,y=void 0,t(new I(`Buffered data exceeded max buffer size of ${o} characters`,{type:"max-buffer-size-exceeded"}))))}function Z(l){let a=0;if(l.indexOf("\r")===-1){let c=l.indexOf(`
|
|
3
|
+
`,a);for(;c!==-1;){if(a===c){m>0&&e({id:w,event:y,data:f}),w=void 0,f="",m=0,y=void 0,a=c+1,c=l.indexOf(`
|
|
4
|
+
`,a);continue}let _=l.charCodeAt(a);if(ae(l,a,_)){let R=l.charCodeAt(a+5)===x?a+6:a+5,v=l.slice(R,c);if(m===0&&l.charCodeAt(c+1)===ie){e({id:w,event:y,data:v}),w=void 0,f="",y=void 0,a=c+2,c=l.indexOf(`
|
|
5
|
+
`,a);continue}f=m===0?v:`${f}
|
|
6
|
+
${v}`,m++}else le(l,a,_)?y=l.slice(l.charCodeAt(a+6)===x?a+7:a+6,c)||void 0:J(l,a,c);a=c+1,c=l.indexOf(`
|
|
7
|
+
`,a)}return l.slice(a)}for(;a<l.length;){let c=l.indexOf("\r",a),_=l.indexOf(`
|
|
8
|
+
`,a),R=-1;if(c!==-1&&_!==-1?R=c<_?c:_:c!==-1?c===l.length-1?R=-1:R=c:_!==-1&&(R=_),R===-1)break;J(l,a,R),a=R+1,l.charCodeAt(a-1)===ve&&l.charCodeAt(a)===ie&&a++}return l.slice(a)}function J(l,a,c){if(a===c){me();return}let _=l.charCodeAt(a);if(ae(l,a,_)){let E=l.charCodeAt(a+5)===x?a+6:a+5,te=l.slice(E,c);f=m===0?te:`${f}
|
|
9
|
+
${te}`,m++;return}if(le(l,a,_)){y=l.slice(l.charCodeAt(a+6)===x?a+7:a+6,c)||void 0;return}if(_===105&&l.charCodeAt(a+1)===100&&l.charCodeAt(a+2)===58){let E=l.slice(l.charCodeAt(a+3)===x?a+4:a+3,c);E.includes("\0")||(w=E);return}if(_===58){if(s){let E=l.slice(a,c);s(E.slice(l.charCodeAt(a+1)===x?2:1))}return}let R=l.slice(a,c),v=R.indexOf(":");if(v===-1){ee(R,"",R);return}let he=R.slice(0,v),fe=R.charCodeAt(v+1)===x?2:1,ge=R.slice(v+fe);ee(he,ge,R)}function ee(l,a,c){switch(l){case"event":y=a||void 0;break;case"data":f=m===0?a:`${f}
|
|
10
|
+
${a}`,m++;break;case"id":a.includes("\0")||(w=a);break;case"retry":/^\d+$/.test(a)?r(parseInt(a,10)):t(new I(`Invalid \`retry\` value: "${a}"`,{type:"invalid-retry",value:a,line:c}));break;default:t(new I(`Unknown field "${l.length>20?`${l.slice(0,20)}\u2026`:l}"`,{type:"unknown-field",field:l,value:a,line:c}));break}}function me(){m>0&&e({id:w,event:y,data:f}),w=void 0,f="",m=0,y=void 0}function pe(l={}){if(l.consume&&i.length>0){let a=i.join("");J(a,0,a.length)}u=!0,w=void 0,f="",m=0,y=void 0,i.length=0,d=0,b=!1}return{feed:Q,reset:pe}}function ae(n,e,t){return t===100&&n.charCodeAt(e+1)===97&&n.charCodeAt(e+2)===116&&n.charCodeAt(e+3)===97&&n.charCodeAt(e+4)===58}function le(n,e,t){return t===101&&n.charCodeAt(e+1)===118&&n.charCodeAt(e+2)===101&&n.charCodeAt(e+3)===110&&n.charCodeAt(e+4)===116&&n.charCodeAt(e+5)===58}var N=0,Te=5,xe=16*1024*1024,ce=3e4,Ee=3e3;function Oe(n,e){let t=Math.max(e,Math.min(1e3*2**n,ce)),r=Math.max(e,t/2);return r+Math.random()*(t-r)}function X(n){n.body&&!n.body.locked&&n.body.cancel().catch(()=>{})}var M=class{_opts;_abort=null;_closed=!1;_started=!1;_counted=!1;_lastEventId=null;_retryFloorMs=0;_wake=null;_columns=null;_warnBudget=new Map;onEvent=null;onStatus=null;onError=null;constructor(e){this._opts=e}connect(){if(!(this._closed||this._started)){if(this._started=!0,!this._opts.fetch&&typeof fetch>"u")throw new Error("[wavehouse] global fetch is not available in this environment. Upgrade to Node 22+ or supply one via `options.fetch`.");N++,this._counted=!0,N>Te&&console.warn(`[wavehouse] ${N} SSE connections open. Browsers limit HTTP/1.1 to 6 connections per domain.`),this._run().catch(e=>{this._emitError({status:0,code:"SSE_CONNECT_ERROR",message:e instanceof Error?e.message:String(e),retryable:!1}),this.disconnect()})}}disconnect(){if(!this._closed){this._closed=!0,this._abort?.abort(),this._abort=null,this._wake?.(),this._counted&&(N=Math.max(0,N-1),this._counted=!1);try{this.onStatus?.("closed")}catch(e){console.error("[wavehouse] SSE status handler threw:",e)}}}async _run(){await Promise.resolve();let e=0;for(;!this._closed;){let{liveMs:t,terminal:r}=await this._attempt();if(this._closed)return;if(r){this.disconnect();return}t>=Ee&&(e=0),this._emitStatus("reconnecting"),await this._sleep(Oe(e,this._retryFloorMs)),e++}}_warnBounded(e,t,r){let o=(this._warnBudget.get(e)??0)+1;this._warnBudget.set(e,o),o<=3?console.warn(t,r):o===4&&console.warn(`${t} \u2014 further occurrences suppressed for this connection`)}async _attempt(){let e=new AbortController;this._abort=e,this._columns=null,this._warnBudget.clear();let t;try{t=this._url()}catch(u){return this._emitError({status:0,code:"SSE_CONNECT_ERROR",message:u instanceof Error?u.message:String(u),retryable:!1}),{liveMs:0,terminal:!0}}let r;try{r=await this._init(e.signal)}catch(u){return this._closed?{liveMs:0,terminal:!0}:(this._emitError({status:0,code:"SSE_AUTH_ERROR",message:u instanceof Error?u.message:String(u),retryable:!0}),{liveMs:0,terminal:!1})}let s;try{let u=this._opts.fetch;s=u?await u(t,r):await fetch(t,r)}catch(u){return this._closed?{liveMs:0,terminal:!0}:(this._emitError({status:0,code:"SSE_NETWORK_ERROR",message:u instanceof Error?u.message:String(u),retryable:!0}),{liveMs:0,terminal:!1})}if(s.type==="opaqueredirect"||s.status>=300&&s.status<400)return this._emitError({status:s.status,code:"SSE_REDIRECT",message:"The stream endpoint redirected and the SDK did not follow it. Redirects are refused when the request carries a credential \u2014 an `auth` token or configured `headers` \u2014 because a cross-origin hop strips the Authorization header, and this endpoint answers an unauthenticated caller with a reduced view instead of an error, while forwarding any configured headers to wherever the redirect points. If this request carries neither, `fetch` was left to follow the redirect itself, so arriving here means a response it will not follow (a 304, or a 3xx with no Location header) or an `options.fetch` that returned the redirect verbatim. Either way, set `baseURL` to the final URL; most often this is an http\u2192https upgrade or a canonical-host redirect at a proxy. To follow a credentialed redirect anyway, supply an `options.fetch` that overrides `redirect`.",retryable:!1}),X(s),{liveMs:0,terminal:!0};if(!s.ok){let u=await j(s);return this._emitError(u),{liveMs:0,terminal:!u.retryable}}let o=s.headers.get("content-type")??"";if(!o.toLowerCase().split(";")[0].trim().startsWith("text/event-stream"))return this._emitError({status:s.status,code:"SSE_BAD_CONTENT_TYPE",message:`Expected \`text/event-stream\`, got \`${o||"(none)"}\`. Something between the client and WaveHouse answered this request \u2014 an auth gateway's login page is the usual cause.`,retryable:!1}),X(s),{liveMs:0,terminal:!0};let i=s.body;if(!i||typeof i.getReader!="function"||i.locked||s.bodyUsed)return this._emitError({status:s.status,code:"SSE_NO_STREAM_BODY",message:"Streaming requires a response with a readable body. The configured `options.fetch` returned one whose body is absent or already read \u2014 an implementation that buffers or consumes the response cannot be used for `.stream()` or `.liveQuery()`.",retryable:!1}),X(s),{liveMs:0,terminal:!0};this._emitStatus("live");let d=Date.now();return await this._pump(i),{liveMs:Date.now()-d,terminal:!1}}_url(){let e=$(this._opts.baseURL,"/v1/stream");if(e.protocol!=="http:"&&e.protocol!=="https:")throw new Error(`baseURL must use http or https, got "${e.protocol}". Streaming is plain HTTP \u2014 there is no WebSocket endpoint.`);return e.searchParams.set("table",this._opts.table),this._opts.since&&e.searchParams.set("since",this._opts.since),e.toString()}async _init(e){let t={Accept:"text/event-stream"};if(this._opts.auth){let o=await this._opts.auth();o&&(t.Authorization=`Bearer ${o}`)}this._lastEventId&&(t["Last-Event-ID"]=this._lastEventId);let r=t.Authorization!==void 0||Object.keys(this._opts.headers??{}).length>0,s={...this._opts.fetchOptions,method:"GET",headers:K(t,this._opts.headers),signal:e,cache:"no-store",redirect:r?"manual":"follow",body:void 0};return"window"in globalThis||delete s.credentials,s}async _pump(e){let t=!1,r=ue({onEvent:i=>{if(i.id&&(this._lastEventId=i.id),!!i.data){if(i.event==="schema"){this._applySchema(i.data);return}this._dispatch(i.data)}},onRetry:i=>{this._retryFloorMs=Math.min(Math.max(i,0),ce)},onError:i=>{i.type==="max-buffer-size-exceeded"&&(t=!0),this._emitError({status:0,code:"SSE_PARSE_ERROR",message:i.message,retryable:!0})},maxBufferSize:xe}),s=e.getReader(),o=new TextDecoder;try{for(;;){let{done:i,value:d}=await s.read();if(i||(r.feed(o.decode(d,{stream:!0})),t))return}}catch(i){if(this._closed)return;this._emitError({status:0,code:"SSE_READ_ERROR",message:i instanceof Error?i.message:String(i),retryable:!0})}finally{s.cancel().catch(()=>{})}}_applySchema(e){try{let t=JSON.parse(e);if(!Array.isArray(t.columns)||t.columns.some(r=>typeof r!="string"))throw new Error("columns must be an array of strings");if(new Set(t.columns).size!==t.columns.length)throw new Error("columns contains a duplicate name");this._columns=t.columns}catch{this._columns=null,this._warnBounded("bad-schema-frame","[wavehouse] SSE received a malformed schema event:",e)}}_dispatch(e){if(this._closed)return;let t;try{let r=JSON.parse(e),s=this._columns;if(!s){this._warnBounded("no-schema","[wavehouse] SSE received a row before any schema event:",e);return}if(!Array.isArray(r.row)){this._warnBounded("row-not-array","[wavehouse] SSE row is not an array:",e);return}if(r.row.length!==s.length){this._warnBounded(r.row.length<s.length?"row-short":"row-long",`[wavehouse] SSE row has ${r.row.length} value(s) but ${s.length} column(s) were announced:`,e);return}let o=Object.create(null);for(let i=0;i<s.length;i++)o[s[i]]=r.row[i];t={table:r.table_name,timestamp:r.received_timestamp,data:o}}catch{this._warnBounded("bad-json","[wavehouse] SSE received malformed message:",e);return}try{this.onEvent?.(t)}catch(r){console.error("[wavehouse] SSE event handler threw:",r)}}_emitError(e){if(!this._closed)try{this.onError?.(e)}catch(t){console.error("[wavehouse] SSE error handler threw:",t)}}_emitStatus(e){if(!this._closed)try{this.onStatus?.(e)}catch(t){console.error("[wavehouse] SSE status handler threw:",t)}}_sleep(e){return this._closed?Promise.resolve():new Promise(t=>{let r=setTimeout(()=>{this._wake=null,t()},e);this._wake=()=>{clearTimeout(r),this._wake=null,t()}})}};var q=class{_ctx;constructor(e){this._ctx=e}async health(e){let{error:t}=await h(this._ctx,{method:"GET",path:"/v1/health",signal:e?.signal});return t?p(t):g(void 0)}};var D=class{_stream;_subscriber;_buffer=[];_buffering=!0;_unsubStream=null;_closed=!1;constructor(e,t,r,s){this._stream=e,this._subscriber=r,this._unsubStream=e.subscribe({next:o=>{this._closed||(this._buffering?this._buffer.push(o):r.next(o))},status:o=>r.status?.(o),error:o=>r.error?.(o)}),this._runBackfill(t)}async _runBackfill(e){try{let t=await e();if(this._closed)return;if(this._subscriber.initial?.(t),t.error){this._buffering=!1;return}let r=t.data,s;r.length>0&&(s=r[r.length-1]?.received_timestamp),this._buffering=!1;for(let o of this._buffer){if(this._closed)break;s&&o.timestamp<=s||this._subscriber.next(o)}this._buffer=[]}catch{this._buffering=!1,this._buffer=[]}}close(){this._closed=!0,this._buffering=!1,this._buffer=[],this._unsubStream?.(),this._stream.close()}};var Ce={"=":"eq","!=":"neq",">":"gt",">=":"gte","<":"lt","<=":"lte",in:"in",like:"like",not_like:"not_like"},k=class n{_state;_ctx;_createStream;constructor(e,t,r){this._ctx=e,this._state=Object.freeze({...t}),this._createStream=r}select(...e){return this._clone({columns:[...this._state.columns,...e]})}selectAll(){return this._clone({selectAll:!0})}where(e,t,r){let s={column:e,op:Ce[t],value:r};return this._clone({filters:[...this._state.filters,s]})}count(e="*",t="count"){return this._addAgg("count",e,t)}sum(e,t=`sum_${e}`){return this._addAgg("sum",e,t)}avg(e,t=`avg_${e}`){return this._addAgg("avg",e,t)}min(e,t=`min_${e}`){return this._addAgg("min",e,t)}max(e,t=`max_${e}`){return this._addAgg("max",e,t)}countDistinct(e,t=`count_distinct_${e}`){return this._addAgg("countDistinct",e,t)}aggregate(e,t,r){return this._addAgg(e,t,r)}groupBy(...e){return this._clone({groupBy:[...this._state.groupBy,...e]})}orderBy(e,t="asc"){return this._clone({orderBy:[...this._state.orderBy,{column:e,dir:t}]})}limit(e){return this._clone({limit:e})}timeRange(e,t,r){return this._clone({timeRange:{column:e,since:t,until:r}})}cacheTTL(e){return this._clone({cacheTTL:e})}static DEFAULT_LIMIT=1e3;async fetch(e){let t=e?.limit??this._state.limit??n.DEFAULT_LIMIT,r=this._buildAST(t),{data:s,error:o}=await h(this._ctx,{method:"POST",path:`/v1/query?table=${encodeURIComponent(this._state.table)}`,body:r,signal:e?.signal});if(o)return p(o);let i=s,d=t!=null&&i.length>=t;return d&&this._state.orderBy.length>0?L(i,!0,()=>this._fetchNext(i,t,e)):L(i,d)}stream(e){let t=this._createStream(this._state.table,e),r=this._state.filters,s=this._state.columns;return r.length===0&&s.length===0?t:new V(t,r,s)}liveQuery(e,t){let r=this.stream(t),s=()=>this.fetch();return new D(r,s,e,this._state.filters)}then(e,t){return this.fetch().then(e,t)}_clone(e){return new n(this._ctx,{...this._state,...e},this._createStream)}_addAgg(e,t,r){let s={fn:e,column:t,alias:r};return this._clone({aggregations:[...this._state.aggregations,s]})}_buildAST(e){let t={},r=this._state.columns.length>0,s=this._state.aggregations.length>0;return this._state.selectAll?t.select_all=!0:r?t.columns=this._state.columns:s||(t.select_all=!0),s&&(t.aggregations=this._state.aggregations),this._state.filters.length>0&&(t.filters=this._state.filters),this._state.groupBy.length>0&&(t.group_by=this._state.groupBy),this._state.orderBy.length>0&&(t.order_by=this._state.orderBy),e!=null&&(t.limit=e),this._state.timeRange&&(t.time_range=this._state.timeRange),t}async _fetchNext(e,t,r){let s=this._state.orderBy[0];if(s==null)return L([],!1);let{column:o,dir:i}=s,u=e[e.length-1]?.[o];if(u===void 0)return L([],!1);let f={column:o,op:i==="desc"?"lt":"gt",value:u};return this._clone({filters:[...this._state.filters,f],orderBy:this._state.orderBy}).fetch(r)}},V=class extends T{constructor(e,t,r){let s={onEvent:null,onStatus:null,onError:null,connect(){e.subscribe({next:o=>{if(!Pe(o.data,t))return;let i=r.length>0?{...o,data:Be(o.data,r)}:o;this.onEvent?.(i)},status:o=>this.onStatus?.(o),error:o=>this.onError?.(o)})},disconnect(){e.close()}};super(s)}};function Pe(n,e){for(let t of e){let r=n[t.column];if(!Ae(r,t.op,t.value))return!1}return!0}function Ae(n,e,t){switch(e){case"eq":return n===t;case"neq":return n!==t;case"gt":return U(n,t,(r,s)=>r>s);case"gte":return U(n,t,(r,s)=>r>=s);case"lt":return U(n,t,(r,s)=>r<s);case"lte":return U(n,t,(r,s)=>r<=s);case"in":return Array.isArray(t)&&t.includes(n);case"like":{if(typeof n!="string"||typeof t!="string")return!1;let s=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/%/g,".*").replace(/_/g,".");return new RegExp(`^${s}$`,"i").test(n)}case"not_like":{if(typeof n!="string"||typeof t!="string")return!1;let s=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/%/g,".*").replace(/_/g,".");return!new RegExp(`^${s}$`,"i").test(n)}default:return!0}}function U(n,e,t){return typeof n=="number"&&typeof e=="number"||typeof n=="string"&&typeof e=="string"?t(n,e):!1}function Be(n,e){let t=Object.create(null);for(let r of e)r in n&&(t[r]=n[r]);return t}var qe="application/json",De="application/x-ndjson";async function ke(n){return typeof n=="string"?n:n instanceof Uint8Array?new TextDecoder().decode(n):new Response(n).text()}var H=class{_ctx;_table;_createStream;constructor(e,t,r){this._ctx=e,this._table=t,this._createStream=r}async fetch(e){return this.select().limit(e?.limit??1e3).fetch(e)}select(...e){return new k(this._ctx,{table:this._table,columns:e,aggregations:[],filters:[],groupBy:[],orderBy:[]},this._createStream)}selectAll(){return this.select().selectAll()}async insert(e,t){if(Array.isArray(e)){if(e.length===0)return g({ok:!0,total:0,succeeded:0,failed:0,duplicates:0,results:[]});let i=e.map(d=>JSON.stringify(d)).join(`
|
|
11
|
+
`);return this._sendNDJSON(i,t)}let{data:r,error:s}=await h(this._ctx,{method:"POST",path:`/v1/ingest?table=${encodeURIComponent(this._table)}`,body:e,contentType:qe,signal:t?.signal});if(s)return p(s);let o={ok:r?.ok??!0};return r?.duplicate!=null&&(o.duplicate=r.duplicate),g(o)}async insertNDJSON(e,t){let r=await ke(e);return this._sendNDJSON(r,t)}async _sendNDJSON(e,t){let{data:r,error:s}=await h(this._ctx,{method:"POST",path:`/v1/ingest?table=${encodeURIComponent(this._table)}`,rawBody:e,contentType:De,signal:t?.signal});if(s)return p(s);let o=r??{total:0,succeeded:0,failed:0,duplicates:0},i={ok:o.failed===0,total:o.total,succeeded:o.succeeded,failed:o.failed,duplicates:o.duplicates};return o.results&&o.results.length>0&&(i.results=o.results),g(i)}async schema(e){let{data:t,error:r}=await h(this._ctx,{method:"GET",path:"/v1/ops/schema",params:{table:this._table,...S(e)},signal:e?.signal});return r?p(r):g(t)}stream(e){return this._createStream(this._table,e)}};var F=class{_ctx;schema;dlq;sys;pipes;settings;constructor(e){this._ctx={baseURL:e.baseURL.replace(/\/+$/,""),auth:e.auth,options:{maxRetries:e.options?.maxRetries??2,fetch:e.options?.fetch,headers:e.options?.headers,fetchOptions:e.options?.fetchOptions}},this.schema=new A(this._ctx),this.dlq=new O(this._ctx,(t,r)=>this._createStream(t,r)),this.sys=new q(this._ctx),this.pipes=new P(this._ctx),this.settings=new B(this._ctx)}from(e){return new H(this._ctx,e,(t,r)=>this._createStream(t,r))}pipe(e,t){return new C(this._ctx,e,t,(r,s)=>this._createStream(r,s))}sql(e,t){if(Array.isArray(t))throw new Error("[WaveHouse SDK] client.sql(sql, params) was removed. The /v1/ops/query endpoint does not accept positional `?` params. Inline literals into the SQL, or use the structured query builder (wh.from(table)\u2026) for safe binding from user input.");return oe(this._ctx,e,t)}_createStream(e,t){let r=new M({baseURL:this._ctx.baseURL,table:e,since:t?.since,auth:this._ctx.auth,fetch:this._ctx.options.fetch,headers:this._ctx.options.headers,fetchOptions:this._ctx.options.fetchOptions}),s=new T(r);return t?.signal&&s.attachSignal(t.signal),s}};function de(n){return new F(n)}return be(He);})();
|
|
12
12
|
//# sourceMappingURL=index.global.js.map
|