nao-core 0.0.15__py3-none-any.whl → 0.0.17__py3-none-any.whl
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.
- nao_core/__init__.py +1 -1
- nao_core/bin/chats/588bbb8a-dcbc-42dc-b0d8-b6b9ed13e2fb.json +45 -0
- nao_core/bin/fastapi/main.py +19 -2
- nao_core/bin/migrations-postgres/{0000_supreme_cable.sql → 0000_user_auth_and_chat_tables.sql} +35 -22
- nao_core/bin/migrations-postgres/meta/0000_snapshot.json +208 -111
- nao_core/bin/migrations-postgres/meta/_journal.json +2 -2
- nao_core/bin/migrations-sqlite/{0000_cloudy_squirrel_girl.sql → 0000_user_auth_and_chat_tables.sql} +35 -22
- nao_core/bin/migrations-sqlite/meta/0000_snapshot.json +189 -105
- nao_core/bin/migrations-sqlite/meta/_journal.json +2 -2
- nao_core/bin/nao-chat-server +0 -0
- nao_core/bin/public/assets/_chat-layout-Do0mWziW.js +1 -0
- nao_core/bin/public/assets/_chat-layout.index-mxrV7qZY.js +1 -0
- nao_core/bin/public/assets/agentProvider-cEZoyU1e.js +1 -0
- nao_core/bin/public/assets/code-block-F6WJLWQG-oIWcWPcR.js +153 -0
- nao_core/bin/public/assets/createLucideIcon-BGNfPWE_.js +1 -0
- nao_core/bin/public/assets/index-B-_pu_22.js +59 -0
- nao_core/bin/public/assets/index-CWAm1NQa.css +1 -0
- nao_core/bin/public/assets/login-CF4uOXFH.js +1 -0
- nao_core/bin/public/assets/mermaid-FSSLJTFX-BzFakw7W.js +380 -0
- nao_core/bin/public/assets/signinForm-D98dwmLQ.js +1 -0
- nao_core/bin/public/assets/signup-CQSmDpcH.js +1 -0
- nao_core/bin/public/assets/utils-DzJYey0s.js +1 -0
- nao_core/bin/public/index.html +2 -2
- nao_core/bin/public/nao-logo-greyscale.svg +25 -0
- nao_core/commands/init.py +111 -0
- nao_core/commands/sync/__init__.py +59 -0
- nao_core/commands/sync/accessors.py +212 -0
- nao_core/commands/sync/databases.py +132 -0
- nao_core/commands/sync/registry.py +23 -0
- nao_core/commands/sync/repositories.py +103 -0
- nao_core/config/base.py +2 -0
- nao_core/config/repos/__init__.py +3 -0
- nao_core/config/repos/base.py +11 -0
- {nao_core-0.0.15.dist-info → nao_core-0.0.17.dist-info}/METADATA +1 -1
- nao_core-0.0.17.dist-info/RECORD +51 -0
- nao_core/bin/public/assets/_chatId-z5gRlor1.js +0 -1
- nao_core/bin/public/assets/chat-messages-DUR3D342.js +0 -1
- nao_core/bin/public/assets/index-BDlcD_HE.js +0 -1
- nao_core/bin/public/assets/index-Bc7icYyJ.css +0 -1
- nao_core/bin/public/assets/index-CGg3ZQH6.js +0 -49
- nao_core/bin/public/assets/login-D87n9R5V.js +0 -1
- nao_core/bin/public/assets/signinForm-9PY1Lvqj.js +0 -1
- nao_core/bin/public/assets/signup-B7NC1g08.js +0 -1
- nao_core/commands/sync.py +0 -380
- nao_core-0.0.15.dist-info/RECORD +0 -39
- {nao_core-0.0.15.dist-info → nao_core-0.0.17.dist-info}/WHEEL +0 -0
- {nao_core-0.0.15.dist-info → nao_core-0.0.17.dist-info}/entry_points.txt +0 -0
- {nao_core-0.0.15.dist-info → nao_core-0.0.17.dist-info}/licenses/LICENSE +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u,r as o,j as c}from"./index-CGg3ZQH6.js";import{S as d,a as g}from"./signinForm-9PY1Lvqj.js";function w(){const r=u(),[e,s]=o.useState({email:"",password:""}),[n,t]=o.useState(""),i=async a=>{a.preventDefault(),t(""),await g.email({email:e.email,password:e.password},{onSuccess:()=>{r({to:"/"})},onError:p=>{t(p.error.message)}})},m=a=>{s({...e,[a.target.name]:a.target.value})},l=[{id:"email",name:"email",type:"email",label:"Email",placeholder:"Enter your email"},{id:"password",name:"password",type:"password",label:"Password",placeholder:"Enter your password"}];return c.jsx(d,{title:"Sign In",fields:l,formData:e,onSubmit:i,onChange:m,submitButtonText:"Sign In",footerText:"Don't have an account?",footerLinkText:"Sign up",footerLinkTo:"/signup",error:n})}export{w as component};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{c as ve,r as H,j as g,a as ae,b as Te,t as Pe,B as le,L as Le}from"./index-CGg3ZQH6.js";const Ie=[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]],Ne=ve("eye-off",Ie);const Ae=[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]],Ue=ve("eye",Ae);function Ce({className:e,type:t,...n}){const[r,s]=H.useState(!1),l=t==="password",o=l&&r?"text":t;return l?g.jsxs("div",{className:"relative",children:[g.jsx("input",{type:o,"data-slot":"input",className:ae("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm","focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]","aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive","pr-10",e),...n}),g.jsx("button",{type:"button",onClick:()=>s(!r),className:"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors",tabIndex:-1,children:r?g.jsx(Ne,{size:16}):g.jsx(Ue,{size:16})})]}):g.jsx("input",{type:t,"data-slot":"input",className:ae("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm","focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]","aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",e),...n})}var je={},ue={};const J=Object.create(null),q=e=>je||globalThis.Deno?.env.toObject()||globalThis.__env__||(e?J:globalThis),E=new Proxy(J,{get(e,t){return q()[t]??J[t]},has(e,t){return t in q()||t in J},set(e,t,n){const r=q(!0);return r[t]=n,!0},deleteProperty(e,t){if(!t)return!1;const n=q(!0);return delete n[t],!0},ownKeys(){const e=q(!0);return Object.keys(e)}});function m(e,t){return typeof process<"u"&&ue?ue[e]??t:typeof Deno<"u"?Deno.env.get(e)??t:typeof Bun<"u"?Bun.env[e]??t:t}const F=1,y=4,I=8,S=24,ce={eterm:y,cons25:y,console:y,cygwin:y,dtterm:y,gnome:y,hurd:y,jfbterm:y,konsole:y,kterm:y,mlterm:y,mosh:S,putty:y,st:y,"rxvt-unicode-24bit":S,terminator:S,"xterm-kitty":S},Me=new Map(Object.entries({APPVEYOR:I,BUILDKITE:I,CIRCLECI:S,DRONE:I,GITEA_ACTIONS:S,GITHUB_ACTIONS:S,GITLAB_CI:I,TRAVIS:I})),ke=[/ansi/,/color/,/linux/,/direct/,/^con[0-9]*x[0-9]/,/^rxvt/,/^screen/,/^xterm/,/^vt100/,/^vt220/];function Be(){if(m("FORCE_COLOR")!==void 0)switch(m("FORCE_COLOR")){case"":case"1":case"true":return y;case"2":return I;case"3":return S;default:return F}if(m("NODE_DISABLE_COLORS")!==void 0&&m("NODE_DISABLE_COLORS")!==""||m("NO_COLOR")!==void 0&&m("NO_COLOR")!==""||m("TERM")==="dumb")return F;if(m("TMUX"))return S;if("TF_BUILD"in E&&"AGENT_NAME"in E)return y;if("CI"in E){for(const{0:e,1:t}of Me)if(e in E)return t;return m("CI_NAME")==="codeship"?I:F}if("TEAMCITY_VERSION"in E)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.exec(m("TEAMCITY_VERSION"))!==null?y:F;switch(m("TERM_PROGRAM")){case"iTerm.app":return!m("TERM_PROGRAM_VERSION")||/^[0-2]\./.exec(m("TERM_PROGRAM_VERSION"))!==null?I:S;case"HyperTerm":case"MacTerm":return S;case"Apple_Terminal":return I}if(m("COLORTERM")==="truecolor"||m("COLORTERM")==="24bit")return S;if(m("TERM")){if(/truecolor/.exec(m("TERM"))!==null)return S;if(/^xterm-256/.exec(m("TERM"))!==null)return I;const e=m("TERM").toLowerCase();if(ce[e])return ce[e];if(ke.some(t=>t.exec(e)!==null))return y}return m("COLORTERM")?y:F}const N={reset:"\x1B[0m",bright:"\x1B[1m",dim:"\x1B[2m",fg:{red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m"}},re=["debug","info","success","warn","error"];function qe(e,t){return re.indexOf(t)>=re.indexOf(e)}const Fe={info:N.fg.blue,success:N.fg.green,warn:N.fg.yellow,error:N.fg.red,debug:N.fg.magenta},De=(e,t,n)=>{const r=new Date().toISOString();return n?`${N.dim}${r}${N.reset} ${Fe[e]}${e.toUpperCase()}${N.reset} ${N.bright}[Better Auth]:${N.reset} ${t}`:`${r} ${e.toUpperCase()} [Better Auth]: ${t}`},$e=e=>{const t="error",n=Be()!==1,r=(s,l,o=[])=>{if(!qe(t,s))return;const d=De(s,l,n);{s==="error"?console.error(d,...o):s==="warn"?console.warn(d,...o):console.log(d,...o);return}};return{...Object.fromEntries(re.map(s=>[s,(...[l,...o])=>r(s,l,o)])),get level(){return t}}};$e();function Ve(e){return e.charAt(0).toUpperCase()+e.slice(1)}var Y=class extends Error{constructor(e,t){super(e),this.name="BetterAuthError",this.message=e,this.cause=t,this.stack=""}};function Ge(e){try{return(new URL(e).pathname.replace(/\/+$/,"")||"/")!=="/"}catch{throw new Y(`Invalid base URL: ${e}. Please provide a valid base URL.`)}}function We(e){try{const t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")throw new Y(`Invalid base URL: ${e}. URL must include 'http://' or 'https://'`)}catch(t){throw t instanceof Y?t:new Y(`Invalid base URL: ${e}. Please provide a valid base URL.`,String(t))}}function X(e,t="/api/auth"){if(We(e),Ge(e))return e;const n=e.replace(/\/+$/,"");return!t||t==="/"?n:(t=t.startsWith("/")?t:`/${t}`,`${n}${t}`)}function He(e,t,n,r,s){if(e)return X(e,t);{const l=E.BETTER_AUTH_URL||E.NEXT_PUBLIC_BETTER_AUTH_URL||E.PUBLIC_BETTER_AUTH_URL||E.NUXT_PUBLIC_BETTER_AUTH_URL||E.NUXT_PUBLIC_AUTH_URL||(E.BASE_URL!=="/"?E.BASE_URL:void 0);if(l)return X(l,t)}if(typeof window<"u"&&window.location)return X(window.location.origin,t)}const Je={id:"redirect",name:"Redirect",hooks:{onSuccess(e){if(e.data?.url&&e.data?.redirect&&typeof window<"u"&&window.location&&window.location)try{window.location.href=e.data.url}catch{}}}},Ye={proto:/"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/,constructor:/"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/,protoShort:/"__proto__"\s*:/,constructorShort:/"constructor"\s*:/},ze=/^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/,fe={true:!0,false:!1,null:null,undefined:void 0,nan:NaN,infinity:Number.POSITIVE_INFINITY,"-infinity":Number.NEGATIVE_INFINITY},Qe=/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,7}))?(?:Z|([+-])(\d{2}):(\d{2}))$/;function Xe(e){return e instanceof Date&&!isNaN(e.getTime())}function Ze(e){const t=Qe.exec(e);if(!t)return null;const[,n,r,s,l,o,d,i,u,a,f]=t;let h=new Date(Date.UTC(parseInt(n,10),parseInt(r,10)-1,parseInt(s,10),parseInt(l,10),parseInt(o,10),parseInt(d,10),i?parseInt(i.padEnd(3,"0"),10):0));if(u){const v=(parseInt(a,10)*60+parseInt(f,10))*(u==="+"?-1:1);h.setUTCMinutes(h.getUTCMinutes()+v)}return Xe(h)?h:null}function Ke(e,t={}){const{strict:n=!1,warnings:r=!1,reviver:s,parseDates:l=!0}=t;if(typeof e!="string")return e;const o=e.trim();if(o.length>0&&o[0]==='"'&&o.endsWith('"')&&!o.slice(1,-1).includes('"'))return o.slice(1,-1);const d=o.toLowerCase();if(d.length<=9&&d in fe)return fe[d];if(!ze.test(o)){if(n)throw new SyntaxError("[better-json] Invalid JSON");return e}if(Object.entries(Ye).some(([i,u])=>{const a=u.test(o);return a&&r&&console.warn(`[better-json] Detected potential prototype pollution attempt using ${i} pattern`),a})&&n)throw new Error("[better-json] Potential prototype pollution attempt detected");try{return JSON.parse(o,(u,a)=>{if(u==="__proto__"||u==="constructor"&&a&&typeof a=="object"&&"prototype"in a){r&&console.warn(`[better-json] Dropping "${u}" key to prevent prototype pollution`);return}if(l&&typeof a=="string"){const f=Ze(a);if(f)return f}return s?s(u,a):a})}catch(i){if(n)throw i;return e}}function et(e,t={strict:!0}){return Ke(e,t)}let T=[],k=0;const V=4,be=e=>{let t=[],n={get(){return n.lc||n.listen(()=>{})(),n.value},lc:0,listen(r){return n.lc=t.push(r),()=>{for(let l=k+V;l<T.length;)T[l]===r?T.splice(l,V):l+=V;let s=t.indexOf(r);~s&&(t.splice(s,1),--n.lc||n.off())}},notify(r,s){let l=!T.length;for(let o of t)T.push(o,n.value,r,s);if(l){for(k=0;k<T.length;k+=V)T[k](T[k+1],T[k+2],T[k+3]);T.length=0}},off(){},set(r){let s=n.value;s!==r&&(n.value=r,n.notify(s))},subscribe(r){let s=n.listen(r);return r(n.value),s},value:e};return n},tt=5,G=6,W=10;let nt=(e,t,n,r)=>(e.events=e.events||{},e.events[n+W]||(e.events[n+W]=r(s=>{e.events[n].reduceRight((l,o)=>(o(l),l),{shared:{},...s})})),e.events[n]=e.events[n]||[],e.events[n].push(t),()=>{let s=e.events[n],l=s.indexOf(t);s.splice(l,1),s.length||(delete e.events[n],e.events[n+W](),delete e.events[n+W])}),rt=1e3,we=(e,t)=>nt(e,r=>{let s=t(r);s&&e.events[G].push(s)},tt,r=>{let s=e.listen;e.listen=(...o)=>(!e.lc&&!e.active&&(e.active=!0,r()),s(...o));let l=e.off;return e.events[G]=[],e.off=()=>{l(),setTimeout(()=>{if(e.active&&!e.lc){e.active=!1;for(let o of e.events[G])o();e.events[G]=[]}},rt)},()=>{e.listen=s,e.off=l}});function st(e,t,n){let r=new Set(t).add(void 0);return e.listen((s,l,o)=>{r.has(o)&&n(s,l,o)})}const it=()=>typeof window>"u",ot=(e,t,n,r)=>{const s=be({data:null,error:null,isPending:!0,isRefetching:!1,refetch:d=>l(d)}),l=async d=>new Promise(i=>{const u=typeof r=="function"?r({data:s.get().data,error:s.get().error,isPending:s.get().isPending}):r;n(t,{...u,query:{...u?.query,...d?.query},async onSuccess(a){s.set({data:a.data,error:null,isPending:!1,isRefetching:!1,refetch:s.value.refetch}),await u?.onSuccess?.(a)},async onError(a){const{request:f}=a,h=typeof f.retry=="number"?f.retry:f.retry?.attempts,v=f.retryAttempt||0;h&&v<h||(s.set({error:a.error,data:null,isPending:!1,isRefetching:!1,refetch:s.value.refetch}),await u?.onError?.(a))},async onRequest(a){const f=s.get();s.set({isPending:f.data===null,data:f.data,error:null,isRefetching:!0,refetch:s.value.refetch}),await u?.onRequest?.(a)}}).catch(a=>{s.set({error:a,data:null,isPending:!1,isRefetching:!1,refetch:s.value.refetch})}).finally(()=>{i(void 0)})});e=Array.isArray(e)?e:[e];let o=!1;for(const d of e)d.subscribe(async()=>{it()||(o?await l():we(s,()=>{const i=setTimeout(async()=>{o||(await l(),o=!0)},0);return()=>{s.off(),d.off(),clearTimeout(i)}}))});return s},Z=Symbol.for("better-auth:broadcast-channel"),at=()=>Math.floor(Date.now()/1e3);var lt=class{listeners=new Set;name;constructor(e="better-auth.message"){this.name=e}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}post(e){if(!(typeof window>"u"))try{localStorage.setItem(this.name,JSON.stringify({...e,timestamp:at()}))}catch{}}setup(){if(typeof window>"u"||typeof window.addEventListener>"u")return()=>{};const e=t=>{if(t.key!==this.name)return;const n=JSON.parse(t.newValue??"{}");n?.event!=="session"||!n?.data||this.listeners.forEach(r=>r(n))};return window.addEventListener("storage",e),()=>{window.removeEventListener("storage",e)}}};function K(e="better-auth.message"){return globalThis[Z]||(globalThis[Z]=new lt(e)),globalThis[Z]}const ee=Symbol.for("better-auth:focus-manager");var ut=class{listeners=new Set;subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}setFocused(e){this.listeners.forEach(t=>t(e))}setup(){if(typeof window>"u"||typeof document>"u"||typeof window.addEventListener>"u")return()=>{};const e=()=>{document.visibilityState==="visible"&&this.setFocused(!0)};return document.addEventListener("visibilitychange",e,!1),()=>{document.removeEventListener("visibilitychange",e,!1)}}};function de(){return globalThis[ee]||(globalThis[ee]=new ut),globalThis[ee]}const te=Symbol.for("better-auth:online-manager");var ct=class{listeners=new Set;isOnline=typeof navigator<"u"?navigator.onLine:!0;subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}setOnline(e){this.isOnline=e,this.listeners.forEach(t=>t(e))}setup(){if(typeof window>"u"||typeof window.addEventListener>"u")return()=>{};const e=()=>this.setOnline(!0),t=()=>this.setOnline(!1);return window.addEventListener("online",e,!1),window.addEventListener("offline",t,!1),()=>{window.removeEventListener("online",e,!1),window.removeEventListener("offline",t,!1)}}};function ne(){return globalThis[te]||(globalThis[te]=new ct),globalThis[te]}const B=()=>Math.floor(Date.now()/1e3),ft=5;function dt(e){const{sessionAtom:t,sessionSignal:n,$fetch:r,options:s={}}=e,l=s.sessionOptions?.refetchInterval??0,o=s.sessionOptions?.refetchOnWindowFocus??!0,d=s.sessionOptions?.refetchWhenOffline??!1,i={lastSync:0,lastSessionRequest:0,cachedSession:void 0},u=()=>d||ne().isOnline,a=b=>{if(!u())return;if(b?.event==="storage"){i.lastSync=B(),n.set(!n.get());return}const R=t.get();if(b?.event==="poll"){i.lastSessionRequest=B(),r("/get-session").then(c=>{c.error?t.set({...R,data:null,error:c.error}):t.set({...R,data:c.data,error:null}),i.lastSync=B(),n.set(!n.get())}).catch(()=>{});return}if(b?.event==="visibilitychange"){if(B()-i.lastSessionRequest<ft)return;i.lastSessionRequest=B()}(R?.data===null||R?.data===void 0||b?.event==="visibilitychange")&&(i.lastSync=B(),n.set(!n.get()))},f=b=>{K().post({event:"session",data:{trigger:b},clientId:Math.random().toString(36).substring(7)})},h=()=>{l&&l>0&&(i.pollInterval=setInterval(()=>{t.get()?.data&&a({event:"poll"})},l*1e3))},v=()=>{i.unsubscribeBroadcast=K().subscribe(()=>{a({event:"storage"})})},_=()=>{o&&(i.unsubscribeFocus=de().subscribe(()=>{a({event:"visibilitychange"})}))},j=()=>{i.unsubscribeOnline=ne().subscribe(b=>{b&&a({event:"visibilitychange"})})};return{init:()=>{h(),v(),_(),j(),K().setup(),de().setup(),ne().setup()},cleanup:()=>{i.pollInterval&&(clearInterval(i.pollInterval),i.pollInterval=void 0),i.unsubscribeBroadcast&&(i.unsubscribeBroadcast(),i.unsubscribeBroadcast=void 0),i.unsubscribeFocus&&(i.unsubscribeFocus(),i.unsubscribeFocus=void 0),i.unsubscribeOnline&&(i.unsubscribeOnline(),i.unsubscribeOnline=void 0),i.lastSync=0,i.lastSessionRequest=0,i.cachedSession=void 0},triggerRefetch:a,broadcastSessionUpdate:f}}function ht(e,t){const n=be(!1),r=ot(n,"/get-session",e,{method:"GET"});return we(r,()=>{const s=dt({sessionAtom:r,sessionSignal:n,$fetch:e,options:t});return s.init(),()=>{s.cleanup()}}),{session:r,$sessionSignal:n}}var pt=Object.defineProperty,gt=Object.defineProperties,mt=Object.getOwnPropertyDescriptors,he=Object.getOwnPropertySymbols,yt=Object.prototype.hasOwnProperty,vt=Object.prototype.propertyIsEnumerable,pe=(e,t,n)=>t in e?pt(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,P=(e,t)=>{for(var n in t||(t={}))yt.call(t,n)&&pe(e,n,t[n]);if(he)for(var n of he(t))vt.call(t,n)&&pe(e,n,t[n]);return e},L=(e,t)=>gt(e,mt(t)),bt=class extends Error{constructor(e,t,n){super(t||e.toString(),{cause:n}),this.status=e,this.statusText=t,this.error=n,Error.captureStackTrace(this,this.constructor)}},wt=async(e,t)=>{var n,r,s,l,o,d;let i=t||{};const u={onRequest:[t?.onRequest],onResponse:[t?.onResponse],onSuccess:[t?.onSuccess],onError:[t?.onError],onRetry:[t?.onRetry]};if(!t||!t?.plugins)return{url:e,options:i,hooks:u};for(const a of t?.plugins||[]){if(a.init){const f=await((n=a.init)==null?void 0:n.call(a,e.toString(),t));i=f.options||i,e=f.url}u.onRequest.push((r=a.hooks)==null?void 0:r.onRequest),u.onResponse.push((s=a.hooks)==null?void 0:s.onResponse),u.onSuccess.push((l=a.hooks)==null?void 0:l.onSuccess),u.onError.push((o=a.hooks)==null?void 0:o.onError),u.onRetry.push((d=a.hooks)==null?void 0:d.onRetry)}return{url:e,options:i,hooks:u}},ge=class{constructor(e){this.options=e}shouldAttemptRetry(e,t){return this.options.shouldRetry?Promise.resolve(e<this.options.attempts&&this.options.shouldRetry(t)):Promise.resolve(e<this.options.attempts)}getDelay(){return this.options.delay}},Ot=class{constructor(e){this.options=e}shouldAttemptRetry(e,t){return this.options.shouldRetry?Promise.resolve(e<this.options.attempts&&this.options.shouldRetry(t)):Promise.resolve(e<this.options.attempts)}getDelay(e){return Math.min(this.options.maxDelay,this.options.baseDelay*2**e)}};function Rt(e){if(typeof e=="number")return new ge({type:"linear",attempts:e,delay:1e3});switch(e.type){case"linear":return new ge(e);case"exponential":return new Ot(e);default:throw new Error("Invalid retry strategy")}}var _t=async e=>{const t={},n=async r=>typeof r=="function"?await r():r;if(e?.auth){if(e.auth.type==="Bearer"){const r=await n(e.auth.token);if(!r)return t;t.authorization=`Bearer ${r}`}else if(e.auth.type==="Basic"){const[r,s]=await Promise.all([n(e.auth.username),n(e.auth.password)]);if(!r||!s)return t;t.authorization=`Basic ${btoa(`${r}:${s}`)}`}else if(e.auth.type==="Custom"){const[r,s]=await Promise.all([n(e.auth.prefix),n(e.auth.value)]);if(!s)return t;t.authorization=`${r??""} ${s}`}}return t},St=/^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i;function xt(e){const t=e.headers.get("content-type"),n=new Set(["image/svg","application/xml","application/xhtml","application/html"]);if(!t)return"json";const r=t.split(";").shift()||"";return St.test(r)?"json":n.has(r)||r.startsWith("text/")?"text":"blob"}function Et(e){try{return JSON.parse(e),!0}catch{return!1}}function se(e){if(e===void 0)return!1;const t=typeof e;return t==="string"||t==="number"||t==="boolean"||t===null?!0:t!=="object"?!1:Array.isArray(e)?!0:e.buffer?!1:e.constructor&&e.constructor.name==="Object"||typeof e.toJSON=="function"}function me(e){try{return JSON.parse(e)}catch{return e}}function ye(e){return typeof e=="function"}function Tt(e){if(e?.customFetchImpl)return e.customFetchImpl;if(typeof globalThis<"u"&&ye(globalThis.fetch))return globalThis.fetch;if(typeof window<"u"&&ye(window.fetch))return window.fetch;throw new Error("No fetch implementation found")}async function Pt(e){const t=new Headers(e?.headers),n=await _t(e);for(const[r,s]of Object.entries(n||{}))t.set(r,s);if(!t.has("content-type")){const r=Lt(e?.body);r&&t.set("content-type",r)}return t}function Lt(e){return se(e)?"application/json":null}function It(e){if(!e?.body)return null;const t=new Headers(e?.headers);if(se(e.body)&&!t.has("content-type")){for(const[n,r]of Object.entries(e?.body))r instanceof Date&&(e.body[n]=r.toISOString());return JSON.stringify(e.body)}return t.has("content-type")&&t.get("content-type")==="application/x-www-form-urlencoded"&&se(e.body)?new URLSearchParams(e.body).toString():e.body}function Nt(e,t){var n;if(t?.method)return t.method.toUpperCase();if(e.startsWith("@")){const r=(n=e.split("@")[1])==null?void 0:n.split("/")[0];return Re.includes(r)?r.toUpperCase():t?.body?"POST":"GET"}return t?.body?"POST":"GET"}function At(e,t){let n;return!e?.signal&&e?.timeout&&(n=setTimeout(()=>t?.abort(),e?.timeout)),{abortTimeout:n,clearTimeout:()=>{n&&clearTimeout(n)}}}var Ut=class Oe extends Error{constructor(t,n){super(n||JSON.stringify(t,null,2)),this.issues=t,Object.setPrototypeOf(this,Oe.prototype)}};async function z(e,t){const n=await e["~standard"].validate(t);if(n.issues)throw new Ut(n.issues);return n.value}var Re=["get","post","put","patch","delete"],Ct=e=>({id:"apply-schema",name:"Apply Schema",version:"1.0.0",async init(t,n){var r,s,l,o;const d=((s=(r=e.plugins)==null?void 0:r.find(i=>{var u;return(u=i.schema)!=null&&u.config?t.startsWith(i.schema.config.baseURL||"")||t.startsWith(i.schema.config.prefix||""):!1}))==null?void 0:s.schema)||e.schema;if(d){let i=t;(l=d.config)!=null&&l.prefix&&i.startsWith(d.config.prefix)&&(i=i.replace(d.config.prefix,""),d.config.baseURL&&(t=t.replace(d.config.prefix,d.config.baseURL))),(o=d.config)!=null&&o.baseURL&&i.startsWith(d.config.baseURL)&&(i=i.replace(d.config.baseURL,""));const u=d.schema[i];if(u){let a=L(P({},n),{method:u.method,output:u.output});return n?.disableValidation||(a=L(P({},a),{body:u.input?await z(u.input,n?.body):n?.body,params:u.params?await z(u.params,n?.params):n?.params,query:u.query?await z(u.query,n?.query):n?.query})),{url:t,options:a}}}return{url:t,options:n}}}),jt=e=>{async function t(n,r){const s=L(P(P({},e),r),{plugins:[...e?.plugins||[],Ct(e||{}),...r?.plugins||[]]});if(e?.catchAllError)try{return await ie(n,s)}catch(l){return{data:null,error:{status:500,statusText:"Fetch Error",message:"Fetch related error. Captured by catchAllError option. See error property for more details.",error:l}}}return await ie(n,s)}return t};function Mt(e,t){const{baseURL:n,params:r,query:s}=t||{query:{},params:{},baseURL:""};let l=e.startsWith("http")?e.split("/").slice(0,3).join("/"):n||"";if(e.startsWith("@")){const f=e.toString().split("@")[1].split("/")[0];Re.includes(f)&&(e=e.replace(`@${f}/`,"/"))}l.endsWith("/")||(l+="/");let[o,d]=e.replace(l,"").split("?");const i=new URLSearchParams(d);for(const[f,h]of Object.entries(s||{})){if(h==null)continue;let v;if(typeof h=="string")v=h;else if(Array.isArray(h)){for(const _ of h)i.append(f,_);continue}else v=JSON.stringify(h);i.set(f,v)}if(r)if(Array.isArray(r)){const f=o.split("/").filter(h=>h.startsWith(":"));for(const[h,v]of f.entries()){const _=r[h];o=o.replace(v,_)}}else for(const[f,h]of Object.entries(r))o=o.replace(`:${f}`,String(h));o=o.split("/").map(encodeURIComponent).join("/"),o.startsWith("/")&&(o=o.slice(1));let u=i.toString();return u=u.length>0?`?${u}`.replace(/\+/g,"%20"):"",l.startsWith("http")?new URL(`${o}${u}`,l):`${l}${o}${u}`}var ie=async(e,t)=>{var n,r,s,l,o,d,i,u;const{hooks:a,url:f,options:h}=await wt(e,t),v=Tt(h),_=new AbortController,j=(n=h.signal)!=null?n:_.signal,O=Mt(f,h),M=It(h),b=await Pt(h),R=Nt(f,h);let c=L(P({},h),{url:O,headers:b,body:M,method:R,signal:j});for(const x of a.onRequest)if(x){const w=await x(c);typeof w=="object"&&w!==null&&(c=w)}("pipeTo"in c&&typeof c.pipeTo=="function"||typeof((r=t?.body)==null?void 0:r.pipe)=="function")&&("duplex"in c||(c.duplex="half"));const{clearTimeout:A}=At(h,_);let p=await v(c.url,c);A();const D={response:p,request:c};for(const x of a.onResponse)if(x){const w=await x(L(P({},D),{response:(s=t?.hookOptions)!=null&&s.cloneResponse?p.clone():p}));w instanceof Response?p=w:typeof w=="object"&&w!==null&&(p=w.response)}if(p.ok){if(!(c.method!=="HEAD"))return{data:"",error:null};const w=xt(p),U={data:null,response:p,request:c};if(w==="json"||w==="text"){const C=await p.text(),Ee=(l=c.jsonParser)!=null?l:me;U.data=await Ee(C)}else U.data=await p[w]();c?.output&&c.output&&!c.disableValidation&&(U.data=await z(c.output,U.data));for(const C of a.onSuccess)C&&await C(L(P({},U),{response:(o=t?.hookOptions)!=null&&o.cloneResponse?p.clone():p}));return t?.throw?U.data:{data:U.data,error:null}}const Se=(d=t?.jsonParser)!=null?d:me,$=await p.text(),oe=Et($),Q=oe?await Se($):null,xe={response:p,responseText:$,request:c,error:L(P({},Q),{status:p.status,statusText:p.statusText})};for(const x of a.onError)x&&await x(L(P({},xe),{response:(i=t?.hookOptions)!=null&&i.cloneResponse?p.clone():p}));if(t?.retry){const x=Rt(t.retry),w=(u=t.retryAttempt)!=null?u:0;if(await x.shouldAttemptRetry(w,p)){for(const C of a.onRetry)C&&await C(D);const U=x.getDelay(w);return await new Promise(C=>setTimeout(C,U)),await ie(e,L(P({},t),{retryAttempt:w+1}))}}if(t?.throw)throw new bt(p.status,p.statusText,oe?Q:$);return{data:null,error:L(P({},Q),{status:p.status,statusText:p.statusText})}};const kt=(e,t)=>{const n="credentials"in Request.prototype,r=He(e?.baseURL,e?.basePath)??"/api/auth",s=e?.plugins?.flatMap(c=>c.fetchPlugins).filter(c=>c!==void 0)||[],l={id:"lifecycle-hooks",name:"lifecycle-hooks",hooks:{onSuccess:e?.fetchOptions?.onSuccess,onError:e?.fetchOptions?.onError,onRequest:e?.fetchOptions?.onRequest,onResponse:e?.fetchOptions?.onResponse}},{onSuccess:o,onError:d,onRequest:i,onResponse:u,...a}=e?.fetchOptions||{},f=jt({baseURL:r,...n?{credentials:"include"}:{},method:"GET",jsonParser(c){return c?et(c,{strict:!1}):null},customFetchImpl:fetch,...a,plugins:[l,...a.plugins||[],...e?.disableDefaultFetchPlugins?[]:[Je],...s]}),{$sessionSignal:h,session:v}=ht(f,e),_=e?.plugins||[];let j={},O={$sessionSignal:h,session:v},M={"/sign-out":"POST","/revoke-sessions":"POST","/revoke-other-sessions":"POST","/delete-user":"POST"};const b=[{signal:"$sessionSignal",matcher(c){return c==="/sign-out"||c==="/update-user"||c==="/sign-up/email"||c==="/sign-in/email"||c==="/delete-user"||c==="/verify-email"||c==="/revoke-sessions"||c==="/revoke-session"||c==="/change-email"}}];for(const c of _)c.getAtoms&&Object.assign(O,c.getAtoms?.(f)),c.pathMethods&&Object.assign(M,c.pathMethods),c.atomListeners&&b.push(...c.atomListeners);const R={notify:c=>{O[c].set(!O[c].get())},listen:(c,A)=>{O[c].subscribe(A)},atoms:O};for(const c of _)c.getActions&&Object.assign(j,c.getActions?.(f,R,e));return{get baseURL(){return r},pluginsActions:j,pluginsAtoms:O,pluginPathMethods:M,atomListeners:b,$fetch:f,$store:R}};function Bt(e){return typeof e=="object"&&e!==null&&"get"in e&&typeof e.get=="function"&&"lc"in e&&typeof e.lc=="number"}function qt(e,t,n){const r=t[e],{fetchOptions:s,query:l,...o}=n||{};return r||(s?.method?s.method:o&&Object.keys(o).length>0?"POST":"GET")}function Ft(e,t,n,r,s){function l(o=[]){return new Proxy(function(){},{get(d,i){if(typeof i!="string"||i==="then"||i==="catch"||i==="finally")return;const u=[...o,i];let a=e;for(const f of u)if(a&&typeof a=="object"&&f in a)a=a[f];else{a=void 0;break}return typeof a=="function"||Bt(a)?a:l(u)},apply:async(d,i,u)=>{const a="/"+o.map(b=>b.replace(/[A-Z]/g,R=>`-${R.toLowerCase()}`)).join("/"),f=u[0]||{},h=u[1]||{},{query:v,fetchOptions:_,...j}=f,O={...h,..._},M=qt(a,n,f);return await t(a,{...O,body:M==="GET"?void 0:{...j,...O?.body||{}},query:v||O?.query,method:M,async onSuccess(b){if(await O?.onSuccess?.(b),!s||O.disableSignal)return;const R=s.filter(A=>A.matcher(a));if(!R.length)return;const c=new Set;for(const A of R){const p=r[A.signal];if(!p)return;if(c.has(A.signal))continue;c.add(A.signal);const D=p.get();setTimeout(()=>{p.set(!D)},10)}}})}})}return l()}function Dt(e,t={}){let n=H.useRef(e.get());const{keys:r,deps:s=[e,r]}=t;let l=H.useCallback(d=>{const i=u=>{n.current!==u&&(n.current=u,d())};return i(e.value),r?.length?st(e,r,i):e.listen(i)},s),o=()=>n.current;return H.useSyncExternalStore(l,o,o)}function $t(e){return`use${Ve(e)}`}function Vt(e){const{pluginPathMethods:t,pluginsActions:n,pluginsAtoms:r,$fetch:s,$store:l,atomListeners:o}=kt(e);let d={};for(const[i,u]of Object.entries(r))d[$t(i)]=()=>Dt(u);return Ft({...n,...d,$fetch:s,$store:l},s,t,r,o)}const _e=Vt({}),{useSession:Ht,signIn:Jt,signUp:Yt,signOut:zt}=_e,Gt=async()=>{await _e.signIn.social({provider:"google"})};function Qt({title:e,fields:t,formData:n,onSubmit:r,onChange:s,submitButtonText:l,footerText:o,footerLinkText:d,footerLinkTo:i,error:u}){const a=Te(Pe.hasGoogleSetup.queryOptions());return g.jsxs("div",{className:"container mx-auto w-full max-w-2xl p-12",children:[g.jsx("h1",{className:"text-4xl font-bold mb-8 text-center",children:e}),u&&g.jsx("p",{className:"text-red-500 text-center mb-4 text-2xl",children:u}),g.jsxs("form",{onSubmit:r,className:"space-y-6",children:[t.map(f=>g.jsxs("div",{className:"space-y-3",children:[g.jsx("label",{htmlFor:f.id,className:"text-base font-medium",children:f.label}),g.jsx(Ce,{id:f.id,name:f.name,type:f.type,placeholder:f.placeholder,value:n[f.name],onChange:s,required:!0,className:"h-12 text-base"})]},f.id)),g.jsx(le,{type:"submit",className:"w-full h-12 text-base",children:l})]}),a.data&&g.jsxs("div",{className:"mt-8",children:[g.jsxs("div",{className:"relative",children:[g.jsx("div",{className:"absolute inset-0 flex items-center",children:g.jsx("div",{className:"w-full border-t border-gray-300"})}),g.jsx("div",{className:"relative flex justify-center text-sm",children:g.jsx("span",{className:"px-2 bg-background text-muted-foreground",children:"Or continue with"})})]}),g.jsx("div",{className:"flex justify-center items-center gap-4 p-4",children:g.jsx(le,{type:"button",variant:"outline",onClick:Gt,children:g.jsx("img",{src:"/google-icon.svg",alt:"Google",className:"w-5 h-5"})})})]}),g.jsxs("p",{className:"text-center text-sm text-muted-foreground mt-8",children:[o," ",g.jsx(Le,{to:i,className:"text-primary hover:underline font-medium",children:d})]})]})}export{Qt as S,Jt as a,Yt as s};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as c,r as n,j as g}from"./index-CGg3ZQH6.js";import{S as d,s as u}from"./signinForm-9PY1Lvqj.js";function x(){const o=c(),[e,s]=n.useState({name:"",email:"",password:""}),[r,t]=n.useState(""),i=async a=>{a.preventDefault(),t(""),await u.email({name:e.name,email:e.email,password:e.password},{onSuccess:()=>{o({to:"/"})},onError:p=>{t(p.error.message)}})},m=a=>{s({...e,[a.target.name]:a.target.value})},l=[{id:"name",name:"name",type:"text",label:"Name"},{id:"email",name:"email",type:"email",label:"Email",placeholder:"test@gmail.com"},{id:"password",name:"password",type:"password",label:"Password"}];return g.jsx(d,{title:"Sign Up",fields:l,formData:e,onSubmit:i,onChange:m,submitButtonText:"Sign Up",footerText:"Already have an account?",footerLinkText:"Sign in",footerLinkTo:"/login",error:r})}export{x as component};
|
nao_core/commands/sync.py
DELETED
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
from abc import ABC, abstractmethod
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
|
|
5
|
-
from ibis import BaseBackend
|
|
6
|
-
from rich.console import Console
|
|
7
|
-
from rich.progress import BarColumn, Progress, SpinnerColumn, TaskProgressColumn, TextColumn
|
|
8
|
-
|
|
9
|
-
from nao_core.config import AccessorType, NaoConfig
|
|
10
|
-
|
|
11
|
-
console = Console()
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
# =============================================================================
|
|
15
|
-
# Data Accessors
|
|
16
|
-
# =============================================================================
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class DataAccessor(ABC):
|
|
20
|
-
"""Base class for data accessors that generate markdown files for tables."""
|
|
21
|
-
|
|
22
|
-
@property
|
|
23
|
-
@abstractmethod
|
|
24
|
-
def filename(self) -> str:
|
|
25
|
-
"""The filename this accessor writes to (e.g., 'columns.md')."""
|
|
26
|
-
...
|
|
27
|
-
|
|
28
|
-
@abstractmethod
|
|
29
|
-
def generate(self, conn: BaseBackend, dataset: str, table: str) -> str:
|
|
30
|
-
"""Generate the markdown content for a table.
|
|
31
|
-
|
|
32
|
-
Args:
|
|
33
|
-
conn: The Ibis database connection
|
|
34
|
-
dataset: The dataset/schema name
|
|
35
|
-
table: The table name
|
|
36
|
-
|
|
37
|
-
Returns:
|
|
38
|
-
Markdown string content
|
|
39
|
-
"""
|
|
40
|
-
...
|
|
41
|
-
|
|
42
|
-
def get_table(self, conn: BaseBackend, dataset: str, table: str):
|
|
43
|
-
"""Helper to get an Ibis table reference."""
|
|
44
|
-
full_table_name = f"{dataset}.{table}"
|
|
45
|
-
return conn.table(full_table_name)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
class ColumnsAccessor(DataAccessor):
|
|
49
|
-
"""Generates columns.md with column names, types, and nullable info."""
|
|
50
|
-
|
|
51
|
-
@property
|
|
52
|
-
def filename(self) -> str:
|
|
53
|
-
return "columns.md"
|
|
54
|
-
|
|
55
|
-
def generate(self, conn: BaseBackend, dataset: str, table: str) -> str:
|
|
56
|
-
try:
|
|
57
|
-
t = self.get_table(conn, dataset, table)
|
|
58
|
-
schema = t.schema()
|
|
59
|
-
|
|
60
|
-
lines = [
|
|
61
|
-
f"# {table}",
|
|
62
|
-
"",
|
|
63
|
-
f"**Dataset:** `{dataset}`",
|
|
64
|
-
"",
|
|
65
|
-
"## Columns",
|
|
66
|
-
"",
|
|
67
|
-
"| Column | Type | Nullable | Description |",
|
|
68
|
-
"|--------|------|----------|-------------|",
|
|
69
|
-
]
|
|
70
|
-
|
|
71
|
-
for name, dtype in schema.items():
|
|
72
|
-
nullable = "Yes" if dtype.nullable else "No"
|
|
73
|
-
description = ""
|
|
74
|
-
lines.append(f"| `{name}` | `{dtype}` | {nullable} | {description} |")
|
|
75
|
-
|
|
76
|
-
return "\n".join(lines)
|
|
77
|
-
except Exception as e:
|
|
78
|
-
return f"# {table}\n\nError fetching schema: {e}"
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
class PreviewAccessor(DataAccessor):
|
|
82
|
-
"""Generates preview.md with the first N rows of data."""
|
|
83
|
-
|
|
84
|
-
def __init__(self, num_rows: int = 10):
|
|
85
|
-
self.num_rows = num_rows
|
|
86
|
-
|
|
87
|
-
@property
|
|
88
|
-
def filename(self) -> str:
|
|
89
|
-
return "preview.md"
|
|
90
|
-
|
|
91
|
-
def generate(self, conn: BaseBackend, dataset: str, table: str) -> str:
|
|
92
|
-
try:
|
|
93
|
-
t = self.get_table(conn, dataset, table)
|
|
94
|
-
schema = t.schema()
|
|
95
|
-
|
|
96
|
-
preview_df = t.limit(self.num_rows).execute()
|
|
97
|
-
|
|
98
|
-
lines = [
|
|
99
|
-
f"# {table} - Preview",
|
|
100
|
-
"",
|
|
101
|
-
f"**Dataset:** `{dataset}`",
|
|
102
|
-
f"**Showing:** First {len(preview_df)} rows",
|
|
103
|
-
"",
|
|
104
|
-
"## Data Preview",
|
|
105
|
-
"",
|
|
106
|
-
]
|
|
107
|
-
|
|
108
|
-
columns = list(schema.keys())
|
|
109
|
-
header = "| " + " | ".join(f"`{col}`" for col in columns) + " |"
|
|
110
|
-
separator = "| " + " | ".join("---" for _ in columns) + " |"
|
|
111
|
-
lines.append(header)
|
|
112
|
-
lines.append(separator)
|
|
113
|
-
|
|
114
|
-
for _, row in preview_df.iterrows():
|
|
115
|
-
row_values = []
|
|
116
|
-
for col in columns:
|
|
117
|
-
val = row[col]
|
|
118
|
-
val_str = str(val) if val is not None else ""
|
|
119
|
-
if len(val_str) > 50:
|
|
120
|
-
val_str = val_str[:47] + "..."
|
|
121
|
-
val_str = val_str.replace("|", "\\|").replace("\n", " ")
|
|
122
|
-
row_values.append(val_str)
|
|
123
|
-
lines.append("| " + " | ".join(row_values) + " |")
|
|
124
|
-
|
|
125
|
-
return "\n".join(lines)
|
|
126
|
-
except Exception as e:
|
|
127
|
-
return f"# {table} - Preview\n\nError fetching preview: {e}"
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
class DescriptionAccessor(DataAccessor):
|
|
131
|
-
"""Generates description.md with table metadata (row count, column count, etc.)."""
|
|
132
|
-
|
|
133
|
-
@property
|
|
134
|
-
def filename(self) -> str:
|
|
135
|
-
return "description.md"
|
|
136
|
-
|
|
137
|
-
def generate(self, conn: BaseBackend, dataset: str, table: str) -> str:
|
|
138
|
-
try:
|
|
139
|
-
t = self.get_table(conn, dataset, table)
|
|
140
|
-
schema = t.schema()
|
|
141
|
-
|
|
142
|
-
row_count = t.count().execute()
|
|
143
|
-
col_count = len(schema)
|
|
144
|
-
|
|
145
|
-
lines = [
|
|
146
|
-
f"# {table}",
|
|
147
|
-
"",
|
|
148
|
-
f"**Dataset:** `{dataset}`",
|
|
149
|
-
"",
|
|
150
|
-
"## Table Metadata",
|
|
151
|
-
"",
|
|
152
|
-
"| Property | Value |",
|
|
153
|
-
"|----------|-------|",
|
|
154
|
-
f"| **Row Count** | {row_count:,} |",
|
|
155
|
-
f"| **Column Count** | {col_count} |",
|
|
156
|
-
"",
|
|
157
|
-
"## Description",
|
|
158
|
-
"",
|
|
159
|
-
"_No description available._",
|
|
160
|
-
"",
|
|
161
|
-
]
|
|
162
|
-
|
|
163
|
-
return "\n".join(lines)
|
|
164
|
-
except Exception as e:
|
|
165
|
-
return f"# {table}\n\nError fetching description: {e}"
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
class ProfilingAccessor(DataAccessor):
|
|
169
|
-
"""Generates profiling.md with column statistics and data profiling."""
|
|
170
|
-
|
|
171
|
-
@property
|
|
172
|
-
def filename(self) -> str:
|
|
173
|
-
return "profiling.md"
|
|
174
|
-
|
|
175
|
-
def generate(self, conn: BaseBackend, dataset: str, table: str) -> str:
|
|
176
|
-
try:
|
|
177
|
-
t = self.get_table(conn, dataset, table)
|
|
178
|
-
schema = t.schema()
|
|
179
|
-
|
|
180
|
-
lines = [
|
|
181
|
-
f"# {table} - Profiling",
|
|
182
|
-
"",
|
|
183
|
-
f"**Dataset:** `{dataset}`",
|
|
184
|
-
"",
|
|
185
|
-
"## Column Statistics",
|
|
186
|
-
"",
|
|
187
|
-
"| Column | Type | Nulls | Unique | Min | Max |",
|
|
188
|
-
"|--------|------|-------|--------|-----|-----|",
|
|
189
|
-
]
|
|
190
|
-
|
|
191
|
-
for name, dtype in schema.items():
|
|
192
|
-
col = t[name]
|
|
193
|
-
dtype_str = str(dtype)
|
|
194
|
-
|
|
195
|
-
try:
|
|
196
|
-
null_count = t.filter(col.isnull()).count().execute()
|
|
197
|
-
unique_count = col.nunique().execute()
|
|
198
|
-
|
|
199
|
-
min_val = ""
|
|
200
|
-
max_val = ""
|
|
201
|
-
if dtype.is_numeric() or dtype.is_temporal():
|
|
202
|
-
try:
|
|
203
|
-
min_val = str(col.min().execute())
|
|
204
|
-
max_val = str(col.max().execute())
|
|
205
|
-
if len(min_val) > 20:
|
|
206
|
-
min_val = min_val[:17] + "..."
|
|
207
|
-
if len(max_val) > 20:
|
|
208
|
-
max_val = max_val[:17] + "..."
|
|
209
|
-
except Exception:
|
|
210
|
-
pass
|
|
211
|
-
|
|
212
|
-
lines.append(
|
|
213
|
-
f"| `{name}` | `{dtype_str}` | {null_count:,} | {unique_count:,} | {min_val} | {max_val} |"
|
|
214
|
-
)
|
|
215
|
-
except Exception as col_error:
|
|
216
|
-
lines.append(f"| `{name}` | `{dtype_str}` | Error: {col_error} | | | |")
|
|
217
|
-
|
|
218
|
-
return "\n".join(lines)
|
|
219
|
-
except Exception as e:
|
|
220
|
-
return f"# {table} - Profiling\n\nError fetching profiling: {e}"
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
# =============================================================================
|
|
224
|
-
# Accessor Registry
|
|
225
|
-
# =============================================================================
|
|
226
|
-
|
|
227
|
-
ACCESSOR_REGISTRY: dict[AccessorType, DataAccessor] = {
|
|
228
|
-
AccessorType.COLUMNS: ColumnsAccessor(),
|
|
229
|
-
AccessorType.PREVIEW: PreviewAccessor(num_rows=10),
|
|
230
|
-
AccessorType.DESCRIPTION: DescriptionAccessor(),
|
|
231
|
-
AccessorType.PROFILING: ProfilingAccessor(),
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
def get_accessors(accessor_types: list[AccessorType]) -> list[DataAccessor]:
|
|
236
|
-
"""Get accessor instances for the given types."""
|
|
237
|
-
return [ACCESSOR_REGISTRY[t] for t in accessor_types if t in ACCESSOR_REGISTRY]
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
# =============================================================================
|
|
241
|
-
# Sync Functions
|
|
242
|
-
# =============================================================================
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
def sync_bigquery(
|
|
246
|
-
db_config,
|
|
247
|
-
base_path: Path,
|
|
248
|
-
progress: Progress,
|
|
249
|
-
accessors: list[DataAccessor],
|
|
250
|
-
) -> tuple[int, int]:
|
|
251
|
-
"""Sync BigQuery database schema to markdown files.
|
|
252
|
-
|
|
253
|
-
Args:
|
|
254
|
-
db_config: The database configuration
|
|
255
|
-
base_path: Base output path
|
|
256
|
-
progress: Rich progress instance
|
|
257
|
-
accessors: List of data accessors to run
|
|
258
|
-
|
|
259
|
-
Returns:
|
|
260
|
-
Tuple of (datasets_synced, tables_synced)
|
|
261
|
-
"""
|
|
262
|
-
conn = db_config.connect()
|
|
263
|
-
db_path = base_path / "bigquery" / db_config.name
|
|
264
|
-
|
|
265
|
-
datasets_synced = 0
|
|
266
|
-
tables_synced = 0
|
|
267
|
-
|
|
268
|
-
if db_config.dataset_id:
|
|
269
|
-
datasets = [db_config.dataset_id]
|
|
270
|
-
else:
|
|
271
|
-
datasets = conn.list_databases()
|
|
272
|
-
|
|
273
|
-
dataset_task = progress.add_task(
|
|
274
|
-
f"[dim]{db_config.name}[/dim]",
|
|
275
|
-
total=len(datasets),
|
|
276
|
-
)
|
|
277
|
-
|
|
278
|
-
for dataset in datasets:
|
|
279
|
-
try:
|
|
280
|
-
all_tables = conn.list_tables(database=dataset)
|
|
281
|
-
except Exception:
|
|
282
|
-
progress.update(dataset_task, advance=1)
|
|
283
|
-
continue
|
|
284
|
-
|
|
285
|
-
# Filter tables based on include/exclude patterns
|
|
286
|
-
tables = [t for t in all_tables if db_config.matches_pattern(dataset, t)]
|
|
287
|
-
|
|
288
|
-
# Skip dataset if no tables match
|
|
289
|
-
if not tables:
|
|
290
|
-
progress.update(dataset_task, advance=1)
|
|
291
|
-
continue
|
|
292
|
-
|
|
293
|
-
dataset_path = db_path / dataset
|
|
294
|
-
dataset_path.mkdir(parents=True, exist_ok=True)
|
|
295
|
-
datasets_synced += 1
|
|
296
|
-
|
|
297
|
-
table_task = progress.add_task(
|
|
298
|
-
f" [cyan]{dataset}[/cyan]",
|
|
299
|
-
total=len(tables),
|
|
300
|
-
)
|
|
301
|
-
|
|
302
|
-
for table in tables:
|
|
303
|
-
table_path = dataset_path / table
|
|
304
|
-
table_path.mkdir(parents=True, exist_ok=True)
|
|
305
|
-
|
|
306
|
-
for accessor in accessors:
|
|
307
|
-
content = accessor.generate(conn, dataset, table)
|
|
308
|
-
output_file = table_path / accessor.filename
|
|
309
|
-
output_file.write_text(content)
|
|
310
|
-
|
|
311
|
-
tables_synced += 1
|
|
312
|
-
progress.update(table_task, advance=1)
|
|
313
|
-
|
|
314
|
-
progress.update(dataset_task, advance=1)
|
|
315
|
-
|
|
316
|
-
return datasets_synced, tables_synced
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
def sync(output_dir: str = "databases"):
|
|
320
|
-
"""Sync database schemas to local markdown files.
|
|
321
|
-
|
|
322
|
-
Creates a folder structure with table metadata:
|
|
323
|
-
databases/bigquery/<connection>/<dataset>/<table>/columns.md
|
|
324
|
-
databases/bigquery/<connection>/<dataset>/<table>/preview.md
|
|
325
|
-
databases/bigquery/<connection>/<dataset>/<table>/description.md
|
|
326
|
-
databases/bigquery/<connection>/<dataset>/<table>/profiling.md
|
|
327
|
-
|
|
328
|
-
Args:
|
|
329
|
-
output_dir: Output directory for the database schemas (default: "databases")
|
|
330
|
-
"""
|
|
331
|
-
console.print("\n[bold cyan]🔄 nao sync[/bold cyan]\n")
|
|
332
|
-
|
|
333
|
-
config = NaoConfig.try_load()
|
|
334
|
-
if not config:
|
|
335
|
-
console.print("[bold red]✗[/bold red] No nao_config.yaml found in current directory")
|
|
336
|
-
console.print("[dim]Run 'nao init' to create a configuration file[/dim]")
|
|
337
|
-
sys.exit(1)
|
|
338
|
-
|
|
339
|
-
console.print(f"[dim]Project:[/dim] {config.project_name}")
|
|
340
|
-
|
|
341
|
-
if not config.databases:
|
|
342
|
-
console.print("[dim]No databases configured[/dim]")
|
|
343
|
-
return
|
|
344
|
-
|
|
345
|
-
base_path = Path(output_dir)
|
|
346
|
-
total_datasets = 0
|
|
347
|
-
total_tables = 0
|
|
348
|
-
|
|
349
|
-
console.print()
|
|
350
|
-
|
|
351
|
-
with Progress(
|
|
352
|
-
SpinnerColumn(style="dim"),
|
|
353
|
-
TextColumn("[progress.description]{task.description}"),
|
|
354
|
-
BarColumn(bar_width=30, style="dim", complete_style="cyan", finished_style="green"),
|
|
355
|
-
TaskProgressColumn(),
|
|
356
|
-
console=console,
|
|
357
|
-
transient=False,
|
|
358
|
-
) as progress:
|
|
359
|
-
for db in config.databases:
|
|
360
|
-
# Get accessors from database config
|
|
361
|
-
db_accessors = get_accessors(db.accessors)
|
|
362
|
-
accessor_names = [a.filename.replace(".md", "") for a in db_accessors]
|
|
363
|
-
|
|
364
|
-
try:
|
|
365
|
-
if db.type == "bigquery":
|
|
366
|
-
console.print(f"[dim]{db.name} accessors:[/dim] {', '.join(accessor_names)}")
|
|
367
|
-
datasets, tables = sync_bigquery(db, base_path, progress, db_accessors)
|
|
368
|
-
total_datasets += datasets
|
|
369
|
-
total_tables += tables
|
|
370
|
-
else:
|
|
371
|
-
console.print(f"[yellow]⚠ Unsupported database type: {db.type}[/yellow]")
|
|
372
|
-
except Exception as e:
|
|
373
|
-
console.print(f"[bold red]✗[/bold red] Failed to sync {db.name}: {e}")
|
|
374
|
-
|
|
375
|
-
console.print()
|
|
376
|
-
console.print(
|
|
377
|
-
f"[green]✓[/green] Synced [bold]{total_tables}[/bold] tables across [bold]{total_datasets}[/bold] datasets"
|
|
378
|
-
)
|
|
379
|
-
console.print(f"[dim] → {base_path.absolute()}[/dim]")
|
|
380
|
-
console.print()
|
nao_core-0.0.15.dist-info/RECORD
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
nao_core/__init__.py,sha256=GOVZRfyqvgZ4Ny7iIYUu_ftdqwzAILXAo67k0hugF9w,46
|
|
2
|
-
nao_core/main.py,sha256=f00vLL4s2B2kCMa8y3lI56LX3TnUppWzYmqM6eOGomA,205
|
|
3
|
-
nao_core/bin/db.sqlite,sha256=FwRfxk8J3T_Qrdcw5TbxSnafGDn0yiHCKhwMdULc7C4,110592
|
|
4
|
-
nao_core/bin/nao-chat-server,sha256=JxuPOtwbfj-2O-L8PTkxZ0qwqN2QFniyA8UahdNkvFA,64657392
|
|
5
|
-
nao_core/bin/fastapi/main.py,sha256=pEH8iMnqQXvQjxseEkXEsParU7REkiTO4UFB1-dDAPc,3068
|
|
6
|
-
nao_core/bin/migrations-postgres/0000_supreme_cable.sql,sha256=BR_BcHRpUr35pbrRDOsFbRm9u4wC-AQ9orGuAc4BJok,3751
|
|
7
|
-
nao_core/bin/migrations-postgres/meta/0000_snapshot.json,sha256=lAf2CNFAqTtLw2mjsF2vdKryTb5UbkwSa1K9XmCcdyY,15080
|
|
8
|
-
nao_core/bin/migrations-postgres/meta/_journal.json,sha256=zIBPX9lX4UnSgo3fzeoQXh2u3M9ZlyxRDvs8-VzBJbI,207
|
|
9
|
-
nao_core/bin/migrations-sqlite/0000_cloudy_squirrel_girl.sql,sha256=i8NqZSv7qTzcVIoLBE0pNcuM4ZCp4WS9iYMUXxzqCT0,3609
|
|
10
|
-
nao_core/bin/migrations-sqlite/meta/0000_snapshot.json,sha256=q-O9sjRNmCT3s0-ZyF1gZ60ZaDH24wGjC-VHG-2RdVU,15268
|
|
11
|
-
nao_core/bin/migrations-sqlite/meta/_journal.json,sha256=-8raNXK1aCMrt-25YnnIM4GRb9w_JT6AtiDDBQfBgx0,210
|
|
12
|
-
nao_core/bin/public/favicon.ico,sha256=s-a2BQ71NeB_Y2uOC_EPF9isG5DavpF9GKwYgxNSOWk,15406
|
|
13
|
-
nao_core/bin/public/github-icon.svg,sha256=drFeRxLjsnngoGOh4heU3E5mX_xUsmGgFOc_mnjXKwU,1926
|
|
14
|
-
nao_core/bin/public/google-icon.svg,sha256=bTmcoH4gkdoV2Atl2kp-pLFpFZNL85FR_8GAKv9LL5I,1140
|
|
15
|
-
nao_core/bin/public/index.html,sha256=BOiBADShUuIisOGAPzzOoWtz6WZGOnPd1she4-nlghk,670
|
|
16
|
-
nao_core/bin/public/assets/_chatId-z5gRlor1.js,sha256=SsV80_uJgklDpNGZvHCd3z2L6gbEhaI4jbjCGUn2skU,317
|
|
17
|
-
nao_core/bin/public/assets/chat-messages-DUR3D342.js,sha256=TdgOYw6ydRjhIaxnGWoAfOYZXSZALfAObQvm5PUXaOs,10008
|
|
18
|
-
nao_core/bin/public/assets/index-BDlcD_HE.js,sha256=2p13XoH_dd-F2EL40raWqWLFQ2M08QsJw54S19PWA5Y,144
|
|
19
|
-
nao_core/bin/public/assets/index-Bc7icYyJ.css,sha256=p2xISnm3R1k1yDMu2H4GgMwOlqvqXrI4vxbkMbWfB9k,34874
|
|
20
|
-
nao_core/bin/public/assets/index-CGg3ZQH6.js,sha256=bymnyMM_CMLWyWDWmNV6qeBI_g5L5zQhVu_t4hkwo-8,521092
|
|
21
|
-
nao_core/bin/public/assets/login-D87n9R5V.js,sha256=ztE0a6I0pP3OS2DgWg8Voe4K5--gvko33VUcRmrl6AQ,793
|
|
22
|
-
nao_core/bin/public/assets/signinForm-9PY1Lvqj.js,sha256=T3y4qLH7YeO6YvZwlVs6y-D_kaao3FwHhmjrKZ4b4JY,28761
|
|
23
|
-
nao_core/bin/public/assets/signup-B7NC1g08.js,sha256=NQcfePZ3vLhH0VZY4ge1RB6eiIAhcjVYDMs1RxUm1ug,832
|
|
24
|
-
nao_core/commands/__init__.py,sha256=rFCuUyA9wM4hS6CxCt2M_5W4VysyQXh6HkA_hyRCxPc,207
|
|
25
|
-
nao_core/commands/chat.py,sha256=TiV-0dEFPRmIirHMnPVbKNomNWO67OsaPT1SzA07EIM,5995
|
|
26
|
-
nao_core/commands/debug.py,sha256=Hdtb6_2F-a9Nr-aU_exdnPZY0-Lf9dgV1QX6QxPr9P8,4794
|
|
27
|
-
nao_core/commands/init.py,sha256=QGKdBn7mKc3yc379DJNOsFh5LW313XS4r7CFsZs-nRY,5184
|
|
28
|
-
nao_core/commands/sync.py,sha256=NCWgWoBqYMk6qzobSQTbGqCc8a9pX2VI-CqCNmXsFhQ,12626
|
|
29
|
-
nao_core/config/__init__.py,sha256=qzM2sXRKfO5ZCKbIRwUS-Roh5ry0zVEqWJBobVlGbJM,308
|
|
30
|
-
nao_core/config/base.py,sha256=O6wf0csZteCk18Mw7hV8sHtUS9KTbR06Ffv3BpHINvc,2715
|
|
31
|
-
nao_core/config/databases/__init__.py,sha256=t62wpLCTi9lAf6rzem7iu605ywtK4qo7DuTP-qSr3jc,1027
|
|
32
|
-
nao_core/config/databases/base.py,sha256=Y0BN8Zowi0n0GKT2sEJ2iqitPf-P4o1V9gCVhgiSzr8,2219
|
|
33
|
-
nao_core/config/databases/bigquery.py,sha256=RA07YMp24kQVPOQStdLCx27e50nUIIoO_U1io1wqtVk,1453
|
|
34
|
-
nao_core/config/llm/__init__.py,sha256=wBVFFmOWWUuIM19fNeXkdIWxg9nE_cR3roWFyUvAuIE,343
|
|
35
|
-
nao_core-0.0.15.dist-info/METADATA,sha256=UgzYickSG7YXbCghidgfBCS1KnN8Zpt70Plf1R1J6CE,5206
|
|
36
|
-
nao_core-0.0.15.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
37
|
-
nao_core-0.0.15.dist-info/entry_points.txt,sha256=SZakIiNybgS3pl_OEZVLyLSweadeBFoEMBECMoj9czY,42
|
|
38
|
-
nao_core-0.0.15.dist-info/licenses/LICENSE,sha256=rn5YtWB6E5hPQI49tCTNSyqlArWGsB6HzA5FfSbRHRs,1066
|
|
39
|
-
nao_core-0.0.15.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|