@lunora/cli
Version:
The Lunora CLI: init, dev, deploy, codegen, migrate, seed, doctor, insights, logs, registry, and the rest of the project commands
2 lines (1 loc) • 3.74 kB
JavaScript
import{LunoraError as h}from"@lunora/errors";import{r as S,d as b}from"../packem_shared/admin-token-VdUnvnKW.mjs";import{r as N,a as _}from"../packem_shared/admin-url-BhF5ufg1.mjs";import{d as U}from"../packem_shared/command-Mmxzxyr5.mjs";import{EXIT_CODE as u,exitCodeForStatus as p}from"../packem_shared/EXIT_CODE-08cwt3MK.mjs";import{r as E}from"../packem_shared/resolve-target-C_ZloTvd.mjs";const y=(r,a="--args")=>{if(r===void 0||r.length===0)return{};let e;try{e=JSON.parse(r)}catch(t){const s=t instanceof Error?t.message:String(t);throw new h("INTERNAL",`failed to parse ${a} as JSON: ${s}`,{cause:t})}if(typeof e!="object"||e===null||Array.isArray(e))throw new h("INTERNAL",`${a} must be a JSON object (e.g. '{"id":1}'), got ${Array.isArray(e)?"an array":typeof e}`);return e},P=/\/$/u,T="__lunora_admin__:runAs",I="__lunora_admin__:",O=async(r,a)=>{const e=await r.text();let t;try{t=JSON.parse(e)}catch{t=e}return a.info(JSON.stringify(t,void 0,2)),t},$=(r,a)=>{const e=a.body?.error?.code;a.runAs||a.status!==403||e!=="FORBIDDEN_SHARD"||r.info("this app authorizes per shard, so an anonymous call is denied — retry with --as <userId> to run as an authenticated user")},k=({args:r,claims:a,options:e,runAs:t})=>{const s=t?{args:{args:r,functionPath:e.functionPath,identity:a,userId:e.as},functionPath:T}:{args:r,functionPath:e.functionPath};return e.shard!==void 0&&(s.shardKey=e.shard),s},R=({cwd:r,logger:a,needsBearer:e,url:t})=>e?N(t,a,r):(E({cwd:r,url:t})??_(r)).replace(P,""),w=({args:r,claims:a},e)=>{try{return{args:y(r),claims:a===void 0?void 0:y(a,"--claims")}}catch(t){e.error(t instanceof Error?t.message:String(t));return}},D=async r=>{const a=r.cwd??process.cwd(),{logger:e}=r,t=r.as!==void 0&&r.as!=="";if(r.claims!==void 0&&!t){const d="--claims requires --as <userId> — extra identity claims only travel inside the admin-gated `runAs` dispatch.";return e.error(d),{body:void 0,code:u.USAGE,error:d,requestUrl:r.url??""}}const s=t||r.functionPath.startsWith(I),n=R({cwd:a,logger:e,needsBearer:s,url:r.url});if(n===void 0)return{body:void 0,code:u.USAGE,error:"could not resolve a usable worker URL",requestUrl:r.url??""};const o=`${n}/_lunora/rpc`,i=r.fetchImpl??globalThis.fetch;if(typeof i!="function")throw new TypeError("no fetch implementation available — pass --fetch via dependency injection or run on Node >= 18");const f=w(r,e);if(f===void 0)return{body:void 0,code:u.USAGE,error:"could not parse --args / --claims as JSON",requestUrl:o};const{source:v,token:l}=s?S({cwd:a,token:r.token,url:n}):{};if(s&&l===void 0){const d="admin token required — pass --token, set LUNORA_ADMIN_TOKEN, or add it to .dev.vars (local targets only)";return e.error(d),{body:void 0,code:u.AUTH,error:d,requestUrl:o}}l!==void 0&&e.debug?.(`admin bearer from ${b(v)}`);const g={"content-type":"application/json",...l===void 0?{}:{authorization:`Bearer ${l}`}},A=k({args:f.args,claims:f.claims,options:r,runAs:t});e.info(`POST ${o} -> ${r.functionPath}${t?` (as ${r.as??""})`:""}`);const c=await i(o,{body:JSON.stringify(A),headers:g,method:"POST"}),m=await O(c,e);return $(e,{body:m,runAs:t,status:c.status}),{body:m,code:c.ok?0:p(c.status),error:c.ok?void 0:`${r.functionPath} failed: HTTP ${String(c.status)}`,requestUrl:o}},j=U(async({argument:r,cwd:a,format:e,logger:t,options:s})=>{const n=r[0];if(!n){const i="missing function path. Usage: lunora run <functionPath> [--args <json>]";return t.error(i),{code:u.USAGE,error:i}}const o=await D({args:s.args,as:s.as,claims:s.claims,cwd:a,format:e,functionPath:n,logger:t,shard:s.shard,token:s.token,url:s.url});return{code:o.code,data:{functionPath:n,requestUrl:o.requestUrl,result:o.body},error:o.error}});export{j as execute,O as readAndLogBody,D as runRpcCommand};