@getjusto/team-cli 0.0.4 → 0.0.6

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/bin/cli.js +776 -315
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -1,76 +1,7 @@
1
1
  #!/usr/bin/env node
2
- var X={main:{local:"http://localhost:3000",develop:"https://api.bejusto.com",prod:"https://api.getjusto.com"},auth:{local:"http://localhost:4112",develop:"https://auth.service.bejusto.com",prod:"https://auth.service.getjusto.com"},webdata:{local:"http://localhost:4125",develop:"https://webdata.service.bejusto.com",prod:"https://webdatacdn.getjusto.com"},preferences:{local:"http://localhost:4120",develop:"https://preferences.service.bejusto.com",prod:"https://preferences.service.getjusto.com"},buckets:{local:"http://localhost:4106",develop:"https://buckets.service.bejusto.com",prod:"https://buckets.service.getjusto.com"},reservations:{local:"http://localhost:4113",develop:"https://reservations.service.bejusto.com",prod:"https://reservations.service.getjusto.com"},data:{local:"http://localhost:4107",develop:"https://data.service.bejusto.com",prod:"https://data.service.getjusto.com"},finances:{local:"http://localhost:4105",develop:"https://finances.service.bejusto.com",prod:"https://finances.service.getjusto.com"},"url-shortener":{local:"http://localhost:4102",develop:"https://url-shortener.service.bejusto.com",prod:"https://url-shortener.service.getjusto.com"},files:{local:"http://localhost:4108",develop:"https://files.service.bejusto.com",prod:"https://files.service.getjusto.com"},tabs:{local:"http://localhost:4115",develop:"https://tabs.service.bejusto.com",prod:"https://tabs.service.getjusto.com"},commander:{local:"http://localhost:4109",develop:"https://commander.service.bejusto.com",prod:"https://commander.service.getjusto.com"},experiments:{local:"http://localhost:4114",develop:"https://experiments.service.bejusto.com",prod:"https://experiments.service.getjusto.com"},sales:{local:"http://localhost:4117",develop:"https://sales.service.bejusto.com",prod:"https://sales.service.getjusto.com"},delivery:{local:"http://localhost:3410",develop:"https://api-delivery.bejusto.com",prod:"https://api-delivery-2.getjusto.com"},payments:{local:"http://localhost:4118",develop:"https://payments.service.bejusto.com",prod:"https://payments.service.getjusto.com"},addresses:{local:"http://localhost:4051",develop:"https://addresses.service.bejusto.com",prod:"https://addresses.service.getjusto.com"},royalty:{local:"http://localhost:4121",develop:"https://royalty.service.bejusto.com",prod:"https://royalty.service.getjusto.com"},marketing:{local:"http://localhost:4005",develop:"https://marketing.service.bejusto.com",prod:"https://marketing.service.getjusto.com"},api:{local:"http://localhost:4119",develop:"https://api.service.bejusto.com",prod:"https://api.service.getjusto.com"},messenger:{local:"http://localhost:4122",develop:"https://messenger.service.bejusto.com",prod:"https://messenger.service.getjusto.com"},invoice:{local:"http://localhost:4123",develop:"https://invoice.service.bejusto.com",prod:"https://invoice.service.getjusto.com"},"drivers-server":{local:"http://localhost:3410",develop:"https://api-delivery.bejusto.com",prod:"https://api-delivery-2.getjusto.com"}},L="prod";function lo(o){L=o}function po(){return L}function B(o){return X[o][L]}function wo(o){let t=[],e={},i={};for(let r=0;r<o.length;r++)if(o[r].startsWith("--")&&o[r+1]&&!o[r+1].startsWith("--")){let s=o[r].slice(2);if(e[s]=o[r+1],!i[s])i[s]=[];i[s].push(o[r+1]),r++}else if(o[r].startsWith("--"))e[o[r].slice(2)]="true";else t.push(o[r]);return{positional:t,flags:e,arrayFlags:i}}function J(o,t){let e=o[t];if(!e)throw Error(`--${t} es requerido.`);return e}import{existsSync as to,mkdirSync as bt,readFileSync as qt,writeFileSync as Ct,unlinkSync as It}from"node:fs";import{join as fo}from"node:path";import{homedir as $t}from"node:os";var oo=fo($t(),".justo-team");function eo(){let o=po(),t=o==="prod"?"credentials.json":`credentials.${o}.json`;return fo(oo,t)}function yt(){if(!to(oo))bt(oo,{recursive:!0})}function Y(o){yt(),Ct(eo(),JSON.stringify(o,null,2))}function d(){let o=eo();if(!to(o))return null;try{let t=qt(o,"utf-8");return JSON.parse(t)}catch{return null}}function io(){let o=eo();if(to(o))It(o)}import{existsSync as bo,readFileSync as jt,writeFileSync as ht,mkdirSync as Rt}from"node:fs";import{join as qo}from"node:path";import{homedir as Et}from"node:os";function xt(){let o=qo(Et(),".justo-team"),t=qo(o,"device-id");if(bo(t))return jt(t,"utf-8").trim();let e=crypto.randomUUID();if(!bo(o))Rt(o,{recursive:!0});return ht(t,e),e}var Io={required:({label:o})=>`${o} no es opcional`,notAString:({label:o})=>`${o} no es un texto`,notANumber:({label:o})=>`${o} no es un número`,notAnInteger:({label:o})=>`${o} no es un número entero`,notABoolean:({label:o})=>`${o} no es un valor verdadero o falso`,notAnEmail:({label:o})=>`${o} no es un email`,notAnId:({label:o})=>`${o} no es un ID válido`,notADate:({label:o})=>`${o} no es una fecha válida`,notAnArray:({label:o})=>`${o} no es un arreglo`,notAnObject:({label:o})=>`${o} no es un objeto`,stringTooShort:({label:o})=>`${o} no tiene el largo suficiente`,stringTooLong:"El largo es mayor al permitido",numberTooSmall:({label:o})=>`${o} es un número muy pequeño`,numberTooBig:({label:o})=>`${o} es un número muy grande`,notInSchema:({label:o})=>`${o} no esta permitido`,notUnique:({label:o})=>`${o} no es único`,notFound:({label:o})=>`${o} no se encontró`,invalid:"No es válido",rateLimitExceeded:"Has excedido el límite de intentos. Intenta de nuevo más tarde.",incorrectLoginCode:"El código es incorrecto",loginCodeExpired:"El código expiró. Solicita un nuevo",loginCodeLocked:"El código se bloqueó. Genera un nuevo código para continuar",userNotFound:"No existe una cuenta con este email"};function Ut(o,t){let e=Io[o];if(!e)return`${t}: ${o}`;if(typeof e==="function")return e({label:t});return e}function Co(o){return Object.entries(o).map(([t,e])=>Ut(e,t)).join(", ")}function Pt(o){if(o.error==="validationError"&&o.validationErrors)return Co(o.validationErrors);if(o.extensions?.code==="PermissionsError"){let r=o.extensions.info?.type;if(r?.includes("User doesn't have permissions for "))return`Tu usuario no tiene permisos para [${r.split("User doesn't have permissions for ")[1]}]`;return o.message}if(o.validationErrors)return`${o.message} (${Co(o.validationErrors)})`;let t=o.message||"Error desconocido",e=Io[t];if(e)return typeof e==="function"?e({label:""}).trim():e;let i=o.error||o.code||o.type;return i?`${t} [${i}]`:t}function Nt(o){try{return JSON.parse(Buffer.from(o.split(".")[1],"base64").toString()).exp*1000<Date.now()}catch{return!0}}async function Wt(){let o=d();if(!o?.refreshToken)return null;let t=`${B("auth")}/refresh-token`,i=await(await fetch(t,{method:"POST",headers:{"X-ORION-REFRESH":o.refreshToken}})).json();if(!i.token)return null;return Y({...o,token:i.token}),i.token}async function At(){let o=d();if(!o?.token)return;if(!Nt(o.token))return o.token;return await Wt()??void 0}async function c(o){let t=`${B(o.service)}/graphql`,e=await At(),i={"Content-Type":"application/json","X-ORION-DEVICEID":xt(),"X-ORION-PLATFORM":"web"};if(e)i["x-orion-jwt"]=e;let r;try{r=await fetch(t,{method:"POST",headers:i,body:JSON.stringify({query:o.query,variables:o.variables}),signal:AbortSignal.timeout(15000)})}catch{throw Error("La solicitud tardó demasiado. Intenta de nuevo.")}let s=await r.json();if(s.errors?.length)throw Error(Pt(s.errors[0]));if(!s.data)throw Error("No data returned from server");return s.data}import{createInterface as Ot}from"node:readline";function ro(o){let t=Ot({input:process.stdin,output:process.stderr});return new Promise((e)=>{t.question(o,(i)=>{t.close(),e(i.trim())})})}var St={comma:",",tab:"\t",pipe:"|"},F=St.comma;function yo(o){return o.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function Qt(o){return o==="true"||o==="false"||o==="null"}function h(o){if(o===null)return null;if(typeof o==="object"&&o!==null&&"toJSON"in o&&typeof o.toJSON==="function"){let t=o.toJSON();if(t!==o)return h(t)}if(typeof o==="string"||typeof o==="boolean")return o;if(typeof o==="number"){if(Object.is(o,-0))return 0;if(!Number.isFinite(o))return null;return o}if(typeof o==="bigint"){if(o>=Number.MIN_SAFE_INTEGER&&o<=Number.MAX_SAFE_INTEGER)return Number(o);return o.toString()}if(o instanceof Date)return o.toISOString();if(Array.isArray(o))return o.map(h);if(o instanceof Set)return Array.from(o).map(h);if(o instanceof Map)return Object.fromEntries(Array.from(o,([t,e])=>[String(t),h(e)]));if(Gt(o)){let t={};for(let e in o)if(Object.prototype.hasOwnProperty.call(o,e))t[e]=h(o[e]);return t}return null}function N(o){return o===null||typeof o==="string"||typeof o==="number"||typeof o==="boolean"}function U(o){return Array.isArray(o)}function w(o){return o!==null&&typeof o==="object"&&!Array.isArray(o)}function v(o){return Object.keys(o).length===0}function Gt(o){if(o===null||typeof o!=="object")return!1;let t=Object.getPrototypeOf(o);return t===null||t===Object.prototype}function T(o){return o.length===0||o.every((t)=>N(t))}function Bt(o){return o.length===0||o.every((t)=>U(t))}function jo(o){return o.length===0||o.every((t)=>w(t))}function Jt(o){return/^[A-Z_][\w.]*$/i.test(o)}function vt(o){return/^[A-Z_]\w*$/i.test(o)}function Tt(o,t=F){if(!o)return!1;if(o!==o.trim())return!1;if(Qt(o)||_t(o))return!1;if(o.includes(":"))return!1;if(o.includes('"')||o.includes("\\"))return!1;if(/[[\]{}]/.test(o))return!1;if(/[\n\r\t]/.test(o))return!1;if(o.includes(t))return!1;if(o.startsWith("-"))return!1;return!0}function _t(o){return/^-?\d+(?:\.\d+)?(?:e[+-]?\d+)?$/i.test(o)||/^0\d+$/.test(o)}var Be=Symbol("quotedKey");function Ft(o,t,e,i,r,s,n){if(i.keyFolding!=="safe")return;if(!w(t))return;let{segments:a,tail:u,leafValue:y}=Mt(o,t,n??i.flattenDepth);if(a.length<2)return;if(!a.every((j)=>vt(j)))return;let b=Xt(a),q=s?`${s}.${b}`:b;if(e.includes(b))return;if(r&&r.has(q))return;return{foldedKey:b,remainder:u,leafValue:y,segmentCount:a.length}}function Mt(o,t,e){let i=[o],r=t;while(i.length<e){if(!w(r))break;let s=Object.keys(r);if(s.length!==1)break;let n=s[0],a=r[n];i.push(n),r=a}if(!w(r)||v(r))return{segments:i,tail:void 0,leafValue:r};return{segments:i,tail:r,leafValue:r}}function Xt(o){return o.join(".")}function A(o,t){if(o===null)return"null";if(typeof o==="boolean")return String(o);if(typeof o==="number")return String(o);return Yt(o,t)}function Yt(o,t=F){if(Tt(o,t))return o;return`"${yo(o)}"`}function _(o){if(Jt(o))return o;return`"${yo(o)}"`}function ho(o,t=F){return o.map((e)=>A(e,t)).join(t)}function R(o,t){let e=t?.key,i=t?.fields,r=t?.delimiter??",",s="";if(e)s+=_(e);if(s+=`[${o}${r!==F?r:""}]`,i){let n=i.map((a)=>_(a));s+=`{${n.join(r)}}`}return s+=":",s}function*Zt(o,t,e){if(N(o)){let i=A(o,t.delimiter);if(i!=="")yield i;return}if(U(o))yield*so(void 0,o,e,t);else if(w(o))yield*W(o,e,t)}function*W(o,t,e,i,r,s){let n=Object.keys(o);if(t===0&&!i)i=new Set(n.filter((u)=>u.includes(".")));let a=s??e.flattenDepth;for(let[u,y]of Object.entries(o))yield*zt(u,y,t,e,n,i,r,a)}function*zt(o,t,e,i,r,s,n,a){let u=n?`${n}.${o}`:o,y=a??i.flattenDepth;if(i.keyFolding==="safe"&&r){let q=Ft(o,t,r,i,s,n,y);if(q){let{foldedKey:j,remainder:G,leafValue:x,segmentCount:pt}=q,V=_(j);if(G===void 0){if(N(x)){yield p(e,`${V}: ${A(x,i.delimiter)}`,i.indent);return}else if(U(x)){yield*so(j,x,e,i);return}else if(w(x)&&v(x)){yield p(e,`${V}:`,i.indent);return}}if(w(G)){yield p(e,`${V}:`,i.indent);let wt=y-pt,ft=n?`${n}.${j}`:j;yield*W(G,e+1,i,s,ft,wt);return}}}let b=_(o);if(N(t))yield p(e,`${b}: ${A(t,i.delimiter)}`,i.indent);else if(U(t))yield*so(o,t,e,i);else if(w(t)){if(yield p(e,`${b}:`,i.indent),!v(t))yield*W(t,e+1,i,s,u,y)}}function*so(o,t,e,i){if(t.length===0){yield p(e,R(0,{key:o,delimiter:i.delimiter}),i.indent);return}if(T(t)){yield p(e,z(t,i.delimiter,o),i.indent);return}if(Bt(t)){if(t.every((r)=>T(r))){yield*Ht(o,t,e,i);return}}if(jo(t)){let r=Ro(t);if(r)yield*Dt(o,t,r,e,i);else yield*$o(o,t,e,i);return}yield*$o(o,t,e,i)}function*Ht(o,t,e,i){yield p(e,R(t.length,{key:o,delimiter:i.delimiter}),i.indent);for(let r of t)if(T(r)){let s=z(r,i.delimiter);yield C(e+1,s,i.indent)}}function z(o,t,e){let i=R(o.length,{key:e,delimiter:t}),r=ho(o,t);if(o.length===0)return i;return`${i} ${r}`}function*Dt(o,t,e,i,r){yield p(i,R(t.length,{key:o,fields:e,delimiter:r.delimiter}),r.indent),yield*Eo(t,e,i+1,r)}function Ro(o){if(o.length===0)return;let t=o[0],e=Object.keys(t);if(e.length===0)return;if(kt(o,e))return e}function kt(o,t){for(let e of o){if(Object.keys(e).length!==t.length)return!1;for(let i of t){if(!(i in e))return!1;if(!N(e[i]))return!1}}return!0}function*Eo(o,t,e,i){for(let r of o)yield p(e,ho(t.map((s)=>r[s]),i.delimiter),i.indent)}function*$o(o,t,e,i){yield p(e,R(t.length,{key:o,delimiter:i.delimiter}),i.indent);for(let r of t)yield*no(r,e+1,i)}function*Kt(o,t,e){if(v(o)){yield p(t,"-",e.indent);return}let i=Object.entries(o),[r,s]=i[0],n=i.slice(1);if(U(s)&&jo(s)){let u=Ro(s);if(u){if(yield C(t,R(s.length,{key:r,fields:u,delimiter:e.delimiter}),e.indent),yield*Eo(s,u,t+2,e),n.length>0)yield*W(Object.fromEntries(n),t+1,e);return}}let a=_(r);if(N(s))yield C(t,`${a}: ${A(s,e.delimiter)}`,e.indent);else if(U(s))if(s.length===0)yield C(t,`${a}${R(0,{delimiter:e.delimiter})}`,e.indent);else if(T(s))yield C(t,`${a}${z(s,e.delimiter)}`,e.indent);else{yield C(t,`${a}${R(s.length,{delimiter:e.delimiter})}`,e.indent);for(let u of s)yield*no(u,t+2,e)}else if(w(s)){if(yield C(t,`${a}:`,e.indent),!v(s))yield*W(s,t+2,e)}if(n.length>0)yield*W(Object.fromEntries(n),t+1,e)}function*no(o,t,e){if(N(o))yield C(t,A(o,e.delimiter),e.indent);else if(U(o))if(T(o))yield C(t,z(o,e.delimiter),e.indent);else{yield C(t,R(o.length,{delimiter:e.delimiter}),e.indent);for(let i of o)yield*no(i,t+1,e)}else if(w(o))yield*Kt(o,t,e)}function p(o,t,e){return" ".repeat(e*o)+t}function C(o,t,e){return p(o,"- "+t,e)}function Vt(o,t){let e=t("",o,[]);if(e===void 0)return Z(o,t,[]);return Z(h(e),t,[])}function Z(o,t,e){if(w(o))return Lt(o,t,e);if(U(o))return oe(o,t,e);return o}function Lt(o,t,e){let i={};for(let[r,s]of Object.entries(o)){let n=[...e,r],a=t(r,s,n);if(a===void 0)continue;i[r]=Z(h(a),t,n)}return i}function oe(o,t,e){let i=[];for(let r=0;r<o.length;r++){let s=o[r],n=[...e,r],a=t(String(r),s,n);if(a===void 0)continue;let u=h(a);i.push(Z(u,t,n))}return i}function ao(o,t){return Array.from(te(o,t)).join(`
3
- `)}function te(o,t){let e=h(o),i=ee(t);return Zt(i.replacer?Vt(e,i.replacer):e,i,0)}function ee(o){return{indent:o?.indent??2,delimiter:o?.delimiter??F,keyFolding:o?.keyFolding??"off",flattenDepth:o?.flattenDepth??Number.POSITIVE_INFINITY,replacer:o?.replacer}}function ie(o){let t=o.format??"toon";if(t!=="toon"&&t!=="json")throw Error("--format debe ser toon o json.");return t}function xo(o,t){if(ie(t)==="json"){console.log(JSON.stringify(o,null,2));return}console.log(ao(o))}function g(o){process.stdout.write(`${o}
4
- `)}function Uo(o,t){let i={ok:!1,error:o instanceof Error?o.message:String(o)};if((t.format==="json"?"json":"toon")==="json"){console.error(JSON.stringify(i,null,2));return}console.error(ao(i))}function I(o){process.stderr.write(o)}async function Po(o){return(await c({service:"auth",query:`mutation ($email: String!) {
5
- requestLoginCode(email: $email)
6
- }`,variables:{email:o}})).requestLoginCode}async function No(o,t,e){let i=await c({service:"auth",query:`mutation ($email: String!, $token: String!, $code: String!) {
7
- loginWithCode(email: $email, token: $token, code: $code) {
8
- token
9
- refreshToken
10
- }
11
- }`,variables:{email:o,token:t,code:e.toUpperCase()}});Y({email:o,token:i.loginWithCode.token,refreshToken:i.loginWithCode.refreshToken}),await re()}async function re(){if(!(await c({service:"main",query:"query { me { roles } }"})).me?.roles?.length)throw io(),Error("Solo miembros del equipo Justo pueden usar esta herramienta.")}async function Wo(){let o=await ro("Email: ");I(`Enviando codigo de verificacion...
12
- `);let t=await Po(o);I(`Codigo enviado a tu email.
13
- `);let e=await ro("Codigo: ");return await No(o,t,e),{ok:!0,authenticated:!0,email:o}}async function Ao(o){let t=J(o,"email"),e=J(o,"token"),i=J(o,"code");return await No(t,e,i),{ok:!0,authenticated:!0,email:t}}async function Oo(o){let t=J(o,"email");I(`Enviando codigo de verificacion...
14
- `);let e=await Po(t);return{ok:!0,email:t,token:e,nextCommand:`npx @getjusto/team-cli auth login-with-token --email ${t} --token ${e} --code <CODIGO>`}}async function So(){return io(),{ok:!0,authenticated:!1}}async function Qo(){let o=d();if(!o)return{authenticated:!1,loginCommand:"npx @getjusto/team-cli@latest auth login"};return{authenticated:!0,email:o.email}}function co(){return`team-cli auth
15
-
16
- Gestion de sesion.
17
-
18
- Uso:
19
- team-cli auth <subcomando> [opciones]
20
-
21
- Subcomandos:
22
- login
23
- Iniciar sesion en modo interactivo.
24
- Uso: team-cli auth login
25
-
26
- logout
27
- Cerrar sesion actual.
28
- Uso: team-cli auth logout
29
-
30
- status
31
- Ver la sesion actual.
32
- Uso: team-cli auth status
33
-
34
- request-code
35
- Solicitar codigo para login no interactivo.
36
- Uso: team-cli auth request-code --email <email>
37
-
38
- login-with-token
39
- Iniciar sesion sin prompts.
40
- Uso: team-cli auth login-with-token --email <email> --token <token> --code <codigo>`}var mo=["main","auth","webdata","preferences","buckets","reservations","data","finances","url-shortener","files","tabs","commander","experiments","sales","delivery","payments","addresses","royalty","marketing","api","messenger","invoice","drivers-server"],Go=`
41
- query ResolverInfo($name: ID!, $mutation: Boolean!) {
42
- params(name: $name, mutation: $mutation) {
43
- name
44
- params
45
- result
46
- basicResultQuery
47
- }
48
- }
49
- `;function se(o){if(!o)throw Error("Uso: team-cli graphql <servicio> '<query>' [--variables '<json>'] [--format toon|json]");if(!mo.includes(o))throw Error(`Servicio "${o}" no válido. Servicios disponibles: ${mo.join(", ")}`)}async function ne(o,t){let e;try{let i=await c({service:o,query:Go,variables:{name:t,mutation:!1}});return{service:o,operationName:t,operationType:"query",info:i.params}}catch(i){e=i}try{let i=await c({service:o,query:Go,variables:{name:t,mutation:!0}});return{service:o,operationName:t,operationType:"mutation",info:i.params}}catch(i){let r=e instanceof Error?e.message:"",s=i instanceof Error?i.message:"";if(r.includes('Cannot query field "params"')||s.includes('Cannot query field "params"'))throw Error(`El servicio "${o}" no expone metadata de resolvers por GraphQL.`);throw e instanceof Error?e:i}}async function Bo(o,t){let e=o[1],i=o[2],r=o[2];if(!d())throw Error("Debes iniciar sesión primero. Usa: team-cli auth login");if(se(e),i==="info"){let a=o[3];if(!a)throw Error("Uso: team-cli graphql <servicio> info <queryName|mutationName> [--format toon|json]");return await ne(e,a)}if(!r)throw Error("Uso: team-cli graphql <servicio> '<query>' [--variables '<json>'] [--format toon|json]");let s;if(t.variables)try{s=JSON.parse(t.variables)}catch{throw Error("Las variables deben ser un JSON válido.")}return await c({service:e,query:r,variables:s})}function Jo(){return`team-cli graphql
50
-
51
- Ejecutar queries y mutations GraphQL.
52
-
53
- Uso:
54
- team-cli graphql <servicio> '<query>' [--variables '<json>'] [--format toon|json]
55
- team-cli graphql <servicio> info <queryName|mutationName> [--format toon|json]
56
-
57
- Ejemplos:
58
- team-cli graphql main 'query { me { _id roles } }'
59
- team-cli graphql main 'query($id: ID) { user(userId: $id) { _id } }' --variables '{"id": "abc123"}'
60
- team-cli graphql main 'query { me { _id } }' --format json
61
- team-cli graphql main info website
62
- team-cli graphql webdata info setWebsiteTheme --format json
63
-
64
- Servicios disponibles:
65
- ${mo.join(", ")}
66
-
67
- Comando info:
68
- Consulta la metadata publicada por OrionJS para un query o mutation.
69
- Devuelve el tipo de operación, los params serializados, el resultado y un basicResultQuery.
70
- Si no indicas si es query o mutation, la CLI prueba ambas automáticamente.
71
-
72
- Formato:
73
- Por defecto usa toon. Usa --format json para JSON estándar.`}function ae(o){return o.replace(/^https?:\/\//,"").replace(/^www\./,"").replace(/\/.*$/,"")}function ce(o){return o.includes(".")||o.startsWith("http://")||o.startsWith("https://")}async function O(o){if(ce(o)){let t=ae(o),e=await fetch(`${B("main")}/website-id/${t}`,{signal:AbortSignal.timeout(1e4)});if(!e.ok)throw Error(`No se encontro el sitio "${t}"`);let i=await e.json();if(!i.websiteId)throw Error(`No se pudo resolver el websiteId para "${t}"`);return{input:o,websiteId:i.websiteId,targetType:"domain"}}return{input:o,websiteId:o,targetType:"websiteId"}}async function vo(o){let t=await c({service:"main",query:`query ($websiteId: ID) {
2
+ function L(e){let t=[],o={},r={};for(let a=0;a<e.length;a++)if(e[a].startsWith("--")&&e[a+1]&&!e[a+1].startsWith("--")){let i=e[a].slice(2);if(o[i]=e[a+1],!r[i])r[i]=[];r[i].push(e[a+1]),a++}else if(e[a].startsWith("--"))o[e[a].slice(2)]="true";else t.push(e[a]);return{positional:t,flags:o,arrayFlags:r}}function G(e,t){let o=e[t];if(!o)throw Error(`--${t} es requerido.`);return o}var Oo={comma:",",tab:"\t",pipe:"|"},H=Oo.comma;function We(e){return e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function To(e){return e==="true"||e==="false"||e==="null"}function E(e){if(e===null)return null;if(typeof e==="object"&&e!==null&&"toJSON"in e&&typeof e.toJSON==="function"){let t=e.toJSON();if(t!==e)return E(t)}if(typeof e==="string"||typeof e==="boolean")return e;if(typeof e==="number"){if(Object.is(e,-0))return 0;if(!Number.isFinite(e))return null;return e}if(typeof e==="bigint"){if(e>=Number.MIN_SAFE_INTEGER&&e<=Number.MAX_SAFE_INTEGER)return Number(e);return e.toString()}if(e instanceof Date)return e.toISOString();if(Array.isArray(e))return e.map(E);if(e instanceof Set)return Array.from(e).map(E);if(e instanceof Map)return Object.fromEntries(Array.from(e,([t,o])=>[String(t),E(o)]));if(Uo(e)){let t={};for(let o in e)if(Object.prototype.hasOwnProperty.call(e,o))t[o]=E(e[o]);return t}return null}function U(e){return e===null||typeof e==="string"||typeof e==="number"||typeof e==="boolean"}function O(e){return Array.isArray(e)}function q(e){return e!==null&&typeof e==="object"&&!Array.isArray(e)}function P(e){return Object.keys(e).length===0}function Uo(e){if(e===null||typeof e!=="object")return!1;let t=Object.getPrototypeOf(e);return t===null||t===Object.prototype}function F(e){return e.length===0||e.every((t)=>U(t))}function Qo(e){return e.length===0||e.every((t)=>O(t))}function Me(e){return e.length===0||e.every((t)=>q(t))}function Jo(e){return/^[A-Z_][\w.]*$/i.test(e)}function Wo(e){return/^[A-Z_]\w*$/i.test(e)}function Mo(e,t=H){if(!e)return!1;if(e!==e.trim())return!1;if(To(e)||_o(e))return!1;if(e.includes(":"))return!1;if(e.includes('"')||e.includes("\\"))return!1;if(/[[\]{}]/.test(e))return!1;if(/[\n\r\t]/.test(e))return!1;if(e.includes(t))return!1;if(e.startsWith("-"))return!1;return!0}function _o(e){return/^-?\d+(?:\.\d+)?(?:e[+-]?\d+)?$/i.test(e)||/^0\d+$/.test(e)}var Aa=Symbol("quotedKey");function Bo(e,t,o,r,a,i,n){if(r.keyFolding!=="safe")return;if(!q(t))return;let{segments:s,tail:c,leafValue:u}=Go(e,t,n??r.flattenDepth);if(s.length<2)return;if(!s.every((p)=>Wo(p)))return;let l=Po(s),g=i?`${i}.${l}`:l;if(o.includes(l))return;if(a&&a.has(g))return;return{foldedKey:l,remainder:c,leafValue:u,segmentCount:s.length}}function Go(e,t,o){let r=[e],a=t;while(r.length<o){if(!q(a))break;let i=Object.keys(a);if(i.length!==1)break;let n=i[0],s=a[n];r.push(n),a=s}if(!q(a)||P(a))return{segments:r,tail:void 0,leafValue:a};return{segments:r,tail:a,leafValue:a}}function Po(e){return e.join(".")}function W(e,t){if(e===null)return"null";if(typeof e==="boolean")return String(e);if(typeof e==="number")return String(e);return Fo(e,t)}function Fo(e,t=H){if(Mo(e,t))return e;return`"${We(e)}"`}function X(e){if(Jo(e))return e;return`"${We(e)}"`}function _e(e,t=H){return e.map((o)=>W(o,t)).join(t)}function j(e,t){let o=t?.key,r=t?.fields,a=t?.delimiter??",",i="";if(o)i+=X(o);if(i+=`[${e}${a!==H?a:""}]`,r){let n=r.map((s)=>X(s));i+=`{${n.join(a)}}`}return i+=":",i}function*Xo(e,t,o){if(U(e)){let r=W(e,t.delimiter);if(r!=="")yield r;return}if(O(e))yield*fe(void 0,e,o,t);else if(q(e))yield*J(e,o,t)}function*J(e,t,o,r,a,i){let n=Object.keys(e);if(t===0&&!r)r=new Set(n.filter((c)=>c.includes(".")));let s=i??o.flattenDepth;for(let[c,u]of Object.entries(e))yield*Ho(c,u,t,o,n,r,a,s)}function*Ho(e,t,o,r,a,i,n,s){let c=n?`${n}.${e}`:e,u=s??r.flattenDepth;if(r.keyFolding==="safe"&&a){let g=Bo(e,t,a,r,i,n,u);if(g){let{foldedKey:p,remainder:C,leafValue:w,segmentCount:V}=g,Q=X(p);if(C===void 0){if(U(w)){yield b(o,`${Q}: ${W(w,r.delimiter)}`,r.indent);return}else if(O(w)){yield*fe(p,w,o,r);return}else if(q(w)&&P(w)){yield b(o,`${Q}:`,r.indent);return}}if(q(C)){yield b(o,`${Q}:`,r.indent);let v=u-V,B=n?`${n}.${p}`:p;yield*J(C,o+1,r,i,B,v);return}}}let l=X(e);if(U(t))yield b(o,`${l}: ${W(t,r.delimiter)}`,r.indent);else if(O(t))yield*fe(e,t,o,r);else if(q(t)){if(yield b(o,`${l}:`,r.indent),!P(t))yield*J(t,o+1,r,i,c,u)}}function*fe(e,t,o,r){if(t.length===0){yield b(o,j(0,{key:e,delimiter:r.delimiter}),r.indent);return}if(F(t)){yield b(o,te(t,r.delimiter,e),r.indent);return}if(Qo(t)){if(t.every((a)=>F(a))){yield*Yo(e,t,o,r);return}}if(Me(t)){let a=Be(t);if(a)yield*Zo(e,t,a,o,r);else yield*Je(e,t,o,r);return}yield*Je(e,t,o,r)}function*Yo(e,t,o,r){yield b(o,j(t.length,{key:e,delimiter:r.delimiter}),r.indent);for(let a of t)if(F(a)){let i=te(a,r.delimiter);yield h(o+1,i,r.indent)}}function te(e,t,o){let r=j(e.length,{key:o,delimiter:t}),a=_e(e,t);if(e.length===0)return r;return`${r} ${a}`}function*Zo(e,t,o,r,a){yield b(r,j(t.length,{key:e,fields:o,delimiter:a.delimiter}),a.indent),yield*Ge(t,o,r+1,a)}function Be(e){if(e.length===0)return;let t=e[0],o=Object.keys(t);if(o.length===0)return;if(Do(e,o))return o}function Do(e,t){for(let o of e){if(Object.keys(o).length!==t.length)return!1;for(let r of t){if(!(r in o))return!1;if(!U(o[r]))return!1}}return!0}function*Ge(e,t,o,r){for(let a of e)yield b(o,_e(t.map((i)=>a[i]),r.delimiter),r.indent)}function*Je(e,t,o,r){yield b(o,j(t.length,{key:e,delimiter:r.delimiter}),r.indent);for(let a of t)yield*we(a,o+1,r)}function*zo(e,t,o){if(P(e)){yield b(t,"-",o.indent);return}let r=Object.entries(e),[a,i]=r[0],n=r.slice(1);if(O(i)&&Me(i)){let c=Be(i);if(c){if(yield h(t,j(i.length,{key:a,fields:c,delimiter:o.delimiter}),o.indent),yield*Ge(i,c,t+2,o),n.length>0)yield*J(Object.fromEntries(n),t+1,o);return}}let s=X(a);if(U(i))yield h(t,`${s}: ${W(i,o.delimiter)}`,o.indent);else if(O(i))if(i.length===0)yield h(t,`${s}${j(0,{delimiter:o.delimiter})}`,o.indent);else if(F(i))yield h(t,`${s}${te(i,o.delimiter)}`,o.indent);else{yield h(t,`${s}${j(i.length,{delimiter:o.delimiter})}`,o.indent);for(let c of i)yield*we(c,t+2,o)}else if(q(i)){if(yield h(t,`${s}:`,o.indent),!P(i))yield*J(i,t+2,o)}if(n.length>0)yield*J(Object.fromEntries(n),t+1,o)}function*we(e,t,o){if(U(e))yield h(t,W(e,o.delimiter),o.indent);else if(O(e))if(F(e))yield h(t,te(e,o.delimiter),o.indent);else{yield h(t,j(e.length,{delimiter:o.delimiter}),o.indent);for(let r of e)yield*we(r,t+1,o)}else if(q(e))yield*zo(e,t,o)}function b(e,t,o){return" ".repeat(o*e)+t}function h(e,t,o){return b(e,"- "+t,o)}function ko(e,t){let o=t("",e,[]);if(o===void 0)return ee(e,t,[]);return ee(E(o),t,[])}function ee(e,t,o){if(q(e))return Ko(e,t,o);if(O(e))return Vo(e,t,o);return e}function Ko(e,t,o){let r={};for(let[a,i]of Object.entries(e)){let n=[...o,a],s=t(a,i,n);if(s===void 0)continue;r[a]=ee(E(s),t,n)}return r}function Vo(e,t,o){let r=[];for(let a=0;a<e.length;a++){let i=e[a],n=[...o,a],s=t(String(a),i,n);if(s===void 0)continue;let c=E(s);r.push(ee(c,t,n))}return r}function be(e,t){return Array.from(Lo(e,t)).join(`
3
+ `)}function Lo(e,t){let o=E(e),r=er(t);return Xo(r.replacer?ko(o,r.replacer):o,r,0)}function er(e){return{indent:e?.indent??2,delimiter:e?.delimiter??H,keyFolding:e?.keyFolding??"off",flattenDepth:e?.flattenDepth??Number.POSITIVE_INFINITY,replacer:e?.replacer}}function tr(e){let t=e.format??"toon";if(t!=="toon"&&t!=="json")throw Error("--format debe ser toon o json.");return t}function Pe(e,t){if(tr(t)==="json"){console.log(JSON.stringify(e,null,2));return}console.log(be(e))}function Fe(e){process.stdout.write(`${e}
4
+ `)}function Xe(e,t){let r={ok:!1,error:e instanceof Error?e.message:String(e)};if((t.format==="json"?"json":"toon")==="json"){console.error(JSON.stringify(r,null,2));return}console.error(be(r))}function y(e){process.stderr.write(e)}import{existsSync as ae,mkdirSync as ar,readFileSync as Ye,writeFileSync as ir,unlinkSync as nr}from"node:fs";import{join as Ze}from"node:path";import{homedir as sr}from"node:os";import{AsyncLocalStorage as or}from"node:async_hooks";var rr=new or;function I(){return rr.getStore()}var oe={main:{local:"http://localhost:3000",develop:"https://api.bejusto.com",prod:"https://api.getjusto.com"},auth:{local:"http://localhost:4112",develop:"https://auth.service.bejusto.com",prod:"https://auth.service.getjusto.com"},webdata:{local:"http://localhost:4125",develop:"https://webdata.service.bejusto.com",prod:"https://webdatacdn.getjusto.com"},preferences:{local:"http://localhost:4120",develop:"https://preferences.service.bejusto.com",prod:"https://preferences.service.getjusto.com"},buckets:{local:"http://localhost:4106",develop:"https://buckets.service.bejusto.com",prod:"https://buckets.service.getjusto.com"},reservations:{local:"http://localhost:4113",develop:"https://reservations.service.bejusto.com",prod:"https://reservations.service.getjusto.com"},data:{local:"http://localhost:4107",develop:"https://data.service.bejusto.com",prod:"https://data.service.getjusto.com"},finances:{local:"http://localhost:4105",develop:"https://finances.service.bejusto.com",prod:"https://finances.service.getjusto.com"},"url-shortener":{local:"http://localhost:4102",develop:"https://url-shortener.service.bejusto.com",prod:"https://url-shortener.service.getjusto.com"},files:{local:"http://localhost:4108",develop:"https://files.service.bejusto.com",prod:"https://files.service.getjusto.com"},tabs:{local:"http://localhost:4115",develop:"https://tabs.service.bejusto.com",prod:"https://tabs.service.getjusto.com"},commander:{local:"http://localhost:4109",develop:"https://commander.service.bejusto.com",prod:"https://commander.service.getjusto.com"},experiments:{local:"http://localhost:4114",develop:"https://experiments.service.bejusto.com",prod:"https://experiments.service.getjusto.com"},sales:{local:"http://localhost:4117",develop:"https://sales.service.bejusto.com",prod:"https://sales.service.getjusto.com"},delivery:{local:"http://localhost:3410",develop:"https://api-delivery.bejusto.com",prod:"https://api-delivery-2.getjusto.com"},payments:{local:"http://localhost:4118",develop:"https://payments.service.bejusto.com",prod:"https://payments.service.getjusto.com"},addresses:{local:"http://localhost:4051",develop:"https://addresses.service.bejusto.com",prod:"https://addresses.service.getjusto.com"},royalty:{local:"http://localhost:4121",develop:"https://royalty.service.bejusto.com",prod:"https://royalty.service.getjusto.com"},marketing:{local:"http://localhost:4005",develop:"https://marketing.service.bejusto.com",prod:"https://marketing.service.getjusto.com"},api:{local:"http://localhost:4119",develop:"https://api.service.bejusto.com",prod:"https://api.service.getjusto.com"},messenger:{local:"http://localhost:4122",develop:"https://messenger.service.bejusto.com",prod:"https://messenger.service.getjusto.com"},invoice:{local:"http://localhost:4123",develop:"https://invoice.service.bejusto.com",prod:"https://invoice.service.getjusto.com"},"drivers-server":{local:"http://localhost:3410",develop:"https://api-delivery.bejusto.com",prod:"https://api-delivery-2.getjusto.com"}},ye="prod";function He(e){ye=e}function re(){let e=process.env.JUSTO_TEAM_CLI_ENV;if(e)return e;let t=I()?.environment;if(t)return t;return ye}function $(e){return oe[e][ye]}var Ce=Ze(sr(),".justo-team");function De(e){let t=e==="prod"?"credentials.json":`credentials.${e}.json`;return Ze(Ce,t)}function qe(){return De(re())}function cr(){if(!ae(Ce))ar(Ce,{recursive:!0})}function ie(e){let t=I();if(t&&t.canPersistCredentials===!1)throw Error("Este entorno no permite guardar credenciales.");cr(),ir(qe(),JSON.stringify(e,null,2))}function d(){let e=process.env.JUSTO_TEAM_CLI_TOKEN,t=process.env.JUSTO_TEAM_CLI_EMAIL,o=process.env.JUSTO_TEAM_CLI_REFRESH_TOKEN;if(e&&t)return{email:t,token:e,refreshToken:o||""};let r=I()?.credentials;if(r!==void 0)return r?{email:r.email,token:r.token,refreshToken:r.refreshToken||""}:null;let a=qe();if(!ae(a))return null;try{let i=Ye(a,"utf-8");return JSON.parse(i)}catch{return null}}function ze(e){let t=De(e);if(!ae(t))return null;try{let o=Ye(t,"utf-8");return JSON.parse(o)}catch{return null}}function Ie(){let e=I();if(e&&e.canPersistCredentials===!1)throw Error("Este entorno no permite borrar credenciales.");let t=qe();if(ae(t))nr(t)}import{existsSync as ke,readFileSync as mr,writeFileSync as ur,mkdirSync as lr}from"node:fs";import{join as Ke}from"node:path";import{homedir as dr}from"node:os";function pr(){let e=process.env.JUSTO_TEAM_CLI_DEVICE_ID;if(e)return e;let t=I()?.deviceId;if(t)return t;let o=Ke(dr(),".justo-team"),r=Ke(o,"device-id");if(ke(r))return mr(r,"utf-8").trim();let a=crypto.randomUUID();if(!ke(o))lr(o,{recursive:!0});return ur(r,a),a}var Le={required:({label:e})=>`${e} no es opcional`,notAString:({label:e})=>`${e} no es un texto`,notANumber:({label:e})=>`${e} no es un número`,notAnInteger:({label:e})=>`${e} no es un número entero`,notABoolean:({label:e})=>`${e} no es un valor verdadero o falso`,notAnEmail:({label:e})=>`${e} no es un email`,notAnId:({label:e})=>`${e} no es un ID válido`,notADate:({label:e})=>`${e} no es una fecha válida`,notAnArray:({label:e})=>`${e} no es un arreglo`,notAnObject:({label:e})=>`${e} no es un objeto`,stringTooShort:({label:e})=>`${e} no tiene el largo suficiente`,stringTooLong:"El largo es mayor al permitido",numberTooSmall:({label:e})=>`${e} es un número muy pequeño`,numberTooBig:({label:e})=>`${e} es un número muy grande`,notInSchema:({label:e})=>`${e} no esta permitido`,notUnique:({label:e})=>`${e} no es único`,notFound:({label:e})=>`${e} no se encontró`,invalid:"No es válido",rateLimitExceeded:"Has excedido el límite de intentos. Intenta de nuevo más tarde.",incorrectLoginCode:"El código es incorrecto",loginCodeExpired:"El código expiró. Solicita un nuevo",loginCodeLocked:"El código se bloqueó. Genera un nuevo código para continuar",userNotFound:"No existe una cuenta con este email"};function gr(e,t){let o=Le[e];if(!o)return`${t}: ${e}`;if(typeof o==="function")return o({label:t});return o}function Ve(e){return Object.entries(e).map(([t,o])=>gr(o,t)).join(", ")}function fr(e){if(e.error==="validationError"&&e.validationErrors)return Ve(e.validationErrors);if(e.extensions?.code==="PermissionsError"){let a=e.extensions.info?.type;if(a?.includes("User doesn't have permissions for "))return`Tu usuario no tiene permisos para [${a.split("User doesn't have permissions for ")[1]}]`;return e.message}if(e.validationErrors)return`${e.message} (${Ve(e.validationErrors)})`;let t=e.message||"Error desconocido",o=Le[t];if(o)return typeof o==="function"?o({label:""}).trim():o;let r=e.error||e.code||e.type;return r?`${t} [${r}]`:t}function wr(e){try{return JSON.parse(Buffer.from(e.split(".")[1],"base64").toString()).exp*1000<Date.now()}catch{return!0}}async function br(){let e=d();if(!e?.refreshToken)return null;let t=`${$("auth")}/refresh-token`,r=await(await fetch(t,{method:"POST",headers:{"X-ORION-REFRESH":e.refreshToken}})).json();if(!r.token)return null;if(I()?.canPersistCredentials!==!1)ie({...e,token:r.token});return r.token}async function $e(){let e=d();if(!e?.token)return;if(!wr(e.token))return e.token;return await br()??void 0}async function xe(e="application/json"){let t=await $e(),o={"Content-Type":e,"X-ORION-DEVICEID":pr(),"X-ORION-PLATFORM":"web"};if(t)o["x-orion-jwt"]=t;return o}async function m(e){let t=`${$(e.service)}/graphql`,o=await xe(),r;try{r=await fetch(t,{method:"POST",headers:o,body:JSON.stringify({query:e.query,variables:e.variables}),signal:AbortSignal.timeout(15000)})}catch{throw Error("La solicitud tardó demasiado. Intenta de nuevo.")}let a=await r.json();if(a.errors?.length)throw Error(fr(a.errors[0]));if(!a.data)throw Error("No data returned from server");return a.data}function yr(e){return e.replace(/^https?:\/\//,"").replace(/^www\./,"").replace(/\/.*$/,"")}function Cr(e){return e.includes(".")||e.startsWith("http://")||e.startsWith("https://")}async function M(e){if(Cr(e)){let t=yr(e),o=await fetch(`${$("main")}/website-id/${t}`,{signal:AbortSignal.timeout(1e4)});if(!o.ok)throw Error(`No se encontro el sitio "${t}"`);let r=await o.json();if(!r.websiteId)throw Error(`No se pudo resolver el websiteId para "${t}"`);return{input:e,websiteId:r.websiteId,targetType:"domain"}}return{input:e,websiteId:e,targetType:"websiteId"}}async function et(e){let t=await m({service:"main",query:`query ($websiteId: ID) {
74
5
  website(websiteId: $websiteId) {
75
6
  _id
76
7
  name
@@ -82,7 +13,7 @@ Formato:
82
13
  timezone
83
14
  defaultMenuId
84
15
  }
85
- }`,variables:{websiteId:o}});if(!t.website)throw Error(`No se encontro el website "${o}"`);return t.website}function me(){if(!d())throw Error("Debes iniciar sesión primero. Usa: team-cli auth login")}async function To(o){if(me(),!o)throw Error("Uso: team-cli admin <websiteId|domain> show");let t=await O(o),e=await vo(t.websiteId);return{context:t,website:e}}function H(){return`team-cli admin
16
+ }`,variables:{websiteId:e}});if(!t.website)throw Error(`No se encontro el website "${e}"`);return t.website}function qr(){if(!d())throw Error("Debes iniciar sesión primero. Recomendado: team-cli auth request-code --email <email> y luego team-cli auth login-with-token --email <email> --token <token> --code <CODIGO>")}async function tt(e){if(qr(),!e)throw Error("Uso: team-cli admin <websiteId|domain> show");let t=await M(e),o=await et(t.websiteId);return{context:t,website:o}}function ne(){return`team-cli admin
86
17
 
87
18
  Comandos administrativos con contexto de website.
88
19
 
@@ -104,7 +35,7 @@ Modulos:
104
35
 
105
36
  coupons
106
37
  Administrar cupones y sus códigos.
107
- Uso: team-cli admin <websiteId|domain> coupons <accion> [opciones]`}var _o=`
38
+ Uso: team-cli admin <websiteId|domain> coupons <accion> [opciones]`}var ot=`
108
39
  availableAtPeriods
109
40
  closedDays
110
41
  closedUntilDate
@@ -120,7 +51,7 @@ Modulos:
120
51
  fromMinute
121
52
  toMinute
122
53
  }
123
- `,D=`
54
+ `,se=`
124
55
  _id
125
56
  websiteId
126
57
  name
@@ -155,13 +86,13 @@ Modulos:
155
86
  requiredBINs
156
87
  extraRequirementsForPaymentTypes
157
88
  schedule {
158
- ${_o}
89
+ ${ot}
159
90
  }
160
91
  scheduleAtUse {
161
- ${_o}
92
+ ${ot}
162
93
  }
163
94
  codesCode
164
- `,Fo=`
95
+ `,rt=`
165
96
  _id
166
97
  code
167
98
  couponId
@@ -170,64 +101,55 @@ Modulos:
170
101
  sentToEmail
171
102
  totalRedemptions
172
103
  createdAt
173
- `;function uo(){if(!d())throw Error("Debes iniciar sesión primero. Usa: team-cli auth login")}function S(o,t){let e=o[t];if(!e)throw Error(`--${t} es requerido.`);try{return JSON.parse(e)}catch{throw Error(`--${t} debe ser un JSON válido.`)}}function $(o,t){let e=o[t];if(!e)return;let i=Number.parseInt(e,10);if(Number.isNaN(i))throw Error(`--${t} debe ser un número entero.`);return i}function Mo(o,t){let e=o[t];if(!e)return;if(e==="true")return!0;if(e==="false")return!1;throw Error(`--${t} debe ser true o false.`)}async function f(o){if(uo(),!o)throw Error("Debes indicar <websiteId|domain>.");return O(o)}async function E(o,t){let e=await c({service:"main",query:`query ($couponId: ID) {
104
+ `;function he(){if(!d())throw Error("Debes iniciar sesión primero. Recomendado: team-cli auth request-code --email <email> y luego team-cli auth login-with-token --email <email> --token <token> --code <CODIGO>")}function _(e,t){let o=e[t];if(!o)throw Error(`--${t} es requerido.`);try{return JSON.parse(o)}catch{throw Error(`--${t} debe ser un JSON válido.`)}}function S(e,t){let o=e[t];if(!o)return;let r=Number.parseInt(o,10);if(Number.isNaN(r))throw Error(`--${t} debe ser un número entero.`);return r}function at(e,t){let o=e[t];if(!o)return;if(o==="true")return!0;if(o==="false")return!1;throw Error(`--${t} debe ser true o false.`)}async function x(e){if(he(),!e)throw Error("Debes indicar <websiteId|domain>.");return M(e)}async function N(e,t){let o=await m({service:"main",query:`query ($couponId: ID) {
174
105
  coupon(couponId: $couponId) {
175
106
  _id
176
107
  websiteId
177
108
  }
178
- }`,variables:{couponId:o}});if(!e.coupon)throw Error(`No se encontró el cupón "${o}"`);if(e.coupon.websiteId!==t)throw Error(`El cupón "${o}" no pertenece al website seleccionado.`);return e.coupon}async function Xo(o,t){uo();let e=o[2]??t.filter;if(!e)throw Error("Debes indicar un término de búsqueda. Uso: team-cli admin search <texto>");let i=$(t,"limit"),r=$(t,"page"),s=Mo(t,"only-active"),n=await c({service:"main",query:`query ($filter: String, $limit: BigInt, $page: BigInt, $onlyActiveWebsites: Boolean) {
179
- websites(filter: $filter, limit: $limit, page: $page, onlyActiveWebsites: $onlyActiveWebsites) {
109
+ }`,variables:{couponId:e}});if(!o.coupon)throw Error(`No se encontró el cupón "${e}"`);if(o.coupon.websiteId!==t)throw Error(`El cupón "${e}" no pertenece al website seleccionado.`);return o.coupon}function Ir(e){if(!Array.isArray(e))throw Error("--input debe ser un arreglo JSON.");return e.map((t)=>{if(!t||typeof t!=="object"||typeof t.code!=="string")throw Error('Cada item de --input debe tener al menos { "code": "..." }.');if(t.userEmail!=null&&typeof t.userEmail!=="string")throw Error("userEmail debe ser string cuando viene informado.");return{code:t.code,userEmail:t.userEmail}})}function $r(e){if(!Array.isArray(e)||e.some((t)=>typeof t!=="string"))throw Error("--ids debe ser un arreglo JSON de strings.");return e}async function it(e,t,o){let r=await x(e);await N(t,r.websiteId);let a=S(o,"limit"),i=S(o,"page"),n=o.filter,s=await m({service:"main",query:`query ($couponId: ID, $filter: String, $limit: BigInt, $page: BigInt) {
110
+ couponCodes(couponId: $couponId, filter: $filter, limit: $limit, page: $page) {
180
111
  items {
181
- _id
182
- name
183
- active
184
- baseURL
185
- domain
186
- countryCode
187
- timezone
112
+ ${rt}
188
113
  }
189
114
  totalCount
190
115
  totalPages
191
116
  hasNextPage
192
117
  hasPreviousPage
193
118
  }
194
- }`,variables:{filter:e,limit:i,page:r,onlyActiveWebsites:s}});return{searchTerm:e,websites:n.websites.items??[],pagination:{totalCount:n.websites.totalCount??0,totalPages:n.websites.totalPages??0,hasNextPage:Boolean(n.websites.hasNextPage),hasPreviousPage:Boolean(n.websites.hasPreviousPage),page:r??1,limit:i??null}}}function Yo(){return`team-cli admin search
119
+ }`,variables:{couponId:t,filter:n,limit:a,page:i}});return{context:r,couponId:t,codes:s.couponCodes.items??[],pagination:{totalCount:s.couponCodes.totalCount??0,totalPages:s.couponCodes.totalPages??0,hasNextPage:Boolean(s.couponCodes.hasNextPage),hasPreviousPage:Boolean(s.couponCodes.hasPreviousPage),page:i??1,limit:a??null}}}async function nt(e,t,o){let r=await x(e);await N(t,r.websiteId);let a=Ir(_(o,"input")),i=a.some((s)=>s.userEmail),n=await m({service:"main",query:`mutation ($couponId: ID, $codesWithEmail: [CodeWithEmailInput], $useCodeWithEmail: Boolean) {
120
+ createCouponCodes(couponId: $couponId, codesWithEmail: $codesWithEmail, useCodeWithEmail: $useCodeWithEmail)
121
+ }`,variables:{couponId:t,codesWithEmail:a,useCodeWithEmail:i}});return{context:r,couponId:t,requestedCount:a.length,result:n.createCouponCodes}}async function st(e,t,o){let r=await x(e);await N(t,r.websiteId);let a=S(o,"quantity");if(!a)throw Error("--quantity es requerido.");let i=await m({service:"main",query:`mutation ($couponId: ID, $couponQuantity: Float, $couponCodePrefix: String) {
122
+ createRandomCouponCodes(couponId: $couponId, couponQuantity: $couponQuantity, couponCodePrefix: $couponCodePrefix)
123
+ }`,variables:{couponId:t,couponQuantity:a,couponCodePrefix:o.prefix}});return{context:r,couponId:t,quantity:a,prefix:o.prefix??null,result:i.createRandomCouponCodes}}async function ct(e,t,o){let r=await x(e);await N(t,r.websiteId);let a=$r(_(o,"ids")),i=await m({service:"main",query:`mutation ($couponId: ID, $couponCodesIds: [ID]) {
124
+ deleteCouponCodes(couponId: $couponId, couponCodesIds: $couponCodesIds, globalCoupon: false)
125
+ }`,variables:{couponId:t,couponCodesIds:a}});return{context:r,couponId:t,deleted:i.deleteCouponCodes,couponCodesIds:a}}function mt(){return`team-cli admin coupons codes create
195
126
 
196
- Buscar websites en admin.
127
+ Crea códigos explícitos para un cupón.
197
128
 
198
129
  Uso:
199
- team-cli admin search <texto> [--limit <n>] [--page <n>] [--only-active true|false]
130
+ team-cli admin <websiteId|domain> coupons codes create <couponId> --input '<json>'
200
131
 
201
- Opciones:
202
- --limit <n>
203
- Límite de resultados.
132
+ Como funciona:
133
+ --input recibe un arreglo JSON.
134
+ Cada item debe tener al menos el campo code.
135
+ Opcionalmente puede incluir userEmail.
204
136
 
205
- --page <n>
206
- Página a consultar.
137
+ Formato esperado:
138
+ [
139
+ {"code":"BIENVENIDA1"},
140
+ {"code":"BIENVENIDA2","userEmail":"persona@ejemplo.com"}
141
+ ]
207
142
 
208
- --only-active true|false
209
- Filtrar solo websites activos.
143
+ Ejemplo:
144
+ team-cli admin <web> coupons codes create <couponId> --input '[{"code":"PROMO001"},{"code":"PROMO002","userEmail":"ana@ejemplo.com"}]'
210
145
 
211
- Ejemplos:
212
- team-cli admin search milas
213
- team-cli admin search buffalo --limit 5
214
- team-cli admin search pizza --only-active true`}function ue(){if(!d())throw Error("Debes iniciar sesión primero. Usa: team-cli auth login")}function ge(o){let t=[o.address?.streetAddress,o.address?.extendedAddress,o.address?.locality].filter(Boolean);if(!t.length)return null;return t.join(", ")}async function Zo(o){if(ue(),!o)throw Error("Uso: team-cli admin <websiteId|domain> stores list");let t=await O(o),i=((await c({service:"main",query:`query ($websiteId: ID) {
215
- stores(websiteId: $websiteId) {
216
- items {
217
- _id
218
- name
219
- address {
220
- streetAddress
221
- extendedAddress
222
- locality
223
- }
224
- }
225
- }
226
- }`,variables:{websiteId:t.websiteId}})).stores.items??[]).map((r)=>({_id:r._id,name:r.name,address:ge(r)})).sort((r,s)=>r.name.localeCompare(s.name,"es",{sensitivity:"base"}));return{context:t,stores:i,totalCount:i.length}}var zo={active:"Boolean",allowedEmails:"[String]",applyDeliveryDiscount:"Boolean",code:"ID",deliveryDiscountPercentage:"Float",deliveryDiscountType:"String",deliveryDiscountValue:"Float",description:"String",discountAmount:"Float",dontApplyToProductsIds:"[ID]",endDate:"Date",externalId:"String",extraRequirementsForPaymentTypes:"JSON",fixedAmount:"Float",fromDate:"Date",isBirthdayCoupon:"Boolean",isHidden:"Boolean",maxPercentageOffDiscount:"Float",maxProductsPerOrder:"Float",maxRedemptions:"Float",maxRedemptionsPerUser:"Float",maxRedemptionsPerUserPerDay:"Boolean",maximumOrderPrice:"Float",minimumOrderPrice:"Float",name:"String",onlyForNewUsers:"Boolean",onlyForProductsWithoutDiscount:"Boolean",onlyRedeemOnBirthday:"Boolean",percentageOff:"Float",requireChannels:"[ID]",requirePhoneVerification:"Boolean",requiredBINs:"[String]",requiresCategoriesIds:"[ID]",requiresMenusIds:"[ID]",requiresPaymentTypes:"[ID]",requiresProductsIds:"[ID]",requiresStoresIds:"[ID]",schedule:"ScheduleInput",scheduleAtUse:"ScheduleInput",type:"ID",websiteId:"ID"};function de(o){let t=Object.entries(o).filter(([,s])=>s!==void 0),e=t.map(([s])=>s).filter((s)=>!zo[s]);if(e.length)throw Error(`Campos no soportados para create: ${e.join(", ")}`);let i=t.map(([s])=>`$${s}: ${zo[s]}`).join(", "),r=t.map(([s])=>`${s}: $${s}`).join(", ");return`mutation (${i}) {
227
- createCoupon(${r}) {
228
- ${D}
146
+ Notas:
147
+ Si algún item trae userEmail, team-cli activa useCodeWithEmail automáticamente.
148
+ couponId se valida contra el website seleccionado antes de ejecutar la mutation.`}var ut={active:"Boolean",allowedEmails:"[String]",applyDeliveryDiscount:"Boolean",code:"ID",deliveryDiscountPercentage:"Float",deliveryDiscountType:"String",deliveryDiscountValue:"Float",description:"String",discountAmount:"Float",dontApplyToProductsIds:"[ID]",endDate:"Date",externalId:"String",extraRequirementsForPaymentTypes:"JSON",fixedAmount:"Float",fromDate:"Date",isBirthdayCoupon:"Boolean",isHidden:"Boolean",maxPercentageOffDiscount:"Float",maxProductsPerOrder:"Float",maxRedemptions:"Float",maxRedemptionsPerUser:"Float",maxRedemptionsPerUserPerDay:"Boolean",maximumOrderPrice:"Float",minimumOrderPrice:"Float",name:"String",onlyForNewUsers:"Boolean",onlyForProductsWithoutDiscount:"Boolean",onlyRedeemOnBirthday:"Boolean",percentageOff:"Float",requireChannels:"[ID]",requirePhoneVerification:"Boolean",requiredBINs:"[String]",requiresCategoriesIds:"[ID]",requiresMenusIds:"[ID]",requiresPaymentTypes:"[ID]",requiresProductsIds:"[ID]",requiresStoresIds:"[ID]",schedule:"ScheduleInput",scheduleAtUse:"ScheduleInput",type:"ID",websiteId:"ID"};function xr(e){let t=Object.entries(e).filter(([,i])=>i!==void 0),o=t.map(([i])=>i).filter((i)=>!ut[i]);if(o.length)throw Error(`Campos no soportados para create: ${o.join(", ")}`);let r=t.map(([i])=>`$${i}: ${ut[i]}`).join(", "),a=t.map(([i])=>`${i}: $${i}`).join(", ");return`mutation (${r}) {
149
+ createCoupon(${a}) {
150
+ ${se}
229
151
  }
230
- }`}async function Ho(o,t){let e=await f(o),i=$(t,"limit"),r=$(t,"page"),s=t.filter,n=await c({service:"main",query:`query ($websiteId: ID, $filter: String, $limit: BigInt, $page: BigInt) {
152
+ }`}async function lt(e,t){let o=await x(e),r=S(t,"limit"),a=S(t,"page"),i=t.filter,n=await m({service:"main",query:`query ($websiteId: ID, $filter: String, $limit: BigInt, $page: BigInt) {
231
153
  coupons(websiteId: $websiteId, filter: $filter, limit: $limit, page: $page) {
232
154
  items {
233
155
  _id
@@ -247,17 +169,17 @@ Ejemplos:
247
169
  hasNextPage
248
170
  hasPreviousPage
249
171
  }
250
- }`,variables:{websiteId:e.websiteId,filter:s,limit:i,page:r}});return{context:e,coupons:n.coupons.items??[],pagination:{totalCount:n.coupons.totalCount??0,totalPages:n.coupons.totalPages??0,hasNextPage:Boolean(n.coupons.hasNextPage),hasPreviousPage:Boolean(n.coupons.hasPreviousPage),page:r??1,limit:i??null}}}async function Do(o,t){let e=await f(o);await E(t,e.websiteId);let i=await c({service:"main",query:`query ($couponId: ID) {
172
+ }`,variables:{websiteId:o.websiteId,filter:i,limit:r,page:a}});return{context:o,coupons:n.coupons.items??[],pagination:{totalCount:n.coupons.totalCount??0,totalPages:n.coupons.totalPages??0,hasNextPage:Boolean(n.coupons.hasNextPage),hasPreviousPage:Boolean(n.coupons.hasPreviousPage),page:a??1,limit:r??null}}}async function dt(e,t){let o=await x(e);await N(t,o.websiteId);let r=await m({service:"main",query:`query ($couponId: ID) {
251
173
  coupon(couponId: $couponId) {
252
- ${D}
174
+ ${se}
253
175
  }
254
- }`,variables:{couponId:t}});return{context:e,coupon:i.coupon}}async function ko(o,t){let e=await f(o),i=S(t,"input");if(i.websiteId&&i.websiteId!==e.websiteId)throw Error("El websiteId del input no coincide con el website seleccionado.");let r={...i,websiteId:e.websiteId},s=de(r),n=await c({service:"main",query:s,variables:r});return{context:e,coupon:n.createCoupon}}async function Ko(o,t,e){let i=await f(o);await E(t,i.websiteId);let r=S(e,"input"),s=await c({service:"main",query:`mutation ($couponId: ID, $coupon: UpdateCouponInput) {
176
+ }`,variables:{couponId:t}});return{context:o,coupon:r.coupon}}async function pt(e,t){let o=await x(e),r=_(t,"input");if(r.websiteId&&r.websiteId!==o.websiteId)throw Error("El websiteId del input no coincide con el website seleccionado.");let a={...r,websiteId:o.websiteId},i=xr(a),n=await m({service:"main",query:i,variables:a});return{context:o,coupon:n.createCoupon}}async function gt(e,t,o){let r=await x(e);await N(t,r.websiteId);let a=_(o,"input"),i=await m({service:"main",query:`mutation ($couponId: ID, $coupon: UpdateCouponInput) {
255
177
  updateCoupon(couponId: $couponId, coupon: $coupon) {
256
- ${D}
178
+ ${se}
257
179
  }
258
- }`,variables:{couponId:t,coupon:r}});return{context:i,coupon:s.updateCoupon}}async function Vo(o,t){let e=await f(o);await E(t,e.websiteId);let i=await c({service:"main",query:`mutation ($couponsIds: [ID]) {
180
+ }`,variables:{couponId:t,coupon:a}});return{context:r,coupon:i.updateCoupon}}async function ft(e,t){let o=await x(e);await N(t,o.websiteId);let r=await m({service:"main",query:`mutation ($couponsIds: [ID]) {
259
181
  deleteCoupons(couponsIds: $couponsIds, globalCoupon: false)
260
- }`,variables:{couponsIds:[t]}});return{context:e,couponId:t,deleted:i.deleteCoupons}}function M(){return`team-cli admin coupons
182
+ }`,variables:{couponsIds:[t]}});return{context:o,couponId:t,deleted:r.deleteCoupons}}function Y(){return`team-cli admin coupons
261
183
 
262
184
  Administracion de cupones para el website seleccionado.
263
185
 
@@ -305,7 +227,7 @@ Acciones:
305
227
  Uso: team-cli admin <web> coupons codes delete <couponId> --ids '["id1","id2"]'
306
228
 
307
229
  Nota:
308
- El schema actual no expone update para coupon codes.`}function Lo(){return`team-cli admin coupons create
230
+ El schema actual no expone update para coupon codes.`}function wt(){return`team-cli admin coupons create
309
231
 
310
232
  Crea un cupón para el website seleccionado.
311
233
 
@@ -354,7 +276,7 @@ Ejemplo con schedule:
354
276
  Tips:
355
277
  Usa comillas simples afuera del JSON en shell.
356
278
  Usa arrays JSON reales para ids o listas.
357
- Si necesitas el shape exacto de un cupón existente, parte con: team-cli admin <web> coupons show <couponId>`}function ot(){return`team-cli admin coupons update
279
+ Si necesitas el shape exacto de un cupón existente, parte con: team-cli admin <web> coupons show <couponId>`}function bt(){return`team-cli admin coupons update
358
280
 
359
281
  Actualiza un cupón existente.
360
282
 
@@ -396,69 +318,568 @@ Ejemplo reemplazando restricciones:
396
318
  team-cli admin <web> coupons update <couponId> --input '{"requiresStoresIds":["store1"],"requiresPaymentTypes":["card"]}'
397
319
 
398
320
  Tip:
399
- Primero mira el cupón actual con: team-cli admin <web> coupons show <couponId>`}function le(o){if(!Array.isArray(o))throw Error("--input debe ser un arreglo JSON.");return o.map((t)=>{if(!t||typeof t!=="object"||typeof t.code!=="string")throw Error('Cada item de --input debe tener al menos { "code": "..." }.');if(t.userEmail!=null&&typeof t.userEmail!=="string")throw Error("userEmail debe ser string cuando viene informado.");return{code:t.code,userEmail:t.userEmail}})}function pe(o){if(!Array.isArray(o)||o.some((t)=>typeof t!=="string"))throw Error("--ids debe ser un arreglo JSON de strings.");return o}async function tt(o,t,e){let i=await f(o);await E(t,i.websiteId);let r=$(e,"limit"),s=$(e,"page"),n=e.filter,a=await c({service:"main",query:`query ($couponId: ID, $filter: String, $limit: BigInt, $page: BigInt) {
400
- couponCodes(couponId: $couponId, filter: $filter, limit: $limit, page: $page) {
321
+ Primero mira el cupón actual con: team-cli admin <web> coupons show <couponId>`}async function yt(e,t){he();let o=e[2]??t.filter;if(!o)throw Error("Debes indicar un término de búsqueda. Uso: team-cli admin search <texto>");let r=S(t,"limit"),a=S(t,"page"),i=at(t,"only-active"),n=await m({service:"main",query:`query ($filter: String, $limit: BigInt, $page: BigInt, $onlyActiveWebsites: Boolean) {
322
+ websites(filter: $filter, limit: $limit, page: $page, onlyActiveWebsites: $onlyActiveWebsites) {
401
323
  items {
402
- ${Fo}
324
+ _id
325
+ name
326
+ active
327
+ baseURL
328
+ domain
329
+ countryCode
330
+ timezone
403
331
  }
404
332
  totalCount
405
333
  totalPages
406
334
  hasNextPage
407
335
  hasPreviousPage
408
336
  }
409
- }`,variables:{couponId:t,filter:n,limit:r,page:s}});return{context:i,couponId:t,codes:a.couponCodes.items??[],pagination:{totalCount:a.couponCodes.totalCount??0,totalPages:a.couponCodes.totalPages??0,hasNextPage:Boolean(a.couponCodes.hasNextPage),hasPreviousPage:Boolean(a.couponCodes.hasPreviousPage),page:s??1,limit:r??null}}}async function et(o,t,e){let i=await f(o);await E(t,i.websiteId);let r=le(S(e,"input")),s=r.some((a)=>a.userEmail),n=await c({service:"main",query:`mutation ($couponId: ID, $codesWithEmail: [CodeWithEmailInput], $useCodeWithEmail: Boolean) {
410
- createCouponCodes(couponId: $couponId, codesWithEmail: $codesWithEmail, useCodeWithEmail: $useCodeWithEmail)
411
- }`,variables:{couponId:t,codesWithEmail:r,useCodeWithEmail:s}});return{context:i,couponId:t,requestedCount:r.length,result:n.createCouponCodes}}async function it(o,t,e){let i=await f(o);await E(t,i.websiteId);let r=$(e,"quantity");if(!r)throw Error("--quantity es requerido.");let s=await c({service:"main",query:`mutation ($couponId: ID, $couponQuantity: Float, $couponCodePrefix: String) {
412
- createRandomCouponCodes(couponId: $couponId, couponQuantity: $couponQuantity, couponCodePrefix: $couponCodePrefix)
413
- }`,variables:{couponId:t,couponQuantity:r,couponCodePrefix:e.prefix}});return{context:i,couponId:t,quantity:r,prefix:e.prefix??null,result:s.createRandomCouponCodes}}async function rt(o,t,e){let i=await f(o);await E(t,i.websiteId);let r=pe(S(e,"ids")),s=await c({service:"main",query:`mutation ($couponId: ID, $couponCodesIds: [ID]) {
414
- deleteCouponCodes(couponId: $couponId, couponCodesIds: $couponCodesIds, globalCoupon: false)
415
- }`,variables:{couponId:t,couponCodesIds:r}});return{context:i,couponId:t,deleted:s.deleteCouponCodes,couponCodesIds:r}}function st(){return`team-cli admin coupons codes create
337
+ }`,variables:{filter:o,limit:r,page:a,onlyActiveWebsites:i}});return{searchTerm:o,websites:n.websites.items??[],pagination:{totalCount:n.websites.totalCount??0,totalPages:n.websites.totalPages??0,hasNextPage:Boolean(n.websites.hasNextPage),hasPreviousPage:Boolean(n.websites.hasPreviousPage),page:a??1,limit:r??null}}}function Ct(){return`team-cli admin search
416
338
 
417
- Crea códigos explícitos para un cupón.
339
+ Buscar websites en admin.
418
340
 
419
341
  Uso:
420
- team-cli admin <websiteId|domain> coupons codes create <couponId> --input '<json>'
342
+ team-cli admin search <texto> [--limit <n>] [--page <n>] [--only-active true|false]
421
343
 
422
- Como funciona:
423
- --input recibe un arreglo JSON.
424
- Cada item debe tener al menos el campo code.
425
- Opcionalmente puede incluir userEmail.
344
+ Opciones:
345
+ --limit <n>
346
+ Límite de resultados.
426
347
 
427
- Formato esperado:
428
- [
429
- {"code":"BIENVENIDA1"},
430
- {"code":"BIENVENIDA2","userEmail":"persona@ejemplo.com"}
431
- ]
348
+ --page <n>
349
+ Página a consultar.
432
350
 
433
- Ejemplo:
434
- team-cli admin <web> coupons codes create <couponId> --input '[{"code":"PROMO001"},{"code":"PROMO002","userEmail":"ana@ejemplo.com"}]'
351
+ --only-active true|false
352
+ Filtrar solo websites activos.
435
353
 
436
- Notas:
437
- Si algún item trae userEmail, team-cli activa useCodeWithEmail automáticamente.
438
- couponId se valida contra el website seleccionado antes de ejecutar la mutation.`}import{writeFileSync as we}from"node:fs";function k(){if(!d())throw Error("Debes iniciar sesión primero. Usa: team-cli auth login")}function K(o,t){let e=o[3];if(!e)throw Error(`Uso: ${t}`);return e}function nt(o){if(!o.params)return{};try{return JSON.parse(o.params)}catch{throw Error("--params debe ser un JSON válido.")}}function fe(o){if(typeof o!=="string")return o;try{return JSON.parse(o)}catch{return{value:o}}}async function at(o){k();let t=K(o,"team-cli data queries view <queryId>");return(await c({service:"data",query:`query ($aggregationQueryId: String) {
354
+ Ejemplos:
355
+ team-cli admin search milas
356
+ team-cli admin search buffalo --limit 5
357
+ team-cli admin search pizza --only-active true`}function hr(){if(!d())throw Error("Debes iniciar sesión primero. Recomendado: team-cli auth request-code --email <email> y luego team-cli auth login-with-token --email <email> --token <token> --code <CODIGO>")}function Sr(e){let t=[e.address?.streetAddress,e.address?.extendedAddress,e.address?.locality].filter(Boolean);if(!t.length)return null;return t.join(", ")}async function qt(e){if(hr(),!e)throw Error("Uso: team-cli admin <websiteId|domain> stores list");let t=await M(e),r=((await m({service:"main",query:`query ($websiteId: ID) {
358
+ stores(websiteId: $websiteId) {
359
+ items {
360
+ _id
361
+ name
362
+ address {
363
+ streetAddress
364
+ extendedAddress
365
+ locality
366
+ }
367
+ }
368
+ }
369
+ }`,variables:{websiteId:t.websiteId}})).stores.items??[]).map((a)=>({_id:a._id,name:a.name,address:Sr(a)})).sort((a,i)=>a.name.localeCompare(i.name,"es",{sensitivity:"base"}));return{context:t,stores:r,totalCount:r.length}}import{createInterface as Er}from"node:readline";function Z(e){if(process.env.JUSTO_TEAM_CLI_INTERACTIVE==="false")throw Error("Este entorno no soporta prompts interactivos.");if(I()?.interactive===!1)throw Error("Este entorno no soporta prompts interactivos.");let t=Er({input:process.stdin,output:process.stderr});return new Promise((o)=>{t.question(e,(r)=>{t.close(),o(r.trim())})})}async function It(e){return(await m({service:"auth",query:`mutation ($email: String!) {
370
+ requestLoginCode(email: $email)
371
+ }`,variables:{email:e}})).requestLoginCode}async function $t(e,t,o){let r=await m({service:"auth",query:`mutation ($email: String!, $token: String!, $code: String!) {
372
+ loginWithCode(email: $email, token: $token, code: $code) {
373
+ token
374
+ refreshToken
375
+ }
376
+ }`,variables:{email:e,token:t,code:o.toUpperCase()}});ie({email:e,token:r.loginWithCode.token,refreshToken:r.loginWithCode.refreshToken}),await jr()}async function jr(){if(!(await m({service:"main",query:"query { me { roles } }"})).me?.roles?.length)throw Ie(),Error("Solo miembros del equipo Justo pueden usar esta herramienta.")}async function xt(){let e=await Z("Email: ");y(`Enviando codigo de verificacion...
377
+ `);let t=await It(e);y(`Codigo enviado a tu email.
378
+ `);let o=await Z("Codigo: ");return await $t(e,t,o),{ok:!0,authenticated:!0,email:e}}async function ht(e){let t=G(e,"email"),o=G(e,"token"),r=G(e,"code");return await $t(t,o,r),{ok:!0,authenticated:!0,email:t}}async function St(e){let t=G(e,"email");y(`Enviando codigo de verificacion...
379
+ `);let o=await It(t);return{ok:!0,email:t,token:o,nextCommand:`npx @getjusto/team-cli auth login-with-token --email ${t} --token ${o} --code <CODIGO>`}}async function Et(){return Ie(),{ok:!0,authenticated:!1}}async function jt(){let e=d();if(!e)return{authenticated:!1,loginCommand:"npx @getjusto/team-cli auth request-code --email <email>",nextCommand:"npx @getjusto/team-cli auth login-with-token --email <email> --token <token> --code <CODIGO>"};return{authenticated:!0,email:e.email}}function Se(){return`team-cli auth
380
+
381
+ Gestion de sesion.
382
+
383
+ Uso:
384
+ team-cli auth <subcomando> [opciones]
385
+
386
+ Subcomandos:
387
+ login
388
+ Iniciar sesion en modo interactivo. Usar solo como fallback manual.
389
+ Uso: team-cli auth login
390
+
391
+ logout
392
+ Cerrar sesion actual.
393
+ Uso: team-cli auth logout
394
+
395
+ status
396
+ Ver la sesion actual.
397
+ Uso: team-cli auth status
398
+
399
+ request-code
400
+ Solicitar codigo para login no interactivo. Recomendado para agentes.
401
+ Uso: team-cli auth request-code --email <email>
402
+
403
+ login-with-token
404
+ Iniciar sesion sin prompts. Recomendado para agentes.
405
+ Uso: team-cli auth login-with-token --email <email> --token <token> --code <codigo>`}import{spawn as de}from"node:child_process";import{createServer as Ht}from"node:http";import{existsSync as Mr,mkdirSync as _r,openSync as Br,readFileSync as Gr,rmSync as Pr,writeFileSync as Fr}from"node:fs";import{dirname as Xr,join as pe,resolve as Yt}from"node:path";import{request as Hr}from"node:http";import{request as Yr}from"node:https";import{execFileSync as Nr}from"node:child_process";import{existsSync as me,mkdirSync as Ar,readFileSync as ue,readdirSync as Rr,rmSync as Ee,writeFileSync as A}from"node:fs";import{basename as Ot,dirname as Tt,join as f,resolve as Ut}from"node:path";function Nt(){return`import {useState, type FormEvent} from 'react'
406
+ import {Badge} from '@/components/ui/badge'
407
+ import {Button} from '@/components/ui/button'
408
+ import {Card, CardContent, CardDescription, CardHeader, CardTitle} from '@/components/ui/card'
409
+ import {ChartContainer, ChartTooltip, ChartTooltipContent} from '@/components/ui/chart'
410
+ import type {ChartConfig} from '@/components/ui/chart'
411
+ import {Input} from '@/components/ui/input'
412
+ import {Separator} from '@/components/ui/separator'
413
+ import {Textarea} from '@/components/ui/textarea'
414
+ import {Toaster} from '@/components/ui/sonner'
415
+ import {MapContainer, TileLayer, CircleMarker, Popup} from 'react-leaflet'
416
+ import {Bar, BarChart, CartesianGrid, XAxis} from 'recharts'
417
+ import {toast} from 'sonner'
418
+ import {justoCli} from '@/lib/justo'
419
+
420
+ const defaultCommand = 'auth status'
421
+ const queryExample = "data queries preview <queryId> --params '{\\"limit\\":10}'"
422
+ const mapTilerToken = 'Ug1j1WYGl6rn0I7x9Kuw'
423
+ const chartData = [
424
+ {day: 'Lun', sessions: 12},
425
+ {day: 'Mar', sessions: 18},
426
+ {day: 'Mié', sessions: 15},
427
+ {day: 'Jue', sessions: 22},
428
+ {day: 'Vie', sessions: 19},
429
+ ]
430
+
431
+ const chartConfig = {
432
+ sessions: {
433
+ label: 'Sesiones',
434
+ color: 'var(--color-stone-900)',
435
+ },
436
+ } satisfies ChartConfig
437
+
438
+ export function App() {
439
+ const [command, setCommand] = useState(defaultCommand)
440
+ const [result, setResult] = useState('Ejecuta un comando para ver el resultado aquí.')
441
+ const [loading, setLoading] = useState(false)
442
+
443
+ async function onSubmit(event: FormEvent<HTMLFormElement>) {
444
+ event.preventDefault()
445
+ setLoading(true)
446
+
447
+ try {
448
+ const response = await justoCli(command)
449
+ setResult(JSON.stringify(response, null, 2))
450
+ toast.success('Comando ejecutado')
451
+ } catch (error) {
452
+ const message = error instanceof Error ? error.message : 'Unexpected error'
453
+ setResult(message)
454
+ toast.error(message)
455
+ } finally {
456
+ setLoading(false)
457
+ }
458
+ }
459
+
460
+ return (
461
+ <>
462
+ <main className="min-h-screen bg-stone-50 text-stone-950">
463
+ <div className="mx-auto flex min-h-screen w-full max-w-6xl flex-col gap-8 px-6 py-10">
464
+ <section className="grid gap-4">
465
+ <Badge variant="secondary" className="w-fit bg-stone-200 text-stone-700">
466
+ Justo Space Starter
467
+ </Badge>
468
+ <div className="grid gap-3">
469
+ <h1 className="max-w-3xl text-4xl font-semibold tracking-tight text-balance">
470
+ React, Vite, Tailwind y todos los componentes shadcn listos para construir un
471
+ space.
472
+ </h1>
473
+ <p className="max-w-3xl text-base leading-7 text-stone-600">
474
+ Este proyecto ya viene preparado para publicar en Justo Spaces. Construye la UI en
475
+ React y llama el CLI con <code>window.justo.cli(...)</code> a través del helper
476
+ <code>justoCli(...)</code>.
477
+ </p>
478
+ </div>
479
+ </section>
480
+
481
+ <section className="grid gap-6 lg:grid-cols-[1.1fr_0.9fr]">
482
+ <Card className="border-stone-200 bg-white text-stone-950 shadow-sm">
483
+ <CardHeader>
484
+ <CardTitle>Playground del CLI</CardTitle>
485
+ <CardDescription className="text-stone-600">
486
+ Usa exactamente los mismos comandos que usarías en team-cli.
487
+ </CardDescription>
488
+ </CardHeader>
489
+ <CardContent className="grid gap-4">
490
+ <form className="grid gap-4" onSubmit={onSubmit}>
491
+ <Input
492
+ value={command}
493
+ onChange={event => setCommand(event.target.value)}
494
+ className="border-stone-300 bg-white text-stone-950"
495
+ />
496
+ <div className="flex flex-wrap gap-3">
497
+ <Button disabled={loading} type="submit">
498
+ {loading ? 'Ejecutando...' : 'Ejecutar comando'}
499
+ </Button>
500
+ <Button
501
+ type="button"
502
+ variant="outline"
503
+ className="border-stone-300 bg-transparent text-stone-900"
504
+ onClick={() => setCommand(queryExample)}
505
+ >
506
+ Probar query preview
507
+ </Button>
508
+ </div>
509
+ </form>
510
+
511
+ <Separator className="bg-stone-200" />
512
+
513
+ <div className="grid gap-2">
514
+ <p className="text-sm font-medium text-stone-700">Resultado</p>
515
+ <Textarea
516
+ readOnly
517
+ value={result}
518
+ className="min-h-[320px] border-stone-300 bg-stone-950 font-mono text-xs text-emerald-200"
519
+ />
520
+ </div>
521
+ </CardContent>
522
+ </Card>
523
+
524
+ <Card className="border-stone-200 bg-white text-stone-950 shadow-sm">
525
+ <CardHeader>
526
+ <CardTitle>Cómo construir el space</CardTitle>
527
+ <CardDescription className="text-stone-600">
528
+ Flujo recomendado para agentes.
529
+ </CardDescription>
530
+ </CardHeader>
531
+ <CardContent className="grid gap-4 text-sm leading-7 text-stone-600">
532
+ <div>
533
+ <p className="font-medium text-stone-900">1. Crea el entity</p>
534
+ <p>team-cli spaces create --name 'Mi space' --description '...' --slug mi-space</p>
535
+ </div>
536
+ <div>
537
+ <p className="font-medium text-stone-900">2. Trabaja aquí mismo</p>
538
+ <p>Edita <code>src/App.tsx</code>, crea pantallas, hooks y usa shadcn libremente.</p>
539
+ </div>
540
+ <div>
541
+ <p className="font-medium text-stone-900">3. Usa queries como APIs</p>
542
+ <p>
543
+ Lo recomendado para obtener data es crear queries en data y luego llamar desde el
544
+ space comandos como <code>data queries preview</code>.
545
+ </p>
546
+ </div>
547
+ <div>
548
+ <p className="font-medium text-stone-900">4. Publica</p>
549
+ <p>team-cli spaces publish &lt;spaceId&gt; --path ./mi-space-app</p>
550
+ </div>
551
+ <div>
552
+ <p className="font-medium text-stone-900">Reglas de diseño</p>
553
+ <p>Prefiere shadcn, usa solo light mode y mantén una paleta neutra.</p>
554
+ </div>
555
+ </CardContent>
556
+ </Card>
557
+ </section>
558
+
559
+ <section className="grid gap-6 lg:grid-cols-[0.95fr_1.05fr]">
560
+ <Card className="border-stone-200 bg-white text-stone-950 shadow-sm">
561
+ <CardHeader>
562
+ <CardTitle>Charts listos</CardTitle>
563
+ <CardDescription className="text-stone-600">
564
+ El starter ya trae el wrapper de charts de shadcn y recharts instalado.
565
+ </CardDescription>
566
+ </CardHeader>
567
+ <CardContent>
568
+ <ChartContainer className="h-[260px] w-full" config={chartConfig}>
569
+ <BarChart accessibilityLayer data={chartData}>
570
+ <CartesianGrid vertical={false} />
571
+ <XAxis axisLine={false} dataKey="day" tickLine={false} tickMargin={10} />
572
+ <ChartTooltip content={<ChartTooltipContent />} cursor={false} />
573
+ <Bar dataKey="sessions" fill="var(--color-sessions)" radius={10} />
574
+ </BarChart>
575
+ </ChartContainer>
576
+ </CardContent>
577
+ </Card>
578
+
579
+ <Card className="border-stone-200 bg-white text-stone-950 shadow-sm">
580
+ <CardHeader>
581
+ <CardTitle>Mapa con OpenStreetMap</CardTitle>
582
+ <CardDescription className="text-stone-600">
583
+ Usa el mismo token de MapTiler que ya ocupa vite-fronts, sobre datos de
584
+ OpenStreetMap.
585
+ </CardDescription>
586
+ </CardHeader>
587
+ <CardContent className="grid gap-3">
588
+ <div className="overflow-hidden rounded-xl border border-stone-200">
589
+ <MapContainer
590
+ center={[-33.4372, -70.6506]}
591
+ className="h-[260px] w-full"
592
+ scrollWheelZoom={false}
593
+ zoom={12}
594
+ >
595
+ <TileLayer
596
+ attribution='&copy; <a href="https://www.maptiler.com/copyright/" target="_blank">MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>'
597
+ tileSize={512}
598
+ url={\`https://api.maptiler.com/maps/streets/{z}/{x}/{y}@2x.png?key=\${mapTilerToken}\`}
599
+ zoomOffset={-1}
600
+ />
601
+ <CircleMarker
602
+ center={[-33.4372, -70.6506]}
603
+ pathOptions={{color: '#44403c', fillColor: '#44403c', fillOpacity: 0.9}}
604
+ radius={10}
605
+ >
606
+ <Popup>Justo Spaces starter</Popup>
607
+ </CircleMarker>
608
+ </MapContainer>
609
+ </div>
610
+ <p className="text-sm text-stone-600">
611
+ No necesitas configurar una key adicional en el space: el starter ya reutiliza el
612
+ token que existe en vite-fronts.
613
+ </p>
614
+ </CardContent>
615
+ </Card>
616
+ </section>
617
+ </div>
618
+ </main>
619
+ <Toaster richColors />
620
+ </>
621
+ )
622
+ }
623
+
624
+ export default App
625
+ `}function At(){return`type JustoCliFunction = <T = unknown>(command: string) => Promise<T>
626
+ type JustoStreamFunction = <T = unknown>(
627
+ command: string,
628
+ onRow: (row: T) => Promise<void> | void,
629
+ ) => Promise<{rowCount: number}>
630
+
631
+ type ImportMetaEnvWithJusto = ImportMeta['env'] & {
632
+ VITE_JUSTO_CLI_ENDPOINT?: string
633
+ VITE_JUSTO_STREAM_ENDPOINT?: string
634
+ }
635
+
636
+ declare global {
637
+ interface Window {
638
+ justo?: {
639
+ cli: JustoCliFunction
640
+ stream: JustoStreamFunction
641
+ }
642
+ }
643
+ }
644
+
645
+ async function callLocalPreviewCli<T>(command: string) {
646
+ const endpoint = (import.meta.env as ImportMetaEnvWithJusto).VITE_JUSTO_CLI_ENDPOINT
647
+
648
+ if (!endpoint) {
649
+ throw new Error(
650
+ 'window.justo.cli no está disponible. Ejecuta team-cli spaces preview --path . para probar esta app localmente o publícala dentro de Justo Spaces.',
651
+ )
652
+ }
653
+
654
+ const response = await fetch(endpoint, {
655
+ method: 'POST',
656
+ headers: {'Content-Type': 'application/json'},
657
+ body: JSON.stringify({command}),
658
+ })
659
+
660
+ const payload = (await response.json()) as {result?: T; error?: string}
661
+ if (!response.ok) {
662
+ throw new Error(payload.error || 'justoCli failed')
663
+ }
664
+
665
+ return payload.result as T
666
+ }
667
+
668
+ async function callLocalPreviewStream<T>(
669
+ command: string,
670
+ onRow: (row: T) => Promise<void> | void,
671
+ ) {
672
+ const endpoint = (import.meta.env as ImportMetaEnvWithJusto).VITE_JUSTO_STREAM_ENDPOINT
673
+
674
+ if (!endpoint) {
675
+ throw new Error(
676
+ 'window.justo.stream no está disponible. Ejecuta team-cli spaces preview --path . para probar esta app localmente o publícala dentro de Justo Spaces.',
677
+ )
678
+ }
679
+
680
+ const response = await fetch(endpoint, {
681
+ method: 'POST',
682
+ headers: {'Content-Type': 'application/json'},
683
+ body: JSON.stringify({command}),
684
+ })
685
+
686
+ if (!response.ok) {
687
+ const payload = (await response.json().catch(() => ({}))) as {error?: string}
688
+ throw new Error(payload.error || 'justoStream failed')
689
+ }
690
+
691
+ if (!response.body) {
692
+ throw new Error('justoStream no recibió datos')
693
+ }
694
+
695
+ const reader = response.body.getReader()
696
+ const decoder = new TextDecoder()
697
+ let buffer = ''
698
+ let rowCount = 0
699
+
700
+ while (true) {
701
+ const result = await reader.read()
702
+ if (result.done) break
703
+
704
+ buffer += decoder.decode(result.value, {stream: true})
705
+
706
+ let newlineIndex = buffer.indexOf('\\n')
707
+ while (newlineIndex >= 0) {
708
+ const line = buffer.slice(0, newlineIndex).trim()
709
+ buffer = buffer.slice(newlineIndex + 1)
710
+ if (line) {
711
+ rowCount += 1
712
+ await onRow(JSON.parse(line) as T)
713
+ }
714
+ newlineIndex = buffer.indexOf('\\n')
715
+ }
716
+ }
717
+
718
+ buffer += decoder.decode()
719
+ if (buffer.trim()) {
720
+ rowCount += 1
721
+ await onRow(JSON.parse(buffer.trim()) as T)
722
+ }
723
+
724
+ return {rowCount}
725
+ }
726
+
727
+ export async function justoCli<T = unknown>(command: string) {
728
+ if (window.justo?.cli) {
729
+ return await window.justo.cli<T>(command)
730
+ }
731
+
732
+ return await callLocalPreviewCli<T>(command)
733
+ }
734
+
735
+ export async function justoStream<T = unknown>(
736
+ command: string,
737
+ onRow: (row: T) => Promise<void> | void,
738
+ ) {
739
+ if (window.justo?.stream) {
740
+ return await window.justo.stream<T>(command, onRow)
741
+ }
742
+
743
+ return await callLocalPreviewStream<T>(command, onRow)
744
+ }
745
+ `}function Rt(e){return`# ${e}
746
+
747
+ Starter de Justo Spaces generado por \`team-cli spaces init\`.
748
+
749
+ Incluye:
750
+ - React + Vite
751
+ - Tailwind
752
+ - todos los componentes shadcn
753
+ - chart wrapper de shadcn + recharts
754
+ - mapas con \`react-leaflet\` + MapTiler/OpenStreetMap
755
+ - helper \`justoCli(...)\` para llamar \`window.justo.cli(...)\`
756
+ - helper \`justoStream(...)\` para consumir NDJSON desde el CLI
757
+
758
+ Reglas de diseño:
759
+ - preferir siempre shadcn
760
+ - usar solo light mode
761
+ - usar paleta de colores neutra
762
+
763
+ Flujo recomendado:
764
+ 1. \`team-cli spaces create --name '...' --description '...' --slug ...\`
765
+ 2. \`team-cli spaces preview --path . --open\`
766
+ 3. desarrolla esta app
767
+ 4. \`team-cli spaces publish <spaceId> --path .\`
768
+ 5. abre el space en intra
769
+
770
+ Tip:
771
+ - usa \`spaces preview --open\` para abrir el dashboard en el navegador por defecto y mostrárselo al usuario mientras lo iteras
772
+ `}function vt(){return`import {StrictMode} from 'react'
773
+ import {createRoot} from 'react-dom/client'
774
+ import App from './App.tsx'
775
+ import './index.css'
776
+ import {ThemeProvider} from '@/components/theme-provider.tsx'
777
+
778
+ createRoot(document.getElementById('root')!).render(
779
+ <StrictMode>
780
+ <ThemeProvider defaultTheme="light">
781
+ <App />
782
+ </ThemeProvider>
783
+ </StrictMode>,
784
+ )
785
+ `}var Qt=".justo-space.json";function ce(e,t,o){Nr(e,t,{cwd:o,stdio:"inherit",env:{...process.env,CI:"1"}})}function vr(e){if(!e)throw Error("Falta --path. Ejemplo: team-cli spaces init --path ./mi-space-app");let t=Ut(e);if(me(t)){if(Rr(t).length>0)throw Error(`La carpeta ya existe y no está vacía: ${t}`);Ee(t,{recursive:!0,force:!0})}return Ar(Tt(t),{recursive:!0}),t}function Or(e){let t=f(e,"vite.config.ts"),o=ue(t,"utf-8");if(o.includes("base: './'"))return;let r=o.replace("export default defineConfig({",`export default defineConfig({
786
+ base: './',`);A(t,r)}function Tr(e){let t=f(e,"tsconfig.app.json"),r=ue(t,"utf-8").replace('"noUnusedLocals": true,','"noUnusedLocals": false,').replace('"noUnusedParameters": true,','"noUnusedParameters": false,');A(t,r)}function Ur(e){let t=f(e,"package.json"),o=JSON.parse(ue(t,"utf-8"));o.dependencies=o.dependencies||{},o.devDependencies=o.devDependencies||{},o.dependencies.leaflet="^1.9.4",o.dependencies["react-leaflet"]="^5.0.0",o.devDependencies["@types/leaflet"]="^1.9.20",o.justoSpaceApp=!0,A(t,`${JSON.stringify(o,null,2)}
787
+ `)}function Qr(e){let t=f(e,"src","index.css"),o=ue(t,"utf-8");if(o.includes("leaflet/dist/leaflet.css"))return;A(t,`@import "leaflet/dist/leaflet.css";
788
+ ${o}`)}function Jr(e){let t=Ot(e);A(f(e,"README.md"),Rt(t)),A(f(e,"src","App.tsx"),Nt()),A(f(e,"src","main.tsx"),vt()),A(f(e,"src","lib","justo.ts"),At()),A(f(e,Qt),`${JSON.stringify({template:"react-vite-shadcn",version:1},null,2)}
789
+ `),Ee(f(e,".git"),{recursive:!0,force:!0})}function Wr(e){Ee(f(e,"package-lock.json"),{force:!0})}function je(e){let t=Ut(e);if(!me(t))throw Error(`No existe la app del space: ${t}`);if(!me(f(t,Qt)))throw Error("Este publish solo acepta apps creadas con team-cli spaces init. Debes apuntar al root de esa app.");return t}function Jt(e){let t=je(e);ce("yarn",["build"],t);let o=f(t,"dist");if(!me(f(o,"index.html")))throw Error("El build no generó dist/index.html");return o}function Wt(e){let t=vr(e),o=Tt(t),r=Ot(t);return ce("npx",["shadcn@latest","init","-t","vite","-d","-y","-n",r],o),ce("npx",["shadcn@latest","add","-a","-y"],t),Wr(t),Ur(t),ce("yarn",["install"],t),Or(t),Tr(t),Qr(t),Jr(t),{path:t,nextSteps:[`cd ${t}`,"team-cli spaces create --name '...' --description '...' --slug mi-space","team-cli spaces publish <spaceId> --path ."]}}function Mt(e){let t=[],o="",r=null,a=!1;for(let i of e){if(a){o+=i,a=!1;continue}if(i==="\\"){a=!0;continue}if(r){if(i===r)r=null;else o+=i;continue}if(i==='"'||i==="'"){r=i;continue}if(/\s/.test(i)){if(o)t.push(o),o="";continue}o+=i}if(r)throw Error("Comando inválido: falta cerrar una comilla");if(o)t.push(o);return t}var Zr=".justo-space-preview",Dr="preview.json",zr=30000;function ge(e){return pe(e,Zr)}function Zt(e){return pe(ge(e),Dr)}function _t(e){return pe(ge(e),"bridge.log")}function Bt(e){return pe(ge(e),"vite.log")}function Dt(e){_r(ge(e),{recursive:!0})}function le(e){if(!e)return;try{process.kill(e,"SIGTERM")}catch{return}}function kr(e){if(process.platform==="darwin")return{command:"open",args:[e]};if(process.platform==="win32")return{command:"cmd",args:["/c","start","",e]};return{command:"xdg-open",args:[e]}}async function Kr(e,t){if(!t)return{attempted:!1,opened:!1};let o=kr(e);return await new Promise((r)=>{let a=de(o.command,o.args,{stdio:"ignore",detached:!0});a.once("error",()=>{r({attempted:!0,opened:!1,message:"No se pudo abrir el navegador por defecto automáticamente. Abre la URL manualmente."})}),a.once("spawn",()=>{a.unref(),r({attempted:!0,opened:!0})})})}function Vr(e){let t=Zt(e);if(!Mr(t))return;try{let o=JSON.parse(Gr(t,"utf-8"));le(o.appPid),le(o.bridgePid)}catch{}Pr(t,{force:!0})}function Gt(){return new Promise((e,t)=>{let o=Ht();o.listen(0,"127.0.0.1",()=>{let r=o.address();if(!r||typeof r==="string"){o.close(),t(Error("No se pudo obtener un puerto libre"));return}let{port:a}=r;o.close((i)=>{if(i){t(i);return}e(a)})}),o.on("error",t)})}function Pt(e){return new Promise((t)=>setTimeout(t,e))}function Lr(e){return new Promise((t,o)=>{let i=(new URL(e).protocol==="https:"?Yr:Hr)(e,{method:"GET"},(n)=>{t(n.statusCode||0),n.resume()});i.on("error",o),i.end()})}async function Ft(e,t=zr){let o=Date.now();while(Date.now()-o<t){try{if(await Lr(e)>0)return}catch{await Pt(500);continue}await Pt(500)}throw Error(`Timeout esperando que el preview responda en ${e}`)}function ea(e){return Dt(Xr(e)),Br(e,"a")}function Xt(e,t,o,r,a){let i=ea(r),n=de(e,t,{cwd:o,detached:!0,stdio:["ignore",i,i],env:{...process.env,...a}});if(!n.pid)throw Error(`No se pudo iniciar el proceso ${e}`);return n.unref(),n.pid}function zt(){let e=ze("prod");if(!e)throw Error("Debes iniciar sesión en prod antes de usar spaces preview. Recomendado: team-cli auth request-code --email <email> y luego team-cli auth login-with-token --email <email> --token <token> --code <CODIGO>");return e}async function ta(e){let t=[];for await(let o of e)t.push(Buffer.isBuffer(o)?o:Buffer.from(o));return Buffer.concat(t).toString("utf-8")}function D(e,t,o){e.writeHead(t,{"Content-Type":"application/json; charset=utf-8","Access-Control-Allow-Origin":"*","Access-Control-Allow-Headers":"Content-Type","Access-Control-Allow-Methods":"POST,OPTIONS,GET"}),e.end(JSON.stringify(o))}function Ne(e){let t=e.trim(),o=new Set([0]);for(let a=0;a<t.length;a++)if(t[a]==="{"||t[a]==="[")o.add(a);let r=[...o].sort((a,i)=>i-a);for(let a of r)try{return JSON.parse(t.slice(a))}catch{continue}return t}function kt(e){return{...process.env,NODE_OPTIONS:"",__JUSTO_REPL_PORT:"",JUSTO_TEAM_CLI_EMAIL:e.email,JUSTO_TEAM_CLI_TOKEN:e.token,JUSTO_TEAM_CLI_REFRESH_TOKEN:e.refreshToken,JUSTO_TEAM_CLI_INTERACTIVE:"false",JUSTO_TEAM_CLI_DEVICE_ID:"spaces-preview"}}function oa(e,t,o,r){return new Promise((a,i)=>{let n=de("node",[t,"--env","prod",...r,"--format","json"],{cwd:process.cwd(),env:kt(o),stdio:["ignore","pipe","pipe"]}),s="";n.stdout.on("data",(c)=>{if(!e.headersSent)e.writeHead(200,{"Content-Type":"application/x-ndjson; charset=utf-8","Access-Control-Allow-Origin":"*","Access-Control-Allow-Headers":"Content-Type","Access-Control-Allow-Methods":"POST,OPTIONS,GET"});e.write(c)}),n.stderr.on("data",(c)=>{s+=Buffer.from(c).toString("utf-8")}),n.on("error",i),n.on("close",(c)=>{if(!c){if(!e.headersSent)e.writeHead(200,{"Content-Type":"application/x-ndjson; charset=utf-8","Access-Control-Allow-Origin":"*","Access-Control-Allow-Headers":"Content-Type","Access-Control-Allow-Methods":"POST,OPTIONS,GET"});e.end(),a();return}let u=Ne(s.trim());i(Error(u.error||s.trim()||"justoStream failed"))})})}async function Kt(e){let t=Number(e.port);if(!t)throw Error("Falta --port para el bridge interno de preview");let o=zt(),r=Yt(e["cli-path"]||process.argv[1]||""),a=Ht(async(i,n)=>{if(i.method==="OPTIONS"){D(n,200,{ok:!0});return}if(i.method==="GET"&&i.url==="/__justo/health"){D(n,200,{ok:!0});return}if(i.method!=="POST"||i.url!=="/__justo/cli"&&i.url!=="/__justo/stream"){D(n,404,{ok:!1,error:"Not found"});return}try{let s=await ta(i),u=JSON.parse(s||"{}").command;if(!u)throw Error("Debes indicar un comando");let l=Array.isArray(u)?u:Mt(u);if(i.url==="/__justo/stream"){await oa(n,r,o,l);return}let g=await new Promise((p,C)=>{let w=de("node",[r,"--env","prod",...l,"--format","json"],{cwd:process.cwd(),env:kt(o),stdio:["ignore","pipe","pipe"]}),V=[],Q=[];w.stdout.on("data",(v)=>V.push(Buffer.from(v))),w.stderr.on("data",(v)=>Q.push(Buffer.from(v))),w.on("error",C),w.on("close",(v)=>{let B=Buffer.concat(V).toString("utf-8")||Buffer.concat(Q).toString("utf-8");if(v&&v!==0){let vo=Ne(B);C(Error(vo.error||B||"justoCli failed"));return}p(Ne(B))})});D(n,200,{result:g})}catch(s){let c=s instanceof Error?s.message:"Unexpected error";D(n,400,{error:c})}});await new Promise((i,n)=>{a.listen(t,"127.0.0.1",()=>i()),a.on("error",n)}),y(`Space preview bridge listening on http://127.0.0.1:${t}
790
+ `),await new Promise((i,n)=>{a.on("close",()=>i()),a.on("error",n)})}async function Vt(e){let t=e.path;if(!t)throw Error("Falta --path. Ejemplo: team-cli spaces preview --path ./mi-space-app");let o=je(t);zt(),Dt(o),Vr(o);let r=Number(e.port)||await Gt(),a=Number(e["bridge-port"])||await Gt(),i=e.open==="true",n=`http://127.0.0.1:${r}`,s=`http://127.0.0.1:${a}/__justo/cli`,c=`http://127.0.0.1:${a}/__justo/stream`,u=Yt(process.argv[1]||""),l=Xt("node",[u,"__spaces-preview-bridge","--port",String(a),"--cli-path",u],process.cwd(),_t(o),{}),g=Xt("yarn",["dev","--host","127.0.0.1","--port",String(r)],o,Bt(o),{VITE_JUSTO_CLI_ENDPOINT:s,VITE_JUSTO_STREAM_ENDPOINT:c,VITE_JUSTO_CLI_MODE:"preview"});try{await Ft(`http://127.0.0.1:${a}/__justo/health`),await Ft(n)}catch(w){throw le(g),le(l),w}let p={appPid:g,bridgePid:l,previewUrl:n,bridgeUrl:s,streamUrl:c,cliEnv:"prod"};Fr(Zt(o),`${JSON.stringify(p,null,2)}
791
+ `);let C=await Kr(n,i);return{ok:!0,path:o,previewUrl:n,bridgeUrl:s,streamUrl:c,cliEnv:"prod",appPid:g,bridgePid:l,logs:{app:Bt(o),bridge:_t(o)},open:C}}import{writeFileSync as pa}from"node:fs";import{mkdtempSync as ra,readFileSync as aa,rmSync as ia,writeFileSync as na}from"node:fs";import{tmpdir as sa}from"node:os";import{join as Lt}from"node:path";import{spawnSync as ca}from"node:child_process";function ma(e){return`'${e.replaceAll("'",`'"'"'`)}'`}function eo(e,t){if(e==null)return;if(!Array.isArray(e)||e.some((o)=>typeof o!=="string"))throw Error(`${t} debe ser un arreglo de strings.`);return e}function ua(e){if(!Array.isArray(e))throw Error("variables debe ser un arreglo.");return e.map((t,o)=>{if(!t||typeof t!=="object"||Array.isArray(t))throw Error(`variables[${o}] debe ser un objeto.`);let r=t;if(typeof r.key!=="string"||!r.key)throw Error(`variables[${o}].key debe ser un string no vacío.`);if(typeof r.fieldType!=="string"||!r.fieldType)throw Error(`variables[${o}].fieldType debe ser un string no vacío.`);if(r.fieldParams!=null&&typeof r.fieldParams!=="string")throw Error(`variables[${o}].fieldParams debe ser un string.`);return{key:r.key,fieldType:r.fieldType,fieldParams:typeof r.fieldParams==="string"?r.fieldParams:void 0}})}function la(e){if(!e||typeof e!=="object"||Array.isArray(e))throw Error("El archivo editado debe contener un objeto JSON.");let t=e;if(typeof t.name!=="string"||!t.name.trim())throw Error("name debe ser un string no vacío.");if(t.description!=null&&typeof t.description!=="string")throw Error("description debe ser un string.");if(typeof t.collection!=="string"||!t.collection.trim())throw Error("collection debe ser un string no vacío.");if(typeof t.pipeline!=="string")throw Error("pipeline debe ser un string.");return{name:t.name.trim(),description:t.description?.trim()||void 0,collection:t.collection.trim(),allowedUsersIds:eo(t.allowedUsersIds,"allowedUsersIds")??[],tags:eo(t.tags,"tags")??[],pipeline:t.pipeline,variables:ua(t.variables)}}function to(e){let t=process.env.VISUAL||process.env.EDITOR||"vi",o=ra(Lt(sa(),"team-cli-query-")),r=Lt(o,"aggregation-query.json");na(r,`${JSON.stringify(e,null,2)}
792
+ `);let a=`${t} ${ma(r)}`,i=ca(a,{shell:!0,stdio:"inherit"});if(i.error)throw Error(`No se pudo abrir el editor "${t}": ${i.error.message}`);if(i.status!==0)throw Error(`El editor terminó con código ${i.status}.`);try{let n=aa(r,"utf-8");if(!n.trim())throw Error("El archivo quedó vacío.");let s;try{s=JSON.parse(n)}catch{throw Error("El archivo editado no contiene JSON válido.")}return la(s)}finally{ia(o,{recursive:!0,force:!0})}}function R(){if(!d())throw Error("Debes iniciar sesión primero. Recomendado: team-cli auth request-code --email <email> y luego team-cli auth login-with-token --email <email> --token <token> --code <CODIGO>")}function T(e,t){let o=e[3];if(!o)throw Error(`Uso: ${t}`);return o}function z(e){if(!e.params)return{};try{return JSON.parse(e.params)}catch{throw Error("--params debe ser un JSON válido.")}}function oo(e){let t=e.limit;if(!t)throw Error("--limit es requerido. Ejemplo: --limit 1000");let o=Number(t);if(!Number.isInteger(o)||o<=0)throw Error("--limit debe ser un entero positivo.");return o}function Ae(e){if(typeof e!=="string")return e;try{return JSON.parse(e)}catch{return{value:e}}}async function k(e){return(await m({service:"data",query:`query ($aggregationQueryId: String) {
439
793
  aggregationQuery(aggregationQueryId: $aggregationQueryId) {
440
794
  _id
441
795
  name
442
796
  description
443
797
  collection
444
798
  currentVersionIndex
799
+ allowedUsersIds
800
+ tags
801
+ pipeline
445
802
  variables {
446
803
  key
447
804
  fieldType
448
805
  fieldParams
449
806
  }
450
807
  }
451
- }`,variables:{aggregationQueryId:t}})).aggregationQuery}async function ct(o){k();let t=K(o,"team-cli data queries view-pipeline <queryId>"),e=await c({service:"data",query:`query ($aggregationQueryId: String) {
452
- aggregationQuery(aggregationQueryId: $aggregationQueryId) {
808
+ }`,variables:{aggregationQueryId:e}})).aggregationQuery}function ro(e){return{name:e.name,description:e.description,collection:e.collection,allowedUsersIds:e.allowedUsersIds??[],tags:e.tags??[],pipeline:e.pipeline,variables:e.variables??[]}}async function Re(e,t){let o=await m({service:"data",query:`mutation ($aggregationQueryId: String, $params: JSON) {
809
+ testAggregationQuery(aggregationQueryId: $aggregationQueryId, params: $params)
810
+ }`,variables:{aggregationQueryId:e,params:t}});return Ae(o.testAggregationQuery)}function da(e){try{return JSON.parse(e).error||e}catch{return e}}async function ao(e,t,o){let r=await fetch(`${$("data")}/aggregation-queries/${e}/run`,{method:"POST",headers:await xe(),body:JSON.stringify({params:t,limit:o}),signal:AbortSignal.timeout(315000)});if(!r.ok){let u=await r.text();throw Error(da(u)||"No se pudo ejecutar el query.")}if(!r.body)throw Error("El servidor no devolvió un stream de datos.");let a=r.body.getReader(),i=new TextDecoder,n="",s=0;while(!0){let{done:u,value:l}=await a.read();if(u)break;let g=i.decode(l,{stream:!0});process.stdout.write(g),n+=g;let p=n.indexOf(`
811
+ `);while(p>=0){if(n.slice(0,p).trim())s++;n=n.slice(p+1),p=n.indexOf(`
812
+ `)}}let c=i.decode();if(c)process.stdout.write(c),n+=c;if(n.trim())s++;return{ok:!0,queryId:e,limit:o,rows:s}}async function ve(e,t){await m({service:"data",query:`mutation ($aggregationQueryId: String, $aggregationQuery: UpdateAggregationQueryInput) {
813
+ updateAggregationQuery(
814
+ aggregationQueryId: $aggregationQueryId
815
+ aggregationQuery: $aggregationQuery
816
+ ) {
817
+ _id
818
+ name
819
+ description
820
+ collection
821
+ allowedUsersIds
822
+ tags
823
+ currentVersionIndex
824
+ }
825
+ }`,variables:{aggregationQueryId:e,aggregationQuery:{name:t.name,description:t.description,collection:t.collection,allowedUsersIds:t.allowedUsersIds,tags:t.tags}}}),await m({service:"data",query:`mutation ($aggregationQueryId: String, $pipeline: String, $variables: [AggregationQueryVariableInput]) {
826
+ addAggregationQueryVersion(
827
+ aggregationQueryId: $aggregationQueryId
828
+ pipeline: $pipeline
829
+ variables: $variables
830
+ ) {
831
+ _id
832
+ currentVersionIndex
833
+ }
834
+ }`,variables:{aggregationQueryId:e,pipeline:t.pipeline,variables:t.variables}})}async function io(){return(await m({service:"data",query:`mutation {
835
+ createAggregationQuery {
836
+ _id
837
+ name
838
+ description
839
+ collection
840
+ currentVersionIndex
841
+ allowedUsersIds
842
+ tags
843
+ pipeline
844
+ variables {
845
+ key
846
+ fieldType
847
+ fieldParams
848
+ }
849
+ }
850
+ }`})).createAggregationQuery}function ga(e){if(!Array.isArray(e))throw Error("El preview del query debe devolver un arreglo para usar AI edit.");return e}async function fa(e){let t=await m({service:"messenger",query:`mutation generateAdminQuery(
851
+ $prompt: String
852
+ $name: String
853
+ $description: String
854
+ $fullCollectionName: String
855
+ $variables: [JSON]
856
+ $pipeline: String
857
+ $preview: [JSON]
858
+ ) {
859
+ generateAdminQuery(
860
+ prompt: $prompt
861
+ name: $name
862
+ description: $description
863
+ fullCollectionName: $fullCollectionName
864
+ variables: $variables
865
+ pipeline: $pipeline
866
+ preview: $preview
867
+ canUseVariables: true
868
+ ) {
869
+ responseText
870
+ fullCollectionName
453
871
  pipeline
872
+ variables
873
+ aggregationDescription
874
+ aggregationName
454
875
  }
455
- }`,variables:{aggregationQueryId:t}});return{queryId:t,pipeline:e.aggregationQuery.pipeline}}async function mt(o,t){k();let e=K(o,"team-cli data queries preview <queryId> --params '<json>'"),i=nt(t),r=await c({service:"data",query:`mutation ($aggregationQueryId: String, $params: JSON) {
456
- testAggregationQuery(aggregationQueryId: $aggregationQueryId, params: $params)
457
- }`,variables:{aggregationQueryId:e,params:i}});return fe(r.testAggregationQuery)}function be(o){return new Promise((t)=>setTimeout(t,o))}async function ut(o,t){k();let e=K(o,"team-cli data queries download <queryId> --params '<json>'"),i=nt(t);if(!t.path)throw Error("--path es requerido. Ejemplo: --path resultado.xlsx");let r=t.path;I(`Iniciando descarga...
458
- `);let n=(await c({service:"data",query:`mutation ($aggregationQueryId: String, $params: JSON) {
876
+ }`,variables:e});if(!t.generateAdminQuery?.pipeline||!t.generateAdminQuery.fullCollectionName)throw Error("La IA no devolvió una versión válida del query.");return t.generateAdminQuery}async function no(){return R(),await io()}async function so(e){R();let t=T(e,"team-cli data queries edit <queryId>"),o=await k(t),r=to(ro(o));return await ve(t,r),{ok:!0,queryId:t,name:r.name,collection:r.collection}}async function co(e,t){R();let o=T(e,"team-cli data queries ai-edit <queryId> --prompt '<texto>' [--params '<json>']"),r=await k(o),a=t.prompt||await Z("Describe los cambios para la IA: ");if(!a)throw Error("Debes indicar un prompt para AI edit.");let i=z(t),n;if(t.params){y(`Obteniendo preview del query actual...
877
+ `);try{let c=await Re(o,i);n=ga(c)}catch(c){let u=c instanceof Error?c.message:String(c);throw Error(`No se pudo obtener el preview para AI edit: ${u}`)}}y(`Generando propuesta con IA...
878
+ `);let s=await fa({prompt:a,fullCollectionName:r.collection,pipeline:r.pipeline,preview:n,description:r.description,name:r.name,variables:r.variables});return await ve(o,{name:r.name==="Nuevo query"?s.aggregationName||r.name:r.name,description:r.description||s.aggregationDescription,collection:s.fullCollectionName,allowedUsersIds:r.allowedUsersIds??[],tags:r.tags??[],pipeline:s.pipeline,variables:s.variables??[]}),{ok:!0,queryId:o,responseText:s.responseText,collection:s.fullCollectionName,name:s.aggregationName,description:s.aggregationDescription}}async function mo(e){R();let t=T(e,"team-cli data queries view <queryId>");return await k(t)}async function uo(e){R();let t=T(e,"team-cli data queries view-pipeline <queryId>"),o=await k(t);return{queryId:t,pipeline:o.pipeline}}async function lo(e,t){R();let o=T(e,"team-cli data queries preview <queryId> --params '<json>'"),r=z(t),a=await Re(o,r);return Ae(a)}async function po(e,t){R();let o=T(e,"team-cli data queries run <queryId> --limit <n> --params '<json>'"),r=z(t),a=oo(t);return await ao(o,r,a),{__streamHandled:!0}}function wa(e){return new Promise((t)=>setTimeout(t,e))}async function go(e,t){R();let o=T(e,"team-cli data queries download <queryId> --params '<json>'"),r=z(t);if(!t.path)throw Error("--path es requerido. Ejemplo: --path resultado.xlsx");y(`Iniciando descarga...
879
+ `);let i=(await m({service:"data",query:`mutation ($aggregationQueryId: String, $params: JSON) {
459
880
  downloadAggregationQueryData(aggregationQueryId: $aggregationQueryId, params: $params)
460
- }`,variables:{aggregationQueryId:e,params:i}})).downloadAggregationQueryData;I(`Reporte en proceso (${n})...
461
- `);let a=null;while(!a){await be(1000);let b=await c({service:"data",query:`query ($id: String) {
881
+ }`,variables:{aggregationQueryId:o,params:r}})).downloadAggregationQueryData;y(`Reporte en proceso (${i})...
882
+ `);let n=null;while(!n){await wa(1000);let u=await m({service:"data",query:`query ($id: String) {
462
883
  getAsyncReport(id: $id) {
463
884
  _id
464
885
  status
@@ -466,16 +887,34 @@ Notas:
466
887
  fileUrl
467
888
  }
468
889
  getAsyncReportRecordsCount(id: $id)
469
- }`,variables:{id:n}}),q=b.getAsyncReport,j=b.getAsyncReportRecordsCount;if(q.status==="error")throw Error("El reporte falló al generarse.");if(q.fileUrl)a=q.fileUrl;else{let G=q.estimatedRecordsCount?` (~${q.estimatedRecordsCount} registros)`:"",x=j!=null?` ${j} procesados`:"";I(`\rGenerando...${G}${x}`)}}I(`
470
- `),I(`Descargando archivo...
471
- `);let u=await fetch(a);if(!u.ok)throw Error(`Error descargando archivo: ${u.status}`);let y=Buffer.from(await u.arrayBuffer());return we(r,y),{ok:!0,queryId:e,asyncReportId:n,outputPath:r,fileUrl:a}}function go(){return`team-cli data
890
+ }`,variables:{id:i}}),l=u.getAsyncReport,g=u.getAsyncReportRecordsCount;if(l.status==="error")throw Error("El reporte falló al generarse.");if(l.fileUrl)n=l.fileUrl;else{let p=l.estimatedRecordsCount?` (~${l.estimatedRecordsCount} registros)`:"",C=g!=null?` ${g} procesados`:"";y(`\rGenerando...${p}${C}`)}}y(`
891
+ Descargando archivo...
892
+ `);let s=await fetch(n);if(!s.ok)throw Error(`Error descargando archivo: ${s.status}`);let c=Buffer.from(await s.arrayBuffer());return pa(t.path,c),{ok:!0,queryId:o,asyncReportId:i,outputPath:t.path,fileUrl:n}}function Oe(){return`team-cli data
472
893
 
473
894
  Comandos de datos y reportes.
474
895
 
896
+ Recomendado:
897
+ Si necesitas obtener data y no existe un query listo, usa create + ai-edit.
898
+ Flujo sugerido: create -> ai-edit -> preview -> run o download.
899
+
475
900
  Uso:
476
901
  team-cli data queries <subcomando> [opciones]
477
902
 
478
903
  Subcomandos:
904
+ create
905
+ Crear un query nuevo.
906
+ Devuelve el _id para seguir con edit, ai-edit, view o preview.
907
+
908
+ edit <queryId>
909
+ Editar un query manualmente en tu editor local usando JSON.
910
+ Campos editables: name, description, collection, allowedUsersIds, tags, pipeline, variables.
911
+ El pipeline debe quedar como string con un array JavaScript válido.
912
+
913
+ ai-edit <queryId>
914
+ Editar un query con IA.
915
+ Uso: team-cli data queries ai-edit <queryId> --prompt '<texto>' [--params '<json>'] [--format toon|json]
916
+ Si envías --params, primero se ejecuta preview y esos resultados se adjuntan al prompt.
917
+
479
918
  view <queryId>
480
919
  Ver informacion de un query.
481
920
 
@@ -486,215 +925,237 @@ Subcomandos:
486
925
  Ejecutar un query de prueba.
487
926
  Uso: team-cli data queries preview <queryId> --params '<json>' [--format toon|json]
488
927
 
928
+ run <queryId>
929
+ Ejecutar un query completo en streaming NDJSON.
930
+ Usa timeout de 5 minutos y read preference secondaryPreferred.
931
+ Uso: team-cli data queries run <queryId> --limit <n> [--params '<json>']
932
+
489
933
  download <queryId>
490
934
  Descargar resultado completo como Excel.
491
935
  Uso: team-cli data queries download <queryId> --path <filepath> [--params '<json>'] [--format toon|json]
492
936
 
493
937
  Opciones:
494
938
  --params '<json>' Parametros del query. Default: {}
939
+ --limit <n> Requerido para run. Máximo 10000 por request.
940
+ --prompt '<texto>' Prompt para ai-edit. Si no viene, se pide interactivamente.
495
941
  --format <toon|json>
496
942
  --path <filepath> Requerido para download
497
943
 
498
944
  Ejemplos:
499
- team-cli data queries view abc123
500
- team-cli data queries view-pipeline abc123
945
+ team-cli data queries create
946
+ team-cli data queries edit abc123
947
+ team-cli data queries ai-edit abc123 --prompt 'Filtra solo ordenes canceladas'
948
+ team-cli data queries ai-edit abc123 --prompt 'Ajusta el pipeline' --params '{"websiteId":"w1"}'
501
949
  team-cli data queries preview abc123 --params '{"startDate": "2026-01-01"}'
502
- team-cli data queries download abc123 --params '{"startDate": "2026-01-01"}' --path resultado.xlsx`}var qe=["local","develop","prod"];function gt(){return Object.keys(X)}function Ce(){return gt().map((o)=>{return[`- \`${o}\``,...qe.map((e)=>{let i=X[o][e];return` - ${e}: \`${i}/graphql\``})].join(`
503
- `)}).join(`
504
- `)}function Ie(){let t=gt().join(", "),e=Ce();return`# @getjusto/team-cli
505
-
506
- CLI tool for Justo team members. Authenticated access to Justo's GraphQL services and data queries.
507
-
508
- ## Prerequisites
509
-
510
- The CLI must be authenticated. Check with:
511
- \`\`\`bash
512
- npx @getjusto/team-cli auth status
513
- \`\`\`
950
+ team-cli data queries run abc123 --limit 1000 --params '{"startDate": "2026-01-01"}'
951
+ team-cli data queries download abc123 --params '{"startDate": "2026-01-01"}' --path resultado.xlsx`}var fo=["main","auth","webdata","preferences","buckets","reservations","data","finances","url-shortener","files","tabs","commander","experiments","sales","delivery","payments","addresses","royalty","marketing","api","messenger","invoice","drivers-server"],wo=`
952
+ query ResolverInfo($name: ID!, $mutation: Boolean!) {
953
+ params(name: $name, mutation: $mutation) {
954
+ name
955
+ params
956
+ result
957
+ basicResultQuery
958
+ }
959
+ }
960
+ `;function ba(e){if(!e)throw Error("Uso: team-cli graphql <servicio> '<query>' [--variables '<json>'] [--format toon|json]");if(!fo.includes(e))throw Error(`Servicio "${e}" no válido. Servicios disponibles: ${fo.join(", ")}`)}async function ya(e,t){let o;try{let r=await m({service:e,query:wo,variables:{name:t,mutation:!1}});return{service:e,operationName:t,operationType:"query",info:r.params}}catch(r){o=r}try{let r=await m({service:e,query:wo,variables:{name:t,mutation:!0}});return{service:e,operationName:t,operationType:"mutation",info:r.params}}catch(r){let a=o instanceof Error?o.message:"",i=r instanceof Error?r.message:"";if(a.includes('Cannot query field "params"')||i.includes('Cannot query field "params"'))throw Error(`El servicio "${e}" no expone metadata de resolvers por GraphQL.`);throw o instanceof Error?o:r}}async function bo(e,t){let o=e[1],r=e[2],a=e[2];if(!d())throw Error("Debes iniciar sesión primero. Recomendado: team-cli auth request-code --email <email> y luego team-cli auth login-with-token --email <email> --token <token> --code <CODIGO>");if(ba(o),r==="info"){let s=e[3];if(!s)throw Error("Uso: team-cli graphql <servicio> info <queryName|mutationName> [--format toon|json]");return await ya(o,s)}if(!a)throw Error("Uso: team-cli graphql <servicio> '<query>' [--variables '<json>'] [--format toon|json]");let i;if(t.variables)try{i=JSON.parse(t.variables)}catch{throw Error("Las variables deben ser un JSON válido.")}return await m({service:o,query:a,variables:i})}function yo(){return Object.keys(oe)}function Ca(){return yo().map((e)=>{let t=oe[e].prod;return`- \`${e}\`: \`${t}/graphql\``}).join(`
961
+ `)}function Co(){let t=yo().join(", "),o=Ca();return`team-cli graphql
514
962
 
515
- If not logged in, the user must log in interactively (you cannot do this):
516
- \`\`\`bash
517
- npx @getjusto/team-cli auth login
518
- \`\`\`
963
+ Ejecutar queries y mutations GraphQL.
519
964
 
520
- ## Global Options
965
+ Uso:
966
+ team-cli graphql <servicio> '<query>' [--variables '<json>'] [--format toon|json]
967
+ team-cli graphql <servicio> info <queryName|mutationName> [--format toon|json]
521
968
 
522
- - \`--env <local|develop|prod>\` — Environment (default: prod)
523
- - \`--format toon|json\` Output format (default: toon)
969
+ Comando info:
970
+ Consulta la metadata publicada por OrionJS para un query o mutation.
971
+ Devuelve el tipo de operación, los params serializados, el resultado y un basicResultQuery.
972
+ Si no indicas si es query o mutation, la CLI prueba ambas automáticamente.
524
973
 
525
- ## Commands
974
+ Formato:
975
+ Por defecto usa toon. Usa --format json para JSON estándar.
526
976
 
527
- ### graphql — Run arbitrary GraphQL queries/mutations
528
977
 
529
- \`\`\`bash
530
- npx @getjusto/team-cli graphql <service> '<query>' [--variables '<json>'] [--format toon|json]
531
- \`\`\`
532
978
 
533
- Available services: ${t}.
979
+ Servicios disponibles: ${t}.
534
980
 
535
- Examples:
981
+ Ejemplos:
536
982
  \`\`\`bash
537
983
  npx @getjusto/team-cli graphql main 'query { me { _id roles } }'
538
984
  npx @getjusto/team-cli graphql main 'query($id: ID) { user(userId: $id) { _id } }' --variables '{"id": "abc123"}'
539
985
  npx @getjusto/team-cli graphql tabs 'query { tab(tabId: "t123") { _id status } }' --format json
540
986
  \`\`\`
541
987
 
542
- ### graphql info — Inspect query/mutation params and result metadata
988
+ ### graphql info
543
989
 
544
- Use this before writing the final GraphQL call when you only know the operation name, or when someone shares a curl and you need to understand the params expected by the resolver.
990
+ Úsalo cuando conoces el nombre del resolver pero no su contrato exacto.
545
991
 
546
992
  \`\`\`bash
547
993
  npx @getjusto/team-cli graphql <service> info <queryName|mutationName> [--format toon|json]
548
994
  \`\`\`
549
995
 
550
- What it returns:
551
- - \`operationType\` — whether Orion exposed it as query or mutation
552
- - \`info.params\` — serialized params schema, including optional fields and GraphQL scalar types
553
- - \`info.result\` — top-level result model/type name when available
554
- - \`info.basicResultQuery\` — a starter field selection you can reuse in the final GraphQL document
996
+ Devuelve:
997
+ - \`operationType\`
998
+ - \`info.params\`
999
+ - \`info.result\`
1000
+ - \`info.basicResultQuery\`
555
1001
 
556
- Examples:
1002
+ Ejemplos:
557
1003
  \`\`\`bash
558
1004
  npx @getjusto/team-cli graphql main info website
559
1005
  npx @getjusto/team-cli graphql auth info requestLoginCode --format json
560
1006
  \`\`\`
561
1007
 
562
- Recommended workflow for converting a curl into team-cli:
563
- 1. Identify the service from the GraphQL URL.
564
- 2. If you know the operation name, inspect it first with \`graphql <service> info <name>\`.
565
- 3. Use \`info.params\` to build the variables object.
566
- 4. Use \`info.basicResultQuery\` as the starting selection set.
567
- 5. Run the final command with \`graphql <service> '<queryOrMutation>' --variables '<json>'\`.
568
-
569
- ### GraphQL Service Map
570
-
571
- Use this when someone shares a GraphQL \`curl\` and you need to map the URL to the correct \`team-cli graphql <service>\` value.
572
-
573
- Rule:
574
- - If the curl points to \`https://something/.../graphql\`, match that URL against the list below and use the corresponding service name.
575
- - In \`team-cli\`, you pass the service name only, not the full URL.
576
-
577
- Service name to endpoint map:
578
- ${e}
579
-
580
- Example conversion:
581
- \`\`\`bash
582
- # curl
583
- curl 'https://tabs.service.getjusto.com/graphql' \\
584
- -H 'content-type: application/json' \\
585
- --data-raw '{"query":"query { tab(tabId: \\"t123\\") { _id status } }"}'
586
-
587
- # inspect the resolver first
588
- npx @getjusto/team-cli graphql tabs info tab
589
-
590
- # team-cli
591
- npx @getjusto/team-cli graphql tabs 'query { tab(tabId: "t123") { _id status } }'
1008
+ ### Mapa de servicios GraphQL
1009
+
1010
+ Usa esto para mapear una URL GraphQL al valor correcto de \`team-cli graphql <service>\`.
1011
+
1012
+ ${o}`}import{execFileSync as qa}from"node:child_process";import{mkdtempSync as Ia,readFileSync as $a,rmSync as xa}from"node:fs";import{tmpdir as ha}from"node:os";import{join as qo,resolve as Sa}from"node:path";function Te(){if(!d())throw Error("Debes iniciar sesión primero. Recomendado: team-cli auth request-code --email <email> y luego team-cli auth login-with-token --email <email> --token <token> --code <CODIGO>")}function K(e,t,o){let r=e[t];if(!r)throw Error(`Falta --${t}. Ejemplo: ${o}`);return r}function Io(e,t){let o=e[2];if(!o)throw Error(`Uso: ${t}`);return o}function Ue(){let e=re();if(e==="local")return"http://intra.localhost:5173";if(e==="develop")return"https://intra.bejusto.com";return"https://intra.getjusto.com"}async function Ea(e,t){let o=await $e(),r=await fetch(`${$("data")}/spaces/publish/${e}`,{method:"POST",headers:{"Content-Type":"application/gzip",...o?{"X-ORION-JWT":o}:{}},body:t}),a=await r.json();if(!r.ok||a.error)throw Error(a.error||"No se pudo publicar el space.");return a}function Qe(){return`team-cli spaces
1013
+
1014
+ Spaces son aplicaciones internas en React, pensadas para que las construyan agentes.
1015
+ El flujo oficial parte con \`spaces init\` y \`spaces publish\` solo acepta apps creadas así.
1016
+
1017
+ Cada space:
1018
+ - vive en data
1019
+ - se desarrolla como app React + Vite
1020
+ - viene con Tailwind y todos los componentes shadcn instalados
1021
+ - publica el resultado de \`yarn build\` a S3 en \`spaces/[slug]/[version]/files/*\`
1022
+ - se sirve en \`/spaces/[slug]\`
1023
+ - el build debe generar \`dist/index.html\`
1024
+ - recibe automáticamente \`<base href="/spaces/[slug]/">\` al servir HTML
1025
+ - además reescribe rutas HTML/CSS que empiecen con \`/\` para que \`/image.jpg\` termine en \`/spaces/[slug]/image.jpg\`
1026
+ - al abrirse desde intra, siembra una cookie del space por 24 horas
1027
+ - esa cookie da acceso al HTML, assets y \`window.justo.cli(...)\` dentro del space
1028
+ - todos los HTML reciben automáticamente \`window.justo.cli(command)\`
1029
+ - \`window.justo.cli(...)\` devuelve Promises, entrega JSON parseado y hace throw en errores
1030
+ - para queries grandes también reciben \`window.justo.stream(command, onRow)\`
1031
+ - \`window.justo.stream(...)\` consume NDJSON, parsea cada fila a JSON y llama tu callback
1032
+
1033
+ Flujo sugerido para agentes:
1034
+ 1. \`team-cli spaces init --path ./mi-space-app\`
1035
+ 2. \`team-cli spaces create --name '...' --description '...' --slug mi-space\`
1036
+ 3. \`team-cli spaces preview --path ./mi-space-app\`
1037
+ 4. desarrollar la app React dentro de esa carpeta
1038
+ 5. \`team-cli spaces publish <spaceId> --path ./mi-space-app\`
1039
+ 6. abrir \`${Ue()}/spaces/<slug>\`
1040
+
1041
+ Qué crea \`spaces init\`:
1042
+ - Vite + React + TypeScript
1043
+ - Tailwind listo para usar
1044
+ - todos los componentes shadcn disponibles en \`src/components/ui\`
1045
+ - charts listos con el wrapper de shadcn + \`recharts\`
1046
+ - mapas listos con \`react-leaflet\` + MapTiler/OpenStreetMap
1047
+ - helper \`justoCli(...)\` en \`src/lib/justo.ts\`
1048
+ - helper \`justoStream(...)\` en \`src/lib/justo.ts\`
1049
+ - ejemplo inicial en \`src/App.tsx\`
1050
+ - configuración para que Vite construya con rutas relativas y funcione dentro del space
1051
+
1052
+ Mapas:
1053
+ - el starter reutiliza el mismo token de MapTiler que ya usa vite-fronts
1054
+ - no necesitas configurar una key adicional para empezar
1055
+
1056
+ Reglas de diseño para agentes:
1057
+ - preferir siempre componentes shadcn antes que UI custom
1058
+ - usar solo light mode
1059
+ - usar paleta de colores neutra
1060
+ - si hace falta color de acento, que sea secundario y sobrio, no la base del diseño
1061
+
1062
+ Qué hace \`spaces preview\`:
1063
+ - levanta Vite localmente para esa app
1064
+ - levanta un bridge local para \`justoCli(...)\`
1065
+ - ese bridge ejecuta \`team-cli\` contra \`prod\`
1066
+ - devuelve la URL local para abrir con browser
1067
+ - si envías \`--open\`, intenta abrir la preview en el navegador por defecto del sistema
1068
+ - \`--open\` es ideal para ir mostrándole al usuario el dashboard mientras el agente lo va construyendo
1069
+
1070
+ Ejemplo desde el propio HTML del space:
1071
+ \`\`\`js
1072
+ import {justoCli, justoStream} from '@/lib/justo'
1073
+
1074
+ const me = await justoCli("graphql main 'query { me { _id email roles } }'")
1075
+ const rows = await justoCli("data queries preview <queryId> --params '{\\"limit\\":10}'")
1076
+ await justoStream(
1077
+ "data queries run <queryId> --limit 1000 --params '{\\"websiteId\\":\\"w1\\"}'",
1078
+ row => {
1079
+ console.log(row)
1080
+ },
1081
+ )
592
1082
  \`\`\`
593
1083
 
594
- ### admin search — Search websites/brands in admin
595
-
596
- Use this when you need to find a website first before calling other admin commands.
597
-
598
- \`\`\`bash
599
- npx @getjusto/team-cli admin search <text> [--limit <n>] [--page <n>] [--only-active true|false]
600
- \`\`\`
1084
+ Comandos:
1085
+ - \`spaces init --path ./mi-space-app\`
1086
+ - \`spaces create --name '...' --description '...' --slug my-space\`
1087
+ - \`spaces preview --path ./mi-space-app [--open]\`
1088
+ - \`spaces publish <spaceId> --path ./mi-space-app\`
1089
+ - \`spaces archive <spaceId>\``}async function $o(e){let t=K(e,"path","team-cli spaces init --path ./mi-space-app");return Wt(t)}async function xo(e){return await Vt(e)}async function ho(e){Te();let t=K(e,"name","team-cli spaces create --name 'Mi space' --description '...' --slug mi-space"),o=K(e,"description","team-cli spaces create --name 'Mi space' --description 'Sitio interno' --slug mi-space"),r=K(e,"slug","team-cli spaces create --name 'Mi space' --description '...' --slug mi-space"),a=await m({service:"data",query:`mutation ($name: String, $description: String, $slug: String) {
1090
+ createSpace(name: $name, description: $description, slug: $slug) {
1091
+ _id
1092
+ name
1093
+ description
1094
+ slug
1095
+ currentVersion
1096
+ createdAt
1097
+ createdByEmail
1098
+ createdById
1099
+ }
1100
+ }`,variables:{name:t,description:o,slug:r}});return{...a.createSpace,intraUrl:`${Ue()}/spaces/${a.createSpace.slug}`,serveUrl:`${$("data")}/spaces/${a.createSpace.slug}`}}async function So(e,t){Te();let o=Io(e,"team-cli spaces publish <spaceId> --path ./mi-space-app"),r=K(t,"path","team-cli spaces publish <spaceId> --path ./mi-space-app"),a=Jt(r),i=Ia(qo(ha(),"team-cli-space-")),n=qo(i,"space.tar.gz");try{qa("tar",["-czf",n,"-C",a,"."]);let s=$a(n),c=await Ea(o,s);return{...c,intraUrl:c.slug?`${Ue()}/spaces/${c.slug}`:void 0,serveUrl:c.slug?`${$("data")}/spaces/${c.slug}`:void 0,builtFrom:Sa(r)}}finally{xa(i,{recursive:!0,force:!0})}}async function Eo(e){Te();let t=Io(e,"team-cli spaces archive <spaceId>");return(await m({service:"data",query:`mutation ($spaceId: String) {
1101
+ archiveSpace(spaceId: $spaceId) {
1102
+ _id
1103
+ name
1104
+ description
1105
+ slug
1106
+ currentVersion
1107
+ createdAt
1108
+ createdByEmail
1109
+ createdById
1110
+ archivedAt
1111
+ }
1112
+ }`,variables:{spaceId:t}})).archiveSpace}function jo(e){return`team-cli
601
1113
 
602
- What it returns:
603
- - \`_id\`
604
- - \`name\`
605
- - \`active\`
606
- - \`baseURL\`
607
- - \`domain\`
608
- - \`countryCode\`
609
- - \`timezone\`
610
-
611
- Typical use:
612
- 1. Search the brand/site by name fragment.
613
- 2. Take either the returned \`_id\` or a known domain/baseURL.
614
- 3. Use that value in \`team-cli admin <websiteId|domain> ...\`.
615
-
616
- Examples:
617
- \`\`\`bash
618
- # find the website
619
- npx @getjusto/team-cli admin search milas --limit 5
1114
+ Herramienta CLI para el equipo Justo.
620
1115
 
621
- # then use the returned website id
622
- npx @getjusto/team-cli admin YRZjQ7L6whxfkezmF show
623
- npx @getjusto/team-cli admin YRZjQ7L6whxfkezmF stores list
624
- npx @getjusto/team-cli admin YRZjQ7L6whxfkezmF coupons list
1116
+ ${e}
625
1117
 
626
- # or use a domain directly
627
- npx @getjusto/team-cli admin www.masmilas.com show
628
- \`\`\`
1118
+ Si necesitas obtener data y no existe un query listo, usa create + ai-edit.
1119
+ Flujo sugerido: create -> ai-edit -> preview -> run o download.
629
1120
 
630
- ### data queries view — View query metadata and required variables
1121
+ ## Login recomendado para agentes
631
1122
 
1123
+ Pide el email al usuario que te esta hablando y usa el flujo no interactivo:
632
1124
  \`\`\`bash
633
- npx @getjusto/team-cli data queries view <queryId>
1125
+ npx @getjusto/team-cli auth request-code --email <email>
1126
+ npx @getjusto/team-cli auth login-with-token --email <email> --token <token> --code <CODIGO>
634
1127
  \`\`\`
635
1128
 
636
- Returns: _id, name, description, collection, currentVersionIndex, and variables (key, fieldType, fieldParams). Use this to understand what params a query expects before running preview or download.
1129
+ ## Opciones globales
637
1130
 
638
- ### data queries view-pipeline View query pipeline code
639
-
640
- \`\`\`bash
641
- npx @getjusto/team-cli data queries view-pipeline <queryId>
642
- \`\`\`
1131
+ - \`--env <local|develop|prod>\`Environment (default: prod)
1132
+ - \`--format toon|json\` — Output format (default: toon)
1133
+ - \`--version\`
1134
+ - \`--help\`
643
1135
 
644
- Returns the raw JavaScript pipeline code.
1136
+ ## Comandos
645
1137
 
646
- ### data queries preview Test-run a query (max 100 rows)
1138
+ Cada grupo de comandos tiene su propia ayuda. Usa \`--help\` para ver los comandos disponibles (ej: npx @getjusto/team-cli spaces --help)
647
1139
 
648
- \`\`\`bash
649
- npx @getjusto/team-cli data queries preview <queryId> [--params '<json>'] [--format toon|json]
650
- \`\`\`
1140
+ - \`auth\` — Gestión de sesión
1141
+ - \`graphql\` Ejecutar queries y mutations GraphQL
1142
+ - \`admin\` — Comandos administrativos con contexto de website
1143
+ - \`data\` — Datos y reportes. Puede obtener data de todas las bases de datos de Justo
1144
+ - \`spaces\` — Crea apps React para Spaces con \`spaces init\`, publícalas con \`spaces publish\` y compártelas en intra.
651
1145
 
652
- Executes the query with a 100-row limit. Use this to verify results before downloading.
1146
+ ## Tips
653
1147
 
654
- ### data queries download Download full query results as Excel
1148
+ ### Obten el websiteId usando admin search
655
1149
 
1150
+ A veces los usuarios de este cli le dicen marcas
656
1151
  \`\`\`bash
657
- npx @getjusto/team-cli data queries download <queryId> --path <filepath> [--params '<json>']
1152
+ npx @getjusto/team-cli admin search <text> [--limit <n>] [--page <n>] [--only-active true|false]
658
1153
  \`\`\`
659
1154
 
660
- \`--path\` is required. Triggers an async report, polls until complete, then downloads the Excel file.
661
-
662
- ## Output Format
663
-
664
- Default output is TOON (Token-Oriented Object Notation), a compact human-readable format. Use \`--format json\` for standard JSON output.
665
-
666
- ## Typical Workflow
667
-
668
- 1. View a query to understand its variables: \`data queries view <id>\`
669
- 2. Preview with params: \`data queries preview <id> --params '{"startDate": "2026-01-01"}'\`
670
- 3. Download full data: \`data queries download <id> --params '{"startDate": "2026-01-01"}' --path output.xlsx\`
671
- `}function dt(){return{skill:Ie()}}var{positional:l,flags:m}=wo(process.argv.slice(2));if(m.env)lo(m.env);var Q=l[0],P=l[1];function lt(){let o=d();return`team-cli
672
-
673
- Herramienta CLI para el equipo Justo.
674
-
675
- ${o?`Sesión: ${o.email}`:"Sesión: no iniciada"}
676
-
677
- Uso:
678
- team-cli <comando> [opciones]
679
-
680
- Comandos:
681
- auth
682
- Gestión de sesión.
683
-
684
- admin
685
- Comandos administrativos con contexto de website.
686
-
687
- graphql
688
- Ejecutar queries y mutations GraphQL.
689
-
690
- data
691
- Datos y reportes.
1155
+ ### Crea queries para usar en los dashboards
692
1156
 
693
- get-skill
694
- Obtener skill para usar con Claude.
1157
+ Crea queries personalizadas usando \`create\` y \`ai-edit\` para generar consultas a la base de datos y luego crear un dashboard que las use
1158
+ para mostrar datos. Usa \`preview\` para iterar rápido, \`run\` para consumir NDJSON en streaming y \`download\` para Excel.
1159
+ También puedes usar queries para poblar selectores y otras partes de la interfaz del space.
695
1160
 
696
- Opciones globales:
697
- --env <local|develop|prod>
698
- --version
699
- --help
700
- --format <toon|json>`}async function $e(){try{let o;if(m.version)o={version:"0.0.4"};else if(m.help&&!Q){g(lt());return}else if(Q==="auth")if(P==="--help"||m.help){g(co());return}else if(P==="login")o=await Wo();else if(P==="login-with-token")o=await Ao(m);else if(P==="request-code")o=await Oo(m);else if(P==="logout")o=await So();else if(P==="status")o=await Qo();else{g(co());return}else if(Q==="admin"){let t=l[1],e=l[2],i=l[3],r=l[4];if(!t||t==="--help"){g(H());return}else if(t==="search"&&m.help){g(Yo());return}else if(t==="search")o=await Xo(l,m);else if(!e||e==="--help"){g(H());return}else if(e==="show")o=await To(t);else if(e==="stores"&&i==="list")o=await Zo(t);else if(e==="coupons"&&(!i||i==="--help")){g(M());return}else if(e==="coupons"&&i==="create"&&m.help){g(Lo());return}else if(e==="coupons"&&i==="update"&&m.help){g(ot());return}else if(e==="coupons"&&i==="codes"&&l[4]==="create"&&m.help){g(st());return}else if(e==="coupons"&&m.help){g(M());return}else if(e==="coupons"&&i==="list")o=await Ho(t,m);else if(e==="coupons"&&i==="show"){if(!r)throw Error("Uso: team-cli admin <web> coupons show <couponId>");o=await Do(t,r)}else if(e==="coupons"&&i==="create")o=await ko(t,m);else if(e==="coupons"&&i==="update"){if(!r)throw Error("Uso: team-cli admin <web> coupons update <couponId> --input '<json>'");o=await Ko(t,r,m)}else if(e==="coupons"&&i==="delete"){if(!r)throw Error("Uso: team-cli admin <web> coupons delete <couponId>");o=await Vo(t,r)}else if(e==="coupons"&&i==="codes"){let s=l[4],n=l[5];if(!s||s==="--help"){g(M());return}else if(s==="list"){if(!n)throw Error("Uso: team-cli admin <web> coupons codes list <couponId>");o=await tt(t,n,m)}else if(s==="create"){if(!n)throw Error("Uso: team-cli admin <web> coupons codes create <couponId> --input '<json>'");o=await et(t,n,m)}else if(s==="create-random"){if(!n)throw Error("Uso: team-cli admin <web> coupons codes create-random <couponId> --quantity <n>");o=await it(t,n,m)}else if(s==="delete"){if(!n)throw Error(`Uso: team-cli admin <web> coupons codes delete <couponId> --ids '["id1"]'`);o=await rt(t,n,m)}else{g(M());return}}else{g(H());return}}else if(Q==="graphql")if(P==="--help"||m.help){g(Jo());return}else o=await Bo(l,m);else if(Q==="get-skill")o=dt();else if(Q==="data"){let t=l[1],e=l[2];if(m.help||P==="--help"){g(go());return}else if(t==="queries"&&e==="view")o=await at(l);else if(t==="queries"&&e==="view-pipeline")o=await ct(l);else if(t==="queries"&&e==="preview")o=await mt(l,m);else if(t==="queries"&&e==="download")o=await ut(l,m);else{g(go());return}}else{g(lt());return}if(o!==void 0)xo(o,m)}catch(o){Uo(o,m),process.exit(1)}}$e();
1161
+ `}function No(){let e=d(),t=e?`Sesión: ${e.email}`:"Sesión: no iniciada";return jo(t)}async function Ao(e){let{positional:t,flags:o}=L(e);if(o.env)He(o.env);let r=t[0],a=t[1];if(r==="__spaces-preview-bridge")return await Kt(o);if(o.version)return{version:"0.0.6"};if(o.help&&!r)return No();if(r==="auth"){if(a==="--help"||o.help)return Se();if(a==="login")return await xt();if(a==="login-with-token")return await ht(o);if(a==="request-code")return await St(o);if(a==="logout")return await Et();if(a==="status")return await jt();return Se()}if(r==="admin"){let i=t[1],n=t[2],s=t[3],c=t[4];if(!i||i==="--help")return ne();if(i==="search"&&o.help)return Ct();if(i==="search")return await yt(t,o);if(!n||n==="--help")return ne();if(n==="show")return await tt(i);if(n==="stores"&&s==="list")return await qt(i);if(n==="coupons"&&(!s||s==="--help"))return Y();if(n==="coupons"&&s==="create"&&o.help)return wt();if(n==="coupons"&&s==="update"&&o.help)return bt();if(n==="coupons"&&s==="codes"&&t[4]==="create"&&o.help)return mt();if(n==="coupons"&&o.help)return Y();if(n==="coupons"&&s==="list")return await lt(i,o);if(n==="coupons"&&s==="show"){if(!c)throw Error("Uso: team-cli admin <web> coupons show <couponId>");return await dt(i,c)}if(n==="coupons"&&s==="create")return await pt(i,o);if(n==="coupons"&&s==="update"){if(!c)throw Error("Uso: team-cli admin <web> coupons update <couponId> --input '<json>'");return await gt(i,c,o)}if(n==="coupons"&&s==="delete"){if(!c)throw Error("Uso: team-cli admin <web> coupons delete <couponId>");return await ft(i,c)}if(n==="coupons"&&s==="codes"){let u=t[4],l=t[5];if(!u||u==="--help")return Y();if(u==="list"){if(!l)throw Error("Uso: team-cli admin <web> coupons codes list <couponId>");return await it(i,l,o)}if(u==="create"){if(!l)throw Error("Uso: team-cli admin <web> coupons codes create <couponId> --input '<json>'");return await nt(i,l,o)}if(u==="create-random"){if(!l)throw Error("Uso: team-cli admin <web> coupons codes create-random <couponId> --quantity <n>");return await st(i,l,o)}if(u==="delete"){if(!l)throw Error(`Uso: team-cli admin <web> coupons codes delete <couponId> --ids '["id1"]'`);return await ct(i,l,o)}return Y()}return ne()}if(r==="graphql"){if(a==="--help"||o.help)return Co();return await bo(t,o)}if(r==="data"){let i=t[1],n=t[2];if(o.help||a==="--help")return Oe();if(i==="queries"&&n==="create")return await no();if(i==="queries"&&n==="edit")return await so(t);if(i==="queries"&&n==="ai-edit")return await co(t,o);if(i==="queries"&&n==="view")return await mo(t);if(i==="queries"&&n==="view-pipeline")return await uo(t);if(i==="queries"&&n==="preview")return await lo(t,o);if(i==="queries"&&n==="run")return await po(t,o);if(i==="queries"&&n==="download")return await go(t,o);return Oe()}if(r==="spaces"){let i=t[1];if(!i||i==="--help"||o.help)return Qe();if(i==="init")return await $o(o);if(i==="create")return await ho(o);if(i==="preview")return await xo(o);if(i==="publish")return await So(t,o);if(i==="archive")return await Eo(t);return Qe()}return No()}var{flags:Ro}=L(process.argv.slice(2));async function ja(){try{let e=await Ao(process.argv.slice(2));if(e&&typeof e==="object"&&"__streamHandled"in e&&e.__streamHandled)return;if(typeof e==="string"){Fe(e);return}Pe(e,Ro)}catch(e){Xe(e,Ro),process.exit(1)}}ja();