UNPKG

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