puter-cli 1.8.5 → 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 +38 -0
- package/README.md +18 -4
- package/bin/index.js +184 -31
- 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 +27 -28
- 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
package/src/commands/shell.js
CHANGED
|
@@ -3,18 +3,11 @@ import chalk from 'chalk';
|
|
|
3
3
|
import Conf from 'conf';
|
|
4
4
|
import { execCommand, getPrompt } from '../executor.js';
|
|
5
5
|
import { PROJECT_NAME } from '../commons.js';
|
|
6
|
-
import
|
|
7
|
-
import ErrorModule from '../modules/ErrorModule.js';
|
|
8
|
-
import ProfileModule from '../modules/ProfileModule.js';
|
|
9
|
-
import putility from '@heyputer/putility';
|
|
6
|
+
import { getProfileModule } from '../modules/ProfileModule.js';
|
|
10
7
|
|
|
11
8
|
const config = new Conf({ projectName: PROJECT_NAME });
|
|
12
9
|
|
|
13
|
-
export
|
|
14
|
-
input: process.stdin,
|
|
15
|
-
output: process.stdout,
|
|
16
|
-
prompt: null
|
|
17
|
-
});
|
|
10
|
+
export let rl;
|
|
18
11
|
|
|
19
12
|
/**
|
|
20
13
|
* Update the current shell prompt
|
|
@@ -28,26 +21,21 @@ export function updatePrompt(currentPath) {
|
|
|
28
21
|
* Start the interactive shell
|
|
29
22
|
*/
|
|
30
23
|
export async function startShell(command) {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
ErrorModule,
|
|
34
|
-
ProfileModule,
|
|
35
|
-
];
|
|
24
|
+
const profileModule = getProfileModule();
|
|
25
|
+
await profileModule.checkLogin();
|
|
36
26
|
|
|
37
|
-
const context = new putility.libs.context.Context({
|
|
38
|
-
events: new putility.libs.event.Emitter(),
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
for ( const module of modules ) module({ context });
|
|
42
|
-
|
|
43
|
-
await context.events.emit('check-login', {});
|
|
44
|
-
|
|
45
27
|
// This argument enables the `puter <subcommand>` commands
|
|
46
|
-
if (
|
|
47
|
-
await execCommand(
|
|
28
|
+
if (command) {
|
|
29
|
+
await execCommand(command);
|
|
48
30
|
process.exit(0);
|
|
49
31
|
}
|
|
50
32
|
|
|
33
|
+
rl = readline.createInterface({
|
|
34
|
+
input: process.stdin,
|
|
35
|
+
output: process.stdout,
|
|
36
|
+
prompt: null
|
|
37
|
+
})
|
|
38
|
+
|
|
51
39
|
try {
|
|
52
40
|
console.log(chalk.green('Welcome to Puter-CLI! Type "help" for available commands.'));
|
|
53
41
|
rl.setPrompt(getPrompt());
|
|
@@ -57,7 +45,7 @@ export async function startShell(command) {
|
|
|
57
45
|
const trimmedLine = line.trim();
|
|
58
46
|
if (trimmedLine) {
|
|
59
47
|
try {
|
|
60
|
-
await execCommand(
|
|
48
|
+
await execCommand(trimmedLine);
|
|
61
49
|
} catch (error) {
|
|
62
50
|
console.error(chalk.red(error.message));
|
|
63
51
|
}
|
package/src/commands/sites.js
CHANGED
|
@@ -1,23 +1,18 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import fetch from 'node-fetch';
|
|
3
2
|
import Table from 'cli-table3';
|
|
4
3
|
import { getCurrentUserName, getCurrentDirectory } from './auth.js';
|
|
5
|
-
import {
|
|
4
|
+
import { resolveRemotePath, isValidAppName } from '../commons.js';
|
|
6
5
|
import { displayNonNullValues, formatDate, isValidAppUuid } from '../utils.js';
|
|
7
|
-
import { getSubdomains, createSubdomain, deleteSubdomain } from './subdomains.js';
|
|
8
|
-
import {
|
|
9
|
-
|
|
6
|
+
import { getSubdomains, createSubdomain, deleteSubdomain, updateSubdomain } from './subdomains.js';
|
|
7
|
+
import { getPuter } from '../modules/PuterModule.js';
|
|
8
|
+
import { report } from '../modules/ErrorModule.js';
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* Listing subdomains
|
|
13
12
|
*/
|
|
14
|
-
export async function listSites(args = {}
|
|
13
|
+
export async function listSites(args = {}) {
|
|
15
14
|
try {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
if (!data.success || !Array.isArray(data.result)) {
|
|
19
|
-
throw new Error('Failed to fetch subdomains');
|
|
20
|
-
}
|
|
15
|
+
const result = await getSubdomains(args);
|
|
21
16
|
|
|
22
17
|
// Create table instance
|
|
23
18
|
const table = new Table({
|
|
@@ -35,7 +30,7 @@ export async function listSites(args = {}, context) {
|
|
|
35
30
|
|
|
36
31
|
// Format and add data to table
|
|
37
32
|
let i = 0;
|
|
38
|
-
|
|
33
|
+
result.forEach(domain => {
|
|
39
34
|
let appDir = domain?.root_dir?.path.split('/').pop().split('-');
|
|
40
35
|
table.push([
|
|
41
36
|
i++,
|
|
@@ -49,16 +44,16 @@ export async function listSites(args = {}, context) {
|
|
|
49
44
|
});
|
|
50
45
|
|
|
51
46
|
// Print table
|
|
52
|
-
if (
|
|
47
|
+
if (result.length === 0) {
|
|
53
48
|
console.log(chalk.yellow('No subdomains found'));
|
|
54
49
|
} else {
|
|
55
50
|
console.log(chalk.bold('\nYour Sites:'));
|
|
56
51
|
console.log(table.toString());
|
|
57
|
-
console.log(chalk.dim(`Total Sites: ${
|
|
52
|
+
console.log(chalk.dim(`Total Sites: ${result.length}`));
|
|
58
53
|
}
|
|
59
54
|
|
|
60
55
|
} catch (error) {
|
|
61
|
-
|
|
56
|
+
report(error);
|
|
62
57
|
console.error(chalk.red('Error listing sites:'), error.message);
|
|
63
58
|
throw error;
|
|
64
59
|
}
|
|
@@ -73,26 +68,11 @@ export async function infoSite(args = []) {
|
|
|
73
68
|
console.log(chalk.red('Usage: site <siteUID>'));
|
|
74
69
|
return;
|
|
75
70
|
}
|
|
76
|
-
|
|
71
|
+
const puter = getPuter();
|
|
72
|
+
for (const subdomain of args)
|
|
77
73
|
try {
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
headers: getHeaders(),
|
|
81
|
-
body: JSON.stringify({
|
|
82
|
-
interface: 'puter-subdomains',
|
|
83
|
-
method: 'read',
|
|
84
|
-
args: { uid: subdomainId }
|
|
85
|
-
})
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
if (!response.ok) {
|
|
89
|
-
throw new Error('Failed to fetch subdomains.');
|
|
90
|
-
}
|
|
91
|
-
const data = await response.json();
|
|
92
|
-
if (!data.success || !data.result) {
|
|
93
|
-
throw new Error(`Failed to get site info: ${data.error?.message}`);
|
|
94
|
-
}
|
|
95
|
-
displayNonNullValues(data.result);
|
|
74
|
+
const result = await puter.hosting.get(subdomain);
|
|
75
|
+
displayNonNullValues(result);
|
|
96
76
|
} catch (error) {
|
|
97
77
|
console.error(chalk.red('Error getting site info:'), error.message);
|
|
98
78
|
}
|
|
@@ -100,43 +80,14 @@ export async function infoSite(args = []) {
|
|
|
100
80
|
|
|
101
81
|
/**
|
|
102
82
|
* Delete hosted web site
|
|
103
|
-
* @param {any[]} args Array of
|
|
83
|
+
* @param {any[]} args Array of subdomain
|
|
104
84
|
*/
|
|
105
85
|
export async function deleteSite(args = []) {
|
|
106
86
|
if (args.length < 1){
|
|
107
|
-
console.log(chalk.red('Usage: site:delete <
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
110
|
-
for (const uuid of args)
|
|
111
|
-
try {
|
|
112
|
-
if (!uuid){
|
|
113
|
-
console.log(chalk.yellow(`We could not find the site ID: ${uuid}`));
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
// The uuid must be prefixed with: 'subdomainObj-'
|
|
117
|
-
const response = await fetch(`${API_BASE}/delete-site`, {
|
|
118
|
-
headers: getHeaders(),
|
|
119
|
-
method: 'POST',
|
|
120
|
-
body: JSON.stringify({
|
|
121
|
-
site_uuid: uuid
|
|
122
|
-
})
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
if (!response.ok) {
|
|
126
|
-
throw new Error(`Failed to delete site (Status: ${response.status})`);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const data = await response.json();
|
|
130
|
-
if (Object.keys(data).length==0) {
|
|
131
|
-
console.log(chalk.green(`Site ID: "${uuid}" has been deleted.`));
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
console.log(chalk.yellow(`Site ID: "${uuid}" should be deleted.`));
|
|
136
|
-
} catch (error) {
|
|
137
|
-
console.error(chalk.red('Error deleting site:'), error.message);
|
|
87
|
+
console.log(chalk.red('Usage: site:delete <subdomain>'));
|
|
138
88
|
return false;
|
|
139
89
|
}
|
|
90
|
+
await deleteSubdomain(args);
|
|
140
91
|
return true;
|
|
141
92
|
}
|
|
142
93
|
|
|
@@ -171,12 +122,7 @@ export async function infoSite(args = []) {
|
|
|
171
122
|
}
|
|
172
123
|
|
|
173
124
|
// Step 2: Check if the subdomain already exists
|
|
174
|
-
const
|
|
175
|
-
if (!data.success || !Array.isArray(data.result)) {
|
|
176
|
-
throw new Error('Failed to fetch subdomains');
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const subdomains = data.result;
|
|
125
|
+
const subdomains = await getSubdomains();;
|
|
180
126
|
const subdomainObj = subdomains.find(sd => sd.subdomain === subdomain);
|
|
181
127
|
if (subdomainObj) {
|
|
182
128
|
console.error(chalk.cyan(`The subdomain "${subdomain}" is already in use and owned by: "${subdomainObj.owner['username']}"`));
|
|
@@ -188,35 +134,31 @@ export async function infoSite(args = []) {
|
|
|
188
134
|
return;
|
|
189
135
|
} else {
|
|
190
136
|
console.log(chalk.yellow(`However, It's linked to different directory at: ${subdomainObj.root_dir?.path}`));
|
|
191
|
-
console.log(chalk.cyan(`
|
|
192
|
-
const result = await
|
|
137
|
+
console.log(chalk.cyan(`Updating this subdomain directory...`));
|
|
138
|
+
const result = await updateSubdomain(subdomain, remoteDir);
|
|
193
139
|
if (result) {
|
|
194
|
-
console.log(chalk.green('
|
|
140
|
+
console.log(chalk.green('Updating subdomain directory successful.'));
|
|
195
141
|
return;
|
|
196
142
|
} else {
|
|
197
|
-
console.log(chalk.red('Could not
|
|
143
|
+
console.log(chalk.red('Could not update this subdomain directory.'));
|
|
144
|
+
return;
|
|
198
145
|
}
|
|
199
146
|
}
|
|
200
147
|
}
|
|
201
148
|
}
|
|
202
|
-
// else {
|
|
203
|
-
// console.log(chalk.yellow(`The subdomain: "${subdomain}" is already taken, so let's generate a new random one:`));
|
|
204
|
-
// subdomain = generateAppName(); // Generate a random subdomain
|
|
205
|
-
// console.log(chalk.cyan(`New generated subdomain: "${subdomain}" will be used.`));
|
|
206
|
-
// }
|
|
207
149
|
|
|
208
150
|
// Use the chosen "subdomain"
|
|
209
151
|
console.log(chalk.cyan(`New generated subdomain: "${subdomain}" will be used if its not already in use.`));
|
|
210
152
|
|
|
211
153
|
// Step 3: Host the current directory under the subdomain
|
|
212
|
-
console.log(chalk.cyan(`Hosting
|
|
154
|
+
console.log(chalk.cyan(`Hosting site "${appName}" under subdomain "${subdomain}"...`));
|
|
213
155
|
const site = await createSubdomain(subdomain, remoteDir);
|
|
214
156
|
if (!site){
|
|
215
157
|
console.error(chalk.red(`Failed to create subdomain: "${chalk.red(subdomain)}"`));
|
|
216
158
|
return;
|
|
217
159
|
}
|
|
218
160
|
|
|
219
|
-
console.log(chalk.green(`
|
|
161
|
+
console.log(chalk.green(`Site ${chalk.dim(appName)} created successfully and accessible at:`));
|
|
220
162
|
console.log(chalk.cyan(`https://${site.subdomain}.puter.site`));
|
|
221
163
|
return site;
|
|
222
164
|
} catch (error) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import fetch from 'node-fetch';
|
|
3
3
|
import { API_BASE, getHeaders } from '../commons.js';
|
|
4
|
+
import { getPuter } from '../modules/PuterModule.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Get list of subdomains.
|
|
@@ -8,20 +9,16 @@ import { API_BASE, getHeaders } from '../commons.js';
|
|
|
8
9
|
* @returns {Array} - Array of subdomains.
|
|
9
10
|
*/
|
|
10
11
|
export async function getSubdomains(args = {}) {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
headers: getHeaders(),
|
|
14
|
-
body: JSON.stringify({
|
|
15
|
-
interface: 'puter-subdomains',
|
|
16
|
-
method: 'select',
|
|
17
|
-
args: args
|
|
18
|
-
})
|
|
19
|
-
});
|
|
12
|
+
const puter = getPuter();
|
|
13
|
+
let result;
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
try {
|
|
16
|
+
result = await puter.hosting.list();
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.log(chalk.red(`Error when getting subdomains.\nError: ${error?.message}`));
|
|
23
19
|
}
|
|
24
|
-
|
|
20
|
+
|
|
21
|
+
return result;
|
|
25
22
|
}
|
|
26
23
|
|
|
27
24
|
/**
|
|
@@ -34,32 +31,22 @@ export async function deleteSubdomain(args = []) {
|
|
|
34
31
|
console.log(chalk.red('Usage: domain:delete <subdomain_id>'));
|
|
35
32
|
return false;
|
|
36
33
|
}
|
|
34
|
+
const puter = getPuter();
|
|
37
35
|
const subdomains = args;
|
|
38
|
-
for (const
|
|
36
|
+
for (const subdomain of subdomains)
|
|
39
37
|
try {
|
|
40
|
-
const
|
|
41
|
-
headers: getHeaders(),
|
|
42
|
-
method: 'POST',
|
|
43
|
-
body: JSON.stringify({
|
|
44
|
-
interface: 'puter-subdomains',
|
|
45
|
-
method: 'delete',
|
|
46
|
-
args: {
|
|
47
|
-
id: { subdomain: subdomainId }
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
});
|
|
38
|
+
const success = await puter.hosting.delete(subdomain);
|
|
51
39
|
|
|
52
|
-
|
|
53
|
-
if (!data.success) {
|
|
54
|
-
if (data.error?.code === 'entity_not_found') {
|
|
55
|
-
console.log(chalk.red(`Subdomain ID: "${subdomainId}" not found`));
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
40
|
+
if (!success) {
|
|
58
41
|
console.log(chalk.red(`Failed to delete subdomain: ${data.error?.message}`));
|
|
59
42
|
return false;
|
|
60
43
|
}
|
|
61
44
|
console.log(chalk.green('Subdomain deleted successfully'));
|
|
62
45
|
} catch (error) {
|
|
46
|
+
if (error.error?.code === 'entity_not_found') {
|
|
47
|
+
console.log(chalk.red(`Subdomain: "${subdomain}" not found`));
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
63
50
|
console.error(chalk.red('Error deleting subdomain:'), error.message);
|
|
64
51
|
}
|
|
65
52
|
return true;
|
|
@@ -72,33 +59,37 @@ export async function deleteSubdomain(args = []) {
|
|
|
72
59
|
* @returns {Object} - Hosting details (e.g., subdomain).
|
|
73
60
|
*/
|
|
74
61
|
export async function createSubdomain(subdomain, remoteDir) {
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
headers: getHeaders(),
|
|
78
|
-
body: JSON.stringify({
|
|
79
|
-
interface: 'puter-subdomains',
|
|
80
|
-
method: 'create',
|
|
81
|
-
args: {
|
|
82
|
-
object: {
|
|
83
|
-
subdomain: subdomain,
|
|
84
|
-
root_dir: remoteDir
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
})
|
|
88
|
-
});
|
|
62
|
+
const puter = getPuter();
|
|
63
|
+
let result;
|
|
89
64
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (data.error?.code === 'already_in_use') {
|
|
96
|
-
// data.error?.status===409
|
|
97
|
-
console.log(chalk.yellow(`Subdomain already taken!\nMessage: ${data?.error?.message}`));
|
|
65
|
+
try {
|
|
66
|
+
result = await puter.hosting.create(subdomain, remoteDir);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
if (error?.error?.code === 'already_in_use') {
|
|
69
|
+
console.log(chalk.yellow(`Subdomain already taken!\nMessage: ${error?.error?.message}`));
|
|
98
70
|
return false;
|
|
99
71
|
}
|
|
100
|
-
console.log(chalk.red(`Error when creating "${subdomain}".\nError: ${
|
|
101
|
-
return false;
|
|
72
|
+
console.log(chalk.red(`Error when creating "${subdomain}".\nError: ${error?.error?.message}\nCode: ${error?.error?.code}`));
|
|
102
73
|
}
|
|
103
|
-
return
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Update a subdomain into remote directory
|
|
79
|
+
* @param {string} subdomain - Subdomain name.
|
|
80
|
+
* @param {string} remoteDir - Remote directory path.
|
|
81
|
+
* @returns {Object} - Hosting details (e.g., subdomain).
|
|
82
|
+
*/
|
|
83
|
+
export async function updateSubdomain(subdomain, remoteDir) {
|
|
84
|
+
const puter = getPuter();
|
|
85
|
+
let result;
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
result = await puter.hosting.update(subdomain, remoteDir);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.log(chalk.red(`Error when updating "${subdomain}".\nError: ${error?.message}`));
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return result;
|
|
104
95
|
}
|
package/src/commons.js
CHANGED
|
@@ -45,7 +45,7 @@ export function getHeaders(contentType = 'application/json') {
|
|
|
45
45
|
* @see: [randName](https://github.com/HeyPuter/puter/blob/06a67a3b223a6cbd7ec2e16853b6d2304f621a88/src/puter-js/src/index.js#L389)
|
|
46
46
|
*/
|
|
47
47
|
export function generateAppName(separateWith = '-'){
|
|
48
|
-
console.log(chalk.cyan('Generating random
|
|
48
|
+
console.log(chalk.cyan('Generating random name...'));
|
|
49
49
|
try {
|
|
50
50
|
const first_adj = ['helpful','sensible', 'loyal', 'honest', 'clever', 'capable','calm', 'smart', 'genius', 'bright', 'charming', 'creative', 'diligent', 'elegant', 'fancy',
|
|
51
51
|
'colorful', 'avid', 'active', 'gentle', 'happy', 'intelligent', 'jolly', 'kind', 'lively', 'merry', 'nice', 'optimistic', 'polite',
|
|
@@ -63,7 +63,7 @@ export function generateAppName(separateWith = '-'){
|
|
|
63
63
|
// return a random combination of first_adj + noun + number (between 0 and 9999)
|
|
64
64
|
// e.g. clever-idea-123
|
|
65
65
|
const appName = first_adj[Math.floor(Math.random() * first_adj.length)] + separateWith + nouns[Math.floor(Math.random() * nouns.length)] + separateWith + Math.floor(Math.random() * 10000);
|
|
66
|
-
console.log(chalk.green(`
|
|
66
|
+
console.log(chalk.green(`Name: "${appName}"`));
|
|
67
67
|
return appName;
|
|
68
68
|
} catch (error) {
|
|
69
69
|
console.error(`Error: ${error.message}`);
|
package/src/executor.js
CHANGED
|
@@ -2,10 +2,12 @@ import chalk from 'chalk';
|
|
|
2
2
|
import Conf from 'conf';
|
|
3
3
|
import { listApps, appInfo, createApp, updateApp, deleteApp } from './commands/apps.js';
|
|
4
4
|
import { listSites, createSite, deleteSite, infoSite } from './commands/sites.js';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
import {
|
|
6
|
+
listFiles, makeDirectory, renameFileOrDirectory,
|
|
7
|
+
removeFileOrDirectory, emptyTrash, changeDirectory, showCwd,
|
|
8
|
+
getInfo, getDiskUsage, createFile, readFile, uploadFile,
|
|
9
|
+
downloadFile, copyFile, syncDirectory, editFile
|
|
10
|
+
} from './commands/files.js';
|
|
9
11
|
import { getUserInfo, getUsageInfo, login } from './commands/auth.js';
|
|
10
12
|
import { deploy } from './commands/deploy.js';
|
|
11
13
|
import { PROJECT_NAME, API_BASE, getHeaders } from './commons.js';
|
|
@@ -13,7 +15,7 @@ import inquirer from 'inquirer';
|
|
|
13
15
|
import { exec } from 'node:child_process';
|
|
14
16
|
import { parseArgs, getSystemEditor } from './utils.js';
|
|
15
17
|
import { rl } from './commands/shell.js';
|
|
16
|
-
import {
|
|
18
|
+
import { showLast } from './modules/ErrorModule.js'
|
|
17
19
|
|
|
18
20
|
const config = new Conf({ projectName: PROJECT_NAME });
|
|
19
21
|
|
|
@@ -39,8 +41,8 @@ const commands = {
|
|
|
39
41
|
whoami: getUserInfo,
|
|
40
42
|
stat: getInfo,
|
|
41
43
|
apps: async (args) => {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
await listApps({
|
|
45
|
+
statsPeriod: args[0] || 'all'
|
|
44
46
|
});
|
|
45
47
|
},
|
|
46
48
|
app: appInfo,
|
|
@@ -64,9 +66,7 @@ const commands = {
|
|
|
64
66
|
rl.write(commandToCopy);
|
|
65
67
|
}
|
|
66
68
|
},
|
|
67
|
-
'last-error':
|
|
68
|
-
context[ErrorAPI].showLast();
|
|
69
|
-
},
|
|
69
|
+
'last-error': showLast,
|
|
70
70
|
'app:create': async (rawArgs) => {
|
|
71
71
|
try {
|
|
72
72
|
const args = parseArgs(rawArgs.join(' '));
|
|
@@ -88,8 +88,8 @@ const commands = {
|
|
|
88
88
|
},
|
|
89
89
|
'app:update': async (args) => {
|
|
90
90
|
if (args.length < 1) {
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
console.log(chalk.red('Usage: app:update <name> <remote_dir>'));
|
|
92
|
+
return;
|
|
93
93
|
}
|
|
94
94
|
await updateApp(args);
|
|
95
95
|
},
|
|
@@ -102,25 +102,25 @@ const commands = {
|
|
|
102
102
|
}
|
|
103
103
|
});
|
|
104
104
|
if (args._.length < 1) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
console.log(chalk.red('You must specify the app name:'));
|
|
106
|
+
console.log(chalk.yellow('Example: app:delete <name>'));
|
|
107
|
+
return;
|
|
108
108
|
}
|
|
109
109
|
const name = args._[0];
|
|
110
110
|
const force = !!args.f;
|
|
111
111
|
|
|
112
|
-
if (!force){
|
|
112
|
+
if (!force) {
|
|
113
113
|
const { confirm } = await inquirer.prompt([
|
|
114
114
|
{
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
type: 'confirm',
|
|
116
|
+
name: 'confirm',
|
|
117
|
+
message: chalk.yellow(`Are you sure you want to delete "${name}"?`),
|
|
118
|
+
default: false
|
|
119
119
|
}
|
|
120
120
|
]);
|
|
121
121
|
if (!confirm) {
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
console.log(chalk.yellow('Operation cancelled.'));
|
|
123
|
+
return false;
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
await deleteApp(name);
|
|
@@ -155,10 +155,9 @@ const commands = {
|
|
|
155
155
|
* Execute a command
|
|
156
156
|
* @param {string} input The command line input
|
|
157
157
|
*/
|
|
158
|
-
export async function execCommand(
|
|
159
|
-
const [cmd, ...args] = input.split(' ');
|
|
158
|
+
export async function execCommand(input) {
|
|
159
|
+
const [cmd, ...args] = input ? input.split(' ') : [];
|
|
160
160
|
|
|
161
|
-
|
|
162
161
|
// Add the command to history (skip the "history" command itself)
|
|
163
162
|
if (cmd !== 'history') {
|
|
164
163
|
commandHistory.push(input);
|
|
@@ -189,7 +188,7 @@ export async function execCommand(context, input) {
|
|
|
189
188
|
}
|
|
190
189
|
if (commands[cmd]) {
|
|
191
190
|
try {
|
|
192
|
-
await commands[cmd](args
|
|
191
|
+
await commands[cmd](args);
|
|
193
192
|
} catch (error) {
|
|
194
193
|
console.error(chalk.red(`Error executing command: ${error.message}`));
|
|
195
194
|
}
|
|
@@ -355,9 +354,9 @@ function showHelp(command) {
|
|
|
355
354
|
Example: site:create mywebsite /path/to/dir --subdomain=mywebsite
|
|
356
355
|
`,
|
|
357
356
|
'site:deploy': `
|
|
358
|
-
${chalk.cyan('site:deploy [<
|
|
357
|
+
${chalk.cyan('site:deploy [<remote_dir>] [--subdomain=<subdomain>]')}
|
|
359
358
|
Deploy a local web project to Puter.
|
|
360
|
-
Example: site:deploy
|
|
359
|
+
Example: site:deploy ./my-app --subdomain my-app
|
|
361
360
|
`,
|
|
362
361
|
'!': `
|
|
363
362
|
${chalk.cyan('!<command>')}
|
|
@@ -1,33 +1,20 @@
|
|
|
1
|
-
const ERROR_BUFFER_LIMIT = 20;
|
|
1
|
+
export const ERROR_BUFFER_LIMIT = 20;
|
|
2
2
|
|
|
3
|
-
export const
|
|
3
|
+
export const errors = [];
|
|
4
4
|
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
},
|
|
22
|
-
// Print the last error from the error history,
|
|
23
|
-
// and remove it from the history
|
|
24
|
-
showLast () {
|
|
25
|
-
const err = errors.pop();
|
|
26
|
-
if (err) {
|
|
27
|
-
console.error(err);
|
|
28
|
-
} else {
|
|
29
|
-
console.log('No errors to report');
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
};
|
|
5
|
+
export const report = (error) => {
|
|
6
|
+
errors.push(error);
|
|
7
|
+
if (errors.length > ERROR_BUFFER_LIMIT) {
|
|
8
|
+
errors.splice(0, errors.length - ERROR_BUFFER_LIMIT)
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export const showLast = () => {
|
|
12
|
+
// Print the last error from the error history,
|
|
13
|
+
// and remove it from the history
|
|
14
|
+
const err = errors.pop();
|
|
15
|
+
if (err) {
|
|
16
|
+
console.error(err);
|
|
17
|
+
} else {
|
|
18
|
+
console.log('No errors to report');
|
|
19
|
+
}
|
|
20
|
+
}
|