@stacksjs/tinker 0.75.541 → 0.75.542

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/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { serialize } from './serialize';
1
2
  import type { TinkerValue } from './serialize';
2
3
  /**
3
4
  * Get the path to the tinker history file.
package/dist/index.js CHANGED
@@ -1,39 +1,42 @@
1
1
  // @bun
2
- import{appendFileSync as oe,chmodSync as q,existsSync as D,readFileSync as ie,writeFileSync as _,writeSync as se}from"fs";import{homedir as ae}from"os";import{join as ce,resolve as ue}from"path";import v from"process";import{writeSync as ne}from"fs";import{isAbsolute as H,resolve as C}from"path";import O from"process";var W={maxDepth:8,maxItems:200,maxString:20000,maxNodes:50000},J=/^\s*at\s+(?:(.*?)\s+\()?(.+?):(\d+):(\d+)\)?\s*$/;function Y(e){if(!e)return[];let r=[];for(let n of e.split(`
3
- `)){let i=J.exec(n);if(!i)continue;r.push({function:i[1]||void 0,file:i[2],line:Number(i[3]),column:Number(i[4])})}return r}function G(e){if(Function.prototype.toString.call(e).startsWith("class"))return"class";let n=e.constructor?.name;if(n==="AsyncFunction"||n==="AsyncGeneratorFunction")return"async";if(n==="GeneratorFunction")return"generator";return"function"}function N(e){let r=Object.getPrototypeOf(e);if(r===null)return"null prototype";let n=r.constructor?.name;return typeof n==="string"&&n&&n!=="Object"?n:void 0}function E(e,r={}){let n={...W,...r.limits},i=r.describers??[],s=new Map,m=0,b=1;function y(a,g){if(m++,a===void 0)return{t:"undefined"};if(a===null)return{t:"null"};switch(typeof a){case"boolean":return{t:"boolean",v:a};case"number":if(Number.isNaN(a))return{t:"number",v:"NaN"};if(a===Number.POSITIVE_INFINITY)return{t:"number",v:"Infinity"};if(a===Number.NEGATIVE_INFINITY)return{t:"number",v:"-Infinity"};if(Object.is(a,-0))return{t:"number",v:"-0"};return{t:"number",v:a};case"bigint":return{t:"bigint",v:a.toString()};case"string":return a.length>n.maxString?{t:"string",v:a.slice(0,n.maxString),truncated:a.length-n.maxString}:{t:"string",v:a};case"symbol":return{t:"symbol",v:a.description??""};case"function":return{t:"function",name:a.name||"(anonymous)",kind:G(a)}}let o=a,l=s.get(o);if(l!==void 0)return{t:"ref",id:l};if(o instanceof Date)return{t:"date",v:Number.isNaN(o.getTime())?null:o.toISOString()};if(o instanceof RegExp)return{t:"regexp",v:o.toString()};if(o instanceof URL)return{t:"url",v:o.href};if(o instanceof Promise)return{t:"promise"};if(ArrayBuffer.isView(o)||o instanceof ArrayBuffer){let t=o instanceof ArrayBuffer?new Uint8Array(o):new Uint8Array(o.buffer,o.byteOffset,o.byteLength);return{t:"bytes",ctor:o.constructor?.name??"ArrayBuffer",length:t.byteLength,hex:Buffer.from(t.subarray(0,64)).toString("hex")}}if(g>=n.maxDepth)return{t:"cut",reason:"depth",ctor:N(o)??(Array.isArray(o)?"Array":"Object")};if(m>=n.maxNodes)return{t:"cut",reason:"nodes",ctor:N(o)};let c=b++;s.set(o,c);let p=(t)=>y(t,g+1);if(o instanceof Error)return S(o,p);for(let t of i){let u;try{u=t(o,p)}catch{u=void 0}if(u)return u}if(Array.isArray(o)){let t=[],u=Math.min(o.length,n.maxItems);for(let d=0;d<u&&m<n.maxNodes;d++)t.push(p(o[d]));let k=o.length-t.length,f=N(o);return{t:"array",id:c,...f&&f!=="Array"?{ctor:f}:{},length:o.length,items:t,...k>0?{more:k}:{}}}if(o instanceof Map){let t=[];for(let[k,f]of o){if(t.length>=n.maxItems||m>=n.maxNodes)break;t.push([p(k),p(f)])}let u=o.size-t.length;return{t:"map",id:c,size:o.size,entries:t,...u>0?{more:u}:{}}}if(o instanceof Set){let t=[];for(let k of o){if(t.length>=n.maxItems||m>=n.maxNodes)break;t.push(p(k))}let u=o.size-t.length;return{t:"set",id:c,size:o.size,items:t,...u>0?{more:u}:{}}}return w(o,c,p)}function w(a,g,o){let l=N(a),c=a,p=Object.keys(a);if(p.length===0&&l&&typeof a.toJSON==="function")try{let k=a.toJSON();if(Array.isArray(k)){let f=o(k);return f.t==="array"?{...f,ctor:l}:f}if(k&&typeof k==="object")c=k,p=Object.keys(c)}catch{}let t=[];for(let k of p){if(t.length>=n.maxItems||m>=n.maxNodes)break;let f;try{f=c[k]}catch(d){f=d}t.push([k,o(f)])}let u=p.length-t.length;return{t:"object",id:g,...l?{ctor:l}:{},entries:t,...u>0?{more:u}:{}}}function S(a,g){let o={t:"error",name:a.name||"Error",message:String(a.message??"")};if(typeof a.stack==="string"){o.stack=a.stack;let c=Y(a.stack);if(c.length)o.frames=c}if(a.cause!==void 0)o.cause=g(a.cause);let l=[];for(let c of Object.keys(a)){if(c==="name"||c==="message"||c==="stack"||c==="cause")continue;if(l.length>=n.maxItems)break;l.push([c,g(a[c])])}if(l.length)o.entries=l;return o}return y(e,0)}function B(e,r={}){if(e instanceof Error)return E(e,r);return{t:"error",name:"Thrown",message:typeof e==="string"?e:Bun.inspect(e),cause:E(e,r)}}class F extends Error{constructor(){super("dd");this.name="TinkerHalt"}}var K=/\bimport\((["'])(\.{1,2}\/[^"']*)\1\)/g;function j(e,r,n="tinker"){return`${new Bun.Transpiler({loader:"ts",replMode:!0}).transformSync(e).replace(K,(m,b,y)=>`import(${b}${C(r,y)}${b})`)}
4
- //# sourceURL=${n}.ts`}function Q(e){let r=e instanceof AggregateError?e.errors:[e],n=[];for(let i of r){if(!i||typeof i!=="object")continue;let{message:s,position:m}=i;n.push({message:typeof s==="string"?s:String(i),...m?.line!==void 0?{line:m.line}:{},...m?.column!==void 0?{column:m.column}:{},...m?.lineText?{lineText:m.lineText}:{}})}return n}async function X(e){let i=!0;try{let{overridesReady:s}=await import("@stacksjs/config");await s}catch(s){i=!1,e.push(`config not loaded: ${s instanceof Error?s.message:String(s)}`)}try{let{injectGlobalAutoImports:s}=await import("@stacksjs/server");await s()}catch(s){i=!1,e.push(`models and framework globals not injected: ${s instanceof Error?s.message:String(s)}`)}return i}var Z=["log","info","debug","dir","table"],ee=["warn","error","trace"];async function I(e={}){let r=e.cwd?H(e.cwd)?e.cwd:C(O.cwd(),e.cwd):O.cwd();if(r!==O.cwd())O.chdir(r);let n={limits:e.limits,describers:e.describers},i=[],s=[],m="boot",b,y=(t)=>{b?.push(t);try{e.onFrame?.(t)}catch{}},w=console,S=(t)=>t.map((u)=>typeof u==="string"?u:Bun.inspect(u,{depth:6})).join(" ");for(let[t,u]of[[Z,"stdout"],[ee,"stderr"]])for(let k of t){let f=w[k];w[k]=(...d)=>y({type:u,id:m,text:`${S(d)}
5
- `}),s.push(()=>{w[k]=f})}for(let[t,u]of[[O.stdout,"stdout"],[O.stderr,"stderr"]]){let k=t.write;t.write=(f,...d)=>(y({type:u,id:m,text:typeof f==="string"?f:Buffer.from(f).toString("utf8")}),d.find((T)=>typeof T==="function")?.(),!0),s.push(()=>{t.write=k})}let a=globalThis;if(a.dump=(...t)=>{for(let u of t)y({type:"dump",id:m,value:E(u,n)})},a.dd=(...t)=>{throw a.dump(...t),new F},e.globals)Object.assign(a,e.globals);let g=!1;if(typeof e.boot==="function")try{await e.boot(),g=!0}catch(t){i.push(`boot failed: ${t instanceof Error?t.message:String(t)}`)}else if(e.boot!==!1)g=await X(i);if(g&&e.boot!==!1&&typeof e.boot!=="function"){let t=(...f)=>{for(let d of f)y({type:"dump",id:m,value:E(d,n)})};a.dump=t,a.dd=(...f)=>{throw t(...f),new F};let u="@stacksjs/logging",k="@stacksjs/query-builder";try{let{registerTransport:f}=await import(u);s.push(f({name:"tinker",log(d){y({type:"log",id:m,level:d.level,message:d.message,timestamp:d.timestamp,...d.context?{context:E(d.context,n)}:{}})}}))}catch(f){i.push(`log capture unavailable: ${f instanceof Error?f.message:String(f)}`)}try{let{registerPersistentQueryHooks:f}=await import(k);s.push(f({onQueryEnd(d){y({type:"query",id:m,sql:d.sql,...d.params?.length?{params:E(d.params,n)}:{},...d.kind?{kind:d.kind}:{},durationMs:d.durationMs,...d.rowCount!==void 0?{rowCount:d.rowCount}:{}})},onQueryError(d){y({type:"query",id:m,sql:d.sql,...d.params?.length?{params:E(d.params,n)}:{},...d.kind?{kind:d.kind}:{},durationMs:d.durationMs,error:d.error instanceof Error?d.error.message:String(d.error)})}}))}catch(f){i.push(`query capture unavailable: ${f instanceof Error?f.message:String(f)}`)}}let o=eval,l=0,c=Promise.resolve();async function p(t,u){let k=[];b=k,m=u;let f=performance.now(),d=()=>Math.round((performance.now()-f)*100)/100,A;try{A=j(t,r,`tinker-${u}`)}catch(T){let x=d();return y({type:"error",id:u,phase:"parse",error:B(T,n),diagnostics:Q(T),durationMs:x}),y({type:"done",id:u,ok:!1}),b=void 0,{id:u,ok:!1,thrown:T,frames:k,durationMs:x}}try{let x=(await o(A))?.value,M=d();return y({type:"result",id:u,value:E(x,n),durationMs:M}),y({type:"done",id:u,ok:!0}),{id:u,ok:!0,value:x,frames:k,durationMs:M}}catch(T){let x=d();if(T instanceof F)return y({type:"result",id:u,value:{t:"undefined"},durationMs:x}),y({type:"done",id:u,ok:!0}),{id:u,ok:!0,frames:k,durationMs:x};return y({type:"error",id:u,phase:"run",error:B(T,n),durationMs:x}),y({type:"done",id:u,ok:!1}),{id:u,ok:!1,thrown:T,frames:k,durationMs:x}}finally{b=void 0}}return{info:{cwd:r,booted:g,bun:Bun.version,warnings:i},evaluate(t,u={}){let k=u.id??String(++l),f=c.then(()=>p(t,k));return c=f.catch(()=>{}),f},dispose(){while(s.length)s.pop()?.()}}}var z="\x1E",re=1;function te(e){return`${z}${JSON.stringify(e)}
6
- `}function $e(){let e="",r=(n)=>{if(n.startsWith(z))try{return{frame:JSON.parse(n.slice(z.length))}}catch{return{stray:n}}return{stray:n}};return{push(n){e+=n;let i=e.split(`
7
- `);return e=i.pop()??"",i.map(r)},flush(){if(!e)return[];let n=e;return e="",[{stray:n}]}}}async function R(e={}){let r=e.write??((c)=>{ne(1,c)}),n=(c)=>r(te(c)),{input:i,write:s,once:m,...b}=e,y=await I({...b,onFrame:n});n({type:"ready",session:y.info,protocol:re});let w=!0,S=!1;if(m!==void 0)return{ok:(await y.evaluate(m)).ok,session:y};let a=new TextDecoder,g="",o=i??Bun.stdin.stream(),l=async(c)=>{if(!c.trim())return!0;let p;try{p=JSON.parse(c)}catch{return n({type:"protocol-error",message:"request is not valid JSON"}),!0}if(p.op==="exit")return!1;if(p.op==="ping")return n({type:"pong",...p.id?{id:p.id}:{}}),!0;if(p.op==="eval"&&typeof p.code==="string"){if(!(await y.evaluate(p.code,{id:p.id})).ok)w=!1;return!0}return n({type:"protocol-error",message:`unknown request: ${String(p.op)}`}),!0};e:for await(let c of o){g+=typeof c==="string"?c:a.decode(c,{stream:!0});let p=g.indexOf(`
8
- `);while(p!==-1){let t=g.slice(0,p);if(g=g.slice(p+1),!await l(t)){S=!0;break e}p=g.indexOf(`
9
- `)}}if(!S&&g.trim())await l(g);return{ok:w,session:y}}function P(e){return e?.historyFile??ce(ae(),".stacks_tinker_history")}function L(e){let r=P(e);if(!D(r))return[];return ie(r,"utf-8").split(`
10
- `).filter(Boolean)}function me(e,r){let n=P(r),i=!D(n);if(oe(n,`${e}
11
- `),i)try{q(n,384)}catch{}let s=r?.historySize??5000,m=L(r);if(m.length>s){let b=m.slice(m.length-s);_(n,b.join(`
2
+ import{appendFileSync as de,chmodSync as q,existsSync as J,readFileSync as fe,writeFileSync as K,writeSync as pe}from"fs";import{homedir as ge}from"os";import{join as ke,resolve as ye}from"path";import F from"process";import{writeSync as ue}from"fs";import{isAbsolute as ne,resolve as D}from"path";import E from"process";var Y={maxDepth:8,maxItems:200,maxString:20000,maxNodes:50000},G=/^\s*at\s+(?:(.*?)\s+\()?(.+?):(\d+):(\d+)\)?\s*$/;function Q(e){if(!e)return[];let r=[];for(let n of e.split(`
3
+ `)){let i=G.exec(n);if(!i)continue;r.push({function:i[1]||void 0,file:i[2],line:Number(i[3]),column:Number(i[4])})}return r}function X(e){if(Function.prototype.toString.call(e).startsWith("class"))return"class";let n=e.constructor?.name;if(n==="AsyncFunction"||n==="AsyncGeneratorFunction")return"async";if(n==="GeneratorFunction")return"generator";return"function"}function j(e){let r=Object.getPrototypeOf(e);if(r===null)return"null prototype";let n=r.constructor?.name;return typeof n==="string"&&n&&n!=="Object"?n:void 0}var _=2000000;class A{kind;html;title;text;constructor(e,r,n,i){this.kind=e;this.html=r;this.title=n;this.text=i}}var Z=["hasOne","hasMany","belongsTo","belongsToMany","hasOneThrough","hasManyThrough","morphOne","morphMany","morphTo","morphToMany"];function R(e){let r=[];for(let n of Z){let i=e[n];if(!i)continue;if(Array.isArray(i)){for(let o of i)if(typeof o==="string")r.push({kind:n,model:o});else if(o&&typeof o==="object"&&typeof o.model==="string")r.push({kind:n,model:o.model,...typeof o.relationName==="string"?{name:o.relationName}:{}})}else if(typeof i==="object"){for(let[o,s]of Object.entries(i))if(typeof s==="string")r.push({kind:n,model:s,name:o})}else if(typeof i==="string")r.push({kind:n,model:i})}return r}function ee(e){let r=e._definition;return typeof r==="object"&&r!==null&&typeof r.name==="string"&&typeof e.toJSON==="function"&&typeof e.getAttributes==="function"}function O(e,r={}){let n={...Y,...r.limits},i=r.describers??[],o=new Map,s=0,b=1;function g(a,y){if(s++,a===void 0)return{t:"undefined"};if(a===null)return{t:"null"};switch(typeof a){case"boolean":return{t:"boolean",v:a};case"number":if(Number.isNaN(a))return{t:"number",v:"NaN"};if(a===Number.POSITIVE_INFINITY)return{t:"number",v:"Infinity"};if(a===Number.NEGATIVE_INFINITY)return{t:"number",v:"-Infinity"};if(Object.is(a,-0))return{t:"number",v:"-0"};return{t:"number",v:a};case"bigint":return{t:"bigint",v:a.toString()};case"string":return a.length>n.maxString?{t:"string",v:a.slice(0,n.maxString),truncated:a.length-n.maxString}:{t:"string",v:a};case"symbol":return{t:"symbol",v:a.description??""};case"function":return{t:"function",name:a.name||"(anonymous)",kind:X(a)}}let t=a,d=o.get(t);if(d!==void 0)return{t:"ref",id:d};if(t instanceof Date)return{t:"date",v:Number.isNaN(t.getTime())?null:t.toISOString()};if(t instanceof RegExp)return{t:"regexp",v:t.toString()};if(t instanceof URL)return{t:"url",v:t.href};if(t instanceof Promise)return{t:"promise"};if(ArrayBuffer.isView(t)||t instanceof ArrayBuffer){let c=t instanceof ArrayBuffer?new Uint8Array(t):new Uint8Array(t.buffer,t.byteOffset,t.byteLength);return{t:"bytes",ctor:t.constructor?.name??"ArrayBuffer",length:c.byteLength,hex:Buffer.from(c.subarray(0,64)).toString("hex")}}if(y>=n.maxDepth)return{t:"cut",reason:"depth",ctor:j(t)??(Array.isArray(t)?"Array":"Object")};if(s>=n.maxNodes)return{t:"cut",reason:"nodes",ctor:j(t)};let u=b++;o.set(t,u);let l=(c)=>g(c,y+1);if(t instanceof Error)return k(t,l);if(t instanceof A){let c=t.html.length-_;return{t:"html",kind:t.kind,...t.title?{title:t.title}:{},html:c>0?t.html.slice(0,_):t.html,...t.text?{text:t.text.slice(0,n.maxString)}:{},...c>0?{truncated:c}:{}}}if(ee(t))return N(t,u,l);for(let c of i){let p;try{p=c(t,l)}catch{p=void 0}if(p)return p}if(Array.isArray(t)){let c=[],p=Math.min(t.length,n.maxItems);for(let S=0;S<p&&s<n.maxNodes;S++)c.push(l(t[S]));let f=t.length-c.length,m=j(t);return{t:"array",id:u,...m&&m!=="Array"?{ctor:m}:{},length:t.length,items:c,...f>0?{more:f}:{}}}if(t instanceof Map){let c=[];for(let[f,m]of t){if(c.length>=n.maxItems||s>=n.maxNodes)break;c.push([l(f),l(m)])}let p=t.size-c.length;return{t:"map",id:u,size:t.size,entries:c,...p>0?{more:p}:{}}}if(t instanceof Set){let c=[];for(let f of t){if(c.length>=n.maxItems||s>=n.maxNodes)break;c.push(l(f))}let p=t.size-c.length;return{t:"set",id:u,size:t.size,items:c,...p>0?{more:p}:{}}}return V(t,u,l)}function N(a,y,t){let d=a._definition,u={};try{let h=a.toJSON();if(h&&typeof h==="object")u=h}catch{}let l={};try{l=a.getLoadedRelations?.()??{}}catch{l={}}let c=Object.keys(u).filter((h)=>!(h in l)),p=[];for(let h of c){if(p.length>=n.maxItems||s>=n.maxNodes)break;p.push([h,t(u[h])])}let f=Object.keys(a).filter((h)=>!(h in u)),m=[];for(let[h,H]of Object.entries(l)){if(m.length>=n.maxItems||s>=n.maxNodes)break;m.push([h,t(H)])}let S=R(d),w=typeof d.primaryKey==="string"?d.primaryKey:"id",T=c.length-p.length;return{t:"model",id:y,model:d.name,...typeof d.table==="string"?{table:d.table}:{},primaryKey:w,...u[w]!==void 0?{key:t(u[w])}:{},attributes:p,...f.length?{hidden:f}:{},...m.length?{loaded:m}:{},...S.length?{relations:S}:{},...T>0?{more:T}:{}}}function V(a,y,t){let d=j(a),u=a,l=Object.keys(a);if(l.length===0&&d&&typeof a.toJSON==="function")try{let f=a.toJSON();if(Array.isArray(f)){let m=t(f);return m.t==="array"?{...m,ctor:d}:m}if(f&&typeof f==="object")u=f,l=Object.keys(u)}catch{}let c=[];for(let f of l){if(c.length>=n.maxItems||s>=n.maxNodes)break;let m;try{m=u[f]}catch(S){m=S}c.push([f,t(m)])}let p=l.length-c.length;return{t:"object",id:y,...d?{ctor:d}:{},entries:c,...p>0?{more:p}:{}}}function k(a,y){let t={t:"error",name:a.name||"Error",message:String(a.message??"")};if(typeof a.stack==="string"){t.stack=a.stack;let u=Q(a.stack);if(u.length)t.frames=u}if(a.cause!==void 0)t.cause=y(a.cause);let d=[];for(let u of Object.keys(a)){if(u==="name"||u==="message"||u==="stack"||u==="cause")continue;if(d.length>=n.maxItems)break;d.push([u,y(a[u])])}if(d.length)t.entries=d;return t}return g(e,0)}function P(e,r={}){if(e instanceof Error)return O(e,r);return{t:"error",name:"Thrown",message:typeof e==="string"?e:Bun.inspect(e),cause:O(e,r)}}function te(){let e=[],r=new Set;for(let n of Object.getOwnPropertyNames(globalThis)){let i;try{i=globalThis[n]}catch{continue}if(!i||typeof i!=="object"&&typeof i!=="function")continue;let o=i.getDefinition;if(typeof o!=="function")continue;let s;try{s=o.call(i)}catch{continue}if(!s||typeof s.name!=="string"||r.has(s.name))continue;r.add(s.name),e.push({name:s.name,...typeof s.table==="string"?{table:s.table}:{},...typeof s.primaryKey==="string"?{primaryKey:s.primaryKey}:{},attributes:s.attributes&&typeof s.attributes==="object"?Object.keys(s.attributes):[],relations:R(s)})}return e.sort((n,i)=>n.name.localeCompare(i.name))}function re(){return{html(e,r){return new A("html",String(e),r)},async mail(e,r={}){let{templateByName:i}=await import("@stacksjs/email"),o=await i(e,{variables:r});if(!o?.html)throw Error(`No mail template named "${e}" rendered. Templates live in resources/emails.`);return new A("mail",o.html,e,o.text)}}}class I extends Error{constructor(){super("dd");this.name="TinkerHalt"}}var ie=/\bimport\((["'])(\.{1,2}\/[^"']*)\1\)/g;function B(e,r,n="tinker"){return`${new Bun.Transpiler({loader:"ts",replMode:!0}).transformSync(e).replace(ie,(s,b,g)=>`import(${b}${D(r,g)}${b})`)}
4
+ //# sourceURL=${n}.ts`}function oe(e){let r=e instanceof AggregateError?e.errors:[e],n=[];for(let i of r){if(!i||typeof i!=="object")continue;let{message:o,position:s}=i;n.push({message:typeof o==="string"?o:String(i),...s?.line!==void 0?{line:s.line}:{},...s?.column!==void 0?{column:s.column}:{},...s?.lineText?{lineText:s.lineText}:{}})}return n}async function se(e){let i=!0;try{let{overridesReady:o}=await import("@stacksjs/config");await o}catch(o){i=!1,e.push(`config not loaded: ${o instanceof Error?o.message:String(o)}`)}try{let{injectGlobalAutoImports:o}=await import("@stacksjs/server");await o()}catch(o){i=!1,e.push(`models and framework globals not injected: ${o instanceof Error?o.message:String(o)}`)}return i}var ae=["log","info","debug","dir","table"],ce=["warn","error","trace"];async function v(e={}){let r=e.cwd?ne(e.cwd)?e.cwd:D(E.cwd(),e.cwd):E.cwd();if(r!==E.cwd())E.chdir(r);let n={limits:e.limits,describers:e.describers},i=[],o=[],s="boot",b,g=(l)=>{b?.push(l);try{e.onFrame?.(l)}catch{}},N=console,V=(l)=>l.map((c)=>typeof c==="string"?c:Bun.inspect(c,{depth:6})).join(" ");for(let[l,c]of[[ae,"stdout"],[ce,"stderr"]])for(let p of l){let f=N[p];N[p]=(...m)=>g({type:c,id:s,text:`${V(m)}
5
+ `}),o.push(()=>{N[p]=f})}for(let[l,c]of[[E.stdout,"stdout"],[E.stderr,"stderr"]]){let p=l.write;l.write=(f,...m)=>(g({type:c,id:s,text:typeof f==="string"?f:Buffer.from(f).toString("utf8")}),m.find((w)=>typeof w==="function")?.(),!0),o.push(()=>{l.write=p})}let k=globalThis;if(k.dump=(...l)=>{for(let c of l)g({type:"dump",id:s,value:O(c,n)})},k.dd=(...l)=>{throw k.dump(...l),new I},k.preview=re(),e.globals)Object.assign(k,e.globals);let a=!1;if(typeof e.boot==="function")try{await e.boot(),a=!0}catch(l){i.push(`boot failed: ${l instanceof Error?l.message:String(l)}`)}else if(e.boot!==!1)a=await se(i);if(a&&e.boot!==!1&&typeof e.boot!=="function"){let l=(...f)=>{for(let m of f)g({type:"dump",id:s,value:O(m,n)})};k.dump=l,k.dd=(...f)=>{throw l(...f),new I};let c="@stacksjs/logging",p="@stacksjs/query-builder";try{let{registerTransport:f}=await import(c);o.push(f({name:"tinker",log(m){g({type:"log",id:s,level:m.level,message:m.message,timestamp:m.timestamp,...m.context?{context:O(m.context,n)}:{}})}}))}catch(f){i.push(`log capture unavailable: ${f instanceof Error?f.message:String(f)}`)}try{let{registerPersistentQueryHooks:f}=await import(p);o.push(f({onQueryEnd(m){g({type:"query",id:s,sql:m.sql,...m.params?.length?{params:O(m.params,n)}:{},...m.kind?{kind:m.kind}:{},durationMs:m.durationMs,...m.rowCount!==void 0?{rowCount:m.rowCount}:{}})},onQueryError(m){g({type:"query",id:s,sql:m.sql,...m.params?.length?{params:O(m.params,n)}:{},...m.kind?{kind:m.kind}:{},durationMs:m.durationMs,error:m.error instanceof Error?m.error.message:String(m.error)})}}))}catch(f){i.push(`query capture unavailable: ${f instanceof Error?f.message:String(f)}`)}}let y=eval,t=0,d=Promise.resolve();async function u(l,c){let p=[];b=p,s=c;let f=performance.now(),m=()=>Math.round((performance.now()-f)*100)/100,S;try{S=B(l,r,`tinker-${c}`)}catch(w){let T=m();return g({type:"error",id:c,phase:"parse",error:P(w,n),diagnostics:oe(w),durationMs:T}),g({type:"done",id:c,ok:!1}),b=void 0,{id:c,ok:!1,thrown:w,frames:p,durationMs:T}}try{let T=(await y(S))?.value,h=m();return g({type:"result",id:c,value:O(T,n),durationMs:h}),g({type:"done",id:c,ok:!0}),{id:c,ok:!0,value:T,frames:p,durationMs:h}}catch(w){let T=m();if(w instanceof I)return g({type:"result",id:c,value:{t:"undefined"},durationMs:T}),g({type:"done",id:c,ok:!0}),{id:c,ok:!0,frames:p,durationMs:T};return g({type:"error",id:c,phase:"run",error:P(w,n),durationMs:T}),g({type:"done",id:c,ok:!1}),{id:c,ok:!1,thrown:w,frames:p,durationMs:T}}finally{b=void 0}}return{info:{cwd:r,booted:a,bun:Bun.version,warnings:i},models:te,evaluate(l,c={}){let p=c.id??String(++t),f=d.then(()=>u(l,p));return d=f.catch(()=>{}),f},dispose(){while(o.length)o.pop()?.()}}}var z="\x1E",me=2;function le(e){return`${z}${JSON.stringify(e)}
6
+ `}function Ie(){let e="",r=(n)=>{if(n.startsWith(z))try{return{frame:JSON.parse(n.slice(z.length))}}catch{return{stray:n}}return{stray:n}};return{push(n){e+=n;let i=e.split(`
7
+ `);return e=i.pop()??"",i.map(r)},flush(){if(!e)return[];let n=e;return e="",[{stray:n}]}}}async function L(e={}){let r=e.write??((d)=>{ue(1,d)}),n=(d)=>r(le(d)),{input:i,write:o,once:s,...b}=e,g=await v({...b,onFrame:n});n({type:"ready",session:g.info,protocol:me});let N=!0,V=!1;if(s!==void 0)return{ok:(await g.evaluate(s)).ok,session:g};let k=new TextDecoder,a="",y=i??Bun.stdin.stream(),t=async(d)=>{if(!d.trim())return!0;let u;try{u=JSON.parse(d)}catch{return n({type:"protocol-error",message:"request is not valid JSON"}),!0}if(u.op==="exit")return!1;if(u.op==="ping")return n({type:"pong",...u.id?{id:u.id}:{}}),!0;if(u.op==="models")return n({type:"models",...u.id?{id:u.id}:{},models:g.models()}),!0;if(u.op==="eval"&&typeof u.code==="string"){if(!(await g.evaluate(u.code,{id:u.id})).ok)N=!1;return!0}return n({type:"protocol-error",message:`unknown request: ${String(u.op)}`}),!0};e:for await(let d of y){a+=typeof d==="string"?d:k.decode(d,{stream:!0});let u=a.indexOf(`
8
+ `);while(u!==-1){let l=a.slice(0,u);if(a=a.slice(u+1),!await t(l)){V=!0;break e}u=a.indexOf(`
9
+ `)}}if(!V&&a.trim())await t(a);return{ok:N,session:g}}function C(e){return e?.historyFile??ke(ge(),".stacks_tinker_history")}function U(e){let r=C(e);if(!J(r))return[];return fe(r,"utf-8").split(`
10
+ `).filter(Boolean)}function be(e,r){let n=C(r),i=!J(n);if(de(n,`${e}
11
+ `),i)try{q(n,384)}catch{}let o=r?.historySize??5000,s=U(r);if(s.length>o){let b=s.slice(s.length-o);K(n,b.join(`
12
12
  `)+`
13
- `);try{q(n,384)}catch{}}}function le(e){let r=P(e);_(r,"")}function fe(e){let r=["",` \x1B[36mStacks Tinker\x1B[0m (Bun v${e.bun})`,e.booted?" Your app is booted: models, jobs, config and framework helpers are globals.":" Bare session: the app context is not booted."];for(let n of e.warnings)r.push(` \x1B[33m${n}\x1B[0m`);return r.push(""," \x1B[2mDeclarations persist between lines. dump(value) inspects, dd(value) inspects and stops."," .help for commands, .exit or Ctrl+D to leave.\x1B[0m","",""),r.join(`
14
- `)}function h(e,r=1){se(r,e)}function V(e,r=""){let n=`${r} `;switch(e.t){case"undefined":return"undefined";case"null":return"null";case"boolean":return String(e.v);case"number":return String(e.v);case"bigint":return`${e.v}n`;case"string":return JSON.stringify(e.v)+(e.truncated?` ... ${e.truncated} more characters`:"");case"symbol":return`Symbol(${e.v})`;case"function":return`[${e.kind==="class"?"class":"Function"}: ${e.name}]`;case"date":return e.v??"Invalid Date";case"regexp":return e.v;case"url":return e.v;case"promise":return"Promise {}";case"bytes":return`${e.ctor}(${e.length}) <${e.hex}${e.length>64?" ...":""}>`;case"ref":return`[Circular *${e.id}]`;case"cut":return`[${e.ctor??"Object"}]`;case"error":return e.stack??`${e.name}: ${e.message}`;case"array":{if(!e.items.length&&!e.more)return`${e.ctor?`${e.ctor} `:""}[]`;let i=e.items.map((s)=>`${n}${V(s,n)}`);if(e.more)i.push(`${n}... ${e.more} more`);return`${e.ctor?`${e.ctor} `:""}[
13
+ `);try{q(n,384)}catch{}}}function he(e){let r=C(e);K(r,"")}function we(e){let r=["",` \x1B[36mStacks Tinker\x1B[0m (Bun v${e.bun})`,e.booted?" Your app is booted: models, jobs, config and framework helpers are globals.":" Bare session: the app context is not booted."];for(let n of e.warnings)r.push(` \x1B[33m${n}\x1B[0m`);return r.push(""," \x1B[2mDeclarations persist between lines. dump(value) inspects, dd(value) inspects and stops."," .help for commands, .exit or Ctrl+D to leave.\x1B[0m","",""),r.join(`
14
+ `)}function x(e,r=1){pe(r,e)}function M(e,r=""){let n=`${r} `;switch(e.t){case"undefined":return"undefined";case"null":return"null";case"boolean":return String(e.v);case"number":return String(e.v);case"bigint":return`${e.v}n`;case"string":return JSON.stringify(e.v)+(e.truncated?` ... ${e.truncated} more characters`:"");case"symbol":return`Symbol(${e.v})`;case"function":return`[${e.kind==="class"?"class":"Function"}: ${e.name}]`;case"date":return e.v??"Invalid Date";case"regexp":return e.v;case"url":return e.v;case"promise":return"Promise {}";case"bytes":return`${e.ctor}(${e.length}) <${e.hex}${e.length>64?" ...":""}>`;case"ref":return`[Circular *${e.id}]`;case"cut":return`[${e.ctor??"Object"}]`;case"error":return e.stack??`${e.name}: ${e.message}`;case"array":{if(!e.items.length&&!e.more)return`${e.ctor?`${e.ctor} `:""}[]`;let i=e.items.map((o)=>`${n}${M(o,n)}`);if(e.more)i.push(`${n}... ${e.more} more`);return`${e.ctor?`${e.ctor} `:""}[
15
15
  ${i.join(`,
16
16
  `)}
17
- ${r}]`}case"set":{let i=e.items.map((s)=>`${n}${V(s,n)}`);if(e.more)i.push(`${n}... ${e.more} more`);return i.length?`Set(${e.size}) {
17
+ ${r}]`}case"set":{let i=e.items.map((o)=>`${n}${M(o,n)}`);if(e.more)i.push(`${n}... ${e.more} more`);return i.length?`Set(${e.size}) {
18
18
  ${i.join(`,
19
19
  `)}
20
- ${r}}`:"Set(0) {}"}case"map":{let i=e.entries.map(([s,m])=>`${n}${V(s,n)} => ${V(m,n)}`);if(e.more)i.push(`${n}... ${e.more} more`);return i.length?`Map(${e.size}) {
20
+ ${r}}`:"Set(0) {}"}case"map":{let i=e.entries.map(([o,s])=>`${n}${M(o,n)} => ${M(s,n)}`);if(e.more)i.push(`${n}... ${e.more} more`);return i.length?`Map(${e.size}) {
21
21
  ${i.join(`,
22
22
  `)}
23
- ${r}}`:"Map(0) {}"}case"object":{if(!e.entries.length&&!e.more)return`${e.ctor?`${e.ctor} `:""}{}`;let i=e.entries.map(([s,m])=>`${n}${s}: ${V(m,n)}`);if(e.more)i.push(`${n}... ${e.more} more`);return`${e.ctor?`${e.ctor} `:""}{
23
+ ${r}}`:"Map(0) {}"}case"html":return`[${e.kind}${e.title?` ${e.title}`:""}: ${e.html.length} characters of markup]`;case"model":{let i=e.attributes.map(([o,s])=>`${n}${o}: ${M(s,n)}`);for(let o of e.hidden??[])i.push(`${n}${o}: [hidden]`);for(let[o,s]of e.loaded??[])i.push(`${n}${o}: ${M(s,n)}`);if(e.more)i.push(`${n}... ${e.more} more`);return`${e.model} {
24
24
  ${i.join(`,
25
25
  `)}
26
- ${r}}`}}}function de(e,r){switch(e.type){case"stdout":h(e.text);break;case"stderr":h(e.text,2);break;case"dump":h(`${V(e.value)}
27
- `);break;case"query":if(r)h(`\x1B[2m ${e.durationMs??"?"}ms ${e.sql}\x1B[0m
28
- `,2);break;case"log":if(r)h(`\x1B[2m [${e.level}] ${e.message}\x1B[0m
29
- `,2);break}}async function pe(e,r){let n=[];for(let i of e??[]){let s=i.replace(/[@/\-.]/g,"_").replace(/^_+/,"");try{let m=i.startsWith(".")?ue(r,i):i;globalThis[s]=await import(m)}catch(m){n.push(`${i}: ${m instanceof Error?m.message:String(m)}`)}}return n}var ge=/Unexpected end of file|Unterminated|Expected "\}" but found end of file|Expected "\)" but found end of file|Expected "\]" but found end of file/;function ke(e,r){try{return j(e,r),!1}catch(n){return(n instanceof AggregateError?n.errors.map((s)=>String(s?.message??s)):[String(n?.message??n)]).some((s)=>ge.test(s))}}async function U(e={}){let r=e.cwd??v.cwd(),n=e.stacksPreload!==!1;if(e.serve){let l=e.eval??e.print,{ok:c}=await R({cwd:r,boot:n,...l!==void 0?{once:l}:{}});return{exitCode:c?0:1}}let i=e.verbose===!0,s=await I({cwd:r,boot:n,onFrame:(l)=>de(l,i)});for(let l of await pe(e.preload,s.info.cwd))h(`\x1B[33mpreload failed: ${l}\x1B[0m
30
- `,2);let m=(l,c)=>{if(!l.ok){let p=l.thrown;h(`${p instanceof Error?Bun.inspect(p,{colors:Boolean(v.stderr.isTTY)}):`Uncaught ${Bun.inspect(p)}`}
31
- `,2);return}if(c&&l.value!==void 0)h(`${Bun.inspect(l.value,{colors:Boolean(v.stdout.isTTY),depth:6})}
32
- `)};if(e.eval!==void 0||e.print!==void 0){for(let c of s.info.warnings)h(`\x1B[33m${c}\x1B[0m
33
- `,2);let l=await s.evaluate(e.print??e.eval??"");return m(l,e.print!==void 0),s.dispose(),{exitCode:l.ok?0:1}}if(e.banner!==!1)h(fe(s.info));let{createInterface:b}=await import("readline"),{Writable:y}=await import("stream"),w=new y({write(l,c,p){h(typeof l==="string"?l:Buffer.from(l).toString("utf8")),p()}}),S=e.historySize??5000,a=b({input:v.stdin,output:w,terminal:Boolean(v.stdin.isTTY),history:L(e).slice(-S).reverse(),historySize:S,prompt:"> "}),g="",o=0;a.prompt();try{for await(let l of a){let c=l.trim();if(!g&&c.startsWith(".")){if(c===".exit")break;if(c===".help")h(` .exit leave
26
+ ${r}}`}case"object":{if(!e.entries.length&&!e.more)return`${e.ctor?`${e.ctor} `:""}{}`;let i=e.entries.map(([o,s])=>`${n}${o}: ${M(s,n)}`);if(e.more)i.push(`${n}... ${e.more} more`);return`${e.ctor?`${e.ctor} `:""}{
27
+ ${i.join(`,
28
+ `)}
29
+ ${r}}`}}}function Te(e,r){switch(e.type){case"stdout":x(e.text);break;case"stderr":x(e.text,2);break;case"dump":x(`${M(e.value)}
30
+ `);break;case"query":if(r)x(`\x1B[2m ${e.durationMs??"?"}ms ${e.sql}\x1B[0m
31
+ `,2);break;case"log":if(r)x(`\x1B[2m [${e.level}] ${e.message}\x1B[0m
32
+ `,2);break}}async function xe(e,r){let n=[];for(let i of e??[]){let o=i.replace(/[@/\-.]/g,"_").replace(/^_+/,"");try{let s=i.startsWith(".")?ye(r,i):i;globalThis[o]=await import(s)}catch(s){n.push(`${i}: ${s instanceof Error?s.message:String(s)}`)}}return n}var Se=/Unexpected end of file|Unterminated|Expected "\}" but found end of file|Expected "\)" but found end of file|Expected "\]" but found end of file/;function $e(e,r){try{return B(e,r),!1}catch(n){return(n instanceof AggregateError?n.errors.map((o)=>String(o?.message??o)):[String(n?.message??n)]).some((o)=>Se.test(o))}}async function W(e={}){let r=e.cwd??F.cwd(),n=e.stacksPreload!==!1;if(e.serve){let t=e.eval??e.print,{ok:d}=await L({cwd:r,boot:n,...t!==void 0?{once:t}:{}});return{exitCode:d?0:1}}let i=e.verbose===!0,o=await v({cwd:r,boot:n,onFrame:(t)=>Te(t,i)});for(let t of await xe(e.preload,o.info.cwd))x(`\x1B[33mpreload failed: ${t}\x1B[0m
33
+ `,2);let s=(t,d)=>{if(!t.ok){let u=t.thrown;x(`${u instanceof Error?Bun.inspect(u,{colors:Boolean(F.stderr.isTTY)}):`Uncaught ${Bun.inspect(u)}`}
34
+ `,2);return}if(d&&t.value!==void 0)x(`${M(O(t.value))}
35
+ `)};if(e.eval!==void 0||e.print!==void 0){for(let d of o.info.warnings)x(`\x1B[33m${d}\x1B[0m
36
+ `,2);let t=await o.evaluate(e.print??e.eval??"");return s(t,e.print!==void 0),o.dispose(),{exitCode:t.ok?0:1}}if(e.banner!==!1)x(we(o.info));let{createInterface:b}=await import("readline"),{Writable:g}=await import("stream"),N=new g({write(t,d,u){x(typeof t==="string"?t:Buffer.from(t).toString("utf8")),u()}}),V=e.historySize??5000,k=b({input:F.stdin,output:N,terminal:Boolean(F.stdin.isTTY),history:U(e).slice(-V).reverse(),historySize:V,prompt:"> "}),a="",y=0;k.prompt();try{for await(let t of k){let d=t.trim();if(!a&&d.startsWith(".")){if(d===".exit")break;if(d===".help")x(` .exit leave
34
37
  .clear forget the history file
35
38
  .help this list
36
39
  dump(v), dd(v) inspect a value; dd also stops the line
37
- `);else if(c===".clear")le(e);else h(` unknown command ${c}
38
- `);a.prompt();continue}if(g=g?`${g}
39
- ${l}`:l,!g.trim()){g="",a.prompt();continue}if(ke(g,s.info.cwd)){a.setPrompt("... "),a.prompt();continue}let p=g;g="";try{me(p.replace(/\n/g," "),e)}catch{}let t=await s.evaluate(p);m(t,!0),o=t.ok?0:o,a.setPrompt("> "),a.prompt()}}finally{a.close(),s.dispose()}return{exitCode:o}}async function Ae(e,r={}){return U({...r,eval:e})}async function Be(e,r={}){return U({...r,print:e})}export{z as FRAME_MARKER,re as PROTOCOL_VERSION,me as appendHistory,le as clearHistory,j as compileSnippet,$e as createFrameReader,I as createTinkerSession,W as defaultSerializeLimits,te as encodeFrame,P as getHistoryPath,ke as isIncompleteSnippet,Y as parseStack,L as readHistory,V as renderValue,E as serialize,B as serializeThrown,R as serveTinker,U as startTinker,Ae as tinkerEval,Be as tinkerPrint};
40
+ `);else if(d===".clear")he(e);else x(` unknown command ${d}
41
+ `);k.prompt();continue}if(a=a?`${a}
42
+ ${t}`:t,!a.trim()){a="",k.prompt();continue}if($e(a,o.info.cwd)){k.setPrompt("... "),k.prompt();continue}let u=a;a="";try{be(u.replace(/\n/g," "),e)}catch{}let l=await o.evaluate(u);s(l,!0),y=l.ok?0:y,k.setPrompt("> "),k.prompt()}}finally{k.close(),o.dispose()}return{exitCode:y}}async function De(e,r={}){return W({...r,eval:e})}async function Le(e,r={}){return W({...r,print:e})}export{z as FRAME_MARKER,me as PROTOCOL_VERSION,A as TinkerPreview,be as appendHistory,he as clearHistory,B as compileSnippet,Ie as createFrameReader,v as createTinkerSession,Y as defaultSerializeLimits,le as encodeFrame,C as getHistoryPath,$e as isIncompleteSnippet,ee as isModelInstance,te as listModels,Q as parseStack,U as readHistory,R as relationsOf,M as renderValue,O as serialize,P as serializeThrown,L as serveTinker,W as startTinker,De as tinkerEval,Le as tinkerPrint};
@@ -1,4 +1,4 @@
1
- import type { TinkerFrame, TinkerSession, TinkerSessionInfo, TinkerSessionOptions } from './session';
1
+ import type { TinkerFrame, TinkerModelSummary, TinkerSession, TinkerSessionInfo, TinkerSessionOptions } from './session';
2
2
  export declare function encodeFrame(frame: TinkerWireFrame): string;
3
3
  /**
4
4
  * Split a chunk of a session's output into frames and stray text.
@@ -31,7 +31,7 @@ export declare function serveTinker(options?: ServeOptions): Promise<{ ok: boole
31
31
  */
