@lunora/cli
Version:
The Lunora CLI: init, dev, deploy, codegen, migrate, seed, doctor, insights, logs, registry, and the rest of the project commands
3 lines (2 loc) • 4.73 kB
JavaScript
import{readLinkedProject as g,resolveDeployDriver as v,execArgsFor as h,detectPackageManager as y}from"@lunora/config";import{d as b}from"../packem_shared/command-DwC11Cwe.mjs";import{defaultSpawner as w}from"../packem_shared/createRecordingSpawner-DJlNacZ6.mjs";import{createR2Sql as L}from"@lunora/bindings/r2sql";import{createPipelineLogReader as _}from"@lunora/runtime";const S=["trace","debug","log","info","warn","error","fatal"],T=new Set(S),m=/^\d+$/,d=(e,t)=>{if(e===void 0)return;const n=e.trim();if(m.test(n))return Number(n);const r=Date.parse(n);if(Number.isNaN(r))throw new TypeError(`logs: invalid ${t} "${e}" — pass epoch-millis or an ISO 8601 date`);return r},E=e=>Buffer.from(JSON.stringify(e),"utf8").toString("base64url"),C=e=>{const t=e.trim();if(m.test(t))return{ts:Number(t)};let n;try{n=JSON.parse(Buffer.from(t,"base64url").toString("utf8"))}catch{throw new TypeError(`logs: invalid --cursor "${e}" — expected the token printed by the previous page (or a bare epoch-millis ts)`)}if(typeof n!="object"||n===null||typeof n.ts!="number"||!Number.isFinite(n.ts))throw new TypeError(`logs: invalid --cursor "${e}" — expected the token printed by the previous page (or a bare epoch-millis ts)`);const{ts:r}=n,s=n.seen,a=Array.isArray(s)?s.filter(i=>typeof i=="string"):void 0;return a!==void 0&&a.length>0?{seen:a,ts:r}:{ts:r}},u=(e,t)=>{if(e!==void 0){if(!T.has(e))throw new TypeError(`logs: invalid ${t} "${e}" — expected one of trace, debug, log, info, warn, error, fatal`);return e}},I=e=>{const t={},n=d(e.since,"--since");n!==void 0&&(t.sinceTs=n);const r=d(e.until,"--until");r!==void 0&&(t.untilTs=r);const s=u(e.level,"--level");s!==void 0&&(t.level=s);const a=u(e.minLevel,"--min-level");if(a!==void 0&&(t.minLevel=a),e.functionPrefix!==void 0&&(t.functionPathPrefix=e.functionPrefix),e.traceId!==void 0&&(t.traceId=e.traceId),e.shardKey!==void 0&&(t.shardKey=e.shardKey),e.userId!==void 0&&(t.userId=e.userId),e.limit!==void 0){const i=Number(e.limit);if(!Number.isFinite(i))throw new TypeError(`logs: invalid --limit "${e.limit}" — expected a number`);t.limit=i}return e.cursor!==void 0&&(t.cursor=C(e.cursor)),t},R=e=>{const t=new Date(e.ts).toISOString(),n=e.level.toUpperCase().padEnd(5);return`${t} ${n} ${e.functionPath} ${e.message}`},$=async e=>{const t=e.environment??process.env,n=t.R2_SQL_ACCOUNT_ID,r=t.R2_SQL_TOKEN,s=t.R2_SQL_BUCKET,a=[];if((n===void 0||n.length===0)&&a.push("R2_SQL_ACCOUNT_ID"),(r===void 0||r.length===0)&&a.push("R2_SQL_TOKEN"),(s===void 0||s.length===0)&&a.push("R2_SQL_BUCKET"),(e.table===void 0||e.table.length===0)&&a.push("--table"),a.length>0)return e.logger.error(`logs --durable: R2 SQL not configured (missing ${a.join(", ")}). The Pipeline must write to an R2 Data Catalog (Iceberg) table, and you must supply R2_SQL_ACCOUNT_ID / R2_SQL_TOKEN / R2_SQL_BUCKET plus --table — see the observability docs.`),{code:1,error:"not configured"};let i;try{i=I(e)}catch(o){return e.logger.error(o instanceof Error?o.message:String(o)),{code:1,error:"invalid option"}}const l=L({accountId:n,apiToken:r,bucket:s,fetch:e.fetch}),c=await _(l,{namespace:e.namespace,table:e.table}).query(i);for(const o of c.rows)process.stdout.write(`${e.ndjson===!0?JSON.stringify(o):R(o)}
`);return c.rows.length===0?e.logger.info("logs --durable: no matching log records"):c.nextCursor!==void 0&&e.logger.info(`logs --durable: more rows available — pass --cursor ${E(c.nextCursor)} for the next page`),{code:0,rows:c.rows}},x=new Set(["json","pretty"]),N=async e=>{const t=e.cwd??process.cwd();if(e.format!==void 0&&!x.has(e.format))return e.logger.error(`logs: unknown --format "${e.format}" — expected pretty | json`),{code:1,descriptor:void 0,error:"invalid format"};const n=e.env??g(t)?.env,r=v(e.target);if(r.toolchain===void 0)return e.logger.error(`logs: deploy target "${r.id}" has no command-line toolchain`),{code:1,descriptor:void 0,error:"no toolchain"};const s=r.toolchain.tail({environment:n,format:e.format,search:e.search,status:e.status,temporary:e.temporary,worker:e.worker}),a=h(y(t),s.tool,s.args),i={args:a.args,command:a.command,cwd:t};return e.logger.info(`tailing logs via ${i.command} ${i.args.join(" ")}`),{code:(await(e.spawner??w)(i)).code,descriptor:i}},k=b(({argument:e,cwd:t,logger:n,options:r})=>r.durable===!0?$({cursor:r.cursor,functionPrefix:r.functionPrefix,level:r.level,limit:r.limit,logger:n,minLevel:r.minLevel,namespace:r.namespace,ndjson:r.ndjson===!0,shardKey:r.shardKey,since:r.since,table:r.table,traceId:r.traceId,until:r.until,userId:r.userId}):N({cwd:t,env:r.env,format:r.format,logger:n,search:r.search,status:r.status,target:r.target,temporary:r.temporary===!0,worker:e[0]}));export{k as execute,N as runLogsCommand};