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.7 kB
import{readLinkedProject as v,resolveDeployDriver as h,execArgsFor as b,detectPackageManager as y}from"@lunora/config";import{d as w}from"../packem_shared/command-Mmxzxyr5.mjs";import{EXIT_CODE as l}from"../packem_shared/EXIT_CODE-08cwt3MK.mjs";import{defaultSpawner as L}from"../packem_shared/createRecordingSpawner-sS7LEN7x.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 n=e.trim();if(f.test(n))return Number(n);const a=Date.parse(n);if(Number.isNaN(a))throw new TypeError(`logs: invalid ${t} "${e}" — pass epoch-millis or an ISO 8601 date`);return a},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 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:a}=n,r=n.seen,s=Array.isArray(r)?r.filter(i=>typeof i=="string"):void 0;return s!==void 0&&s.length>0?{seen:s,ts:a}:{ts:a}},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={},n=u(e.since,"--since");n!==void 0&&(t.sinceTs=n);const a=u(e.until,"--until");a!==void 0&&(t.untilTs=a);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(),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,a=t.R2_SQL_TOKEN,r=t.R2_SQL_BUCKET,s=[];if((n===void 0||n.length===0)&&s.push("R2_SQL_ACCOUNT_ID"),(a===void 0||a.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:l.USAGE,error:"not configured"};let i;try{i=p(e)}catch(o){return e.logger.error(o instanceof Error?o.message:String(o)),{code:l.USAGE,error:"invalid option"}}const d=S({accountId:n,apiToken:a,bucket:r,fetch:e.fetch}),c=await _(d,{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 ${C(c.nextCursor)} for the next page`),{code:0,rows:c.rows}},N=async e=>{const t=e.cwd??process.cwd(),n=e.env??v(t)?.env,a=h(e.target);if(a.toolchain===void 0){const c=`logs: deploy target "${a.id}" has no command-line toolchain`;return e.logger.error(c),{code:l.USAGE,descriptor:void 0,error:c}}const r=a.toolchain.tail({environment:n,format:e.format,search:e.search,status:e.status,temporary:e.temporary,worker:e.worker}),s=b(y(t),r.tool,r.args),i={args:s.args,command:s.command,cwd:t};return e.logger.info(`tailing logs via ${i.command} ${i.args.join(" ")}`),{code:(await(e.spawner??L)(i)).code,delegated:!0,descriptor:i}},U=w(async({argument:e,cwd:t,format:n,logger:a,options:r})=>{if(r.durable===!0){const s=await $({cursor:r.cursor,functionPrefix:r.functionPrefix,level:r.level,limit:r.limit,logger:a,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:n,logger:a,search:r.search,status:r.status,target:r.target,temporary:r.temporary===!0,worker:e[0]})});export{U as execute,N as runLogsCommand};