@getjusto/team-cli 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +155 -96
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
function
|
|
3
|
-
`)}function
|
|
4
|
-
`)}function
|
|
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 D(e,r){let t=e[r];if(!t)throw Error(`--${r} es requerido.`);return t}var io={comma:",",tab:"\t",pipe:"|"},k=io.comma;function He(e){return e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function no(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(so(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 X(e){return Object.keys(e).length===0}function so(e){if(e===null||typeof e!=="object")return!1;let r=Object.getPrototypeOf(e);return r===null||r===Object.prototype}function H(e){return e.length===0||e.every((r)=>B(r))}function co(e){return e.length===0||e.every((r)=>Q(r))}function Ze(e){return e.length===0||e.every((r)=>q(r))}function uo(e){return/^[A-Z_][\w.]*$/i.test(e)}function lo(e){return/^[A-Z_]\w*$/i.test(e)}function mo(e,r=k){if(!e)return!1;if(e!==e.trim())return!1;if(no(e)||po(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 po(e){return/^-?\d+(?:\.\d+)?(?:e[+-]?\d+)?$/i.test(e)||/^0\d+$/.test(e)}var Ai=Symbol("quotedKey");function go(e,r,t,o,a,i,n){if(o.keyFolding!=="safe")return;if(!q(r))return;let{segments:s,tail:c,leafValue:l}=fo(e,r,n??o.flattenDepth);if(s.length<2)return;if(!s.every((d)=>lo(d)))return;let m=wo(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 fo(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)||X(a))return{segments:o,tail:void 0,leafValue:a};return{segments:o,tail:a,leafValue:a}}function wo(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 bo(e,r)}function bo(e,r=k){if(mo(e,r))return e;return`"${He(e)}"`}function Z(e){if(uo(e))return e;return`"${He(e)}"`}function ke(e,r=k){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+=Z(t);if(i+=`[${e}${a!==k?a:""}]`,o){let n=o.map((s)=>Z(s));i+=`{${n.join(a)}}`}return i+=":",i}function*yo(e,r,t){if(B(e)){let o=P(e,r.delimiter);if(o!=="")yield o;return}if(Q(e))yield*Ee(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*Co(c,l,r,t,n,o,a,s)}function*Co(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=go(e,r,a,o,i,n,l);if(p){let{foldedKey:d,remainder:b,leafValue:f,segmentCount:T}=p,O=Z(d);if(b===void 0){if(B(f)){yield y(t,`${O}: ${P(f,o.delimiter)}`,o.indent);return}else if(Q(f)){yield*Ee(d,f,t,o);return}else if(q(f)&&X(f)){yield y(t,`${O}:`,o.indent);return}}if(q(b)){yield y(t,`${O}:`,o.indent);let U=l-T,z=n?`${n}.${d}`:d;yield*W(b,t+1,o,i,z,U);return}}}let m=Z(e);if(B(r))yield y(t,`${m}: ${P(r,o.delimiter)}`,o.indent);else if(Q(r))yield*Ee(e,r,t,o);else if(q(r)){if(yield y(t,`${m}:`,o.indent),!X(r))yield*W(r,t+1,o,i,c,l)}}function*Ee(e,r,t,o){if(r.length===0){yield y(t,v(0,{key:e,delimiter:o.delimiter}),o.indent);return}if(H(r)){yield y(t,se(r,o.delimiter,e),o.indent);return}if(co(r)){if(r.every((a)=>H(a))){yield*ho(e,r,t,o);return}}if(Ze(r)){let a=Ye(r);if(a)yield*qo(e,r,a,t,o);else yield*Xe(e,r,t,o);return}yield*Xe(e,r,t,o)}function*ho(e,r,t,o){yield y(t,v(r.length,{key:e,delimiter:o.delimiter}),o.indent);for(let a of r)if(H(a)){let i=se(a,o.delimiter);yield x(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*qo(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(Io(e,t))return t}function Io(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(X(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 x(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=Z(a);if(B(i))yield x(r,`${s}: ${P(i,t.delimiter)}`,t.indent);else if(Q(i))if(i.length===0)yield x(r,`${s}${v(0,{delimiter:t.delimiter})}`,t.indent);else if(H(i))yield x(r,`${s}${se(i,t.delimiter)}`,t.indent);else{yield x(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 x(r,`${s}:`,t.indent),!X(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 x(r,P(e,t.delimiter),t.indent);else if(Q(e))if(H(e))yield x(r,se(e,t.delimiter),t.indent);else{yield x(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 x(e,r,t){return y(e,"- "+r,t)}function xo(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 Eo(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 Eo(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(jo(e,r)).join(`
|
|
3
|
+
`)}function jo(e,r){let t=j(e),o=vo(r);return yo(o.replacer?xo(t,o.replacer):t,o,0)}function vo(e){return{indent:e?.indent??2,delimiter:e?.delimiter??k,keyFolding:e?.keyFolding??"off",flattenDepth:e?.flattenDepth??Number.POSITIVE_INFINITY,replacer:e?.replacer}}function Ao(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(Ao(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 To,readFileSync as tr,writeFileSync as Oo,unlinkSync as Uo}from"node:fs";import{join as or}from"node:path";import{homedir as Qo}from"node:os";import{AsyncLocalStorage as Ro}from"node:async_hooks";var No=new Ro;function I(){return No.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(Qo(),".justo-team");function ar(e){let r=e==="prod"?"credentials.json":`credentials.${e}.json`;return or(Re,r)}function Ne(){return ar(ue())}function Bo(){if(!le(Re))To(Re,{recursive:!0})}function me(e){let r=I();if(r&&r.canPersistCredentials===!1)throw Error("Este entorno no permite guardar credenciales.");Bo(),Oo(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))Uo(r)}import{existsSync as nr,readFileSync as _o,writeFileSync as Jo,mkdirSync as Wo}from"node:fs";import{join as sr}from"node:path";import{homedir as Po}from"node:os";function Mo(){let e=process.env.JUSTO_TEAM_CLI_DEVICE_ID;if(e)return e;let r=I()?.deviceId;if(r)return r;let t=sr(Po(),".justo-team"),o=sr(t,"device-id");if(nr(o))return _o(o,"utf-8").trim();let a=crypto.randomUUID();if(!nr(t))Wo(t,{recursive:!0});return Jo(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 Go(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])=>Go(t,r)).join(", ")}function Fo(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 zo(e){try{return JSON.parse(Buffer.from(e.split(".")[1],"base64").toString()).exp*1000<Date.now()}catch{return!0}}async function Do(){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(!zo(e.token))return e.token;return await Do()??void 0}async function Oe(e="application/json"){let r=await de(),t={"Content-Type":e,"X-ORION-DEVICEID":Mo(),"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(15000)})}catch{throw Error("La solicitud tardó demasiado. Intenta de nuevo.")}let a=await o.json();if(a.errors?.length)throw Error(Fo(a.errors[0]));if(!a.data)throw Error("No data returned from server");return a.data}function Xo(e){return e.replace(/^https?:\/\//,"").replace(/^www\./,"").replace(/\/.*$/,"")}function Ho(e){return e.includes(".")||e.startsWith("http://")||e.startsWith("https://")}async function M(e){if(Ho(e)){let r=Xo(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 re(e){let t=[],o={},r={};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(!
|
|
16
|
+
}`,variables:{websiteId:e}});if(!r.website)throw Error(`No se encontro el website "${e}"`);return r.website}function Zo(){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(Zo(),!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
|
|
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
|
-
`,
|
|
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
|
-
${
|
|
89
|
+
${dr}
|
|
90
90
|
}
|
|
91
91
|
scheduleAtUse {
|
|
92
|
-
${
|
|
92
|
+
${dr}
|
|
93
93
|
}
|
|
94
94
|
codesCode
|
|
95
|
-
`,
|
|
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
|
|
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 $(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(!
|
|
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 ko(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 Yo(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 $(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
|
-
${
|
|
112
|
+
${pr}
|
|
113
113
|
}
|
|
114
114
|
totalCount
|
|
115
115
|
totalPages
|
|
116
116
|
hasNextPage
|
|
117
117
|
hasPreviousPage
|
|
118
118
|
}
|
|
119
|
-
}`,variables:{couponId:
|
|
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 $(e);await A(r,o.websiteId);let a=ko(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:
|
|
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 $(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:
|
|
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 $(e);await A(r,o.websiteId);let a=Yo(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:
|
|
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
|
|
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 Vo(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
|
-
${
|
|
150
|
+
${ge}
|
|
151
151
|
}
|
|
152
|
-
}`}async function
|
|
152
|
+
}`}async function qr(e,r){let t=await $(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:
|
|
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 $(e);await A(r,t.websiteId);let o=await u({service:"main",query:`query ($couponId: ID) {
|
|
173
173
|
coupon(couponId: $couponId) {
|
|
174
|
-
${
|
|
174
|
+
${ge}
|
|
175
175
|
}
|
|
176
|
-
}`,variables:{couponId:
|
|
176
|
+
}`,variables:{couponId:r}});return{context:t,coupon:o.coupon}}async function $r(e,r){let t=await $(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=Vo(a),n=await u({service:"main",query:i,variables:a});return{context:t,coupon:n.createCoupon}}async function xr(e,r,t){let o=await $(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
|
-
${
|
|
178
|
+
${ge}
|
|
179
179
|
}
|
|
180
|
-
}`,variables:{couponId:
|
|
180
|
+
}`,variables:{couponId:r,coupon:a}});return{context:o,coupon:i.updateCoupon}}async function Sr(e,r){let t=await $(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:[
|
|
182
|
+
}`,variables:{couponsIds:[r]}});return{context:t,couponId:r,deleted:o.deleteCoupons}}function Y(){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
|
|
230
|
+
El schema actual no expone update para coupon codes.`}function Er(){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
|
|
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
|
|
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:
|
|
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
|
|
357
|
+
team-cli admin search pizza --only-active true`}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>")}function Lo(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(Ko(),!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:
|
|
369
|
+
}`,variables:{websiteId:r.websiteId}})).stores.items??[]).map((a)=>({_id:a._id,name:a.name,address:Lo(a)})).sort((a,i)=>a.name.localeCompare(i.name,"es",{sensitivity:"base"}));return{context:r,stores:o,totalCount:o.length}}import{createInterface as ea}from"node:readline";function V(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=ea({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
|
|
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:
|
|
377
|
-
`);let
|
|
378
|
-
`);let
|
|
379
|
-
`);let
|
|
376
|
+
}`,variables:{email:e,token:r,code:t.toUpperCase()}});me({email:e,token:o.loginWithCode.token,refreshToken:o.loginWithCode.refreshToken}),await ra()}async function ra(){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 V("Email: ");C(`Enviando codigo de verificacion...
|
|
377
|
+
`);let r=await Nr(e);C(`Codigo enviado a tu email.
|
|
378
|
+
`);let t=await V("Codigo: ");return await Tr(e,r,t),{ok:!0,authenticated:!0,email:e}}async function Ur(e){let r=D(e,"email"),t=D(e,"token"),o=D(e,"code");return await Tr(r,t,o),{ok:!0,authenticated:!0,email:r}}async function Qr(e){let r=D(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
|
|
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 pa,mkdirSync as ga,openSync as fa,readFileSync as wa,rmSync as ba,writeFileSync as ya}from"node:fs";import{dirname as Ca,join as qe,resolve as tt}from"node:path";import{request as ha}from"node:http";import{request as qa}from"node:https";import{execFileSync as ta}from"node:child_process";import{existsSync as be,mkdirSync as oa,readFileSync as ye,readdirSync as aa,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 {${
|
|
424
|
-
'${
|
|
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>
|
|
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 <spaceId> --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
|
|
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
|
|
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. \`
|
|
789
|
-
2. \`team-cli spaces
|
|
790
|
-
3.
|
|
791
|
-
4.
|
|
792
|
-
5.
|
|
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
|
-
|
|
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
|
|
811
|
-
base: './',`);
|
|
812
|
-
`)}function
|
|
813
|
-
${
|
|
814
|
-
`),
|
|
815
|
-
`),await new Promise((n
|
|
816
|
-
`);let
|
|
817
|
-
`);let a=`${
|
|
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){ta(e,r,{cwd:t,stdio:"inherit",env:{...process.env,CI:"1"}})}function ia(e){if(!e)throw Error("Falta --path. Ejemplo: team-cli spaces init --path ./mi-space-app");let r=zr(e);if(be(r)){if(aa(r).length>0)throw Error(`La carpeta ya existe y no está vacía: ${r}`);Be(r,{recursive:!0,force:!0})}return oa(Fr(r),{recursive:!0}),r}function na(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 sa(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 ca(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 ua(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 la(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 ma(e){L("git",["init"],e)}function da(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=ia(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),da(r),ca(r),L(_("yarn"),["install"],r),na(r),sa(r),ua(r),la(r),ma(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 Ia=".justo-space-preview",$a="preview.json",xa=30000;function Ie(e){return qe(e,Ia)}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){ga(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 Ea(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 ja(e){let r=ot(e);if(!pa(r))return;try{let t=JSON.parse(wa(r,"utf-8"));Ce(t.appPid),Ce(t.bridgePid)}catch{}ba(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 va(e){return new Promise((r,t)=>{let i=(new URL(e).protocol==="https:"?qa:ha)(e,{method:"GET"},(n)=>{r(n.statusCode||0),n.resume()});i.on("error",t),i.end()})}async function Lr(e,r=xa){let t=Date.now();while(Date.now()-t<r){try{if(await va(e)>0)return}catch{await Kr(500);continue}await Kr(500)}throw Error(`Timeout esperando que el preview responda en ${e}`)}function Aa(e){return at(Ca(e)),fa(e,"a")}function et(e,r,t,o,a){let i=Aa(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 Ra(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 Na(e,r){return{VITE_JUSTO_CLI_ENDPOINT:e,VITE_JUSTO_STREAM_ENDPOINT:r,VITE_JUSTO_CLI_MODE:"preview",[K]:fe}}function Ta(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 Ra(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 Ta(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 z=Buffer.concat(T).toString("utf-8")||Buffer.concat(O).toString("utf-8");if(U&&U!==0){let ao=Je(z);b(Error(ao.error||z||"justoCli failed"));return}d(Je(z))})});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),ja(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),Na(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"};ya(ot(t),`${JSON.stringify(d,null,2)}
|
|
832
|
+
`);let b=await Ea(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 Fa}from"node:fs";import{mkdtempSync as Oa,readFileSync as Ua,rmSync as Qa,writeFileSync as Ba}from"node:fs";import{tmpdir as _a}from"node:os";import{join as ut}from"node:path";import{spawnSync as Ja}from"node:child_process";function Wa(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 Pa(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 Ma(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:Pa(r.variables)}}function mt(e){let r=process.env.VISUAL||process.env.EDITOR||"vi",t=Oa(ut(_a(),"team-cli-query-")),o=ut(t,"aggregation-query.json");Ba(o,`${JSON.stringify(e,null,2)}
|
|
833
|
+
`);let a=`${r} ${Wa(o)}`,i=Ja(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=Ua(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 Ma(s)}finally{Qa(t,{recursive:!0,force:!0})}}function E(){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 F(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 @@ ${o}`)}function Xr(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
|
|
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:
|
|
836
|
-
`);while(
|
|
837
|
-
`)}}let c=
|
|
859
|
+
}`,variables:{aggregationQueryId:e,params:r}});return We(t.testAggregationQuery)}function Ga(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(Ga(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 @@ ${o}`)}function Xr(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:
|
|
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 po(){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 @@ ${o}`)}function Xr(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
|
|
899
|
+
}`})).createAggregationQuery}function za(e){if(!Array.isArray(e))throw Error("El preview del query debe devolver un arreglo para usar AI edit.");return e}async function Da(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,13 @@ ${o}`)}function Xr(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(!
|
|
902
|
-
`);try{let c=await
|
|
903
|
-
`);let s=await
|
|
904
|
-
`);let
|
|
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 yt(){return E(),await bt()}async function Ct(e){E();let r=N(e,"team-cli data queries edit <queryId>"),t=await F(r),o=mt(ft(t));return await Me(r,o),{ok:!0,queryId:r,name:o.name,collection:o.collection}}async function ht(e,r){E();let t=N(e,"team-cli data queries ai-edit <queryId> --prompt '<texto>' [--params '<json>']"),o=await F(t),a=r.prompt||await V("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...
|
|
926
|
+
`);try{let c=await Pe(t,i);n=za(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...
|
|
927
|
+
`);let s=await Da({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 qt(e){E();let r=N(e,"team-cli data queries view <queryId>");return await F(r)}async function It(e){E();let r=N(e,"team-cli data queries view-pipeline <queryId>"),t=await F(r);return{queryId:r,pipeline:t.pipeline}}async function $t(e,r){E();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 xt(e,r){E();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){E();let t=N(e,"team-cli data queries add-viewers <queryId> --emails 'ana@justo.com,bob@justo.com'"),o=pt(r),a=await F(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 Xa(e){return new Promise((r)=>setTimeout(r,e))}async function Et(e,r){E();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...
|
|
928
|
+
`);let i=(await u({service:"data",query:`mutation ($aggregationQueryId: String, $params: JSON) {
|
|
905
929
|
downloadAggregationQueryData(aggregationQueryId: $aggregationQueryId, params: $params)
|
|
906
|
-
}`,variables:{aggregationQueryId:
|
|
907
|
-
`);let
|
|
930
|
+
}`,variables:{aggregationQueryId:t,params:o}})).downloadAggregationQueryData;C(`Reporte en proceso (${i})...
|
|
931
|
+
`);let n=null;while(!n){await Xa(1000);let l=await u({service:"data",query:`query ($id: String) {
|
|
908
932
|
getAsyncReport(id: $id) {
|
|
909
933
|
_id
|
|
910
934
|
status
|
|
@@ -912,15 +936,17 @@ ${o}`)}function Xr(e){let t=Bt(e);N(f(e,"README.md"),Wt(t)),N(f(e,"src","App.tsx
|
|
|
912
936
|
fileUrl
|
|
913
937
|
}
|
|
914
938
|
getAsyncReportRecordsCount(id: $id)
|
|
915
|
-
}`,variables:{id:
|
|
939
|
+
}`,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
940
|
Descargando archivo...
|
|
917
|
-
`);let s=await fetch(
|
|
941
|
+
`);let s=await fetch(n);if(!s.ok)throw Error(`Error descargando archivo: ${s.status}`);let c=Buffer.from(await s.arrayBuffer());return Fa(r.path,c),{ok:!0,queryId:t,asyncReportId:i,outputPath:r.path,fileUrl:n}}function Fe(){return`team-cli data
|
|
918
942
|
|
|
919
943
|
Comandos de datos y reportes.
|
|
920
944
|
|
|
921
945
|
Recomendado:
|
|
922
946
|
Si necesitas obtener data y no existe un query listo, usa create + ai-edit.
|
|
923
947
|
Flujo sugerido: create -> ai-edit -> preview -> run o download.
|
|
948
|
+
Siempre que puedas, prefiere varias queries simples antes que un solo pipeline con lookup.
|
|
949
|
+
Para dashboards suele ser mejor resolver joins en la UI o con queries separadas.
|
|
924
950
|
|
|
925
951
|
Uso:
|
|
926
952
|
team-cli data queries <subcomando> [opciones]
|
|
@@ -959,9 +985,15 @@ Subcomandos:
|
|
|
959
985
|
Descargar resultado completo como Excel.
|
|
960
986
|
Uso: team-cli data queries download <queryId> --path <filepath> [--params '<json>'] [--format toon|json]
|
|
961
987
|
|
|
988
|
+
add-viewers <queryId>
|
|
989
|
+
Agregar personas con acceso a un query usando sus emails de Justo.
|
|
990
|
+
Uso: team-cli data queries add-viewers <queryId> --emails 'ana@justo.com,bob@justo.com'
|
|
991
|
+
Esto actualiza allowedUsersIds sin cambiar el pipeline ni crear una versión nueva.
|
|
992
|
+
|
|
962
993
|
Opciones:
|
|
963
994
|
--params '<json>' Parametros del query. Default: {}
|
|
964
995
|
--limit <n> Requerido para run. Máximo 10000 por request.
|
|
996
|
+
--emails '<csv>' Requerido para add-viewers. Lista separada por comas.
|
|
965
997
|
--prompt '<texto>' Prompt para ai-edit. Si no viene, se pide interactivamente.
|
|
966
998
|
--format <toon|json>
|
|
967
999
|
--path <filepath> Requerido para download
|
|
@@ -973,7 +1005,8 @@ Ejemplos:
|
|
|
973
1005
|
team-cli data queries ai-edit abc123 --prompt 'Ajusta el pipeline' --params '{"websiteId":"w1"}'
|
|
974
1006
|
team-cli data queries preview abc123 --params '{"startDate": "2026-01-01"}'
|
|
975
1007
|
team-cli data queries run abc123 --limit 1000 --params '{"startDate": "2026-01-01"}'
|
|
976
|
-
team-cli data queries download abc123 --params '{"startDate": "2026-01-01"}' --path resultado.xlsx
|
|
1008
|
+
team-cli data queries download abc123 --params '{"startDate": "2026-01-01"}' --path resultado.xlsx
|
|
1009
|
+
team-cli data queries add-viewers abc123 --emails 'ana@justo.com,bob@justo.com'`}var jt=["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"],vt=`
|
|
977
1010
|
query ResolverInfo($name: ID!, $mutation: Boolean!) {
|
|
978
1011
|
params(name: $name, mutation: $mutation) {
|
|
979
1012
|
name
|
|
@@ -982,8 +1015,8 @@ Ejemplos:
|
|
|
982
1015
|
basicResultQuery
|
|
983
1016
|
}
|
|
984
1017
|
}
|
|
985
|
-
`;function
|
|
986
|
-
`)}function
|
|
1018
|
+
`;function Ha(e){if(!e)throw Error("Uso: team-cli graphql <servicio> '<query>' [--variables '<json>'] [--format toon|json]");if(!jt.includes(e))throw Error(`Servicio "${e}" no válido. Servicios disponibles: ${jt.join(", ")}`)}async function Za(e,r){let t;try{let o=await u({service:e,query:vt,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:vt,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 At(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(Ha(t),o==="info"){let s=e[3];if(!s)throw Error("Uso: team-cli graphql <servicio> info <queryName|mutationName> [--format toon|json]");return await Za(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 Rt(){return Object.keys(ce)}function ka(){return Rt().map((e)=>{let r=ce[e].prod;return`- \`${e}\`: \`${r}/graphql\``}).join(`
|
|
1019
|
+
`)}function Nt(){let r=Rt().join(", "),t=ka();return`team-cli graphql
|
|
987
1020
|
|
|
988
1021
|
Ejecutar queries y mutations GraphQL.
|
|
989
1022
|
|
|
@@ -1001,7 +1034,7 @@ Formato:
|
|
|
1001
1034
|
|
|
1002
1035
|
|
|
1003
1036
|
|
|
1004
|
-
Servicios disponibles: ${
|
|
1037
|
+
Servicios disponibles: ${r}.
|
|
1005
1038
|
|
|
1006
1039
|
Ejemplos:
|
|
1007
1040
|
\`\`\`bash
|
|
@@ -1034,7 +1067,7 @@ npx @getjusto/team-cli graphql auth info requestLoginCode --format json
|
|
|
1034
1067
|
|
|
1035
1068
|
Usa esto para mapear una URL GraphQL al valor correcto de \`team-cli graphql <service>\`.
|
|
1036
1069
|
|
|
1037
|
-
${
|
|
1070
|
+
${t}`}import{existsSync as qi,mkdirSync as Ii,readdirSync as $i}from"node:fs";import{resolve as Xt}from"node:path";import{readdirSync as Qt,readFileSync as Bt,statSync as _t}from"node:fs";import{gzipSync as ai}from"node:zlib";import{join as Jt,relative as Wt,resolve as Ot}from"node:path";import{existsSync as Ya,readFileSync as Va}from"node:fs";import{join as Ka}from"node:path";var La=[".git","node_modules","dist",".justo-space-preview",".DS_Store"];function ei(e){return e.replace(/[|\\{}()[\]^$+?.]/g,"\\$&")}function ri(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+=ei(o)}return r}function ti(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=ri(i),c=n?`^${s}${a?"(?:/.*)?":""}$`:`(?:^|/)${s}${a?"(?:/.*)?":"(?:$|/)"}`;return{negate:t,directoryOnly:a,regex:new RegExp(c)}}function oi(e){let r=Ka(e,".gitignore"),t=[...La];if(Ya(r))t.push(...Va(r,"utf-8").split(/\r?\n/));return t.map(ti).filter((o)=>Boolean(o))}function Tt(e){let r=oi(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 $e=512,ii=2,ni="repo",si="dist";function ci(e){let r=e.replaceAll("\\","/");if(r.startsWith("/")||r.includes("../"))throw Error(`Ruta inválida en el space: ${e}`);return r}function ui(e){let r=ci(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 li(e){let r=Buffer.alloc($e,0),{name:t,prefix:o}=ui(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 mi(e){let r=e%$e;return r===0?0:$e-r}function Pt(e,r=e){return Qt(r,{withFileTypes:!0}).sort((o,a)=>o.name.localeCompare(a.name)).flatMap((o)=>{let a=Jt(r,o.name);if(o.isDirectory())return Pt(e,a);if(!o.isFile())return[];let i=Wt(e,a),n=_t(a);return[{path:i,content:Bt(a),mode:n.mode&511,mtime:Math.floor(n.mtimeMs/1000)}]})}function Ut(e,r){return e.map((t)=>({...t,path:`${r}/${t.path.replaceAll("\\","/")}`}))}function Mt(e,r=e){let t=Tt(e);return Qt(r,{withFileTypes:!0}).sort((a,i)=>a.name.localeCompare(i.name)).flatMap((a)=>{let i=Jt(r,a.name),n=Wt(e,i).replaceAll("\\","/");if(t(n,a.isDirectory()))return[];if(a.isDirectory())return Mt(e,i);if(!a.isFile())return[];let s=_t(i);return[{path:n,content:Bt(i),mode:s.mode&511,mtime:Math.floor(s.mtimeMs/1000)}]})}function Gt(e,r){let t=Ot(e),o=Ot(r),a=[...Ut(Mt(t),ni),...Ut(Pt(o),si)];if(!a.length)throw Error("El build del space no contiene archivos para publicar");let i=[];for(let n of a){i.push(li(n)),i.push(n.content);let s=mi(n.content.length);if(s>0)i.push(Buffer.alloc(s,0))}return i.push(Buffer.alloc($e*ii,0)),ai(Buffer.concat(i))}import{mkdirSync as Ft,writeFileSync as di}from"node:fs";import{dirname as pi,join as gi,normalize as fi,sep as zt}from"node:path";import{gunzipSync as wi}from"node:zlib";var oe=512;function xe(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 bi(e,r,t){let o=xe(e,r,t).replaceAll("\x00","").trim();if(!o)return 0;return Number.parseInt(o,8)}function yi(e){let r=e%oe;return r===0?0:oe-r}function Ci(e){let r=xe(e,0,100),t=xe(e,345,155);return t?`${t}/${r}`:r}function hi(e){let r=fi(e);if(!e||e.startsWith("/")||r.startsWith("..")||r.includes(`${zt}..${zt}`)||r==="..")throw Error("El paquete del space contiene rutas inválidas")}function Dt(e,r,t){let o=wi(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=Ci(c),p=xe(c,156,1)||"0",d=bi(c,124,12),b=o.subarray(n,n+d);if(n+=d+yi(d),!m.startsWith(i))continue;let f=m.slice(i.length);if(!f)continue;hi(f);let T=gi(t,...f.split("/"));if(p==="5"){Ft(T,{recursive:!0});continue}if(p!=="0")continue;Ft(pi(T),{recursive:!0}),di(T,b),s+=1}if(!s)throw Error(`El paquete del space no contiene la carpeta ${a}/`);return s}function Se(){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 Ht(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 xi(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 Si(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 Ei(e){let r=Xt(e);if(qi(r)&&$i(r).length>0)throw Error(`La carpeta ya existe y no está vacía: ${r}`);return Ii(r,{recursive:!0}),r}function De(){return`team-cli spaces
|
|
1038
1071
|
|
|
1039
1072
|
Spaces son aplicaciones internas en React, pensadas para que las construyan agentes.
|
|
1040
1073
|
El flujo oficial parte con \`spaces init\` y \`spaces publish\` solo acepta apps creadas así.
|
|
@@ -1043,7 +1076,9 @@ Cada space:
|
|
|
1043
1076
|
- vive en data
|
|
1044
1077
|
- se desarrolla como app React + Vite
|
|
1045
1078
|
- viene con Tailwind y todos los componentes shadcn instalados
|
|
1046
|
-
- publica el resultado de \`yarn build\`
|
|
1079
|
+
- publica el repo del space (sin \`node_modules\` ni otros archivos ignorados por git) y el resultado de \`yarn build\`
|
|
1080
|
+
- guarda el repo publicado y permite recuperarlo con \`spaces fork <slug>\`
|
|
1081
|
+
- sube los archivos servidos a S3 en \`spaces/[slug]/[version]/files/*\`
|
|
1047
1082
|
- se sirve en \`/spaces/[slug]\`
|
|
1048
1083
|
- el build debe generar \`dist/index.html\`
|
|
1049
1084
|
- recibe automáticamente \`<base href="/spaces/[slug]/">\` al servir HTML
|
|
@@ -1058,11 +1093,20 @@ Cada space:
|
|
|
1058
1093
|
|
|
1059
1094
|
Flujo sugerido para agentes:
|
|
1060
1095
|
1. \`team-cli spaces init --path ./mi-space-app\`
|
|
1061
|
-
2.
|
|
1062
|
-
3. \`team-cli spaces
|
|
1063
|
-
4.
|
|
1064
|
-
5.
|
|
1065
|
-
6.
|
|
1096
|
+
2. hacer initial commit del repo nuevo
|
|
1097
|
+
3. \`team-cli spaces create --name '...' --description '...' --slug dashboard-1234\`
|
|
1098
|
+
4. \`team-cli spaces preview --path ./mi-space-app\`
|
|
1099
|
+
5. desarrollar la app React dentro de esa carpeta
|
|
1100
|
+
6. \`team-cli spaces publish <spaceId> --path ./mi-space-app\`
|
|
1101
|
+
7. hacer commit del repo después de publicar
|
|
1102
|
+
8. abrir \`${ze()}/spaces/<slug>\`
|
|
1103
|
+
9. si necesitas retomarlo en otra carpeta: \`team-cli spaces fork <slug> --path ./mi-space-app\`
|
|
1104
|
+
|
|
1105
|
+
Slugs:
|
|
1106
|
+
- usa en \`--slug\` el nombre que quieres para el space, por ejemplo \`dashboard-1234\`
|
|
1107
|
+
- el sistema siempre agrega automáticamente el prefijo del usuario
|
|
1108
|
+
- el slug final queda como \`usuario:slug-base\`
|
|
1109
|
+
- ejemplo: si tu email es \`nicolaslopezj@...\`, el slug final queda \`nicolaslopezj:dashboard-1234\`
|
|
1066
1110
|
|
|
1067
1111
|
Qué crea \`spaces init\`:
|
|
1068
1112
|
- Vite + React + TypeScript
|
|
@@ -1074,6 +1118,12 @@ Qué crea \`spaces init\`:
|
|
|
1074
1118
|
- helper \`justoStream(...)\` en \`src/lib/justo.ts\`
|
|
1075
1119
|
- ejemplo inicial en \`src/App.tsx\`
|
|
1076
1120
|
- configuración para que Vite construya con rutas relativas y funcione dentro del space
|
|
1121
|
+
- un repo git nuevo e independiente en la carpeta del space
|
|
1122
|
+
|
|
1123
|
+
Compartir dashboards:
|
|
1124
|
+
- si el usuario pide compartir un dashboard con otra persona, normalmente hay que darle acceso a las queries que usa ese dashboard
|
|
1125
|
+
- para eso usa \`team-cli data queries add-viewers <queryId> --emails 'persona@justo.com'\`
|
|
1126
|
+
- comparte todas las queries usadas por el dashboard, no solo el space
|
|
1077
1127
|
|
|
1078
1128
|
Mapas:
|
|
1079
1129
|
- el starter reutiliza el mismo token de MapTiler que ya usa vite-fronts
|
|
@@ -1093,6 +1143,11 @@ Qué hace \`spaces preview\`:
|
|
|
1093
1143
|
- si envías \`--open\`, intenta abrir la preview en el navegador por defecto del sistema
|
|
1094
1144
|
- \`--open\` es ideal para ir mostrándole al usuario el dashboard mientras el agente lo va construyendo
|
|
1095
1145
|
|
|
1146
|
+
Disciplina recomendada:
|
|
1147
|
+
- después de \`spaces init\`, haz un initial commit del repo del space
|
|
1148
|
+
- después de cada \`spaces publish\`, haz commit del repo del space
|
|
1149
|
+
- eso deja trazabilidad clara entre lo publicado y el código fuente
|
|
1150
|
+
|
|
1096
1151
|
Ejemplo desde el propio HTML del space:
|
|
1097
1152
|
\`\`\`js
|
|
1098
1153
|
import {justoCli, justoStream} from '@/lib/justo'
|
|
@@ -1109,11 +1164,12 @@ await justoStream(
|
|
|
1109
1164
|
|
|
1110
1165
|
Comandos:
|
|
1111
1166
|
- \`spaces init --path ./mi-space-app\`
|
|
1112
|
-
- \`spaces create --name '...' --description '...' --slug
|
|
1167
|
+
- \`spaces create --name '...' --description '...' --slug dashboard-1234\`
|
|
1113
1168
|
- \`spaces preview --path ./mi-space-app [--open]\`
|
|
1114
1169
|
- \`spaces publish <spaceId> --path ./mi-space-app\`
|
|
1170
|
+
- \`spaces fork <slug> --path ./mi-space-app\`
|
|
1115
1171
|
- \`spaces archive <spaceId>\`
|
|
1116
|
-
`}async function
|
|
1172
|
+
`}async function Zt(e){let r=ae(e,"path","team-cli spaces init --path ./mi-space-app");return Hr(r)}async function kt(e){return await ct(e)}async function Yt(e){Se();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) {
|
|
1117
1173
|
createSpace(name: $name, description: $description, slug: $slug) {
|
|
1118
1174
|
_id
|
|
1119
1175
|
name
|
|
@@ -1124,7 +1180,7 @@ Comandos:
|
|
|
1124
1180
|
createdByEmail
|
|
1125
1181
|
createdById
|
|
1126
1182
|
}
|
|
1127
|
-
}`,variables:{name:
|
|
1183
|
+
}`,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 Vt(e,r){Se();let t=Ht(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=Gt(o,a),n=await xi(t,i);return{...n,intraUrl:n.slug?`${ze()}/spaces/${n.slug}`:void 0,serveUrl:n.slug?`${h("data")}/spaces/${n.slug}`:void 0,builtFrom:Xt(o)}}async function Kt(e,r){Se();let t=e[2];if(!t)throw Error("Uso: team-cli spaces fork <slug> --path ./mi-space-app");let o=Ei(r.path||`./${t}`),a=await Si(t),i=Dt(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 Lt(e){Se();let r=Ht(e,"team-cli spaces archive <spaceId>");return(await u({service:"data",query:`mutation ($spaceId: String) {
|
|
1128
1184
|
archiveSpace(spaceId: $spaceId) {
|
|
1129
1185
|
_id
|
|
1130
1186
|
name
|
|
@@ -1136,7 +1192,7 @@ Comandos:
|
|
|
1136
1192
|
createdById
|
|
1137
1193
|
archivedAt
|
|
1138
1194
|
}
|
|
1139
|
-
}`,variables:{spaceId:
|
|
1195
|
+
}`,variables:{spaceId:r}})).archiveSpace}function eo(e){return`team-cli
|
|
1140
1196
|
|
|
1141
1197
|
Herramienta CLI para el equipo Justo.
|
|
1142
1198
|
|
|
@@ -1184,5 +1240,8 @@ npx @getjusto/team-cli admin search <text> [--limit <n>] [--page <n>] [--only-ac
|
|
|
1184
1240
|
Crea queries personalizadas usando \`create\` y \`ai-edit\` para generar consultas a la base de datos y luego crear un dashboard que las use
|
|
1185
1241
|
para mostrar datos. Usa \`preview\` para iterar rápido, \`run\` para consumir NDJSON en streaming y \`download\` para Excel.
|
|
1186
1242
|
También puedes usar queries para poblar selectores y otras partes de la interfaz del space.
|
|
1243
|
+
Siempre que puedas, prefiere varias queries simples antes que un solo query con \`lookup\`.
|
|
1244
|
+
Eso suele ser más fácil de iterar, más claro para agentes y menos frágil para dashboards.
|
|
1245
|
+
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\`.
|
|
1187
1246
|
|
|
1188
|
-
`}function
|
|
1247
|
+
`}function ro(){let e=g(),r=e?`Sesión: ${e.email}`:"Sesión: no iniciada";return eo(r)}async function to(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.9"};if(t.help&&!o)return ro();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 Y();if(n==="coupons"&&s==="create"&&t.help)return Er();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 Y();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 $r(i,t);if(n==="coupons"&&s==="update"){if(!c)throw Error("Uso: team-cli admin <web> coupons update <couponId> --input '<json>'");return await xr(i,c,t)}if(n==="coupons"&&s==="delete"){if(!c)throw Error("Uso: team-cli admin <web> coupons delete <couponId>");return await Sr(i,c)}if(n==="coupons"&&s==="codes"){let l=r[4],m=r[5];if(!l||l==="--help")return Y();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 Y()}return pe()}if(o==="graphql"){if(a==="--help"||t.help)return Nt();return await At(r,t)}if(o==="data"){let i=r[1],n=r[2];if(t.help||a==="--help")return Fe();if(i==="queries"&&n==="create")return await yt();if(i==="queries"&&n==="edit")return await Ct(r);if(i==="queries"&&n==="ai-edit")return await ht(r,t);if(i==="queries"&&n==="view")return await qt(r);if(i==="queries"&&n==="view-pipeline")return await It(r);if(i==="queries"&&n==="preview")return await $t(r,t);if(i==="queries"&&n==="run")return await xt(r,t);if(i==="queries"&&n==="add-viewers")return await St(r,t);if(i==="queries"&&n==="download")return await Et(r,t);return Fe()}if(o==="spaces"){let i=r[1];if(!i||i==="--help"||t.help)return De();if(i==="init")return await Zt(t);if(i==="create")return await Yt(t);if(i==="preview")return await kt(t);if(i==="publish")return await Vt(r,t);if(i==="fork")return await Kt(r,t);if(i==="archive")return await Lt(r);return De()}return ro()}var{flags:oo}=ie(process.argv.slice(2));async function ji(){try{let e=await to(process.argv.slice(2));if(e&&typeof e==="object"&&"__streamHandled"in e&&e.__streamHandled)return;if(typeof e==="string"){Le(e);return}Ke(e,oo)}catch(e){er(e,oo),process.exit(1)}}ji();
|