32
32
  export declare const FRAME_MARKER: '\x1E';
33
33
  /** Bumped when a frame changes shape in a way an older reader would misread. */
34
- export declare const PROTOCOL_VERSION: 1;
34
+ export declare const PROTOCOL_VERSION: 2;
35
35
  export declare interface ServeOptions extends Omit<TinkerSessionOptions, 'onFrame'> {
36
36
  input?: AsyncIterable<Uint8Array | string>
37
37
  write?: (text: string) => void
@@ -39,8 +39,10 @@ export declare interface ServeOptions extends Omit<TinkerSessionOptions, 'onFram
39
39
  }
40
40
  export type TinkerRequest = | { op: 'eval', id?: string, code: string }
41
41
  | { op: 'ping', id?: string }
42
+ | { op: 'models', id?: string }
42
43
  | { op: 'exit' }
43
44
  export type TinkerWireFrame = | TinkerFrame
44
45
  | { type: 'ready', session: TinkerSessionInfo, protocol: number }
45
46
  | { type: 'pong', id?: string }
47
+ | { type: 'models', id?: string, models: TinkerModelSummary[] }
46
48
  | { type: 'protocol-error', message: string }
@@ -1,5 +1,13 @@
1
1
  /** Parse a V8/JavaScriptCore `at fn (file:line:col)` stack into frames. */
