@getjusto/team-cli 0.0.8 → 0.0.10

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 +172 -100
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- function oe(e){let t=[],r={},o={};for(let a=0;a<e.length;a++)if(e[a].startsWith("--")&&e[a+1]&&!e[a+1].startsWith("--")){let n=e[a].slice(2);if(r[n]=e[a+1],!o[n])o[n]=[];o[n].push(e[a+1]),a++}else if(e[a].startsWith("--"))r[e[a].slice(2)]="true";else t.push(e[a]);return{positional:t,flags:r,arrayFlags:o}}function F(e,t){let r=e[t];if(!r)throw Error(`--${t} es requerido.`);return r}var Br={comma:",",tab:"\t",pipe:"|"},Y=Br.comma;function Xe(e){return e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function Mr(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,r])=>[String(t),E(r)]));if(Pr(e)){let t={};for(let r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[r]=E(e[r]);return t}return null}function U(e){return e===null||typeof e==="string"||typeof e==="number"||typeof e==="boolean"}function T(e){return Array.isArray(e)}function q(e){return e!==null&&typeof e==="object"&&!Array.isArray(e)}function X(e){return Object.keys(e).length===0}function Pr(e){if(e===null||typeof e!=="object")return!1;let t=Object.getPrototypeOf(e);return t===null||t===Object.prototype}function H(e){return e.length===0||e.every((t)=>U(t))}function Gr(e){return e.length===0||e.every((t)=>T(t))}function He(e){return e.length===0||e.every((t)=>q(t))}function Fr(e){return/^[A-Z_][\w.]*$/i.test(e)}function Xr(e){return/^[A-Z_]\w*$/i.test(e)}function Hr(e,t=Y){if(!e)return!1;if(e!==e.trim())return!1;if(Mr(e)||Zr(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 Zr(e){return/^-?\d+(?:\.\d+)?(?:e[+-]?\d+)?$/i.test(e)||/^0\d+$/.test(e)}var Ha=Symbol("quotedKey");function Yr(e,t,r,o,a,n,i){if(o.keyFolding!=="safe")return;if(!q(t))return;let{segments:s,tail:c,leafValue:m}=Dr(e,t,i??o.flattenDepth);if(s.length<2)return;if(!s.every((p)=>Xr(p)))return;let l=zr(s),g=n?`${n}.${l}`:l;if(r.includes(l))return;if(a&&a.has(g))return;return{foldedKey:l,remainder:c,leafValue:m,segmentCount:s.length}}function Dr(e,t,r){let o=[e],a=t;while(o.length<r){if(!q(a))break;let n=Object.keys(a);if(n.length!==1)break;let i=n[0],s=a[i];o.push(i),a=s}if(!q(a)||X(a))return{segments:o,tail:void 0,leafValue:a};return{segments:o,tail:a,leafValue:a}}function zr(e){return e.join(".")}function B(e,t){if(e===null)return"null";if(typeof e==="boolean")return String(e);if(typeof e==="number")return String(e);return kr(e,t)}function kr(e,t=Y){if(Hr(e,t))return e;return`"${Xe(e)}"`}function Z(e){if(Fr(e))return e;return`"${Xe(e)}"`}function Ze(e,t=Y){return e.map((r)=>B(r,t)).join(t)}function j(e,t){let r=t?.key,o=t?.fields,a=t?.delimiter??",",n="";if(r)n+=Z(r);if(n+=`[${e}${a!==Y?a:""}]`,o){let i=o.map((s)=>Z(s));n+=`{${i.join(a)}}`}return n+=":",n}function*Kr(e,t,r){if(U(e)){let o=B(e,t.delimiter);if(o!=="")yield o;return}if(T(e))yield*he(void 0,e,r,t);else if(q(e))yield*_(e,r,t)}function*_(e,t,r,o,a,n){let i=Object.keys(e);if(t===0&&!o)o=new Set(i.filter((c)=>c.includes(".")));let s=n??r.flattenDepth;for(let[c,m]of Object.entries(e))yield*Vr(c,m,t,r,i,o,a,s)}function*Vr(e,t,r,o,a,n,i,s){let c=i?`${i}.${e}`:e,m=s??o.flattenDepth;if(o.keyFolding==="safe"&&a){let g=Yr(e,t,a,o,n,i,m);if(g){let{foldedKey:p,remainder:C,leafValue:w,segmentCount:re}=g,W=Z(p);if(C===void 0){if(U(w)){yield b(r,`${W}: ${B(w,o.delimiter)}`,o.indent);return}else if(T(w)){yield*he(p,w,r,o);return}else if(q(w)&&X(w)){yield b(r,`${W}:`,o.indent);return}}if(q(C)){yield b(r,`${W}:`,o.indent);let R=m-re,G=i?`${i}.${p}`:p;yield*_(C,r+1,o,n,G,R);return}}}let l=Z(e);if(U(t))yield b(r,`${l}: ${B(t,o.delimiter)}`,o.indent);else if(T(t))yield*he(e,t,r,o);else if(q(t)){if(yield b(r,`${l}:`,o.indent),!X(t))yield*_(t,r+1,o,n,c,m)}}function*he(e,t,r,o){if(t.length===0){yield b(r,j(0,{key:e,delimiter:o.delimiter}),o.indent);return}if(H(t)){yield b(r,ne(t,o.delimiter,e),o.indent);return}if(Gr(t)){if(t.every((a)=>H(a))){yield*Lr(e,t,r,o);return}}if(He(t)){let a=Ye(t);if(a)yield*eo(e,t,a,r,o);else yield*Fe(e,t,r,o);return}yield*Fe(e,t,r,o)}function*Lr(e,t,r,o){yield b(r,j(t.length,{key:e,delimiter:o.delimiter}),o.indent);for(let a of t)if(H(a)){let n=ne(a,o.delimiter);yield x(r+1,n,o.indent)}}function ne(e,t,r){let o=j(e.length,{key:r,delimiter:t}),a=Ze(e,t);if(e.length===0)return o;return`${o} ${a}`}function*eo(e,t,r,o,a){yield b(o,j(t.length,{key:e,fields:r,delimiter:a.delimiter}),a.indent),yield*De(t,r,o+1,a)}function Ye(e){if(e.length===0)return;let t=e[0],r=Object.keys(t);if(r.length===0)return;if(to(e,r))return r}function to(e,t){for(let r of e){if(Object.keys(r).length!==t.length)return!1;for(let o of t){if(!(o in r))return!1;if(!U(r[o]))return!1}}return!0}function*De(e,t,r,o){for(let a of e)yield b(r,Ze(t.map((n)=>a[n]),o.delimiter),o.indent)}function*Fe(e,t,r,o){yield b(r,j(t.length,{key:e,delimiter:o.delimiter}),o.indent);for(let a of t)yield*$e(a,r+1,o)}function*ro(e,t,r){if(X(e)){yield b(t,"-",r.indent);return}let o=Object.entries(e),[a,n]=o[0],i=o.slice(1);if(T(n)&&He(n)){let c=Ye(n);if(c){if(yield x(t,j(n.length,{key:a,fields:c,delimiter:r.delimiter}),r.indent),yield*De(n,c,t+2,r),i.length>0)yield*_(Object.fromEntries(i),t+1,r);return}}let s=Z(a);if(U(n))yield x(t,`${s}: ${B(n,r.delimiter)}`,r.indent);else if(T(n))if(n.length===0)yield x(t,`${s}${j(0,{delimiter:r.delimiter})}`,r.indent);else if(H(n))yield x(t,`${s}${ne(n,r.delimiter)}`,r.indent);else{yield x(t,`${s}${j(n.length,{delimiter:r.delimiter})}`,r.indent);for(let c of n)yield*$e(c,t+2,r)}else if(q(n)){if(yield x(t,`${s}:`,r.indent),!X(n))yield*_(n,t+2,r)}if(i.length>0)yield*_(Object.fromEntries(i),t+1,r)}function*$e(e,t,r){if(U(e))yield x(t,B(e,r.delimiter),r.indent);else if(T(e))if(H(e))yield x(t,ne(e,r.delimiter),r.indent);else{yield x(t,j(e.length,{delimiter:r.delimiter}),r.indent);for(let o of e)yield*$e(o,t+1,r)}else if(q(e))yield*ro(e,t,r)}function b(e,t,r){return" ".repeat(r*e)+t}function x(e,t,r){return b(e,"- "+t,r)}function oo(e,t){let r=t("",e,[]);if(r===void 0)return ae(e,t,[]);return ae(E(r),t,[])}function ae(e,t,r){if(q(e))return ao(e,t,r);if(T(e))return no(e,t,r);return e}function ao(e,t,r){let o={};for(let[a,n]of Object.entries(e)){let i=[...r,a],s=t(a,n,i);if(s===void 0)continue;o[a]=ae(E(s),t,i)}return o}function no(e,t,r){let o=[];for(let a=0;a<e.length;a++){let n=e[a],i=[...r,a],s=t(String(a),n,i);if(s===void 0)continue;let c=E(s);o.push(ae(c,t,i))}return o}function xe(e,t){return Array.from(io(e,t)).join(`
3
- `)}function io(e,t){let r=E(e),o=so(t);return Kr(o.replacer?oo(r,o.replacer):r,o,0)}function so(e){return{indent:e?.indent??2,delimiter:e?.delimiter??Y,keyFolding:e?.keyFolding??"off",flattenDepth:e?.flattenDepth??Number.POSITIVE_INFINITY,replacer:e?.replacer}}function co(e){let t=e.format??"toon";if(t!=="toon"&&t!=="json")throw Error("--format debe ser toon o json.");return t}function ze(e,t){if(co(t)==="json"){console.log(JSON.stringify(e,null,2));return}console.log(xe(e))}function ke(e){process.stdout.write(`${e}
4
- `)}function Ke(e,t){let o={ok:!1,error:e instanceof Error?e.message:String(e)};if((t.format==="json"?"json":"toon")==="json"){console.error(JSON.stringify(o,null,2));return}console.error(xe(o))}function y(e){process.stderr.write(e)}import{existsSync as ce,mkdirSync as lo,readFileSync as Le,writeFileSync as po,unlinkSync as go}from"node:fs";import{join as et}from"node:path";import{homedir as fo}from"node:os";import{AsyncLocalStorage as uo}from"node:async_hooks";var mo=new uo;function I(){return mo.getStore()}var ie={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"}},Se="prod";function Ve(e){Se=e}function se(){let e=process.env.JUSTO_TEAM_CLI_ENV;if(e)return e;let t=I()?.environment;if(t)return t;return Se}function h(e){return ie[e][Se]}var Ee=et(fo(),".justo-team");function tt(e){let t=e==="prod"?"credentials.json":`credentials.${e}.json`;return et(Ee,t)}function je(){return tt(se())}function wo(){if(!ce(Ee))lo(Ee,{recursive:!0})}function ue(e){let t=I();if(t&&t.canPersistCredentials===!1)throw Error("Este entorno no permite guardar credenciales.");wo(),po(je(),JSON.stringify(e,null,2))}function d(){let e=process.env.JUSTO_TEAM_CLI_TOKEN,t=process.env.JUSTO_TEAM_CLI_EMAIL,r=process.env.JUSTO_TEAM_CLI_REFRESH_TOKEN;if(e&&t)return{email:t,token:e,refreshToken:r||""};let o=I()?.credentials;if(o!==void 0)return o?{email:o.email,token:o.token,refreshToken:o.refreshToken||""}:null;let a=je();if(!ce(a))return null;try{let n=Le(a,"utf-8");return JSON.parse(n)}catch{return null}}function rt(e){let t=tt(e);if(!ce(t))return null;try{let r=Le(t,"utf-8");return JSON.parse(r)}catch{return null}}function Ae(){let e=I();if(e&&e.canPersistCredentials===!1)throw Error("Este entorno no permite borrar credenciales.");let t=je();if(ce(t))go(t)}import{existsSync as ot,readFileSync as bo,writeFileSync as yo,mkdirSync as Co}from"node:fs";import{join as at}from"node:path";import{homedir as qo}from"node:os";function Io(){let e=process.env.JUSTO_TEAM_CLI_DEVICE_ID;if(e)return e;let t=I()?.deviceId;if(t)return t;let r=at(qo(),".justo-team"),o=at(r,"device-id");if(ot(o))return bo(o,"utf-8").trim();let a=crypto.randomUUID();if(!ot(r))Co(r,{recursive:!0});return yo(o,a),a}var it={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 ho(e,t){let r=it[e];if(!r)return`${t}: ${e}`;if(typeof r==="function")return r({label:t});return r}function nt(e){return Object.entries(e).map(([t,r])=>ho(r,t)).join(", ")}function $o(e){if(e.error==="validationError"&&e.validationErrors)return nt(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} (${nt(e.validationErrors)})`;let t=e.message||"Error desconocido",r=it[t];if(r)return typeof r==="function"?r({label:""}).trim():r;let o=e.error||e.code||e.type;return o?`${t} [${o}]`:t}function xo(e){try{return JSON.parse(Buffer.from(e.split(".")[1],"base64").toString()).exp*1000<Date.now()}catch{return!0}}async function So(){let e=d();if(!e?.refreshToken)return null;let t=`${h("auth")}/refresh-token`,o=await(await fetch(t,{method:"POST",headers:{"X-ORION-REFRESH":e.refreshToken}})).json();if(!o.token)return null;if(I()?.canPersistCredentials!==!1)ue({...e,token:o.token});return o.token}async function Ne(){let e=d();if(!e?.token)return;if(!xo(e.token))return e.token;return await So()??void 0}async function ve(e="application/json"){let t=await Ne(),r={"Content-Type":e,"X-ORION-DEVICEID":Io(),"X-ORION-PLATFORM":"web"};if(t)r["x-orion-jwt"]=t;return r}async function u(e){let t=`${h(e.service)}/graphql`,r=await ve(),o;try{o=await fetch(t,{method:"POST",headers:r,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 o.json();if(a.errors?.length)throw Error($o(a.errors[0]));if(!a.data)throw Error("No data returned from server");return a.data}function Eo(e){return e.replace(/^https?:\/\//,"").replace(/^www\./,"").replace(/\/.*$/,"")}function jo(e){return e.includes(".")||e.startsWith("http://")||e.startsWith("https://")}async function M(e){if(jo(e)){let t=Eo(e),r=await fetch(`${h("main")}/website-id/${t}`,{signal:AbortSignal.timeout(1e4)});if(!r.ok)throw Error(`No se encontro el sitio "${t}"`);let o=await r.json();if(!o.websiteId)throw Error(`No se pudo resolver el websiteId para "${t}"`);return{input:e,websiteId:o.websiteId,targetType:"domain"}}return{input:e,websiteId:e,targetType:"websiteId"}}async function st(e){let t=await u({service:"main",query:`query ($websiteId: ID) {
2
+ function ie(e){let r=[],t={},o={};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(t[i]=e[a+1],!o[i])o[i]=[];o[i].push(e[a+1]),a++}else if(e[a].startsWith("--"))t[e[a].slice(2)]="true";else r.push(e[a]);return{positional:r,flags:t,arrayFlags:o}}function X(e,r){let t=e[r];if(!t)throw Error(`--${r} es requerido.`);return t}var no={comma:",",tab:"\t",pipe:"|"},Y=no.comma;function He(e){return e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function so(e){return e==="true"||e==="false"||e==="null"}function j(e){if(e===null)return null;if(typeof e==="object"&&e!==null&&"toJSON"in e&&typeof e.toJSON==="function"){let r=e.toJSON();if(r!==e)return j(r)}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(j);if(e instanceof Set)return Array.from(e).map(j);if(e instanceof Map)return Object.fromEntries(Array.from(e,([r,t])=>[String(r),j(t)]));if(co(e)){let r={};for(let t in e)if(Object.prototype.hasOwnProperty.call(e,t))r[t]=j(e[t]);return r}return null}function B(e){return e===null||typeof e==="string"||typeof e==="number"||typeof e==="boolean"}function Q(e){return Array.isArray(e)}function q(e){return e!==null&&typeof e==="object"&&!Array.isArray(e)}function H(e){return Object.keys(e).length===0}function co(e){if(e===null||typeof e!=="object")return!1;let r=Object.getPrototypeOf(e);return r===null||r===Object.prototype}function Z(e){return e.length===0||e.every((r)=>B(r))}function uo(e){return e.length===0||e.every((r)=>Q(r))}function Ze(e){return e.length===0||e.every((r)=>q(r))}function lo(e){return/^[A-Z_][\w.]*$/i.test(e)}function mo(e){return/^[A-Z_]\w*$/i.test(e)}function po(e,r=Y){if(!e)return!1;if(e!==e.trim())return!1;if(so(e)||go(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(r))return!1;if(e.startsWith("-"))return!1;return!0}function go(e){return/^-?\d+(?:\.\d+)?(?:e[+-]?\d+)?$/i.test(e)||/^0\d+$/.test(e)}var Ni=Symbol("quotedKey");function fo(e,r,t,o,a,i,n){if(o.keyFolding!=="safe")return;if(!q(r))return;let{segments:s,tail:c,leafValue:l}=wo(e,r,n??o.flattenDepth);if(s.length<2)return;if(!s.every((d)=>mo(d)))return;let m=bo(s),p=i?`${i}.${m}`:m;if(t.includes(m))return;if(a&&a.has(p))return;return{foldedKey:m,remainder:c,leafValue:l,segmentCount:s.length}}function wo(e,r,t){let o=[e],a=r;while(o.length<t){if(!q(a))break;let i=Object.keys(a);if(i.length!==1)break;let n=i[0],s=a[n];o.push(n),a=s}if(!q(a)||H(a))return{segments:o,tail:void 0,leafValue:a};return{segments:o,tail:a,leafValue:a}}function bo(e){return e.join(".")}function P(e,r){if(e===null)return"null";if(typeof e==="boolean")return String(e);if(typeof e==="number")return String(e);return yo(e,r)}function yo(e,r=Y){if(po(e,r))return e;return`"${He(e)}"`}function k(e){if(lo(e))return e;return`"${He(e)}"`}function ke(e,r=Y){return e.map((t)=>P(t,r)).join(r)}function v(e,r){let t=r?.key,o=r?.fields,a=r?.delimiter??",",i="";if(t)i+=k(t);if(i+=`[${e}${a!==Y?a:""}]`,o){let n=o.map((s)=>k(s));i+=`{${n.join(a)}}`}return i+=":",i}function*Co(e,r,t){if(B(e)){let o=P(e,r.delimiter);if(o!=="")yield o;return}if(Q(e))yield*Se(void 0,e,t,r);else if(q(e))yield*W(e,t,r)}function*W(e,r,t,o,a,i){let n=Object.keys(e);if(r===0&&!o)o=new Set(n.filter((c)=>c.includes(".")));let s=i??t.flattenDepth;for(let[c,l]of Object.entries(e))yield*ho(c,l,r,t,n,o,a,s)}function*ho(e,r,t,o,a,i,n,s){let c=n?`${n}.${e}`:e,l=s??o.flattenDepth;if(o.keyFolding==="safe"&&a){let p=fo(e,r,a,o,i,n,l);if(p){let{foldedKey:d,remainder:b,leafValue:f,segmentCount:T}=p,O=k(d);if(b===void 0){if(B(f)){yield y(t,`${O}: ${P(f,o.delimiter)}`,o.indent);return}else if(Q(f)){yield*Se(d,f,t,o);return}else if(q(f)&&H(f)){yield y(t,`${O}:`,o.indent);return}}if(q(b)){yield y(t,`${O}:`,o.indent);let U=l-T,D=n?`${n}.${d}`:d;yield*W(b,t+1,o,i,D,U);return}}}let m=k(e);if(B(r))yield y(t,`${m}: ${P(r,o.delimiter)}`,o.indent);else if(Q(r))yield*Se(e,r,t,o);else if(q(r)){if(yield y(t,`${m}:`,o.indent),!H(r))yield*W(r,t+1,o,i,c,l)}}function*Se(e,r,t,o){if(r.length===0){yield y(t,v(0,{key:e,delimiter:o.delimiter}),o.indent);return}if(Z(r)){yield y(t,se(r,o.delimiter,e),o.indent);return}if(uo(r)){if(r.every((a)=>Z(a))){yield*qo(e,r,t,o);return}}if(Ze(r)){let a=Ye(r);if(a)yield*Io(e,r,a,t,o);else yield*Xe(e,r,t,o);return}yield*Xe(e,r,t,o)}function*qo(e,r,t,o){yield y(t,v(r.length,{key:e,delimiter:o.delimiter}),o.indent);for(let a of r)if(Z(a)){let i=se(a,o.delimiter);yield E(t+1,i,o.indent)}}function se(e,r,t){let o=v(e.length,{key:t,delimiter:r}),a=ke(e,r);if(e.length===0)return o;return`${o} ${a}`}function*Io(e,r,t,o,a){yield y(o,v(r.length,{key:e,fields:t,delimiter:a.delimiter}),a.indent),yield*Ve(r,t,o+1,a)}function Ye(e){if(e.length===0)return;let r=e[0],t=Object.keys(r);if(t.length===0)return;if(xo(e,t))return t}function xo(e,r){for(let t of e){if(Object.keys(t).length!==r.length)return!1;for(let o of r){if(!(o in t))return!1;if(!B(t[o]))return!1}}return!0}function*Ve(e,r,t,o){for(let a of e)yield y(t,ke(r.map((i)=>a[i]),o.delimiter),o.indent)}function*Xe(e,r,t,o){yield y(t,v(r.length,{key:e,delimiter:o.delimiter}),o.indent);for(let a of r)yield*je(a,t+1,o)}function*$o(e,r,t){if(H(e)){yield y(r,"-",t.indent);return}let o=Object.entries(e),[a,i]=o[0],n=o.slice(1);if(Q(i)&&Ze(i)){let c=Ye(i);if(c){if(yield E(r,v(i.length,{key:a,fields:c,delimiter:t.delimiter}),t.indent),yield*Ve(i,c,r+2,t),n.length>0)yield*W(Object.fromEntries(n),r+1,t);return}}let s=k(a);if(B(i))yield E(r,`${s}: ${P(i,t.delimiter)}`,t.indent);else if(Q(i))if(i.length===0)yield E(r,`${s}${v(0,{delimiter:t.delimiter})}`,t.indent);else if(Z(i))yield E(r,`${s}${se(i,t.delimiter)}`,t.indent);else{yield E(r,`${s}${v(i.length,{delimiter:t.delimiter})}`,t.indent);for(let c of i)yield*je(c,r+2,t)}else if(q(i)){if(yield E(r,`${s}:`,t.indent),!H(i))yield*W(i,r+2,t)}if(n.length>0)yield*W(Object.fromEntries(n),r+1,t)}function*je(e,r,t){if(B(e))yield E(r,P(e,t.delimiter),t.indent);else if(Q(e))if(Z(e))yield E(r,se(e,t.delimiter),t.indent);else{yield E(r,v(e.length,{delimiter:t.delimiter}),t.indent);for(let o of e)yield*je(o,r+1,t)}else if(q(e))yield*$o(e,r,t)}function y(e,r,t){return" ".repeat(t*e)+r}function E(e,r,t){return y(e,"- "+r,t)}function Eo(e,r){let t=r("",e,[]);if(t===void 0)return ne(e,r,[]);return ne(j(t),r,[])}function ne(e,r,t){if(q(e))return So(e,r,t);if(Q(e))return jo(e,r,t);return e}function So(e,r,t){let o={};for(let[a,i]of Object.entries(e)){let n=[...t,a],s=r(a,i,n);if(s===void 0)continue;o[a]=ne(j(s),r,n)}return o}function jo(e,r,t){let o=[];for(let a=0;a<e.length;a++){let i=e[a],n=[...t,a],s=r(String(a),i,n);if(s===void 0)continue;let c=j(s);o.push(ne(c,r,n))}return o}function ve(e,r){return Array.from(vo(e,r)).join(`
3
+ `)}function vo(e,r){let t=j(e),o=Ao(r);return Co(o.replacer?Eo(t,o.replacer):t,o,0)}function Ao(e){return{indent:e?.indent??2,delimiter:e?.delimiter??Y,keyFolding:e?.keyFolding??"off",flattenDepth:e?.flattenDepth??Number.POSITIVE_INFINITY,replacer:e?.replacer}}function Ro(e){let r=e.format??"toon";if(r!=="toon"&&r!=="json")throw Error("--format debe ser toon o json.");return r}function Ke(e,r){if(Ro(r)==="json"){console.log(JSON.stringify(e,null,2));return}console.log(ve(e))}function Le(e){process.stdout.write(`${e}
4
+ `)}function er(e,r){let o={ok:!1,error:e instanceof Error?e.message:String(e)};if((r.format==="json"?"json":"toon")==="json"){console.error(JSON.stringify(o,null,2));return}console.error(ve(o))}function C(e){process.stderr.write(e)}import{existsSync as le,mkdirSync as Oo,readFileSync as tr,writeFileSync as Uo,unlinkSync as Qo}from"node:fs";import{join as or}from"node:path";import{homedir as Bo}from"node:os";import{AsyncLocalStorage as No}from"node:async_hooks";var To=new No;function I(){return To.getStore()}var ce={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"}},Ae="prod";function rr(e){Ae=e}function ue(){let e=process.env.JUSTO_TEAM_CLI_ENV;if(e)return e;let r=I()?.environment;if(r)return r;return Ae}function h(e){return ce[e][Ae]}var Re=or(Bo(),".justo-team");function ar(e){let r=e==="prod"?"credentials.json":`credentials.${e}.json`;return or(Re,r)}function Ne(){return ar(ue())}function _o(){if(!le(Re))Oo(Re,{recursive:!0})}function me(e){let r=I();if(r&&r.canPersistCredentials===!1)throw Error("Este entorno no permite guardar credenciales.");_o(),Uo(Ne(),JSON.stringify(e,null,2))}function g(){let e=process.env.JUSTO_TEAM_CLI_TOKEN,r=process.env.JUSTO_TEAM_CLI_EMAIL,t=process.env.JUSTO_TEAM_CLI_REFRESH_TOKEN;if(e&&r)return{email:r,token:e,refreshToken:t||""};let o=I()?.credentials;if(o!==void 0)return o?{email:o.email,token:o.token,refreshToken:o.refreshToken||""}:null;let a=Ne();if(!le(a))return null;try{let i=tr(a,"utf-8");return JSON.parse(i)}catch{return null}}function ir(e){let r=ar(e);if(!le(r))return null;try{let t=tr(r,"utf-8");return JSON.parse(t)}catch{return null}}function Te(){let e=I();if(e&&e.canPersistCredentials===!1)throw Error("Este entorno no permite borrar credenciales.");let r=Ne();if(le(r))Qo(r)}import{existsSync as nr,readFileSync as Jo,writeFileSync as Wo,mkdirSync as Po}from"node:fs";import{join as sr}from"node:path";import{homedir as Mo}from"node:os";function Go(){let e=process.env.JUSTO_TEAM_CLI_DEVICE_ID;if(e)return e;let r=I()?.deviceId;if(r)return r;let t=sr(Mo(),".justo-team"),o=sr(t,"device-id");if(nr(o))return Jo(o,"utf-8").trim();let a=crypto.randomUUID();if(!nr(t))Po(t,{recursive:!0});return Wo(o,a),a}var ur={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 Fo(e,r){let t=ur[e];if(!t)return`${r}: ${e}`;if(typeof t==="function")return t({label:r});return t}function cr(e){return Object.entries(e).map(([r,t])=>Fo(t,r)).join(", ")}function zo(e){if(e.error==="validationError"&&e.validationErrors)return cr(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} (${cr(e.validationErrors)})`;let r=e.message||"Error desconocido",t=ur[r];if(t)return typeof t==="function"?t({label:""}).trim():t;let o=e.error||e.code||e.type;return o?`${r} [${o}]`:r}function Do(e){try{return JSON.parse(Buffer.from(e.split(".")[1],"base64").toString()).exp*1000<Date.now()}catch{return!0}}async function Xo(){let e=g();if(!e?.refreshToken)return null;let r=`${h("auth")}/refresh-token`,o=await(await fetch(r,{method:"POST",headers:{"X-ORION-REFRESH":e.refreshToken}})).json();if(!o.token)return null;if(I()?.canPersistCredentials!==!1)me({...e,token:o.token});return o.token}async function de(){let e=g();if(!e?.token)return;if(!Do(e.token))return e.token;return await Xo()??void 0}async function Oe(e="application/json"){let r=await de(),t={"Content-Type":e,"X-ORION-DEVICEID":Go(),"X-ORION-PLATFORM":"web"};if(r)t["x-orion-jwt"]=r;return t}async function u(e){let r=`${h(e.service)}/graphql`,t=await Oe(),o;try{o=await fetch(r,{method:"POST",headers:t,body:JSON.stringify({query:e.query,variables:e.variables}),signal:AbortSignal.timeout(e.timeoutMs||15000)})}catch{throw Error("La solicitud tardó demasiado. Intenta de nuevo.")}let a=await o.json();if(a.errors?.length)throw Error(zo(a.errors[0]));if(!a.data)throw Error("No data returned from server");return a.data}function Ho(e){return e.replace(/^https?:\/\//,"").replace(/^www\./,"").replace(/\/.*$/,"")}function Zo(e){return e.includes(".")||e.startsWith("http://")||e.startsWith("https://")}async function M(e){if(Zo(e)){let r=Ho(e),t=await fetch(`${h("main")}/website-id/${r}`,{signal:AbortSignal.timeout(1e4)});if(!t.ok)throw Error(`No se encontro el sitio "${r}"`);let o=await t.json();if(!o.websiteId)throw Error(`No se pudo resolver el websiteId para "${r}"`);return{input:e,websiteId:o.websiteId,targetType:"domain"}}return{input:e,websiteId:e,targetType:"websiteId"}}async function lr(e){let r=await u({service:"main",query:`query ($websiteId: ID) {
5
5
  website(websiteId: $websiteId) {
6
6
  _id
7
7
  name
@@ -13,7 +13,7 @@ function oe(e){let t=[],r={},o={};for(let a=0;a<e.length;a++)if(e[a].startsWith(
13
13
  timezone
14
14
  defaultMenuId
15
15
  }
16
- }`,variables:{websiteId:e}});if(!t.website)throw Error(`No se encontro el website "${e}"`);return t.website}function Ao(){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 ct(e){if(Ao(),!e)throw Error("Uso: team-cli admin <websiteId|domain> show");let t=await M(e),r=await st(t.websiteId);return{context:t,website:r}}function me(){return`team-cli admin
16
+ }`,variables:{websiteId:e}});if(!r.website)throw Error(`No se encontro el website "${e}"`);return r.website}function ko(){if(!g())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 mr(e){if(ko(),!e)throw Error("Uso: team-cli admin <websiteId|domain> show");let r=await M(e),t=await lr(r.websiteId);return{context:r,website:t}}function pe(){return`team-cli admin
17
17
 
18
18
  Comandos administrativos con contexto de website.
19
19
 
@@ -35,7 +35,7 @@ Modulos:
35
35
 
36
36
  coupons
37
37
  Administrar cupones y sus códigos.
38
- Uso: team-cli admin <websiteId|domain> coupons <accion> [opciones]`}var ut=`
38
+ Uso: team-cli admin <websiteId|domain> coupons <accion> [opciones]`}var dr=`
39
39
  availableAtPeriods
40
40
  closedDays
41
41
  closedUntilDate
@@ -51,7 +51,7 @@ Modulos:
51
51
  fromMinute
52
52
  toMinute
53
53
  }
54
- `,le=`
54
+ `,ge=`
55
55
  _id
56
56
  websiteId
57
57
  name
@@ -86,13 +86,13 @@ Modulos:
86
86
  requiredBINs
87
87
  extraRequirementsForPaymentTypes
88
88
  schedule {
89
- ${ut}
89
+ ${dr}
90
90
  }
91
91
  scheduleAtUse {
92
- ${ut}
92
+ ${dr}
93
93
  }
94
94
  codesCode
95
- `,mt=`
95
+ `,pr=`
96
96
  _id
97
97
  code
98
98
  couponId
@@ -101,28 +101,28 @@ Modulos:
101
101
  sentToEmail
102
102
  totalRedemptions
103
103
  createdAt
104
- `;function Re(){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 P(e,t){let r=e[t];if(!r)throw Error(`--${t} es requerido.`);try{return JSON.parse(r)}catch{throw Error(`--${t} debe ser un JSON válido.`)}}function S(e,t){let r=e[t];if(!r)return;let o=Number.parseInt(r,10);if(Number.isNaN(o))throw Error(`--${t} debe ser un número entero.`);return o}function lt(e,t){let r=e[t];if(!r)return;if(r==="true")return!0;if(r==="false")return!1;throw Error(`--${t} debe ser true o false.`)}async function $(e){if(Re(),!e)throw Error("Debes indicar <websiteId|domain>.");return M(e)}async function A(e,t){let r=await u({service:"main",query:`query ($couponId: ID) {
104
+ `;function Ue(){if(!g())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 G(e,r){let t=e[r];if(!t)throw Error(`--${r} es requerido.`);try{return JSON.parse(t)}catch{throw Error(`--${r} debe ser un JSON válido.`)}}function S(e,r){let t=e[r];if(!t)return;let o=Number.parseInt(t,10);if(Number.isNaN(o))throw Error(`--${r} debe ser un número entero.`);return o}function gr(e,r){let t=e[r];if(!t)return;if(t==="true")return!0;if(t==="false")return!1;throw Error(`--${r} debe ser true o false.`)}async function x(e){if(Ue(),!e)throw Error("Debes indicar <websiteId|domain>.");return M(e)}async function A(e,r){let t=await u({service:"main",query:`query ($couponId: ID) {
105
105
  coupon(couponId: $couponId) {
106
106
  _id
107
107
  websiteId
108
108
  }
109
- }`,variables:{couponId:e}});if(!r.coupon)throw Error(`No se encontró el cupón "${e}"`);if(r.coupon.websiteId!==t)throw Error(`El cupón "${e}" no pertenece al website seleccionado.`);return r.coupon}function No(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 vo(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 dt(e,t,r){let o=await $(e);await A(t,o.websiteId);let a=S(r,"limit"),n=S(r,"page"),i=r.filter,s=await u({service:"main",query:`query ($couponId: ID, $filter: String, $limit: BigInt, $page: BigInt) {
109
+ }`,variables:{couponId:e}});if(!t.coupon)throw Error(`No se encontró el cupón "${e}"`);if(t.coupon.websiteId!==r)throw Error(`El cupón "${e}" no pertenece al website seleccionado.`);return t.coupon}function Yo(e){if(!Array.isArray(e))throw Error("--input debe ser un arreglo JSON.");return e.map((r)=>{if(!r||typeof r!=="object"||typeof r.code!=="string")throw Error('Cada item de --input debe tener al menos { "code": "..." }.');if(r.userEmail!=null&&typeof r.userEmail!=="string")throw Error("userEmail debe ser string cuando viene informado.");return{code:r.code,userEmail:r.userEmail}})}function Vo(e){if(!Array.isArray(e)||e.some((r)=>typeof r!=="string"))throw Error("--ids debe ser un arreglo JSON de strings.");return e}async function fr(e,r,t){let o=await x(e);await A(r,o.websiteId);let a=S(t,"limit"),i=S(t,"page"),n=t.filter,s=await u({service:"main",query:`query ($couponId: ID, $filter: String, $limit: BigInt, $page: BigInt) {
110
110
  couponCodes(couponId: $couponId, filter: $filter, limit: $limit, page: $page) {
111
111
  items {
112
- ${mt}
112
+ ${pr}
113
113
  }
114
114
  totalCount
115
115
  totalPages
116
116
  hasNextPage
117
117
  hasPreviousPage
118
118
  }
119
- }`,variables:{couponId:t,filter:i,limit:a,page:n}});return{context:o,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:n??1,limit:a??null}}}async function pt(e,t,r){let o=await $(e);await A(t,o.websiteId);let a=No(P(r,"input")),n=a.some((s)=>s.userEmail),i=await u({service:"main",query:`mutation ($couponId: ID, $codesWithEmail: [CodeWithEmailInput], $useCodeWithEmail: Boolean) {
119
+ }`,variables:{couponId:r,filter:n,limit:a,page:i}});return{context:o,couponId:r,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 wr(e,r,t){let o=await x(e);await A(r,o.websiteId);let a=Yo(G(t,"input")),i=a.some((s)=>s.userEmail),n=await u({service:"main",query:`mutation ($couponId: ID, $codesWithEmail: [CodeWithEmailInput], $useCodeWithEmail: Boolean) {
120
120
  createCouponCodes(couponId: $couponId, codesWithEmail: $codesWithEmail, useCodeWithEmail: $useCodeWithEmail)
121
- }`,variables:{couponId:t,codesWithEmail:a,useCodeWithEmail:n}});return{context:o,couponId:t,requestedCount:a.length,result:i.createCouponCodes}}async function gt(e,t,r){let o=await $(e);await A(t,o.websiteId);let a=S(r,"quantity");if(!a)throw Error("--quantity es requerido.");let n=await u({service:"main",query:`mutation ($couponId: ID, $couponQuantity: Float, $couponCodePrefix: String) {
121
+ }`,variables:{couponId:r,codesWithEmail:a,useCodeWithEmail:i}});return{context:o,couponId:r,requestedCount:a.length,result:n.createCouponCodes}}async function br(e,r,t){let o=await x(e);await A(r,o.websiteId);let a=S(t,"quantity");if(!a)throw Error("--quantity es requerido.");let i=await u({service:"main",query:`mutation ($couponId: ID, $couponQuantity: Float, $couponCodePrefix: String) {
122
122
  createRandomCouponCodes(couponId: $couponId, couponQuantity: $couponQuantity, couponCodePrefix: $couponCodePrefix)
123
- }`,variables:{couponId:t,couponQuantity:a,couponCodePrefix:r.prefix}});return{context:o,couponId:t,quantity:a,prefix:r.prefix??null,result:n.createRandomCouponCodes}}async function ft(e,t,r){let o=await $(e);await A(t,o.websiteId);let a=vo(P(r,"ids")),n=await u({service:"main",query:`mutation ($couponId: ID, $couponCodesIds: [ID]) {
123
+ }`,variables:{couponId:r,couponQuantity:a,couponCodePrefix:t.prefix}});return{context:o,couponId:r,quantity:a,prefix:t.prefix??null,result:i.createRandomCouponCodes}}async function yr(e,r,t){let o=await x(e);await A(r,o.websiteId);let a=Vo(G(t,"ids")),i=await u({service:"main",query:`mutation ($couponId: ID, $couponCodesIds: [ID]) {
124
124
  deleteCouponCodes(couponId: $couponId, couponCodesIds: $couponCodesIds, globalCoupon: false)
125
- }`,variables:{couponId:t,couponCodesIds:a}});return{context:o,couponId:t,deleted:n.deleteCouponCodes,couponCodesIds:a}}function wt(){return`team-cli admin coupons codes create
125
+ }`,variables:{couponId:r,couponCodesIds:a}});return{context:o,couponId:r,deleted:i.deleteCouponCodes,couponCodesIds:a}}function Cr(){return`team-cli admin coupons codes create
126
126
 
127
127
  Crea códigos explícitos para un cupón.
128
128
 
@@ -145,11 +145,11 @@ Ejemplo:
145
145
 
146
146
  Notas:
147
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 bt={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 Ro(e){let t=Object.entries(e).filter(([,n])=>n!==void 0),r=t.map(([n])=>n).filter((n)=>!bt[n]);if(r.length)throw Error(`Campos no soportados para create: ${r.join(", ")}`);let o=t.map(([n])=>`$${n}: ${bt[n]}`).join(", "),a=t.map(([n])=>`${n}: $${n}`).join(", ");return`mutation (${o}) {
148
+ couponId se valida contra el website seleccionado antes de ejecutar la mutation.`}var hr={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 Ko(e){let r=Object.entries(e).filter(([,i])=>i!==void 0),t=r.map(([i])=>i).filter((i)=>!hr[i]);if(t.length)throw Error(`Campos no soportados para create: ${t.join(", ")}`);let o=r.map(([i])=>`$${i}: ${hr[i]}`).join(", "),a=r.map(([i])=>`${i}: $${i}`).join(", ");return`mutation (${o}) {
149
149
  createCoupon(${a}) {
150
- ${le}
150
+ ${ge}
151
151
  }
152
- }`}async function yt(e,t){let r=await $(e),o=S(t,"limit"),a=S(t,"page"),n=t.filter,i=await u({service:"main",query:`query ($websiteId: ID, $filter: String, $limit: BigInt, $page: BigInt) {
152
+ }`}async function qr(e,r){let t=await x(e),o=S(r,"limit"),a=S(r,"page"),i=r.filter,n=await u({service:"main",query:`query ($websiteId: ID, $filter: String, $limit: BigInt, $page: BigInt) {
153
153
  coupons(websiteId: $websiteId, filter: $filter, limit: $limit, page: $page) {
154
154
  items {
155
155
  _id
@@ -169,17 +169,17 @@ Notas:
169
169
  hasNextPage
170
170
  hasPreviousPage
171
171
  }
172
- }`,variables:{websiteId:r.websiteId,filter:n,limit:o,page:a}});return{context:r,coupons:i.coupons.items??[],pagination:{totalCount:i.coupons.totalCount??0,totalPages:i.coupons.totalPages??0,hasNextPage:Boolean(i.coupons.hasNextPage),hasPreviousPage:Boolean(i.coupons.hasPreviousPage),page:a??1,limit:o??null}}}async function Ct(e,t){let r=await $(e);await A(t,r.websiteId);let o=await u({service:"main",query:`query ($couponId: ID) {
172
+ }`,variables:{websiteId:t.websiteId,filter:i,limit:o,page:a}});return{context:t,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:o??null}}}async function Ir(e,r){let t=await x(e);await A(r,t.websiteId);let o=await u({service:"main",query:`query ($couponId: ID) {
173
173
  coupon(couponId: $couponId) {
174
- ${le}
174
+ ${ge}
175
175
  }
176
- }`,variables:{couponId:t}});return{context:r,coupon:o.coupon}}async function qt(e,t){let r=await $(e),o=P(t,"input");if(o.websiteId&&o.websiteId!==r.websiteId)throw Error("El websiteId del input no coincide con el website seleccionado.");let a={...o,websiteId:r.websiteId},n=Ro(a),i=await u({service:"main",query:n,variables:a});return{context:r,coupon:i.createCoupon}}async function It(e,t,r){let o=await $(e);await A(t,o.websiteId);let a=P(r,"input"),n=await u({service:"main",query:`mutation ($couponId: ID, $coupon: UpdateCouponInput) {
176
+ }`,variables:{couponId:r}});return{context:t,coupon:o.coupon}}async function xr(e,r){let t=await x(e),o=G(r,"input");if(o.websiteId&&o.websiteId!==t.websiteId)throw Error("El websiteId del input no coincide con el website seleccionado.");let a={...o,websiteId:t.websiteId},i=Ko(a),n=await u({service:"main",query:i,variables:a});return{context:t,coupon:n.createCoupon}}async function $r(e,r,t){let o=await x(e);await A(r,o.websiteId);let a=G(t,"input"),i=await u({service:"main",query:`mutation ($couponId: ID, $coupon: UpdateCouponInput) {
177
177
  updateCoupon(couponId: $couponId, coupon: $coupon) {
178
- ${le}
178
+ ${ge}
179
179
  }
180
- }`,variables:{couponId:t,coupon:a}});return{context:o,coupon:n.updateCoupon}}async function ht(e,t){let r=await $(e);await A(t,r.websiteId);let o=await u({service:"main",query:`mutation ($couponsIds: [ID]) {
180
+ }`,variables:{couponId:r,coupon:a}});return{context:o,coupon:i.updateCoupon}}async function Er(e,r){let t=await x(e);await A(r,t.websiteId);let o=await u({service:"main",query:`mutation ($couponsIds: [ID]) {
181
181
  deleteCoupons(couponsIds: $couponsIds, globalCoupon: false)
182
- }`,variables:{couponsIds:[t]}});return{context:r,couponId:t,deleted:o.deleteCoupons}}function D(){return`team-cli admin coupons
182
+ }`,variables:{couponsIds:[r]}});return{context:t,couponId:r,deleted:o.deleteCoupons}}function V(){return`team-cli admin coupons
183
183
 
184
184
  Administracion de cupones para el website seleccionado.
185
185
 
@@ -227,7 +227,7 @@ Acciones:
227
227
  Uso: team-cli admin <web> coupons codes delete <couponId> --ids '["id1","id2"]'
228
228
 
229
229
  Nota:
230
- El schema actual no expone update para coupon codes.`}function $t(){return`team-cli admin coupons create
230
+ El schema actual no expone update para coupon codes.`}function Sr(){return`team-cli admin coupons create
231
231
 
232
232
  Crea un cupón para el website seleccionado.
233
233
 
@@ -276,7 +276,7 @@ Ejemplo con schedule:
276
276
  Tips:
277
277
  Usa comillas simples afuera del JSON en shell.
278
278
  Usa arrays JSON reales para ids o listas.
279
- Si necesitas el shape exacto de un cupón existente, parte con: team-cli admin <web> coupons show <couponId>`}function xt(){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 jr(){return`team-cli admin coupons update
280
280
 
281
281
  Actualiza un cupón existente.
282
282
 
@@ -318,7 +318,7 @@ Ejemplo reemplazando restricciones:
318
318
  team-cli admin <web> coupons update <couponId> --input '{"requiresStoresIds":["store1"],"requiresPaymentTypes":["card"]}'
319
319
 
320
320
  Tip:
321
- Primero mira el cupón actual con: team-cli admin <web> coupons show <couponId>`}async function St(e,t){Re();let r=e[2]??t.filter;if(!r)throw Error("Debes indicar un término de búsqueda. Uso: team-cli admin search <texto>");let o=S(t,"limit"),a=S(t,"page"),n=lt(t,"only-active"),i=await u({service:"main",query:`query ($filter: String, $limit: BigInt, $page: BigInt, $onlyActiveWebsites: Boolean) {
321
+ Primero mira el cupón actual con: team-cli admin <web> coupons show <couponId>`}async function vr(e,r){Ue();let t=e[2]??r.filter;if(!t)throw Error("Debes indicar un término de búsqueda. Uso: team-cli admin search <texto>");let o=S(r,"limit"),a=S(r,"page"),i=gr(r,"only-active"),n=await u({service:"main",query:`query ($filter: String, $limit: BigInt, $page: BigInt, $onlyActiveWebsites: Boolean) {
322
322
  websites(filter: $filter, limit: $limit, page: $page, onlyActiveWebsites: $onlyActiveWebsites) {
323
323
  items {
324
324
  _id
@@ -334,7 +334,7 @@ Tip:
334
334
  hasNextPage
335
335
  hasPreviousPage
336
336
  }
337
- }`,variables:{filter:r,limit:o,page:a,onlyActiveWebsites:n}});return{searchTerm:r,websites:i.websites.items??[],pagination:{totalCount:i.websites.totalCount??0,totalPages:i.websites.totalPages??0,hasNextPage:Boolean(i.websites.hasNextPage),hasPreviousPage:Boolean(i.websites.hasPreviousPage),page:a??1,limit:o??null}}}function Et(){return`team-cli admin search
337
+ }`,variables:{filter:t,limit:o,page:a,onlyActiveWebsites:i}});return{searchTerm:t,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:o??null}}}function Ar(){return`team-cli admin search
338
338
 
339
339
  Buscar websites en admin.
340
340
 
@@ -354,7 +354,7 @@ Opciones:
354
354
  Ejemplos:
355
355
  team-cli admin search milas
356
356
  team-cli admin search buffalo --limit 5
357
- team-cli admin search pizza --only-active true`}function To(){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 Oo(e){let t=[e.address?.streetAddress,e.address?.extendedAddress,e.address?.locality].filter(Boolean);if(!t.length)return null;return t.join(", ")}async function jt(e){if(To(),!e)throw Error("Uso: team-cli admin <websiteId|domain> stores list");let t=await M(e),o=((await u({service:"main",query:`query ($websiteId: ID) {
357
+ team-cli admin search pizza --only-active true`}function Lo(){if(!g())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 ea(e){let r=[e.address?.streetAddress,e.address?.extendedAddress,e.address?.locality].filter(Boolean);if(!r.length)return null;return r.join(", ")}async function Rr(e){if(Lo(),!e)throw Error("Uso: team-cli admin <websiteId|domain> stores list");let r=await M(e),o=((await u({service:"main",query:`query ($websiteId: ID) {
358
358
  stores(websiteId: $websiteId) {
359
359
  items {
360
360
  _id
@@ -366,17 +366,17 @@ Ejemplos:
366
366
  }
367
367
  }
368
368
  }
369
- }`,variables:{websiteId:t.websiteId}})).stores.items??[]).map((a)=>({_id:a._id,name:a.name,address:Oo(a)})).sort((a,n)=>a.name.localeCompare(n.name,"es",{sensitivity:"base"}));return{context:t,stores:o,totalCount:o.length}}import{createInterface as Uo}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=Uo({input:process.stdin,output:process.stderr});return new Promise((r)=>{t.question(e,(o)=>{t.close(),r(o.trim())})})}async function At(e){return(await u({service:"auth",query:`mutation ($email: String!) {
369
+ }`,variables:{websiteId:r.websiteId}})).stores.items??[]).map((a)=>({_id:a._id,name:a.name,address:ea(a)})).sort((a,i)=>a.name.localeCompare(i.name,"es",{sensitivity:"base"}));return{context:r,stores:o,totalCount:o.length}}import{createInterface as ra}from"node:readline";function F(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 r=ra({input:process.stdin,output:process.stderr});return new Promise((t)=>{r.question(e,(o)=>{r.close(),t(o.trim())})})}async function Nr(e){return(await u({service:"auth",query:`mutation ($email: String!) {
370
370
  requestLoginCode(email: $email)
371
- }`,variables:{email:e}})).requestLoginCode}async function Nt(e,t,r){let o=await u({service:"auth",query:`mutation ($email: String!, $token: String!, $code: String!) {
371
+ }`,variables:{email:e}})).requestLoginCode}async function Tr(e,r,t){let o=await u({service:"auth",query:`mutation ($email: String!, $token: String!, $code: String!) {
372
372
  loginWithCode(email: $email, token: $token, code: $code) {
373
373
  token
374
374
  refreshToken
375
375
  }
376
- }`,variables:{email:e,token:t,code:r.toUpperCase()}});ue({email:e,token:o.loginWithCode.token,refreshToken:o.loginWithCode.refreshToken}),await Qo()}async function Qo(){if(!(await u({service:"main",query:"query { me { roles } }"})).me?.roles?.length)throw Ae(),Error("Solo miembros del equipo Justo pueden usar esta herramienta.")}async function vt(){let e=await z("Email: ");y(`Enviando codigo de verificacion...
377
- `);let t=await At(e);y(`Codigo enviado a tu email.
378
- `);let r=await z("Codigo: ");return await Nt(e,t,r),{ok:!0,authenticated:!0,email:e}}async function Rt(e){let t=F(e,"email"),r=F(e,"token"),o=F(e,"code");return await Nt(t,r,o),{ok:!0,authenticated:!0,email:t}}async function Tt(e){let t=F(e,"email");y(`Enviando codigo de verificacion...
379
- `);let r=await At(t);return{ok:!0,email:t,token:r,nextCommand:`npx @getjusto/team-cli auth login-with-token --email ${t} --token ${r} --code <CODIGO>`}}async function Ot(){return Ae(),{ok:!0,authenticated:!1}}async function Ut(){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 Te(){return`team-cli auth
376
+ }`,variables:{email:e,token:r,code:t.toUpperCase()}});me({email:e,token:o.loginWithCode.token,refreshToken:o.loginWithCode.refreshToken}),await ta()}async function ta(){if(!(await u({service:"main",query:"query { me { roles } }"})).me?.roles?.length)throw Te(),Error("Solo miembros del equipo Justo pueden usar esta herramienta.")}async function Or(){let e=await F("Email: ");C(`Enviando codigo de verificacion...
377
+ `);let r=await Nr(e);C(`Codigo enviado a tu email.
378
+ `);let t=await F("Codigo: ");return await Tr(e,r,t),{ok:!0,authenticated:!0,email:e}}async function Ur(e){let r=X(e,"email"),t=X(e,"token"),o=X(e,"code");return await Tr(r,t,o),{ok:!0,authenticated:!0,email:r}}async function Qr(e){let r=X(e,"email");C(`Enviando codigo de verificacion...
379
+ `);let t=await Nr(r);return{ok:!0,email:r,token:t,nextCommand:`npx @getjusto/team-cli auth login-with-token --email ${r} --token ${t} --code <CODIGO>`}}async function Br(){return Te(),{ok:!0,authenticated:!1}}async function _r(){let e=g();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 Qe(){return`team-cli auth
380
380
 
381
381
  Gestion de sesion.
382
382
 
@@ -402,7 +402,7 @@ Subcomandos:
402
402
 
403
403
  login-with-token
404
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 ye}from"node:child_process";import{createServer as Vt}from"node:http";import{existsSync as Zo,mkdirSync as Yo,openSync as Do,readFileSync as zo,rmSync as ko,writeFileSync as Ko}from"node:fs";import{dirname as Vo,join as Ce,resolve as Lt}from"node:path";import{request as Lo}from"node:http";import{request as ea}from"node:https";import{execFileSync as Jo}from"node:child_process";import{existsSync as fe,mkdirSync as Wo,readFileSync as we,readdirSync as _o,rmSync as Oe,writeFileSync as N}from"node:fs";import{basename as Bt,dirname as Mt,join as f,resolve as Pt}from"node:path";var de="iUzDOAFCUx33tmT6OCea",k="VITE_JUSTO_MAP_TILER_TOKEN";function Qt(){return`import {useState, type FormEvent} from 'react'
405
+ Uso: team-cli auth login-with-token --email <email> --token <token> --code <codigo>`}import{spawn as he}from"node:child_process";import{createServer as rt}from"node:http";import{existsSync as ga,mkdirSync as fa,openSync as wa,readFileSync as ba,rmSync as ya,writeFileSync as Ca}from"node:fs";import{dirname as ha,join as qe,resolve as tt}from"node:path";import{request as qa}from"node:http";import{request as Ia}from"node:https";import{execFileSync as oa}from"node:child_process";import{existsSync as be,mkdirSync as aa,readFileSync as ye,readdirSync as ia,rmSync as Be,writeFileSync as R}from"node:fs";import{basename as Gr,dirname as Fr,join as w,resolve as zr}from"node:path";var fe="iUzDOAFCUx33tmT6OCea",K="VITE_JUSTO_MAP_TILER_TOKEN";function Jr(){return`import {useState, type FormEvent} from 'react'
406
406
  import {Badge} from '@/components/ui/badge'
407
407
  import {Button} from '@/components/ui/button'
408
408
  import {Card, CardContent, CardDescription, CardHeader, CardTitle} from '@/components/ui/card'
@@ -420,8 +420,8 @@ import {justoCli} from '@/lib/justo'
420
420
  const defaultCommand = 'auth status'
421
421
  const queryExample = "data queries preview <queryId> --params '{\\"limit\\":10}'"
422
422
  const mapTilerToken =
423
- (import.meta.env as {${k}?: string}).${k} ||
424
- '${de}'
423
+ (import.meta.env as {${K}?: string}).${K} ||
424
+ '${fe}'
425
425
  const chartData = [
426
426
  {day: 'Lun', sessions: 12},
427
427
  {day: 'Mar', sessions: 18},
@@ -533,7 +533,14 @@ export function App() {
533
533
  <CardContent className="grid gap-4 text-sm leading-7 text-stone-600">
534
534
  <div>
535
535
  <p className="font-medium text-stone-900">1. Crea el entity</p>
536
- <p>team-cli spaces create --name 'Mi space' --description '...' --slug mi-space</p>
536
+ <p>
537
+ team-cli spaces create --name 'Mi space' --description '...' --slug
538
+ dashboard-1234
539
+ </p>
540
+ <p>
541
+ El sistema agrega automáticamente el prefijo del usuario. Ejemplo: si tu email
542
+ es tuusuario@justo.com, queda tuusuario:dashboard-1234.
543
+ </p>
537
544
  </div>
538
545
  <div>
539
546
  <p className="font-medium text-stone-900">2. Trabaja aquí mismo</p>
@@ -547,8 +554,9 @@ export function App() {
547
554
  </p>
548
555
  </div>
549
556
  <div>
550
- <p className="font-medium text-stone-900">4. Publica</p>
557
+ <p className="font-medium text-stone-900">4. Publica y commitea</p>
551
558
  <p>team-cli spaces publish &lt;spaceId&gt; --path ./mi-space-app</p>
559
+ <p>git add . && git commit -m "feat: update published space"</p>
552
560
  </div>
553
561
  <div>
554
562
  <p className="font-medium text-stone-900">Reglas de diseño</p>
@@ -624,7 +632,7 @@ export function App() {
624
632
  }
625
633
 
626
634
  export default App
627
- `}function Jt(){return`type JustoCliFunction = <T = unknown>(command: string) => Promise<T>
635
+ `}function Wr(){return`type JustoCliFunction = <T = unknown>(command: string) => Promise<T>
628
636
  type JustoStreamFunction = <T = unknown>(
629
637
  command: string,
630
638
  onRow: (row: T) => Promise<void> | void,
@@ -766,7 +774,7 @@ export async function justoStream<T = unknown>(
766
774
  }
767
775
 
768
776
  ensurePreviewWindowJusto()
769
- `}function Wt(e){return`# ${e}
777
+ `}function Pr(e){return`# ${e}
770
778
 
771
779
  Starter de Justo Spaces generado por \`team-cli spaces init\`.
772
780
 
@@ -778,6 +786,7 @@ Incluye:
778
786
  - mapas con \`react-leaflet\` + MapTiler/OpenStreetMap
779
787
  - helper \`justoCli(...)\` para llamar \`window.justo.cli(...)\`
780
788
  - helper \`justoStream(...)\` para consumir NDJSON desde el CLI
789
+ - un repo git nuevo e independiente para versionar el space
781
790
 
782
791
  Reglas de diseño:
783
792
  - preferir siempre shadcn
@@ -785,15 +794,22 @@ Reglas de diseño:
785
794
  - usar paleta de colores neutra
786
795
 
787
796
  Flujo recomendado:
788
- 1. \`team-cli spaces create --name '...' --description '...' --slug ...\`
789
- 2. \`team-cli spaces preview --path . --open\`
790
- 3. desarrolla esta app
791
- 4. \`team-cli spaces publish <spaceId> --path .\`
792
- 5. abre el space en intra
797
+ 1. \`git add . && git commit -m "chore: initial space scaffold"\`
798
+ 2. \`team-cli spaces create --name '...' --description '...' --slug dashboard-1234\`
799
+ 3. \`team-cli spaces preview --path . --open\`
800
+ 4. desarrolla esta app
801
+ 5. \`team-cli spaces publish <spaceId> --path .\`
802
+ 6. \`git add . && git commit -m "feat: update published space"\`
803
+ 7. si necesitas retomarlo en otra carpeta, usa \`team-cli spaces fork <slug> --path ./otra-carpeta\`
804
+ 8. abre el space en intra
793
805
 
794
806
  Tip:
795
807
  - usa \`spaces preview --open\` para abrir el dashboard en el navegador por defecto y mostrárselo al usuario mientras lo iteras
796
- `}function _t(){return`import {StrictMode} from 'react'
808
+ - \`spaces publish\` sube el repo del space sin \`node_modules\` ni otros archivos ignorados por git, además del build listo para servir
809
+ - después de \`spaces init\`, haz un initial commit para fijar el scaffold base
810
+ - después de cada publish, haz commit para que el repo refleje exactamente lo que quedó publicado
811
+ - si alguien necesita ver el dashboard y no puede cargar data, comparte las queries del dashboard con \`team-cli data queries add-viewers <queryId> --emails 'persona@justo.com'\`
812
+ `}function Mr(){return`import {StrictMode} from 'react'
797
813
  import {createRoot} from 'react-dom/client'
798
814
  import App from './App.tsx'
799
815
  import './index.css'
@@ -807,14 +823,14 @@ createRoot(document.getElementById('root')!).render(
807
823
  </ThemeProvider>
808
824
  </StrictMode>,
809
825
  )
810
- `}function pe(){return process.execPath}function Q(e){if(process.platform==="win32")return`${e}.cmd`;return e}var Gt=".justo-space.json";function ge(e,t,r){Jo(e,t,{cwd:r,stdio:"inherit",env:{...process.env,CI:"1"}})}function Bo(e){if(!e)throw Error("Falta --path. Ejemplo: team-cli spaces init --path ./mi-space-app");let t=Pt(e);if(fe(t)){if(_o(t).length>0)throw Error(`La carpeta ya existe y no está vacía: ${t}`);Oe(t,{recursive:!0,force:!0})}return Wo(Mt(t),{recursive:!0}),t}function Mo(e){let t=f(e,"vite.config.ts"),r=we(t,"utf-8");if(r.includes("base: './'"))return;let o=r.replace("export default defineConfig({",`export default defineConfig({
811
- base: './',`);N(t,o)}function Po(e){let t=f(e,"tsconfig.app.json"),o=we(t,"utf-8").replace('"noUnusedLocals": true,','"noUnusedLocals": false,').replace('"noUnusedParameters": true,','"noUnusedParameters": false,');N(t,o)}function Go(e){let t=f(e,"package.json"),r=JSON.parse(we(t,"utf-8"));r.dependencies=r.dependencies||{},r.devDependencies=r.devDependencies||{},r.dependencies.leaflet="^1.9.4",r.dependencies["react-leaflet"]="^5.0.0",r.devDependencies["@types/leaflet"]="^1.9.20",r.justoSpaceApp=!0,N(t,`${JSON.stringify(r,null,2)}
812
- `)}function Fo(e){let t=f(e,"src","index.css"),r=we(t,"utf-8");if(r.includes("leaflet/dist/leaflet.css"))return;N(t,`@import "leaflet/dist/leaflet.css";
813
- ${r}`)}function Xo(e){let t=Bt(e);N(f(e,"README.md"),Wt(t)),N(f(e,"src","App.tsx"),Qt()),N(f(e,"src","main.tsx"),_t()),N(f(e,"src","lib","justo.ts"),Jt()),N(f(e,Gt),`${JSON.stringify({template:"react-vite-shadcn",version:1},null,2)}
814
- `),Oe(f(e,".git"),{recursive:!0,force:!0})}function Ho(e){Oe(f(e,"package-lock.json"),{force:!0})}function Ue(e){let t=Pt(e);if(!fe(t))throw Error(`No existe la app del space: ${t}`);if(!fe(f(t,Gt)))throw Error("Este publish solo acepta apps creadas con team-cli spaces init. Debes apuntar al root de esa app.");return t}function Ft(e){let t=Ue(e);ge(Q("yarn"),["build"],t);let r=f(t,"dist");if(!fe(f(r,"index.html")))throw Error("El build no generó dist/index.html");return r}function Xt(e){let t=Bo(e),r=Mt(t),o=Bt(t);return ge(Q("npx"),["shadcn@latest","init","-t","vite","-d","-y","-n",o],r),ge(Q("npx"),["shadcn@latest","add","-a","-y"],t),Ho(t),Go(t),ge(Q("yarn"),["install"],t),Mo(t),Po(t),Fo(t),Xo(t),{path:t,nextSteps:[`cd ${t}`,"team-cli spaces create --name '...' --description '...' --slug mi-space","team-cli spaces publish <spaceId> --path ."]}}function Ht(e){let t=[],r="",o=null,a=!1;for(let n of e){if(a){r+=n,a=!1;continue}if(n==="\\"){a=!0;continue}if(o){if(n===o)o=null;else r+=n;continue}if(n==='"'||n==="'"){o=n;continue}if(/\s/.test(n)){if(r)t.push(r),r="";continue}r+=n}if(o)throw Error("Comando inválido: falta cerrar una comilla");if(r)t.push(r);return t}var ta=".justo-space-preview",ra="preview.json",oa=30000;function qe(e){return Ce(e,ta)}function er(e){return Ce(qe(e),ra)}function Zt(e){return Ce(qe(e),"bridge.log")}function Yt(e){return Ce(qe(e),"vite.log")}function tr(e){Yo(qe(e),{recursive:!0})}function be(e){if(!e)return;try{process.kill(e,"SIGTERM")}catch{return}}function aa(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 na(e,t){if(!t)return{attempted:!1,opened:!1};let r=aa(e);return await new Promise((o)=>{let a=ye(r.command,r.args,{stdio:"ignore",detached:!0});a.once("error",()=>{o({attempted:!0,opened:!1,message:"No se pudo abrir el navegador por defecto automáticamente. Abre la URL manualmente."})}),a.once("spawn",()=>{a.unref(),o({attempted:!0,opened:!0})})})}function ia(e){let t=er(e);if(!Zo(t))return;try{let r=JSON.parse(zo(t,"utf-8"));be(r.appPid),be(r.bridgePid)}catch{}ko(t,{force:!0})}function Dt(){return new Promise((e,t)=>{let r=Vt();r.listen(0,"127.0.0.1",()=>{let o=r.address();if(!o||typeof o==="string"){r.close(),t(Error("No se pudo obtener un puerto libre"));return}let{port:a}=o;r.close((n)=>{if(n){t(n);return}e(a)})}),r.on("error",t)})}function zt(e){return new Promise((t)=>setTimeout(t,e))}function sa(e){return new Promise((t,r)=>{let n=(new URL(e).protocol==="https:"?ea:Lo)(e,{method:"GET"},(i)=>{t(i.statusCode||0),i.resume()});n.on("error",r),n.end()})}async function kt(e,t=oa){let r=Date.now();while(Date.now()-r<t){try{if(await sa(e)>0)return}catch{await zt(500);continue}await zt(500)}throw Error(`Timeout esperando que el preview responda en ${e}`)}function ca(e){return tr(Vo(e)),Do(e,"a")}function Kt(e,t,r,o,a){let n=ca(o),i=ye(e,t,{cwd:r,detached:!0,stdio:["ignore",n,n],env:{...process.env,...a}});if(!i.pid)throw Error(`No se pudo iniciar el proceso ${e}`);return i.unref(),i.pid}function rr(){let e=rt("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 ua(e){let t=[];for await(let r of e)t.push(Buffer.isBuffer(r)?r:Buffer.from(r));return Buffer.concat(t).toString("utf-8")}function K(e,t,r){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(r))}function Qe(e){let t=e.trim(),r=new Set([0]);for(let a=0;a<t.length;a++)if(t[a]==="{"||t[a]==="[")r.add(a);let o=[...r].sort((a,n)=>n-a);for(let a of o)try{return JSON.parse(t.slice(a))}catch{continue}return t}function or(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 ma(e,t){return{VITE_JUSTO_CLI_ENDPOINT:e,VITE_JUSTO_STREAM_ENDPOINT:t,VITE_JUSTO_CLI_MODE:"preview",[k]:de}}function la(e,t,r,o){return new Promise((a,n)=>{let i=ye(pe(),[t,"--env","prod",...o,"--format","json"],{cwd:process.cwd(),env:or(r),stdio:["ignore","pipe","pipe"]}),s="";i.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)}),i.stderr.on("data",(c)=>{s+=Buffer.from(c).toString("utf-8")}),i.on("error",n),i.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 m=Qe(s.trim());n(Error(m.error||s.trim()||"justoStream failed"))})})}async function ar(e){let t=Number(e.port);if(!t)throw Error("Falta --port para el bridge interno de preview");let r=rr(),o=Lt(e["cli-path"]||process.argv[1]||""),a=Vt(async(n,i)=>{if(n.method==="OPTIONS"){K(i,200,{ok:!0});return}if(n.method==="GET"&&n.url==="/__justo/health"){K(i,200,{ok:!0});return}if(n.method!=="POST"||n.url!=="/__justo/cli"&&n.url!=="/__justo/stream"){K(i,404,{ok:!1,error:"Not found"});return}try{let s=await ua(n),m=JSON.parse(s||"{}").command;if(!m)throw Error("Debes indicar un comando");let l=Array.isArray(m)?m:Ht(m);if(n.url==="/__justo/stream"){await la(i,o,r,l);return}let g=await new Promise((p,C)=>{let w=ye(pe(),[o,"--env","prod",...l,"--format","json"],{cwd:process.cwd(),env:or(r),stdio:["ignore","pipe","pipe"]}),re=[],W=[];w.stdout.on("data",(R)=>re.push(Buffer.from(R))),w.stderr.on("data",(R)=>W.push(Buffer.from(R))),w.on("error",C),w.on("close",(R)=>{let G=Buffer.concat(re).toString("utf-8")||Buffer.concat(W).toString("utf-8");if(R&&R!==0){let _r=Qe(G);C(Error(_r.error||G||"justoCli failed"));return}p(Qe(G))})});K(i,200,{result:g})}catch(s){let c=s instanceof Error?s.message:"Unexpected error";K(i,400,{error:c})}});await new Promise((n,i)=>{a.listen(t,"127.0.0.1",()=>n()),a.on("error",i)}),y(`Space preview bridge listening on http://127.0.0.1:${t}
815
- `),await new Promise((n,i)=>{a.on("close",()=>n()),a.on("error",i)})}async function nr(e){let t=e.path;if(!t)throw Error("Falta --path. Ejemplo: team-cli spaces preview --path ./mi-space-app");let r=Ue(t);rr(),tr(r),ia(r);let o=Number(e.port)||await Dt(),a=Number(e["bridge-port"])||await Dt(),n=e.open==="true",i=`http://127.0.0.1:${o}`,s=`http://127.0.0.1:${a}/__justo/cli`,c=`http://127.0.0.1:${a}/__justo/stream`,m=Lt(process.argv[1]||""),l=Kt(pe(),[m,"__spaces-preview-bridge","--port",String(a),"--cli-path",m],process.cwd(),Zt(r),{}),g=Kt(Q("yarn"),["dev","--host","127.0.0.1","--port",String(o)],r,Yt(r),ma(s,c));try{await kt(`http://127.0.0.1:${a}/__justo/health`),await kt(i)}catch(w){throw be(g),be(l),w}let p={appPid:g,bridgePid:l,previewUrl:i,bridgeUrl:s,streamUrl:c,cliEnv:"prod"};Ko(er(r),`${JSON.stringify(p,null,2)}
816
- `);let C=await na(i,n);return{ok:!0,path:r,previewUrl:i,bridgeUrl:s,streamUrl:c,cliEnv:"prod",appPid:g,bridgePid:l,logs:{app:Yt(r),bridge:Zt(r)},open:C}}import{writeFileSync as ha}from"node:fs";import{mkdtempSync as da,readFileSync as pa,rmSync as ga,writeFileSync as fa}from"node:fs";import{tmpdir as wa}from"node:os";import{join as ir}from"node:path";import{spawnSync as ba}from"node:child_process";function ya(e){return`'${e.replaceAll("'",`'"'"'`)}'`}function sr(e,t){if(e==null)return;if(!Array.isArray(e)||e.some((r)=>typeof r!=="string"))throw Error(`${t} debe ser un arreglo de strings.`);return e}function Ca(e){if(!Array.isArray(e))throw Error("variables debe ser un arreglo.");return e.map((t,r)=>{if(!t||typeof t!=="object"||Array.isArray(t))throw Error(`variables[${r}] debe ser un objeto.`);let o=t;if(typeof o.key!=="string"||!o.key)throw Error(`variables[${r}].key debe ser un string no vacío.`);if(typeof o.fieldType!=="string"||!o.fieldType)throw Error(`variables[${r}].fieldType debe ser un string no vacío.`);if(o.fieldParams!=null&&typeof o.fieldParams!=="string")throw Error(`variables[${r}].fieldParams debe ser un string.`);return{key:o.key,fieldType:o.fieldType,fieldParams:typeof o.fieldParams==="string"?o.fieldParams:void 0}})}function qa(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:sr(t.allowedUsersIds,"allowedUsersIds")??[],tags:sr(t.tags,"tags")??[],pipeline:t.pipeline,variables:Ca(t.variables)}}function cr(e){let t=process.env.VISUAL||process.env.EDITOR||"vi",r=da(ir(wa(),"team-cli-query-")),o=ir(r,"aggregation-query.json");fa(o,`${JSON.stringify(e,null,2)}
817
- `);let a=`${t} ${ya(o)}`,n=ba(a,{shell:!0,stdio:"inherit"});if(n.error)throw Error(`No se pudo abrir el editor "${t}": ${n.error.message}`);if(n.status!==0)throw Error(`El editor terminó con código ${n.status}.`);try{let i=pa(o,"utf-8");if(!i.trim())throw Error("El archivo quedó vacío.");let s;try{s=JSON.parse(i)}catch{throw Error("El archivo editado no contiene JSON válido.")}return qa(s)}finally{ga(r,{recursive:!0,force:!0})}}function v(){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 O(e,t){let r=e[3];if(!r)throw Error(`Uso: ${t}`);return r}function V(e){if(!e.params)return{};try{return JSON.parse(e.params)}catch{throw Error("--params debe ser un JSON válido.")}}function ur(e){let t=e.limit;if(!t)throw Error("--limit es requerido. Ejemplo: --limit 1000");let r=Number(t);if(!Number.isInteger(r)||r<=0)throw Error("--limit debe ser un entero positivo.");return r}function Je(e){if(typeof e!=="string")return e;try{return JSON.parse(e)}catch{return{value:e}}}async function L(e){return(await u({service:"data",query:`query ($aggregationQueryId: String) {
826
+ `}function we(){return process.execPath}function _(e){if(process.platform==="win32")return`${e}.cmd`;return e}var Dr=".justo-space.json";function L(e,r,t){oa(e,r,{cwd:t,stdio:"inherit",env:{...process.env,CI:"1"}})}function na(e){if(!e)throw Error("Falta --path. Ejemplo: team-cli spaces init --path ./mi-space-app");let r=zr(e);if(be(r)){if(ia(r).length>0)throw Error(`La carpeta ya existe y no está vacía: ${r}`);Be(r,{recursive:!0,force:!0})}return aa(Fr(r),{recursive:!0}),r}function sa(e){let r=w(e,"vite.config.ts"),t=ye(r,"utf-8");if(t.includes("base: './'"))return;let o=t.replace("export default defineConfig({",`export default defineConfig({
827
+ base: './',`);R(r,o)}function ca(e){let r=w(e,"tsconfig.app.json"),o=ye(r,"utf-8").replace('"noUnusedLocals": true,','"noUnusedLocals": false,').replace('"noUnusedParameters": true,','"noUnusedParameters": false,');R(r,o)}function ua(e){let r=w(e,"package.json"),t=JSON.parse(ye(r,"utf-8"));t.dependencies=t.dependencies||{},t.devDependencies=t.devDependencies||{},t.dependencies.leaflet="^1.9.4",t.dependencies["react-leaflet"]="^5.0.0",t.devDependencies["@types/leaflet"]="^1.9.20",t.justoSpaceApp=!0,R(r,`${JSON.stringify(t,null,2)}
828
+ `)}function la(e){let r=w(e,"src","index.css"),t=ye(r,"utf-8");if(t.includes("leaflet/dist/leaflet.css"))return;R(r,`@import "leaflet/dist/leaflet.css";
829
+ ${t}`)}function ma(e){let r=Gr(e);R(w(e,"README.md"),Pr(r)),R(w(e,"src","App.tsx"),Jr()),R(w(e,"src","main.tsx"),Mr()),R(w(e,"src","lib","justo.ts"),Wr()),R(w(e,Dr),`${JSON.stringify({template:"react-vite-shadcn",version:1},null,2)}
830
+ `),Be(w(e,".git"),{recursive:!0,force:!0})}function da(e){L("git",["init"],e)}function pa(e){Be(w(e,"package-lock.json"),{force:!0})}function _e(e){let r=zr(e);if(!be(r))throw Error(`No existe la app del space: ${r}`);if(!be(w(r,Dr)))throw Error("Este publish solo acepta apps creadas con team-cli spaces init. Debes apuntar al root de esa app.");return r}function Xr(e){let r=_e(e);L(_("yarn"),["build"],r);let t=w(r,"dist");if(!be(w(t,"index.html")))throw Error("El build no generó dist/index.html");return t}function Hr(e){let r=na(e),t=Fr(r),o=Gr(r);return L(_("npx"),["shadcn@latest","init","-t","vite","-d","-y","-n",o],t),L(_("npx"),["shadcn@latest","add","-a","-y"],r),pa(r),ua(r),L(_("yarn"),["install"],r),sa(r),ca(r),la(r),ma(r),da(r),{path:r,nextSteps:[`cd ${r}`,'git add . && git commit -m "chore: initial space scaffold"',"team-cli spaces create --name '...' --description '...' --slug dashboard-1234","team-cli spaces publish <spaceId> --path .",'git add . && git commit -m "feat: update published space"']}}function Zr(e){let r=[],t="",o=null,a=!1;for(let i of e){if(a){t+=i,a=!1;continue}if(i==="\\"){a=!0;continue}if(o){if(i===o)o=null;else t+=i;continue}if(i==='"'||i==="'"){o=i;continue}if(/\s/.test(i)){if(t)r.push(t),t="";continue}t+=i}if(o)throw Error("Comando inválido: falta cerrar una comilla");if(t)r.push(t);return r}var xa=".justo-space-preview",$a="preview.json",Ea=30000;function Ie(e){return qe(e,xa)}function ot(e){return qe(Ie(e),$a)}function kr(e){return qe(Ie(e),"bridge.log")}function Yr(e){return qe(Ie(e),"vite.log")}function at(e){fa(Ie(e),{recursive:!0})}function Ce(e){if(!e)return;try{process.kill(e,"SIGTERM")}catch{return}}function Sa(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 ja(e,r){if(!r)return{attempted:!1,opened:!1};let t=Sa(e);return await new Promise((o)=>{let a=he(t.command,t.args,{stdio:"ignore",detached:!0});a.once("error",()=>{o({attempted:!0,opened:!1,message:"No se pudo abrir el navegador por defecto automáticamente. Abre la URL manualmente."})}),a.once("spawn",()=>{a.unref(),o({attempted:!0,opened:!0})})})}function va(e){let r=ot(e);if(!ga(r))return;try{let t=JSON.parse(ba(r,"utf-8"));Ce(t.appPid),Ce(t.bridgePid)}catch{}ya(r,{force:!0})}function Vr(){return new Promise((e,r)=>{let t=rt();t.listen(0,"127.0.0.1",()=>{let o=t.address();if(!o||typeof o==="string"){t.close(),r(Error("No se pudo obtener un puerto libre"));return}let{port:a}=o;t.close((i)=>{if(i){r(i);return}e(a)})}),t.on("error",r)})}function Kr(e){return new Promise((r)=>setTimeout(r,e))}function Aa(e){return new Promise((r,t)=>{let i=(new URL(e).protocol==="https:"?Ia:qa)(e,{method:"GET"},(n)=>{r(n.statusCode||0),n.resume()});i.on("error",t),i.end()})}async function Lr(e,r=Ea){let t=Date.now();while(Date.now()-t<r){try{if(await Aa(e)>0)return}catch{await Kr(500);continue}await Kr(500)}throw Error(`Timeout esperando que el preview responda en ${e}`)}function Ra(e){return at(ha(e)),wa(e,"a")}function et(e,r,t,o,a){let i=Ra(o),n=he(e,r,{cwd:t,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 it(){let e=ir("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 Na(e){let r=[];for await(let t of e)r.push(Buffer.isBuffer(t)?t:Buffer.from(t));return Buffer.concat(r).toString("utf-8")}function ee(e,r,t){e.writeHead(r,{"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(t))}function Je(e){let r=e.trim(),t=new Set([0]);for(let a=0;a<r.length;a++)if(r[a]==="{"||r[a]==="[")t.add(a);let o=[...t].sort((a,i)=>i-a);for(let a of o)try{return JSON.parse(r.slice(a))}catch{continue}return r}function nt(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 Ta(e,r){return{VITE_JUSTO_CLI_ENDPOINT:e,VITE_JUSTO_STREAM_ENDPOINT:r,VITE_JUSTO_CLI_MODE:"preview",[K]:fe}}function Oa(e,r,t,o){return new Promise((a,i)=>{let n=he(we(),[r,"--env","prod",...o,"--format","json"],{cwd:process.cwd(),env:nt(t),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 l=Je(s.trim());i(Error(l.error||s.trim()||"justoStream failed"))})})}async function st(e){let r=Number(e.port);if(!r)throw Error("Falta --port para el bridge interno de preview");let t=it(),o=tt(e["cli-path"]||process.argv[1]||""),a=rt(async(i,n)=>{if(i.method==="OPTIONS"){ee(n,200,{ok:!0});return}if(i.method==="GET"&&i.url==="/__justo/health"){ee(n,200,{ok:!0});return}if(i.method!=="POST"||i.url!=="/__justo/cli"&&i.url!=="/__justo/stream"){ee(n,404,{ok:!1,error:"Not found"});return}try{let s=await Na(i),l=JSON.parse(s||"{}").command;if(!l)throw Error("Debes indicar un comando");let m=Array.isArray(l)?l:Zr(l);if(i.url==="/__justo/stream"){await Oa(n,o,t,m);return}let p=await new Promise((d,b)=>{let f=he(we(),[o,"--env","prod",...m,"--format","json"],{cwd:process.cwd(),env:nt(t),stdio:["ignore","pipe","pipe"]}),T=[],O=[];f.stdout.on("data",(U)=>T.push(Buffer.from(U))),f.stderr.on("data",(U)=>O.push(Buffer.from(U))),f.on("error",b),f.on("close",(U)=>{let D=Buffer.concat(T).toString("utf-8")||Buffer.concat(O).toString("utf-8");if(U&&U!==0){let io=Je(D);b(Error(io.error||D||"justoCli failed"));return}d(Je(D))})});ee(n,200,{result:p})}catch(s){let c=s instanceof Error?s.message:"Unexpected error";ee(n,400,{error:c})}});await new Promise((i,n)=>{a.listen(r,"127.0.0.1",()=>i()),a.on("error",n)}),C(`Space preview bridge listening on http://127.0.0.1:${r}
831
+ `),await new Promise((i,n)=>{a.on("close",()=>i()),a.on("error",n)})}async function ct(e){let r=e.path;if(!r)throw Error("Falta --path. Ejemplo: team-cli spaces preview --path ./mi-space-app");let t=_e(r);it(),at(t),va(t);let o=Number(e.port)||await Vr(),a=Number(e["bridge-port"])||await Vr(),i=e.open==="true",n=`http://127.0.0.1:${o}`,s=`http://127.0.0.1:${a}/__justo/cli`,c=`http://127.0.0.1:${a}/__justo/stream`,l=tt(process.argv[1]||""),m=et(we(),[l,"__spaces-preview-bridge","--port",String(a),"--cli-path",l],process.cwd(),kr(t),{}),p=et(_("yarn"),["dev","--host","127.0.0.1","--port",String(o)],t,Yr(t),Ta(s,c));try{await Lr(`http://127.0.0.1:${a}/__justo/health`),await Lr(n)}catch(f){throw Ce(p),Ce(m),f}let d={appPid:p,bridgePid:m,previewUrl:n,bridgeUrl:s,streamUrl:c,cliEnv:"prod"};Ca(ot(t),`${JSON.stringify(d,null,2)}
832
+ `);let b=await ja(n,i);return{ok:!0,path:t,previewUrl:n,bridgeUrl:s,streamUrl:c,cliEnv:"prod",appPid:p,bridgePid:m,logs:{app:Yr(t),bridge:kr(t)},open:b}}import{writeFileSync as za}from"node:fs";import{mkdtempSync as Ua,readFileSync as Qa,rmSync as Ba,writeFileSync as _a}from"node:fs";import{tmpdir as Ja}from"node:os";import{join as ut}from"node:path";import{spawnSync as Wa}from"node:child_process";function Pa(e){return`'${e.replaceAll("'",`'"'"'`)}'`}function lt(e,r){if(e==null)return;if(!Array.isArray(e)||e.some((t)=>typeof t!=="string"))throw Error(`${r} debe ser un arreglo de strings.`);return e}function Ma(e){if(!Array.isArray(e))throw Error("variables debe ser un arreglo.");return e.map((r,t)=>{if(!r||typeof r!=="object"||Array.isArray(r))throw Error(`variables[${t}] debe ser un objeto.`);let o=r;if(typeof o.key!=="string"||!o.key)throw Error(`variables[${t}].key debe ser un string no vacío.`);if(typeof o.fieldType!=="string"||!o.fieldType)throw Error(`variables[${t}].fieldType debe ser un string no vacío.`);if(o.fieldParams!=null&&typeof o.fieldParams!=="string")throw Error(`variables[${t}].fieldParams debe ser un string.`);return{key:o.key,fieldType:o.fieldType,fieldParams:typeof o.fieldParams==="string"?o.fieldParams:void 0}})}function Ga(e){if(!e||typeof e!=="object"||Array.isArray(e))throw Error("El archivo editado debe contener un objeto JSON.");let r=e;if(typeof r.name!=="string"||!r.name.trim())throw Error("name debe ser un string no vacío.");if(r.description!=null&&typeof r.description!=="string")throw Error("description debe ser un string.");if(typeof r.collection!=="string"||!r.collection.trim())throw Error("collection debe ser un string no vacío.");if(typeof r.pipeline!=="string")throw Error("pipeline debe ser un string.");return{name:r.name.trim(),description:r.description?.trim()||void 0,collection:r.collection.trim(),allowedUsersIds:lt(r.allowedUsersIds,"allowedUsersIds")??[],tags:lt(r.tags,"tags")??[],pipeline:r.pipeline,variables:Ma(r.variables)}}function mt(e){let r=process.env.VISUAL||process.env.EDITOR||"vi",t=Ua(ut(Ja(),"team-cli-query-")),o=ut(t,"aggregation-query.json");_a(o,`${JSON.stringify(e,null,2)}
833
+ `);let a=`${r} ${Pa(o)}`,i=Wa(a,{shell:!0,stdio:"inherit"});if(i.error)throw Error(`No se pudo abrir el editor "${r}": ${i.error.message}`);if(i.status!==0)throw Error(`El editor terminó con código ${i.status}.`);try{let n=Qa(o,"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 Ga(s)}finally{Ba(t,{recursive:!0,force:!0})}}function $(){if(!g())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 N(e,r){let t=e[3];if(!t)throw Error(`Uso: ${r}`);return t}function re(e){if(!e.params)return{};try{return JSON.parse(e.params)}catch{throw Error("--params debe ser un JSON válido.")}}function dt(e){let r=e.limit;if(!r)throw Error("--limit es requerido. Ejemplo: --limit 1000");let t=Number(r);if(!Number.isInteger(t)||t<=0)throw Error("--limit debe ser un entero positivo.");return t}function pt(e){let r=e.emails;if(!r)throw Error("--emails es requerido. Ejemplo: --emails ana@justo.com,bob@justo.com");let t=r.split(",").map((a)=>a.trim().toLowerCase()).filter(Boolean);if(!t.length)throw Error("--emails debe contener al menos un email.");let o=t.find((a)=>!a.includes("@"));if(o)throw Error(`Email inválido: ${o}`);return[...new Set(t)]}function We(e){if(typeof e!=="string")return e;try{return JSON.parse(e)}catch{return{value:e}}}async function z(e){return(await u({service:"data",query:`query ($aggregationQueryId: String) {
818
834
  aggregationQuery(aggregationQueryId: $aggregationQueryId) {
819
835
  _id
820
836
  name
@@ -830,11 +846,28 @@ ${r}`)}function Xo(e){let t=Bt(e);N(f(e,"README.md"),Wt(t)),N(f(e,"src","App.tsx
830
846
  fieldParams
831
847
  }
832
848
  }
833
- }`,variables:{aggregationQueryId:e}})).aggregationQuery}function mr(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 We(e,t){let r=await u({service:"data",query:`mutation ($aggregationQueryId: String, $params: JSON) {
849
+ }`,variables:{aggregationQueryId:e}})).aggregationQuery}async function gt(e){return await Promise.all(e.map(async(t)=>{let a=(await u({service:"main",query:`query ($filter: String, $limit: BigInt) {
850
+ justoUsers(filter: $filter, limit: $limit) {
851
+ items {
852
+ _id
853
+ email
854
+ fullName
855
+ }
856
+ }
857
+ }`,variables:{filter:t,limit:10}})).justoUsers?.items?.find((i)=>i.email?.toLowerCase()===t);if(!a?._id)throw Error(`No encontramos un usuario de Justo para ${t}`);return a}))}function ft(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 Pe(e,r){let t=await u({service:"data",query:`mutation ($aggregationQueryId: String, $params: JSON) {
834
858
  testAggregationQuery(aggregationQueryId: $aggregationQueryId, params: $params)
835
- }`,variables:{aggregationQueryId:e,params:t}});return Je(r.testAggregationQuery)}function Ia(e){try{return JSON.parse(e).error||e}catch{return e}}async function lr(e,t,r){let o=await fetch(`${h("data")}/aggregation-queries/${e}/run`,{method:"POST",headers:await ve(),body:JSON.stringify({params:t,limit:r}),signal:AbortSignal.timeout(315000)});if(!o.ok){let m=await o.text();throw Error(Ia(m)||"No se pudo ejecutar el query.")}if(!o.body)throw Error("El servidor no devolvió un stream de datos.");let a=o.body.getReader(),n=new TextDecoder,i="",s=0;while(!0){let{done:m,value:l}=await a.read();if(m)break;let g=n.decode(l,{stream:!0});process.stdout.write(g),i+=g;let p=i.indexOf(`
836
- `);while(p>=0){if(i.slice(0,p).trim())s++;i=i.slice(p+1),p=i.indexOf(`
837
- `)}}let c=n.decode();if(c)process.stdout.write(c),i+=c;if(i.trim())s++;return{ok:!0,queryId:e,limit:r,rows:s}}async function _e(e,t){await u({service:"data",query:`mutation ($aggregationQueryId: String, $aggregationQuery: UpdateAggregationQueryInput) {
859
+ }`,variables:{aggregationQueryId:e,params:r}});return We(t.testAggregationQuery)}function Fa(e){try{return JSON.parse(e).error||e}catch{return e}}async function wt(e,r,t){let o=await fetch(`${h("data")}/aggregation-queries/${e}/run`,{method:"POST",headers:await Oe(),body:JSON.stringify({params:r,limit:t}),signal:AbortSignal.timeout(315000)});if(!o.ok){let l=await o.text();throw Error(Fa(l)||"No se pudo ejecutar el query.")}if(!o.body)throw Error("El servidor no devolvió un stream de datos.");let a=o.body.getReader(),i=new TextDecoder,n="",s=0;while(!0){let{done:l,value:m}=await a.read();if(l)break;let p=i.decode(m,{stream:!0});process.stdout.write(p),n+=p;let d=n.indexOf(`
860
+ `);while(d>=0){if(n.slice(0,d).trim())s++;n=n.slice(d+1),d=n.indexOf(`
861
+ `)}}let c=i.decode();if(c)process.stdout.write(c),n+=c;if(n.trim())s++;return{ok:!0,queryId:e,limit:t,rows:s}}async function Me(e,r){await Ge(e,{name:r.name,description:r.description,collection:r.collection,allowedUsersIds:r.allowedUsersIds,tags:r.tags}),await u({service:"data",query:`mutation ($aggregationQueryId: String, $pipeline: String, $variables: [AggregationQueryVariableInput]) {
862
+ addAggregationQueryVersion(
863
+ aggregationQueryId: $aggregationQueryId
864
+ pipeline: $pipeline
865
+ variables: $variables
866
+ ) {
867
+ _id
868
+ currentVersionIndex
869
+ }
870
+ }`,variables:{aggregationQueryId:e,pipeline:r.pipeline,variables:r.variables}})}async function Ge(e,r){await u({service:"data",query:`mutation ($aggregationQueryId: String, $aggregationQuery: UpdateAggregationQueryInput) {
838
871
  updateAggregationQuery(
839
872
  aggregationQueryId: $aggregationQueryId
840
873
  aggregationQuery: $aggregationQuery
@@ -847,16 +880,7 @@ ${r}`)}function Xo(e){let t=Bt(e);N(f(e,"README.md"),Wt(t)),N(f(e,"src","App.tsx
847
880
  tags
848
881
  currentVersionIndex
849
882
  }
850
- }`,variables:{aggregationQueryId:e,aggregationQuery:{name:t.name,description:t.description,collection:t.collection,allowedUsersIds:t.allowedUsersIds,tags:t.tags}}}),await u({service:"data",query:`mutation ($aggregationQueryId: String, $pipeline: String, $variables: [AggregationQueryVariableInput]) {
851
- addAggregationQueryVersion(
852
- aggregationQueryId: $aggregationQueryId
853
- pipeline: $pipeline
854
- variables: $variables
855
- ) {
856
- _id
857
- currentVersionIndex
858
- }
859
- }`,variables:{aggregationQueryId:e,pipeline:t.pipeline,variables:t.variables}})}async function dr(){return(await u({service:"data",query:`mutation {
883
+ }`,variables:{aggregationQueryId:e,aggregationQuery:{name:r.name,description:r.description,collection:r.collection,allowedUsersIds:r.allowedUsersIds,tags:r.tags}}})}async function bt(){return(await u({service:"data",query:`mutation {
860
884
  createAggregationQuery {
861
885
  _id
862
886
  name
@@ -872,7 +896,7 @@ ${r}`)}function Xo(e){let t=Bt(e);N(f(e,"README.md"),Wt(t)),N(f(e,"src","App.tsx
872
896
  fieldParams
873
897
  }
874
898
  }
875
- }`})).createAggregationQuery}function $a(e){if(!Array.isArray(e))throw Error("El preview del query debe devolver un arreglo para usar AI edit.");return e}async function xa(e){let t=await u({service:"messenger",query:`mutation generateAdminQuery(
899
+ }`})).createAggregationQuery}function Da(e){if(!Array.isArray(e))throw Error("El preview del query debe devolver un arreglo para usar AI edit.");return e}async function Xa(e){let r=await u({service:"messenger",query:`mutation generateAdminQuery(
876
900
  $prompt: String
877
901
  $name: String
878
902
  $description: String
@@ -898,13 +922,17 @@ ${r}`)}function Xo(e){let t=Bt(e);N(f(e,"README.md"),Wt(t)),N(f(e,"src","App.tsx
898
922
  aggregationDescription
899
923
  aggregationName
900
924
  }
901
- }`,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 pr(){return v(),await dr()}async function gr(e){v();let t=O(e,"team-cli data queries edit <queryId>"),r=await L(t),o=cr(mr(r));return await _e(t,o),{ok:!0,queryId:t,name:o.name,collection:o.collection}}async function fr(e,t){v();let r=O(e,"team-cli data queries ai-edit <queryId> --prompt '<texto>' [--params '<json>']"),o=await L(r),a=t.prompt||await z("Describe los cambios para la IA: ");if(!a)throw Error("Debes indicar un prompt para AI edit.");let n=V(t),i;if(t.params){y(`Obteniendo preview del query actual...
902
- `);try{let c=await We(r,n);i=$a(c)}catch(c){let m=c instanceof Error?c.message:String(c);throw Error(`No se pudo obtener el preview para AI edit: ${m}`)}}y(`Generando propuesta con IA...
903
- `);let s=await xa({prompt:a,fullCollectionName:o.collection,pipeline:o.pipeline,preview:i,description:o.description,name:o.name,variables:o.variables});return await _e(r,{name:o.name==="Nuevo query"?s.aggregationName||o.name:o.name,description:o.description||s.aggregationDescription,collection:s.fullCollectionName,allowedUsersIds:o.allowedUsersIds??[],tags:o.tags??[],pipeline:s.pipeline,variables:s.variables??[]}),{ok:!0,queryId:r,responseText:s.responseText,collection:s.fullCollectionName,name:s.aggregationName,description:s.aggregationDescription}}async function wr(e){v();let t=O(e,"team-cli data queries view <queryId>");return await L(t)}async function br(e){v();let t=O(e,"team-cli data queries view-pipeline <queryId>"),r=await L(t);return{queryId:t,pipeline:r.pipeline}}async function yr(e,t){v();let r=O(e,"team-cli data queries preview <queryId> --params '<json>'"),o=V(t),a=await We(r,o);return Je(a)}async function Cr(e,t){v();let r=O(e,"team-cli data queries run <queryId> --limit <n> --params '<json>'"),o=V(t),a=ur(t);return await lr(r,o,a),{__streamHandled:!0}}function Sa(e){return new Promise((t)=>setTimeout(t,e))}async function qr(e,t){v();let r=O(e,"team-cli data queries download <queryId> --params '<json>'"),o=V(t);if(!t.path)throw Error("--path es requerido. Ejemplo: --path resultado.xlsx");y(`Iniciando descarga...
904
- `);let n=(await u({service:"data",query:`mutation ($aggregationQueryId: String, $params: JSON) {
925
+ }`,variables:e});if(!r.generateAdminQuery?.pipeline||!r.generateAdminQuery.fullCollectionName)throw Error("La IA no devolvió una versión válida del query.");return r.generateAdminQuery}async function Ha(e){let r=await u({service:"messenger",timeoutMs:120000,query:`mutation explainAdminQuery($prompt: String) {
926
+ explainAdminQuery(prompt: $prompt) {
927
+ responseText
928
+ }
929
+ }`,variables:{prompt:e}});if(!r.explainAdminQuery?.responseText)throw Error("La IA no devolvió una explicación válida.");return r.explainAdminQuery}async function yt(){return $(),await bt()}async function Ct(e){$();let r=e.prompt||await F("Explica qué query quieres investigar o construir: ");if(!r)throw Error("Debes indicar un prompt para explain.");return(await Ha(r)).responseText}async function ht(e){$();let r=N(e,"team-cli data queries edit <queryId>"),t=await z(r),o=mt(ft(t));return await Me(r,o),{ok:!0,queryId:r,name:o.name,collection:o.collection}}async function qt(e,r){$();let t=N(e,"team-cli data queries ai-edit <queryId> --prompt '<texto>' [--params '<json>']"),o=await z(t),a=r.prompt||await F("Describe los cambios para la IA: ");if(!a)throw Error("Debes indicar un prompt para AI edit.");let i=re(r),n;if(r.params){C(`Obteniendo preview del query actual...
930
+ `);try{let c=await Pe(t,i);n=Da(c)}catch(c){let l=c instanceof Error?c.message:String(c);throw Error(`No se pudo obtener el preview para AI edit: ${l}`)}}C(`Generando propuesta con IA...
931
+ `);let s=await Xa({prompt:a,fullCollectionName:o.collection,pipeline:o.pipeline,preview:n,description:o.description,name:o.name,variables:o.variables});return await Me(t,{name:o.name==="Nuevo query"?s.aggregationName||o.name:o.name,description:o.description||s.aggregationDescription,collection:s.fullCollectionName,allowedUsersIds:o.allowedUsersIds??[],tags:o.tags??[],pipeline:s.pipeline,variables:s.variables??[]}),{ok:!0,queryId:t,responseText:s.responseText,collection:s.fullCollectionName,name:s.aggregationName,description:s.aggregationDescription}}async function It(e){$();let r=N(e,"team-cli data queries view <queryId>");return await z(r)}async function xt(e){$();let r=N(e,"team-cli data queries view-pipeline <queryId>"),t=await z(r);return{queryId:r,pipeline:t.pipeline}}async function $t(e,r){$();let t=N(e,"team-cli data queries preview <queryId> --params '<json>'"),o=re(r),a=await Pe(t,o);return We(a)}async function Et(e,r){$();let t=N(e,"team-cli data queries run <queryId> --limit <n> --params '<json>'"),o=re(r),a=dt(r);return await wt(t,o,a),{__streamHandled:!0}}async function St(e,r){$();let t=N(e,"team-cli data queries add-viewers <queryId> --emails 'ana@justo.com,bob@justo.com'"),o=pt(r),a=await z(t),i=await gt(o),n=[...new Set([...a.allowedUsersIds??[],...i.map((s)=>s._id)])];return await Ge(t,{name:a.name,description:a.description,collection:a.collection,allowedUsersIds:n,tags:a.tags??[]}),{ok:!0,queryId:t,addedViewers:i.map((s)=>({_id:s._id,email:s.email,fullName:s.fullName})),allowedUsersIds:n}}function Za(e){return new Promise((r)=>setTimeout(r,e))}async function jt(e,r){$();let t=N(e,"team-cli data queries download <queryId> --params '<json>'"),o=re(r);if(!r.path)throw Error("--path es requerido. Ejemplo: --path resultado.xlsx");C(`Iniciando descarga...
932
+ `);let i=(await u({service:"data",query:`mutation ($aggregationQueryId: String, $params: JSON) {
905
933
  downloadAggregationQueryData(aggregationQueryId: $aggregationQueryId, params: $params)
906
- }`,variables:{aggregationQueryId:r,params:o}})).downloadAggregationQueryData;y(`Reporte en proceso (${n})...
907
- `);let i=null;while(!i){await Sa(1000);let m=await u({service:"data",query:`query ($id: String) {
934
+ }`,variables:{aggregationQueryId:t,params:o}})).downloadAggregationQueryData;C(`Reporte en proceso (${i})...
935
+ `);let n=null;while(!n){await Za(1000);let l=await u({service:"data",query:`query ($id: String) {
908
936
  getAsyncReport(id: $id) {
909
937
  _id
910
938
  status
@@ -912,22 +940,34 @@ ${r}`)}function Xo(e){let t=Bt(e);N(f(e,"README.md"),Wt(t)),N(f(e,"src","App.tsx
912
940
  fileUrl
913
941
  }
914
942
  getAsyncReportRecordsCount(id: $id)
915
- }`,variables:{id:n}}),l=m.getAsyncReport,g=m.getAsyncReportRecordsCount;if(l.status==="error")throw Error("El reporte falló al generarse.");if(l.fileUrl)i=l.fileUrl;else{let p=l.estimatedRecordsCount?` (~${l.estimatedRecordsCount} registros)`:"",C=g!=null?` ${g} procesados`:"";y(`\rGenerando...${p}${C}`)}}y(`
943
+ }`,variables:{id:i}}),m=l.getAsyncReport,p=l.getAsyncReportRecordsCount;if(m.status==="error")throw Error("El reporte falló al generarse.");if(m.fileUrl)n=m.fileUrl;else{let d=m.estimatedRecordsCount?` (~${m.estimatedRecordsCount} registros)`:"",b=p!=null?` ${p} procesados`:"";C(`\rGenerando...${d}${b}`)}}C(`
916
944
  Descargando archivo...
917
- `);let s=await fetch(i);if(!s.ok)throw Error(`Error descargando archivo: ${s.status}`);let c=Buffer.from(await s.arrayBuffer());return ha(t.path,c),{ok:!0,queryId:r,asyncReportId:n,outputPath:t.path,fileUrl:i}}function Be(){return`team-cli data
945
+ `);let s=await fetch(n);if(!s.ok)throw Error(`Error descargando archivo: ${s.status}`);let c=Buffer.from(await s.arrayBuffer());return za(r.path,c),{ok:!0,queryId:t,asyncReportId:i,outputPath:r.path,fileUrl:n}}function Fe(){return`team-cli data
918
946
 
919
947
  Comandos de datos y reportes.
920
948
 
921
949
  Recomendado:
922
- Si necesitas obtener data y no existe un query listo, usa create + ai-edit.
923
- Flujo sugerido: create -> ai-edit -> preview -> run o download.
950
+ Si necesitas obtener data y no existe un query listo, usa explain -> create -> ai-edit.
951
+ Flujo sugerido: explain -> create -> ai-edit -> preview -> run o download.
924
952
  Siempre que puedas, prefiere varias queries simples antes que un solo pipeline con lookup.
925
953
  Para dashboards suele ser mejor resolver joins en la UI o con queries separadas.
926
954
 
927
955
  Uso:
928
- team-cli data queries <subcomando> [opciones]
956
+ team-cli data <subcomando> [opciones]
929
957
 
930
958
  Subcomandos:
959
+ explain
960
+ Pedir una explicación guiada para investigar cómo construir un query usando el subagente de repo.
961
+ Uso: team-cli data explain --prompt '<texto>' [--format toon|json]
962
+ Solo disponible para usuarios con rol queries.
963
+
964
+ queries
965
+ Administrar y ejecutar aggregation queries.
966
+
967
+ Uso de queries:
968
+ team-cli data queries <subcomando> [opciones]
969
+
970
+ Subcomandos de queries:
931
971
  create
932
972
  Crear un query nuevo.
933
973
  Devuelve el _id para seguir con edit, ai-edit, view o preview.
@@ -961,21 +1001,29 @@ Subcomandos:
961
1001
  Descargar resultado completo como Excel.
962
1002
  Uso: team-cli data queries download <queryId> --path <filepath> [--params '<json>'] [--format toon|json]
963
1003
 
1004
+ add-viewers <queryId>
1005
+ Agregar personas con acceso a un query usando sus emails de Justo.
1006
+ Uso: team-cli data queries add-viewers <queryId> --emails 'ana@justo.com,bob@justo.com'
1007
+ Esto actualiza allowedUsersIds sin cambiar el pipeline ni crear una versión nueva.
1008
+
964
1009
  Opciones:
965
1010
  --params '<json>' Parametros del query. Default: {}
966
1011
  --limit <n> Requerido para run. Máximo 10000 por request.
1012
+ --emails '<csv>' Requerido para add-viewers. Lista separada por comas.
967
1013
  --prompt '<texto>' Prompt para ai-edit. Si no viene, se pide interactivamente.
968
1014
  --format <toon|json>
969
1015
  --path <filepath> Requerido para download
970
1016
 
971
1017
  Ejemplos:
1018
+ team-cli data explain --prompt 'Quiero entender dónde viven los campos de courier de los pedidos'
972
1019
  team-cli data queries create
973
1020
  team-cli data queries edit abc123
974
1021
  team-cli data queries ai-edit abc123 --prompt 'Filtra solo ordenes canceladas'
975
1022
  team-cli data queries ai-edit abc123 --prompt 'Ajusta el pipeline' --params '{"websiteId":"w1"}'
976
1023
  team-cli data queries preview abc123 --params '{"startDate": "2026-01-01"}'
977
1024
  team-cli data queries run abc123 --limit 1000 --params '{"startDate": "2026-01-01"}'
978
- team-cli data queries download abc123 --params '{"startDate": "2026-01-01"}' --path resultado.xlsx`}var Ir=["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"],hr=`
1025
+ team-cli data queries download abc123 --params '{"startDate": "2026-01-01"}' --path resultado.xlsx
1026
+ team-cli data queries add-viewers abc123 --emails 'ana@justo.com,bob@justo.com'`}var vt=["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"],At=`
979
1027
  query ResolverInfo($name: ID!, $mutation: Boolean!) {
980
1028
  params(name: $name, mutation: $mutation) {
981
1029
  name
@@ -984,8 +1032,8 @@ Ejemplos:
984
1032
  basicResultQuery
985
1033
  }
986
1034
  }
987
- `;function Ea(e){if(!e)throw Error("Uso: team-cli graphql <servicio> '<query>' [--variables '<json>'] [--format toon|json]");if(!Ir.includes(e))throw Error(`Servicio "${e}" no válido. Servicios disponibles: ${Ir.join(", ")}`)}async function ja(e,t){let r;try{let o=await u({service:e,query:hr,variables:{name:t,mutation:!1}});return{service:e,operationName:t,operationType:"query",info:o.params}}catch(o){r=o}try{let o=await u({service:e,query:hr,variables:{name:t,mutation:!0}});return{service:e,operationName:t,operationType:"mutation",info:o.params}}catch(o){let a=r instanceof Error?r.message:"",n=o instanceof Error?o.message:"";if(a.includes('Cannot query field "params"')||n.includes('Cannot query field "params"'))throw Error(`El servicio "${e}" no expone metadata de resolvers por GraphQL.`);throw r instanceof Error?r:o}}async function $r(e,t){let r=e[1],o=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(Ea(r),o==="info"){let s=e[3];if(!s)throw Error("Uso: team-cli graphql <servicio> info <queryName|mutationName> [--format toon|json]");return await ja(r,s)}if(!a)throw Error("Uso: team-cli graphql <servicio> '<query>' [--variables '<json>'] [--format toon|json]");let n;if(t.variables)try{n=JSON.parse(t.variables)}catch{throw Error("Las variables deben ser un JSON válido.")}return await u({service:r,query:a,variables:n})}function xr(){return Object.keys(ie)}function Aa(){return xr().map((e)=>{let t=ie[e].prod;return`- \`${e}\`: \`${t}/graphql\``}).join(`
988
- `)}function Sr(){let t=xr().join(", "),r=Aa();return`team-cli graphql
1035
+ `;function ka(e){if(!e)throw Error("Uso: team-cli graphql <servicio> '<query>' [--variables '<json>'] [--format toon|json]");if(!vt.includes(e))throw Error(`Servicio "${e}" no válido. Servicios disponibles: ${vt.join(", ")}`)}async function Ya(e,r){let t;try{let o=await u({service:e,query:At,variables:{name:r,mutation:!1}});return{service:e,operationName:r,operationType:"query",info:o.params}}catch(o){t=o}try{let o=await u({service:e,query:At,variables:{name:r,mutation:!0}});return{service:e,operationName:r,operationType:"mutation",info:o.params}}catch(o){let a=t instanceof Error?t.message:"",i=o instanceof Error?o.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 t instanceof Error?t:o}}async function Rt(e,r){let t=e[1],o=e[2],a=e[2];if(!g())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(ka(t),o==="info"){let s=e[3];if(!s)throw Error("Uso: team-cli graphql <servicio> info <queryName|mutationName> [--format toon|json]");return await Ya(t,s)}if(!a)throw Error("Uso: team-cli graphql <servicio> '<query>' [--variables '<json>'] [--format toon|json]");let i;if(r.variables)try{i=JSON.parse(r.variables)}catch{throw Error("Las variables deben ser un JSON válido.")}return await u({service:t,query:a,variables:i})}function Nt(){return Object.keys(ce)}function Va(){return Nt().map((e)=>{let r=ce[e].prod;return`- \`${e}\`: \`${r}/graphql\``}).join(`
1036
+ `)}function Tt(){let r=Nt().join(", "),t=Va();return`team-cli graphql
989
1037
 
990
1038
  Ejecutar queries y mutations GraphQL.
991
1039
 
@@ -1003,7 +1051,7 @@ Formato:
1003
1051
 
1004
1052
 
1005
1053
 
1006
- Servicios disponibles: ${t}.
1054
+ Servicios disponibles: ${r}.
1007
1055
 
1008
1056
  Ejemplos:
1009
1057
  \`\`\`bash
@@ -1036,7 +1084,7 @@ npx @getjusto/team-cli graphql auth info requestLoginCode --format json
1036
1084
 
1037
1085
  Usa esto para mapear una URL GraphQL al valor correcto de \`team-cli graphql <service>\`.
1038
1086
 
1039
- ${r}`}import{resolve as Pa}from"node:path";import{readdirSync as Na,readFileSync as va,statSync as Ra}from"node:fs";import{gzipSync as Ta}from"node:zlib";import{join as Oa,relative as Ua,resolve as Qa}from"node:path";var Ie=512,Ja=2;function Wa(e){let t=e.replaceAll("\\","/");if(t.startsWith("/")||t.includes("../"))throw Error(`Ruta inválida en el space: ${e}`);return t}function _a(e){let t=Wa(e);if(Buffer.from(t).length<=100)return{name:t,prefix:""};let o=t.lastIndexOf("/");if(o<=0)throw Error(`La ruta es demasiado larga para el paquete del space: ${e}`);let a=t.slice(0,o),n=t.slice(o+1);if(Buffer.from(a).length>155||Buffer.from(n).length>100)throw Error(`La ruta es demasiado larga para el paquete del space: ${e}`);return{name:n,prefix:a}}function J(e,t,r,o){let a=Buffer.from(o);a.copy(e,t,0,Math.min(a.length,r))}function ee(e,t,r,o){let a=Math.max(0,Math.trunc(o)).toString(8).padStart(r-1,"0");J(e,t,r,`${a}\x00`)}function Ba(e){let t=Buffer.alloc(Ie,0),{name:r,prefix:o}=_a(e.path);J(t,0,100,r),ee(t,100,8,e.mode),ee(t,108,8,0),ee(t,116,8,0),ee(t,124,12,e.content.length),ee(t,136,12,e.mtime),t.fill(32,148,156),J(t,156,1,"0"),J(t,257,6,"ustar"),J(t,263,2,"00"),J(t,345,155,o);let a=0;for(let i of t)a+=i;let n=`${a.toString(8).padStart(6,"0")}\x00 `;return J(t,148,8,n),t}function Ma(e){let t=e%Ie;return t===0?0:Ie-t}function Er(e,t=e){return Na(t,{withFileTypes:!0}).sort((o,a)=>o.name.localeCompare(a.name)).flatMap((o)=>{let a=Oa(t,o.name);if(o.isDirectory())return Er(e,a);if(!o.isFile())return[];let n=Ua(e,a),i=Ra(a);return[{path:n,content:va(a),mode:i.mode&511,mtime:Math.floor(i.mtimeMs/1000)}]})}function jr(e){let t=Qa(e),r=Er(t);if(!r.length)throw Error("El build del space no contiene archivos para publicar");let o=[];for(let a of r){o.push(Ba(a)),o.push(a.content);let n=Ma(a.content.length);if(n>0)o.push(Buffer.alloc(n,0))}return o.push(Buffer.alloc(Ie*Ja,0)),Ta(Buffer.concat(o))}function Me(){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 te(e,t,r){let o=e[t];if(!o)throw Error(`Falta --${t}. Ejemplo: ${r}`);return o}function Ar(e,t){let r=e[2];if(!r)throw Error(`Uso: ${t}`);return r}function Pe(){let e=se();if(e==="local")return"http://intra.localhost:5173";if(e==="develop")return"https://intra.bejusto.com";return"https://intra.getjusto.com"}async function Ga(e,t){let r=await Ne(),o=await fetch(`${h("data")}/spaces/publish/${e}`,{method:"POST",headers:{"Content-Type":"application/gzip",...r?{"X-ORION-JWT":r}:{}},body:t}),a=await o.json();if(!o.ok||a.error)throw Error(a.error||"No se pudo publicar el space.");return a}function Ge(){return`team-cli spaces
1087
+ ${t}`}import{existsSync as xi,mkdirSync as $i,readdirSync as Ei}from"node:fs";import{resolve as Ht}from"node:path";import{readdirSync as Bt,readFileSync as _t,statSync as Jt}from"node:fs";import{gzipSync as ni}from"node:zlib";import{join as Wt,relative as Pt,resolve as Ut}from"node:path";import{existsSync as Ka,readFileSync as La}from"node:fs";import{join as ei}from"node:path";var ri=[".git","node_modules","dist",".justo-space-preview",".DS_Store"];function ti(e){return e.replace(/[|\\{}()[\]^$+?.]/g,"\\$&")}function oi(e){let r="";for(let t=0;t<e.length;t++){let o=e[t],a=e[t+1];if(o==="*"){if(a==="*"){r+=".*",t+=1;continue}r+="[^/]*";continue}if(o==="?"){r+="[^/]";continue}r+=ti(o)}return r}function ai(e){let r=e.trim();if(!r||r.startsWith("#"))return null;let t=r.startsWith("!"),o=t?r.slice(1).trim():r;if(!o)return null;let a=o.endsWith("/"),i=o.replace(/^\/+/,"").replace(/\/+$/,"");if(!i)return null;let n=i.includes("/"),s=oi(i),c=n?`^${s}${a?"(?:/.*)?":""}$`:`(?:^|/)${s}${a?"(?:/.*)?":"(?:$|/)"}`;return{negate:t,directoryOnly:a,regex:new RegExp(c)}}function ii(e){let r=ei(e,".gitignore"),t=[...ri];if(Ka(r))t.push(...La(r,"utf-8").split(/\r?\n/));return t.map(ai).filter((o)=>Boolean(o))}function Ot(e){let r=ii(e);return(t,o)=>{let a=t.replaceAll("\\","/").replace(/^\/+/,""),i=!1;for(let n of r){if(!n.regex.test(a))continue;i=!n.negate}return i}}var xe=512,si=2,ci="repo",ui="dist";function li(e){let r=e.replaceAll("\\","/");if(r.startsWith("/")||r.includes("../"))throw Error(`Ruta inválida en el space: ${e}`);return r}function mi(e){let r=li(e);if(Buffer.from(r).length<=100)return{name:r,prefix:""};let o=r.lastIndexOf("/");if(o<=0)throw Error(`La ruta es demasiado larga para el paquete del space: ${e}`);let a=r.slice(0,o),i=r.slice(o+1);if(Buffer.from(a).length>155||Buffer.from(i).length>100)throw Error(`La ruta es demasiado larga para el paquete del space: ${e}`);return{name:i,prefix:a}}function J(e,r,t,o){let a=Buffer.from(o);a.copy(e,r,0,Math.min(a.length,t))}function te(e,r,t,o){let a=Math.max(0,Math.trunc(o)).toString(8).padStart(t-1,"0");J(e,r,t,`${a}\x00`)}function di(e){let r=Buffer.alloc(xe,0),{name:t,prefix:o}=mi(e.path);J(r,0,100,t),te(r,100,8,e.mode),te(r,108,8,0),te(r,116,8,0),te(r,124,12,e.content.length),te(r,136,12,e.mtime),r.fill(32,148,156),J(r,156,1,"0"),J(r,257,6,"ustar"),J(r,263,2,"00"),J(r,345,155,o);let a=0;for(let n of r)a+=n;let i=`${a.toString(8).padStart(6,"0")}\x00 `;return J(r,148,8,i),r}function pi(e){let r=e%xe;return r===0?0:xe-r}function Mt(e,r=e){return Bt(r,{withFileTypes:!0}).sort((o,a)=>o.name.localeCompare(a.name)).flatMap((o)=>{let a=Wt(r,o.name);if(o.isDirectory())return Mt(e,a);if(!o.isFile())return[];let i=Pt(e,a),n=Jt(a);return[{path:i,content:_t(a),mode:n.mode&511,mtime:Math.floor(n.mtimeMs/1000)}]})}function Qt(e,r){return e.map((t)=>({...t,path:`${r}/${t.path.replaceAll("\\","/")}`}))}function Gt(e,r=e){let t=Ot(e);return Bt(r,{withFileTypes:!0}).sort((a,i)=>a.name.localeCompare(i.name)).flatMap((a)=>{let i=Wt(r,a.name),n=Pt(e,i).replaceAll("\\","/");if(t(n,a.isDirectory()))return[];if(a.isDirectory())return Gt(e,i);if(!a.isFile())return[];let s=Jt(i);return[{path:n,content:_t(i),mode:s.mode&511,mtime:Math.floor(s.mtimeMs/1000)}]})}function Ft(e,r){let t=Ut(e),o=Ut(r),a=[...Qt(Gt(t),ci),...Qt(Mt(o),ui)];if(!a.length)throw Error("El build del space no contiene archivos para publicar");let i=[];for(let n of a){i.push(di(n)),i.push(n.content);let s=pi(n.content.length);if(s>0)i.push(Buffer.alloc(s,0))}return i.push(Buffer.alloc(xe*si,0)),ni(Buffer.concat(i))}import{mkdirSync as zt,writeFileSync as gi}from"node:fs";import{dirname as fi,join as wi,normalize as bi,sep as Dt}from"node:path";import{gunzipSync as yi}from"node:zlib";var oe=512;function $e(e,r,t){let o=e.subarray(r,r+t),a=o.indexOf(0);return(a>=0?o.subarray(0,a):o).toString("utf-8").trim()}function Ci(e,r,t){let o=$e(e,r,t).replaceAll("\x00","").trim();if(!o)return 0;return Number.parseInt(o,8)}function hi(e){let r=e%oe;return r===0?0:oe-r}function qi(e){let r=$e(e,0,100),t=$e(e,345,155);return t?`${t}/${r}`:r}function Ii(e){let r=bi(e);if(!e||e.startsWith("/")||r.startsWith("..")||r.includes(`${Dt}..${Dt}`)||r==="..")throw Error("El paquete del space contiene rutas inválidas")}function Xt(e,r,t){let o=yi(e),a=r.replaceAll("\\","/").replace(/^\/+|\/+$/g,""),i=`${a}/`,n=0,s=0;while(n+oe<=o.length){let c=o.subarray(n,n+oe),l=c.every((O)=>O===0);if(n+=oe,l)break;let m=qi(c),p=$e(c,156,1)||"0",d=Ci(c,124,12),b=o.subarray(n,n+d);if(n+=d+hi(d),!m.startsWith(i))continue;let f=m.slice(i.length);if(!f)continue;Ii(f);let T=wi(t,...f.split("/"));if(p==="5"){zt(T,{recursive:!0});continue}if(p!=="0")continue;zt(fi(T),{recursive:!0}),gi(T,b),s+=1}if(!s)throw Error(`El paquete del space no contiene la carpeta ${a}/`);return s}function Ee(){if(!g())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 ae(e,r,t){let o=e[r];if(!o)throw Error(`Falta --${r}. Ejemplo: ${t}`);return o}function Zt(e,r){let t=e[2];if(!t)throw Error(`Uso: ${r}`);return t}function ze(){let e=ue();if(e==="local")return"http://intra.localhost:5173";if(e==="develop")return"https://intra.bejusto.com";return"https://intra.getjusto.com"}async function Si(e,r){let t=await de(),o=await fetch(`${h("data")}/spaces/publish/${e}`,{method:"POST",headers:{"Content-Type":"application/gzip",...t?{"X-ORION-JWT":t}:{}},body:r}),a=await o.json();if(!o.ok||a.error)throw Error(a.error||"No se pudo publicar el space.");return a}async function ji(e){let r=await de(),t=await fetch(`${h("data")}/spaces/fork/${e}`,{method:"GET",headers:r?{"X-ORION-JWT":r}:{}});if(!t.ok){let o=await t.json().catch(()=>({}));throw Error(o.error||"No se pudo descargar el repo del space.")}return Buffer.from(await t.arrayBuffer())}function vi(e){let r=Ht(e);if(xi(r)&&Ei(r).length>0)throw Error(`La carpeta ya existe y no está vacía: ${r}`);return $i(r,{recursive:!0}),r}function De(){return`team-cli spaces
1040
1088
 
1041
1089
  Spaces son aplicaciones internas en React, pensadas para que las construyan agentes.
1042
1090
  El flujo oficial parte con \`spaces init\` y \`spaces publish\` solo acepta apps creadas así.
@@ -1045,7 +1093,9 @@ Cada space:
1045
1093
  - vive en data
1046
1094
  - se desarrolla como app React + Vite
1047
1095
  - viene con Tailwind y todos los componentes shadcn instalados
1048
- - publica el resultado de \`yarn build\` a S3 en \`spaces/[slug]/[version]/files/*\`
1096
+ - publica el repo del space (sin \`node_modules\` ni otros archivos ignorados por git) y el resultado de \`yarn build\`
1097
+ - guarda el repo publicado y permite recuperarlo con \`spaces fork <slug>\`
1098
+ - sube los archivos servidos a S3 en \`spaces/[slug]/[version]/files/*\`
1049
1099
  - se sirve en \`/spaces/[slug]\`
1050
1100
  - el build debe generar \`dist/index.html\`
1051
1101
  - recibe automáticamente \`<base href="/spaces/[slug]/">\` al servir HTML
@@ -1060,11 +1110,20 @@ Cada space:
1060
1110
 
1061
1111
  Flujo sugerido para agentes:
1062
1112
  1. \`team-cli spaces init --path ./mi-space-app\`
1063
- 2. \`team-cli spaces create --name '...' --description '...' --slug mi-space\`
1064
- 3. \`team-cli spaces preview --path ./mi-space-app\`
1065
- 4. desarrollar la app React dentro de esa carpeta
1066
- 5. \`team-cli spaces publish <spaceId> --path ./mi-space-app\`
1067
- 6. abrir \`${Pe()}/spaces/<slug>\`
1113
+ 2. hacer initial commit del repo nuevo
1114
+ 3. \`team-cli spaces create --name '...' --description '...' --slug dashboard-1234\`
1115
+ 4. \`team-cli spaces preview --path ./mi-space-app\`
1116
+ 5. desarrollar la app React dentro de esa carpeta
1117
+ 6. \`team-cli spaces publish <spaceId> --path ./mi-space-app\`
1118
+ 7. hacer commit del repo después de publicar
1119
+ 8. abrir \`${ze()}/spaces/<slug>\`
1120
+ 9. si necesitas retomarlo en otra carpeta: \`team-cli spaces fork <slug> --path ./mi-space-app\`
1121
+
1122
+ Slugs:
1123
+ - usa en \`--slug\` el nombre que quieres para el space, por ejemplo \`dashboard-1234\`
1124
+ - el sistema siempre agrega automáticamente el prefijo del usuario
1125
+ - el slug final queda como \`usuario:slug-base\`
1126
+ - ejemplo: si tu email es \`nicolaslopezj@...\`, el slug final queda \`nicolaslopezj:dashboard-1234\`
1068
1127
 
1069
1128
  Qué crea \`spaces init\`:
1070
1129
  - Vite + React + TypeScript
@@ -1076,6 +1135,12 @@ Qué crea \`spaces init\`:
1076
1135
  - helper \`justoStream(...)\` en \`src/lib/justo.ts\`
1077
1136
  - ejemplo inicial en \`src/App.tsx\`
1078
1137
  - configuración para que Vite construya con rutas relativas y funcione dentro del space
1138
+ - un repo git nuevo e independiente en la carpeta del space
1139
+
1140
+ Compartir dashboards:
1141
+ - si el usuario pide compartir un dashboard con otra persona, normalmente hay que darle acceso a las queries que usa ese dashboard
1142
+ - para eso usa \`team-cli data queries add-viewers <queryId> --emails 'persona@justo.com'\`
1143
+ - comparte todas las queries usadas por el dashboard, no solo el space
1079
1144
 
1080
1145
  Mapas:
1081
1146
  - el starter reutiliza el mismo token de MapTiler que ya usa vite-fronts
@@ -1095,6 +1160,11 @@ Qué hace \`spaces preview\`:
1095
1160
  - si envías \`--open\`, intenta abrir la preview en el navegador por defecto del sistema
1096
1161
  - \`--open\` es ideal para ir mostrándole al usuario el dashboard mientras el agente lo va construyendo
1097
1162
 
1163
+ Disciplina recomendada:
1164
+ - después de \`spaces init\`, haz un initial commit del repo del space
1165
+ - después de cada \`spaces publish\`, haz commit del repo del space
1166
+ - eso deja trazabilidad clara entre lo publicado y el código fuente
1167
+
1098
1168
  Ejemplo desde el propio HTML del space:
1099
1169
  \`\`\`js
1100
1170
  import {justoCli, justoStream} from '@/lib/justo'
@@ -1111,11 +1181,12 @@ await justoStream(
1111
1181
 
1112
1182
  Comandos:
1113
1183
  - \`spaces init --path ./mi-space-app\`
1114
- - \`spaces create --name '...' --description '...' --slug my-space\`
1184
+ - \`spaces create --name '...' --description '...' --slug dashboard-1234\`
1115
1185
  - \`spaces preview --path ./mi-space-app [--open]\`
1116
1186
  - \`spaces publish <spaceId> --path ./mi-space-app\`
1187
+ - \`spaces fork <slug> --path ./mi-space-app\`
1117
1188
  - \`spaces archive <spaceId>\`
1118
- `}async function Nr(e){let t=te(e,"path","team-cli spaces init --path ./mi-space-app");return Xt(t)}async function vr(e){return await nr(e)}async function Rr(e){Me();let t=te(e,"name","team-cli spaces create --name 'Mi space' --description '...' --slug mi-space"),r=te(e,"description","team-cli spaces create --name 'Mi space' --description 'Sitio interno' --slug mi-space"),o=te(e,"slug","team-cli spaces create --name 'Mi space' --description '...' --slug mi-space"),a=await u({service:"data",query:`mutation ($name: String, $description: String, $slug: String) {
1189
+ `}async function kt(e){let r=ae(e,"path","team-cli spaces init --path ./mi-space-app");return Hr(r)}async function Yt(e){return await ct(e)}async function Vt(e){Ee();let r=ae(e,"name","team-cli spaces create --name 'Mi space' --description '...' --slug dashboard-1234"),t=ae(e,"description","team-cli spaces create --name 'Mi space' --description 'Sitio interno' --slug dashboard-1234"),o=ae(e,"slug","team-cli spaces create --name 'Mi space' --description '...' --slug dashboard-1234"),a=await u({service:"data",query:`mutation ($name: String, $description: String, $slug: String) {
1119
1190
  createSpace(name: $name, description: $description, slug: $slug) {
1120
1191
  _id
1121
1192
  name
@@ -1126,7 +1197,7 @@ Comandos:
1126
1197
  createdByEmail
1127
1198
  createdById
1128
1199
  }
1129
- }`,variables:{name:t,description:r,slug:o}});return{...a.createSpace,intraUrl:`${Pe()}/spaces/${a.createSpace.slug}`,serveUrl:`${h("data")}/spaces/${a.createSpace.slug}`}}async function Tr(e,t){Me();let r=Ar(e,"team-cli spaces publish <spaceId> --path ./mi-space-app"),o=te(t,"path","team-cli spaces publish <spaceId> --path ./mi-space-app"),a=Ft(o),n=jr(a),i=await Ga(r,n);return{...i,intraUrl:i.slug?`${Pe()}/spaces/${i.slug}`:void 0,serveUrl:i.slug?`${h("data")}/spaces/${i.slug}`:void 0,builtFrom:Pa(o)}}async function Or(e){Me();let t=Ar(e,"team-cli spaces archive <spaceId>");return(await u({service:"data",query:`mutation ($spaceId: String) {
1200
+ }`,variables:{name:r,description:t,slug:o}});return{...a.createSpace,intraUrl:`${ze()}/spaces/${a.createSpace.slug}`,serveUrl:`${h("data")}/spaces/${a.createSpace.slug}`}}async function Kt(e,r){Ee();let t=Zt(e,"team-cli spaces publish <spaceId> --path ./mi-space-app"),o=ae(r,"path","team-cli spaces publish <spaceId> --path ./mi-space-app"),a=Xr(o),i=Ft(o,a),n=await Si(t,i);return{...n,intraUrl:n.slug?`${ze()}/spaces/${n.slug}`:void 0,serveUrl:n.slug?`${h("data")}/spaces/${n.slug}`:void 0,builtFrom:Ht(o)}}async function Lt(e,r){Ee();let t=e[2];if(!t)throw Error("Uso: team-cli spaces fork <slug> --path ./mi-space-app");let o=vi(r.path||`./${t}`),a=await ji(t),i=Xt(a,"repo",o);return{ok:!0,slug:t,path:o,extractedFiles:i,nextSteps:[`cd ${o}`,"yarn install","team-cli spaces preview --path . --open"]}}async function eo(e){Ee();let r=Zt(e,"team-cli spaces archive <spaceId>");return(await u({service:"data",query:`mutation ($spaceId: String) {
1130
1201
  archiveSpace(spaceId: $spaceId) {
1131
1202
  _id
1132
1203
  name
@@ -1138,7 +1209,7 @@ Comandos:
1138
1209
  createdById
1139
1210
  archivedAt
1140
1211
  }
1141
- }`,variables:{spaceId:t}})).archiveSpace}function Ur(e){return`team-cli
1212
+ }`,variables:{spaceId:r}})).archiveSpace}function ro(e){return`team-cli
1142
1213
 
1143
1214
  Herramienta CLI para el equipo Justo.
1144
1215
 
@@ -1183,10 +1254,11 @@ npx @getjusto/team-cli admin search <text> [--limit <n>] [--page <n>] [--only-ac
1183
1254
 
1184
1255
  ### Crea queries para usar en los dashboards
1185
1256
 
1186
- Crea queries personalizadas usando \`create\` y \`ai-edit\` para generar consultas a la base de datos y luego crear un dashboard que las use
1257
+ Crea queries personalizadas usando \`data explain\`, \`data queries create\` y \`data queries ai-edit\` para generar consultas a la base de datos y luego crear un dashboard que las use
1187
1258
  para mostrar datos. Usa \`preview\` para iterar rápido, \`run\` para consumir NDJSON en streaming y \`download\` para Excel.
1188
1259
  También puedes usar queries para poblar selectores y otras partes de la interfaz del space.
1189
1260
  Siempre que puedas, prefiere varias queries simples antes que un solo query con \`lookup\`.
1190
1261
  Eso suele ser más fácil de iterar, más claro para agentes y menos frágil para dashboards.
1262
+ Si el usuario pide compartir un dashboard con otra persona, normalmente lo que hay que hacer es compartir las queries que usa ese dashboard con \`data queries add-viewers\`.
1191
1263
 
1192
- `}function Qr(){let e=d(),t=e?`Sesión: ${e.email}`:"Sesión: no iniciada";return Ur(t)}async function Jr(e){let{positional:t,flags:r}=oe(e);if(r.env)Ve(r.env);let o=t[0],a=t[1];if(o==="__spaces-preview-bridge")return await ar(r);if(r.version)return{version:"0.0.8"};if(r.help&&!o)return Qr();if(o==="auth"){if(a==="--help"||r.help)return Te();if(a==="login")return await vt();if(a==="login-with-token")return await Rt(r);if(a==="request-code")return await Tt(r);if(a==="logout")return await Ot();if(a==="status")return await Ut();return Te()}if(o==="admin"){let n=t[1],i=t[2],s=t[3],c=t[4];if(!n||n==="--help")return me();if(n==="search"&&r.help)return Et();if(n==="search")return await St(t,r);if(!i||i==="--help")return me();if(i==="show")return await ct(n);if(i==="stores"&&s==="list")return await jt(n);if(i==="coupons"&&(!s||s==="--help"))return D();if(i==="coupons"&&s==="create"&&r.help)return $t();if(i==="coupons"&&s==="update"&&r.help)return xt();if(i==="coupons"&&s==="codes"&&t[4]==="create"&&r.help)return wt();if(i==="coupons"&&r.help)return D();if(i==="coupons"&&s==="list")return await yt(n,r);if(i==="coupons"&&s==="show"){if(!c)throw Error("Uso: team-cli admin <web> coupons show <couponId>");return await Ct(n,c)}if(i==="coupons"&&s==="create")return await qt(n,r);if(i==="coupons"&&s==="update"){if(!c)throw Error("Uso: team-cli admin <web> coupons update <couponId> --input '<json>'");return await It(n,c,r)}if(i==="coupons"&&s==="delete"){if(!c)throw Error("Uso: team-cli admin <web> coupons delete <couponId>");return await ht(n,c)}if(i==="coupons"&&s==="codes"){let m=t[4],l=t[5];if(!m||m==="--help")return D();if(m==="list"){if(!l)throw Error("Uso: team-cli admin <web> coupons codes list <couponId>");return await dt(n,l,r)}if(m==="create"){if(!l)throw Error("Uso: team-cli admin <web> coupons codes create <couponId> --input '<json>'");return await pt(n,l,r)}if(m==="create-random"){if(!l)throw Error("Uso: team-cli admin <web> coupons codes create-random <couponId> --quantity <n>");return await gt(n,l,r)}if(m==="delete"){if(!l)throw Error(`Uso: team-cli admin <web> coupons codes delete <couponId> --ids '["id1"]'`);return await ft(n,l,r)}return D()}return me()}if(o==="graphql"){if(a==="--help"||r.help)return Sr();return await $r(t,r)}if(o==="data"){let n=t[1],i=t[2];if(r.help||a==="--help")return Be();if(n==="queries"&&i==="create")return await pr();if(n==="queries"&&i==="edit")return await gr(t);if(n==="queries"&&i==="ai-edit")return await fr(t,r);if(n==="queries"&&i==="view")return await wr(t);if(n==="queries"&&i==="view-pipeline")return await br(t);if(n==="queries"&&i==="preview")return await yr(t,r);if(n==="queries"&&i==="run")return await Cr(t,r);if(n==="queries"&&i==="download")return await qr(t,r);return Be()}if(o==="spaces"){let n=t[1];if(!n||n==="--help"||r.help)return Ge();if(n==="init")return await Nr(r);if(n==="create")return await Rr(r);if(n==="preview")return await vr(r);if(n==="publish")return await Tr(t,r);if(n==="archive")return await Or(t);return Ge()}return Qr()}var{flags:Wr}=oe(process.argv.slice(2));async function Fa(){try{let e=await Jr(process.argv.slice(2));if(e&&typeof e==="object"&&"__streamHandled"in e&&e.__streamHandled)return;if(typeof e==="string"){ke(e);return}ze(e,Wr)}catch(e){Ke(e,Wr),process.exit(1)}}Fa();
1264
+ `}function to(){let e=g(),r=e?`Sesión: ${e.email}`:"Sesión: no iniciada";return ro(r)}async function oo(e){let{positional:r,flags:t}=ie(e);if(t.env)rr(t.env);let o=r[0],a=r[1];if(o==="__spaces-preview-bridge")return await st(t);if(t.version)return{version:"0.0.10"};if(t.help&&!o)return to();if(o==="auth"){if(a==="--help"||t.help)return Qe();if(a==="login")return await Or();if(a==="login-with-token")return await Ur(t);if(a==="request-code")return await Qr(t);if(a==="logout")return await Br();if(a==="status")return await _r();return Qe()}if(o==="admin"){let i=r[1],n=r[2],s=r[3],c=r[4];if(!i||i==="--help")return pe();if(i==="search"&&t.help)return Ar();if(i==="search")return await vr(r,t);if(!n||n==="--help")return pe();if(n==="show")return await mr(i);if(n==="stores"&&s==="list")return await Rr(i);if(n==="coupons"&&(!s||s==="--help"))return V();if(n==="coupons"&&s==="create"&&t.help)return Sr();if(n==="coupons"&&s==="update"&&t.help)return jr();if(n==="coupons"&&s==="codes"&&r[4]==="create"&&t.help)return Cr();if(n==="coupons"&&t.help)return V();if(n==="coupons"&&s==="list")return await qr(i,t);if(n==="coupons"&&s==="show"){if(!c)throw Error("Uso: team-cli admin <web> coupons show <couponId>");return await Ir(i,c)}if(n==="coupons"&&s==="create")return await xr(i,t);if(n==="coupons"&&s==="update"){if(!c)throw Error("Uso: team-cli admin <web> coupons update <couponId> --input '<json>'");return await $r(i,c,t)}if(n==="coupons"&&s==="delete"){if(!c)throw Error("Uso: team-cli admin <web> coupons delete <couponId>");return await Er(i,c)}if(n==="coupons"&&s==="codes"){let l=r[4],m=r[5];if(!l||l==="--help")return V();if(l==="list"){if(!m)throw Error("Uso: team-cli admin <web> coupons codes list <couponId>");return await fr(i,m,t)}if(l==="create"){if(!m)throw Error("Uso: team-cli admin <web> coupons codes create <couponId> --input '<json>'");return await wr(i,m,t)}if(l==="create-random"){if(!m)throw Error("Uso: team-cli admin <web> coupons codes create-random <couponId> --quantity <n>");return await br(i,m,t)}if(l==="delete"){if(!m)throw Error(`Uso: team-cli admin <web> coupons codes delete <couponId> --ids '["id1"]'`);return await yr(i,m,t)}return V()}return pe()}if(o==="graphql"){if(a==="--help"||t.help)return Tt();return await Rt(r,t)}if(o==="data"){let i=r[1],n=r[2];if(t.help||a==="--help")return Fe();if(i==="explain")return await Ct(t);if(i==="queries"&&n==="create")return await yt();if(i==="queries"&&n==="edit")return await ht(r);if(i==="queries"&&n==="ai-edit")return await qt(r,t);if(i==="queries"&&n==="view")return await It(r);if(i==="queries"&&n==="view-pipeline")return await xt(r);if(i==="queries"&&n==="preview")return await $t(r,t);if(i==="queries"&&n==="run")return await Et(r,t);if(i==="queries"&&n==="add-viewers")return await St(r,t);if(i==="queries"&&n==="download")return await jt(r,t);return Fe()}if(o==="spaces"){let i=r[1];if(!i||i==="--help"||t.help)return De();if(i==="init")return await kt(t);if(i==="create")return await Vt(t);if(i==="preview")return await Yt(t);if(i==="publish")return await Kt(r,t);if(i==="fork")return await Lt(r,t);if(i==="archive")return await eo(r);return De()}return to()}var{flags:ao}=ie(process.argv.slice(2));async function Ai(){try{let e=await oo(process.argv.slice(2));if(e&&typeof e==="object"&&"__streamHandled"in e&&e.__streamHandled)return;if(typeof e==="string"){Le(e);return}Ke(e,ao)}catch(e){er(e,ao),process.exit(1)}}Ai();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getjusto/team-cli",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "CLI tool for Justo team members",
5
5
  "type": "module",
6
6
  "bin": {