diff --git a/bin/index.js b/bin/index.js index 28853ab..eae197e 100755 --- a/bin/index.js +++ b/bin/index.js @@ -26,9 +26,12 @@ async function main() { program .command('login') .description('Login to Puter account') - .option('-s, --save', 'Save authentication token in .env file', '') - .action(async () => { - await login(); + .option('-s, --save', 'Save authentication token in .env file') + .option('--web', 'Use browser-based login (default)') + .option('--with-credentials', 'Use username/password login') + .option('--host ', 'Puter host URL', 'https://puter.com') + .action(async (options) => { + await login(options); process.exit(0); }); diff --git a/package.json b/package.json index b7bf8f9..4b71cd9 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "author": "Ibrahim.H", "license": "MIT", "dependencies": { - "@heyputer/puter.js": "^2.1.2", + "@heyputer/puter.js": "^2.2.8", "chalk": "^5.3.0", "cli-table3": "^0.6.5", "commander": "^13.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0c7acad..87b1b52 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@heyputer/puter.js': - specifier: ^2.1.2 - version: 2.1.2 + specifier: ^2.2.8 + version: 2.2.8 chalk: specifier: ^5.3.0 version: 5.6.2 @@ -28,7 +28,7 @@ dependencies: version: 16.6.1 glob: specifier: ^11.0.0 - version: 11.0.3 + version: 11.1.0 inquirer: specifier: ^9.2.12 version: 9.3.8 @@ -79,16 +79,16 @@ packages: engines: {node: '>=6.9.0'} dev: true - /@babel/parser@7.28.5: - resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + /@babel/parser@7.29.0: + resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.29.0 dev: true - /@babel/types@7.28.5: - resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + /@babel/types@7.29.0: + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-string-parser': 7.27.1 @@ -317,19 +317,15 @@ packages: resolution: {integrity: sha512-YhVtzz7ZA/HmuaDvzZZhhUyQWBvp3/TXeY4jULssTdLJwT+tEM4BTYHXttORX+V5auvrYinjj8dNFQnby5T82w==} dev: false - /@heyputer/puter.js@2.1.2: - resolution: {integrity: sha512-FZosKSj4CfvD3vmyXdYPtq3WHpyQnGYwrY8hmFH/WAOj3HQFDUyvKUqYFK3Z3OfIqUS2fZsG2n7LcTx/Vj1++w==} + /@heyputer/puter.js@2.2.8: + resolution: {integrity: sha512-94p16VYOnTLhsUerbPJMlTSKtY3j3E0p4DdtOiAIY7jnFpcGb7AgW+7nzVbGszc738XNcokWl0Z+V4ZWj82G5w==} dependencies: '@heyputer/kv.js': 0.2.1 - '@heyputer/putility': 1.1.1 - dev: false - - /@heyputer/putility@1.1.1: - resolution: {integrity: sha512-auedlVnHli2o8VtyR3Uj8JjlyaC1OPWHtcTgYdsMF46i+/lHz2iXK47Pwq2J9fdgM6sJX9lGtDZL6T10xJRrOA==} + open: 10.2.0 dev: false - /@inquirer/external-editor@1.0.2: - resolution: {integrity: sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==} + /@inquirer/external-editor@1.0.3: + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -338,11 +334,11 @@ packages: optional: true dependencies: chardet: 2.1.1 - iconv-lite: 0.7.0 + iconv-lite: 0.7.2 dev: false - /@inquirer/figures@1.0.14: - resolution: {integrity: sha512-DbFgdt+9/OZYFM+19dbpXOSeAstPy884FPy1KjDu4anWwymZeOYhMY1mdFri172htv6mvc/uvIAAi7b7tvjJBQ==} + /@inquirer/figures@1.0.15: + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} engines: {node: '>=18'} dev: false @@ -404,176 +400,200 @@ packages: dev: true optional: true - /@rollup/rollup-android-arm-eabi@4.52.5: - resolution: {integrity: sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==} + /@rollup/rollup-android-arm-eabi@4.57.1: + resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} cpu: [arm] os: [android] requiresBuild: true dev: true optional: true - /@rollup/rollup-android-arm64@4.52.5: - resolution: {integrity: sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==} + /@rollup/rollup-android-arm64@4.57.1: + resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==} cpu: [arm64] os: [android] requiresBuild: true dev: true optional: true - /@rollup/rollup-darwin-arm64@4.52.5: - resolution: {integrity: sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==} + /@rollup/rollup-darwin-arm64@4.57.1: + resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==} cpu: [arm64] os: [darwin] requiresBuild: true dev: true optional: true - /@rollup/rollup-darwin-x64@4.52.5: - resolution: {integrity: sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==} + /@rollup/rollup-darwin-x64@4.57.1: + resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==} cpu: [x64] os: [darwin] requiresBuild: true dev: true optional: true - /@rollup/rollup-freebsd-arm64@4.52.5: - resolution: {integrity: sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==} + /@rollup/rollup-freebsd-arm64@4.57.1: + resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==} cpu: [arm64] os: [freebsd] requiresBuild: true dev: true optional: true - /@rollup/rollup-freebsd-x64@4.52.5: - resolution: {integrity: sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==} + /@rollup/rollup-freebsd-x64@4.57.1: + resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==} cpu: [x64] os: [freebsd] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-arm-gnueabihf@4.52.5: - resolution: {integrity: sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==} + /@rollup/rollup-linux-arm-gnueabihf@4.57.1: + resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} cpu: [arm] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-arm-musleabihf@4.52.5: - resolution: {integrity: sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==} + /@rollup/rollup-linux-arm-musleabihf@4.57.1: + resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} cpu: [arm] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-arm64-gnu@4.52.5: - resolution: {integrity: sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==} + /@rollup/rollup-linux-arm64-gnu@4.57.1: + resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-arm64-musl@4.52.5: - resolution: {integrity: sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==} + /@rollup/rollup-linux-arm64-musl@4.57.1: + resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-loong64-gnu@4.52.5: - resolution: {integrity: sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==} + /@rollup/rollup-linux-loong64-gnu@4.57.1: + resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} cpu: [loong64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-ppc64-gnu@4.52.5: - resolution: {integrity: sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==} + /@rollup/rollup-linux-loong64-musl@4.57.1: + resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-ppc64-gnu@4.57.1: + resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-ppc64-musl@4.57.1: + resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} cpu: [ppc64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-riscv64-gnu@4.52.5: - resolution: {integrity: sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==} + /@rollup/rollup-linux-riscv64-gnu@4.57.1: + resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} cpu: [riscv64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-riscv64-musl@4.52.5: - resolution: {integrity: sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==} + /@rollup/rollup-linux-riscv64-musl@4.57.1: + resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} cpu: [riscv64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-s390x-gnu@4.52.5: - resolution: {integrity: sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==} + /@rollup/rollup-linux-s390x-gnu@4.57.1: + resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} cpu: [s390x] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-x64-gnu@4.52.5: - resolution: {integrity: sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==} + /@rollup/rollup-linux-x64-gnu@4.57.1: + resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-x64-musl@4.52.5: - resolution: {integrity: sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==} + /@rollup/rollup-linux-x64-musl@4.57.1: + resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-openharmony-arm64@4.52.5: - resolution: {integrity: sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==} + /@rollup/rollup-openbsd-x64@4.57.1: + resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-openharmony-arm64@4.57.1: + resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==} cpu: [arm64] os: [openharmony] requiresBuild: true dev: true optional: true - /@rollup/rollup-win32-arm64-msvc@4.52.5: - resolution: {integrity: sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==} + /@rollup/rollup-win32-arm64-msvc@4.57.1: + resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==} cpu: [arm64] os: [win32] requiresBuild: true dev: true optional: true - /@rollup/rollup-win32-ia32-msvc@4.52.5: - resolution: {integrity: sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==} + /@rollup/rollup-win32-ia32-msvc@4.57.1: + resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==} cpu: [ia32] os: [win32] requiresBuild: true dev: true optional: true - /@rollup/rollup-win32-x64-gnu@4.52.5: - resolution: {integrity: sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==} + /@rollup/rollup-win32-x64-gnu@4.57.1: + resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==} cpu: [x64] os: [win32] requiresBuild: true dev: true optional: true - /@rollup/rollup-win32-x64-msvc@4.52.5: - resolution: {integrity: sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==} + /@rollup/rollup-win32-x64-msvc@4.57.1: + resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==} cpu: [x64] os: [win32] requiresBuild: true @@ -772,6 +792,13 @@ packages: ieee754: 1.2.1 dev: false + /bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + dependencies: + run-applescript: 7.1.0 + dev: false + /cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -782,7 +809,7 @@ packages: engines: {node: '>=18'} dependencies: assertion-error: 2.0.1 - check-error: 2.1.1 + check-error: 2.1.3 deep-eql: 5.0.2 loupe: 3.2.1 pathval: 2.0.1 @@ -805,8 +832,8 @@ packages: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} dev: false - /check-error@2.1.1: - resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + /check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} engines: {node: '>= 16'} dev: true @@ -877,7 +904,7 @@ packages: debounce-fn: 5.1.2 dot-prop: 8.0.2 env-paths: 3.0.0 - json-schema-typed: 8.0.1 + json-schema-typed: 8.0.2 semver: 7.7.3 uint8array-extras: 0.3.0 dev: false @@ -919,12 +946,30 @@ packages: engines: {node: '>=6'} dev: true + /default-browser-id@5.0.1: + resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} + engines: {node: '>=18'} + dev: false + + /default-browser@5.5.0: + resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} + engines: {node: '>=18'} + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.1 + dev: false + /defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} dependencies: clone: 1.0.4 dev: false + /define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + dev: false + /dot-prop@8.0.2: resolution: {integrity: sha512-xaBe6ZT4DHPkg0k4Ytbvn5xoxgpG0jOS1dYxSOwAHPuNLjP3/OzN0gH55SrLqpx8cBfSaVt91lXYkApjb+nYdQ==} engines: {node: '>=16'} @@ -996,8 +1041,8 @@ packages: '@types/estree': 1.0.8 dev: true - /expect-type@1.2.2: - resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} + /expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} dev: true @@ -1044,8 +1089,8 @@ packages: engines: {node: '>=18'} dev: false - /glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + /glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} hasBin: true dependencies: foreground-child: 3.3.1 @@ -1056,8 +1101,8 @@ packages: path-scurry: 1.11.1 dev: true - /glob@11.0.3: - resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==} + /glob@11.1.0: + resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} engines: {node: 20 || >=22} hasBin: true dependencies: @@ -1066,7 +1111,7 @@ packages: minimatch: 10.1.1 minipass: 7.1.2 package-json-from-dist: 1.0.1 - path-scurry: 2.0.0 + path-scurry: 2.0.1 dev: false /handlebars@4.7.8: @@ -1090,8 +1135,8 @@ packages: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} dev: true - /iconv-lite@0.7.0: - resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} + /iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 @@ -1123,8 +1168,8 @@ packages: resolution: {integrity: sha512-pFGGdaHrmRKMh4WoDDSowddgjT1Vkl90atobmTeSmcPGdYiwikch/m/Ef5wRaiamHejtw0cUUMMerzDUXCci2w==} engines: {node: '>=18'} dependencies: - '@inquirer/external-editor': 1.0.2 - '@inquirer/figures': 1.0.14 + '@inquirer/external-editor': 1.0.3 + '@inquirer/figures': 1.0.15 ansi-escapes: 4.3.2 cli-width: 4.1.0 mute-stream: 1.0.0 @@ -1139,10 +1184,24 @@ packages: - '@types/node' dev: false + /is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + dev: false + /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + /is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + dependencies: + is-docker: 3.0.0 + dev: false + /is-interactive@1.0.0: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} @@ -1168,6 +1227,13 @@ packages: engines: {node: '>=18'} dev: false + /is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + dependencies: + is-inside-container: 1.0.0 + dev: false + /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -1223,8 +1289,8 @@ packages: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} dev: false - /json-schema-typed@8.0.1: - resolution: {integrity: sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg==} + /json-schema-typed@8.0.2: + resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} dev: false /log-symbols@4.1.0: @@ -1251,8 +1317,8 @@ packages: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} dev: true - /lru-cache@11.2.2: - resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} + /lru-cache@11.2.5: + resolution: {integrity: sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==} engines: {node: 20 || >=22} dev: false @@ -1265,8 +1331,8 @@ packages: /magicast@0.3.5: resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 source-map-js: 1.2.1 dev: true @@ -1374,6 +1440,16 @@ packages: mimic-function: 5.0.1 dev: false + /open@10.2.0: + resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} + engines: {node: '>=18'} + dependencies: + default-browser: 5.5.0 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + wsl-utils: 0.1.0 + dev: false + /ora@5.4.1: resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} engines: {node: '>=10'} @@ -1425,11 +1501,11 @@ packages: minipass: 7.1.2 dev: true - /path-scurry@2.0.0: - resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + /path-scurry@2.0.1: + resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} engines: {node: 20 || >=22} dependencies: - lru-cache: 11.2.2 + lru-cache: 11.2.5 minipass: 7.1.2 dev: false @@ -1490,38 +1566,46 @@ packages: signal-exit: 4.1.0 dev: false - /rollup@4.52.5: - resolution: {integrity: sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==} + /rollup@4.57.1: + resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.52.5 - '@rollup/rollup-android-arm64': 4.52.5 - '@rollup/rollup-darwin-arm64': 4.52.5 - '@rollup/rollup-darwin-x64': 4.52.5 - '@rollup/rollup-freebsd-arm64': 4.52.5 - '@rollup/rollup-freebsd-x64': 4.52.5 - '@rollup/rollup-linux-arm-gnueabihf': 4.52.5 - '@rollup/rollup-linux-arm-musleabihf': 4.52.5 - '@rollup/rollup-linux-arm64-gnu': 4.52.5 - '@rollup/rollup-linux-arm64-musl': 4.52.5 - '@rollup/rollup-linux-loong64-gnu': 4.52.5 - '@rollup/rollup-linux-ppc64-gnu': 4.52.5 - '@rollup/rollup-linux-riscv64-gnu': 4.52.5 - '@rollup/rollup-linux-riscv64-musl': 4.52.5 - '@rollup/rollup-linux-s390x-gnu': 4.52.5 - '@rollup/rollup-linux-x64-gnu': 4.52.5 - '@rollup/rollup-linux-x64-musl': 4.52.5 - '@rollup/rollup-openharmony-arm64': 4.52.5 - '@rollup/rollup-win32-arm64-msvc': 4.52.5 - '@rollup/rollup-win32-ia32-msvc': 4.52.5 - '@rollup/rollup-win32-x64-gnu': 4.52.5 - '@rollup/rollup-win32-x64-msvc': 4.52.5 + '@rollup/rollup-android-arm-eabi': 4.57.1 + '@rollup/rollup-android-arm64': 4.57.1 + '@rollup/rollup-darwin-arm64': 4.57.1 + '@rollup/rollup-darwin-x64': 4.57.1 + '@rollup/rollup-freebsd-arm64': 4.57.1 + '@rollup/rollup-freebsd-x64': 4.57.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.57.1 + '@rollup/rollup-linux-arm-musleabihf': 4.57.1 + '@rollup/rollup-linux-arm64-gnu': 4.57.1 + '@rollup/rollup-linux-arm64-musl': 4.57.1 + '@rollup/rollup-linux-loong64-gnu': 4.57.1 + '@rollup/rollup-linux-loong64-musl': 4.57.1 + '@rollup/rollup-linux-ppc64-gnu': 4.57.1 + '@rollup/rollup-linux-ppc64-musl': 4.57.1 + '@rollup/rollup-linux-riscv64-gnu': 4.57.1 + '@rollup/rollup-linux-riscv64-musl': 4.57.1 + '@rollup/rollup-linux-s390x-gnu': 4.57.1 + '@rollup/rollup-linux-x64-gnu': 4.57.1 + '@rollup/rollup-linux-x64-musl': 4.57.1 + '@rollup/rollup-openbsd-x64': 4.57.1 + '@rollup/rollup-openharmony-arm64': 4.57.1 + '@rollup/rollup-win32-arm64-msvc': 4.57.1 + '@rollup/rollup-win32-ia32-msvc': 4.57.1 + '@rollup/rollup-win32-x64-gnu': 4.57.1 + '@rollup/rollup-win32-x64-msvc': 4.57.1 fsevents: 2.3.3 dev: true + /run-applescript@7.1.0: + resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} + engines: {node: '>=18'} + dev: false + /run-async@3.0.0: resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} engines: {node: '>=0.12.0'} @@ -1655,7 +1739,7 @@ packages: engines: {node: '>=18'} dependencies: '@istanbuljs/schema': 0.1.3 - glob: 10.4.5 + glob: 10.5.0 minimatch: 9.0.5 dev: true @@ -1777,7 +1861,7 @@ packages: dependencies: esbuild: 0.21.5 postcss: 8.5.6 - rollup: 4.52.5 + rollup: 4.57.1 optionalDependencies: fsevents: 2.3.3 dev: true @@ -1816,7 +1900,7 @@ packages: '@vitest/utils': 2.1.9 chai: 5.3.3 debug: 4.4.3 - expect-type: 1.2.2 + expect-type: 1.3.0 magic-string: 0.30.21 pathe: 1.1.2 std-env: 3.10.0 @@ -1910,6 +1994,13 @@ packages: string-width: 5.1.2 strip-ansi: 7.1.2 + /wsl-utils@0.1.0: + resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} + engines: {node: '>=18'} + dependencies: + is-wsl: 3.1.0 + dev: false + /yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} diff --git a/src/commands/auth.js b/src/commands/auth.js index 8a19dc1..e5e0052 100644 --- a/src/commands/auth.js +++ b/src/commands/auth.js @@ -8,11 +8,16 @@ const config = new Conf({ projectName: PROJECT_NAME }); /** * Login user + * @param {Object} options - Login options + * @param {boolean} options.save - Save token to .env file + * @param {boolean} options.web - Use browser-based login (default) + * @param {boolean} options.withCredentials - Use username/password login + * @param {string} options.host - Puter host URL * @returns void */ -export async function login() { - const profileAPI = getProfileModule();; - await profileAPI.switchProfileWizard(); +export async function login(options = {}) { + const profileAPI = getProfileModule(); + await profileAPI.switchProfileWizard(options); } /** diff --git a/src/modules/ProfileModule.js b/src/modules/ProfileModule.js index 32b9706..6536fe0 100644 --- a/src/modules/ProfileModule.js +++ b/src/modules/ProfileModule.js @@ -3,6 +3,8 @@ import inquirer from 'inquirer'; import Conf from 'conf'; import chalk from 'chalk'; import ora from 'ora'; +import {getAuthToken} from "@heyputer/puter.js/src/init.cjs"; +import { puter } from "@heyputer/puter.js"; // project import { BASE_URL, NULL_UUID, PROJECT_NAME, getHeaders, reconfigureURLs } from '../commons.js' @@ -108,10 +110,9 @@ class ProfileModule { async switchProfileWizard(args = {}) { const profiles = this.getProfiles(); if (profiles.length < 1) { - return this.addProfileWizard(); + return this.addProfileWizard(args); } - // console.log('doing this branch'); const answer = await inquirer.prompt([ { name: 'profile', @@ -133,21 +134,79 @@ class ProfileModule { ]); if (answer.profile === 'new') { - return await this.addProfileWizard(); + return await this.addProfileWizard(args); } this.selectProfile(answer.profile); } async addProfileWizard(args = {}) { + const host = args.host || 'https://puter.com'; + + if (args.withCredentials) { + return await this.credentialLogin({ ...args, host }); + } + + // Browser-based login (default) + return await this.browserLogin({ ...args, host }); + } + + async browserLogin(args) { + const { host, save } = args; + const TIMEOUT_MS = 60000; // 1 minute timeout + let spinner; + + try { + spinner = ora('Opening browser for login...').start(); + + const timeoutPromise = new Promise((_, reject) => { + setTimeout(() => reject(new Error('Login timed out after 60 seconds')), TIMEOUT_MS); + }); + + const authToken = await Promise.race([ + getAuthToken(), + timeoutPromise + ]); + + if (!authToken) { + spinner.fail(chalk.red('Login failed or was cancelled.')); + return; + } + + spinner.text = 'Fetching user info...'; + + // Set token and fetch user info + puter.setAuthToken(authToken); + const userInfo = await puter.auth.getUser(); + + const profileUUID = crypto.randomUUID(); + const profile = { + host, + username: userInfo.username, + cwd: `/${userInfo.username}`, + token: authToken, + uuid: profileUUID, + }; + + this.addProfile(profile); + this.selectProfile(profile); + spinner.succeed(chalk.green(`Successfully logged in as ${userInfo.username}!`)); + + // Handle --save option + this.saveTokenToEnv(authToken, save); + } catch (error) { + if (spinner) { + spinner.fail(chalk.red(`Failed to login: ${error.message}`)); + } else { + console.error(chalk.red(`Failed to login: ${error.message}`)); + } + } + } + + async credentialLogin(args) { + const { host, save } = args; + const answers = await inquirer.prompt([ - { - type: 'input', - name: 'host', - message: 'Host (leave blank for puter.com):', - default: 'https://puter.com', - validate: input => input.length >= 1 || 'Host is required' - }, { type: 'input', name: 'username', @@ -167,100 +226,96 @@ class ProfileModule { try { spinner = ora('Logging in to Puter...').start(); - const response = await fetch(`${answers.host}/login`, { + const apiHost = toApiSubdomain(host); + const response = await fetch(`${apiHost}/login`, { method: 'POST', headers: getHeaders(), body: JSON.stringify({ username: answers.username, - password: answers.password - }) + password: answers.password, + }), }); + const data = await response.json(); - const contentType = response.headers.get('content-type'); - //console.log('content type?', '|' + contentType + '|'); - - // TODO: proper content type parsing - if (!contentType.trim().startsWith('application/json')) { - throw new Error(await response.text()); - } - - let data = await response.json(); - - while (data.proceed && data.next_step) { - if (data.next_step === 'otp') { - spinner.succeed(chalk.green('2FA is enabled')); - const answers2FA = await inquirer.prompt([ - { - type: 'input', - name: 'otp', - message: 'Authenticator Code:', - validate: input => input.length === 6 || 'OTP must be 6 digits' - } - ]); - spinner = ora('Logging in to Puter...').start(); - const response = await fetch(`${answers.host}/login/otp`, { - method: 'POST', - headers: getHeaders(), - body: JSON.stringify({ - token: data.otp_jwt_token, - code: answers2FA.otp, - }), - }); - data = await response.json(); - continue; - } + if (data.proceed && data.next_step === 'otp') { + // Handle 2FA + spinner.stop(); + const otpAnswer = await inquirer.prompt([ + { + type: 'input', + name: 'otp', + message: 'Enter your 2FA code:', + validate: input => input.length >= 1 || '2FA code is required' + } + ]); - if (data.next_step === 'complete') break; + spinner = ora('Verifying 2FA code...').start(); + const otpResponse = await fetch(`${apiHost}/login/otp`, { + method: 'POST', + headers: getHeaders(), + body: JSON.stringify({ + token: data.otp_jwt_token, + code: otpAnswer.otp, + }), + }); - spinner.fail(chalk.red(`Unrecognized login step "${data.next_step}"; you might need to update puter-cli.`)); - return; - } + const otpData = await otpResponse.json(); - if (data.proceed && data.token) { - const profileUUID = crypto.randomUUID(); - const profile = { - host: answers.host, - username: answers.username, - cwd: `/${answers.username}`, - token: data.token, - uuid: profileUUID, - }; - this.addProfile(profile); - this.selectProfile(profile); - if (spinner) { - spinner.succeed(chalk.green('Successfully logged in to Puter!')); - } - console.log(chalk.dim(`Token: ${data.token.slice(0, 5)}...${data.token.slice(-5)}`)); - // Save token - if (args.save) { - const localEnvFile = '.env'; - try { - // Check if the file exists, if so then append the api key to the EOF. - if (fs.existsSync(localEnvFile)) { - console.log(chalk.yellow(`File "${localEnvFile}" already exists... Adding token.`)); - fs.appendFileSync(localEnvFile, `\nPUTER_API_KEY="${data.token}"`, 'utf8'); - } else { - console.log(chalk.cyan(`Saving token to ${chalk.green(localEnvFile)} file.`)); - fs.writeFileSync(localEnvFile, `PUTER_API_KEY="${data.token}"`, 'utf8'); - } - } catch (error) { - console.error(chalk.red(`Cannot save token to .env file. Error: ${error.message}`)); - console.log(chalk.cyan(`PUTER_API_KEY="${data.token}"`)); - } + if (otpData.token) { + this.createProfileFromToken(otpData.token, answers.username, host, spinner, save); + } else { + spinner.fail(chalk.red('2FA verification failed.')); } + } else if (data.token) { + this.createProfileFromToken(data.token, answers.username, host, spinner, save); } else { - spinner.fail(chalk.red('Login failed. Please check your credentials.')); + spinner.fail(chalk.red(data.error?.message || 'Login failed. Please check your credentials.')); } } catch (error) { if (spinner) { spinner.fail(chalk.red(`Failed to login: ${error.message}`)); - console.log(error); } else { console.error(chalk.red(`Failed to login: ${error.message}`)); } } } + + createProfileFromToken(token, username, host, spinner, save) { + const profileUUID = crypto.randomUUID(); + const profile = { + host, + username, + cwd: `/${username}`, + token, + uuid: profileUUID, + }; + + this.addProfile(profile); + this.selectProfile(profile); + spinner.succeed(chalk.green(`Successfully logged in as ${username}!`)); + + // Handle --save option + this.saveTokenToEnv(token, save); + } + + saveTokenToEnv(token, save) { + if (!save) return; + + const localEnvFile = '.env'; + try { + if (fs.existsSync(localEnvFile)) { + console.log(chalk.yellow(`File "${localEnvFile}" already exists... Adding token.`)); + fs.appendFileSync(localEnvFile, `\nPUTER_API_KEY="${token}"`, 'utf8'); + } else { + console.log(chalk.cyan(`Saving token to ${chalk.green(localEnvFile)} file.`)); + fs.writeFileSync(localEnvFile, `PUTER_API_KEY="${token}"`, 'utf8'); + } + } catch (error) { + console.error(chalk.red(`Cannot save token to .env file. Error: ${error.message}`)); + console.log(chalk.cyan(`PUTER_API_KEY="${token}"`)); + } + } } export const initProfileModule = () => {