2
2
  export declare function parseStack(stack: string | undefined): TinkerStackFrame[];
3
+ /** The relations a model definition declares, flattened. */
4
+ export declare function relationsOf(definition: Record<string, unknown>): Array<{ kind: string, model: string, name?: string }>;
5
+ /**
6
+ * Whether a value is a Stacks ORM model instance. Told by shape, not by
7
+ * class, so this package needs no dependency on the ORM and a model from any
8
+ * copy of it is recognised.
9
+ */
10
+ export declare function isModelInstance(value: object): value is ModelLike;
3
11
  export declare function serialize(root: unknown, options?: SerializeOptions): TinkerValue;
4
12
  /** Describe anything thrown, including non-Error throws, as an error value. */
5
13
  export declare function serializeThrown(thrown: unknown, options?: SerializeOptions): TinkerErrorValue;
@@ -41,10 +49,38 @@ export declare interface TinkerErrorValue {
41
49
  cause?: TinkerValue
42
50
  entries?: Array<[string, TinkerValue]>
43
51
  }
52
+ /** An ORM model instance: what it is, its visible attributes, and what it relates to. */
53
+ export declare interface TinkerModelValue {
54
+ t: 'model'
55
+ id: number
56
+ model: string
57
+ table?: string
58
+ primaryKey?: string
59
+ key?: TinkerValue
60
+ attributes: Array<[string, TinkerValue]>
61
+ hidden?: string[]
62
+ loaded?: Array<[string, TinkerValue]>
63
+ relations?: Array<{ kind: string, model: string, name?: string }>
64
+ more?: number
65
+ }
66
+ /** Rendered markup to show as a page instead of as text: a mail, a view, any HTML. */
67
+ export declare interface TinkerHtmlValue {
68
+ t: 'html'
69
+ kind: 'mail' | 'view' | 'html'
70
+ title?: string
71
+ html: string
72
+ text?: string
73
+ truncated?: number
74
+ }
44
75
  export declare interface SerializeOptions {
45
76
  limits?: Partial<SerializeLimits>
46
77
  describers?: TinkerDescriber[]
47
78
  }
