phala 0.0.1-alpha โ 0.0.1-alpha-6
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/README.md +40 -47
- package/dist/chunk-DGIS5AEA.js +2 -0
- package/dist/chunk-DGIS5AEA.js.map +1 -0
- package/dist/index.js +19 -15
- package/dist/index.js.map +1 -1
- package/dist/logger-672CA57G.js +2 -0
- package/package.json +3 -2
- package/dist/chunk-A4IAJHG6.js +0 -2
- package/dist/chunk-A4IAJHG6.js.map +0 -1
- package/dist/logger-LBGFMBSV.js +0 -2
- /package/dist/{logger-LBGFMBSV.js.map โ logger-672CA57G.js.map} +0 -0
package/README.md
CHANGED
@@ -1,25 +1,28 @@
|
|
1
|
-
|
1
|
+
<h1 align="center">Phala Cloud CLI</h1>
|
2
|
+
<p align="center">
|
3
|
+
<b>Secure. Confidential. Verifiable.</b>
|
4
|
+
</p>
|
2
5
|
|
3
6
|
A command-line tool for managing Trusted Execution Environment (TEE) deployments on Phala Cloud, from local development to cloud deployment.
|
7
|
+
___
|
4
8
|
|
5
9
|
<p align="center">
|
6
|
-
|
7
|
-
</p>
|
10
|
+
<b>๐ฅ Community & Support</b>
|
8
11
|
|
9
|
-
<
|
10
|
-
<b>Secure. Confidential. Verifiable.</b>
|
11
|
-
</p>
|
12
|
+
<div align="center">
|
12
13
|
|
13
|
-
|
14
|
+
[Phala Network Discord](https://discord.gg/phala-network) | [GitHub Issues](https://github.com/Phala-Network/phala-cloud-cli/issues) | [Phala Documentation](https://docs.phala.network)
|
14
15
|
|
15
|
-
|
16
|
+
</div>
|
17
|
+
</p>
|
16
18
|
|
17
|
-
|
19
|
+
## Usage
|
18
20
|
|
19
|
-
-
|
20
|
-
-
|
21
|
-
-
|
22
|
-
-
|
21
|
+
- [Dstack-TEE: Dstack](https://github.com/Dstack-TEE/dstack)
|
22
|
+
- Bun for runtime and package management
|
23
|
+
- TypeScript for type safety
|
24
|
+
- Commander.js for CLI interface
|
25
|
+
- Zod for runtime validation
|
23
26
|
|
24
27
|
## ๐ Quick Start (5 Minutes)
|
25
28
|
|
@@ -38,13 +41,20 @@ Phala Cloud is a confidential cloud platform that enables developers to deploy a
|
|
38
41
|
```bash
|
39
42
|
# Install the CLI globally
|
40
43
|
npm install -g phala
|
41
|
-
|
42
|
-
# Use npx/bunx
|
43
|
-
npx phala help
|
44
|
-
bunx phala help
|
45
44
|
```
|
46
|
-
|
47
|
-
|
45
|
+
|
46
|
+
> **NOTE**
|
47
|
+
>
|
48
|
+
> You can use `npx` or `bunx` to call the `phala` command
|
49
|
+
>
|
50
|
+
> ```bash
|
51
|
+
> # Use npx/bunx
|
52
|
+
>
|
53
|
+
> npx phala help
|
54
|
+
> bunx phala help
|
55
|
+
> ```
|
56
|
+
|
57
|
+
or clone source
|
48
58
|
|
49
59
|
```bash
|
50
60
|
# Clone the repository
|
@@ -74,6 +84,11 @@ Phala Cloud is a confidential cloud platform that enables developers to deploy a
|
|
74
84
|
```
|
75
85
|
|
76
86
|
4. **Deploy Your First Confidential App**:
|
87
|
+
Clone the [Dstack Examples](https://github.com/Dstack-TEE/dstack-examples) repo and cd into the webshell directory
|
88
|
+
```bash
|
89
|
+
git clone https://github.com/Dstack-TEE/dstack-examples.git && cd dstack-examples/webshell
|
90
|
+
```
|
91
|
+
|
77
92
|
```bash
|
78
93
|
# Deploy the webshell Dstack example
|
79
94
|
phala cvms create
|
@@ -83,16 +98,9 @@ Phala Cloud is a confidential cloud platform that enables developers to deploy a
|
|
83
98
|
|
84
99
|
```bash
|
85
100
|
# ? Enter a name for the CVM: webshell
|
86
|
-
#
|
87
|
-
|
88
|
-
#
|
89
|
-
# private-docker-image-deployment
|
90
|
-
# โฏ webshell
|
91
|
-
# custom-domain
|
92
|
-
# prelaunch-script
|
93
|
-
# timelock-nts
|
94
|
-
# ssh-over-tproxy
|
95
|
-
# Using example: webshell (~/phala-cloud-cli/examples/webshell/docker-compose.yaml)
|
101
|
+
# โน Detected docker compose file: ./docker-compose.yml
|
102
|
+
|
103
|
+
# ? Enter the path to your Docker Compose file:(docker-compose.yml)
|
96
104
|
# โ Enter number of vCPUs (default: 1): 1
|
97
105
|
|
98
106
|
# โ Enter memory in MB (default: 2048): 2048
|
@@ -562,8 +570,8 @@ Create a new CVM on Phala Cloud.
|
|
562
570
|
- `--vcpu <vcpu>`: Number of vCPUs (default: 1)
|
563
571
|
- `--memory <memory>`: Memory in MB (default: 2048)
|
564
572
|
- `--disk-size <diskSize>`: Disk size in GB (default: 20)
|
565
|
-
- `--teepod-id <teepodId>`: TEEPod ID to launch the CVM to
|
566
|
-
- `--image <image>`: Version of dstack image to use (i.e. dstack-
|
573
|
+
- `--teepod-id <teepodId>`: TEEPod ID to launch the CVM to (default: 3)
|
574
|
+
- `--image <image>`: Version of dstack image to use (i.e. dstack-0.3.5)
|
567
575
|
- `-e, --env-file <envFile>`: Environment variables in the form of KEY=VALUE
|
568
576
|
- `--skip-env`: Path to environment file (default: false)
|
569
577
|
- `--debug`: Enable debug mode
|
@@ -701,6 +709,7 @@ phala cvms resize e15c1a29a9dfb522da528464a8d5ce40ac28039f --name resource-inten
|
|
701
709
|
phala cvms create --name env-app --compose ./compose.yml --env-file ./.env
|
702
710
|
```
|
703
711
|
|
712
|
+
|
704
713
|
## ๐ Security
|
705
714
|
|
706
715
|
The TEE Cloud CLI employs several security measures:
|
@@ -734,12 +743,6 @@ phala --help
|
|
734
743
|
phala <command> --help
|
735
744
|
```
|
736
745
|
|
737
|
-
## ๐ฅ Community & Support
|
738
|
-
|
739
|
-
- [Phala Network Discord](https://discord.gg/phala-network)
|
740
|
-
- [GitHub Issues](https://github.com/Phala-Network/phala-cloud-cli/issues)
|
741
|
-
- [Phala Documentation](https://docs.phala.network)
|
742
|
-
|
743
746
|
## ๐ License
|
744
747
|
|
745
748
|
Apache 2.0
|
@@ -750,13 +753,3 @@ To contribute or run in development mode:
|
|
750
753
|
```bash
|
751
754
|
bun run src/index.ts
|
752
755
|
```
|
753
|
-
|
754
|
-
The project uses:
|
755
|
-
|
756
|
-
- [Dstack-TEE: Dstack](https://github.com/Dstack-TEE/dstack)
|
757
|
-
- Bun for runtime and package management
|
758
|
-
- TypeScript for type safety
|
759
|
-
- Commander.js for CLI interface
|
760
|
-
- Zod for runtime validation
|
761
|
-
|
762
|
-
We welcome contributions! Please see our [contributing guide](CONTRIBUTING.md) for details.
|
@@ -0,0 +1,2 @@
|
|
1
|
+
var U=Object.defineProperty;var V=(t,n,g)=>n in t?U(t,n,{enumerable:!0,configurable:!0,writable:!0,value:g}):t[n]=g;var P=(t,n,g)=>(V(t,typeof n!="symbol"?n+"":n,g),g);import m from"chalk";function A(t,n){if(!t)return[""];if(t.length<=n)return[t];let g=[],s="",p=t.split(/(\s+)/).filter(f=>f.trim().length>0);for(let f of p){if(f.length>n){s&&(g.push(s),s="");for(let l=0;l<f.length;l+=n)g.push(f.slice(l,l+n));continue}s.length+f.length+1>n?(g.push(s),s=f):s=s?`${s} ${f}`:f}return s&&g.push(s),g}var I={error:(t,...n)=>{console.error(m.red("\u2717"),m.red(t),...n)},warn:(t,...n)=>{console.log(m.yellow("\u26A0"),m.yellow(t),...n)},info:(t,...n)=>{console.log(m.blue("\u2139"),m.blue(t),...n)},success:(t,...n)=>{console.log(m.green("\u2713"),m.green(t),...n)},debug:(t,...n)=>{process.env.DEBUG&&console.log(m.gray("\u{1F50D}"),m.gray(t),...n)},table:(t,n)=>{if(t.length===0){console.log(m.yellow("No data to display"));return}if(n)if(typeof n[0]=="string"){let g=n.map(s=>({key:s,header:s.charAt(0).toUpperCase()+s.slice(1)}));M(t,{columns:g,borderStyle:"rounded",headerStyle:s=>m.cyan.bold(s)})}else M(t,{columns:n,borderStyle:"rounded",headerStyle:g=>m.cyan.bold(g)});else M(t,{borderStyle:"rounded",headerStyle:g=>m.cyan.bold(g)})},keyValueTable:(t,n)=>{let s={...{borderStyle:"rounded",enableTextWrapping:!0,maxDepth:2,formatKeys:!0,keyFormatter:u=>{let b=["URL","ID","API","UI","URI","CPU","GPU","RAM","JSON","XML","HTML","HTTP","HTTPS","SSH","FTP","IP","TCP","UDP","DNS","SSL","TLS","SQL","VCPU","CVM","TEE","IO"],T={teepod:"TEEPod",dstack:"Dstack"},W;u.includes("_")?W=u.split("_").map(k=>k.charAt(0).toUpperCase()+k.slice(1).toLowerCase()).join(" "):u.includes("-")?W=u.split("-").map(k=>k.charAt(0).toUpperCase()+k.slice(1).toLowerCase()).join(" "):W=u.charAt(0).toUpperCase()+u.slice(1).replace(/([a-z])([A-Z])/g,"$1 $2");for(let k of b){let v=new RegExp(`\\b${k.toLowerCase()}\\b`,"gi");W=W.replace(v,k)}for(let[k,v]of Object.entries(T)){let j=new RegExp(`\\b${k}\\b`,"gi");W=W.replace(j,v)}return W},valueFormatter:u=>String(u??"")},...n},{include:p,exclude:f,keyFormatter:l,valueFormatter:S,formatKeys:x,keyWidth:y,valueWidth:$,borderStyle:L,enableTextWrapping:o,maxDepth:i}=s,r=Object.keys(t);if(p&&(r=r.filter(u=>p.includes(u))),f&&(r=r.filter(u=>!f.includes(u))),r.length===0){console.log(m.yellow("No properties to display"));return}let a=r.map(u=>{let b=t[u],T;return b==null?T="":typeof b=="object"&&!Array.isArray(b)?T=z(b,0,i):Array.isArray(b)?b.length===0?T="[]":typeof b[0]=="object"?T=`[${b.length} items]`:T=`[${b.join(", ")}]`:T=String(b),S&&(T=S(b,u)),{key:x&&l?l(u):u,value:T}}),c=E(),e=y,h=$;e||(e=Math.max(...a.map(u=>u.key.length),10),e=Math.min(e,Math.floor(c/3))),h||(h=c-e-7);let d=B(L),C=`${d.topLeft}${d.horizontal.repeat(e+2)}${d.topT}${d.horizontal.repeat(h+2)}${d.topRight}`,w=`${d.leftT}${d.horizontal.repeat(e+2)}${d.cross}${d.horizontal.repeat(h+2)}${d.rightT}`;console.log(C),console.log(w),a.forEach((u,b)=>{let T=o?A(u.key,e):[u.key],W=o?A(u.value,h):[u.value],k=Math.max(T.length,W.length);for(let v=0;v<k;v++){let j=(T[v]||"").padEnd(e),H=(W[v]||"").padEnd(h);console.log(`${d.vertical} ${j} ${d.vertical} ${H} ${d.vertical}`)}b<a.length-1&&console.log(`${d.leftT}${d.horizontal.repeat(e+2)}${d.cross}${d.horizontal.repeat(h+2)}${d.rightT}`)});let R=`${d.bottomLeft}${d.horizontal.repeat(e+2)}${d.bottomT}${d.horizontal.repeat(h+2)}${d.bottomRight}`;console.log(R)},startSpinner:t=>(process.stdout.write(`${m.blue("\u27F3")} ${t}... `),{stop:(n=!0,g)=>{let s=n?m.green("\u2713"):m.red("\u2717"),p=g?`: ${g}`:"";console.log(`${s}${p}`)}}),break(){console.log("")}};function z(t,n,g){if(n>=g)return"[Nested Object]";if(t==null)return"";if(Array.isArray(t))return t.length===0?"[]":`[${t.length} items]`;let s=[];for(let[p,f]of Object.entries(t))f==null?s.push(`${p}: `):typeof f=="object"?s.push(`${p}: ${z(f,n+1,g)}`):s.push(`${p}: ${f}`);return s.join(", ")}function B(t="single"){return{single:{topLeft:"\u250C",topRight:"\u2510",bottomLeft:"\u2514",bottomRight:"\u2518",horizontal:"\u2500",vertical:"\u2502",leftT:"\u251C",rightT:"\u2524",topT:"\u252C",bottomT:"\u2534",cross:"\u253C"},double:{topLeft:"\u2554",topRight:"\u2557",bottomLeft:"\u255A",bottomRight:"\u255D",horizontal:"\u2550",vertical:"\u2551",leftT:"\u2560",rightT:"\u2563",topT:"\u2566",bottomT:"\u2569",cross:"\u256C"},rounded:{topLeft:"\u256D",topRight:"\u256E",bottomLeft:"\u2570",bottomRight:"\u256F",horizontal:"\u2500",vertical:"\u2502",leftT:"\u251C",rightT:"\u2524",topT:"\u252C",bottomT:"\u2534",cross:"\u253C"}}[t]}function E(){return process.stdout.columns||80}function O(t,n,g={}){let s=E(),p=g.borderChars??3,l=(g.additionalBorderWidth??1)+n.length*p,S=s-l,x={},y=0,$=0;for(let i of n){let r=i.key;if(i.fixedWidth!==void 0){x[r]=i.fixedWidth,y+=i.fixedWidth;continue}let a=i.minWidth??i.header.length,c;i.getWidth?c=Math.max(a,i.header.length,...t.map(e=>i.getWidth(e))):i.getValue?c=Math.max(a,i.header.length,...t.map(e=>String(i.getValue(e)||"").length)):c=Math.max(a,i.header.length,...t.map(e=>String(e[i.key]||"").length)),x[r]=c,y+=c,$+=i.weight??1}let L=Math.max(0,S-y);if(L>0&&$>0)for(let i of n){let r=i.key;if(i.fixedWidth===void 0&&i.weight){let a=Math.floor(L*(i.weight/$));x[r]+=a}}let o=Object.values(x).reduce((i,r)=>i+r,0)+l;if(o>s){let i=S/(o-l),r={};for(let a of n){let c=a.key,e=a.minWidth??a.header.length;r[c]=Math.max(e,Math.floor(x[c]*i))}return r}return x}function N(t,n){let g=n.map((f,l)=>({key:`col_${l}`,header:f.header,minWidth:f.minWidth,weight:f.weight,getValue:f.accessor})),s=O(t,g,{borderChars:3,additionalBorderWidth:1}),p={};return n.forEach((f,l)=>{p[f.key]=s[`col_${l}`]}),p}function M(t,n={}){if(n.keyValueMode&&t.length===1){let o=t[0],i=[];n.columns||(n.columns=Object.keys(o).map(r=>({key:r,header:r.charAt(0).toUpperCase()+r.slice(1).replace(/([A-Z])/g," $1")})));for(let r of n.columns){let a=String(r.key),c;if(r.accessor)c=r.accessor(o);else if(typeof r.key=="string"&&r.key.includes(".")){let e=r.key.split("."),h=o;for(let d of e){if(h==null){c="";break}h=h[d]}c=h}else c=o[r.key];r.formatter&&(c=r.formatter(c)),i.push({key:r.header||a,value:c})}t=i,n.columns=[{key:"key",minWidth:15},{key:"value",minWidth:20}]}if(t.length===0){console.log(m.yellow("No data to display"));return}let s={...{includeHeaders:!0,border:!0,borderStyle:"single",headerStyle:o=>m.bold(o),cellStyle:o=>o,enableTextWrapping:!0},...n},p=s.columns;if(p)p=p.map(o=>({...o,enableTextWrapping:o.enableTextWrapping!==void 0?o.enableTextWrapping:s.enableTextWrapping}));else{let o=t[0];p=Object.keys(o).map(i=>({key:i,header:i.charAt(0).toUpperCase()+i.slice(1),enableTextWrapping:s.enableTextWrapping}))}let l={single:{topLeft:"\u250C",topRight:"\u2510",bottomLeft:"\u2514",bottomRight:"\u2518",horizontal:"\u2500",vertical:"\u2502",leftT:"\u251C",rightT:"\u2524",topT:"\u252C",bottomT:"\u2534",cross:"\u253C"},double:{topLeft:"\u2554",topRight:"\u2557",bottomLeft:"\u255A",bottomRight:"\u255D",horizontal:"\u2550",vertical:"\u2551",leftT:"\u2560",rightT:"\u2563",topT:"\u2566",bottomT:"\u2569",cross:"\u256C"},rounded:{topLeft:"\u256D",topRight:"\u256E",bottomLeft:"\u2570",bottomRight:"\u256F",horizontal:"\u2500",vertical:"\u2502",leftT:"\u251C",rightT:"\u2524",topT:"\u252C",bottomT:"\u2534",cross:"\u253C"}}[s.borderStyle],S=p.map(o=>({key:o.key,header:o.header||String(o.key),minWidth:o.minWidth||3,weight:o.weight,enableTextWrapping:o.enableTextWrapping,getValue:o.accessor?i=>o.accessor(i):i=>{if(typeof o.key=="string"&&o.key.includes(".")){let r=o.key.split("."),a=i;for(let c of r){if(a==null)return"";a=a[c]}return a??""}return i[o.key]??""}})),x=O(t,S),y=p.map((o,i)=>({...o,width:x[S[i].key]})),$=y.map(o=>o.header||String(o.key)),L=(o,i)=>{let r=y.map(e=>{let h;if(e.accessor)h=e.accessor(o);else if(typeof e.key=="string"&&e.key.includes(".")){let C=e.key.split("."),w=o;for(let R of C){if(w==null){h="";break}w=w[R]}h=w??""}else h=o[e.key]??"";let d=e.formatter?e.formatter(h):String(h||"");return e.enableTextWrapping?{lines:A(d,e.width),key:String(e.key)}:{lines:[d.length>e.width?d.substring(0,e.width-1)+"\u2026":d],key:String(e.key)}}),a=Math.max(...r.map(e=>e.lines.length)),c=[];for(let e=0;e<a;e++){let h=r.map((d,C)=>{let w=d.lines[e]||"";return s.cellStyle(w.padEnd(y[C].width),i,d.key)});c.push(h)}return c};if(s.border){let o=l.topLeft+y.map(r=>l.horizontal.repeat(r.width+2)).join(l.topT)+l.topRight;if(console.log(o),s.includeHeaders){let r=y.map((e,h)=>({lines:e.enableTextWrapping?A($[h],e.width):[$[h]],width:e.width})),a=Math.max(...r.map(e=>e.lines.length));for(let e=0;e<a;e++){let h=l.vertical+r.map(d=>{let C=d.lines[e]||"";return" "+s.headerStyle(C.padEnd(d.width))+" "}).join(l.vertical)+l.vertical;console.log(h)}let c=l.leftT+y.map(e=>l.horizontal.repeat(e.width+2)).join(l.cross)+l.rightT;console.log(c)}t.forEach((r,a)=>{let c=L(r,a);if(c.forEach(e=>{console.log(l.vertical+e.map(h=>` ${h} `).join(l.vertical)+l.vertical)}),a<t.length-1&&c.length>1){let e=l.leftT+y.map(h=>l.horizontal.repeat(h.width+2)).join(l.cross)+l.rightT;console.log(e)}});let i=l.bottomLeft+y.map(r=>l.horizontal.repeat(r.width+2)).join(l.bottomT)+l.bottomRight;console.log(i)}else{if(s.includeHeaders){let o=y.map((a,c)=>({lines:a.enableTextWrapping?A($[c],a.width):[$[c]],width:a.width})),i=Math.max(...o.map(a=>a.lines.length));for(let a=0;a<i;a++){let c=o.map(e=>{let h=e.lines[a]||"";return s.headerStyle(h.padEnd(e.width))}).join(" ");console.log(c)}let r=y.map(a=>"\u2500".repeat(a.width)).join(" ");console.log(r)}t.forEach((o,i)=>{let r=L(o,i);r.forEach(a=>{console.log(a.join(" "))}),i<t.length-1&&r.length>1&&console.log("")})}console.log(`Total: ${t.length} rows`)}export{P as a,I as b,O as c,N as d,M as e};
|
2
|
+
//# sourceMappingURL=chunk-DGIS5AEA.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../src/utils/logger.ts"],"sourcesContent":["import chalk from \"chalk\"\n\n/**\n * Wraps text to fit within a specified width\n * @param text Text to wrap\n * @param maxWidth Maximum width for the text\n * @returns Array of lines of text\n */\nfunction wrapText(text: string, maxWidth: number): string[] {\n if (!text) return [''];\n \n // Handle case where a single word is longer than maxWidth\n if (text.length <= maxWidth) return [text];\n \n const lines: string[] = [];\n let currentLine = '';\n \n // Split by any whitespace and preserve URLs\n const words = text.split(/(\\s+)/).filter(word => word.trim().length > 0);\n \n for (const word of words) {\n // If the word itself is longer than maxWidth, split it\n if (word.length > maxWidth) {\n if (currentLine) {\n lines.push(currentLine);\n currentLine = '';\n }\n for (let i = 0; i < word.length; i += maxWidth) {\n lines.push(word.slice(i, i + maxWidth));\n }\n continue;\n }\n \n // If adding the word would exceed maxWidth\n if (currentLine.length + word.length + 1 > maxWidth) {\n lines.push(currentLine);\n currentLine = word;\n } else {\n // Add word to current line\n currentLine = currentLine ? `${currentLine} ${word}` : word;\n }\n }\n \n if (currentLine) {\n lines.push(currentLine);\n }\n \n return lines;\n}\n\nexport const logger = {\n error: (message: string, ...args: any[]) => {\n console.error(chalk.red('โ'), chalk.red(message), ...args)\n },\n warn: (message: string, ...args: any[]) => {\n console.log(chalk.yellow('โ '), chalk.yellow(message), ...args)\n },\n info: (message: string, ...args: any[]) => {\n console.log(chalk.blue('โน'), chalk.blue(message), ...args)\n },\n success: (message: string, ...args: any[]) => {\n console.log(chalk.green('โ'), chalk.green(message), ...args)\n },\n debug: (message: string, ...args: any[]) => {\n if (process.env.DEBUG) {\n console.log(chalk.gray('๐'), chalk.gray(message), ...args)\n }\n },\n table: <T>(\n data: T[], \n columns?: Array<string> | Array<{ key: keyof T | string, header?: string }> | Array<any>\n ) => {\n if (data.length === 0) {\n console.log(chalk.yellow('No data to display'));\n return;\n }\n \n // Support for old API with just column names\n if (columns) {\n if (typeof columns[0] === 'string') {\n // Convert simple string array to column config\n const columnConfig = (columns as string[]).map(col => ({\n key: col,\n header: col.charAt(0).toUpperCase() + col.slice(1) // Capitalize\n }));\n \n // Filter data to only include specified columns\n formatTable(data, { \n columns: columnConfig,\n borderStyle: 'rounded',\n headerStyle: (text) => chalk.cyan.bold(text)\n });\n } else {\n // Using the new column config format\n formatTable(data, { \n columns: columns as Array<{ key: keyof T | string, header?: string }>,\n borderStyle: 'rounded',\n headerStyle: (text) => chalk.cyan.bold(text)\n });\n }\n } else {\n // No columns specified, show all\n formatTable(data, {\n borderStyle: 'rounded',\n headerStyle: (text) => chalk.cyan.bold(text)\n });\n }\n },\n /**\n * Displays an object's properties in a key-value table format (vertical table)\n * @param data Object to display\n * @param options Table display options\n */\n keyValueTable: <T extends object>(\n data: T,\n options?: {\n include?: string[]; // Optional list of keys to include\n exclude?: string[]; // Optional list of keys to exclude\n keyFormatter?: (key: string) => string; // Optional formatter for keys\n valueFormatter?: (value: any, key: string) => string; // Optional formatter for values\n formatKeys?: boolean; // Whether to format keys (default: true)\n keyHeader?: string; // Optional header for the key column\n valueHeader?: string; // Optional header for the value column\n keyWidth?: number; // Optional fixed width for the key column\n valueWidth?: number; // Optional fixed width for the value column\n borderStyle?: 'single' | 'double' | 'rounded'; // Border style\n enableTextWrapping?: boolean; // Whether to wrap text\n maxDepth?: number; // Maximum depth for nested objects (default: 2)\n }\n ) => {\n // Default options\n const defaultOptions = {\n borderStyle: 'rounded' as const,\n enableTextWrapping: true,\n maxDepth: 2,\n formatKeys: true,\n // Improved key formatter with different formatting options\n keyFormatter: (key: string) => {\n // Common acronyms that should remain uppercase\n const commonAcronyms = [\n 'URL', 'ID', 'API', 'UI', 'URI', 'CPU', 'GPU', 'RAM', 'JSON', 'XML', 'HTML', \n 'HTTP', 'HTTPS', 'SSH', 'FTP', 'IP', 'TCP', 'UDP', 'DNS', 'SSL', 'TLS', 'SQL', \n 'VCPU', 'CVM', 'TEE', 'IO'\n ];\n \n // Phala-specific terms with custom capitalization\n const customTerms = {\n 'teepod': 'TEEPod',\n 'dstack': 'Dstack'\n };\n \n // Handle different cases\n let formatted;\n \n if (key.includes('_')) {\n // Handle snake_case: convert app_url to App Url\n formatted = key.split('_')\n .map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())\n .join(' ');\n } else if (key.includes('-')) {\n // Handle kebab-case: convert app-url to App Url\n formatted = key.split('-')\n .map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())\n .join(' ');\n } else {\n // Handle camelCase: convert appUrl to App Url\n formatted = key.charAt(0).toUpperCase() + \n key.slice(1).replace(/([a-z])([A-Z])/g, '$1 $2');\n }\n \n // Replace common acronyms in the formatted text, preserving case\n for (const acronym of commonAcronyms) {\n // Only uppercase the whole acronym if it appears as a whole word\n const regex = new RegExp(`\\\\b${acronym.toLowerCase()}\\\\b`, 'gi');\n formatted = formatted.replace(regex, acronym);\n }\n \n // Apply custom term formatting\n for (const [term, replacement] of Object.entries(customTerms)) {\n const regex = new RegExp(`\\\\b${term}\\\\b`, 'gi');\n formatted = formatted.replace(regex, replacement);\n }\n \n return formatted;\n },\n valueFormatter: (value: any) => String(value ?? '')\n };\n\n const mergedOptions = { ...defaultOptions, ...options };\n const { include, exclude, keyFormatter, valueFormatter, formatKeys, keyWidth, valueWidth, borderStyle, enableTextWrapping, maxDepth } = mergedOptions;\n\n // Extract keys based on include/exclude\n let keys = Object.keys(data);\n if (include) {\n keys = keys.filter(key => include.includes(key));\n }\n if (exclude) {\n keys = keys.filter(key => !exclude.includes(key));\n }\n\n // If no keys to display, show message and return\n if (keys.length === 0) {\n console.log(chalk.yellow('No properties to display'));\n return;\n }\n\n // Prepare the data array for the table formatter\n const tableData = keys.map(key => {\n const value = data[key as keyof T];\n \n // Format the value based on its type\n let formattedValue: string;\n if (value === null || value === undefined) {\n formattedValue = '';\n } else if (typeof value === 'object' && !Array.isArray(value)) {\n // Handle nested objects (but limit depth)\n formattedValue = formatNestedObject(value, 0, maxDepth);\n } else if (Array.isArray(value)) {\n // Handle arrays\n if (value.length === 0) {\n formattedValue = '[]';\n } else if (typeof value[0] === 'object') {\n // Array of objects\n formattedValue = `[${value.length} items]`;\n } else {\n // Array of primitives\n formattedValue = `[${value.join(', ')}]`;\n }\n } else {\n // Handle primitives\n formattedValue = String(value);\n }\n \n // Apply custom value formatter if provided\n if (valueFormatter) {\n formattedValue = valueFormatter(value, key);\n }\n \n return {\n key: formatKeys && keyFormatter ? keyFormatter(key) : key,\n value: formattedValue\n };\n });\n\n // Calculate column widths\n const terminalWidth = getTerminalWidth();\n let finalKeyWidth = keyWidth;\n let finalValueWidth = valueWidth;\n \n if (!finalKeyWidth) {\n // Calculate key column width based on content\n finalKeyWidth = Math.max(\n ...tableData.map(item => item.key.length),\n 10 // Minimum key width\n );\n // Limit to 1/3 of terminal width\n finalKeyWidth = Math.min(finalKeyWidth, Math.floor(terminalWidth / 3));\n }\n \n if (!finalValueWidth) {\n // Calculate value column width\n const borderChars = 7; // Typical border chars count\n finalValueWidth = terminalWidth - finalKeyWidth - borderChars;\n }\n\n // Configure border characters based on style\n const border = getBorderChars(borderStyle);\n\n // Header row\n const topBorder = `${border.topLeft}${border.horizontal.repeat(finalKeyWidth + 2)}${border.topT}${border.horizontal.repeat(finalValueWidth + 2)}${border.topRight}`;\n const headerSeparator = `${border.leftT}${border.horizontal.repeat(finalKeyWidth + 2)}${border.cross}${border.horizontal.repeat(finalValueWidth + 2)}${border.rightT}`;\n \n console.log(topBorder);\n console.log(headerSeparator);\n \n // Data rows\n tableData.forEach((row, index) => {\n const keyLines = enableTextWrapping ? wrapText(row.key, finalKeyWidth) : [row.key];\n const valueLines = enableTextWrapping ? wrapText(row.value, finalValueWidth) : [row.value];\n \n const maxLines = Math.max(keyLines.length, valueLines.length);\n \n for (let i = 0; i < maxLines; i++) {\n const keyContent = (keyLines[i] || '').padEnd(finalKeyWidth);\n const valueContent = (valueLines[i] || '').padEnd(finalValueWidth);\n console.log(`${border.vertical} ${keyContent} ${border.vertical} ${valueContent} ${border.vertical}`);\n }\n \n // Add a separator between rows, but not after the last row\n if (index < tableData.length - 1) {\n console.log(`${border.leftT}${border.horizontal.repeat(finalKeyWidth + 2)}${border.cross}${border.horizontal.repeat(finalValueWidth + 2)}${border.rightT}`);\n }\n });\n \n // Bottom border\n const bottomBorder = `${border.bottomLeft}${border.horizontal.repeat(finalKeyWidth + 2)}${border.bottomT}${border.horizontal.repeat(finalValueWidth + 2)}${border.bottomRight}`;\n console.log(bottomBorder);\n },\n startSpinner: (message: string) => {\n process.stdout.write(`${chalk.blue('โณ')} ${message}... `)\n return {\n stop: (success = true, result?: string) => {\n const icon = success ? chalk.green('โ') : chalk.red('โ')\n const resultText = result ? `: ${result}` : ''\n console.log(`${icon}${resultText}`)\n }\n }\n },\n break() {\n console.log(\"\")\n },\n}\n\n/**\n * Formats a nested object for display in the keyValueTable\n */\nfunction formatNestedObject(obj: any, currentDepth: number, maxDepth: number): string {\n if (currentDepth >= maxDepth) {\n return '[Nested Object]';\n }\n \n if (obj === null || obj === undefined) {\n return '';\n }\n \n if (Array.isArray(obj)) {\n if (obj.length === 0) return '[]';\n return `[${obj.length} items]`;\n }\n \n const lines: string[] = [];\n for (const [key, value] of Object.entries(obj)) {\n if (value === null || value === undefined) {\n lines.push(`${key}: `);\n } else if (typeof value === 'object') {\n lines.push(`${key}: ${formatNestedObject(value, currentDepth + 1, maxDepth)}`);\n } else {\n lines.push(`${key}: ${value}`);\n }\n }\n \n return lines.join(', ');\n}\n\n/**\n * Get border characters based on style\n */\nfunction getBorderChars(style: 'single' | 'double' | 'rounded' = 'single') {\n return {\n single: {\n topLeft: 'โ', topRight: 'โ', bottomLeft: 'โ', bottomRight: 'โ',\n horizontal: 'โ', vertical: 'โ', \n leftT: 'โ', rightT: 'โค', topT: 'โฌ', bottomT: 'โด', cross: 'โผ'\n },\n double: {\n topLeft: 'โ', topRight: 'โ', bottomLeft: 'โ', bottomRight: 'โ',\n horizontal: 'โ', vertical: 'โ',\n leftT: 'โ ', rightT: 'โฃ', topT: 'โฆ', bottomT: 'โฉ', cross: 'โฌ'\n },\n rounded: {\n topLeft: 'โญ', topRight: 'โฎ', bottomLeft: 'โฐ', bottomRight: 'โฏ',\n horizontal: 'โ', vertical: 'โ',\n leftT: 'โ', rightT: 'โค', topT: 'โฌ', bottomT: 'โด', cross: 'โผ'\n }\n }[style];\n}\n\nfunction getTerminalWidth(): number {\n return process.stdout.columns || 80; // Default to 80 if width cannot be determined\n}\n\n/**\n * Calculate column widths for tabular data display\n * @param data Array of objects to display in table\n * @param columns Configuration for each column to display\n * @param options Additional display options\n * @returns Object with calculated widths for each column\n */\nexport function calculateColumnWidths<T>(\n data: T[],\n columns: {\n key: keyof T;\n header: string;\n minWidth?: number;\n weight?: number; // Relative weight for distributing remaining space (default: 1)\n fixedWidth?: number; // If set, this column will have exactly this width\n getValue?: (item: T) => string; // Custom accessor for nested properties\n getWidth?: (item: T) => number; // Custom width calculator\n }[],\n options: {\n borderChars?: number; // Characters used for borders per column\n additionalBorderWidth?: number; // Additional border width (outer borders, etc.)\n } = {}\n): { [key: string]: number } {\n const terminalWidth = getTerminalWidth();\n \n // Calculate total border width\n const borderCharsPerColumn = options.borderChars ?? 3; // Default \"| \" + \" \" per column\n const additionalBorderWidth = options.additionalBorderWidth ?? 1; // Default \"|\" at the end\n const totalBorderWidth = additionalBorderWidth + columns.length * borderCharsPerColumn;\n \n const availableContentWidth = terminalWidth - totalBorderWidth;\n \n // Calculate initial widths based on content and minimum requirements\n const initialWidths: { [key: string]: number } = {};\n let totalFixedWidth = 0;\n let totalWeight = 0;\n \n // First pass: Calculate initial widths and total weight\n for (const column of columns) {\n const key = column.key as string;\n \n if (column.fixedWidth !== undefined) {\n initialWidths[key] = column.fixedWidth;\n totalFixedWidth += column.fixedWidth;\n continue;\n }\n \n const minWidth = column.minWidth ?? column.header.length;\n \n let contentWidth: number;\n if (column.getWidth) {\n // Use custom width calculator if provided\n contentWidth = Math.max(\n minWidth,\n column.header.length,\n ...data.map(item => column.getWidth!(item))\n );\n } else if (column.getValue) {\n // Use custom accessor if provided\n contentWidth = Math.max(\n minWidth,\n column.header.length,\n ...data.map(item => String(column.getValue!(item) || '').length)\n );\n } else {\n // Default behavior\n contentWidth = Math.max(\n minWidth,\n column.header.length,\n ...data.map(item => String(item[column.key] || '').length)\n );\n }\n \n initialWidths[key] = contentWidth;\n totalFixedWidth += contentWidth;\n totalWeight += column.weight ?? 1;\n }\n \n // Calculate remaining width to distribute\n const remainingWidth = Math.max(0, availableContentWidth - totalFixedWidth);\n \n // If we have remaining width and weights, distribute according to weights\n if (remainingWidth > 0 && totalWeight > 0) {\n for (const column of columns) {\n const key = column.key as string;\n if (column.fixedWidth === undefined && column.weight) {\n const extraWidth = Math.floor(remainingWidth * (column.weight / totalWeight));\n initialWidths[key] += extraWidth;\n }\n }\n }\n \n // If total width would exceed terminal, scale everything down proportionally\n const calculatedTotalWidth = Object.values(initialWidths).reduce((sum, width) => sum + width, 0) + totalBorderWidth;\n \n if (calculatedTotalWidth > terminalWidth) {\n const scale = availableContentWidth / (calculatedTotalWidth - totalBorderWidth);\n \n const finalWidths: { [key: string]: number } = {};\n for (const column of columns) {\n const key = column.key as string;\n const minWidth = column.minWidth ?? column.header.length;\n finalWidths[key] = Math.max(minWidth, Math.floor(initialWidths[key] * scale));\n }\n \n return finalWidths;\n }\n \n return initialWidths;\n}\n\n/**\n * Example of how to use calculateColumnWidths with nested objects\n * @param data Array of objects with nested properties\n * @returns Object with calculated column widths\n */\nexport function calculateNestedTableWidths<T>(\n data: T[],\n columns: Array<{\n key: string; // Output key in the result object\n header: string;\n minWidth: number;\n weight?: number;\n accessor: (item: T) => string; // Function to access the nested property\n }>\n): { [key: string]: number } {\n // Convert to the format expected by calculateColumnWidths\n const columnConfig = columns.map((col, index) => ({\n key: `col_${index}` as keyof T, // Use a unique key for each column\n header: col.header,\n minWidth: col.minWidth,\n weight: col.weight,\n getValue: col.accessor\n }));\n\n // Get the raw widths\n const widths = calculateColumnWidths(data, columnConfig, { borderChars: 3, additionalBorderWidth: 1 });\n \n // Remap to expected keys\n const result: { [key: string]: number } = {};\n columns.forEach((col, index) => {\n result[col.key] = widths[`col_${index}` as string];\n });\n \n return result;\n}\n\n/**\n * Format and display data as a table in the terminal with customizable styling\n * @param data Array of objects to display in table\n * @param options Table display options\n */\nexport function formatTable<T>(\n data: T[],\n options: {\n columns?: Array<{\n key: keyof T | string;\n header?: string;\n minWidth?: number;\n weight?: number;\n accessor?: (item: T) => any;\n formatter?: (value: any) => string;\n enableTextWrapping?: boolean; // Changed from wrapText to enableTextWrapping\n }>;\n includeHeaders?: boolean;\n border?: boolean;\n borderStyle?: 'single' | 'double' | 'rounded';\n headerStyle?: (text: string) => string;\n cellStyle?: (text: string, rowIndex: number, colKey: string) => string;\n enableTextWrapping?: boolean; // Global option to control text wrapping\n keyValueMode?: boolean; // Option to display a single object in key-value rows\n } = {}\n): void {\n // If in key-value mode, transform the data\n if (options.keyValueMode && data.length === 1) {\n const obj = data[0];\n const keyValueData: Array<{key: string, value: any}> = [];\n \n // Generate columns if not provided\n if (!options.columns) {\n options.columns = Object.keys(obj).map(key => ({\n key,\n header: key.charAt(0).toUpperCase() + key.slice(1).replace(/([A-Z])/g, ' $1') // Capitalize and add spaces\n }));\n }\n \n // Transform object to key-value rows\n for (const col of options.columns) {\n const key = String(col.key);\n let value;\n \n if (col.accessor) {\n value = col.accessor(obj);\n } else if (typeof col.key === 'string' && col.key.includes('.')) {\n // Handle dot notation for nested objects\n const parts = col.key.split('.');\n let current: any = obj;\n for (const part of parts) {\n if (current === null || current === undefined) {\n value = '';\n break;\n }\n current = current[part as keyof typeof current];\n }\n value = current;\n } else {\n value = obj[col.key as keyof T];\n }\n \n // Apply formatter if provided\n if (col.formatter) {\n value = col.formatter(value);\n }\n \n keyValueData.push({\n key: col.header || key,\n value: value\n });\n }\n \n // Replace data and columns\n data = keyValueData as unknown as T[];\n options.columns = [\n { key: 'key' as keyof T, minWidth: 15 },\n { key: 'value' as keyof T, minWidth: 20 }\n ];\n }\n\n if (data.length === 0) {\n console.log(chalk.yellow('No data to display'));\n return;\n }\n\n // Default options\n const defaultOptions = {\n includeHeaders: true,\n border: true,\n borderStyle: 'single' as const,\n headerStyle: (text: string) => chalk.bold(text),\n cellStyle: (text: string) => text,\n enableTextWrapping: true // Enable text wrapping by default\n };\n\n const mergedOptions = { ...defaultOptions, ...options };\n\n // Auto-generate columns if not provided\n let columns = mergedOptions.columns;\n if (!columns) {\n const sample = data[0];\n columns = Object.keys(sample).map(key => ({\n key,\n header: key.charAt(0).toUpperCase() + key.slice(1), // Capitalize header\n enableTextWrapping: mergedOptions.enableTextWrapping\n }));\n } else {\n // Ensure all columns have enableTextWrapping property set if not explicitly defined\n columns = columns.map(col => ({\n ...col,\n enableTextWrapping: col.enableTextWrapping !== undefined ? col.enableTextWrapping : mergedOptions.enableTextWrapping\n }));\n }\n\n // Configure border characters based on style\n const borderChars = {\n single: {\n topLeft: 'โ', topRight: 'โ', bottomLeft: 'โ', bottomRight: 'โ',\n horizontal: 'โ', vertical: 'โ', \n leftT: 'โ', rightT: 'โค', topT: 'โฌ', bottomT: 'โด', cross: 'โผ'\n },\n double: {\n topLeft: 'โ', topRight: 'โ', bottomLeft: 'โ', bottomRight: 'โ',\n horizontal: 'โ', vertical: 'โ',\n leftT: 'โ ', rightT: 'โฃ', topT: 'โฆ', bottomT: 'โฉ', cross: 'โฌ'\n },\n rounded: {\n topLeft: 'โญ', topRight: 'โฎ', bottomLeft: 'โฐ', bottomRight: 'โฏ',\n horizontal: 'โ', vertical: 'โ',\n leftT: 'โ', rightT: 'โค', topT: 'โฌ', bottomT: 'โด', cross: 'โผ'\n }\n };\n\n const border = borderChars[mergedOptions.borderStyle];\n\n // Configure column config for width calculation\n const columnConfig = columns.map(col => ({\n key: col.key as keyof T,\n header: col.header || String(col.key),\n minWidth: col.minWidth || 3,\n weight: col.weight,\n enableTextWrapping: col.enableTextWrapping,\n getValue: col.accessor ? \n (item: T) => col.accessor!(item) : \n (item: T) => {\n // Handle dot notation for nested objects\n if (typeof col.key === 'string' && col.key.includes('.')) {\n const parts = col.key.split('.');\n let value: any = item;\n for (const part of parts) {\n if (value === null || value === undefined) return '';\n value = value[part as keyof typeof value];\n }\n return value ?? '';\n }\n return item[col.key as keyof T] ?? '';\n }\n }));\n\n // Calculate column widths\n const widths = calculateColumnWidths(data, columnConfig);\n\n // Prepare column and header arrays with proper keys\n const formattedColumns = columns.map((col, index) => ({\n ...col,\n width: widths[columnConfig[index].key as string]\n }));\n\n // Format headers and rows\n const headers = formattedColumns.map(col => col.header || String(col.key));\n \n // Helper to format a row with text wrapping support\n const formatRow = (row: T, rowIndex: number) => {\n // For each column, get the value and wrap it if needed\n const rowData = formattedColumns.map(col => {\n let value;\n if (col.accessor) {\n value = col.accessor(row);\n } else if (typeof col.key === 'string' && col.key.includes('.')) {\n // Handle dot notation for nested objects\n const parts = col.key.split('.');\n let current: any = row;\n for (const part of parts) {\n if (current === null || current === undefined) {\n value = '';\n break;\n }\n current = current[part as keyof typeof current];\n }\n value = current ?? '';\n } else {\n value = row[col.key as keyof T] ?? '';\n }\n \n // Format the value\n let displayValue = col.formatter ? col.formatter(value) : String(value || '');\n \n // Wrap text if enabled for this column\n if (col.enableTextWrapping) {\n return {\n lines: wrapText(displayValue, col.width),\n key: String(col.key)\n };\n } else {\n // Truncate if not wrapping\n return {\n lines: [displayValue.length > col.width ? \n displayValue.substring(0, col.width - 1) + 'โฆ' : \n displayValue],\n key: String(col.key)\n };\n }\n });\n \n // Calculate the maximum number of lines in any column for this row\n const maxLines = Math.max(...rowData.map(col => col.lines.length));\n \n // Format each line of the row\n const formattedLines = [];\n for (let lineIndex = 0; lineIndex < maxLines; lineIndex++) {\n const lineContent = rowData.map((col, colIndex) => {\n const content = col.lines[lineIndex] || '';\n return mergedOptions.cellStyle(\n content.padEnd(formattedColumns[colIndex].width), \n rowIndex, \n col.key\n );\n });\n formattedLines.push(lineContent);\n }\n \n return formattedLines;\n };\n\n // Generate table parts\n if (mergedOptions.border) {\n // Top border\n const topBorder = border.topLeft + \n formattedColumns.map(col => border.horizontal.repeat(col.width + 2)).join(border.topT) +\n border.topRight;\n console.log(topBorder);\n \n // Headers with possible wrapping\n if (mergedOptions.includeHeaders) {\n // Wrap header text if needed\n const wrappedHeaders = formattedColumns.map((col, i) => ({\n lines: col.enableTextWrapping ? wrapText(headers[i], col.width) : [headers[i]],\n width: col.width\n }));\n \n // Find the maximum number of lines in any header\n const maxHeaderLines = Math.max(...wrappedHeaders.map(h => h.lines.length));\n \n // Display each line of the header\n for (let lineIndex = 0; lineIndex < maxHeaderLines; lineIndex++) {\n const headerLine = border.vertical + \n wrappedHeaders.map((header) => {\n const content = header.lines[lineIndex] || '';\n return ' ' + mergedOptions.headerStyle(content.padEnd(header.width)) + ' ';\n }).join(border.vertical) + \n border.vertical;\n console.log(headerLine);\n }\n \n // Header-data separator\n const headerSeparator = border.leftT +\n formattedColumns.map(col => border.horizontal.repeat(col.width + 2)).join(border.cross) +\n border.rightT;\n console.log(headerSeparator);\n }\n \n // Data rows with text wrapping\n data.forEach((row, rowIndex) => {\n const formattedRows = formatRow(row, rowIndex);\n \n formattedRows.forEach(rowLine => {\n console.log(\n border.vertical + \n rowLine.map(cell => ` ${cell} `).join(border.vertical) + \n border.vertical\n );\n });\n \n // Optional: Add a separator between rows for better readability\n if (rowIndex < data.length - 1 && formattedRows.length > 1) {\n const rowSeparator = border.leftT +\n formattedColumns.map(col => border.horizontal.repeat(col.width + 2)).join(border.cross) +\n border.rightT;\n console.log(rowSeparator);\n }\n });\n \n // Bottom border\n const bottomBorder = border.bottomLeft + \n formattedColumns.map(col => border.horizontal.repeat(col.width + 2)).join(border.bottomT) +\n border.bottomRight;\n console.log(bottomBorder);\n } else {\n // No borders, simpler display\n if (mergedOptions.includeHeaders) {\n // Wrap header text if needed\n const wrappedHeaders = formattedColumns.map((col, i) => ({\n lines: col.enableTextWrapping ? wrapText(headers[i], col.width) : [headers[i]],\n width: col.width\n }));\n \n // Find the maximum number of lines in any header\n const maxHeaderLines = Math.max(...wrappedHeaders.map(h => h.lines.length));\n \n // Display each line of the header\n for (let lineIndex = 0; lineIndex < maxHeaderLines; lineIndex++) {\n const headerLine = wrappedHeaders.map((header) => {\n const content = header.lines[lineIndex] || '';\n return mergedOptions.headerStyle(content.padEnd(header.width));\n }).join(' ');\n console.log(headerLine);\n }\n \n // Simple underline for headers\n const headerSeparator = formattedColumns.map(col => \n 'โ'.repeat(col.width)\n ).join(' ');\n console.log(headerSeparator);\n }\n \n // Data rows with text wrapping\n data.forEach((row, rowIndex) => {\n const formattedRows = formatRow(row, rowIndex);\n \n formattedRows.forEach(rowLine => {\n console.log(rowLine.join(' '));\n });\n \n // Add a blank line between multi-line rows for better readability\n if (rowIndex < data.length - 1 && formattedRows.length > 1) {\n console.log('');\n }\n });\n }\n \n console.log(`Total: ${data.length} rows`);\n}\n\n"],"mappings":"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","names":["chalk","wrapText","text","maxWidth","lines","currentLine","words","word","i","logger","message","args","data","columns","columnConfig","col","formatTable","options","mergedOptions","key","commonAcronyms","customTerms","formatted","part","acronym","regex","term","replacement","value","include","exclude","keyFormatter","valueFormatter","formatKeys","keyWidth","valueWidth","borderStyle","enableTextWrapping","maxDepth","keys","tableData","formattedValue","formatNestedObject","terminalWidth","getTerminalWidth","finalKeyWidth","finalValueWidth","item","border","getBorderChars","topBorder","headerSeparator","row","index","keyLines","valueLines","maxLines","keyContent","valueContent","bottomBorder","success","result","icon","resultText","obj","currentDepth","style","calculateColumnWidths","borderCharsPerColumn","totalBorderWidth","availableContentWidth","initialWidths","totalFixedWidth","totalWeight","column","minWidth","contentWidth","remainingWidth","extraWidth","calculatedTotalWidth","sum","width","scale","finalWidths","calculateNestedTableWidths","widths","keyValueData","parts","current","sample","formattedColumns","headers","formatRow","rowIndex","rowData","displayValue","formattedLines","lineIndex","lineContent","colIndex","content","wrappedHeaders","maxHeaderLines","h","headerLine","header","formattedRows","rowLine","cell","rowSeparator"]}
|