@lowlighter/run 2.0.1 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/command.mjs CHANGED
@@ -1,90 +1 @@
1
- var e=class e{constructor({level:t,format:n,output:r,tags:o,...i}={}){"granted"===globalThis.Deno?.permissions.querySync?.({name:"env",variable:"LOG_LEVEL"}).state&&(t??=globalThis.Deno?.env.get("LOG_LEVEL")),this.#e=r||null===r?r:console,this.#t=e.level.log,this.#n=e.format.text,this.#r={date:!1,time:!1,delta:!0,caller:{file:!1,name:!1,line:!1,fileformat:null}},this.level(t).format(n).options(i),this.tags=o??{}}#e;#r;options(e){if(!e)return structuredClone(this.#r);if("date"in e&&(this.#r.date=e.date),"time"in e&&(this.#r.time=e.time),"delta"in e&&(this.#r.delta=e.delta),"caller"in e)switch(!0){case!0===e.caller:this.#r.caller={file:!0,name:!0,line:!0,fileformat:this.#r.caller.fileformat};break;case!1===e.caller:this.#r.caller={file:!1,name:!1,line:!1,fileformat:this.#r.caller.fileformat};break;case"object"==typeof e.caller:"file"in e.caller&&(this.#r.caller.file=e.caller.file),"name"in e.caller&&(this.#r.caller.name=e.caller.name),"line"in e.caller&&(this.#r.caller.line=e.caller.line),"fileformat"in e.caller&&void 0!==e.caller.fileformat&&(this.#r.caller.fileformat=e.caller.fileformat)}return this}#t;level(t){return arguments.length?(Number.isNaN(Number.parseInt(`${t}`))||(t=Number.parseInt(`${t}`)),"string"==typeof t&&t in e.level&&(t=e.level[t]),"number"==typeof t&&(this.#t=!Number.isNaN(t)&&t>=0?t:-1),this):this.#t>=0?this.#t:NaN}static level=Object.freeze({disabled:NaN,error:0,warn:1,info:2,ok:2,log:3,debug:4,wdebug:4,trace:5,probe:NaN,always:1/0});error(...t){return this.#t>=e.level.error&&this.#e?.error(...this.#n(this,{level:"error",content:t,options:this.#r})),this}warn(...t){return this.#t>=e.level.warn&&this.#e?.warn(...this.#n(this,{level:"warn",content:t,options:this.#r})),this}info(...t){return this.#t>=e.level.info&&this.#e?.info(...this.#n(this,{level:"info",content:t,options:this.#r})),this}ok(...t){return this.#t>=e.level.info&&this.#e?.info(...this.#n(this,{level:"ok",content:t,options:this.#r})),this}log(...t){return this.#t>=e.level.log&&this.#e?.log(...this.#n(this,{level:"log",content:t,options:this.#r})),this}debug(...t){return this.#t>=e.level.debug&&this.#e?.debug(...this.#n(this,{level:"debug",content:t,options:this.#r})),this}wdebug(...t){return this.#t>=e.level.debug&&this.#e?.debug(...this.#n(this,{level:"wdebug",content:t,options:this.#r})),this}trace(...t){return this.#t>=e.level.trace&&this.#e?.debug(...this.#n(this,{level:"trace",content:t,options:this.#r})),this}probe(...e){return this.#e?.debug(...this.#n(this,{level:"probe",content:e,options:this.#r})),this}tags;with(t={}){return new e({level:this.#t,format:this.#n,output:this.#e,...this.#r,tags:{...this.tags,...t}})}#o(e=3){const t=Error,n=t.prepareStackTrace;t.prepareStackTrace=(e,t)=>t;const{stack:r}=new Error;t.prepareStackTrace=n;return r.map((e=>({file:e.getFileName(),name:e.getFunctionName(),line:e.getLineNumber(),column:e.getColumnNumber()})))[e]}static inspect(e){return globalThis.Deno?.inspect(e,{colors:!0,depth:1/0,strAbbreviateSize:1/0})??e}#n;format(t){return this.#n=("string"==typeof t?e.format[t]:t)??e.format.text,this}static format={text(t,{level:n,content:r,options:o}){const i={error:"red",warn:"orange",info:"cyan",ok:"green",log:"white",debug:"gray",wdebug:"yellow",trace:"gray",probe:"magenta"}[n],s=[`%c ${n.replace("wdebug","debug").toLocaleUpperCase().padEnd(5)} │%c`],l=[`color: black; background-color: ${i}`,""];if(o.date||o.time||o.delta){const e=(new Date).toISOString(),t=[];if(o.delta){const e=performance.now()/1e3;let n=e.toPrecision(4);e<1&&(n=e.toPrecision(2)),t.push(`+${n}`)}o.date&&o.time?t.push(e):o.date?t.push(e.slice(0,e.indexOf("T"))):o.time&&t.push(e.slice(e.indexOf("T")+1,-1)),s.push(`%c ${t.join(" ¦ ").trim()} %c`),l.push(`color: black; background-color: ${i}`,"")}if(o.caller.file||o.caller.name||o.caller.line){const e=t.#o();if(e){const t=[];if(o.caller.file){let n=`${e.file}`;Array.isArray(o.caller.fileformat)&&(n=n.replace(o.caller.fileformat[0],o.caller.fileformat[1])),t.push(n)}o.caller.name&&e.name&&t.push(e.name),o.caller.line&&t.push(e.line,e.column),s.push(`%c ${t.join(":").trim()} %c`),l.push("color: black; background-color: gray","")}}const a=[];for(const[n,r]of Object.entries(t.tags))a.push(`${n}:${e.inspect(r)}`);return s.push(`%c ${a.join(" ").trim()} %c`),l.push("background-color: black",""),[s.join(""),...l,...r.map(e.inspect)]},json(e,{level:t,content:n,options:r}){const o={level:t,timestamp:Date.now(),tags:e.tags,content:n},i={};if(r.date||r.time){const e=new Date(o.timestamp).toISOString();r.date&&(i.date=e.slice(0,e.indexOf("T"))),r.time&&(i.time=e.slice(e.indexOf("T")+1,-1))}if(r.delta&&(i.delta=performance.now()/1e3),r.caller.file||r.caller.name||r.caller.line){const t=e.#o();if(t){if(i.caller={},r.caller.file){let e=`${t.file}`;Array.isArray(r.caller.fileformat)&&(e=e.replace(r.caller.fileformat[0],r.caller.fileformat[1])),i.caller.file=e}r.caller.name&&t.name&&(i.caller.name=t.name),r.caller.line&&(i.caller.line=[t.line,t.column])}}return[JSON.stringify({...o,...i})]}}};TransformStream;function t(e){let t=0;for(const n of e)t+=n.length;const n=new Uint8Array(t);let r=0;for(const t of e)n.set(t,r),r+=t.length;return n}function n(e){const t=e.length,n=new Uint8Array(t);n[0]=0;let r=0,o=1;for(;o<t;)e[o]===e[r]?(r++,n[o]=r,o++):0===r?(n[o]=0,o++):r=n[r-1];return n}TransformStream,TransformStream,TransformStream,TransformStream;var r=class extends TransformStream{#i="";constructor(e={allowCR:!1}){super({transform:(t,n)=>{for(t=this.#i+t;;){const r=t.indexOf("\n"),o=e.allowCR?t.indexOf("\r"):-1;if(-1!==o&&o!==t.length-1&&(-1===r||r-1>o)){n.enqueue(t.slice(0,o)),t=t.slice(o+1);continue}if(-1===r)break;const i="\r"===t[r-1]?r-1:r;n.enqueue(t.slice(0,i)),t=t.slice(r+1)}this.#i=t},flush:t=>{if(""===this.#i)return;const n=e.allowCR&&this.#i.endsWith("\r")?this.#i.slice(0,-1):this.#i;t.enqueue(n)}})}};new TextDecoder;var o=new TextEncoder,i=new TextDecoder;function s(t,n,{logger:s=new e,stdin:a=null,stdout:c="debug",stderr:u="error",env:d,cwd:h,raw:f,callback:p,buffering:m,sync:g,throw:w,dryrun:b,winext:v="",os:y=Deno.build.os}={}){"windows"===y&&(t=`${t}${v}`),s=s.with({bin:t}),p&&"piped"!==l(a)&&(a="piped");const T=new Deno.Command(t,{args:n,stdin:g?"null":l(a),stdout:l(c),stderr:l(u),env:d,cwd:h,windowsRawArguments:f});if(b){s.wdebug(`dryrun: ${t} not executed`);const e={success:!0,code:0,stdio:[],stdin:"",stdout:"",stderr:""};return g?e:Promise.resolve(e)}return g?function(e,{bin:t,log:n,throw:r,stdout:o,stderr:s}){const a=Date.now(),c=e.outputSync(),{success:u,code:d}=c,h=Date.now()-a,f={get stdio(){return[[h,1,this.stdout],[h,2,this.stderr]]},stdin:"",stdout:"piped"===l(o)?i.decode(c.stdout):"",stderr:"piped"===l(s)?i.decode(c.stderr):""};for(const{channel:e,mode:t}of[{channel:"stdout",mode:o},{channel:"stderr",mode:s}])"piped"===l(t)&&f[e]&&n.with({t:h,channel:e})[t]?.(f[e]);if(!u&&r)throw new EvalError(`${t} exited with non-zero code ${d}:\n${f.stdout}\n${f.stderr}`);return{success:u,code:d,...f}}(T,{bin:t,log:s,throw:w,stdout:c,stderr:u}):async function(e,{bin:t,log:n,callback:i=({close:e})=>e?.(),buffering:s=250,throw:a,...c}){const u=e.spawn(),d=Date.now(),h={stdio:[],get stdin(){return this.stdio.filter((([e,t])=>0===t)).map((([e,t,n])=>n)).join("\n")},get stdout(){return this.stdio.filter((([e,t])=>1===t)).map((([e,t,n])=>n)).join("\n")},get stderr(){return this.stdio.filter((([e,t])=>2===t)).map((([e,t,n])=>n)).join("\n")}},f={};let p="";const m=function(e,t){let n=null,r=null;const o=(...i)=>{o.clear(),r=()=>{o.clear(),e.call(o,...i)},n=setTimeout(r,t)};return o.clear=()=>{"number"==typeof n&&(clearTimeout(n),n=null,r=null)},o.flush=()=>{r?.()},Object.defineProperty(o,"pending",{get:()=>"number"==typeof n}),o}((async e=>{n.with({t:e}).trace("debounced"),p="",await i({stdio:h,i:h.stdin.length,...f})}),s);if("piped"===l(c.stdin)){const e=u.stdin.getWriter();Object.assign(f,{async write(t,r=!0){const i=Date.now()-d;c.stdin&&n.with({t:i,channel:"stdin"})[c.stdin]?.(t),h.stdio.push([i,0,t]),r&&!t.endsWith("\n")&&(t+="\n"),await e.write(o.encode(t)),p="stdin",e.releaseLock()},async close(){try{e.releaseLock(),await u.stdin.close(),n.with({t:Date.now()-d,closed:"stdin"}).trace()}catch{}},async wait(e=1e3){const t=Date.now()-d;n.with({t:t,waiting:e}).trace(),await function(e,t={}){const{signal:n,persistent:r=!0}=t;return n?.aborted?Promise.reject(n.reason):new Promise(((t,o)=>{const i=()=>{clearTimeout(s),o(n?.reason)},s=setTimeout((()=>{n?.removeEventListener("abort",i),t()}),e);if(n?.addEventListener("abort",i,{once:!0}),!1===r)try{Deno.unrefTimer(s)}catch(e){if(!(e instanceof ReferenceError))throw e;console.error("`persistent` option is only available in Deno")}}))}(e),m(t)}}),m(Date.now()-d)}await Promise.all(["stdout","stderr"].filter((e=>"piped"===l(c[e]))).map((async e=>{for await(const t of u[e].pipeThrough(new TextDecoderStream).pipeThrough(new r)){const r=Date.now()-d,o={stdout:1,stderr:2}[e];if(c[e]&&n.with({t:r,channel:e})[c[e]]?.(t),h.stdio.length&&p===e){const e=h.stdio.at(-1);e[1]===o&&(e[2]+=`\n${t}`)}else h.stdio.push([r,o,t]);p=e,m(r)}}))),m.flush();const{success:g,code:w}=await u.status;if(!g&&a)throw new EvalError(`${t} exited with non-zero code ${w}:\n${h.stdout}\n${h.stderr}`);return{success:g,code:w,...h}}(T,{bin:t,log:s,callback:p,buffering:m,throw:w,stdin:"piped"===l(a)?a:null,stdout:"piped"===l(c)?c:null,stderr:"piped"===l(u)?u:null})}function l(e){return["inherit","null"].includes(`${e}`)?`${e}`:"piped"}export{s as command};
2
- /**
3
- * Logger class.
4
- *
5
- * This class provides a simple and efficient logging framework intended to supersed the native {@link https://developer.mozilla.org/en-US/docs/Web/API/console | console} by providing additional features and metadata.
6
- *
7
- * It supports out-of-the-box colored output, a log level mechanism (that honor `LOG_LEVEL` environment variable), a tag system, and a variety of options to customize the output.
8
- * A neat addition is the ability to display caller information (file, name, line) which can be especially useful for debugging.
9
- *
10
- * @example
11
- * ```ts
12
- * import { Logger } from "./mod.ts"
13
- *
14
- * // Configure logger
15
- * const tags = { foo: "bar" }
16
- * const log = new Logger({ level: "trace", tags, date: true, time: true, delta:true, caller:true })
17
- *
18
- * // Print logs
19
- * log
20
- * .error("🍱 bento")
21
- * .warn("🍜 ramen")
22
- * .ok("🍚 gohan")
23
- * .info("🍣 sushi")
24
- * .log("🍥 narutomaki")
25
- * .debug("🍡 dango")
26
- * .wdebug("🍵 matcha")
27
- * .trace("🍙 onigiri")
28
- * .probe("🥟 gyoza")
29
- *
30
- * // Create a new inherited logger with additional tags
31
- * log.with({ bar: "true" }).log("🍶 sake")
32
- * ```
33
- *
34
- * @author Simon Lecoq (lowlighter)
35
- * @license MIT
36
- */
37
- /**
38
- * Run a command.
39
- *
40
- * This is a wrapper around {@link https://docs.deno.com/api/deno/~/Deno.Command | Deno.command} that provides a better handling of stdio for interactive processes.
41
- *
42
- * Like `Deno.command`, the `env`, `cwd`, and `raw` (alias for `windowsRawArguments`) options are supported.
43
- *
44
- * The `stdin`, `stdout` and `stderr` options can be either set to an allowed {@link https://docs.deno.com/api/deno/~/Deno.Command | Deno.command} values (`"inherit"`, `"null"`, `"piped"`), or either to a supported log level of {@link Logger}.
45
- * In the later case, the content will be always be "piped" and logged to the specified level of the provided {@link Logger} instance.
46
- *
47
- * Set `winext` option to automatically append an extension to the binary path on Windows (like `.cmd` or `.exe`).
48
- * This is useful when the binary path isn't automatically resolved on Windows.
49
- *
50
- * Pass a `callback` option to interact with the process stdin and stdout.
51
- * It is called each time data is received on of the piped channels, after input buffering.
52
- * It will receive an object with the current stdio content, the current command index (based on the content written to stdin), along with a few additional functions:
53
- * - `write(content: string, newline?: boolean): Promise<void>` encodes and writes content to stdin.
54
- * - A newline is automatically appended by default but can be toggled off by passing `false` as second argument.
55
- * - `close(): Promise<void>` closes stdin.
56
- * - Note that you **need** to eventually call this method to prevent most processes from hanging as they're waiting for more input.
57
- * - `wait(dt: number): Promise<void>` waits for a given amount of time before calling the callback again.
58
- * - It is especially useful for polling, like checking if a specific line has been written to stdio or not.
59
- *
60
- * The `buffering` option is used to merge messages that are received relatively closely.
61
- * Setting this option to a low value will also increase the rate at which the `callback` is called.
62
- *
63
- * Resulting object contains the same properties as {@link https://docs.deno.com/api/deno/~/Deno.CommandStatus | Deno.CommandStatus}
64
- * with an additional `stdio` property that contains an array of ordered tuples with the delta timestamp since process start, the channel idenfitier (0:stdin, 1:stdout, 2:stderr) and the content.
65
- * This offers a proper history of exchanged content.
66
- *
67
- * @example
68
- * ```ts
69
- * import { command } from "./command.ts"
70
- * import { Logger } from "jsr:@libs/logger"
71
- * await command("deno", ["version"], { env: { NO_COLOR: "true" }, cwd: "/tmp", raw: true })
72
- * await command("deno", ["version"], { stdout: "piped" })
73
- * await command("deno", ["version"], { logger: new Logger(), stdout: "debug" })
74
- * await command("deno", ["version"], { winext: ".exe" })
75
- * ```
76
- *
77
- * @example
78
- * ```ts
79
- * import { command } from "./command.ts"
80
- * const { stdout } = await command("deno", ["repl"], {
81
- * env: { NO_COLOR: "true" },
82
- * callback: ({ i, write, close }) => i === 0 ? write("console.log('hello')") : close(),
83
- * })
84
- * console.assert(stdout.includes("hello"))
85
- * ```
86
- *
87
- * @author Simon Lecoq (lowlighter)
88
- * @license MIT
89
- * @module
90
- */
1
+ var e=class e{constructor({level:t,format:r,output:n,tags:o,...i}={}){"granted"===globalThis.Deno?.permissions.querySync?.({name:"env",variable:"LOG_LEVEL"}).state&&(t??=globalThis.Deno?.env.get("LOG_LEVEL")),this.#e=n||null===n?n:console,this.#t=e.level.log,this.#r=e.format.text,this.#n={date:!1,time:!1,delta:!0,caller:{file:!1,name:!1,line:!1,fileformat:null}},this.level(t).format(r).options(i),this.tags=o??{}}#e;#n;options(e){if(!e)return structuredClone(this.#n);if("date"in e&&(this.#n.date=e.date),"time"in e&&(this.#n.time=e.time),"delta"in e&&(this.#n.delta=e.delta),"caller"in e)switch(!0){case!0===e.caller:this.#n.caller={file:!0,name:!0,line:!0,fileformat:this.#n.caller.fileformat};break;case!1===e.caller:this.#n.caller={file:!1,name:!1,line:!1,fileformat:this.#n.caller.fileformat};break;case"object"==typeof e.caller:"file"in e.caller&&(this.#n.caller.file=e.caller.file),"name"in e.caller&&(this.#n.caller.name=e.caller.name),"line"in e.caller&&(this.#n.caller.line=e.caller.line),"fileformat"in e.caller&&void 0!==e.caller.fileformat&&(this.#n.caller.fileformat=e.caller.fileformat)}return this}#t;level(t){return arguments.length?(Number.isNaN(Number.parseInt(`${t}`))||(t=Number.parseInt(`${t}`)),"string"==typeof t&&t in e.level&&(t=e.level[t]),"number"==typeof t&&(this.#t=!Number.isNaN(t)&&t>=0?t:-1),this):this.#t>=0?this.#t:NaN}static level=Object.freeze({disabled:NaN,error:0,warn:1,info:2,ok:2,log:3,debug:4,wdebug:4,trace:5,probe:NaN,always:1/0});error(...t){return this.#t>=e.level.error&&this.#e?.error(...this.#r(this,{level:"error",content:t,options:this.#n})),this}warn(...t){return this.#t>=e.level.warn&&this.#e?.warn(...this.#r(this,{level:"warn",content:t,options:this.#n})),this}info(...t){return this.#t>=e.level.info&&this.#e?.info(...this.#r(this,{level:"info",content:t,options:this.#n})),this}ok(...t){return this.#t>=e.level.info&&this.#e?.info(...this.#r(this,{level:"ok",content:t,options:this.#n})),this}log(...t){return this.#t>=e.level.log&&this.#e?.log(...this.#r(this,{level:"log",content:t,options:this.#n})),this}debug(...t){return this.#t>=e.level.debug&&this.#e?.debug(...this.#r(this,{level:"debug",content:t,options:this.#n})),this}wdebug(...t){return this.#t>=e.level.debug&&this.#e?.debug(...this.#r(this,{level:"wdebug",content:t,options:this.#n})),this}trace(...t){return this.#t>=e.level.trace&&this.#e?.debug(...this.#r(this,{level:"trace",content:t,options:this.#n})),this}probe(...e){return this.#e?.debug(...this.#r(this,{level:"probe",content:e,options:this.#n})),this}tags;with(t={}){return new e({level:this.#t,format:this.#r,output:this.#e,...this.#n,tags:{...this.tags,...t}})}#o(e=3){const t=Error,r=t.prepareStackTrace;t.prepareStackTrace=(e,t)=>t;const{stack:n}=new Error;t.prepareStackTrace=r;return n.map((e=>({file:e.getFileName(),name:e.getFunctionName(),line:e.getLineNumber(),column:e.getColumnNumber()})))[e]}static inspect(e){return globalThis.Deno?.inspect(e,{colors:!0,depth:1/0,strAbbreviateSize:1/0})??e}#r;format(t){return this.#r=("string"==typeof t?e.format[t]:t)??e.format.text,this}static format={text(t,{level:r,content:n,options:o}){const i={error:"red",warn:"orange",info:"cyan",ok:"green",log:"white",debug:"gray",wdebug:"yellow",trace:"gray",probe:"magenta"}[r],s=[`%c ${r.replace("wdebug","debug").toLocaleUpperCase().padEnd(5)} │%c`],l=[`color: black; background-color: ${i}`,""];if(o.date||o.time||o.delta){const e=(new Date).toISOString(),t=[];if(o.delta){const e=performance.now()/1e3;let r=e.toPrecision(4);e<1&&(r=e.toPrecision(2)),t.push(`+${r}`)}o.date&&o.time?t.push(e):o.date?t.push(e.slice(0,e.indexOf("T"))):o.time&&t.push(e.slice(e.indexOf("T")+1,-1)),s.push(`%c ${t.join(" ¦ ").trim()} %c`),l.push(`color: black; background-color: ${i}`,"")}if(o.caller.file||o.caller.name||o.caller.line){const e=t.#o();if(e){const t=[];if(o.caller.file){let r=`${e.file}`;Array.isArray(o.caller.fileformat)&&(r=r.replace(o.caller.fileformat[0],o.caller.fileformat[1])),t.push(r)}o.caller.name&&e.name&&t.push(e.name),o.caller.line&&t.push(e.line,e.column),s.push(`%c ${t.join(":").trim()} %c`),l.push("color: black; background-color: gray","")}}const a=[];for(const[r,n]of Object.entries(t.tags))a.push(`${r}:${e.inspect(n)}`);return s.push(`%c ${a.join(" ").trim()} %c`),l.push("background-color: black",""),[s.join(""),...l,...n.map(e.inspect)]},json(e,{level:t,content:r,options:n}){const o={level:t,timestamp:Date.now(),tags:e.tags,content:r},i={};if(n.date||n.time){const e=new Date(o.timestamp).toISOString();n.date&&(i.date=e.slice(0,e.indexOf("T"))),n.time&&(i.time=e.slice(e.indexOf("T")+1,-1))}if(n.delta&&(i.delta=performance.now()/1e3),n.caller.file||n.caller.name||n.caller.line){const t=e.#o();if(t){if(i.caller={},n.caller.file){let e=`${t.file}`;Array.isArray(n.caller.fileformat)&&(e=e.replace(n.caller.fileformat[0],n.caller.fileformat[1])),i.caller.file=e}n.caller.name&&t.name&&(i.caller.name=t.name),n.caller.line&&(i.caller.line=[t.line,t.column])}}return[JSON.stringify({...o,...i})]}}};TransformStream;function t(e){let t=0;for(const r of e)t+=r.length;const r=new Uint8Array(t);let n=0;for(const t of e)r.set(t,n),n+=t.length;return r}function r(e){const t=e.length,r=new Uint8Array(t);r[0]=0;let n=0,o=1;for(;o<t;)e[o]===e[n]?(n++,r[o]=n,o++):0===n?(r[o]=0,o++):n=r[n-1];return r}TransformStream,TransformStream,TransformStream,TransformStream,TransformStream;var n=class extends TransformStream{#i="";constructor(e={allowCR:!1}){super({transform:(t,r)=>{for(t=this.#i+t;;){const n=t.indexOf("\n"),o=e.allowCR?t.indexOf("\r"):-1;if(-1!==o&&o!==t.length-1&&(-1===n||n-1>o)){r.enqueue(t.slice(0,o)),t=t.slice(o+1);continue}if(-1===n)break;const i="\r"===t[n-1]?n-1:n;r.enqueue(t.slice(0,i)),t=t.slice(n+1)}this.#i=t},flush:t=>{if(""===this.#i)return;const r=e.allowCR&&this.#i.endsWith("\r")?this.#i.slice(0,-1):this.#i;t.enqueue(r)}})}};var o=new TextEncoder,i=new TextDecoder;function s(t,r,{logger:s=new e,stdin:a=null,stdout:c="debug",stderr:u="error",env:d,cwd:h,raw:f,callback:p,buffering:m,sync:g,throw:w,dryrun:b,winext:v="",os:y=Deno.build.os}={}){"windows"===y&&(t=`${t}${v}`),s=s.with({bin:t}),p&&"piped"!==l(a)&&(a="piped");const T=new Deno.Command(t,{args:r,stdin:g?"null":l(a),stdout:l(c),stderr:l(u),env:d,cwd:h,windowsRawArguments:f});if(b){s.wdebug(`dryrun: ${t} not executed`);const e={success:!0,code:0,stdio:[],stdin:"",stdout:"",stderr:""};return g?e:Promise.resolve(e)}return g?function(e,{bin:t,log:r,throw:n,stdout:o,stderr:s}){const a=Date.now(),c=e.outputSync(),{success:u,code:d}=c,h=Date.now()-a,f={get stdio(){return[[h,1,this.stdout],[h,2,this.stderr]]},stdin:"",stdout:"piped"===l(o)?i.decode(c.stdout):"",stderr:"piped"===l(s)?i.decode(c.stderr):""};for(const{channel:e,mode:t}of[{channel:"stdout",mode:o},{channel:"stderr",mode:s}])"piped"===l(t)&&f[e]&&r.with({t:h,channel:e})[t]?.(f[e]);if(!u&&n)throw new EvalError(`${t} exited with non-zero code ${d}:\n${f.stdout}\n${f.stderr}`);return{success:u,code:d,...f}}(T,{bin:t,log:s,throw:w,stdout:c,stderr:u}):async function(e,{bin:t,log:r,callback:i=({close:e})=>e?.(),buffering:s=250,throw:a,...c}){const u=e.spawn(),d=Date.now(),h={stdio:[],get stdin(){return this.stdio.filter((([e,t])=>0===t)).map((([e,t,r])=>r)).join("\n")},get stdout(){return this.stdio.filter((([e,t])=>1===t)).map((([e,t,r])=>r)).join("\n")},get stderr(){return this.stdio.filter((([e,t])=>2===t)).map((([e,t,r])=>r)).join("\n")}},f={};let p="";const m=function(e,t){let r=null,n=null;const o=(...i)=>{o.clear(),n=()=>{o.clear(),e.call(o,...i)},r=Number(setTimeout(n,t))};return o.clear=()=>{"number"==typeof r&&(clearTimeout(r),r=null,n=null)},o.flush=()=>{n?.()},Object.defineProperty(o,"pending",{get:()=>"number"==typeof r}),o}((async e=>{r.with({t:e}).trace("debounced"),p="",await i({stdio:h,i:h.stdin.length,...f})}),s);if("piped"===l(c.stdin)){const e=u.stdin.getWriter();Object.assign(f,{async write(t,n=!0){const i=Date.now()-d;c.stdin&&r.with({t:i,channel:"stdin"})[c.stdin]?.(t),h.stdio.push([i,0,t]),n&&!t.endsWith("\n")&&(t+="\n"),await e.write(o.encode(t)),p="stdin",e.releaseLock()},async close(){try{e.releaseLock(),await u.stdin.close(),r.with({t:Date.now()-d,closed:"stdin"}).trace()}catch{}},async wait(e=1e3){const t=Date.now()-d;r.with({t:t,waiting:e}).trace(),await function(e,t={}){const{signal:r,persistent:n=!0}=t;return r?.aborted?Promise.reject(r.reason):new Promise(((t,o)=>{const i=()=>{clearTimeout(s),o(r?.reason)},s=setTimeout((()=>{r?.removeEventListener("abort",i),t()}),e);if(r?.addEventListener("abort",i,{once:!0}),!1===n)try{Deno.unrefTimer(s)}catch(e){if(!(e instanceof ReferenceError))throw e;console.error("`persistent` option is only available in Deno")}}))}(e),m(t)}}),m(Date.now()-d)}await Promise.all(["stdout","stderr"].filter((e=>"piped"===l(c[e]))).map((async e=>{for await(const t of u[e].pipeThrough(new TextDecoderStream).pipeThrough(new n)){const n=Date.now()-d,o={stdout:1,stderr:2}[e];if(c[e]&&r.with({t:n,channel:e})[c[e]]?.(t),h.stdio.length&&p===e){const e=h.stdio.at(-1);e[1]===o&&(e[2]+=`\n${t}`)}else h.stdio.push([n,o,t]);p=e,m(n)}}))),m.flush();const{success:g,code:w}=await u.status;if(!g&&a)throw new EvalError(`${t} exited with non-zero code ${w}:\n${h.stdout}\n${h.stderr}`);return{success:g,code:w,...h}}(T,{bin:t,log:s,callback:p,buffering:m,throw:w,stdin:"piped"===l(a)?a:null,stdout:"piped"===l(c)?c:null,stderr:"piped"===l(u)?u:null})}function l(e){return["inherit","null"].includes(`${e}`)?`${e}`:"piped"}export{s as command};
package/deno.jsonc CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "icon": "⏯️",
3
3
  "name": "@libs/run",
4
- "version": "2.0.1",
4
+ "version": "2.0.3",
5
5
  "description": "Utilities to run subprocess.",
6
6
  "keywords": [
7
7
  "subprocess",
@@ -25,9 +25,9 @@
25
25
  "./command": "./command.ts"
26
26
  },
27
27
  "imports": {
28
- "@std/async/delay": "jsr:@std/async@0.224.2/delay",
29
- "@std/async/debounce": "jsr:@std/async@0.224.2/debounce",
30
- "@std/streams": "jsr:@std/streams@0.224.5",
28
+ "@std/async/delay": "jsr:@std/async@1/delay",
29
+ "@std/async/debounce": "jsr:@std/async@1/debounce",
30
+ "@std/streams": "jsr:@std/streams@1",
31
31
  "@libs/logger": "jsr:@libs/logger@2",
32
32
  "@libs/testing": "jsr:@libs/testing@2",
33
33
  "@libs/typing": "jsr:@libs/typing@2"
package/deno.lock CHANGED
@@ -2,99 +2,64 @@
2
2
  "version": "3",
3
3
  "packages": {
4
4
  "specifiers": {
5
- "jsr:@libs/logger": "jsr:@libs/logger@2.0.1",
6
- "jsr:@libs/logger@1.1.3": "jsr:@libs/logger@1.1.3",
7
- "jsr:@libs/logger@2": "jsr:@libs/logger@2.0.1",
8
- "jsr:@libs/run@1": "jsr:@libs/run@1.0.3",
9
- "jsr:@libs/testing@2": "jsr:@libs/testing@2.0.0",
10
- "jsr:@libs/typing@2": "jsr:@libs/typing@2.6.0",
11
- "jsr:@std/assert@0.226.0": "jsr:@std/assert@0.226.0",
12
- "jsr:@std/assert@1.0.0-rc.2": "jsr:@std/assert@1.0.0-rc.2",
13
- "jsr:@std/async@0.224.2": "jsr:@std/async@0.224.2",
14
- "jsr:@std/bytes@^1.0.0-rc.3": "jsr:@std/bytes@1.0.1",
15
- "jsr:@std/bytes@^1.0.1-rc.3": "jsr:@std/bytes@1.0.1",
16
- "jsr:@std/expect@0.224.5": "jsr:@std/expect@0.224.5",
17
- "jsr:@std/http@0.224.5": "jsr:@std/http@0.224.5",
18
- "jsr:@std/internal@^1.0.0": "jsr:@std/internal@1.0.1",
19
- "jsr:@std/io@^0.224.1": "jsr:@std/io@0.224.3",
20
- "jsr:@std/path@0.225.2": "jsr:@std/path@0.225.2",
21
- "jsr:@std/streams@0.224.5": "jsr:@std/streams@0.224.5"
5
+ "jsr:@libs/logger": "jsr:@libs/logger@2.1.1",
6
+ "jsr:@libs/logger@2": "jsr:@libs/logger@2.1.1",
7
+ "jsr:@libs/testing@2": "jsr:@libs/testing@2.2.4",
8
+ "jsr:@libs/typing@2": "jsr:@libs/typing@2.8.2",
9
+ "jsr:@std/assert@1": "jsr:@std/assert@1.0.2",
10
+ "jsr:@std/assert@^1.0.1": "jsr:@std/assert@1.0.2",
11
+ "jsr:@std/async@1": "jsr:@std/async@1.0.3",
12
+ "jsr:@std/bytes@^1.0.2-rc.3": "jsr:@std/bytes@1.0.2",
13
+ "jsr:@std/expect@1": "jsr:@std/expect@1.0.0",
14
+ "jsr:@std/http@1": "jsr:@std/http@1.0.3",
15
+ "jsr:@std/internal@^1.0.1": "jsr:@std/internal@1.0.1",
16
+ "jsr:@std/streams@1": "jsr:@std/streams@1.0.2"
22
17
  },
23
18
  "jsr": {
24
- "@libs/logger@1.1.3": {
25
- "integrity": "a359d5ce4aa9f2508b1515ad6f48f41e9dfbc2250ebaa1fd9059930b3a9bab3a"
19
+ "@libs/logger@2.1.1": {
20
+ "integrity": "508216c245aa7a13d55972cec6cf2ff45b341469334634a2748cd60c938677d6"
26
21
  },
27
- "@libs/logger@2.0.1": {
28
- "integrity": "b712d36396dfbd8018af092afdba919afc1f92062d11ce27a83724fe7eb22b13"
29
- },
30
- "@libs/run@1.0.3": {
31
- "integrity": "21eeabe1f8fdcc8d5ebb20e950bc8de3142eb74b6edaa2281572ce890ce1f5a0",
32
- "dependencies": [
33
- "jsr:@libs/logger@1.1.3",
34
- "jsr:@libs/typing@2",
35
- "jsr:@std/async@0.224.2",
36
- "jsr:@std/streams@0.224.5"
37
- ]
38
- },
39
- "@libs/testing@2.0.0": {
40
- "integrity": "a1cb40f127ec8ab3a37814beb13ff604b5aacbf9da633b413b243b7fcbd2309a",
22
+ "@libs/testing@2.2.4": {
23
+ "integrity": "3ef407b62cf18424b3e2e604eef5df81d3c07cf8adb4b78ab4cf40db2a029f2c",
41
24
  "dependencies": [
42
- "jsr:@libs/run@1",
43
25
  "jsr:@libs/typing@2",
44
- "jsr:@std/assert@0.226.0",
45
- "jsr:@std/expect@0.224.5",
46
- "jsr:@std/http@0.224.5",
47
- "jsr:@std/path@0.225.2"
26
+ "jsr:@std/assert@1",
27
+ "jsr:@std/expect@1",
28
+ "jsr:@std/http@1"
48
29
  ]
49
30
  },
50
- "@libs/typing@2.6.0": {
51
- "integrity": "07a1ee52fa6d769d68d95d7310bac7dd608932c91760a0bc8a95ce6de3630603"
52
- },
53
- "@std/assert@0.226.0": {
54
- "integrity": "0dfb5f7c7723c18cec118e080fec76ce15b4c31154b15ad2bd74822603ef75b3",
55
- "dependencies": [
56
- "jsr:@std/internal@^1.0.0"
57
- ]
31
+ "@libs/typing@2.8.2": {
32
+ "integrity": "c53f8aad9b01621de893aeac5d6cd592ec2ce783f8e89b677dcd81490a3be0a0"
58
33
  },
59
- "@std/assert@1.0.0-rc.2": {
60
- "integrity": "0484eab1d76b55fca1c3beaff485a274e67dd3b9f065edcbe70030dfc0b964d3",
34
+ "@std/assert@1.0.2": {
35
+ "integrity": "ccacec332958126deaceb5c63ff8b4eaf9f5ed0eac9feccf124110435e59e49c",
61
36
  "dependencies": [
62
- "jsr:@std/internal@^1.0.0"
37
+ "jsr:@std/internal@^1.0.1"
63
38
  ]
64
39
  },
65
- "@std/async@0.224.2": {
66
- "integrity": "4d277d6e165df43d5e061ba0ef3edfddb8e8d558f5b920e3e6b1d2614b44d074"
40
+ "@std/async@1.0.3": {
41
+ "integrity": "6ed64678db43451683c6c176a21426a2ccd21ba0269ebb2c36133ede3f165792"
67
42
  },
68
- "@std/bytes@1.0.1": {
69
- "integrity": "e57c9b243932b95a4c3672f8a038cdadea7492efeeb6b8a774844fee70426815"
43
+ "@std/bytes@1.0.2": {
44
+ "integrity": "fbdee322bbd8c599a6af186a1603b3355e59a5fb1baa139f8f4c3c9a1b3e3d57"
70
45
  },
71
- "@std/expect@0.224.5": {
72
- "integrity": "ae6e57ee6f23a2fd5ae130cb84448eef182354cb902e1a2a98d64c72ac3a5a1c",
46
+ "@std/expect@1.0.0": {
47
+ "integrity": "030275683c23d6708878c5439a3ffd99285948d708e00835fd38fcef9a0bb921",
73
48
  "dependencies": [
74
- "jsr:@std/assert@1.0.0-rc.2",
75
- "jsr:@std/internal@^1.0.0"
49
+ "jsr:@std/assert@^1.0.1",
50
+ "jsr:@std/internal@^1.0.1"
76
51
  ]
77
52
  },
78
- "@std/http@0.224.5": {
79
- "integrity": "b03b5d1529f6c423badfb82f6640f9f2557b4034cd7c30655ba5bb447ff750a4"
53
+ "@std/http@1.0.3": {
54
+ "integrity": "bff3770c4df4711567de1711fe988d28db9535be0c9b0f1d2de8d0fb97e8b44c"
80
55
  },
81
56
  "@std/internal@1.0.1": {
82
57
  "integrity": "6f8c7544d06a11dd256c8d6ba54b11ed870aac6c5aeafff499892662c57673e6"
83
58
  },
84
- "@std/io@0.224.3": {
85
- "integrity": "b402edeb99c6b3778d9ae3e9927bc9085b170b41e5a09bbb7064ab2ee394ae2f",
86
- "dependencies": [
87
- "jsr:@std/bytes@^1.0.1-rc.3"
88
- ]
89
- },
90
- "@std/path@0.225.2": {
91
- "integrity": "0f2db41d36b50ef048dcb0399aac720a5348638dd3cb5bf80685bf2a745aa506"
92
- },
93
- "@std/streams@0.224.5": {
94
- "integrity": "bcde7818dd5460d474cdbd674b15f6638b9cd73cd64e52bd852fba2bd4d8ec91",
59
+ "@std/streams@1.0.2": {
60
+ "integrity": "187c3c875675221f5355807a735e51b0f8769caade2cbca6d7f4fa710ea4ace4",
95
61
  "dependencies": [
96
- "jsr:@std/bytes@^1.0.0-rc.3",
97
- "jsr:@std/io@^0.224.1"
62
+ "jsr:@std/bytes@^1.0.2-rc.3"
98
63
  ]
99
64
  }
100
65
  }
@@ -105,8 +70,8 @@
105
70
  "jsr:@libs/logger@2",
106
71
  "jsr:@libs/testing@2",
107
72
  "jsr:@libs/typing@2",
108
- "jsr:@std/async@0.224.2",
109
- "jsr:@std/streams@0.224.5"
73
+ "jsr:@std/async@1",
74
+ "jsr:@std/streams@1"
110
75
  ]
111
76
  }
112
77
  }
package/mod.mjs CHANGED
@@ -1,90 +1 @@
1
- var e=class e{constructor({level:t,format:n,output:r,tags:o,...i}={}){"granted"===globalThis.Deno?.permissions.querySync?.({name:"env",variable:"LOG_LEVEL"}).state&&(t??=globalThis.Deno?.env.get("LOG_LEVEL")),this.#e=r||null===r?r:console,this.#t=e.level.log,this.#n=e.format.text,this.#r={date:!1,time:!1,delta:!0,caller:{file:!1,name:!1,line:!1,fileformat:null}},this.level(t).format(n).options(i),this.tags=o??{}}#e;#r;options(e){if(!e)return structuredClone(this.#r);if("date"in e&&(this.#r.date=e.date),"time"in e&&(this.#r.time=e.time),"delta"in e&&(this.#r.delta=e.delta),"caller"in e)switch(!0){case!0===e.caller:this.#r.caller={file:!0,name:!0,line:!0,fileformat:this.#r.caller.fileformat};break;case!1===e.caller:this.#r.caller={file:!1,name:!1,line:!1,fileformat:this.#r.caller.fileformat};break;case"object"==typeof e.caller:"file"in e.caller&&(this.#r.caller.file=e.caller.file),"name"in e.caller&&(this.#r.caller.name=e.caller.name),"line"in e.caller&&(this.#r.caller.line=e.caller.line),"fileformat"in e.caller&&void 0!==e.caller.fileformat&&(this.#r.caller.fileformat=e.caller.fileformat)}return this}#t;level(t){return arguments.length?(Number.isNaN(Number.parseInt(`${t}`))||(t=Number.parseInt(`${t}`)),"string"==typeof t&&t in e.level&&(t=e.level[t]),"number"==typeof t&&(this.#t=!Number.isNaN(t)&&t>=0?t:-1),this):this.#t>=0?this.#t:NaN}static level=Object.freeze({disabled:NaN,error:0,warn:1,info:2,ok:2,log:3,debug:4,wdebug:4,trace:5,probe:NaN,always:1/0});error(...t){return this.#t>=e.level.error&&this.#e?.error(...this.#n(this,{level:"error",content:t,options:this.#r})),this}warn(...t){return this.#t>=e.level.warn&&this.#e?.warn(...this.#n(this,{level:"warn",content:t,options:this.#r})),this}info(...t){return this.#t>=e.level.info&&this.#e?.info(...this.#n(this,{level:"info",content:t,options:this.#r})),this}ok(...t){return this.#t>=e.level.info&&this.#e?.info(...this.#n(this,{level:"ok",content:t,options:this.#r})),this}log(...t){return this.#t>=e.level.log&&this.#e?.log(...this.#n(this,{level:"log",content:t,options:this.#r})),this}debug(...t){return this.#t>=e.level.debug&&this.#e?.debug(...this.#n(this,{level:"debug",content:t,options:this.#r})),this}wdebug(...t){return this.#t>=e.level.debug&&this.#e?.debug(...this.#n(this,{level:"wdebug",content:t,options:this.#r})),this}trace(...t){return this.#t>=e.level.trace&&this.#e?.debug(...this.#n(this,{level:"trace",content:t,options:this.#r})),this}probe(...e){return this.#e?.debug(...this.#n(this,{level:"probe",content:e,options:this.#r})),this}tags;with(t={}){return new e({level:this.#t,format:this.#n,output:this.#e,...this.#r,tags:{...this.tags,...t}})}#o(e=3){const t=Error,n=t.prepareStackTrace;t.prepareStackTrace=(e,t)=>t;const{stack:r}=new Error;t.prepareStackTrace=n;return r.map((e=>({file:e.getFileName(),name:e.getFunctionName(),line:e.getLineNumber(),column:e.getColumnNumber()})))[e]}static inspect(e){return globalThis.Deno?.inspect(e,{colors:!0,depth:1/0,strAbbreviateSize:1/0})??e}#n;format(t){return this.#n=("string"==typeof t?e.format[t]:t)??e.format.text,this}static format={text(t,{level:n,content:r,options:o}){const i={error:"red",warn:"orange",info:"cyan",ok:"green",log:"white",debug:"gray",wdebug:"yellow",trace:"gray",probe:"magenta"}[n],s=[`%c ${n.replace("wdebug","debug").toLocaleUpperCase().padEnd(5)} │%c`],l=[`color: black; background-color: ${i}`,""];if(o.date||o.time||o.delta){const e=(new Date).toISOString(),t=[];if(o.delta){const e=performance.now()/1e3;let n=e.toPrecision(4);e<1&&(n=e.toPrecision(2)),t.push(`+${n}`)}o.date&&o.time?t.push(e):o.date?t.push(e.slice(0,e.indexOf("T"))):o.time&&t.push(e.slice(e.indexOf("T")+1,-1)),s.push(`%c ${t.join(" ¦ ").trim()} %c`),l.push(`color: black; background-color: ${i}`,"")}if(o.caller.file||o.caller.name||o.caller.line){const e=t.#o();if(e){const t=[];if(o.caller.file){let n=`${e.file}`;Array.isArray(o.caller.fileformat)&&(n=n.replace(o.caller.fileformat[0],o.caller.fileformat[1])),t.push(n)}o.caller.name&&e.name&&t.push(e.name),o.caller.line&&t.push(e.line,e.column),s.push(`%c ${t.join(":").trim()} %c`),l.push("color: black; background-color: gray","")}}const a=[];for(const[n,r]of Object.entries(t.tags))a.push(`${n}:${e.inspect(r)}`);return s.push(`%c ${a.join(" ").trim()} %c`),l.push("background-color: black",""),[s.join(""),...l,...r.map(e.inspect)]},json(e,{level:t,content:n,options:r}){const o={level:t,timestamp:Date.now(),tags:e.tags,content:n},i={};if(r.date||r.time){const e=new Date(o.timestamp).toISOString();r.date&&(i.date=e.slice(0,e.indexOf("T"))),r.time&&(i.time=e.slice(e.indexOf("T")+1,-1))}if(r.delta&&(i.delta=performance.now()/1e3),r.caller.file||r.caller.name||r.caller.line){const t=e.#o();if(t){if(i.caller={},r.caller.file){let e=`${t.file}`;Array.isArray(r.caller.fileformat)&&(e=e.replace(r.caller.fileformat[0],r.caller.fileformat[1])),i.caller.file=e}r.caller.name&&t.name&&(i.caller.name=t.name),r.caller.line&&(i.caller.line=[t.line,t.column])}}return[JSON.stringify({...o,...i})]}}};TransformStream;function t(e){let t=0;for(const n of e)t+=n.length;const n=new Uint8Array(t);let r=0;for(const t of e)n.set(t,r),r+=t.length;return n}function n(e){const t=e.length,n=new Uint8Array(t);n[0]=0;let r=0,o=1;for(;o<t;)e[o]===e[r]?(r++,n[o]=r,o++):0===r?(n[o]=0,o++):r=n[r-1];return n}TransformStream,TransformStream,TransformStream,TransformStream;var r=class extends TransformStream{#i="";constructor(e={allowCR:!1}){super({transform:(t,n)=>{for(t=this.#i+t;;){const r=t.indexOf("\n"),o=e.allowCR?t.indexOf("\r"):-1;if(-1!==o&&o!==t.length-1&&(-1===r||r-1>o)){n.enqueue(t.slice(0,o)),t=t.slice(o+1);continue}if(-1===r)break;const i="\r"===t[r-1]?r-1:r;n.enqueue(t.slice(0,i)),t=t.slice(r+1)}this.#i=t},flush:t=>{if(""===this.#i)return;const n=e.allowCR&&this.#i.endsWith("\r")?this.#i.slice(0,-1):this.#i;t.enqueue(n)}})}};new TextDecoder;var o=new TextEncoder,i=new TextDecoder;function s(t,n,{logger:s=new e,stdin:a=null,stdout:c="debug",stderr:u="error",env:d,cwd:h,raw:f,callback:p,buffering:m,sync:g,throw:w,dryrun:b,winext:v="",os:y=Deno.build.os}={}){"windows"===y&&(t=`${t}${v}`),s=s.with({bin:t}),p&&"piped"!==l(a)&&(a="piped");const T=new Deno.Command(t,{args:n,stdin:g?"null":l(a),stdout:l(c),stderr:l(u),env:d,cwd:h,windowsRawArguments:f});if(b){s.wdebug(`dryrun: ${t} not executed`);const e={success:!0,code:0,stdio:[],stdin:"",stdout:"",stderr:""};return g?e:Promise.resolve(e)}return g?function(e,{bin:t,log:n,throw:r,stdout:o,stderr:s}){const a=Date.now(),c=e.outputSync(),{success:u,code:d}=c,h=Date.now()-a,f={get stdio(){return[[h,1,this.stdout],[h,2,this.stderr]]},stdin:"",stdout:"piped"===l(o)?i.decode(c.stdout):"",stderr:"piped"===l(s)?i.decode(c.stderr):""};for(const{channel:e,mode:t}of[{channel:"stdout",mode:o},{channel:"stderr",mode:s}])"piped"===l(t)&&f[e]&&n.with({t:h,channel:e})[t]?.(f[e]);if(!u&&r)throw new EvalError(`${t} exited with non-zero code ${d}:\n${f.stdout}\n${f.stderr}`);return{success:u,code:d,...f}}(T,{bin:t,log:s,throw:w,stdout:c,stderr:u}):async function(e,{bin:t,log:n,callback:i=({close:e})=>e?.(),buffering:s=250,throw:a,...c}){const u=e.spawn(),d=Date.now(),h={stdio:[],get stdin(){return this.stdio.filter((([e,t])=>0===t)).map((([e,t,n])=>n)).join("\n")},get stdout(){return this.stdio.filter((([e,t])=>1===t)).map((([e,t,n])=>n)).join("\n")},get stderr(){return this.stdio.filter((([e,t])=>2===t)).map((([e,t,n])=>n)).join("\n")}},f={};let p="";const m=function(e,t){let n=null,r=null;const o=(...i)=>{o.clear(),r=()=>{o.clear(),e.call(o,...i)},n=setTimeout(r,t)};return o.clear=()=>{"number"==typeof n&&(clearTimeout(n),n=null,r=null)},o.flush=()=>{r?.()},Object.defineProperty(o,"pending",{get:()=>"number"==typeof n}),o}((async e=>{n.with({t:e}).trace("debounced"),p="",await i({stdio:h,i:h.stdin.length,...f})}),s);if("piped"===l(c.stdin)){const e=u.stdin.getWriter();Object.assign(f,{async write(t,r=!0){const i=Date.now()-d;c.stdin&&n.with({t:i,channel:"stdin"})[c.stdin]?.(t),h.stdio.push([i,0,t]),r&&!t.endsWith("\n")&&(t+="\n"),await e.write(o.encode(t)),p="stdin",e.releaseLock()},async close(){try{e.releaseLock(),await u.stdin.close(),n.with({t:Date.now()-d,closed:"stdin"}).trace()}catch{}},async wait(e=1e3){const t=Date.now()-d;n.with({t:t,waiting:e}).trace(),await function(e,t={}){const{signal:n,persistent:r=!0}=t;return n?.aborted?Promise.reject(n.reason):new Promise(((t,o)=>{const i=()=>{clearTimeout(s),o(n?.reason)},s=setTimeout((()=>{n?.removeEventListener("abort",i),t()}),e);if(n?.addEventListener("abort",i,{once:!0}),!1===r)try{Deno.unrefTimer(s)}catch(e){if(!(e instanceof ReferenceError))throw e;console.error("`persistent` option is only available in Deno")}}))}(e),m(t)}}),m(Date.now()-d)}await Promise.all(["stdout","stderr"].filter((e=>"piped"===l(c[e]))).map((async e=>{for await(const t of u[e].pipeThrough(new TextDecoderStream).pipeThrough(new r)){const r=Date.now()-d,o={stdout:1,stderr:2}[e];if(c[e]&&n.with({t:r,channel:e})[c[e]]?.(t),h.stdio.length&&p===e){const e=h.stdio.at(-1);e[1]===o&&(e[2]+=`\n${t}`)}else h.stdio.push([r,o,t]);p=e,m(r)}}))),m.flush();const{success:g,code:w}=await u.status;if(!g&&a)throw new EvalError(`${t} exited with non-zero code ${w}:\n${h.stdout}\n${h.stderr}`);return{success:g,code:w,...h}}(T,{bin:t,log:s,callback:p,buffering:m,throw:w,stdin:"piped"===l(a)?a:null,stdout:"piped"===l(c)?c:null,stderr:"piped"===l(u)?u:null})}function l(e){return["inherit","null"].includes(`${e}`)?`${e}`:"piped"}export{s as command};
2
- /**
3
- * Logger class.
4
- *
5
- * This class provides a simple and efficient logging framework intended to supersed the native {@link https://developer.mozilla.org/en-US/docs/Web/API/console | console} by providing additional features and metadata.
6
- *
7
- * It supports out-of-the-box colored output, a log level mechanism (that honor `LOG_LEVEL` environment variable), a tag system, and a variety of options to customize the output.
8
- * A neat addition is the ability to display caller information (file, name, line) which can be especially useful for debugging.
9
- *
10
- * @example
11
- * ```ts
12
- * import { Logger } from "./mod.ts"
13
- *
14
- * // Configure logger
15
- * const tags = { foo: "bar" }
16
- * const log = new Logger({ level: "trace", tags, date: true, time: true, delta:true, caller:true })
17
- *
18
- * // Print logs
19
- * log
20
- * .error("🍱 bento")
21
- * .warn("🍜 ramen")
22
- * .ok("🍚 gohan")
23
- * .info("🍣 sushi")
24
- * .log("🍥 narutomaki")
25
- * .debug("🍡 dango")
26
- * .wdebug("🍵 matcha")
27
- * .trace("🍙 onigiri")
28
- * .probe("🥟 gyoza")
29
- *
30
- * // Create a new inherited logger with additional tags
31
- * log.with({ bar: "true" }).log("🍶 sake")
32
- * ```
33
- *
34
- * @author Simon Lecoq (lowlighter)
35
- * @license MIT
36
- */
37
- /**
38
- * Run a command.
39
- *
40
- * This is a wrapper around {@link https://docs.deno.com/api/deno/~/Deno.Command | Deno.command} that provides a better handling of stdio for interactive processes.
41
- *
42
- * Like `Deno.command`, the `env`, `cwd`, and `raw` (alias for `windowsRawArguments`) options are supported.
43
- *
44
- * The `stdin`, `stdout` and `stderr` options can be either set to an allowed {@link https://docs.deno.com/api/deno/~/Deno.Command | Deno.command} values (`"inherit"`, `"null"`, `"piped"`), or either to a supported log level of {@link Logger}.
45
- * In the later case, the content will be always be "piped" and logged to the specified level of the provided {@link Logger} instance.
46
- *
47
- * Set `winext` option to automatically append an extension to the binary path on Windows (like `.cmd` or `.exe`).
48
- * This is useful when the binary path isn't automatically resolved on Windows.
49
- *
50
- * Pass a `callback` option to interact with the process stdin and stdout.
51
- * It is called each time data is received on of the piped channels, after input buffering.
52
- * It will receive an object with the current stdio content, the current command index (based on the content written to stdin), along with a few additional functions:
53
- * - `write(content: string, newline?: boolean): Promise<void>` encodes and writes content to stdin.
54
- * - A newline is automatically appended by default but can be toggled off by passing `false` as second argument.
55
- * - `close(): Promise<void>` closes stdin.
56
- * - Note that you **need** to eventually call this method to prevent most processes from hanging as they're waiting for more input.
57
- * - `wait(dt: number): Promise<void>` waits for a given amount of time before calling the callback again.
58
- * - It is especially useful for polling, like checking if a specific line has been written to stdio or not.
59
- *
60
- * The `buffering` option is used to merge messages that are received relatively closely.
61
- * Setting this option to a low value will also increase the rate at which the `callback` is called.
62
- *
63
- * Resulting object contains the same properties as {@link https://docs.deno.com/api/deno/~/Deno.CommandStatus | Deno.CommandStatus}
64
- * with an additional `stdio` property that contains an array of ordered tuples with the delta timestamp since process start, the channel idenfitier (0:stdin, 1:stdout, 2:stderr) and the content.
65
- * This offers a proper history of exchanged content.
66
- *
67
- * @example
68
- * ```ts
69
- * import { command } from "./command.ts"
70
- * import { Logger } from "jsr:@libs/logger"
71
- * await command("deno", ["version"], { env: { NO_COLOR: "true" }, cwd: "/tmp", raw: true })
72
- * await command("deno", ["version"], { stdout: "piped" })
73
- * await command("deno", ["version"], { logger: new Logger(), stdout: "debug" })
74
- * await command("deno", ["version"], { winext: ".exe" })
75
- * ```
76
- *
77
- * @example
78
- * ```ts
79
- * import { command } from "./command.ts"
80
- * const { stdout } = await command("deno", ["repl"], {
81
- * env: { NO_COLOR: "true" },
82
- * callback: ({ i, write, close }) => i === 0 ? write("console.log('hello')") : close(),
83
- * })
84
- * console.assert(stdout.includes("hello"))
85
- * ```
86
- *
87
- * @author Simon Lecoq (lowlighter)
88
- * @license MIT
89
- * @module
90
- */
1
+ var e=class e{constructor({level:t,format:r,output:n,tags:o,...i}={}){"granted"===globalThis.Deno?.permissions.querySync?.({name:"env",variable:"LOG_LEVEL"}).state&&(t??=globalThis.Deno?.env.get("LOG_LEVEL")),this.#e=n||null===n?n:console,this.#t=e.level.log,this.#r=e.format.text,this.#n={date:!1,time:!1,delta:!0,caller:{file:!1,name:!1,line:!1,fileformat:null}},this.level(t).format(r).options(i),this.tags=o??{}}#e;#n;options(e){if(!e)return structuredClone(this.#n);if("date"in e&&(this.#n.date=e.date),"time"in e&&(this.#n.time=e.time),"delta"in e&&(this.#n.delta=e.delta),"caller"in e)switch(!0){case!0===e.caller:this.#n.caller={file:!0,name:!0,line:!0,fileformat:this.#n.caller.fileformat};break;case!1===e.caller:this.#n.caller={file:!1,name:!1,line:!1,fileformat:this.#n.caller.fileformat};break;case"object"==typeof e.caller:"file"in e.caller&&(this.#n.caller.file=e.caller.file),"name"in e.caller&&(this.#n.caller.name=e.caller.name),"line"in e.caller&&(this.#n.caller.line=e.caller.line),"fileformat"in e.caller&&void 0!==e.caller.fileformat&&(this.#n.caller.fileformat=e.caller.fileformat)}return this}#t;level(t){return arguments.length?(Number.isNaN(Number.parseInt(`${t}`))||(t=Number.parseInt(`${t}`)),"string"==typeof t&&t in e.level&&(t=e.level[t]),"number"==typeof t&&(this.#t=!Number.isNaN(t)&&t>=0?t:-1),this):this.#t>=0?this.#t:NaN}static level=Object.freeze({disabled:NaN,error:0,warn:1,info:2,ok:2,log:3,debug:4,wdebug:4,trace:5,probe:NaN,always:1/0});error(...t){return this.#t>=e.level.error&&this.#e?.error(...this.#r(this,{level:"error",content:t,options:this.#n})),this}warn(...t){return this.#t>=e.level.warn&&this.#e?.warn(...this.#r(this,{level:"warn",content:t,options:this.#n})),this}info(...t){return this.#t>=e.level.info&&this.#e?.info(...this.#r(this,{level:"info",content:t,options:this.#n})),this}ok(...t){return this.#t>=e.level.info&&this.#e?.info(...this.#r(this,{level:"ok",content:t,options:this.#n})),this}log(...t){return this.#t>=e.level.log&&this.#e?.log(...this.#r(this,{level:"log",content:t,options:this.#n})),this}debug(...t){return this.#t>=e.level.debug&&this.#e?.debug(...this.#r(this,{level:"debug",content:t,options:this.#n})),this}wdebug(...t){return this.#t>=e.level.debug&&this.#e?.debug(...this.#r(this,{level:"wdebug",content:t,options:this.#n})),this}trace(...t){return this.#t>=e.level.trace&&this.#e?.debug(...this.#r(this,{level:"trace",content:t,options:this.#n})),this}probe(...e){return this.#e?.debug(...this.#r(this,{level:"probe",content:e,options:this.#n})),this}tags;with(t={}){return new e({level:this.#t,format:this.#r,output:this.#e,...this.#n,tags:{...this.tags,...t}})}#o(e=3){const t=Error,r=t.prepareStackTrace;t.prepareStackTrace=(e,t)=>t;const{stack:n}=new Error;t.prepareStackTrace=r;return n.map((e=>({file:e.getFileName(),name:e.getFunctionName(),line:e.getLineNumber(),column:e.getColumnNumber()})))[e]}static inspect(e){return globalThis.Deno?.inspect(e,{colors:!0,depth:1/0,strAbbreviateSize:1/0})??e}#r;format(t){return this.#r=("string"==typeof t?e.format[t]:t)??e.format.text,this}static format={text(t,{level:r,content:n,options:o}){const i={error:"red",warn:"orange",info:"cyan",ok:"green",log:"white",debug:"gray",wdebug:"yellow",trace:"gray",probe:"magenta"}[r],s=[`%c ${r.replace("wdebug","debug").toLocaleUpperCase().padEnd(5)} │%c`],l=[`color: black; background-color: ${i}`,""];if(o.date||o.time||o.delta){const e=(new Date).toISOString(),t=[];if(o.delta){const e=performance.now()/1e3;let r=e.toPrecision(4);e<1&&(r=e.toPrecision(2)),t.push(`+${r}`)}o.date&&o.time?t.push(e):o.date?t.push(e.slice(0,e.indexOf("T"))):o.time&&t.push(e.slice(e.indexOf("T")+1,-1)),s.push(`%c ${t.join(" ¦ ").trim()} %c`),l.push(`color: black; background-color: ${i}`,"")}if(o.caller.file||o.caller.name||o.caller.line){const e=t.#o();if(e){const t=[];if(o.caller.file){let r=`${e.file}`;Array.isArray(o.caller.fileformat)&&(r=r.replace(o.caller.fileformat[0],o.caller.fileformat[1])),t.push(r)}o.caller.name&&e.name&&t.push(e.name),o.caller.line&&t.push(e.line,e.column),s.push(`%c ${t.join(":").trim()} %c`),l.push("color: black; background-color: gray","")}}const a=[];for(const[r,n]of Object.entries(t.tags))a.push(`${r}:${e.inspect(n)}`);return s.push(`%c ${a.join(" ").trim()} %c`),l.push("background-color: black",""),[s.join(""),...l,...n.map(e.inspect)]},json(e,{level:t,content:r,options:n}){const o={level:t,timestamp:Date.now(),tags:e.tags,content:r},i={};if(n.date||n.time){const e=new Date(o.timestamp).toISOString();n.date&&(i.date=e.slice(0,e.indexOf("T"))),n.time&&(i.time=e.slice(e.indexOf("T")+1,-1))}if(n.delta&&(i.delta=performance.now()/1e3),n.caller.file||n.caller.name||n.caller.line){const t=e.#o();if(t){if(i.caller={},n.caller.file){let e=`${t.file}`;Array.isArray(n.caller.fileformat)&&(e=e.replace(n.caller.fileformat[0],n.caller.fileformat[1])),i.caller.file=e}n.caller.name&&t.name&&(i.caller.name=t.name),n.caller.line&&(i.caller.line=[t.line,t.column])}}return[JSON.stringify({...o,...i})]}}};TransformStream;function t(e){let t=0;for(const r of e)t+=r.length;const r=new Uint8Array(t);let n=0;for(const t of e)r.set(t,n),n+=t.length;return r}function r(e){const t=e.length,r=new Uint8Array(t);r[0]=0;let n=0,o=1;for(;o<t;)e[o]===e[n]?(n++,r[o]=n,o++):0===n?(r[o]=0,o++):n=r[n-1];return r}TransformStream,TransformStream,TransformStream,TransformStream,TransformStream;var n=class extends TransformStream{#i="";constructor(e={allowCR:!1}){super({transform:(t,r)=>{for(t=this.#i+t;;){const n=t.indexOf("\n"),o=e.allowCR?t.indexOf("\r"):-1;if(-1!==o&&o!==t.length-1&&(-1===n||n-1>o)){r.enqueue(t.slice(0,o)),t=t.slice(o+1);continue}if(-1===n)break;const i="\r"===t[n-1]?n-1:n;r.enqueue(t.slice(0,i)),t=t.slice(n+1)}this.#i=t},flush:t=>{if(""===this.#i)return;const r=e.allowCR&&this.#i.endsWith("\r")?this.#i.slice(0,-1):this.#i;t.enqueue(r)}})}};var o=new TextEncoder,i=new TextDecoder;function s(t,r,{logger:s=new e,stdin:a=null,stdout:c="debug",stderr:u="error",env:d,cwd:h,raw:f,callback:p,buffering:m,sync:g,throw:w,dryrun:b,winext:v="",os:y=Deno.build.os}={}){"windows"===y&&(t=`${t}${v}`),s=s.with({bin:t}),p&&"piped"!==l(a)&&(a="piped");const T=new Deno.Command(t,{args:r,stdin:g?"null":l(a),stdout:l(c),stderr:l(u),env:d,cwd:h,windowsRawArguments:f});if(b){s.wdebug(`dryrun: ${t} not executed`);const e={success:!0,code:0,stdio:[],stdin:"",stdout:"",stderr:""};return g?e:Promise.resolve(e)}return g?function(e,{bin:t,log:r,throw:n,stdout:o,stderr:s}){const a=Date.now(),c=e.outputSync(),{success:u,code:d}=c,h=Date.now()-a,f={get stdio(){return[[h,1,this.stdout],[h,2,this.stderr]]},stdin:"",stdout:"piped"===l(o)?i.decode(c.stdout):"",stderr:"piped"===l(s)?i.decode(c.stderr):""};for(const{channel:e,mode:t}of[{channel:"stdout",mode:o},{channel:"stderr",mode:s}])"piped"===l(t)&&f[e]&&r.with({t:h,channel:e})[t]?.(f[e]);if(!u&&n)throw new EvalError(`${t} exited with non-zero code ${d}:\n${f.stdout}\n${f.stderr}`);return{success:u,code:d,...f}}(T,{bin:t,log:s,throw:w,stdout:c,stderr:u}):async function(e,{bin:t,log:r,callback:i=({close:e})=>e?.(),buffering:s=250,throw:a,...c}){const u=e.spawn(),d=Date.now(),h={stdio:[],get stdin(){return this.stdio.filter((([e,t])=>0===t)).map((([e,t,r])=>r)).join("\n")},get stdout(){return this.stdio.filter((([e,t])=>1===t)).map((([e,t,r])=>r)).join("\n")},get stderr(){return this.stdio.filter((([e,t])=>2===t)).map((([e,t,r])=>r)).join("\n")}},f={};let p="";const m=function(e,t){let r=null,n=null;const o=(...i)=>{o.clear(),n=()=>{o.clear(),e.call(o,...i)},r=Number(setTimeout(n,t))};return o.clear=()=>{"number"==typeof r&&(clearTimeout(r),r=null,n=null)},o.flush=()=>{n?.()},Object.defineProperty(o,"pending",{get:()=>"number"==typeof r}),o}((async e=>{r.with({t:e}).trace("debounced"),p="",await i({stdio:h,i:h.stdin.length,...f})}),s);if("piped"===l(c.stdin)){const e=u.stdin.getWriter();Object.assign(f,{async write(t,n=!0){const i=Date.now()-d;c.stdin&&r.with({t:i,channel:"stdin"})[c.stdin]?.(t),h.stdio.push([i,0,t]),n&&!t.endsWith("\n")&&(t+="\n"),await e.write(o.encode(t)),p="stdin",e.releaseLock()},async close(){try{e.releaseLock(),await u.stdin.close(),r.with({t:Date.now()-d,closed:"stdin"}).trace()}catch{}},async wait(e=1e3){const t=Date.now()-d;r.with({t:t,waiting:e}).trace(),await function(e,t={}){const{signal:r,persistent:n=!0}=t;return r?.aborted?Promise.reject(r.reason):new Promise(((t,o)=>{const i=()=>{clearTimeout(s),o(r?.reason)},s=setTimeout((()=>{r?.removeEventListener("abort",i),t()}),e);if(r?.addEventListener("abort",i,{once:!0}),!1===n)try{Deno.unrefTimer(s)}catch(e){if(!(e instanceof ReferenceError))throw e;console.error("`persistent` option is only available in Deno")}}))}(e),m(t)}}),m(Date.now()-d)}await Promise.all(["stdout","stderr"].filter((e=>"piped"===l(c[e]))).map((async e=>{for await(const t of u[e].pipeThrough(new TextDecoderStream).pipeThrough(new n)){const n=Date.now()-d,o={stdout:1,stderr:2}[e];if(c[e]&&r.with({t:n,channel:e})[c[e]]?.(t),h.stdio.length&&p===e){const e=h.stdio.at(-1);e[1]===o&&(e[2]+=`\n${t}`)}else h.stdio.push([n,o,t]);p=e,m(n)}}))),m.flush();const{success:g,code:w}=await u.status;if(!g&&a)throw new EvalError(`${t} exited with non-zero code ${w}:\n${h.stdout}\n${h.stderr}`);return{success:g,code:w,...h}}(T,{bin:t,log:s,callback:p,buffering:m,throw:w,stdin:"piped"===l(a)?a:null,stdout:"piped"===l(c)?c:null,stderr:"piped"===l(u)?u:null})}function l(e){return["inherit","null"].includes(`${e}`)?`${e}`:"piped"}export{s as command};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lowlighter/run",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "type": "module",
5
5
  "scripts": {},
6
6
  "dependencies": {},