79
+ declare interface ModelLike {
80
+ _definition: { name: string, table?: string, primaryKey?: string } & Record<string, unknown>
81
+ toJSON: () => unknown
82
+ getLoadedRelations?: () => Record<string, unknown>
83
+ }
48
84
  export type TinkerValue = | { t: 'undefined' }
49
85
  | { t: 'null' }
50
86
  | { t: 'boolean', v: boolean }
@@ -62,6 +98,8 @@ export type TinkerValue = | { t: 'undefined' }
62
98
  | { t: 'object', id: number, ctor?: string, entries: Array<[string, TinkerValue]>, more?: number }
63
99
  | { t: 'map', id: number, size: number, entries: Array<[TinkerValue, TinkerValue]>, more?: number }
64
100
  | { t: 'set', id: number, size: number, items: TinkerValue[], more?: number }
101
+ | TinkerModelValue
102
+ | TinkerHtmlValue
65
103
  | { t: 'ref', id: number }
66
104
  | { t: 'cut', reason: 'depth' | 'nodes', ctor?: string }
67
105
  | TinkerErrorValue;
@@ -74,3 +112,15 @@ export type TinkerDescriber = (
74
112
  value: object,
75
113
  describe: (value: unknown) => TinkerValue,
76
114
  ) => TinkerValue | undefined;
