@fusedio/widget-sdk 0.1.1 → 0.3.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/dist/bridge.d.ts +9 -0
- package/dist/bundle.js +2 -2
- package/dist/define-catalog.d.ts +5 -3
- package/dist/hooks/json-ui-binding.d.ts +7 -0
- package/dist/hooks/json-ui-binding.js +27 -0
- package/dist/hooks/sql-source-overrides.d.ts +16 -0
- package/dist/hooks/sql-source-overrides.js +29 -0
- package/dist/hooks/use-duckdb-sql.d.ts +8 -2
- package/dist/hooks/use-duckdb-sql.js +25 -3
- package/dist/hooks/use-fused-param-with-form.d.ts +18 -0
- package/dist/hooks/use-fused-param-with-form.js +56 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +11 -1
- package/dist/utils/parse-style.d.ts +9 -0
- package/dist/utils/parse-style.js +27 -0
- package/package.json +1 -1
package/dist/bridge.d.ts
CHANGED
|
@@ -87,6 +87,15 @@ export interface RoutingBridge {
|
|
|
87
87
|
export interface SqlQueryOptions {
|
|
88
88
|
defaultLimit?: number;
|
|
89
89
|
signal?: AbortSignal;
|
|
90
|
+
/**
|
|
91
|
+
* Optional binding identity (chunk-2 MCP-host seam). When the host resolves
|
|
92
|
+
* data server-side (the MCP Apps renderer), it stamps a `_queryId` into each
|
|
93
|
+
* data-bound node's props and the SDK threads it here so the static bridge can
|
|
94
|
+
* look up the pre-resolved rows by id. The workbench bridge ignores this field
|
|
95
|
+
* (it runs the query against DuckDB regardless), so it is fully
|
|
96
|
+
* backward-compatible.
|
|
97
|
+
*/
|
|
98
|
+
queryId?: string;
|
|
90
99
|
}
|
|
91
100
|
export interface SqlQueryResult {
|
|
92
101
|
rows: ReadonlyArray<Record<string, unknown>>;
|
package/dist/bundle.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var ir="parameter-updates",ae=(o=>(o.PARAM="param",o.RANGE="range",o.VIEWPORT="viewport",o.CLEAR="clear",o))(ae||{});function ur(e){if(typeof e!="object"||e===null)return!1;let n=e;return typeof n.type=="string"&&Object.values(ae).includes(n.type)&&typeof n.parameter=="string"&&"values"in n}import{createContext as ye,useContext as Re}from"react";var be=ye(null);be.displayName="FusedWidgetBridgeContext";function y(){let e=Re(be);if(!e)throw new Error("useFusedWidgetBridge: no FusedWidgetBridgeContext provider in the tree. Wrap your components with the workbench's <JsonUiProvider> or the test harness's <FusedWidgetBridgeContext.Provider value={createTestBridge()}>.");return e}var he=ye(null);he.displayName="JsonUiNodeOverrideContext";function V(){let e=y(),n=Re(he);return n?{udfUniqueId:n.udfUniqueId??e.node.udfUniqueId,udfName:n.udfName??e.node.udfName,configHash:n.configHash??e.node.configHash}:{udfUniqueId:e.node.udfUniqueId,udfName:e.node.udfName,configHash:e.node.configHash}}import{createContext as nn,useCallback as ve,useContext as rn,useRef as we,useSyncExternalStore as tn}from"react";function dr(){let e=new Map,n=new Set,r=t=>{n.forEach(o=>{o.names.has(t)&&o.cb()})};return{get(t){return e.get(t)},getSnapshot(t){let o={};for(let i of t)e.has(i)&&(o[i]=e.get(i));return o},getAll(){let t={};return e.forEach((o,i)=>{t[i]=o}),t},setField(t,o){e.has(t)&&Object.is(e.get(t),o)||(e.set(t,o),r(t))},removeField(t){e.has(t)&&(e.delete(t),r(t))},subscribe(t,o){let i={names:new Set(t),cb:o};return n.add(i),()=>{n.delete(i)}}}}var Ue=nn({store:null,isInForm:!1});Ue.displayName="JsonUiFormContext";function on(){return rn(Ue)}var xe=Object.freeze({});function j(e){let{store:n,isInForm:r}=on(),t=un(e),o=ve(f=>n?n.subscribe(t,f):()=>{},[n,t]),i=we(xe),l=ve(()=>{if(!n)return xe;let f=n.getSnapshot(t),a=i.current;return sn(a,f)?a:(i.current=f,f)},[n,t]),s=tn(o,l,l);return{inForm:r,values:s}}function sn(e,n){if(e===n)return!0;let r=Object.keys(e),t=Object.keys(n);if(r.length!==t.length)return!1;for(let o of r)if(!Object.is(e[o],n[o]))return!1;return!0}function un(e){let n=we(e),r=n.current;return r!==e&&(r.length!==e.length||r.some((t,o)=>t!==e[o]))&&(n.current=e),n.current}function an(e){return e}function ln(e){return e}import{useCallback as X,useEffect as J,useMemo as Y,useRef as I,useState as cn}from"react";function fn({param:e,debounceMs:n=300,readOnly:r=!1,defaultValue:t,broadcastDefaultValue:o=!0,validate:i,preprocess:l}){let s=y(),{configHash:f}=V(),a=!!e,R=(u,c)=>{if(!e)return;if(u==="Cleared"){s.log.log(`Cleared param "${e}"`,"info",f);return}let d=JSON.stringify(c),N=d&&d.length>100?d.slice(0,100)+"\u2026":d;s.log.log(`${u} param "${e}" = ${N}`,"info",f)},p=Y(()=>l??gn(t),[l]),C=Y(()=>i??dn(t),[i]),g=Y(()=>e?[e]:[],[e]),{inForm:b,values:h}=j(g),P=e?h[e]:void 0,T=Y(()=>{if(!(!a||!e))return s.params.getSnapshot(e)},[s,a,e]),v=()=>{let u=b&&P!==void 0?P:T;if(u==null)return t;let c=p(u);return C(c)?c:t},[D,w]=cn(v),x=I(D);x.current=D;let m=I(null),A=I(!1),L=I(!1),F=I({enabled:a,param:e});F.current={enabled:a,param:e};let E=I(s);E.current=s;let Q=I(e);J(()=>{let u=Q.current;Q.current=e,u&&u!==e&&s.params.clear(u)},[s,e]),J(()=>{if(!a||!e||A.current)return;let u=b&&P!==void 0?P:s.params.getSnapshot(e);if(u==null)return;let c=p(u);c!==x.current&&C(c)&&(w(c),R("Received",u))},[s,e,a,b,P,p,C]),J(()=>!a||!e?void 0:s.params.subscribe(e,()=>{if(A.current)return;let c=s.params.getSnapshot(e);if(c==null)return;let d=p(c);d!==x.current&&C(d)&&(w(d),R("Received",c))}),[s,e,a,p,C]);let M=X(u=>{!a||!e||(s.params.set(e,u,"param"),s.edges.stopLoading(),R("Broadcast",u))},[s,a,e]),q=X(()=>{!a||r||(m.current&&(clearTimeout(m.current),m.current=null),s.edges.startLoading(),M(x.current),A.current=!1)},[s,M,a,r]),U=X(u=>{m.current&&(clearTimeout(m.current),m.current=null),w(u),x.current=u,A.current=!1,!(!a||!e||r)&&(s.params.clear(e),s.edges.stopLoading(),R("Cleared",null))},[s,a,e,r]);J(()=>{L.current=!1},[e,a]),J(()=>{if(!a||!e||r||!o||L.current)return;let u=s.params.getSnapshot(e);if(u!=null){L.current=!0;return}if(x.current===""){L.current=!0;return}M(x.current),L.current=!0},[s,a,e,r,o,M]);let _=X(u=>{w(u),!(!a||r)&&(A.current=!0,s.edges.startLoading(),m.current&&clearTimeout(m.current),m.current=setTimeout(()=>{M(u),A.current=!1},n))},[s,M,n,a,r]);return J(()=>()=>{m.current&&clearTimeout(m.current);let{enabled:u,param:c}=F.current;!u||!c||E.current.params.clear(c)},[]),{value:D,setValue:_,broadcastNow:q,clearValue:U}}function dn(e){return typeof e=="string"?(n=>typeof n=="string"):typeof e=="number"?(n=>typeof n=="number"):typeof e=="boolean"?(n=>typeof n=="boolean"):Array.isArray(e)?(n=>Array.isArray(n)):e!==null&&typeof e=="object"?(n=>n!==null&&typeof n=="object"&&!Array.isArray(n)):(n=>!0)}function gn(e){return typeof e=="string"?n=>typeof n=="string"?n:Array.isArray(n)?n.join(","):n!==null&&typeof n=="object"?JSON.stringify(n):String(n):n=>n}import{useCallback as ke,useRef as Pe,useSyncExternalStore as pn}from"react";var Ce=Object.freeze({});function Z(e){let n=y(),r=Sn(e),t=ke(l=>r.length===0?()=>{}:n.params.subscribeMany(r,l),[n,r]),o=Pe(Ce),i=ke(()=>{if(r.length===0)return Ce;let l=n.params.getSnapshotMany(r),s=o.current;return mn(s,l)?s:(o.current=l,l)},[n,r]);return pn(t,i,i)}function mn(e,n){if(e===n)return!0;let r=Object.keys(e),t=Object.keys(n);if(r.length!==t.length)return!1;for(let o of r)if(!Object.is(e[o],n[o]))return!1;return!0}function Sn(e){let n=Pe(e),r=n.current;return r!==e&&(r.length!==e.length||r.some((t,o)=>t!==e[o]))&&(n.current=e),n.current}import{useCallback as le,useRef as yn,useSyncExternalStore as Rn}from"react";function bn(){let e=y(),n=le(l=>e.routing.subscribeAllowedSources(l),[e]),r=yn(null),t=le(()=>{let l=e.routing.getAllowedSources(),s=r.current;return hn(s,l)?s:(r.current=l,l)},[e]),o=Rn(n,t,t),i=le((l,s)=>!o||o.length===0||!l&&!s?!0:o.some(f=>f.udfUniqueId&&f.udfUniqueId===l||f.udfName&&f.udfName===s),[o]);return{allowedSources:o,isAllowedSource:i}}function hn(e,n){return e===n?!0:e===null||n===null||e.length!==n.length?!1:e.every((r,t)=>r.udfUniqueId===n[t].udfUniqueId&&r.udfName===n[t].udfName)}import{useCallback as Ee,useRef as vn,useSyncExternalStore as xn}from"react";function wn(){let e=y(),n=Ee(o=>e.routing.subscribeAllowedSources(o),[e]),r=vn(null),t=Ee(()=>{let o=e.routing.getAllowedUdfNames(),i=r.current;return Un(i,o)?i:(r.current=o,o)},[e]);return xn(n,t,t)}function Un(e,n){if(e===n)return!0;if(e===null||n===null||e.size!==n.size)return!1;for(let r of e)if(!n.has(r))return!1;return!0}import{useEffect as kn,useMemo as $,useRef as Cn,useState as Ae,useSyncExternalStore as Pn,useCallback as Le}from"react";var Fe=/\$([a-zA-Z_][a-zA-Z0-9_]*)/g,En=/\{\{[\s\S]*?\}\}/,Te=/\{\{\s*([A-Za-z_][A-Za-z0-9_]*)\b/g;function ce(e,n={}){let r=e??"",t=n.preserveMissingParams??!1,o=y(),i=$(()=>An(r),[r]),l=Z(i),{inForm:s,values:f}=j(i),a=$(()=>s?{...l,...f}:l,[l,f,s]),R=$(()=>En.test(r),[r]),p=$(()=>R?"":Ln(r,a,t),[r,a,t,R]),C=$(()=>{if(!R)return[];let w=new Set,x=[];Te.lastIndex=0;let m;for(;(m=Te.exec(r))!==null;)w.has(m[1])||(w.add(m[1]),x.push(m[1]));return x},[r,R]),g=Fn(o,C),[b,h]=Ae(()=>({key:"",value:""})),[P,T]=Ae(!1),v=$(()=>JSON.stringify({template:r,paramValues:a,preserveMissingParams:t,tick:g}),[r,a,t,g]);return kn(()=>{if(!R){T(!1);return}let w=!1,x=new AbortController;return T(!0),o.template.render(r,a,{preserveMissingParams:t,signal:x.signal}).then(m=>{w||(h(A=>A.key===v&&A.value===m.value?A:{key:v,value:m.value}),T(m.loading))},m=>{w||m?.name!=="AbortError"&&T(!1)}),()=>{w=!0,x.abort()}},[o,R,r,a,t,v]),{value:$(()=>{if(!R)return p;if(b.key===v)return b.value;try{return o.template.renderLoading(r,a,{preserveMissingParams:t})}catch{return r}},[o,R,p,b,v,r,a,t]),loading:R?P:!1}}function An(e){let n=[],r=new Set;for(let t of e.matchAll(Fe)){let o=t[1];r.has(o)||(r.add(o),n.push(o))}return n}function Ln(e,n,r){return e.replace(Fe,(t,o)=>{let i=n[o];return i==null?r?t:"":Tn(i)})}function Tn(e){return e==null?"":typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):JSON.stringify(e)??""}function Fn(e,n){let r=Cn(0),t=n.slice().sort().join("|"),o=Le(l=>{let s=()=>{r.current+=1,l()},f=[e.template.subscribe(s)];for(let a of n)f.push(e.udfs.subscribeOutput(a,s));return()=>f.forEach(a=>a())},[e,t]),i=Le(()=>r.current,[]);return Pn(o,i,i)}import{useCallback as ee,useEffect as Dn,useMemo as ne,useRef as On,useState as De,useSyncExternalStore as Nn}from"react";function Oe(e){let n=y(),r=ee(i=>e?n.udfs.subscribeOutput(e,i):()=>{},[n,e]),t=On(void 0),o=ee(()=>{if(!e)return;let i=n.udfs.getOutputSnapshot(e),l=t.current;return Mn(l,i)?l:(t.current=i,i)},[n,e]);return Nn(r,o,o)}function Ne(){let e=y();return ee(n=>e.udfs.requestReexecute(n),[e])}function Mn(e,n){return e===n?!0:!e||!n?!1:e.data===n.data&&e.isExecutionInProgress===n.isExecutionInProgress&&e.error===n.error&&e.vfsFilename===n.vfsFilename}var Me=/^\{\{(\w+)\.(\w+)(?:\[(\d+)\])?\}\}$/;function re(e){return!e||typeof e!="string"?!1:Me.test(e)}function fe(e){if(!re(e))return null;let n=e.match(Me);if(!n)return null;let[,r,t,o]=n,i=o!==void 0?parseInt(o,10):void 0;return{udfName:r,columnName:t,index:i}}function Bn(e){return!!e&&typeof e=="object"&&typeof e.getRows=="function"}function de({udfName:e,sampleSize:n=200}){let r=Oe(e),t=Ne(),[o,i]=De([]),[l,s]=De([]);Dn(()=>{let a=!1,R=r?.data;if(!R||!Bn(R)){i([]),s([]);return}return(async()=>{try{let p=await R.getRows(0,Math.max(0,n));if(a)return;let C=p.map(b=>{let h=b;return h&&typeof h=="object"&&h.properties&&typeof h.properties=="object"?h.properties:b});i(C);let g=Array.from(new Set(C.flatMap(b=>Object.keys(b??{}))));s(g)}catch{if(a)return;i([]),s([])}})(),()=>{a=!0}},[r?.data,n]);let f=ee(()=>{e&&t(e)},[t,e]);return{loading:r?.isExecutionInProgress??!1,errorMessage:r?.error??null,isError:!!r?.error,columns:l,rows:o,requestReexecute:f}}function qn(e,n=200){let r=re(e),t=ne(()=>r?fe(e):null,[r,e]),{rows:o,loading:i}=de({udfName:t?.udfName,sampleSize:n});return{values:ne(()=>!t||!t.columnName?[]:o.map(s=>s?.[t.columnName]).filter(s=>s!=null),[o,t]),loading:r?i:!1}}function _n(e,n=200){let r=re(e),t=ne(()=>r?fe(e):null,[r,e]),{rows:o,loading:i}=de({udfName:t?.udfName,sampleSize:n});return{value:ne(()=>{if(!t||!t.columnName||t.index===void 0)return null;let s=o[t.index];if(!s)return null;let f=s[t.columnName];return f!==void 0?f:null},[o,t]),loading:r?i:!1}}import{useCallback as Ke,useEffect as z,useMemo as O,useRef as Hn,useState as B}from"react";import{useCallback as te,useMemo as Qn,useRef as ge,useSyncExternalStore as In}from"react";var Be=Object.freeze([]);function oe(){let e=y(),{configHash:n}=V(),r=ge(e);r.current=e;let t=ge(n);t.current=n;let o=te((i,l="info")=>{r.current.log.log(i,l,t.current)},[]);return Qn(()=>({log:o}),[o])}function $n(e){let n=y(),r=te(i=>e?n.log.subscribeLogs(e,i):()=>{},[n,e]),t=ge(Be),o=te(()=>{if(!e)return Be;let i=n.log.getLogsSnapshot(e);return i===t.current?t.current:(t.current=i,i)},[n,e]);return In(r,o,o)}function Vn(e){let n=y();return te(()=>{e&&n.log.clearLogs(e)},[n,e])}function se(){let e=y();return{startLoading:e.edges.startLoading,stopLoading:e.edges.stopLoading}}var pe=/\$([a-zA-Z_][a-zA-Z0-9_]*)/g,qe=/\{\{(\w+)(?:\?([^}]*))?\}\}/g,me=/'((?:s3|gs|fd):\/\/[^'\n]+)'/g;function jn(e){return e==null?"''":typeof e=="number"&&!Number.isNaN(e)?String(e):typeof e=="boolean"?e?"TRUE":"FALSE":`'${String(e).replace(/'/g,"''")}'`}function Jn(e,n){let r=!1;for(let t=0;t<n;t++)if(e[t]==="'"){if(r&&e[t+1]==="'"){t++;continue}r=!r}return r}function _e(e,n){return e.replace(pe,(r,t,o)=>{let i=n[t],l=i==null?"":String(i);return Jn(e,o)?l.replace(/'/g,"''"):jn(i)})}function Qe(e){let n=new Set,r=[];pe.lastIndex=0;for(let t of e.matchAll(pe)){let o=t[1];n.has(o)||(n.add(o),r.push(o))}return r}function Wn(e){if(!e)return null;let n={},r=!1;for(let t of e.split(/[&,]/)){if(!t)continue;let o=t.indexOf("=");if(o===-1)continue;let i=t.slice(0,o),l=t.slice(o+1),s,f;try{s=decodeURIComponent(i),f=decodeURIComponent(l)}catch{s=i,f=l}s&&(n[s]=f,r=!0)}return r?n:null}function Ie(e){let n=[],r;for(qe.lastIndex=0;(r=qe.exec(e))!==null;){let[t,o,i]=r;n.push({match:t,name:o,overrides:Wn(i),start:r.index,end:r.index+t.length})}return n}function $e(e){if(!e)return[];let n=new Set,r=[];me.lastIndex=0;let t;for(;(t=me.exec(e))!==null;){let o=t[1];n.has(o)||(n.add(o),r.push(o))}return r}function Ve(e,n){return e&&e.replace(me,(r,t)=>{let o=n[t];return o?`'${o}'`:r})}var je=/^\$([a-zA-Z_][a-zA-Z0-9_]*)$/;function Je(e){let n=e.trim(),r=je.exec(n);return r?r[1]:null}function We(e,n){let r=je.exec(e);if(!r)return{value:e,unresolved:!1};let t=r[1];if(!(t in n))return{value:e,unresolved:!0};let o=n[t];return o==null?{value:"",unresolved:!1}:{value:String(o),unresolved:!1}}function zn(e){return Object.keys(e).sort().map(n=>`${n}=${e[n]}`).join("&")}function ze(e,n){return n?`${e}#${zn(n)}`:e}var Ze=500,W=Object.freeze([]),G=Object.freeze([]);function He(e,n){if(/\bLIMIT\b/i.test(e))return e;let r=e.trimEnd();return`${r.endsWith(";")?r.slice(0,-1):r} LIMIT ${n}`}function Kn(e){return`"${e.replace(/"/g,'""')}"`}function Zn(e,n,r,t,o,i){let l=e.match(/^\$([a-zA-Z_][a-zA-Z0-9_]*)$/);if(l){let f=o[l[1]];return f==null?"":He(String(f),i)}let s=e;for(let f=n.length-1;f>=0;f--){let{raw:a,key:R,resolvedOverrides:p}=n[f],g=p===null&&t?t[a.name]:void 0,b;g?b=Kn(g.relationName):b=`'${r.get(R)??`${a.name}.parquet`}'`,s=s.slice(0,a.start)+b+s.slice(a.end)}return s=He(s,i),_e(s,o)}function Ge({sql:e,enabled:n=!0,maxRows:r=Ze,sourceOverrides:t}){let o=y(),{startLoading:i,stopLoading:l}=se(),{log:s}=oe(),[f,a]=B(""),[R,p]=B(!1),[C,g]=B(null),[b,h]=B(0),P=O(()=>e?Ie(e):[],[e]),T=O(()=>t?P.filter(u=>u.overrides!==null||!t[u.name]):P,[P,t]),v=O(()=>{let u=new Set;for(let c of T)if(c.overrides)for(let d of Object.values(c.overrides)){let N=Je(d);N&&u.add(N)}return Array.from(u)},[T]),D=O(()=>e?Qe(e):[],[e]),w=O(()=>{let u=new Set,c=[];for(let d of D)u.has(d)||(u.add(d),c.push(d));for(let d of v)u.has(d)||(u.add(d),c.push(d));return c},[D,v]),x=Z(w),{inForm:m,values:A}=j(w),L=O(()=>m?{...x,...A}:x,[m,x,A]),F=O(()=>T.map(u=>{if(!u.overrides)return{raw:u,key:u.name,resolvedOverrides:null,unresolved:!1};let c={},d=!1;for(let[N,H]of Object.entries(u.overrides)){let S=We(H,L);S.unresolved&&(d=!0),c[N]=S.value}return{raw:u,key:ze(u.name,c),resolvedOverrides:c,unresolved:d}}),[T,L]),E=O(()=>{let u=new Set,c=[];for(let d of F)d.unresolved||u.has(d.key)||(u.add(d.key),c.push({name:d.raw.name,key:d.key,overrides:d.resolvedOverrides??void 0}));return c},[F]),Q=O(()=>E.map(u=>`${u.key}|${u.name}|${u.overrides?Object.entries(u.overrides).sort(([c],[d])=>c.localeCompare(d)).map(([c,d])=>`${c}=${d}`).join(","):""}`).join(`
|
|
2
|
-
`),[
|
|
1
|
+
var xr="parameter-updates",ce=(o=>(o.PARAM="param",o.RANGE="range",o.VIEWPORT="viewport",o.CLEAR="clear",o))(ce||{});function br(e){if(typeof e!="object"||e===null)return!1;let n=e;return typeof n.type=="string"&&Object.values(ce).includes(n.type)&&typeof n.parameter=="string"&&"values"in n}import{createContext as ke,useContext as Ce}from"react";var Pe=ke(null);Pe.displayName="FusedWidgetBridgeContext";function v(){let e=Ce(Pe);if(!e)throw new Error("useFusedWidgetBridge: no FusedWidgetBridgeContext provider in the tree. Wrap your components with the workbench's <JsonUiProvider> or the test harness's <FusedWidgetBridgeContext.Provider value={createTestBridge()}>.");return e}var Ee=ke(null);Ee.displayName="JsonUiNodeOverrideContext";function j(){let e=v(),n=Ce(Ee);return n?{udfUniqueId:n.udfUniqueId??e.node.udfUniqueId,udfName:n.udfName??e.node.udfName,configHash:n.configHash??e.node.configHash}:{udfUniqueId:e.node.udfUniqueId,udfName:e.node.udfName,configHash:e.node.configHash}}import{createContext as dn,useCallback as Ae,useContext as fn,useRef as Le,useSyncExternalStore as gn}from"react";function Cr(){let e=new Map,n=new Set,r=t=>{n.forEach(o=>{o.names.has(t)&&o.cb()})};return{get(t){return e.get(t)},getSnapshot(t){let o={};for(let s of t)e.has(s)&&(o[s]=e.get(s));return o},getAll(){let t={};return e.forEach((o,s)=>{t[s]=o}),t},setField(t,o){e.has(t)&&Object.is(e.get(t),o)||(e.set(t,o),r(t))},removeField(t){e.has(t)&&(e.delete(t),r(t))},subscribe(t,o){let s={names:new Set(t),cb:o};return n.add(s),()=>{n.delete(s)}}}}var Fe=dn({store:null,isInForm:!1});Fe.displayName="JsonUiFormContext";function de(){return fn(Fe)}var Oe=Object.freeze({});function W(e){let{store:n,isInForm:r}=de(),t=mn(e),o=Ae(c=>n?n.subscribe(t,c):()=>{},[n,t]),s=Le(Oe),u=Ae(()=>{if(!n)return Oe;let c=n.getSnapshot(t),l=s.current;return pn(l,c)?l:(s.current=c,c)},[n,t]),i=gn(o,u,u);return{inForm:r,values:i}}function pn(e,n){if(e===n)return!0;let r=Object.keys(e),t=Object.keys(n);if(r.length!==t.length)return!1;for(let o of r)if(!Object.is(e[o],n[o]))return!1;return!0}function mn(e){let n=Le(e),r=n.current;return r!==e&&(r.length!==e.length||r.some((t,o)=>t!==e[o]))&&(n.current=e),n.current}function Sn(e){return e}function yn(e){return e}import{useCallback as ee,useEffect as z,useMemo as ne,useRef as J,useState as Rn}from"react";function fe({param:e,debounceMs:n=300,readOnly:r=!1,defaultValue:t,broadcastDefaultValue:o=!0,validate:s,preprocess:u}){let i=v(),{configHash:c}=j(),l=!!e,x=(d,f)=>{if(!e)return;if(d==="Cleared"){i.log.log(`Cleared param "${e}"`,"info",c);return}let a=JSON.stringify(f),g=a&&a.length>100?a.slice(0,100)+"\u2026":a;i.log.log(`${d} param "${e}" = ${g}`,"info",c)},b=ne(()=>u??xn(t),[u]),w=ne(()=>s??vn(t),[s]),S=ne(()=>e?[e]:[],[e]),{inForm:p,values:h}=W(S),E=e?h[e]:void 0,q=ne(()=>{if(!(!l||!e))return i.params.getSnapshot(e)},[i,l,e]),k=()=>{let d=p&&E!==void 0?E:q;if(d==null)return t;let f=b(d);return w(f)?f:t},[N,O]=Rn(k),U=J(N);U.current=N;let y=J(null),C=J(!1),D=J(!1),T=J({enabled:l,param:e});T.current={enabled:l,param:e};let M=J(i);M.current=i;let L=J(e);z(()=>{let d=L.current;L.current=e,d&&d!==e&&i.params.clear(d)},[i,e]),z(()=>{if(!l||!e||C.current)return;let d=p&&E!==void 0?E:i.params.getSnapshot(e);if(d==null)return;let f=b(d);f!==U.current&&w(f)&&(O(f),x("Received",d))},[i,e,l,p,E,b,w]),z(()=>!l||!e?void 0:i.params.subscribe(e,()=>{if(C.current)return;let f=i.params.getSnapshot(e);if(f==null)return;let a=b(f);a!==U.current&&w(a)&&(O(a),x("Received",f))}),[i,e,l,b,w]);let A=ee(d=>{!l||!e||(i.params.set(e,d,"param"),i.edges.stopLoading(),x("Broadcast",d))},[i,l,e]),I=ee(()=>{!l||r||(y.current&&(clearTimeout(y.current),y.current=null),i.edges.startLoading(),A(U.current),C.current=!1)},[i,A,l,r]),$=ee(d=>{y.current&&(clearTimeout(y.current),y.current=null),O(d),U.current=d,C.current=!1,!(!l||!e||r)&&(i.params.clear(e),i.edges.stopLoading(),x("Cleared",null))},[i,l,e,r]);z(()=>{D.current=!1},[e,l]),z(()=>{if(!l||!e||r||!o||D.current)return;let d=i.params.getSnapshot(e);if(d!=null){D.current=!0;return}if(U.current===""){D.current=!0;return}A(U.current),D.current=!0},[i,l,e,r,o,A]);let Q=ee(d=>{O(d),!(!l||r)&&(C.current=!0,i.edges.startLoading(),y.current&&clearTimeout(y.current),y.current=setTimeout(()=>{A(d),C.current=!1},n))},[i,A,n,l,r]);return z(()=>()=>{y.current&&clearTimeout(y.current);let{enabled:d,param:f}=T.current;!d||!f||M.current.params.clear(f)},[]),{value:N,setValue:Q,broadcastNow:I,clearValue:$}}function vn(e){return typeof e=="string"?(n=>typeof n=="string"):typeof e=="number"?(n=>typeof n=="number"):typeof e=="boolean"?(n=>typeof n=="boolean"):Array.isArray(e)?(n=>Array.isArray(n)):e!==null&&typeof e=="object"?(n=>n!==null&&typeof n=="object"&&!Array.isArray(n)):(n=>!0)}function xn(e){return typeof e=="string"?n=>typeof n=="string"?n:Array.isArray(n)?n.join(","):n!==null&&typeof n=="object"?JSON.stringify(n):String(n):n=>n}import{useEffect as Te}from"react";function bn(e){let n=de(),r=e.param,t=!!(n.isInForm&&r),{value:o,setValue:s,broadcastNow:u,clearValue:i}=fe({...e,param:t?void 0:e.param}),c=n.store;return Te(()=>{!t||!r||!c||c.setField(r,o)},[o,t,r,c]),Te(()=>{if(!(!t||!r||!c))return()=>{c.removeField(r)}},[t,r,c]),{value:o,setValue:s,broadcastNow:u,clearValue:i,isInForm:n.isInForm}}import{useCallback as qe,useRef as De,useSyncExternalStore as hn}from"react";var Ne=Object.freeze({});function Y(e){let n=v(),r=wn(e),t=qe(u=>r.length===0?()=>{}:n.params.subscribeMany(r,u),[n,r]),o=De(Ne),s=qe(()=>{if(r.length===0)return Ne;let u=n.params.getSnapshotMany(r),i=o.current;return Un(i,u)?i:(o.current=u,u)},[n,r]);return hn(t,s,s)}function Un(e,n){if(e===n)return!0;let r=Object.keys(e),t=Object.keys(n);if(r.length!==t.length)return!1;for(let o of r)if(!Object.is(e[o],n[o]))return!1;return!0}function wn(e){let n=De(e),r=n.current;return r!==e&&(r.length!==e.length||r.some((t,o)=>t!==e[o]))&&(n.current=e),n.current}import{useCallback as ge,useRef as kn,useSyncExternalStore as Cn}from"react";function Pn(){let e=v(),n=ge(u=>e.routing.subscribeAllowedSources(u),[e]),r=kn(null),t=ge(()=>{let u=e.routing.getAllowedSources(),i=r.current;return En(i,u)?i:(r.current=u,u)},[e]),o=Cn(n,t,t),s=ge((u,i)=>!o||o.length===0||!u&&!i?!0:o.some(c=>c.udfUniqueId&&c.udfUniqueId===u||c.udfName&&c.udfName===i),[o]);return{allowedSources:o,isAllowedSource:s}}function En(e,n){return e===n?!0:e===null||n===null||e.length!==n.length?!1:e.every((r,t)=>r.udfUniqueId===n[t].udfUniqueId&&r.udfName===n[t].udfName)}import{useCallback as Be,useRef as An,useSyncExternalStore as On}from"react";function Ln(){let e=v(),n=Be(o=>e.routing.subscribeAllowedSources(o),[e]),r=An(null),t=Be(()=>{let o=e.routing.getAllowedUdfNames(),s=r.current;return Fn(s,o)?s:(r.current=o,o)},[e]);return On(n,t,t)}function Fn(e,n){if(e===n)return!0;if(e===null||n===null||e.size!==n.size)return!1;for(let r of e)if(!n.has(r))return!1;return!0}import{useEffect as Tn,useMemo as V,useRef as qn,useState as Me,useSyncExternalStore as Nn,useCallback as Ie}from"react";var Qe=/\$([a-zA-Z_][a-zA-Z0-9_]*)/g,Dn=/\{\{[\s\S]*?\}\}/,_e=/\{\{\s*([A-Za-z_][A-Za-z0-9_]*)\b/g;function pe(e,n={}){let r=e??"",t=n.preserveMissingParams??!1,o=v(),s=V(()=>Bn(r),[r]),u=Y(s),{inForm:i,values:c}=W(s),l=V(()=>i?{...u,...c}:u,[u,c,i]),x=V(()=>Dn.test(r),[r]),b=V(()=>x?"":Mn(r,l,t),[r,l,t,x]),w=V(()=>{if(!x)return[];let O=new Set,U=[];_e.lastIndex=0;let y;for(;(y=_e.exec(r))!==null;)O.has(y[1])||(O.add(y[1]),U.push(y[1]));return U},[r,x]),S=_n(o,w),[p,h]=Me(()=>({key:"",value:""})),[E,q]=Me(!1),k=V(()=>JSON.stringify({template:r,paramValues:l,preserveMissingParams:t,tick:S}),[r,l,t,S]);return Tn(()=>{if(!x){q(!1);return}let O=!1,U=new AbortController;return q(!0),o.template.render(r,l,{preserveMissingParams:t,signal:U.signal}).then(y=>{O||(h(C=>C.key===k&&C.value===y.value?C:{key:k,value:y.value}),q(y.loading))},y=>{O||y?.name!=="AbortError"&&q(!1)}),()=>{O=!0,U.abort()}},[o,x,r,l,t,k]),{value:V(()=>{if(!x)return b;if(p.key===k)return p.value;try{return o.template.renderLoading(r,l,{preserveMissingParams:t})}catch{return r}},[o,x,b,p,k,r,l,t]),loading:x?E:!1}}function Bn(e){let n=[],r=new Set;for(let t of e.matchAll(Qe)){let o=t[1];r.has(o)||(r.add(o),n.push(o))}return n}function Mn(e,n,r){return e.replace(Qe,(t,o)=>{let s=n[o];return s==null?r?t:"":In(s)})}function In(e){return e==null?"":typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):JSON.stringify(e)??""}function _n(e,n){let r=qn(0),t=n.slice().sort().join("|"),o=Ie(u=>{let i=()=>{r.current+=1,u()},c=[e.template.subscribe(i)];for(let l of n)c.push(e.udfs.subscribeOutput(l,i));return()=>c.forEach(l=>l())},[e,t]),s=Ie(()=>r.current,[]);return Nn(o,s,s)}import{useCallback as re,useEffect as Qn,useMemo as te,useRef as Jn,useState as Je,useSyncExternalStore as Vn}from"react";function Ve(e){let n=v(),r=re(s=>e?n.udfs.subscribeOutput(e,s):()=>{},[n,e]),t=Jn(void 0),o=re(()=>{if(!e)return;let s=n.udfs.getOutputSnapshot(e),u=t.current;return $n(u,s)?u:(t.current=s,s)},[n,e]);return Vn(r,o,o)}function $e(){let e=v();return re(n=>e.udfs.requestReexecute(n),[e])}function $n(e,n){return e===n?!0:!e||!n?!1:e.data===n.data&&e.isExecutionInProgress===n.isExecutionInProgress&&e.error===n.error&&e.vfsFilename===n.vfsFilename}var je=/^\{\{(\w+)\.(\w+)(?:\[(\d+)\])?\}\}$/;function oe(e){return!e||typeof e!="string"?!1:je.test(e)}function me(e){if(!oe(e))return null;let n=e.match(je);if(!n)return null;let[,r,t,o]=n,s=o!==void 0?parseInt(o,10):void 0;return{udfName:r,columnName:t,index:s}}function jn(e){return!!e&&typeof e=="object"&&typeof e.getRows=="function"}function Se({udfName:e,sampleSize:n=200}){let r=Ve(e),t=$e(),[o,s]=Je([]),[u,i]=Je([]);Qn(()=>{let l=!1,x=r?.data;if(!x||!jn(x)){s([]),i([]);return}return(async()=>{try{let b=await x.getRows(0,Math.max(0,n));if(l)return;let w=b.map(p=>{let h=p;return h&&typeof h=="object"&&h.properties&&typeof h.properties=="object"?h.properties:p});s(w);let S=Array.from(new Set(w.flatMap(p=>Object.keys(p??{}))));i(S)}catch{if(l)return;s([]),i([])}})(),()=>{l=!0}},[r?.data,n]);let c=re(()=>{e&&t(e)},[t,e]);return{loading:r?.isExecutionInProgress??!1,errorMessage:r?.error??null,isError:!!r?.error,columns:u,rows:o,requestReexecute:c}}function Wn(e,n=200){let r=oe(e),t=te(()=>r?me(e):null,[r,e]),{rows:o,loading:s}=Se({udfName:t?.udfName,sampleSize:n});return{values:te(()=>!t||!t.columnName?[]:o.map(i=>i?.[t.columnName]).filter(i=>i!=null),[o,t]),loading:r?s:!1}}function zn(e,n=200){let r=oe(e),t=te(()=>r?me(e):null,[r,e]),{rows:o,loading:s}=Se({udfName:t?.udfName,sampleSize:n});return{value:te(()=>{if(!t||!t.columnName||t.index===void 0)return null;let i=o[t.index];if(!i)return null;let c=i[t.columnName];return c!==void 0?c:null},[o,t]),loading:r?s:!1}}import{useCallback as on,useEffect as K,useMemo as F,useRef as ur,useState as B}from"react";import{createContext as Hn,useContext as Kn}from"react";var ye=Hn({});ye.displayName="JsonUiBindingContext";function Re(){return Kn(ye)}import{useCallback as se,useMemo as Zn,useRef as ve,useSyncExternalStore as Gn}from"react";var We=Object.freeze([]);function ie(){let e=v(),{configHash:n}=j(),r=ve(e);r.current=e;let t=ve(n);t.current=n;let o=se((s,u="info")=>{r.current.log.log(s,u,t.current)},[]);return Zn(()=>({log:o}),[o])}function Yn(e){let n=v(),r=se(s=>e?n.log.subscribeLogs(e,s):()=>{},[n,e]),t=ve(We),o=se(()=>{if(!e)return We;let s=n.log.getLogsSnapshot(e);return s===t.current?t.current:(t.current=s,s)},[n,e]);return Gn(r,o,o)}function Xn(e){let n=v();return se(()=>{e&&n.log.clearLogs(e)},[n,e])}function ue(){let e=v();return{startLoading:e.edges.startLoading,stopLoading:e.edges.stopLoading}}import{createContext as er,useContext as nr}from"react";var rr=Object.freeze({}),xe=er(rr);xe.displayName="SqlSourceOverrideContext";function be(){return nr(xe)}var he=/\$([a-zA-Z_][a-zA-Z0-9_]*)/g,ze=/\{\{(\w+)(?:\?([^}]*))?\}\}/g,Ue=/'((?:s3|gs|fd):\/\/[^'\n]+)'/g;function tr(e){return e==null?"''":typeof e=="number"&&!Number.isNaN(e)?String(e):typeof e=="boolean"?e?"TRUE":"FALSE":`'${String(e).replace(/'/g,"''")}'`}function or(e,n){let r=!1;for(let t=0;t<n;t++)if(e[t]==="'"){if(r&&e[t+1]==="'"){t++;continue}r=!r}return r}function He(e,n){return e.replace(he,(r,t,o)=>{let s=n[t],u=s==null?"":String(s);return or(e,o)?u.replace(/'/g,"''"):tr(s)})}function Ke(e){let n=new Set,r=[];he.lastIndex=0;for(let t of e.matchAll(he)){let o=t[1];n.has(o)||(n.add(o),r.push(o))}return r}function sr(e){if(!e)return null;let n={},r=!1;for(let t of e.split(/[&,]/)){if(!t)continue;let o=t.indexOf("=");if(o===-1)continue;let s=t.slice(0,o),u=t.slice(o+1),i,c;try{i=decodeURIComponent(s),c=decodeURIComponent(u)}catch{i=s,c=u}i&&(n[i]=c,r=!0)}return r?n:null}function Ze(e){let n=[],r;for(ze.lastIndex=0;(r=ze.exec(e))!==null;){let[t,o,s]=r;n.push({match:t,name:o,overrides:sr(s),start:r.index,end:r.index+t.length})}return n}function Ge(e){if(!e)return[];let n=new Set,r=[];Ue.lastIndex=0;let t;for(;(t=Ue.exec(e))!==null;){let o=t[1];n.has(o)||(n.add(o),r.push(o))}return r}function Ye(e,n){return e&&e.replace(Ue,(r,t)=>{let o=n[t];return o?`'${o}'`:r})}var Xe=/^\$([a-zA-Z_][a-zA-Z0-9_]*)$/;function en(e){let n=e.trim(),r=Xe.exec(n);return r?r[1]:null}function nn(e,n){let r=Xe.exec(e);if(!r)return{value:e,unresolved:!1};let t=r[1];if(!(t in n))return{value:e,unresolved:!0};let o=n[t];return o==null?{value:"",unresolved:!1}:{value:String(o),unresolved:!1}}function ir(e){return Object.keys(e).sort().map(n=>`${n}=${e[n]}`).join("&")}function rn(e,n){return n?`${e}#${ir(n)}`:e}var sn=500,H=Object.freeze([]),X=Object.freeze([]);function tn(e,n){if(/\bLIMIT\b/i.test(e))return e;let r=e.trimEnd();return`${r.endsWith(";")?r.slice(0,-1):r} LIMIT ${n}`}function ar(e){return`"${e.replace(/"/g,'""')}"`}function lr(e,n,r,t,o,s){let u=e.match(/^\$([a-zA-Z_][a-zA-Z0-9_]*)$/);if(u){let c=o[u[1]];return c==null?"":tn(String(c),s)}let i=e;for(let c=n.length-1;c>=0;c--){let{raw:l,key:x,resolvedOverrides:b}=n[c],S=b===null&&t?t[l.name]:void 0,p;S?p=ar(S.relationName):p=`'${r.get(x)??`${l.name}.parquet`}'`,i=i.slice(0,l.start)+p+i.slice(l.end)}return i=tn(i,s),He(i,o)}function un({sql:e,enabled:n=!0,maxRows:r=sn,sourceOverrides:t}){let o=v(),s=be(),u=F(()=>{let a=Object.keys(s).length>0;return t?a?{...s,...t}:t:a?s:void 0},[s,t]),{startLoading:i,stopLoading:c}=ue(),{log:l}=ie(),[x,b]=B(""),[w,S]=B(!1),[p,h]=B(null),[E,q]=B(0),k=F(()=>e?Ze(e):[],[e]),N=F(()=>u?k.filter(a=>a.overrides!==null||!u[a.name]):k,[k,u]),O=F(()=>{let a=new Set;for(let g of N)if(g.overrides)for(let R of Object.values(g.overrides)){let _=en(R);_&&a.add(_)}return Array.from(a)},[N]),U=F(()=>e?Ke(e):[],[e]),y=F(()=>{let a=new Set,g=[];for(let R of U)a.has(R)||(a.add(R),g.push(R));for(let R of O)a.has(R)||(a.add(R),g.push(R));return g},[U,O]),C=Y(y),{inForm:D,values:T}=W(y),M=F(()=>D?{...C,...T}:C,[D,C,T]),L=F(()=>N.map(a=>{if(!a.overrides)return{raw:a,key:a.name,resolvedOverrides:null,unresolved:!1};let g={},R=!1;for(let[_,Z]of Object.entries(a.overrides)){let m=nn(Z,M);m.unresolved&&(R=!0),g[_]=m.value}return{raw:a,key:rn(a.name,g),resolvedOverrides:g,unresolved:R}}),[N,M]),A=F(()=>{let a=new Set,g=[];for(let R of L)R.unresolved||a.has(R.key)||(a.add(R.key),g.push({name:R.raw.name,key:R.key,overrides:R.resolvedOverrides??void 0}));return g},[L]),I=F(()=>A.map(a=>`${a.key}|${a.name}|${a.overrides?Object.entries(a.overrides).sort(([g],[R])=>g.localeCompare(R)).map(([g,R])=>`${g}=${R}`).join(","):""}`).join(`
|
|
2
|
+
`),[A]),$=on(()=>{q(a=>a+1)},[]);K(()=>{if(!n||A.length===0)return;let a=A.map(g=>o.udfs.subscribeOutput(g.name,()=>{q(R=>R+1)}));return()=>{a.forEach(g=>g())}},[o,n,A]),K(()=>{w?i():c()},[w,i,c]);let Q=F(()=>{if(!u)return null;for(let a of k){if(a.overrides!==null)continue;let g=u[a.name];if(g?.error)return g.error}return null},[k,u]),d=F(()=>u?k.some(a=>a.overrides===null&&u[a.name]?.loading):!1,[k,u]),f=L.some(a=>a.unresolved);return K(()=>{if(!n||!e){b(""),S(!1),h(null);return}if(Q){b(""),h(Q),S(!1),l(`SQL preprocessing: ${Q}`,"error");return}if(d||f){b(""),h(null),S(!0);return}let a=!1;return S(!0),h(null),(async()=>{let g=new Map,R;if(A.length>0)try{let m=await o.sql.resolveVfsFilenames(A);if(a)return;if(m instanceof Map)for(let P of L){if(P.resolvedOverrides)continue;let G=m.get(P.raw.name);G&&g.set(P.key,G)}else g=m.filenames,R=m.errors}catch(m){if(a)return;let P=m instanceof Error?m.message:typeof m=="string"?m:"VFS registration failed";b(""),h(P),S(!1),l(`SQL preprocessing: ${P}`,"error");return}if(R)for(let m of L){let P=R.get(m.key);if(P){if(a)return;b(""),h(P),S(!1),l(`SQL preprocessing: ${P}`,"error");return}}for(let m of L)if(!(m.unresolved||m.resolvedOverrides===null&&u?.[m.raw.name]!==void 0)&&!g.has(m.key)){if(a)return;b(""),h(null),S(!0);return}let _;try{_=lr(e,L,g,u,M,r)}catch(m){if(a)return;let P=m instanceof Error?m.message:typeof m=="string"?m:"SQL preprocessing failed";b(""),h(P),S(!1),l(`SQL preprocessing failed: ${P}`,"error");return}let Z=Ge(_);if(Z.length===0){if(a)return;b(_),h(null),S(!1),l("SQL preprocessing completed");return}try{let m={},P=await Promise.all(Z.map(le=>o.signUrl(le)));if(a)return;Z.forEach((le,cn)=>{m[le]=P[cn].signed});let G=Ye(_,m);b(G),h(null),S(!1),l("SQL preprocessing completed")}catch(m){if(a)return;let P=m instanceof Error?m.message:typeof m=="string"?m:"URL signing failed";b(""),h(P),S(!1),l(`SQL preprocessing failed: ${P}`,"error")}})(),()=>{a=!0}},[o,n,e,I,L,M,u,Q,d,f,r,E,l,A]),{processedSql:x,loading:w,error:p,refetch:$}}function cr({sql:e,enabled:n=!0,maxRows:r=sn,sourceOverrides:t,queryId:o}){let s=v(),{startLoading:u,stopLoading:i}=ue(),{log:c}=ie(),{queryId:l}=Re(),x=o??l,[b,w]=B(H),[S,p]=B(X),[h,E]=B(!1),[q,k]=B(null),[N,O]=B(0),{processedSql:U,loading:y,error:C,refetch:D}=un({sql:e,enabled:n,maxRows:r,sourceOverrides:t}),T=ur(""),M=n&&!!e&&!!U&&!y&&!C&&U!==T.current,L=y||h||M;K(()=>{L?u():i()},[L,u,i]);let A=on(()=>{T.current="",D(),O(I=>I+1)},[D]);return K(()=>{if(!n||!e){T.current="",w(H),p(X),E(!1),k(null);return}if(C){T.current="",k(C),w(H),p(X),E(!1);return}if(y||!U){T.current="",E(!1);return}let I=!1,$=new AbortController;T.current=U,E(!0),k(null);let Q=U.length>120?U.slice(0,120)+"\u2026":U;c(`SQL query started: ${Q}`);let d=performance.now();return s.sql.query(U,{signal:$.signal,queryId:x}).then(f=>{if(I)return;let a=Math.round(performance.now()-d);if(f.error){w(H),p(X),k(f.error),E(!1),c(`SQL failed (${a}ms): ${f.error}`,"error");return}w(f.rows.length===0?H:f.rows),p(f.columns),k(null),E(!1),c(`SQL completed: ${f.rows.length} row${f.rows.length!==1?"s":""} in ${a}ms`)},f=>{if(I||f?.name==="AbortError")return;let a=Math.round(performance.now()-d),g=f instanceof Error?f.message:typeof f=="string"?f:"SQL query failed";k(g),w(H),p(X),E(!1),c(`SQL failed (${a}ms): ${g}`,"error")}),()=>{I=!0,$.abort()}},[s,n,e,U,y,C,N,c,x]),{rows:b,columns:S,loading:L,error:q,refetch:A}}function dr(e,n=!0){let r=v(),[t,o]=B({filenames:new Map,loading:!1}),s=F(()=>e.slice().sort().join("|"),[e]);return K(()=>{if(!n||e.length===0){o({filenames:new Map,loading:!1});return}let u=!1;return o(i=>({...i,loading:!0,error:void 0})),r.sql.resolveVfsFilenames(e).then(i=>{if(u)return;let c=i instanceof Map?i:i.filenames;o({filenames:c,loading:!1})},i=>{u||o({filenames:new Map,loading:!1,error:i instanceof Error?i.message:String(i)})}),()=>{u=!0}},[r,s,n]),t}import{useCallback as an,useEffect as fr,useState as ae}from"react";var ln=["s3://","gs://","fd://"];function we(e){return ln.some(n=>e.startsWith(n))}function gr(){let e=v();return{signUrl:an(r=>e.signUrl(r),[e])}}function pr(e){let n=v(),{value:r,loading:t}=pe(e),[o,s]=ae(null),[u,i]=ae(null),[c,l]=ae(!1),[x,b]=ae(0);fr(()=>{if(t)return;if(!r){s(null),i(null),l(!1);return}if(!we(r)){s(r),i(null),l(!1);return}let S=!1;return l(!0),i(null),n.signUrl(r).then(({signed:p})=>{S||s(p??r)}).catch(p=>{S||(i(p instanceof Error?p.message:"Failed to load media"),s(null))}).finally(()=>{S||l(!1)}),()=>{S=!0}},[n,t,r,x]);let w=an(async()=>{if(!r||!we(r))return r??null;let{signed:S}=await n.signUrl(r),p=S??r;return s(p),i(null),b(h=>h+1),p},[n,r]);return{src:o,loading:t||c,error:u,refreshSignedUrl:w,resolvedSrc:r,needsSigning:!!(r&&we(r))}}import{useEffect as mr,useState as Sr}from"react";function yr(e,n){let r=v(),[t,o]=Sr({status:"idle"});return mr(()=>{if(!n||!e?.trim()){o({status:"idle"});return}let s=!1;return o({status:"checking"}),r.uploads.checkAccess(e).then(u=>{s||(u.ok?o({status:"allowed"}):o({status:"denied",message:u.message??"Upload access denied."}))}),()=>{s=!0}},[r,e,n]),t}function Rr(){return j()}function vr(e){if(!e)return{};let n={};for(let r of e.split(";")){let t=r.indexOf(":");if(t===-1)continue;let o=r.slice(0,t).trim(),s=r.slice(t+1).trim();if(!o||!s)continue;let u=o.replace(/-([a-z])/g,(i,c)=>c.toUpperCase());n[u]=s}return n}export{Fe as FormContext,Pe as FusedWidgetBridgeContext,ye as JsonUiBindingContext,Ee as JsonUiNodeOverrideContext,xr as PARAMETER_BROADCAST_CHANNEL,ce as ParameterMessageType,Ue as SIGNABLE_URL_LITERAL_REGEX,ln as SIGNED_URL_SCHEMES,he as SQL_PARAM_REGEX,ze as SQL_SOURCE_PLACEHOLDER_REGEX,xe as SqlSourceOverrideContext,ir as canonicalOverrideKey,rn as computePlaceholderKey,Cr as createFormParamsStore,yn as defineCatalog,Sn as defineComponent,tr as escapeSqlValue,Ge as extractSignableUrls,Ke as extractSqlParams,en as getDollarRefName,br as isStandardMessage,oe as isUdfQuery,sr as parseOverridesString,Ze as parseSqlUdfPlaceholders,vr as parseStyle,me as parseUdfColumnQuery,nn as resolveOverrideValue,Ye as rewriteSignedUrls,He as substituteSqlParams,Pn as useAllowedSources,Ln as useAllowedUdfNames,Y as useCanvasParams,cr as useDuckDbSqlQuery,un as useDuckDbSqlQueryPreprocessing,de as useFormContext,W as useFormParams,fe as useFusedParam,bn as useFusedParamWithForm,v as useFusedWidgetBridge,Re as useJsonUiBinding,ue as useJsonUiEdgeAnimation,ie as useJsonUiLog,Xn as useJsonUiLogClear,Yn as useJsonUiLogs,j as useJsonUiNode,Rr as useJsonUiUdfInfo,pr as useMediaSrc,pe as useParamSubstitution,$e as useRequestUdfReexecute,be as useSqlSourceOverrides,zn as useUdfColumnValue,Wn as useUdfColumnValues,Se as useUdfDataFrameSample,Ve as useUdfOutputByName,yr as useUploadAccessCheck,gr as useUrlSigning,dr as useVfsRegistration};
|
package/dist/define-catalog.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { CatalogComponentDefinition } from "./define-component";
|
|
|
5
5
|
* export default defineCatalog({
|
|
6
6
|
* components: { "kebab-key": defineComponent({...}), ... },
|
|
7
7
|
* skill, // string imported from "../SKILL.md" (esbuild text loader)
|
|
8
|
-
* summary, // ≤
|
|
8
|
+
* summary, // ≤240-char headline; REQUIRED when skill is present
|
|
9
9
|
* });
|
|
10
10
|
*
|
|
11
11
|
* `skill` and `summary` are co-required at the **type level** via function
|
|
@@ -36,9 +36,11 @@ export interface CatalogDefinitionWithSkill extends CatalogDefinitionBase {
|
|
|
36
36
|
*/
|
|
37
37
|
skill: string;
|
|
38
38
|
/**
|
|
39
|
-
* ≤
|
|
39
|
+
* ≤240-char headline shown in the system prompt's
|
|
40
40
|
* `<available_catalog_skills>` block so the AI can decide whether the
|
|
41
|
-
* catalog is relevant before fetching the full skill.
|
|
41
|
+
* catalog is relevant before fetching the full skill. A longer summary is
|
|
42
|
+
* truncated to 240 chars by the workbench loader (with a console warning)
|
|
43
|
+
* rather than failing the catalog load.
|
|
42
44
|
*/
|
|
43
45
|
summary: string;
|
|
44
46
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface JsonUiBinding {
|
|
2
|
+
/** Resolver-stamped query id for this node (e.g. `"q0"`); undefined elsewhere. */
|
|
3
|
+
queryId?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const JsonUiBindingContext: import("react").Context<JsonUiBinding>;
|
|
6
|
+
/** Read the current node's data-binding identity. `{}` when no provider is present. */
|
|
7
|
+
export declare function useJsonUiBinding(): JsonUiBinding;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JsonUiBindingContext = void 0;
|
|
4
|
+
exports.useJsonUiBinding = useJsonUiBinding;
|
|
5
|
+
/**
|
|
6
|
+
* JsonUiBindingContext — per-node data-binding identity (chunk-2 MCP-host seam).
|
|
7
|
+
*
|
|
8
|
+
* When a host resolves a widget's data server-side (the MCP Apps renderer), it
|
|
9
|
+
* stamps a deterministic `_queryId` into each data-bound node's props and wraps
|
|
10
|
+
* that node's renderer in a `<JsonUiBindingContext.Provider value={{queryId}}>`.
|
|
11
|
+
* SDK data hooks (currently `useDuckDbSqlQuery`) read the id via
|
|
12
|
+
* `useJsonUiBinding()` and thread it into `bridge.sql.query(sql, { queryId })`,
|
|
13
|
+
* letting the static MCP bridge look up the pre-resolved rows by id instead of
|
|
14
|
+
* running DuckDB in the sandbox.
|
|
15
|
+
*
|
|
16
|
+
* The default value is `{}` (no binding). In every other host (workbench, test
|
|
17
|
+
* harness, mobile) the provider is absent, `queryId` is `undefined`, and the
|
|
18
|
+
* hooks behave exactly as before — so this seam is fully backward-compatible and
|
|
19
|
+
* data-bound components never need editing.
|
|
20
|
+
*/
|
|
21
|
+
const react_1 = require("react");
|
|
22
|
+
exports.JsonUiBindingContext = (0, react_1.createContext)({});
|
|
23
|
+
exports.JsonUiBindingContext.displayName = "JsonUiBindingContext";
|
|
24
|
+
/** Read the current node's data-binding identity. `{}` when no provider is present. */
|
|
25
|
+
function useJsonUiBinding() {
|
|
26
|
+
return (0, react_1.useContext)(exports.JsonUiBindingContext);
|
|
27
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface SqlSourceOverride {
|
|
2
|
+
/** In-memory DuckDB relation name to substitute for the `{{name}}` placeholder. */
|
|
3
|
+
relationName: string;
|
|
4
|
+
/** Error from materializing the source, if any. */
|
|
5
|
+
error?: string;
|
|
6
|
+
/** True while the source is still materializing. */
|
|
7
|
+
loading?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export type SqlSourceOverrideMap = Record<string, SqlSourceOverride>;
|
|
10
|
+
/**
|
|
11
|
+
* Provided by hosts that expose named in-memory SQL sources to descendant
|
|
12
|
+
* widgets. Defaults to empty — most hosts and most subtrees have no overrides.
|
|
13
|
+
*/
|
|
14
|
+
export declare const SqlSourceOverrideContext: import("react").Context<SqlSourceOverrideMap>;
|
|
15
|
+
/** Read the ancestor-provided SQL source overrides (empty map when none). */
|
|
16
|
+
export declare function useSqlSourceOverrides(): SqlSourceOverrideMap;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SqlSourceOverrideContext = void 0;
|
|
4
|
+
exports.useSqlSourceOverrides = useSqlSourceOverrides;
|
|
5
|
+
/**
|
|
6
|
+
* Host-provided SQL source overrides.
|
|
7
|
+
*
|
|
8
|
+
* Lets a host replace `{{name}}` SQL placeholders with an in-memory DuckDB
|
|
9
|
+
* relation instead of the UDF's VFS Parquet file. The Fused workbench's
|
|
10
|
+
* `sql-runner` component provides these for its descendant json-ui widgets
|
|
11
|
+
* (so a chart/metric/text nested under a sql-runner reads its in-memory tab);
|
|
12
|
+
* other hosts (MCP, test harness) leave it empty.
|
|
13
|
+
*
|
|
14
|
+
* The SDK SQL hooks (`useDuckDbSqlQuery` / `useDuckDbSqlQueryPreprocessing`)
|
|
15
|
+
* read this context automatically and merge it with any explicit
|
|
16
|
+
* `sourceOverrides` option, so component authors never thread it manually.
|
|
17
|
+
*/
|
|
18
|
+
const react_1 = require("react");
|
|
19
|
+
const EMPTY_OVERRIDES = Object.freeze({});
|
|
20
|
+
/**
|
|
21
|
+
* Provided by hosts that expose named in-memory SQL sources to descendant
|
|
22
|
+
* widgets. Defaults to empty — most hosts and most subtrees have no overrides.
|
|
23
|
+
*/
|
|
24
|
+
exports.SqlSourceOverrideContext = (0, react_1.createContext)(EMPTY_OVERRIDES);
|
|
25
|
+
exports.SqlSourceOverrideContext.displayName = "SqlSourceOverrideContext";
|
|
26
|
+
/** Read the ancestor-provided SQL source overrides (empty map when none). */
|
|
27
|
+
function useSqlSourceOverrides() {
|
|
28
|
+
return (0, react_1.useContext)(exports.SqlSourceOverrideContext);
|
|
29
|
+
}
|
|
@@ -24,6 +24,12 @@ export interface UseDuckDbSqlQueryOptions {
|
|
|
24
24
|
}>;
|
|
25
25
|
/** @deprecated Use `maxRows` — kept temporarily for the SDK's existing surface. */
|
|
26
26
|
defaultLimit?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Binding identity for server-resolved data (MCP-host seam). When omitted,
|
|
29
|
+
* the hook falls back to `useJsonUiBinding()`. Threaded into
|
|
30
|
+
* `bridge.sql.query(sql, { queryId })`; the workbench bridge ignores it.
|
|
31
|
+
*/
|
|
32
|
+
queryId?: string;
|
|
27
33
|
}
|
|
28
34
|
export interface UseDuckDbSqlQueryResult {
|
|
29
35
|
rows: ReadonlyArray<Record<string, unknown>>;
|
|
@@ -43,13 +49,13 @@ export interface UseDuckDbSqlQueryPreprocessingResult {
|
|
|
43
49
|
* Preprocess SQL: resolve placeholders, register UDFs via the bridge,
|
|
44
50
|
* substitute params, sign URLs, append LIMIT. Returns the prepared SQL.
|
|
45
51
|
*/
|
|
46
|
-
export declare function useDuckDbSqlQueryPreprocessing({ sql, enabled, maxRows, sourceOverrides, }: UseDuckDbSqlQueryOptions): UseDuckDbSqlQueryPreprocessingResult;
|
|
52
|
+
export declare function useDuckDbSqlQueryPreprocessing({ sql, enabled, maxRows, sourceOverrides: explicitSourceOverrides, }: UseDuckDbSqlQueryOptions): UseDuckDbSqlQueryPreprocessingResult;
|
|
47
53
|
/**
|
|
48
54
|
* Execute a DuckDB SQL query against UDF Parquet outputs. Uses
|
|
49
55
|
* `useDuckDbSqlQueryPreprocessing` to prepare the SQL string, then runs
|
|
50
56
|
* it via the bridge.
|
|
51
57
|
*/
|
|
52
|
-
export declare function useDuckDbSqlQuery({ sql, enabled, maxRows, sourceOverrides, }: UseDuckDbSqlQueryOptions): UseDuckDbSqlQueryResult;
|
|
58
|
+
export declare function useDuckDbSqlQuery({ sql, enabled, maxRows, sourceOverrides, queryId: queryIdOption, }: UseDuckDbSqlQueryOptions): UseDuckDbSqlQueryResult;
|
|
53
59
|
/**
|
|
54
60
|
* Resolve UDF names to VFS filenames, registering them in DuckDB if needed.
|
|
55
61
|
* Exposed for advanced use cases (e.g. building your own query string).
|
|
@@ -21,9 +21,11 @@ exports.useVfsRegistration = useVfsRegistration;
|
|
|
21
21
|
const react_1 = require("react");
|
|
22
22
|
const bridge_1 = require("../bridge");
|
|
23
23
|
const form_1 = require("../form");
|
|
24
|
+
const json_ui_binding_1 = require("./json-ui-binding");
|
|
24
25
|
const use_json_ui_log_1 = require("./use-json-ui-log");
|
|
25
26
|
const use_json_ui_edge_animation_1 = require("./use-json-ui-edge-animation");
|
|
26
27
|
const use_canvas_params_1 = require("./use-canvas-params");
|
|
28
|
+
const sql_source_overrides_1 = require("./sql-source-overrides");
|
|
27
29
|
const sql_placeholders_1 = require("../utils/sql-placeholders");
|
|
28
30
|
const DEFAULT_MAX_ROWS = 500;
|
|
29
31
|
const EMPTY_ROWS = Object.freeze([]);
|
|
@@ -74,8 +76,22 @@ function buildProcessedSql(sql, resolved, fileNameMap, sourceOverrides, sqlParam
|
|
|
74
76
|
* Preprocess SQL: resolve placeholders, register UDFs via the bridge,
|
|
75
77
|
* substitute params, sign URLs, append LIMIT. Returns the prepared SQL.
|
|
76
78
|
*/
|
|
77
|
-
function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows = DEFAULT_MAX_ROWS, sourceOverrides, }) {
|
|
79
|
+
function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows = DEFAULT_MAX_ROWS, sourceOverrides: explicitSourceOverrides, }) {
|
|
78
80
|
const bridge = (0, bridge_1.useFusedWidgetBridge)();
|
|
81
|
+
// Auto-detect host-provided source overrides (e.g. the workbench's
|
|
82
|
+
// sql-runner exposes in-memory relations to descendants) and merge them with
|
|
83
|
+
// any explicit option. Explicit overrides win on key collision. Component
|
|
84
|
+
// authors never thread this manually.
|
|
85
|
+
const contextSourceOverrides = (0, sql_source_overrides_1.useSqlSourceOverrides)();
|
|
86
|
+
const sourceOverrides = (0, react_1.useMemo)(() => {
|
|
87
|
+
const hasContext = Object.keys(contextSourceOverrides).length > 0;
|
|
88
|
+
if (!explicitSourceOverrides) {
|
|
89
|
+
return hasContext ? contextSourceOverrides : undefined;
|
|
90
|
+
}
|
|
91
|
+
if (!hasContext)
|
|
92
|
+
return explicitSourceOverrides;
|
|
93
|
+
return { ...contextSourceOverrides, ...explicitSourceOverrides };
|
|
94
|
+
}, [contextSourceOverrides, explicitSourceOverrides]);
|
|
79
95
|
const { startLoading: startEdgeLoading, stopLoading: stopEdgeLoading } = (0, use_json_ui_edge_animation_1.useJsonUiEdgeAnimation)();
|
|
80
96
|
const { log } = (0, use_json_ui_log_1.useJsonUiLog)();
|
|
81
97
|
const [processedSql, setProcessedSql] = (0, react_1.useState)("");
|
|
@@ -407,10 +423,15 @@ function useDuckDbSqlQueryPreprocessing({ sql, enabled = true, maxRows = DEFAULT
|
|
|
407
423
|
* `useDuckDbSqlQueryPreprocessing` to prepare the SQL string, then runs
|
|
408
424
|
* it via the bridge.
|
|
409
425
|
*/
|
|
410
|
-
function useDuckDbSqlQuery({ sql, enabled = true, maxRows = DEFAULT_MAX_ROWS, sourceOverrides, }) {
|
|
426
|
+
function useDuckDbSqlQuery({ sql, enabled = true, maxRows = DEFAULT_MAX_ROWS, sourceOverrides, queryId: queryIdOption, }) {
|
|
411
427
|
const bridge = (0, bridge_1.useFusedWidgetBridge)();
|
|
412
428
|
const { startLoading: startEdgeLoading, stopLoading: stopEdgeLoading } = (0, use_json_ui_edge_animation_1.useJsonUiEdgeAnimation)();
|
|
413
429
|
const { log } = (0, use_json_ui_log_1.useJsonUiLog)();
|
|
430
|
+
// Server-resolved data seam: explicit option wins, else fall back to the
|
|
431
|
+
// per-node binding context. `undefined` in every non-MCP host (no behavior
|
|
432
|
+
// change for the workbench).
|
|
433
|
+
const { queryId: queryIdBinding } = (0, json_ui_binding_1.useJsonUiBinding)();
|
|
434
|
+
const queryId = queryIdOption ?? queryIdBinding;
|
|
414
435
|
const [rows, setRows] = (0, react_1.useState)(EMPTY_ROWS);
|
|
415
436
|
const [columns, setColumns] = (0, react_1.useState)(EMPTY_COLUMNS);
|
|
416
437
|
const [queryLoading, setQueryLoading] = (0, react_1.useState)(false);
|
|
@@ -475,7 +496,7 @@ function useDuckDbSqlQuery({ sql, enabled = true, maxRows = DEFAULT_MAX_ROWS, so
|
|
|
475
496
|
: processedSql;
|
|
476
497
|
log(`SQL query started: ${truncatedSql}`);
|
|
477
498
|
const t0 = performance.now();
|
|
478
|
-
bridge.sql.query(processedSql, { signal: controller.signal }).then((result) => {
|
|
499
|
+
bridge.sql.query(processedSql, { signal: controller.signal, queryId }).then((result) => {
|
|
479
500
|
if (cancelled)
|
|
480
501
|
return;
|
|
481
502
|
const elapsed = Math.round(performance.now() - t0);
|
|
@@ -522,6 +543,7 @@ function useDuckDbSqlQuery({ sql, enabled = true, maxRows = DEFAULT_MAX_ROWS, so
|
|
|
522
543
|
preprocessingError,
|
|
523
544
|
fetchKey,
|
|
524
545
|
log,
|
|
546
|
+
queryId,
|
|
525
547
|
]);
|
|
526
548
|
return { rows, columns, loading, error, refetch };
|
|
527
549
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { UseFusedParamOptions, UseFusedParamReturn } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Form-aware variant of {@link useFusedParam}.
|
|
4
|
+
*
|
|
5
|
+
* When the component is rendered inside a built-in Form, the field becomes
|
|
6
|
+
* local state (its value is NOT broadcast to the canvas) and its live value is
|
|
7
|
+
* mirrored into the form's subscription store, so sibling components (a
|
|
8
|
+
* dropdown's SQL options, a chart, a text binding, …) can react to it before
|
|
9
|
+
* the form is submitted. Outside a form it behaves exactly like
|
|
10
|
+
* `useFusedParam` — two-way canvas binding with debounced broadcast.
|
|
11
|
+
*
|
|
12
|
+
* Requires a `FusedWidgetBridgeContext` ancestor (like `useFusedParam`) and a
|
|
13
|
+
* `FormContext` ancestor for the in-form behavior (the built-in Form component
|
|
14
|
+
* provides one).
|
|
15
|
+
*/
|
|
16
|
+
export declare function useFusedParamWithForm<T extends string | number>(options: UseFusedParamOptions<T>): UseFusedParamReturn<T> & {
|
|
17
|
+
isInForm: boolean;
|
|
18
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useFusedParamWithForm = useFusedParamWithForm;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const form_1 = require("../form");
|
|
6
|
+
const use_fused_param_1 = require("./use-fused-param");
|
|
7
|
+
/**
|
|
8
|
+
* Form-aware variant of {@link useFusedParam}.
|
|
9
|
+
*
|
|
10
|
+
* When the component is rendered inside a built-in Form, the field becomes
|
|
11
|
+
* local state (its value is NOT broadcast to the canvas) and its live value is
|
|
12
|
+
* mirrored into the form's subscription store, so sibling components (a
|
|
13
|
+
* dropdown's SQL options, a chart, a text binding, …) can react to it before
|
|
14
|
+
* the form is submitted. Outside a form it behaves exactly like
|
|
15
|
+
* `useFusedParam` — two-way canvas binding with debounced broadcast.
|
|
16
|
+
*
|
|
17
|
+
* Requires a `FusedWidgetBridgeContext` ancestor (like `useFusedParam`) and a
|
|
18
|
+
* `FormContext` ancestor for the in-form behavior (the built-in Form component
|
|
19
|
+
* provides one).
|
|
20
|
+
*/
|
|
21
|
+
function useFusedParamWithForm(options) {
|
|
22
|
+
const formContext = (0, form_1.useFormContext)();
|
|
23
|
+
const param = options.param;
|
|
24
|
+
const isFormField = Boolean(formContext.isInForm && param);
|
|
25
|
+
// Hook handles both cases: with param (canvas sync) or without (local state).
|
|
26
|
+
// Disable canvas messaging when inside a form by withholding the param.
|
|
27
|
+
const { value, setValue, broadcastNow, clearValue } = (0, use_fused_param_1.useFusedParam)({
|
|
28
|
+
...options,
|
|
29
|
+
param: isFormField ? undefined : options.param,
|
|
30
|
+
});
|
|
31
|
+
// Mirror the live value into the form's subscription store so sibling
|
|
32
|
+
// components can react to it. Value updates use a dedicated effect so we
|
|
33
|
+
// don't briefly remove the field from the store between renders —
|
|
34
|
+
// unregistration runs only when the binding (store/param) actually changes
|
|
35
|
+
// or on unmount.
|
|
36
|
+
const store = formContext.store;
|
|
37
|
+
(0, react_1.useEffect)(() => {
|
|
38
|
+
if (!isFormField || !param || !store)
|
|
39
|
+
return;
|
|
40
|
+
store.setField(param, value);
|
|
41
|
+
}, [value, isFormField, param, store]);
|
|
42
|
+
(0, react_1.useEffect)(() => {
|
|
43
|
+
if (!isFormField || !param || !store)
|
|
44
|
+
return;
|
|
45
|
+
return () => {
|
|
46
|
+
store.removeField(param);
|
|
47
|
+
};
|
|
48
|
+
}, [isFormField, param, store]);
|
|
49
|
+
return {
|
|
50
|
+
value,
|
|
51
|
+
setValue,
|
|
52
|
+
broadcastNow,
|
|
53
|
+
clearValue,
|
|
54
|
+
isInForm: formContext.isInForm,
|
|
55
|
+
};
|
|
56
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -21,15 +21,19 @@ export * from "./types";
|
|
|
21
21
|
export { defineComponent, type CatalogComponentDefinition, } from "./define-component";
|
|
22
22
|
export { defineCatalog, type CatalogDefinition, type CatalogDefinitionBase, type CatalogDefinitionWithSkill, } from "./define-catalog";
|
|
23
23
|
export { useFusedParam } from "./hooks/use-fused-param";
|
|
24
|
+
export { useFusedParamWithForm } from "./hooks/use-fused-param-with-form";
|
|
24
25
|
export { useCanvasParams } from "./hooks/use-canvas-params";
|
|
25
26
|
export { useAllowedSources } from "./hooks/use-allowed-sources";
|
|
26
27
|
export { useAllowedUdfNames } from "./hooks/use-allowed-udf-names";
|
|
27
28
|
export { useParamSubstitution } from "./hooks/use-param-substitution";
|
|
28
29
|
export { useUdfOutputByName, useRequestUdfReexecute, useUdfDataFrameSample, useUdfColumnValue, useUdfColumnValues, isUdfQuery, parseUdfColumnQuery, type ParsedUdfQuery, type UseUdfDataFrameSampleOptions, type UseUdfDataFrameSampleResult, type UseUdfColumnValueResult, type UseUdfColumnValuesResult, } from "./hooks/use-udf-output";
|
|
29
30
|
export { useDuckDbSqlQuery, useDuckDbSqlQueryPreprocessing, useVfsRegistration, type UseDuckDbSqlQueryOptions, type UseDuckDbSqlQueryResult, type UseDuckDbSqlQueryPreprocessingResult, } from "./hooks/use-duckdb-sql";
|
|
31
|
+
export { SqlSourceOverrideContext, useSqlSourceOverrides, type SqlSourceOverride, type SqlSourceOverrideMap, } from "./hooks/sql-source-overrides";
|
|
30
32
|
export { useUrlSigning, useMediaSrc, SIGNED_URL_SCHEMES, type UseMediaSrcResult, } from "./hooks/use-url-signing";
|
|
31
33
|
export { useUploadAccessCheck, type UploadAccessState, } from "./hooks/use-upload-access-check";
|
|
32
34
|
export { useJsonUiLog, useJsonUiLogs, useJsonUiLogClear, } from "./hooks/use-json-ui-log";
|
|
33
35
|
export { useJsonUiUdfInfo } from "./hooks/use-json-ui-udf-info";
|
|
34
36
|
export { useJsonUiEdgeAnimation } from "./hooks/use-json-ui-edge-animation";
|
|
37
|
+
export { JsonUiBindingContext, useJsonUiBinding, type JsonUiBinding, } from "./hooks/json-ui-binding";
|
|
35
38
|
export * from "./utils/sql-placeholders";
|
|
39
|
+
export { parseStyle } from "./utils/parse-style";
|
package/dist/index.js
CHANGED
|
@@ -30,7 +30,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
30
30
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
31
31
|
};
|
|
32
32
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
-
exports.useJsonUiEdgeAnimation = exports.useJsonUiUdfInfo = exports.useJsonUiLogClear = exports.useJsonUiLogs = exports.useJsonUiLog = exports.useUploadAccessCheck = exports.SIGNED_URL_SCHEMES = exports.useMediaSrc = exports.useUrlSigning = exports.useVfsRegistration = exports.useDuckDbSqlQueryPreprocessing = exports.useDuckDbSqlQuery = exports.parseUdfColumnQuery = exports.isUdfQuery = exports.useUdfColumnValues = exports.useUdfColumnValue = exports.useUdfDataFrameSample = exports.useRequestUdfReexecute = exports.useUdfOutputByName = exports.useParamSubstitution = exports.useAllowedUdfNames = exports.useAllowedSources = exports.useCanvasParams = exports.useFusedParam = exports.defineCatalog = exports.defineComponent = void 0;
|
|
33
|
+
exports.parseStyle = exports.useJsonUiBinding = exports.JsonUiBindingContext = exports.useJsonUiEdgeAnimation = exports.useJsonUiUdfInfo = exports.useJsonUiLogClear = exports.useJsonUiLogs = exports.useJsonUiLog = exports.useUploadAccessCheck = exports.SIGNED_URL_SCHEMES = exports.useMediaSrc = exports.useUrlSigning = exports.useSqlSourceOverrides = exports.SqlSourceOverrideContext = exports.useVfsRegistration = exports.useDuckDbSqlQueryPreprocessing = exports.useDuckDbSqlQuery = exports.parseUdfColumnQuery = exports.isUdfQuery = exports.useUdfColumnValues = exports.useUdfColumnValue = exports.useUdfDataFrameSample = exports.useRequestUdfReexecute = exports.useUdfOutputByName = exports.useParamSubstitution = exports.useAllowedUdfNames = exports.useAllowedSources = exports.useCanvasParams = exports.useFusedParamWithForm = exports.useFusedParam = exports.defineCatalog = exports.defineComponent = void 0;
|
|
34
34
|
// ── Part 1: Provider contract ────────────────────────────────────────────────
|
|
35
35
|
__exportStar(require("./protocol"), exports);
|
|
36
36
|
__exportStar(require("./bridge"), exports);
|
|
@@ -45,6 +45,8 @@ Object.defineProperty(exports, "defineCatalog", { enumerable: true, get: functio
|
|
|
45
45
|
// ── Part 2: Hooks ────────────────────────────────────────────────────────────
|
|
46
46
|
var use_fused_param_1 = require("./hooks/use-fused-param");
|
|
47
47
|
Object.defineProperty(exports, "useFusedParam", { enumerable: true, get: function () { return use_fused_param_1.useFusedParam; } });
|
|
48
|
+
var use_fused_param_with_form_1 = require("./hooks/use-fused-param-with-form");
|
|
49
|
+
Object.defineProperty(exports, "useFusedParamWithForm", { enumerable: true, get: function () { return use_fused_param_with_form_1.useFusedParamWithForm; } });
|
|
48
50
|
var use_canvas_params_1 = require("./hooks/use-canvas-params");
|
|
49
51
|
Object.defineProperty(exports, "useCanvasParams", { enumerable: true, get: function () { return use_canvas_params_1.useCanvasParams; } });
|
|
50
52
|
var use_allowed_sources_1 = require("./hooks/use-allowed-sources");
|
|
@@ -65,6 +67,9 @@ var use_duckdb_sql_1 = require("./hooks/use-duckdb-sql");
|
|
|
65
67
|
Object.defineProperty(exports, "useDuckDbSqlQuery", { enumerable: true, get: function () { return use_duckdb_sql_1.useDuckDbSqlQuery; } });
|
|
66
68
|
Object.defineProperty(exports, "useDuckDbSqlQueryPreprocessing", { enumerable: true, get: function () { return use_duckdb_sql_1.useDuckDbSqlQueryPreprocessing; } });
|
|
67
69
|
Object.defineProperty(exports, "useVfsRegistration", { enumerable: true, get: function () { return use_duckdb_sql_1.useVfsRegistration; } });
|
|
70
|
+
var sql_source_overrides_1 = require("./hooks/sql-source-overrides");
|
|
71
|
+
Object.defineProperty(exports, "SqlSourceOverrideContext", { enumerable: true, get: function () { return sql_source_overrides_1.SqlSourceOverrideContext; } });
|
|
72
|
+
Object.defineProperty(exports, "useSqlSourceOverrides", { enumerable: true, get: function () { return sql_source_overrides_1.useSqlSourceOverrides; } });
|
|
68
73
|
var use_url_signing_1 = require("./hooks/use-url-signing");
|
|
69
74
|
Object.defineProperty(exports, "useUrlSigning", { enumerable: true, get: function () { return use_url_signing_1.useUrlSigning; } });
|
|
70
75
|
Object.defineProperty(exports, "useMediaSrc", { enumerable: true, get: function () { return use_url_signing_1.useMediaSrc; } });
|
|
@@ -79,5 +84,10 @@ var use_json_ui_udf_info_1 = require("./hooks/use-json-ui-udf-info");
|
|
|
79
84
|
Object.defineProperty(exports, "useJsonUiUdfInfo", { enumerable: true, get: function () { return use_json_ui_udf_info_1.useJsonUiUdfInfo; } });
|
|
80
85
|
var use_json_ui_edge_animation_1 = require("./hooks/use-json-ui-edge-animation");
|
|
81
86
|
Object.defineProperty(exports, "useJsonUiEdgeAnimation", { enumerable: true, get: function () { return use_json_ui_edge_animation_1.useJsonUiEdgeAnimation; } });
|
|
87
|
+
var json_ui_binding_1 = require("./hooks/json-ui-binding");
|
|
88
|
+
Object.defineProperty(exports, "JsonUiBindingContext", { enumerable: true, get: function () { return json_ui_binding_1.JsonUiBindingContext; } });
|
|
89
|
+
Object.defineProperty(exports, "useJsonUiBinding", { enumerable: true, get: function () { return json_ui_binding_1.useJsonUiBinding; } });
|
|
82
90
|
// ── Pure utilities (re-exported for advanced workbench paths) ────────────────
|
|
83
91
|
__exportStar(require("./utils/sql-placeholders"), exports);
|
|
92
|
+
var parse_style_1 = require("./utils/parse-style");
|
|
93
|
+
Object.defineProperty(exports, "parseStyle", { enumerable: true, get: function () { return parse_style_1.parseStyle; } });
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Parses a plain CSS string into a React CSSProperties object.
|
|
4
|
+
* e.g. "color: red; font-size: 16px" → { color: "red", fontSize: "16px" }
|
|
5
|
+
*
|
|
6
|
+
* Pure — no bridge, no context. Used by every json-ui component that accepts
|
|
7
|
+
* a `style` string prop, across all hosts (workbench, MCP, test harness).
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseStyle(style: string | undefined): CSSProperties;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseStyle = parseStyle;
|
|
4
|
+
/**
|
|
5
|
+
* Parses a plain CSS string into a React CSSProperties object.
|
|
6
|
+
* e.g. "color: red; font-size: 16px" → { color: "red", fontSize: "16px" }
|
|
7
|
+
*
|
|
8
|
+
* Pure — no bridge, no context. Used by every json-ui component that accepts
|
|
9
|
+
* a `style` string prop, across all hosts (workbench, MCP, test harness).
|
|
10
|
+
*/
|
|
11
|
+
function parseStyle(style) {
|
|
12
|
+
if (!style)
|
|
13
|
+
return {};
|
|
14
|
+
const result = {};
|
|
15
|
+
for (const declaration of style.split(";")) {
|
|
16
|
+
const colonIdx = declaration.indexOf(":");
|
|
17
|
+
if (colonIdx === -1)
|
|
18
|
+
continue;
|
|
19
|
+
const property = declaration.slice(0, colonIdx).trim();
|
|
20
|
+
const value = declaration.slice(colonIdx + 1).trim();
|
|
21
|
+
if (!property || !value)
|
|
22
|
+
continue;
|
|
23
|
+
const camelCase = property.replace(/-([a-z])/g, (_, l) => l.toUpperCase());
|
|
24
|
+
result[camelCase] = value;
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|