@barekey/cli 0.5.1 → 0.5.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/bun.lock +141 -0
- package/dist/commands/auth.js +6 -4
- package/dist/commands/target-prompts.d.ts +1 -1
- package/dist/contracts/index.d.ts +1 -0
- package/dist/contracts/index.js +1 -0
- package/dist/output/avatar.d.ts +14 -0
- package/dist/output/avatar.js +123 -0
- package/package.json +2 -1
- package/src/commands/auth.ts +8 -4
- package/src/contracts/index.ts +1 -0
- package/src/output/avatar.ts +168 -0
package/bun.lock
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"@clack/prompts": "^0.11.0",
|
|
9
9
|
"commander": "^14.0.1",
|
|
10
10
|
"effect": "3.19.19",
|
|
11
|
+
"jimp": "^1.6.0",
|
|
11
12
|
"open": "^10.2.0",
|
|
12
13
|
"picocolors": "^1.1.1",
|
|
13
14
|
},
|
|
@@ -22,10 +23,80 @@
|
|
|
22
23
|
|
|
23
24
|
"@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="],
|
|
24
25
|
|
|
26
|
+
"@jimp/core": ["@jimp/core@1.6.0", "", { "dependencies": { "@jimp/file-ops": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "await-to-js": "^3.0.0", "exif-parser": "^0.1.12", "file-type": "^16.0.0", "mime": "3" } }, "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w=="],
|
|
27
|
+
|
|
28
|
+
"@jimp/diff": ["@jimp/diff@1.6.0", "", { "dependencies": { "@jimp/plugin-resize": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "pixelmatch": "^5.3.0" } }, "sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw=="],
|
|
29
|
+
|
|
30
|
+
"@jimp/file-ops": ["@jimp/file-ops@1.6.0", "", {}, "sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ=="],
|
|
31
|
+
|
|
32
|
+
"@jimp/js-bmp": ["@jimp/js-bmp@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "bmp-ts": "^1.0.9" } }, "sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw=="],
|
|
33
|
+
|
|
34
|
+
"@jimp/js-gif": ["@jimp/js-gif@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "gifwrap": "^0.10.1", "omggif": "^1.0.10" } }, "sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g=="],
|
|
35
|
+
|
|
36
|
+
"@jimp/js-jpeg": ["@jimp/js-jpeg@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "jpeg-js": "^0.4.4" } }, "sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA=="],
|
|
37
|
+
|
|
38
|
+
"@jimp/js-png": ["@jimp/js-png@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "pngjs": "^7.0.0" } }, "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg=="],
|
|
39
|
+
|
|
40
|
+
"@jimp/js-tiff": ["@jimp/js-tiff@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "utif2": "^4.1.0" } }, "sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw=="],
|
|
41
|
+
|
|
42
|
+
"@jimp/plugin-blit": ["@jimp/plugin-blit@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "zod": "^3.23.8" } }, "sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA=="],
|
|
43
|
+
|
|
44
|
+
"@jimp/plugin-blur": ["@jimp/plugin-blur@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/utils": "1.6.0" } }, "sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw=="],
|
|
45
|
+
|
|
46
|
+
"@jimp/plugin-circle": ["@jimp/plugin-circle@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "zod": "^3.23.8" } }, "sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw=="],
|
|
47
|
+
|
|
48
|
+
"@jimp/plugin-color": ["@jimp/plugin-color@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "tinycolor2": "^1.6.0", "zod": "^3.23.8" } }, "sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA=="],
|
|
49
|
+
|
|
50
|
+
"@jimp/plugin-contain": ["@jimp/plugin-contain@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/plugin-blit": "1.6.0", "@jimp/plugin-resize": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "zod": "^3.23.8" } }, "sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ=="],
|
|
51
|
+
|
|
52
|
+
"@jimp/plugin-cover": ["@jimp/plugin-cover@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/plugin-crop": "1.6.0", "@jimp/plugin-resize": "1.6.0", "@jimp/types": "1.6.0", "zod": "^3.23.8" } }, "sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA=="],
|
|
53
|
+
|
|
54
|
+
"@jimp/plugin-crop": ["@jimp/plugin-crop@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "zod": "^3.23.8" } }, "sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang=="],
|
|
55
|
+
|
|
56
|
+
"@jimp/plugin-displace": ["@jimp/plugin-displace@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "zod": "^3.23.8" } }, "sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q=="],
|
|
57
|
+
|
|
58
|
+
"@jimp/plugin-dither": ["@jimp/plugin-dither@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0" } }, "sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ=="],
|
|
59
|
+
|
|
60
|
+
"@jimp/plugin-fisheye": ["@jimp/plugin-fisheye@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "zod": "^3.23.8" } }, "sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA=="],
|
|
61
|
+
|
|
62
|
+
"@jimp/plugin-flip": ["@jimp/plugin-flip@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "zod": "^3.23.8" } }, "sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg=="],
|
|
63
|
+
|
|
64
|
+
"@jimp/plugin-hash": ["@jimp/plugin-hash@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/js-bmp": "1.6.0", "@jimp/js-jpeg": "1.6.0", "@jimp/js-png": "1.6.0", "@jimp/js-tiff": "1.6.0", "@jimp/plugin-color": "1.6.0", "@jimp/plugin-resize": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "any-base": "^1.1.0" } }, "sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q=="],
|
|
65
|
+
|
|
66
|
+
"@jimp/plugin-mask": ["@jimp/plugin-mask@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "zod": "^3.23.8" } }, "sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA=="],
|
|
67
|
+
|
|
68
|
+
"@jimp/plugin-print": ["@jimp/plugin-print@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/js-jpeg": "1.6.0", "@jimp/js-png": "1.6.0", "@jimp/plugin-blit": "1.6.0", "@jimp/types": "1.6.0", "parse-bmfont-ascii": "^1.0.6", "parse-bmfont-binary": "^1.0.6", "parse-bmfont-xml": "^1.1.6", "simple-xml-to-json": "^1.2.2", "zod": "^3.23.8" } }, "sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A=="],
|
|
69
|
+
|
|
70
|
+
"@jimp/plugin-quantize": ["@jimp/plugin-quantize@1.6.0", "", { "dependencies": { "image-q": "^4.0.0", "zod": "^3.23.8" } }, "sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg=="],
|
|
71
|
+
|
|
72
|
+
"@jimp/plugin-resize": ["@jimp/plugin-resize@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/types": "1.6.0", "zod": "^3.23.8" } }, "sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA=="],
|
|
73
|
+
|
|
74
|
+
"@jimp/plugin-rotate": ["@jimp/plugin-rotate@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/plugin-crop": "1.6.0", "@jimp/plugin-resize": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "zod": "^3.23.8" } }, "sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw=="],
|
|
75
|
+
|
|
76
|
+
"@jimp/plugin-threshold": ["@jimp/plugin-threshold@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/plugin-color": "1.6.0", "@jimp/plugin-hash": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "zod": "^3.23.8" } }, "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w=="],
|
|
77
|
+
|
|
78
|
+
"@jimp/types": ["@jimp/types@1.6.0", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg=="],
|
|
79
|
+
|
|
80
|
+
"@jimp/utils": ["@jimp/utils@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "tinycolor2": "^1.6.0" } }, "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA=="],
|
|
81
|
+
|
|
25
82
|
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
|
26
83
|
|
|
84
|
+
"@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
|
|
85
|
+
|
|
27
86
|
"@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
|
28
87
|
|
|
88
|
+
"abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
|
|
89
|
+
|
|
90
|
+
"any-base": ["any-base@1.1.0", "", {}, "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg=="],
|
|
91
|
+
|
|
92
|
+
"await-to-js": ["await-to-js@3.0.0", "", {}, "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g=="],
|
|
93
|
+
|
|
94
|
+
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
|
95
|
+
|
|
96
|
+
"bmp-ts": ["bmp-ts@1.0.9", "", {}, "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw=="],
|
|
97
|
+
|
|
98
|
+
"buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
|
|
99
|
+
|
|
29
100
|
"bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
|
|
30
101
|
|
|
31
102
|
"commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="],
|
|
@@ -38,28 +109,98 @@
|
|
|
38
109
|
|
|
39
110
|
"effect": ["effect@3.19.19", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-Yc8U/SVXo2dHnaP7zNBlAo83h/nzSJpi7vph6Hzyl4ulgMBIgPmz3UzOjb9sBgpFE00gC0iETR244sfXDNLHRg=="],
|
|
40
111
|
|
|
112
|
+
"event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
|
|
113
|
+
|
|
114
|
+
"events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="],
|
|
115
|
+
|
|
116
|
+
"exif-parser": ["exif-parser@0.1.12", "", {}, "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw=="],
|
|
117
|
+
|
|
41
118
|
"fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="],
|
|
42
119
|
|
|
120
|
+
"file-type": ["file-type@16.5.4", "", { "dependencies": { "readable-web-to-node-stream": "^3.0.0", "strtok3": "^6.2.4", "token-types": "^4.1.1" } }, "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw=="],
|
|
121
|
+
|
|
122
|
+
"gifwrap": ["gifwrap@0.10.1", "", { "dependencies": { "image-q": "^4.0.0", "omggif": "^1.0.10" } }, "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw=="],
|
|
123
|
+
|
|
124
|
+
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
|
125
|
+
|
|
126
|
+
"image-q": ["image-q@4.0.0", "", { "dependencies": { "@types/node": "16.9.1" } }, "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw=="],
|
|
127
|
+
|
|
43
128
|
"is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
|
|
44
129
|
|
|
45
130
|
"is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="],
|
|
46
131
|
|
|
47
132
|
"is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="],
|
|
48
133
|
|
|
134
|
+
"jimp": ["jimp@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/diff": "1.6.0", "@jimp/js-bmp": "1.6.0", "@jimp/js-gif": "1.6.0", "@jimp/js-jpeg": "1.6.0", "@jimp/js-png": "1.6.0", "@jimp/js-tiff": "1.6.0", "@jimp/plugin-blit": "1.6.0", "@jimp/plugin-blur": "1.6.0", "@jimp/plugin-circle": "1.6.0", "@jimp/plugin-color": "1.6.0", "@jimp/plugin-contain": "1.6.0", "@jimp/plugin-cover": "1.6.0", "@jimp/plugin-crop": "1.6.0", "@jimp/plugin-displace": "1.6.0", "@jimp/plugin-dither": "1.6.0", "@jimp/plugin-fisheye": "1.6.0", "@jimp/plugin-flip": "1.6.0", "@jimp/plugin-hash": "1.6.0", "@jimp/plugin-mask": "1.6.0", "@jimp/plugin-print": "1.6.0", "@jimp/plugin-quantize": "1.6.0", "@jimp/plugin-resize": "1.6.0", "@jimp/plugin-rotate": "1.6.0", "@jimp/plugin-threshold": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0" } }, "sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg=="],
|
|
135
|
+
|
|
136
|
+
"jpeg-js": ["jpeg-js@0.4.4", "", {}, "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg=="],
|
|
137
|
+
|
|
138
|
+
"mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="],
|
|
139
|
+
|
|
140
|
+
"omggif": ["omggif@1.0.10", "", {}, "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw=="],
|
|
141
|
+
|
|
49
142
|
"open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="],
|
|
50
143
|
|
|
144
|
+
"pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="],
|
|
145
|
+
|
|
146
|
+
"parse-bmfont-ascii": ["parse-bmfont-ascii@1.0.6", "", {}, "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA=="],
|
|
147
|
+
|
|
148
|
+
"parse-bmfont-binary": ["parse-bmfont-binary@1.0.6", "", {}, "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA=="],
|
|
149
|
+
|
|
150
|
+
"parse-bmfont-xml": ["parse-bmfont-xml@1.1.6", "", { "dependencies": { "xml-parse-from-string": "^1.0.0", "xml2js": "^0.5.0" } }, "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA=="],
|
|
151
|
+
|
|
152
|
+
"peek-readable": ["peek-readable@4.1.0", "", {}, "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg=="],
|
|
153
|
+
|
|
51
154
|
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
|
52
155
|
|
|
156
|
+
"pixelmatch": ["pixelmatch@5.3.0", "", { "dependencies": { "pngjs": "^6.0.0" }, "bin": { "pixelmatch": "bin/pixelmatch" } }, "sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q=="],
|
|
157
|
+
|
|
158
|
+
"pngjs": ["pngjs@7.0.0", "", {}, "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow=="],
|
|
159
|
+
|
|
160
|
+
"process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="],
|
|
161
|
+
|
|
53
162
|
"pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
|
|
54
163
|
|
|
164
|
+
"readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="],
|
|
165
|
+
|
|
166
|
+
"readable-web-to-node-stream": ["readable-web-to-node-stream@3.0.4", "", { "dependencies": { "readable-stream": "^4.7.0" } }, "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw=="],
|
|
167
|
+
|
|
55
168
|
"run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="],
|
|
56
169
|
|
|
170
|
+
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
|
171
|
+
|
|
172
|
+
"sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="],
|
|
173
|
+
|
|
174
|
+
"simple-xml-to-json": ["simple-xml-to-json@1.2.4", "", {}, "sha512-3MY16e0ocMHL7N1ufpdObURGyX+lCo0T/A+y6VCwosLdH1HSda4QZl1Sdt/O+2qWp48WFi26XEp5rF0LoaL0Dg=="],
|
|
175
|
+
|
|
57
176
|
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
|
58
177
|
|
|
178
|
+
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
|
179
|
+
|
|
180
|
+
"strtok3": ["strtok3@6.3.0", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^4.1.0" } }, "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw=="],
|
|
181
|
+
|
|
182
|
+
"tinycolor2": ["tinycolor2@1.6.0", "", {}, "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="],
|
|
183
|
+
|
|
184
|
+
"token-types": ["token-types@4.2.1", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ=="],
|
|
185
|
+
|
|
59
186
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
60
187
|
|
|
61
188
|
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
|
62
189
|
|
|
190
|
+
"utif2": ["utif2@4.1.0", "", { "dependencies": { "pako": "^1.0.11" } }, "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w=="],
|
|
191
|
+
|
|
63
192
|
"wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="],
|
|
193
|
+
|
|
194
|
+
"xml-parse-from-string": ["xml-parse-from-string@1.0.1", "", {}, "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g=="],
|
|
195
|
+
|
|
196
|
+
"xml2js": ["xml2js@0.5.0", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA=="],
|
|
197
|
+
|
|
198
|
+
"xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="],
|
|
199
|
+
|
|
200
|
+
"zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
|
201
|
+
|
|
202
|
+
"image-q/@types/node": ["@types/node@16.9.1", "", {}, "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g=="],
|
|
203
|
+
|
|
204
|
+
"pixelmatch/pngjs": ["pngjs@6.0.0", "", {}, "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg=="],
|
|
64
205
|
}
|
|
65
206
|
}
|
package/dist/commands/auth.js
CHANGED
|
@@ -8,6 +8,7 @@ import { buildSessionId } from "../context/session-id.js";
|
|
|
8
8
|
import { clearConfig, deleteCredentials, saveConfig, saveCredentials, } from "../credentials-store.js";
|
|
9
9
|
import { CliSessionResponseSchema, DevicePollResponseSchema, DeviceStartResponseSchema, RefreshResponseSchema, } from "../contracts/index.js";
|
|
10
10
|
import { getJson, postJson } from "../http.js";
|
|
11
|
+
import { formatWhoamiWithAvatar } from "../output/avatar.js";
|
|
11
12
|
import { requireLocalSession, resolveBaseUrl, toJsonOutput } from "../command-utils.js";
|
|
12
13
|
function resolveClientName() {
|
|
13
14
|
const configured = process.env.BAREKEY_CLIENT_NAME?.trim() ||
|
|
@@ -158,10 +159,11 @@ async function runWhoami(options) {
|
|
|
158
159
|
toJsonOutput(true, session);
|
|
159
160
|
return;
|
|
160
161
|
}
|
|
161
|
-
console.log(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
162
|
+
console.log(await formatWhoamiWithAvatar({
|
|
163
|
+
displayName: resolveDisplayName(session),
|
|
164
|
+
email: session.email,
|
|
165
|
+
imageUrl: session.imageUrl,
|
|
166
|
+
}));
|
|
165
167
|
}
|
|
166
168
|
export function registerAuthCommands(program) {
|
|
167
169
|
const auth = program.command("auth").description("Authentication commands");
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
* @author GPT-5.4
|
|
8
8
|
*/
|
|
9
9
|
export declare function listOrganizationsForCurrentUser(): Promise<readonly {
|
|
10
|
+
readonly imageUrl: string;
|
|
10
11
|
readonly name: string;
|
|
11
12
|
readonly id: string;
|
|
12
13
|
readonly slug: string;
|
|
13
14
|
readonly role: string;
|
|
14
|
-
readonly imageUrl: string;
|
|
15
15
|
}[]>;
|
|
16
16
|
/**
|
|
17
17
|
* Loads projects for one organization.
|
|
@@ -53,6 +53,7 @@ export declare const CliSessionResponseSchema: Schema.Struct<{
|
|
|
53
53
|
clerkUserId: typeof Schema.String;
|
|
54
54
|
displayName: Schema.NullOr<typeof Schema.String>;
|
|
55
55
|
email: Schema.NullOr<typeof Schema.String>;
|
|
56
|
+
imageUrl: Schema.NullOr<typeof Schema.String>;
|
|
56
57
|
orgId: typeof Schema.String;
|
|
57
58
|
orgSlug: typeof Schema.String;
|
|
58
59
|
source: Schema.Literal<["clerk", "cli"]>;
|
package/dist/contracts/index.js
CHANGED
|
@@ -55,6 +55,7 @@ export const CliSessionResponseSchema = Schema.Struct({
|
|
|
55
55
|
clerkUserId: Schema.String,
|
|
56
56
|
displayName: Schema.NullOr(Schema.String),
|
|
57
57
|
email: Schema.NullOr(Schema.String),
|
|
58
|
+
imageUrl: Schema.NullOr(Schema.String),
|
|
58
59
|
orgId: Schema.String,
|
|
59
60
|
orgSlug: Schema.String,
|
|
60
61
|
source: Schema.Literal("clerk", "cli"),
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the terminal `whoami` output with a tiny ANSI avatar when supported.
|
|
3
|
+
*
|
|
4
|
+
* @param input The display name, email, and optional avatar image URL.
|
|
5
|
+
* @returns The formatted `whoami` string ready for stdout.
|
|
6
|
+
* @remarks Non-TTY terminals and avatar failures fall back to plain text without throwing.
|
|
7
|
+
* @lastModified 2026-03-19
|
|
8
|
+
* @author GPT-5.4
|
|
9
|
+
*/
|
|
10
|
+
export declare function formatWhoamiWithAvatar(input: {
|
|
11
|
+
displayName: string;
|
|
12
|
+
email: string | null;
|
|
13
|
+
imageUrl: string | null;
|
|
14
|
+
}): Promise<string>;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { Jimp } from "jimp";
|
|
2
|
+
const DEFAULT_AVATAR_COLUMNS = 10;
|
|
3
|
+
const DEFAULT_AVATAR_ROWS = 8;
|
|
4
|
+
function supportsAnsiAvatar() {
|
|
5
|
+
if (!process.stdout.isTTY) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
if ((process.env.NO_COLOR ?? "").trim().length > 0) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
const term = (process.env.TERM ?? "").toLowerCase();
|
|
12
|
+
if (term === "dumb") {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
function pixelOffset(width, x, y) {
|
|
18
|
+
return (y * width + x) * 4;
|
|
19
|
+
}
|
|
20
|
+
function readPixel(data, width, x, y) {
|
|
21
|
+
const offset = pixelOffset(width, x, y);
|
|
22
|
+
return {
|
|
23
|
+
red: data[offset] ?? 0,
|
|
24
|
+
green: data[offset + 1] ?? 0,
|
|
25
|
+
blue: data[offset + 2] ?? 0,
|
|
26
|
+
alpha: data[offset + 3] ?? 0,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function isOpaque(pixel) {
|
|
30
|
+
return pixel.alpha >= 96;
|
|
31
|
+
}
|
|
32
|
+
function foregroundColor(pixel) {
|
|
33
|
+
return `\u001b[38;2;${pixel.red};${pixel.green};${pixel.blue}m`;
|
|
34
|
+
}
|
|
35
|
+
function backgroundColor(pixel) {
|
|
36
|
+
return `\u001b[48;2;${pixel.red};${pixel.green};${pixel.blue}m`;
|
|
37
|
+
}
|
|
38
|
+
function renderPixelPair(top, bottom) {
|
|
39
|
+
const topOpaque = isOpaque(top);
|
|
40
|
+
const bottomOpaque = isOpaque(bottom);
|
|
41
|
+
if (!topOpaque && !bottomOpaque) {
|
|
42
|
+
return " ";
|
|
43
|
+
}
|
|
44
|
+
if (topOpaque && bottomOpaque) {
|
|
45
|
+
return `${foregroundColor(top)}${backgroundColor(bottom)}▀`;
|
|
46
|
+
}
|
|
47
|
+
if (topOpaque) {
|
|
48
|
+
return `${foregroundColor(top)}▀`;
|
|
49
|
+
}
|
|
50
|
+
return `${foregroundColor(bottom)}▄`;
|
|
51
|
+
}
|
|
52
|
+
async function fetchAvatarBuffer(imageUrl) {
|
|
53
|
+
const response = await fetch(imageUrl, {
|
|
54
|
+
signal: AbortSignal.timeout(4_000),
|
|
55
|
+
});
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
throw new Error(`Avatar request failed with HTTP ${response.status}.`);
|
|
58
|
+
}
|
|
59
|
+
return Buffer.from(await response.arrayBuffer());
|
|
60
|
+
}
|
|
61
|
+
async function renderAvatarLines(imageUrl) {
|
|
62
|
+
const bitmapRows = DEFAULT_AVATAR_ROWS * 2;
|
|
63
|
+
const buffer = await fetchAvatarBuffer(imageUrl);
|
|
64
|
+
const image = await Jimp.read(buffer);
|
|
65
|
+
image.cover({
|
|
66
|
+
w: DEFAULT_AVATAR_COLUMNS,
|
|
67
|
+
h: bitmapRows,
|
|
68
|
+
});
|
|
69
|
+
image.circle();
|
|
70
|
+
const { data, width, height } = image.bitmap;
|
|
71
|
+
const lines = [];
|
|
72
|
+
for (let y = 0; y < height; y += 2) {
|
|
73
|
+
let line = "";
|
|
74
|
+
for (let x = 0; x < width; x += 1) {
|
|
75
|
+
const top = readPixel(data, width, x, y);
|
|
76
|
+
const bottom = readPixel(data, width, x, Math.min(y + 1, height - 1));
|
|
77
|
+
line += renderPixelPair(top, bottom);
|
|
78
|
+
}
|
|
79
|
+
lines.push(`${line}\u001b[0m`);
|
|
80
|
+
}
|
|
81
|
+
while (lines.length > 0 && isBlankAvatarLine(lines[0] ?? "")) {
|
|
82
|
+
lines.shift();
|
|
83
|
+
}
|
|
84
|
+
while (lines.length > 0 && isBlankAvatarLine(lines[lines.length - 1] ?? "")) {
|
|
85
|
+
lines.pop();
|
|
86
|
+
}
|
|
87
|
+
return lines;
|
|
88
|
+
}
|
|
89
|
+
function isBlankAvatarLine(line) {
|
|
90
|
+
return line.replace(/\u001b\[[0-9;]*m/g, "").trim().length === 0;
|
|
91
|
+
}
|
|
92
|
+
function joinAvatarAndText(avatarLines, textLines) {
|
|
93
|
+
const totalRows = Math.max(avatarLines.length, textLines.length);
|
|
94
|
+
const renderedRows = [];
|
|
95
|
+
for (let index = 0; index < totalRows; index += 1) {
|
|
96
|
+
const avatarLine = avatarLines[index] ?? " ".repeat(DEFAULT_AVATAR_COLUMNS);
|
|
97
|
+
const textLine = textLines[index] ?? "";
|
|
98
|
+
renderedRows.push(textLine.length > 0 ? `${avatarLine} ${textLine}` : avatarLine);
|
|
99
|
+
}
|
|
100
|
+
return renderedRows.join("\n");
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Builds the terminal `whoami` output with a tiny ANSI avatar when supported.
|
|
104
|
+
*
|
|
105
|
+
* @param input The display name, email, and optional avatar image URL.
|
|
106
|
+
* @returns The formatted `whoami` string ready for stdout.
|
|
107
|
+
* @remarks Non-TTY terminals and avatar failures fall back to plain text without throwing.
|
|
108
|
+
* @lastModified 2026-03-19
|
|
109
|
+
* @author GPT-5.4
|
|
110
|
+
*/
|
|
111
|
+
export async function formatWhoamiWithAvatar(input) {
|
|
112
|
+
const textLines = [`Signed in as ${input.displayName}.`, input.email ?? ""].filter((line) => line.length > 0);
|
|
113
|
+
if (!supportsAnsiAvatar() || input.imageUrl === null) {
|
|
114
|
+
return textLines.join("\n");
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const avatarLines = await renderAvatarLines(input.imageUrl);
|
|
118
|
+
return joinAvatarAndText(avatarLines, textLines);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return textLines.join("\n");
|
|
122
|
+
}
|
|
123
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barekey/cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Barekey command line interface",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"@clack/prompts": "^0.11.0",
|
|
18
18
|
"commander": "^14.0.1",
|
|
19
19
|
"effect": "3.19.19",
|
|
20
|
+
"jimp": "^1.6.0",
|
|
20
21
|
"open": "^10.2.0",
|
|
21
22
|
"picocolors": "^1.1.1"
|
|
22
23
|
},
|
package/src/commands/auth.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
RefreshResponseSchema,
|
|
22
22
|
} from "../contracts/index.js";
|
|
23
23
|
import { getJson, postJson } from "../http.js";
|
|
24
|
+
import { formatWhoamiWithAvatar } from "../output/avatar.js";
|
|
24
25
|
import { requireLocalSession, resolveBaseUrl, toJsonOutput } from "../command-utils.js";
|
|
25
26
|
|
|
26
27
|
function resolveClientName(): string | undefined {
|
|
@@ -196,10 +197,13 @@ async function runWhoami(options: { json?: boolean }): Promise<void> {
|
|
|
196
197
|
return;
|
|
197
198
|
}
|
|
198
199
|
|
|
199
|
-
console.log(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
200
|
+
console.log(
|
|
201
|
+
await formatWhoamiWithAvatar({
|
|
202
|
+
displayName: resolveDisplayName(session),
|
|
203
|
+
email: session.email,
|
|
204
|
+
imageUrl: session.imageUrl,
|
|
205
|
+
}),
|
|
206
|
+
);
|
|
203
207
|
}
|
|
204
208
|
|
|
205
209
|
export function registerAuthCommands(program: Command): void {
|
package/src/contracts/index.ts
CHANGED
|
@@ -77,6 +77,7 @@ export const CliSessionResponseSchema = Schema.Struct({
|
|
|
77
77
|
clerkUserId: Schema.String,
|
|
78
78
|
displayName: Schema.NullOr(Schema.String),
|
|
79
79
|
email: Schema.NullOr(Schema.String),
|
|
80
|
+
imageUrl: Schema.NullOr(Schema.String),
|
|
80
81
|
orgId: Schema.String,
|
|
81
82
|
orgSlug: Schema.String,
|
|
82
83
|
source: Schema.Literal("clerk", "cli"),
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { Jimp } from "jimp";
|
|
2
|
+
|
|
3
|
+
const DEFAULT_AVATAR_COLUMNS = 10;
|
|
4
|
+
const DEFAULT_AVATAR_ROWS = 8;
|
|
5
|
+
|
|
6
|
+
type Rgba = {
|
|
7
|
+
red: number;
|
|
8
|
+
green: number;
|
|
9
|
+
blue: number;
|
|
10
|
+
alpha: number;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function supportsAnsiAvatar(): boolean {
|
|
14
|
+
if (!process.stdout.isTTY) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if ((process.env.NO_COLOR ?? "").trim().length > 0) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const term = (process.env.TERM ?? "").toLowerCase();
|
|
23
|
+
if (term === "dumb") {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function pixelOffset(width: number, x: number, y: number): number {
|
|
31
|
+
return (y * width + x) * 4;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function readPixel(data: Buffer, width: number, x: number, y: number): Rgba {
|
|
35
|
+
const offset = pixelOffset(width, x, y);
|
|
36
|
+
return {
|
|
37
|
+
red: data[offset] ?? 0,
|
|
38
|
+
green: data[offset + 1] ?? 0,
|
|
39
|
+
blue: data[offset + 2] ?? 0,
|
|
40
|
+
alpha: data[offset + 3] ?? 0,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function isOpaque(pixel: Rgba): boolean {
|
|
45
|
+
return pixel.alpha >= 96;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function foregroundColor(pixel: Rgba): string {
|
|
49
|
+
return `\u001b[38;2;${pixel.red};${pixel.green};${pixel.blue}m`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function backgroundColor(pixel: Rgba): string {
|
|
53
|
+
return `\u001b[48;2;${pixel.red};${pixel.green};${pixel.blue}m`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function renderPixelPair(top: Rgba, bottom: Rgba): string {
|
|
57
|
+
const topOpaque = isOpaque(top);
|
|
58
|
+
const bottomOpaque = isOpaque(bottom);
|
|
59
|
+
|
|
60
|
+
if (!topOpaque && !bottomOpaque) {
|
|
61
|
+
return " ";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (topOpaque && bottomOpaque) {
|
|
65
|
+
return `${foregroundColor(top)}${backgroundColor(bottom)}▀`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (topOpaque) {
|
|
69
|
+
return `${foregroundColor(top)}▀`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return `${foregroundColor(bottom)}▄`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function fetchAvatarBuffer(imageUrl: string): Promise<Buffer> {
|
|
76
|
+
const response = await fetch(imageUrl, {
|
|
77
|
+
signal: AbortSignal.timeout(4_000),
|
|
78
|
+
});
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
throw new Error(`Avatar request failed with HTTP ${response.status}.`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return Buffer.from(await response.arrayBuffer());
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function renderAvatarLines(imageUrl: string): Promise<Array<string>> {
|
|
87
|
+
const bitmapRows = DEFAULT_AVATAR_ROWS * 2;
|
|
88
|
+
const buffer = await fetchAvatarBuffer(imageUrl);
|
|
89
|
+
const image = await Jimp.read(buffer);
|
|
90
|
+
|
|
91
|
+
image.cover({
|
|
92
|
+
w: DEFAULT_AVATAR_COLUMNS,
|
|
93
|
+
h: bitmapRows,
|
|
94
|
+
});
|
|
95
|
+
image.circle();
|
|
96
|
+
|
|
97
|
+
const { data, width, height } = image.bitmap;
|
|
98
|
+
const lines: Array<string> = [];
|
|
99
|
+
|
|
100
|
+
for (let y = 0; y < height; y += 2) {
|
|
101
|
+
let line = "";
|
|
102
|
+
for (let x = 0; x < width; x += 1) {
|
|
103
|
+
const top = readPixel(data, width, x, y);
|
|
104
|
+
const bottom = readPixel(data, width, x, Math.min(y + 1, height - 1));
|
|
105
|
+
line += renderPixelPair(top, bottom);
|
|
106
|
+
}
|
|
107
|
+
lines.push(`${line}\u001b[0m`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
while (lines.length > 0 && isBlankAvatarLine(lines[0] ?? "")) {
|
|
111
|
+
lines.shift();
|
|
112
|
+
}
|
|
113
|
+
while (lines.length > 0 && isBlankAvatarLine(lines[lines.length - 1] ?? "")) {
|
|
114
|
+
lines.pop();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return lines;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function isBlankAvatarLine(line: string): boolean {
|
|
121
|
+
return line.replace(/\u001b\[[0-9;]*m/g, "").trim().length === 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function joinAvatarAndText(
|
|
125
|
+
avatarLines: Array<string>,
|
|
126
|
+
textLines: Array<string>,
|
|
127
|
+
): string {
|
|
128
|
+
const totalRows = Math.max(avatarLines.length, textLines.length);
|
|
129
|
+
const renderedRows: Array<string> = [];
|
|
130
|
+
|
|
131
|
+
for (let index = 0; index < totalRows; index += 1) {
|
|
132
|
+
const avatarLine = avatarLines[index] ?? " ".repeat(DEFAULT_AVATAR_COLUMNS);
|
|
133
|
+
const textLine = textLines[index] ?? "";
|
|
134
|
+
renderedRows.push(textLine.length > 0 ? `${avatarLine} ${textLine}` : avatarLine);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return renderedRows.join("\n");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Builds the terminal `whoami` output with a tiny ANSI avatar when supported.
|
|
142
|
+
*
|
|
143
|
+
* @param input The display name, email, and optional avatar image URL.
|
|
144
|
+
* @returns The formatted `whoami` string ready for stdout.
|
|
145
|
+
* @remarks Non-TTY terminals and avatar failures fall back to plain text without throwing.
|
|
146
|
+
* @lastModified 2026-03-19
|
|
147
|
+
* @author GPT-5.4
|
|
148
|
+
*/
|
|
149
|
+
export async function formatWhoamiWithAvatar(input: {
|
|
150
|
+
displayName: string;
|
|
151
|
+
email: string | null;
|
|
152
|
+
imageUrl: string | null;
|
|
153
|
+
}): Promise<string> {
|
|
154
|
+
const textLines = [`Signed in as ${input.displayName}.`, input.email ?? ""].filter(
|
|
155
|
+
(line) => line.length > 0,
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
if (!supportsAnsiAvatar() || input.imageUrl === null) {
|
|
159
|
+
return textLines.join("\n");
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
const avatarLines = await renderAvatarLines(input.imageUrl);
|
|
164
|
+
return joinAvatarAndText(avatarLines, textLines);
|
|
165
|
+
} catch {
|
|
166
|
+
return textLines.join("\n");
|
|
167
|
+
}
|
|
168
|
+
}
|