@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.93 kB
JavaScript
import{readLinkedProject as h,resolveDeployDriver as b}from"@lunora/config";import{d as y}from"../packem_shared/command-B6vu47iR.mjs";import{r as w}from"../packem_shared/deploy-target-resolve-BTCW1Iv4.mjs";import{EXIT_CODE as m}from"../packem_shared/EXIT_CODE-DVjUgIaG.mjs";import{defaultSpawner as E}from"../packem_shared/createRecordingSpawner-01ZngIwK.mjs";import{createR2Sql as L}from"@lunora/bindings/r2sql";import{createPipelineLogReader as S}from"@lunora/runtime";import{toolchainExecArgs as _,detectPackageManager as T}from"@lunora/config/cli";const p=["trace","debug","log","info","warn","error","fatal"],C=new Set(p),v=/^\d+$/,f=(e,r)=>{if(e===void 0)return;const a=e.trim();if(v.test(a))return Number(a);const n=Date.parse(a);if(Number.isNaN(n))throw new TypeError(`logs: invalid ${r} "${e}" — pass epoch-millis or an ISO 8601 date`);return n},I=e=>Buffer.from(JSON.stringify(e),"utf8").toString("base64url"),$=e=>{const r=e.trim();if(v.test(r))return{ts:Number(r)};let a;try{a=JSON.parse(Buffer.from(r,"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 a!="object"||a===null||typeof a.ts!="number"||!Number.isFinite(a.ts))throw new TypeError(`logs: invalid --cursor "${e}" — expected the token printed by the previous page (or a bare epoch-millis ts)`);const{ts:n}=a,t=a.seen,s=Array.isArray(t)?t.filter(o=>typeof o=="string"):void 0;return s!==void 0&&s.length>0?{seen:s,ts:n}:{ts:n}},g=(e,r)=>{if(e!==void 0){if(!C.has(e))throw new TypeError(`logs: invalid ${r} "${e}" — expected one of trace, debug, log, info, warn, error, fatal`);return e}},R=e=>{const r={},a=f(e.since,"--since");a!==void 0&&(r.sinceTs=a);const n=f(e.until,"--until");n!==void 0&&(r.untilTs=n);const t=g(e.level,"--level");t!==void 0&&(r.level=t);const s=g(e.minLevel,"--min-level");if(s!==void 0&&(r.minLevel=s),e.functionPrefix!==void 0&&(r.functionPathPrefix=e.functionPrefix),e.traceId!==void 0&&(r.traceId=e.traceId),e.shardKey!==void 0&&(r.shardKey=e.shardKey),e.userId!==void 0&&(r.userId=e.userId),e.limit!==void 0){const o=Number(e.limit);if(!Number.isFinite(o))throw new TypeError(`logs: invalid --limit "${e.limit}" — expected a number`);r.limit=o}return e.cursor!==void 0&&(r.cursor=$(e.cursor)),r},N=e=>{const r=new Date(e.ts).toISOString(),a=e.level.toUpperCase().padEnd(5);return`${r} ${a} ${e.functionPath} ${e.message}`},O=async e=>{const r=e.environment??process.env,a=r.R2_SQL_ACCOUNT_ID,n=r.R2_SQL_TOKEN,t=r.R2_SQL_BUCKET,s=[];if((a===void 0||a.length===0)&&s.push("R2_SQL_ACCOUNT_ID"),(n===void 0||n.length===0)&&s.push("R2_SQL_TOKEN"),(t===void 0||t.length===0)&&s.push("R2_SQL_BUCKET"),(e.table===void 0||e.table.length===0)&&s.push("--table"),s.length>0)return e.logger.error(`logs --durable: R2 SQL not configured (missing ${s.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:m.USAGE,error:"not configured"};let o;try{o=R(e)}catch(i){return e.logger.error(i instanceof Error?i.message:String(i)),{code:m.USAGE,error:"invalid option"}}const u=L({accountId:a,apiToken:n,bucket:t,fetch:e.fetch}),c=await S(u,{namespace:e.namespace,table:e.table}).query(o);for(const i of c.rows)process.stdout.write(`${e.ndjson===!0?JSON.stringify(i):N(i)}
`);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 ${I(c.nextCursor)} for the next page`),{code:0,rows:c.rows}},x=async e=>{const r=e.cwd??process.cwd(),a=e.env??h(r)?.env,n=w(r,e.target);if(n.target===void 0){const d=`logs: ${n.error??"no deploy target"}`;return e.logger.error(d),{code:m.USAGE,descriptor:void 0,error:d}}const t=b(n.target),s=t.toolchain?.tail;if(s===void 0){const d=`logs: deploy target "${t.id}" has no log tail`;return e.logger.error(d),{code:m.USAGE,descriptor:void 0,error:d}}const o=s({environment:a,format:e.format,search:e.search,status:e.status,temporary:e.temporary,worker:e.worker}),u=_(T(r),o),l={args:u.args,command:u.command,cwd:r};return e.logger.info(`tailing logs via ${l.command} ${l.args.join(" ")}`),{code:(await(e.spawner??E)(l)).code,delegated:!0,descriptor:l}},G=y(async({argument:e,cwd:r,format:a,logger:n,options:t})=>{if(t.durable===!0){const s=await O({cursor:t.cursor,functionPrefix:t.functionPrefix,level:t.level,limit:t.limit,logger:n,minLevel:t.minLevel,namespace:t.namespace,ndjson:t.ndjson===!0,shardKey:t.shardKey,since:t.since,table:t.table,traceId:t.traceId,until:t.until,userId:t.userId});return{...s,...s.rows===void 0?{}:{delegated:!0}}}return x({cwd:r,env:t.env,format:a,logger:n,search:t.search,status:t.status,target:t.target,temporary:t.temporary===!0,worker:e[0]})});export{G as execute,x as runLogsCommand};