@seldonqa/cli 0.1.2 → 0.1.3

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.
Files changed (2) hide show
  1. package/dist/bin.js +1 -1
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -30,7 +30,7 @@ import{createHash as Ao}from"crypto";import{mkdir as xo,readFile as ki,writeFile
30
30
  `+o.slice(A,_),A=_+1),S=L;return O+=`
31
31
  `,o.length-A>h&&S>A?O+=o.slice(A,S)+`
32
32
  `+o.slice(S+1):O+=o.slice(A),O.slice(1)}function dn(o){let h="",C=0;for(let b=0;b<o.length;C>=65536?b+=2:b++){C=me(o,b);let A=H[C];!A&&ae(C)?(h+=o[b],C>=65536&&(h+=o[b+1])):h+=A||J(C)}return h}function Ve(o,h,C){let b="",A=o.tag;for(let _=0,S=C.length;_<S;_+=1){let L=C[_];o.replacer&&(L=o.replacer.call(C,String(_),L)),(y(o,h,L,!1,!1)||typeof L>"u"&&y(o,h,null,!1,!1))&&(b!==""&&(b+=","+(o.condenseFlow?"":" ")),b+=o.dump)}o.tag=A,o.dump="["+b+"]"}function Je(o,h,C,b){let A="",_=o.tag;for(let S=0,L=C.length;S<L;S+=1){let O=C[S];o.replacer&&(O=o.replacer.call(C,String(S),O)),(y(o,h+1,O,!0,!0,!1,!0)||typeof O>"u"&&y(o,h+1,null,!0,!0,!1,!0))&&((!b||A!=="")&&(A+=ue(o,h)),o.dump&&c===o.dump.charCodeAt(0)?A+="-":A+="- ",A+=o.dump)}o.tag=_,o.dump=A||"[]"}function hn(o,h,C){let b="",A=o.tag,_=Object.keys(C);for(let S=0,L=_.length;S<L;S+=1){let O="";b!==""&&(O+=", "),o.condenseFlow&&(O+='"');let D=_[S],U=C[D];o.replacer&&(U=o.replacer.call(C,D,U)),y(o,h,D,!1,!1)&&(o.dump.length>1024&&(O+="? "),O+=o.dump+(o.condenseFlow?'"':"")+":"+(o.condenseFlow?"":" "),y(o,h,U,!1,!1)&&(O+=o.dump,b+=O))}o.tag=A,o.dump="{"+b+"}"}function e(o,h,C,b){let A="",_=o.tag,S=Object.keys(C);if(o.sortKeys===!0)S.sort();else if(typeof o.sortKeys=="function")S.sort(o.sortKeys);else if(o.sortKeys)throw new t("sortKeys must be a boolean or a function");for(let L=0,O=S.length;L<O;L+=1){let D="";(!b||A!=="")&&(D+=ue(o,h));let U=S[L],Y=C[U];if(o.replacer&&(Y=o.replacer.call(C,U,Y)),!y(o,h+1,U,!0,!0,!0))continue;let W=o.tag!==null&&o.tag!=="?"||o.dump&&o.dump.length>1024;W&&(o.dump&&c===o.dump.charCodeAt(0)?D+="?":D+="? "),D+=o.dump,W&&(D+=ue(o,h)),y(o,h+1,Y,!0,W)&&(o.dump&&c===o.dump.charCodeAt(0)?D+=":":D+=": ",D+=o.dump,A+=D)}o.tag=_,o.dump=A||"{}"}function d(o,h,C){let b=C?o.explicitTypes:o.implicitTypes;for(let A=0,_=b.length;A<_;A+=1){let S=b[A];if((S.instanceOf||S.predicate)&&(!S.instanceOf||typeof h=="object"&&h instanceof S.instanceOf)&&(!S.predicate||S.predicate(h))){if(C?S.multi&&S.representName?o.tag=S.representName(h):o.tag=S.tag:o.tag="?",S.represent){let L=o.styleMap[S.tag]||S.defaultStyle,O;if(r.call(S.represent)==="[object Function]")O=S.represent(h,L);else if(a.call(S.represent,L))O=S.represent[L](h,L);else throw new t("!<"+S.tag+'> tag resolver accepts not "'+L+'" style');o.dump=O}return!0}}return!1}function y(o,h,C,b,A,_,S){o.tag=null,o.dump=C,d(o,C,!1)||d(o,C,!0);let L=r.call(o.dump),O=b;b&&(b=o.flowLevel<0||o.flowLevel>h);let D=L==="[object Object]"||L==="[object Array]",U,Y;if(D&&(U=o.duplicates.indexOf(C),Y=U!==-1),(o.tag!==null&&o.tag!=="?"||Y||o.indent!==2&&h>0)&&(A=!1),Y&&o.usedDuplicates[U])o.dump="*ref_"+U;else{if(D&&Y&&!o.usedDuplicates[U]&&(o.usedDuplicates[U]=!0),L==="[object Object]")b&&Object.keys(o.dump).length!==0?(e(o,h,o.dump,A),Y&&(o.dump="&ref_"+U+o.dump)):(hn(o,h,o.dump),Y&&(o.dump="&ref_"+U+" "+o.dump));else if(L==="[object Array]")b&&o.dump.length!==0?(o.noArrayIndent&&!S&&h>0?Je(o,h-1,o.dump,A):Je(o,h,o.dump,A),Y&&(o.dump="&ref_"+U+o.dump)):(Ve(o,h,o.dump),Y&&(o.dump="&ref_"+U+" "+o.dump));else if(L==="[object String]")o.tag!=="?"&&fn(o,o.dump,h,_,O);else{if(L==="[object Undefined]")return!1;if(o.skipInvalid)return!1;throw new t("unacceptable kind of an object to dump "+L)}if(o.tag!==null&&o.tag!=="?"){let W=encodeURI(o.tag[0]==="!"?o.tag.slice(1):o.tag).replace(/!/g,"%21");o.tag[0]==="!"?W="!"+W:W.slice(0,18)==="tag:yaml.org,2002:"?W="!!"+W.slice(18):W="!<"+W+">",o.dump=W+" "+o.dump}}return!0}function x(o,h){let C=[],b=[];m(o,C,b);let A=b.length;for(let _=0;_<A;_+=1)h.duplicates.push(C[b[_]]);h.usedDuplicates=new Array(A)}function m(o,h,C){if(o!==null&&typeof o=="object"){let b=h.indexOf(o);if(b!==-1)C.indexOf(b)===-1&&C.push(b);else if(h.push(o),Array.isArray(o))for(let A=0,_=o.length;A<_;A+=1)m(o[A],h,C);else{let A=Object.keys(o);for(let _=0,S=A.length;_<S;_+=1)m(o[A[_]],h,C)}}}function I(o,h){h=h||{};let C=new le(h);C.noRefs||x(o,C);let b=o;return C.replacer&&(b=C.replacer.call({"":b},"",b)),y(C,0,b,!0,!0)?C.dump+`
33
- `:""}return Kn.dump=I,Kn}var oi;function no(){if(oi)return re;oi=1;let n=Xr(),t=eo();function i(r,a){return function(){throw new Error("Function yaml."+r+" is removed in js-yaml 4. Use yaml."+a+" instead, which is now safe by default.")}}return re.Type=se(),re.Schema=ai(),re.FAILSAFE_SCHEMA=ui(),re.JSON_SCHEMA=gi(),re.CORE_SCHEMA=mi(),re.DEFAULT_SCHEMA=Hn(),re.load=n.load,re.loadAll=n.loadAll,re.dump=t.dump,re.YAMLException=je(),re.types={binary:wi(),float:hi(),map:ci(),null:fi(),pairs:Ai(),set:xi(),timestamp:vi(),bool:pi(),int:di(),merge:yi(),omap:bi(),seq:li(),str:si()},re.safeLoad=i("safeLoad","load"),re.safeLoadAll=i("safeLoadAll","loadAll"),re.safeDump=i("safeDump","dump"),re}var to=no(),io=Jr(to),{Type:Fa,Schema:Da,FAILSAFE_SCHEMA:Ba,JSON_SCHEMA:Ua,CORE_SCHEMA:Pa,DEFAULT_SCHEMA:ja,load:Si,loadAll:qa,dump:Ci,YAMLException:Ya,types:za,safeLoad:Ka,safeLoadAll:Ha,safeDump:Ga}=io;var ne=class extends Error{status;detail;requestId;constructor(n,t={}){super(n),this.name=new.target.name,this.status=t.status,this.detail=t.detail,this.requestId=t.requestId}},ro=class extends ne{},oo=class extends ne{},ao=class extends ne{},Gn=class extends ne{};function nn(n,t){if(n&&typeof n=="object"&&"detail"in n){let i=n.detail;if(typeof i=="string")return i}return t}function _i(n,t,i){let r={status:n,detail:t,requestId:i};return n===401||n===403?new ro(nn(t,"Authentication failed"),r):n===404?new oo(nn(t,"Not found"),r):n>=500?new ao(nn(t,"Server error"),r):new ne(nn(t,`Request failed with status ${n}`),r)}function Ii(n){try{return JSON.parse(n)}catch{return n}}var so=class{constructor(n){this.config=n}config;async request(n,t,i={}){let r=new URL(t.startsWith("http")?t:`${this.config.baseUrl}${t}`);if(i.query)for(let[u,f]of Object.entries(i.query))f!=null&&r.searchParams.set(u,String(f));let a={accept:"application/json",...i.headers};this.config.apiKey&&(a["X-API-Key"]=this.config.apiKey);let s;i.body!==void 0&&(a["content-type"]="application/json",s=JSON.stringify(i.body));let l=await fetch(r,{method:n,headers:a,body:s,signal:AbortSignal.timeout(i.timeoutMs??this.config.timeoutMs)}),c=await l.text(),p=c?Ii(c):null;if(!l.ok)throw _i(l.status,p,l.headers.get("x-request-id")??void 0);return p}async upload(n,t,i,r={}){let a=new URL(t.startsWith("http")?t:`${this.config.baseUrl}${t}`),s={accept:"application/json"};this.config.apiKey&&(s["X-API-Key"]=this.config.apiKey);let l=new FormData,c=new Blob([i.bytes],{type:i.contentType});l.append(i.field??"file",c,i.filename);let p=await fetch(a,{method:n,headers:s,body:l,signal:AbortSignal.timeout(r.timeoutMs??this.config.timeoutMs)}),u=await p.text(),f=u?Ii(u):null;if(!p.ok)throw _i(p.status,f,p.headers.get("x-request-id")??void 0);return f}},lo=(()=>{try{return"https://api.joinblok.co"}catch{return"http://127.0.0.1:8001"}})(),co=3e4,uo=3e5;function fo(n){return n.endsWith("/")?n.slice(0,-1):n}function po(n={}){let t=n.baseUrl??process.env.SELDON_BASE_URL??process.env.BLOK_BASE_URL??lo,i=n.apiKey??process.env.SELDON_API_KEY??process.env.BLOK_API_KEY??void 0,r=Number(process.env.SELDON_TIMEOUT_MS??process.env.BLOK_TIMEOUT_MS);return{baseUrl:fo(t),apiKey:i||void 0,timeoutMs:n.timeoutMs??(Number.isFinite(r)&&r>0?r:co),specCacheTtlMs:n.specCacheTtlMs??uo}}var ho=new Set(["get","post","put","patch","delete"]),go="_api_v1_";function mo(n){let t=n.indexOf(go);return t>0?n.slice(0,t):n}function vo(n){let t=new Set,i=n.components?.securitySchemes??{};for(let[r,a]of Object.entries(i))a?.type==="apiKey"&&a?.in==="header"&&t.add(r);return t}function yo(n){let t=n.security;if(!Array.isArray(t))return[];let i=[];for(let r of t)r&&typeof r=="object"&&i.push(...Object.keys(r));return i}var wo=class Fi{constructor(t,i){this.operations=t,this.apiKeySchemes=i}operations;apiKeySchemes;static fromSpec(t){let i=vo(t),r=[];for(let[a,s]of Object.entries(t.paths??{}))for(let[l,c]of Object.entries(s)){if(!ho.has(l))continue;let p=c,u=String(p.operationId??`${l}_${a}`),f=Array.isArray(p.parameters)?p.parameters.map(v=>({name:String(v.name),in:v.in,required:!!v.required,description:typeof v.description=="string"?v.description:void 0,schema:v.schema})):[],g=p.tags;r.push({operationId:u,name:mo(u),method:l.toUpperCase(),path:a,tag:g?.[0],summary:typeof p.summary=="string"?p.summary:void 0,description:typeof p.description=="string"?p.description:void 0,params:f,requestBodySchema:bo(p.requestBody),security:yo(p)})}return new Fi(r,i)}apiKeyOps(){return this.apiKeySchemes.size===0?[]:this.operations.filter(t=>t.security.some(i=>this.apiKeySchemes.has(i)))}get(t){return this.apiKeyOps().find(i=>i.name===t||i.operationId===t)}};function bo(n){if(!n||typeof n!="object")return;let t=n.content;if(t)return t["application/json"]?.schema??Object.values(t)[0]?.schema}function Bi(){if(process.env.BLOK_CACHE_DIR)return process.env.BLOK_CACHE_DIR;let n=Co()||_o();return Di(n,".cache","blok")}function Io(n){let t=Ao("sha256").update(n).digest("hex").slice(0,16);return Di(Bi(),`openapi-${t}.json`)}var ko=class{constructor(n,t=fetch){this.config=n,this.fetchImpl=t}config;fetchImpl;async load(n={}){let t=process.env.BLOK_SPEC_PATH;if(t)try{return JSON.parse(await ki(t,"utf8"))}catch(r){throw new Gn(`Could not read BLOK_SPEC_PATH (${t}): ${String(r)}`)}let i=Io(this.config.baseUrl);if(!n.refresh){let r=await this.readFreshCache(i);if(r)return r}return this.fetchAndCache(i)}async refresh(){return this.load({refresh:!0})}async readFreshCache(n){try{let t=await ki(n,"utf8"),i=JSON.parse(t);return Date.now()-i.ts<=this.config.specCacheTtlMs?i.spec:null}catch{return null}}async fetchAndCache(n){let t=new URL("/openapi.json",`${this.config.baseUrl}/`),i;try{i=await this.fetchImpl(t,{signal:AbortSignal.timeout(this.config.timeoutMs)})}catch(a){throw new Gn(`Could not fetch OpenAPI from ${t.toString()}: ${String(a)}`)}if(!i.ok)throw new Gn(`OpenAPI fetch failed (${i.status}) from ${t.toString()}`,{status:i.status});let r=await i.json();return await this.writeCache(n,r),r}async writeCache(n,t){try{await xo(Bi(),{recursive:!0});let i={ts:Date.now(),spec:t};await So(n,JSON.stringify(i),"utf8")}catch{}}};function Ti(n,t={}){return n.replace(/\{([^}]+)\}/g,(i,r)=>{let a=t[r];if(a===void 0)throw new ne(`Missing path parameter: ${r}`);return encodeURIComponent(String(a))})}var Ui=class{config;client;loader;registry;constructor(n={}){this.config=po(n),this.client=new so(this.config),this.loader=new ko(this.config)}async operations(n={}){if(!this.registry||n.refresh){let t=await this.loader.load(n);this.registry=wo.fromSpec(t)}return this.registry}async apiKeyOps(){return(await this.operations()).apiKeyOps()}async hasOperation(n){return(await this.operations()).get(n)!==void 0}async call(n,t={}){let i=(await this.operations()).get(n);if(!i)throw new ne(`Unknown or non-API-key operation: ${n}`);let r=Ti(i.path,t.path);return this.client.request(i.method,r,{query:t.query,body:t.body,timeoutMs:t.timeoutMs})}async upload(n,t,i={}){let r=(await this.operations()).get(n);if(!r)throw new ne(`Unknown or non-API-key operation: ${n}`);let a=Ti(r.path,i.path);return this.client.upload(r.method,a,t,{timeoutMs:i.timeoutMs})}};function Xn(n,t){if(n.length===0)return"";let i=n.map(c=>t.map(p=>p.cell(c))),r=t.map((c,p)=>Math.max(c.header.length,...i.map(u=>u[p].length))),a=(c,p,u="left")=>u==="right"?c.padStart(p):c.padEnd(p),s=t.map((c,p)=>a(c.header,r[p],c.align)).join(" "),l=i.map(c=>c.map((p,u)=>a(p,r[u],t[u].align)).join(" "));return[s,...l].join(`
33
+ `:""}return Kn.dump=I,Kn}var oi;function no(){if(oi)return re;oi=1;let n=Xr(),t=eo();function i(r,a){return function(){throw new Error("Function yaml."+r+" is removed in js-yaml 4. Use yaml."+a+" instead, which is now safe by default.")}}return re.Type=se(),re.Schema=ai(),re.FAILSAFE_SCHEMA=ui(),re.JSON_SCHEMA=gi(),re.CORE_SCHEMA=mi(),re.DEFAULT_SCHEMA=Hn(),re.load=n.load,re.loadAll=n.loadAll,re.dump=t.dump,re.YAMLException=je(),re.types={binary:wi(),float:hi(),map:ci(),null:fi(),pairs:Ai(),set:xi(),timestamp:vi(),bool:pi(),int:di(),merge:yi(),omap:bi(),seq:li(),str:si()},re.safeLoad=i("safeLoad","load"),re.safeLoadAll=i("safeLoadAll","loadAll"),re.safeDump=i("safeDump","dump"),re}var to=no(),io=Jr(to),{Type:Fa,Schema:Da,FAILSAFE_SCHEMA:Ba,JSON_SCHEMA:Ua,CORE_SCHEMA:Pa,DEFAULT_SCHEMA:ja,load:Si,loadAll:qa,dump:Ci,YAMLException:Ya,types:za,safeLoad:Ka,safeLoadAll:Ha,safeDump:Ga}=io;var ne=class extends Error{status;detail;requestId;constructor(n,t={}){super(n),this.name=new.target.name,this.status=t.status,this.detail=t.detail,this.requestId=t.requestId}},ro=class extends ne{},oo=class extends ne{},ao=class extends ne{},Gn=class extends ne{};function nn(n,t){if(n&&typeof n=="object"&&"detail"in n){let i=n.detail;if(typeof i=="string")return i}return t}function _i(n,t,i){let r={status:n,detail:t,requestId:i};return n===401||n===403?new ro(nn(t,"Authentication failed"),r):n===404?new oo(nn(t,"Not found"),r):n>=500?new ao(nn(t,"Server error"),r):new ne(nn(t,`Request failed with status ${n}`),r)}function Ii(n){try{return JSON.parse(n)}catch{return n}}var so=class{constructor(n){this.config=n}config;async request(n,t,i={}){let r=new URL(t.startsWith("http")?t:`${this.config.baseUrl}${t}`);if(i.query)for(let[u,f]of Object.entries(i.query))f!=null&&r.searchParams.set(u,String(f));let a={accept:"application/json",...i.headers};this.config.apiKey&&(a["X-API-Key"]=this.config.apiKey);let s;i.body!==void 0&&(a["content-type"]="application/json",s=JSON.stringify(i.body));let l=await fetch(r,{method:n,headers:a,body:s,signal:AbortSignal.timeout(i.timeoutMs??this.config.timeoutMs)}),c=await l.text(),p=c?Ii(c):null;if(!l.ok)throw _i(l.status,p,l.headers.get("x-request-id")??void 0);return p}async upload(n,t,i,r={}){let a=new URL(t.startsWith("http")?t:`${this.config.baseUrl}${t}`),s={accept:"application/json"};this.config.apiKey&&(s["X-API-Key"]=this.config.apiKey);let l=new FormData,c=new Blob([i.bytes],{type:i.contentType});l.append(i.field??"file",c,i.filename);let p=await fetch(a,{method:n,headers:s,body:l,signal:AbortSignal.timeout(r.timeoutMs??this.config.timeoutMs)}),u=await p.text(),f=u?Ii(u):null;if(!p.ok)throw _i(p.status,f,p.headers.get("x-request-id")??void 0);return f}},lo=(()=>{try{return"https://api.joinblok.co"}catch{return"http://127.0.0.1:8001"}})(),co=3e4,uo=3e5;function fo(n){return n.endsWith("/")?n.slice(0,-1):n}function po(n={}){let t=n.baseUrl??process.env.SELDON_BASE_URL??process.env.BLOK_BASE_URL??lo,i=n.apiKey??process.env.SELDON_API_KEY??process.env.BLOK_API_KEY??void 0,r=Number(process.env.SELDON_TIMEOUT_MS??process.env.BLOK_TIMEOUT_MS);return{baseUrl:fo(t),apiKey:i||void 0,timeoutMs:n.timeoutMs??(Number.isFinite(r)&&r>0?r:co),specCacheTtlMs:n.specCacheTtlMs??uo}}var ho=new Set(["get","post","put","patch","delete"]),go="_api_v1_";function mo(n){let t=n.indexOf(go);return t>0?n.slice(0,t):n}function vo(n){let t=new Set,i=n.components?.securitySchemes??{};for(let[r,a]of Object.entries(i))a?.type==="apiKey"&&a?.in==="header"&&t.add(r);return t}function yo(n){let t=n.security;if(!Array.isArray(t))return[];let i=[];for(let r of t)r&&typeof r=="object"&&i.push(...Object.keys(r));return i}var wo=class Fi{constructor(t,i){this.operations=t,this.apiKeySchemes=i}operations;apiKeySchemes;static fromSpec(t){let i=vo(t),r=[];for(let[a,s]of Object.entries(t.paths??{}))for(let[l,c]of Object.entries(s)){if(!ho.has(l))continue;let p=c,u=String(p.operationId??`${l}_${a}`),f=Array.isArray(p.parameters)?p.parameters.map(v=>({name:String(v.name),in:v.in,required:!!v.required,description:typeof v.description=="string"?v.description:void 0,schema:v.schema})):[],g=p.tags;r.push({operationId:u,name:mo(u),method:l.toUpperCase(),path:a,tag:g?.[0],summary:typeof p.summary=="string"?p.summary:void 0,description:typeof p.description=="string"?p.description:void 0,params:f,requestBodySchema:bo(p.requestBody),security:yo(p)})}return new Fi(r,i)}apiKeyOps(){return this.apiKeySchemes.size===0?[]:this.operations.filter(t=>t.security.some(i=>this.apiKeySchemes.has(i)))}get(t){return this.apiKeyOps().find(i=>i.name===t||i.operationId===t)}};function bo(n){if(!n||typeof n!="object")return;let t=n.content;if(t)return t["application/json"]?.schema??Object.values(t)[0]?.schema}function Bi(){if(process.env.BLOK_CACHE_DIR)return process.env.BLOK_CACHE_DIR;let n=Co()||_o();return Di(n,".cache","blok")}function Io(n){let t=Ao("sha256").update(n).digest("hex").slice(0,16);return Di(Bi(),`openapi-${t}.json`)}var ko=class{constructor(n,t=fetch){this.config=n,this.fetchImpl=t}config;fetchImpl;async load(n={}){let t=process.env.BLOK_SPEC_PATH;if(t)try{return JSON.parse(await ki(t,"utf8"))}catch(r){throw new Gn(`Could not read BLOK_SPEC_PATH (${t}): ${String(r)}`)}let i=Io(this.config.baseUrl);if(!n.refresh){let r=await this.readFreshCache(i);if(r)return r}return this.fetchAndCache(i)}async refresh(){return this.load({refresh:!0})}async readFreshCache(n){try{let t=await ki(n,"utf8"),i=JSON.parse(t);return Date.now()-i.ts<=this.config.specCacheTtlMs?i.spec:null}catch{return null}}async fetchAndCache(n){let t=process.env.SELDON_OPENAPI_URL??process.env.BLOK_OPENAPI_URL??`${this.config.baseUrl}/`,i=t.endsWith(".json")?new URL(t):new URL("/openapi.json",t),r;try{r=await this.fetchImpl(i,{signal:AbortSignal.timeout(this.config.timeoutMs)})}catch(s){throw new Gn(`Could not fetch OpenAPI from ${i.toString()}: ${String(s)}`)}if(!r.ok)throw new Gn(`OpenAPI fetch failed (${r.status}) from ${i.toString()}`,{status:r.status});let a=await r.json();return await this.writeCache(n,a),a}async writeCache(n,t){try{await xo(Bi(),{recursive:!0});let i={ts:Date.now(),spec:t};await So(n,JSON.stringify(i),"utf8")}catch{}}};function Ti(n,t={}){return n.replace(/\{([^}]+)\}/g,(i,r)=>{let a=t[r];if(a===void 0)throw new ne(`Missing path parameter: ${r}`);return encodeURIComponent(String(a))})}var Ui=class{config;client;loader;registry;constructor(n={}){this.config=po(n),this.client=new so(this.config),this.loader=new ko(this.config)}async operations(n={}){if(!this.registry||n.refresh){let t=await this.loader.load(n);this.registry=wo.fromSpec(t)}return this.registry}async apiKeyOps(){return(await this.operations()).apiKeyOps()}async hasOperation(n){return(await this.operations()).get(n)!==void 0}async call(n,t={}){let i=(await this.operations()).get(n);if(!i)throw new ne(`Unknown or non-API-key operation: ${n}`);let r=Ti(i.path,t.path);return this.client.request(i.method,r,{query:t.query,body:t.body,timeoutMs:t.timeoutMs})}async upload(n,t,i={}){let r=(await this.operations()).get(n);if(!r)throw new ne(`Unknown or non-API-key operation: ${n}`);let a=Ti(r.path,i.path);return this.client.upload(r.method,a,t,{timeoutMs:i.timeoutMs})}};function Xn(n,t){if(n.length===0)return"";let i=n.map(c=>t.map(p=>p.cell(c))),r=t.map((c,p)=>Math.max(c.header.length,...i.map(u=>u[p].length))),a=(c,p,u="left")=>u==="right"?c.padStart(p):c.padEnd(p),s=t.map((c,p)=>a(c.header,r[p],c.align)).join(" "),l=i.map(c=>c.map((p,u)=>a(p,r[u],t[u].align)).join(" "));return[s,...l].join(`
34
34
  `)}function Yi(n,t){return t<=0||n.length<=t?{shown:n,hiddenCount:0}:{shown:n.slice(0,t),hiddenCount:n.length-t}}var Ei={blocker:0,major:1,minor:2,cosmetic:3},Oi={fail:0,blocked:1,timed_out:2},Li={pass:"\u2705",fail:"\u274C",blocked:"\u{1F6AB}",timed_out:"\u231B"},Oo={pass:"PASS",fail:"FAIL",blocked:"BLOCKED",timed_out:"TIMED_OUT"};function Lo(n){let t=n.toLowerCase();return t==="pass"?"pass":t==="fail"?"fail":t==="timed_out"||t==="timedout"?"timed_out":"blocked"}function $o(n){return n?.evidence?.length?n.evidence.map(t=>{let i={file:t.source_path};return typeof t.start_line=="number"&&typeof t.end_line=="number"&&(i.lines={start:t.start_line,end:t.end_line}),t.chunk_hash&&(i.chunkHash=t.chunk_hash),t.note&&(i.note=t.note),i}):[]}function et(n){return n.lines?`\`${n.file}\` (lines ${n.lines.start}-${n.lines.end})`:`\`${n.file}\``}function Mo(n,t,i){let r=[];if(n==="blocked"){let l=t.unmet_preconditions??[];l.length?r.push(`Blocked \u2014 unmet preconditions: ${l.join("; ")}.`):r.push("Blocked before the case could be evaluated.")}else n==="timed_out"&&r.push("The run stalled and never completed; re-run to confirm before triaging.");if(i.length){let l=i.slice(0,3).map(et).join(", ");r.push(`Likely in ${l}.`)}let a=(t.expected??"").trim(),s=(t.actual??"").trim();return a&&s?r.push(`Expected: ${a} Observed: ${s}`):a?r.push(`Expected: ${a}`):s&&r.push(`Observed: ${s}`),r.length===0&&t.acceptance_criterion&&r.push(`Did not satisfy: ${t.acceptance_criterion}`),r.join(" ").trim()}function No(n){if(n.total===0)return"No cases were executed.";let t=Math.round(n.passRate*100),i=[`${n.passed}/${n.total} passed (${t}%)`];return n.failed&&i.push(`${n.failed} failed`),n.blocked&&i.push(`${n.blocked} blocked`),n.timedOut&&i.push(`${n.timedOut} timed out`),i.join(", ")+"."}function Fo(n){let t=n.test_plan??{title:"Untitled plan"},i=new Map;for(let v of t.test_cases??[])i.set(v.id,v);let r=n.experiment_id??"",a=n.report?.plan_title||t.title||"Untitled plan",s=t.open_questions??[];if(!n.report)return{experimentId:r,planTitle:a,status:"not_run",summary:{total:t.test_cases?.length??0,passed:0,failed:0,blocked:0,timedOut:0,passRate:0,headline:"Plan generated; not run yet."},failures:[],passed:[],coverage:{journeysExercised:[],unreachable:[],flakyCaseIds:[]},openQuestions:s};let l=n.report,c=l.case_results??[],p=[],u=[];for(let v of c){let R=Lo(v.verdict);if(R==="pass"){u.push({id:v.test_case_id,title:v.title});continue}let F=$o(i.get(v.test_case_id)),$=v.attempts??1,w=v.passes??0;p.push({id:v.test_case_id,title:v.title,area:i.get(v.test_case_id)?.area,verdict:R,severity:v.severity??void 0,acceptanceCriterion:v.acceptance_criterion,expected:v.expected??void 0,actual:v.actual??void 0,reproductionSteps:v.reproduction_steps??[],unmetPreconditions:v.unmet_preconditions??[],evidence:F,hint:Mo(R,v,F),screenshotUrls:v.screenshot_urls??[],recordingUrl:v.recording_url??void 0,attempts:$,passes:w,flaky:$>1&&w>0&&w<$})}p.sort((v,R)=>{let F=(Oi[v.verdict]??9)-(Oi[R.verdict]??9);if(F!==0)return F;let $=Ei[(v.severity??"").toLowerCase()]??9,w=Ei[(R.severity??"").toLowerCase()]??9;return $-w});let f=l.total_cases??c.length,g={total:f,passed:l.passed??0,failed:l.failed??0,blocked:l.blocked??0,timedOut:l.timed_out??0,passRate:f>0?(l.passed??0)/f:0};return{experimentId:r,planTitle:a,status:"complete",summary:{...g,headline:No(g)},failures:p,passed:u,coverage:{journeysExercised:l.coverage?.journeys_exercised??[],unreachable:l.coverage?.unreachable??[],confidenceNote:l.coverage?.confidence_note??void 0,flakyCaseIds:l.coverage?.flaky_case_ids??[]},narrative:l.summary||void 0,openQuestions:s}}var Do=8,Bo=8,$i=12,zi=5;function Ki(n){let t=n.summary,i=[];t.failed&&i.push(`\u274C${t.failed}`),t.blocked&&i.push(`\u{1F6AB}${t.blocked}`),t.timedOut&&i.push(`\u231B${t.timedOut}`);let r=Math.round(t.passRate*100);return[`${t.passed}/${t.total} passed (${r}%)`,...i].join(" \xB7 ")}function Hi(n){let t=n.failures.map(r=>({verdict:r.verdict,severity:r.severity,id:r.id,title:r.title})),i=n.passed.map(r=>({verdict:"pass",id:r.id,title:r.title}));return[...t,...i]}function Gi(n,t={}){let i=[`Seldon QA \u2014 ${n.planTitle} \xB7 ${Ki(n)}`];if(n.narrative&&i.push("",n.narrative),n.status==="not_run")return i.push("",`Plan has ${n.summary.total} case(s); run it against a URL to produce results.`),i.join(`
35
35
  `);i.push("");for(let s of Hi(n)){let l=Oo[s.verdict].padEnd(Do),c=(s.severity?.toUpperCase()??"").padEnd(Bo);i.push(`${l} ${c} ${s.id} ${s.title}`)}let{shown:r,hiddenCount:a}=t.full?{shown:n.failures,hiddenCount:0}:Yi(n.failures,t.compactLimit??zi);for(let s of r){i.push("",`${s.id} ${s.title}${s.flaky?" (FLAKY)":""}`);let l=(c,p)=>` ${c.padEnd($i)}${p}`;s.acceptanceCriterion&&i.push(l("acceptance:",s.acceptanceCriterion)),s.expected&&i.push(l("expected:",s.expected)),s.actual&&i.push(l("observed:",s.actual)),s.evidence.length&&i.push(l("source:",s.evidence.map(et).join(", "))),s.reproductionSteps.length&&(i.push(l("repro:",s.reproductionSteps[0])),s.reproductionSteps.slice(1).forEach(c=>i.push(" ".repeat(2+$i)+c))),s.screenshotUrls.length&&i.push(l("evidence:",s.screenshotUrls.join(", "))),s.recordingUrl&&i.push(l("recording:",s.recordingUrl)),!s.acceptanceCriterion&&!s.expected&&!s.actual&&!s.evidence.length&&i.push(l("hint:",s.hint))}return a>0&&i.push("",`\u2026 +${a} more \u2014 pass \`full\` to see every detail block.`),n.coverage.unreachable.length&&i.push("",`Not reached: ${n.coverage.unreachable.join("; ")}`),n.coverage.flakyCaseIds.length&&i.push(`Flaky cases: ${n.coverage.flakyCaseIds.join(", ")}`),i.join(`
36
36
  `)}function Wi(n,t={}){let i=[`**Seldon QA \u2014 ${n.planTitle}** \xB7 ${Ki(n)}`];if(n.narrative&&i.push("",`> ${n.narrative}`),n.status==="not_run")return i.push("",`_Plan has ${n.summary.total} case(s); run it against a URL to produce results._`),i.join(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seldonqa/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Seldon - generate QA baselines from any codebase and run them from your terminal (thin client over @blok/sdk).",
5
5
  "type": "module",
6
6
  "bin": {