115
+ /**
116
+ * A value that says "show me as rendered markup". Returned by the session's
117
+ * `preview` helpers; a snippet can also construct one.
118
+ */
119
+ export declare class TinkerPreview {
120
+ readonly kind: TinkerHtmlValue['kind'];
121
+ readonly html: string;
122
+ readonly title?: string;
123
+ readonly text?: string;
124
+ constructor(kind: TinkerHtmlValue['kind'], html: string, title?: string, text?: string);
125
+ }
126
+ export {};
package/dist/session.d.ts CHANGED
@@ -1,4 +1,9 @@
1
1
  import type { SerializeOptions, TinkerErrorValue, TinkerValue } from './serialize';
2
+ /**
3
+ * The models reachable as globals in this process. After a Stacks boot that
4
+ * is every model the app loaded; in a bare session it is none.
5
+ */
6
+ export declare function listModels(): TinkerModelSummary[];
2
7
  /**
3
8
  * Compile a snippet into JavaScript that, evaluated at global scope, runs it
4
9
  * and yields `{ value }` for its last expression.
@@ -35,8 +40,17 @@ export declare interface TinkerEvaluation {
35
40
  frames: TinkerFrame[]
36
41
  durationMs: number
37
42
  }
43
+ /** One model the app knows, as a relation graph and a completion list need it. */
44
+ export declare interface TinkerModelSummary {
45
+ name: string
46
+ table?: string
47
+ primaryKey?: string
48
+ attributes: string[]
49
+ relations: Array<{ kind: string, model: string, name?: string }>
50
+ }
38
51
  export declare interface TinkerSession {
39
52
  info: TinkerSessionInfo
53
+ models: () => TinkerModelSummary[]
40
54
  evaluate: (code: string, options?: { id?: string }) => Promise<TinkerEvaluation>
41
55
  dispose: () => void
42
56
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/tinker",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.75.541",
5
+ "version": "0.75.542",
6
6
  "description": "Interactive REPL with Stacks framework preloaded.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [