puter-cli 1.8.6 → 2.0.0
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/.github/workflows/npm-build.yml +4 -3
- package/CHANGELOG.md +29 -0
- package/README.md +10 -2
- package/bin/index.js +184 -30
- package/package.json +12 -12
- package/src/commands/apps.js +53 -139
- package/src/commands/auth.js +113 -115
- package/src/commands/deploy.js +29 -27
- package/src/commands/files.js +151 -512
- package/src/commands/shell.js +13 -25
- package/src/commands/sites.js +25 -83
- package/src/commands/subdomains.js +46 -55
- package/src/commons.js +2 -2
- package/src/executor.js +26 -26
- package/src/modules/ErrorModule.js +18 -31
- package/src/modules/ProfileModule.js +183 -123
- package/src/modules/PuterModule.js +30 -0
- package/tests/ErrorModule.test.js +42 -0
- package/tests/ProfileModule.test.js +274 -0
- package/tests/PuterModule.test.js +56 -0
- package/tests/apps.test.js +194 -0
- package/tests/commons.test.js +380 -0
- package/tests/deploy.test.js +84 -0
- package/tests/executor.test.js +52 -0
- package/tests/files.test.js +640 -0
- package/tests/login.test.js +69 -51
- package/tests/shell.test.js +184 -0
- package/tests/sites.test.js +67 -0
- package/tests/subdomains.test.js +90 -0
- package/src/modules/SetContextModule.js +0 -5
- package/src/temporary/context_helpers.js +0 -17
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# This workflow will run tests using node on every push
|
|
1
|
+
# This workflow will run tests using node on every push and pull request
|
|
2
2
|
name: Build package
|
|
3
3
|
|
|
4
|
-
on: push
|
|
4
|
+
on: [push, pull_request]
|
|
5
5
|
|
|
6
6
|
jobs:
|
|
7
7
|
build:
|
|
@@ -9,7 +9,7 @@ jobs:
|
|
|
9
9
|
|
|
10
10
|
strategy:
|
|
11
11
|
matrix:
|
|
12
|
-
node-version: ['
|
|
12
|
+
node-version: ['20.x', '22.x', '24.x']
|
|
13
13
|
steps:
|
|
14
14
|
- uses: actions/checkout@v4
|
|
15
15
|
- name: Install pnpm
|
|
@@ -26,6 +26,7 @@ jobs:
|
|
|
26
26
|
- name: Run tests & coverage
|
|
27
27
|
run: pnpm run coverage
|
|
28
28
|
- name: Upload coverage reports to Codecov
|
|
29
|
+
if: github.event_name != 'pull_request'
|
|
29
30
|
uses: codecov/codecov-action@v5
|
|
30
31
|
with:
|
|
31
32
|
token: ${{ secrets.CODECOV_TOKEN }}
|
package/CHANGELOG.md
CHANGED
|
@@ -4,8 +4,37 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
#### [v2.0.0](https://github.com/HeyPuter/puter-cli/compare/v1.8.6...v2.0.0)
|
|
8
|
+
|
|
9
|
+
- Add browser based login [`#75`](https://github.com/HeyPuter/puter-cli/pull/75)
|
|
10
|
+
- Adjust actions for PR test [`#73`](https://github.com/HeyPuter/puter-cli/pull/73)
|
|
11
|
+
- Add test for file commands [`#69`](https://github.com/HeyPuter/puter-cli/pull/69)
|
|
12
|
+
- Add deploy test [`#68`](https://github.com/HeyPuter/puter-cli/pull/68)
|
|
13
|
+
- Add executor test [`#67`](https://github.com/HeyPuter/puter-cli/pull/67)
|
|
14
|
+
- Add ProfileModule test [`#66`](https://github.com/HeyPuter/puter-cli/pull/66)
|
|
15
|
+
- Add commons.test.js [`#64`](https://github.com/HeyPuter/puter-cli/pull/64)
|
|
16
|
+
- Add test shell [`#65`](https://github.com/HeyPuter/puter-cli/pull/65)
|
|
17
|
+
- Add PuterModule test [`#63`](https://github.com/HeyPuter/puter-cli/pull/63)
|
|
18
|
+
- Add test error module [`#62`](https://github.com/HeyPuter/puter-cli/pull/62)
|
|
19
|
+
- Add subdomains test [`#61`](https://github.com/HeyPuter/puter-cli/pull/61)
|
|
20
|
+
- Add sites test [`#60`](https://github.com/HeyPuter/puter-cli/pull/60)
|
|
21
|
+
- Fix first init puter module [`#59`](https://github.com/HeyPuter/puter-cli/pull/59)
|
|
22
|
+
- Fix puter module causing unref error [`#52`](https://github.com/HeyPuter/puter-cli/pull/52)
|
|
23
|
+
- Migrate drivers call to Puter.js NPM [`#33`](https://github.com/HeyPuter/puter-cli/pull/33)
|
|
24
|
+
- Add non interactive puter site deploy [`#30`](https://github.com/HeyPuter/puter-cli/pull/30)
|
|
25
|
+
- Set program name to be hardcoded puter string [`#32`](https://github.com/HeyPuter/puter-cli/pull/32)
|
|
26
|
+
- Enable site:deploy redeploy under same subdomain [`#26`](https://github.com/HeyPuter/puter-cli/pull/26)
|
|
27
|
+
- Fix CLI close unexpectedly when first login [`#29`](https://github.com/HeyPuter/puter-cli/pull/29)
|
|
28
|
+
- Fix logout [`#28`](https://github.com/HeyPuter/puter-cli/pull/28)
|
|
29
|
+
- Site deploy from local dir [`#25`](https://github.com/HeyPuter/puter-cli/pull/25)
|
|
30
|
+
- Fix CI [`0b189de`](https://github.com/HeyPuter/puter-cli/commit/0b189dede790280bdf6e2a4691843970eb7ea83f)
|
|
31
|
+
- Init puter js npm [`b1bd5e7`](https://github.com/HeyPuter/puter-cli/commit/b1bd5e78a232391a2102e85e3ee0c0665ed1a00b)
|
|
32
|
+
- Update pnpm-lock.yaml [`9f7f8fc`](https://github.com/HeyPuter/puter-cli/commit/9f7f8fc7921427a580fe0bb8ca0dd10fe5db8b6b)
|
|
33
|
+
|
|
7
34
|
#### [v1.8.6](https://github.com/HeyPuter/puter-cli/compare/v1.8.5...v1.8.6)
|
|
8
35
|
|
|
36
|
+
> 8 October 2025
|
|
37
|
+
|
|
9
38
|
- Use random name if not specified for `site:deploy` [`#24`](https://github.com/HeyPuter/puter-cli/pull/24)
|
|
10
39
|
- Use random name if not specified [`48ae3f0`](https://github.com/HeyPuter/puter-cli/commit/48ae3f04325f27b654e00050c7ec514bee72535e)
|
|
11
40
|
- docs(readme): update site command [`aa4ba6e`](https://github.com/HeyPuter/puter-cli/commit/aa4ba6e1ee52e1c6e2c0cb5fb74c120fb1b5c0c3)
|
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ The **Puter CLI** is a command-line interface tool designed to interact with the
|
|
|
36
36
|
## Installation
|
|
37
37
|
|
|
38
38
|
### Prerequisites
|
|
39
|
-
- Node.js (
|
|
39
|
+
- Node.js (v20 or higher)
|
|
40
40
|
- npm (v7 or higher)
|
|
41
41
|
|
|
42
42
|
Run the following command to install puter-cli globally in your system:
|
|
@@ -258,10 +258,18 @@ or just type (you'll need to login):
|
|
|
258
258
|
|
|
259
259
|
## Examples
|
|
260
260
|
|
|
261
|
-
|
|
261
|
+
In order to execute any command you'll need to authenticate first, this is a one time action:
|
|
262
262
|
```bash
|
|
263
|
+
# This will open the browser to authenticate you for the first time.
|
|
263
264
|
puter login
|
|
265
|
+
# or (if you want to authenticate using your username/password)
|
|
266
|
+
#puter login --with-credentials
|
|
267
|
+
```
|
|
268
|
+
1. **Log in and List Files**:
|
|
269
|
+
```bash
|
|
264
270
|
puter> ls
|
|
271
|
+
# or list files in a specific directory:
|
|
272
|
+
puter> ls /
|
|
265
273
|
```
|
|
266
274
|
|
|
267
275
|
2. **Create and Deploy a Static Site**:
|
package/bin/index.js
CHANGED
|
@@ -5,30 +5,43 @@ import { login, logout } from '../src/commands/auth.js';
|
|
|
5
5
|
import { init } from '../src/commands/init.js';
|
|
6
6
|
import { startShell } from '../src/commands/shell.js';
|
|
7
7
|
import { PROJECT_NAME, getLatestVersion } from '../src/commons.js';
|
|
8
|
-
import { createApp } from '../src/commands/apps.js';
|
|
9
|
-
import
|
|
8
|
+
import { appInfo, createApp, listApps, deleteApp, updateApp } from '../src/commands/apps.js';
|
|
9
|
+
import inquirer from 'inquirer';
|
|
10
|
+
import { initProfileModule } from '../src/modules/ProfileModule.js';
|
|
11
|
+
import { initPuterModule } from '../src/modules/PuterModule.js';
|
|
12
|
+
import { createSite, infoSite, listSites, deleteSite } from '../src/commands/sites.js';
|
|
10
13
|
|
|
11
14
|
async function main() {
|
|
15
|
+
initProfileModule();
|
|
16
|
+
initPuterModule();
|
|
17
|
+
|
|
12
18
|
const version = await getLatestVersion(PROJECT_NAME);
|
|
13
19
|
|
|
14
20
|
const program = new Command();
|
|
15
21
|
program
|
|
16
|
-
.name(
|
|
22
|
+
.name('puter')
|
|
17
23
|
.description('CLI tool for Puter cloud platform')
|
|
18
24
|
.version(version);
|
|
19
25
|
|
|
20
26
|
program
|
|
21
27
|
.command('login')
|
|
22
28
|
.description('Login to Puter account')
|
|
23
|
-
.option('-s, --save', 'Save authentication token in .env file'
|
|
24
|
-
.
|
|
25
|
-
|
|
29
|
+
.option('-s, --save', 'Save authentication token in .env file')
|
|
30
|
+
.option('--web', 'Use browser-based login (default)')
|
|
31
|
+
.option('--with-credentials', 'Use username/password login')
|
|
32
|
+
.option('--host <url>', 'Puter host URL', 'https://puter.com')
|
|
33
|
+
.action(async (options) => {
|
|
34
|
+
await login(options);
|
|
35
|
+
process.exit(0);
|
|
26
36
|
});
|
|
27
37
|
|
|
28
38
|
program
|
|
29
39
|
.command('logout')
|
|
30
40
|
.description('Logout from Puter account')
|
|
31
|
-
.action(
|
|
41
|
+
.action(async () => {
|
|
42
|
+
await logout();
|
|
43
|
+
process.exit(0);
|
|
44
|
+
});
|
|
32
45
|
|
|
33
46
|
program
|
|
34
47
|
.command('init')
|
|
@@ -38,24 +51,46 @@ async function main() {
|
|
|
38
51
|
program
|
|
39
52
|
.command('shell')
|
|
40
53
|
.description('Start interactive shell')
|
|
41
|
-
.action(startShell);
|
|
54
|
+
.action(() => startShell());
|
|
42
55
|
|
|
43
56
|
|
|
44
57
|
// App commands
|
|
45
58
|
program
|
|
46
|
-
.command('
|
|
47
|
-
.description('
|
|
59
|
+
.command('apps')
|
|
60
|
+
.description('List all your apps')
|
|
61
|
+
.argument('[period]', 'period: today, yesterday, 7d, 30d, this_month, last_month')
|
|
62
|
+
.action(async (period) => {
|
|
63
|
+
await listApps({
|
|
64
|
+
statsPeriod: period || 'all'
|
|
65
|
+
});
|
|
66
|
+
process.exit(0);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const app = program
|
|
70
|
+
.command('app')
|
|
71
|
+
.description('App management commands');
|
|
72
|
+
|
|
73
|
+
app
|
|
74
|
+
.command('info')
|
|
75
|
+
.description('Get application information')
|
|
76
|
+
.argument('<app_name>', 'Name of the application')
|
|
77
|
+
.action(async (app_name) => {
|
|
78
|
+
await appInfo([app_name]);
|
|
79
|
+
process.exit(0);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
app
|
|
83
|
+
.command('create')
|
|
84
|
+
.description('Create a new app')
|
|
48
85
|
.argument('<name>', 'Name of the application')
|
|
49
|
-
.argument('
|
|
50
|
-
.
|
|
51
|
-
.option('-u, --url <url>', 'Application URL', 'https://dev-center.puter.com/coming-soon.html')
|
|
52
|
-
.action(async (name, remoteDir, options) => {
|
|
86
|
+
.argument('<remote_dir>', 'Remote directory URL')
|
|
87
|
+
.action(async (name, remote_dir) => {
|
|
53
88
|
try {
|
|
54
89
|
await createApp({
|
|
55
|
-
name,
|
|
56
|
-
directory:
|
|
57
|
-
description:
|
|
58
|
-
url:
|
|
90
|
+
name: name,
|
|
91
|
+
directory: remote_dir || '',
|
|
92
|
+
description: '',
|
|
93
|
+
url: 'https://dev-center.puter.com/coming-soon.html'
|
|
59
94
|
});
|
|
60
95
|
} catch (error) {
|
|
61
96
|
console.error(chalk.red(error.message));
|
|
@@ -63,21 +98,140 @@ async function main() {
|
|
|
63
98
|
process.exit(0);
|
|
64
99
|
});
|
|
65
100
|
|
|
66
|
-
|
|
101
|
+
app
|
|
102
|
+
.command('update')
|
|
103
|
+
.description('Update an app')
|
|
104
|
+
.argument('<name>', 'Name of the application')
|
|
105
|
+
.argument('[dir]', 'Directory path', '.')
|
|
106
|
+
.action(async (name, dir) => {
|
|
107
|
+
await updateApp([name, dir]);
|
|
108
|
+
process.exit(0);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
app
|
|
112
|
+
.command('delete')
|
|
113
|
+
.description('Delete an app')
|
|
114
|
+
.argument('<name>', 'Name of the application')
|
|
115
|
+
.option('-f, --force', 'Force deletion without confirmation')
|
|
116
|
+
.action(async (name, options) => {
|
|
117
|
+
let shouldDelete = options.force;
|
|
118
|
+
|
|
119
|
+
if (!shouldDelete) {
|
|
120
|
+
const answer = await inquirer.prompt([
|
|
121
|
+
{
|
|
122
|
+
type: 'confirm',
|
|
123
|
+
name: 'confirm',
|
|
124
|
+
message: `Are you sure you want to delete the app "${name}"?`,
|
|
125
|
+
default: false
|
|
126
|
+
}
|
|
127
|
+
]);
|
|
128
|
+
shouldDelete = answer.confirm;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (shouldDelete) {
|
|
132
|
+
await deleteApp(name);
|
|
133
|
+
} else {
|
|
134
|
+
console.log(chalk.yellow('App deletion cancelled.'));
|
|
135
|
+
}
|
|
136
|
+
process.exit(0);
|
|
137
|
+
});
|
|
138
|
+
|
|
67
139
|
program
|
|
68
|
-
.command('
|
|
140
|
+
.command('sites')
|
|
141
|
+
.description('List sites and subdomains')
|
|
142
|
+
.action(async () => {
|
|
143
|
+
await listSites();
|
|
144
|
+
process.exit(0);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const site = program
|
|
148
|
+
.command('site')
|
|
149
|
+
.description('Site management commands');
|
|
150
|
+
|
|
151
|
+
site
|
|
152
|
+
.command('info')
|
|
153
|
+
.description('Get site information by UID')
|
|
154
|
+
.argument('<site_uid>', 'Site UID')
|
|
155
|
+
.action(async (site_uid) => {
|
|
156
|
+
await infoSite([site_uid]);
|
|
157
|
+
process.exit(0);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
site
|
|
161
|
+
.command('create')
|
|
162
|
+
.description('Create a static website from directory')
|
|
163
|
+
.argument('<app_name>', 'Application name')
|
|
164
|
+
.argument('[dir]', 'Directory path')
|
|
165
|
+
.option('--subdomain <name>', 'Subdomain name')
|
|
166
|
+
.action(async (app_name, dir, options) => {
|
|
167
|
+
const args = [app_name];
|
|
168
|
+
if (dir) args.push(dir);
|
|
169
|
+
if (options.subdomain) args.push(`--subdomain=${options.subdomain}`)
|
|
170
|
+
|
|
171
|
+
await createSite(args)
|
|
172
|
+
process.exit(0);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
site
|
|
176
|
+
.command('deploy')
|
|
69
177
|
.description('Deploy a local web project to Puter')
|
|
70
|
-
.argument('[
|
|
71
|
-
.
|
|
72
|
-
.action(async (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
178
|
+
.argument('[local_dir]', 'Local directory path')
|
|
179
|
+
.argument('[subdomain]', 'Deployment subdomain (<subdomain>.puter.site)')
|
|
180
|
+
.action(async (local_dir, subdomain) => {
|
|
181
|
+
if (!local_dir) {
|
|
182
|
+
const answer = await inquirer.prompt([
|
|
183
|
+
{
|
|
184
|
+
type: 'input',
|
|
185
|
+
name: 'local_dir',
|
|
186
|
+
message: 'Local directory path:',
|
|
187
|
+
default: '.'
|
|
188
|
+
}
|
|
189
|
+
]);
|
|
190
|
+
local_dir = answer.local_dir;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (!subdomain) {
|
|
194
|
+
const answer = await inquirer.prompt([
|
|
195
|
+
{
|
|
196
|
+
type: 'input',
|
|
197
|
+
name: 'subdomain',
|
|
198
|
+
message: 'Deployment subdomain (leave empty for random):',
|
|
199
|
+
}
|
|
200
|
+
]);
|
|
201
|
+
subdomain = answer.subdomain;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
await startShell(`site:deploy ${local_dir}${subdomain ? ` --subdomain=${subdomain}` : ''}`)
|
|
205
|
+
process.exit(0);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
site
|
|
209
|
+
.command('delete')
|
|
210
|
+
.description('Delete a site by UID')
|
|
211
|
+
.argument('<uid>', 'Site UID')
|
|
212
|
+
.option('-f, --force', 'Force deletion without confirmation')
|
|
213
|
+
.action(async (uid, options) => {
|
|
214
|
+
let shouldDelete = options.force;
|
|
215
|
+
|
|
216
|
+
if (!shouldDelete) {
|
|
217
|
+
const answer = await inquirer.prompt([
|
|
218
|
+
{
|
|
219
|
+
type: 'confirm',
|
|
220
|
+
name: 'confirm',
|
|
221
|
+
message: `Are you sure you want to delete the site with UID "${uid}"?`,
|
|
222
|
+
default: false
|
|
223
|
+
}
|
|
224
|
+
]);
|
|
225
|
+
shouldDelete = answer.confirm;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (shouldDelete) {
|
|
229
|
+
await deleteSite([uid]);
|
|
230
|
+
} else {
|
|
231
|
+
console.log(chalk.yellow('Site deletion cancelled.'));
|
|
232
|
+
}
|
|
233
|
+
process.exit(0);
|
|
79
234
|
});
|
|
80
|
-
*/
|
|
81
235
|
|
|
82
236
|
if (process.argv.length === 2) {
|
|
83
237
|
startShell();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "puter-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Command line interface for Puter cloud platform",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,8 +8,15 @@
|
|
|
8
8
|
},
|
|
9
9
|
"preferGlobal": true,
|
|
10
10
|
"type": "module",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"start": "node bin/index.js",
|
|
13
|
+
"test": "TZ=UTC vitest run tests/*",
|
|
14
|
+
"test:watch": "TZ=UTC vitest --watch tests/*",
|
|
15
|
+
"version": "auto-changelog -p && git add CHANGELOG.md",
|
|
16
|
+
"coverage": "TZ=UTC vitest run --coverage"
|
|
17
|
+
},
|
|
11
18
|
"engines": {
|
|
12
|
-
"node": ">=
|
|
19
|
+
"node": ">=20.0.0"
|
|
13
20
|
},
|
|
14
21
|
"keywords": [
|
|
15
22
|
"puter",
|
|
@@ -19,7 +26,7 @@
|
|
|
19
26
|
"author": "Ibrahim.H",
|
|
20
27
|
"license": "MIT",
|
|
21
28
|
"dependencies": {
|
|
22
|
-
"@heyputer/
|
|
29
|
+
"@heyputer/puter.js": "^2.2.8",
|
|
23
30
|
"chalk": "^5.3.0",
|
|
24
31
|
"cli-table3": "^0.6.5",
|
|
25
32
|
"commander": "^13.0.0",
|
|
@@ -46,12 +53,5 @@
|
|
|
46
53
|
"bugs": {
|
|
47
54
|
"url": "https://github.com/HeyPuter/puter-cli/issues"
|
|
48
55
|
},
|
|
49
|
-
"homepage": "https://github.com/HeyPuter/puter-cli"
|
|
50
|
-
|
|
51
|
-
"start": "node bin/index.js",
|
|
52
|
-
"test": "TZ=UTC vitest run tests/*",
|
|
53
|
-
"test:watch": "TZ=UTC vitest --watch tests/*",
|
|
54
|
-
"version": "auto-changelog -p && git add CHANGELOG.md",
|
|
55
|
-
"coverage": "TZ=UTC vitest run --coverage"
|
|
56
|
-
}
|
|
57
|
-
}
|
|
56
|
+
"homepage": "https://github.com/HeyPuter/puter-cli"
|
|
57
|
+
}
|