puter-cli 1.1.3 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/bin/index.js +23 -2
- package/commands/apps.js +18 -14
- package/commands/crypto.js +176 -0
- package/commands/executor.js +36 -12
- package/commands/files.js +1 -0
- package/commands/sites.js +4 -4
- package/commands/utils.js +12 -1
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -148,7 +148,7 @@ P.S. Please check the help command `help apps` for more details about any argume
|
|
|
148
148
|
|
|
149
149
|
- **Create Application**: Create a new application.
|
|
150
150
|
```bash
|
|
151
|
-
puter app:create <name> [<
|
|
151
|
+
puter app:create <name> [<directory>] [--description="My App Description"] [--url=<url>]
|
|
152
152
|
```
|
|
153
153
|
P.S. By default a new `index.html` with basic content will be created, but you can set a directory when you create a new application as follows: `app:create nameOfApp ./appDir`, so all files will be copied to the `AppData` directoy, you can then update your app using `app:update <name> <remote_dir>`. This command will attempt to create a subdomain with a random `uid` prefixed with the name of the app.
|
|
154
154
|
|
|
@@ -170,7 +170,7 @@ The static sites are served from the selected directory (or the current director
|
|
|
170
170
|
|
|
171
171
|
- **Deploy Site**: Deploy a static website from a directory.
|
|
172
172
|
```bash
|
|
173
|
-
puter site:create <dir> [--subdomain=<name>]
|
|
173
|
+
puter site:create <app_name> [<dir>] [--subdomain=<name>]
|
|
174
174
|
```
|
|
175
175
|
P.S. If the subdomain already exists, it will generate a new random one can set your own subdomain using `--subdomain` argument.
|
|
176
176
|
|
package/bin/index.js
CHANGED
|
@@ -5,7 +5,6 @@ import { init } from '../commands/init.js';
|
|
|
5
5
|
import { startShell } from '../commands/shell.js';
|
|
6
6
|
import { PROJECT_NAME, getLatestVersion } from '../commands/commons.js';
|
|
7
7
|
|
|
8
|
-
|
|
9
8
|
async function main() {
|
|
10
9
|
const { version } = await getLatestVersion(PROJECT_NAME);
|
|
11
10
|
|
|
@@ -35,10 +34,32 @@ async function main() {
|
|
|
35
34
|
.description('Start interactive shell')
|
|
36
35
|
.action(startShell);
|
|
37
36
|
|
|
37
|
+
|
|
38
|
+
// App commands
|
|
39
|
+
program
|
|
40
|
+
.command('app:create <name>')
|
|
41
|
+
.description('Create a new Puter application')
|
|
42
|
+
.argument('<name>', 'Name of the application')
|
|
43
|
+
.argument('[directory]', 'Local directory path')
|
|
44
|
+
.option('-d, --description <description>', 'Application description')
|
|
45
|
+
.option('-u, --url <url>', 'Application URL', 'https://dev-center.puter.com/coming-soon.html')
|
|
46
|
+
.action(async (name, directory, options) => {
|
|
47
|
+
try {
|
|
48
|
+
await createApp({
|
|
49
|
+
name,
|
|
50
|
+
directory: directory || '',
|
|
51
|
+
description: options.description || '',
|
|
52
|
+
url: options.url
|
|
53
|
+
});
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error(chalk.red(error.message));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
38
59
|
if (process.argv.length === 2) {
|
|
39
60
|
startShell();
|
|
40
61
|
} else {
|
|
41
|
-
program.parse();
|
|
62
|
+
program.parse(process.argv);
|
|
42
63
|
}
|
|
43
64
|
}
|
|
44
65
|
|
package/commands/apps.js
CHANGED
|
@@ -8,6 +8,7 @@ import { createSubdomain, getSubdomains } from './subdomains.js';
|
|
|
8
8
|
import { deleteSite } from './sites.js';
|
|
9
9
|
import { copyFile, createFile, listRemoteFiles, pathExists, removeFileOrDirectory } from './files.js';
|
|
10
10
|
import { getCurrentDirectory } from './auth.js';
|
|
11
|
+
import crypto from './crypto.js';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* List all apps
|
|
@@ -125,25 +126,28 @@ export async function appInfo(args = []) {
|
|
|
125
126
|
/**
|
|
126
127
|
* Create a new web application
|
|
127
128
|
* @param {string} name The name of the App
|
|
129
|
+
* @param {string} directory Optional directory path
|
|
128
130
|
* @param {string} description A description of the App
|
|
129
131
|
* @param {string} url A default coming-soon URL
|
|
130
|
-
* @returns Output JSON data
|
|
132
|
+
* @returns {Promise<Object>} Output JSON data
|
|
131
133
|
*/
|
|
132
|
-
export async function createApp(args
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
console.log(chalk.yellow('Example: app:create myapp --description=myapp'));
|
|
138
|
-
return;
|
|
134
|
+
export async function createApp(args) {
|
|
135
|
+
const name = args.name; // App name (required)
|
|
136
|
+
console.log(args);
|
|
137
|
+
if (!isValidAppName(name)) {
|
|
138
|
+
throw new Error('Invalid application name');
|
|
139
139
|
}
|
|
140
|
-
const name = args[0]; // App name (required)
|
|
141
140
|
// Use the default home page if the root directory if none specified
|
|
142
|
-
const localDir =
|
|
143
|
-
|
|
144
|
-
const
|
|
141
|
+
const localDir = args.directory ? resolvePath(getCurrentDirectory(), args.directory) : '';
|
|
142
|
+
// Optional description
|
|
143
|
+
const description = args.description || '';
|
|
144
|
+
const url = args.url || '';
|
|
145
|
+
|
|
146
|
+
console.log(chalk.green(`Creating app "${name}"...`));
|
|
147
|
+
console.log(chalk.dim(`Directory: ${localDir || '[default]'}`));
|
|
148
|
+
console.log(chalk.dim(`Description: ${description}`));
|
|
149
|
+
console.log(chalk.dim(`URL: ${url}`));
|
|
145
150
|
|
|
146
|
-
console.log(chalk.green(`Creating app: "${chalk.dim(name)}"...\n`));
|
|
147
151
|
try {
|
|
148
152
|
// Step 1: Create the app
|
|
149
153
|
const createAppResponse = await fetch(`${API_BASE}/drivers/call`, {
|
|
@@ -379,7 +383,7 @@ export async function deleteApp(name) {
|
|
|
379
383
|
const readData = await readResponse.json();
|
|
380
384
|
|
|
381
385
|
if (!readData.success || !readData.result) {
|
|
382
|
-
console.log(chalk.
|
|
386
|
+
console.log(chalk.red(`App "${chalk.bold(name)}" not found.`));
|
|
383
387
|
return false;
|
|
384
388
|
}
|
|
385
389
|
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
2
|
+
import { TextEncoder } from 'util';
|
|
3
|
+
|
|
4
|
+
class Hash {
|
|
5
|
+
constructor(algorithm) {
|
|
6
|
+
this.algorithm = algorithm;
|
|
7
|
+
this.data = [];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
update(data) {
|
|
11
|
+
if (typeof data === 'string') {
|
|
12
|
+
const encoder = new TextEncoder();
|
|
13
|
+
data = encoder.encode(data);
|
|
14
|
+
}
|
|
15
|
+
this.data.push(Buffer.from(data));
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async digest(encoding = 'hex') {
|
|
20
|
+
const concatenatedData = Buffer.concat(this.data);
|
|
21
|
+
const hashBuffer = await crypto.subtle.digest(
|
|
22
|
+
this.algorithm.toUpperCase(),
|
|
23
|
+
concatenatedData
|
|
24
|
+
);
|
|
25
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
26
|
+
|
|
27
|
+
if (encoding === 'buffer') {
|
|
28
|
+
return Buffer.from(hashArray);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const hashHex = hashArray
|
|
32
|
+
.map(byte => byte.toString(16).padStart(2, '0'))
|
|
33
|
+
.join('');
|
|
34
|
+
|
|
35
|
+
if (encoding === 'hex') return hashHex;
|
|
36
|
+
if (encoding === 'base64') return Buffer.from(hashHex, 'hex').toString('base64');
|
|
37
|
+
|
|
38
|
+
throw new Error(`Unsupported encoding: ${encoding}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
class Hmac {
|
|
43
|
+
constructor(algorithm, key) {
|
|
44
|
+
this.algorithm = algorithm;
|
|
45
|
+
this.key = typeof key === 'string' ? Buffer.from(key) : key;
|
|
46
|
+
this.data = [];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
update(data) {
|
|
50
|
+
if (typeof data === 'string') {
|
|
51
|
+
const encoder = new TextEncoder();
|
|
52
|
+
data = encoder.encode(data);
|
|
53
|
+
}
|
|
54
|
+
this.data.push(Buffer.from(data));
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async digest(encoding = 'hex') {
|
|
59
|
+
const concatenatedData = Buffer.concat(this.data);
|
|
60
|
+
const key = await crypto.subtle.importKey(
|
|
61
|
+
'raw',
|
|
62
|
+
this.key,
|
|
63
|
+
{ name: 'HMAC', hash: { name: this.algorithm.toUpperCase() } },
|
|
64
|
+
false,
|
|
65
|
+
['sign']
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const signature = await crypto.subtle.sign(
|
|
69
|
+
'HMAC',
|
|
70
|
+
key,
|
|
71
|
+
concatenatedData
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const hashArray = Array.from(new Uint8Array(signature));
|
|
75
|
+
|
|
76
|
+
if (encoding === 'buffer') {
|
|
77
|
+
return Buffer.from(hashArray);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const hashHex = hashArray
|
|
81
|
+
.map(byte => byte.toString(16).padStart(2, '0'))
|
|
82
|
+
.join('');
|
|
83
|
+
|
|
84
|
+
if (encoding === 'hex') return hashHex;
|
|
85
|
+
if (encoding === 'base64') return Buffer.from(hashHex, 'hex').toString('base64');
|
|
86
|
+
|
|
87
|
+
throw new Error(`Unsupported encoding: ${encoding}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const randomBytes = (size) => {
|
|
92
|
+
const array = new Uint8Array(size);
|
|
93
|
+
crypto.getRandomValues(array);
|
|
94
|
+
return Buffer.from(array);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const createHash = (algorithm) => {
|
|
98
|
+
return new Hash(algorithm);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const createHmac = (algorithm, key) => {
|
|
102
|
+
return new Hmac(algorithm, key);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const randomUUID = () => {
|
|
106
|
+
return uuidv4();
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const scrypt = async (password, salt, keylen, options = {}) => {
|
|
110
|
+
const encoder = new TextEncoder();
|
|
111
|
+
const passwordBuffer = encoder.encode(password);
|
|
112
|
+
const saltBuffer = encoder.encode(salt);
|
|
113
|
+
|
|
114
|
+
const N = options.N || 16384;
|
|
115
|
+
const r = options.r || 8;
|
|
116
|
+
const p = options.p || 1;
|
|
117
|
+
|
|
118
|
+
const key = await crypto.subtle.importKey(
|
|
119
|
+
'raw',
|
|
120
|
+
passwordBuffer,
|
|
121
|
+
'PBKDF2',
|
|
122
|
+
false,
|
|
123
|
+
['deriveBits']
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const derivedKey = await crypto.subtle.deriveBits(
|
|
127
|
+
{
|
|
128
|
+
name: 'PBKDF2',
|
|
129
|
+
salt: saltBuffer,
|
|
130
|
+
iterations: N * r * p,
|
|
131
|
+
hash: 'SHA-256'
|
|
132
|
+
},
|
|
133
|
+
key,
|
|
134
|
+
keylen * 8
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
return Buffer.from(derivedKey);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const pbkdf2 = async (password, salt, iterations, keylen, digest) => {
|
|
141
|
+
const encoder = new TextEncoder();
|
|
142
|
+
const passwordBuffer = encoder.encode(password);
|
|
143
|
+
const saltBuffer = encoder.encode(salt);
|
|
144
|
+
|
|
145
|
+
const key = await crypto.subtle.importKey(
|
|
146
|
+
'raw',
|
|
147
|
+
passwordBuffer,
|
|
148
|
+
'PBKDF2',
|
|
149
|
+
false,
|
|
150
|
+
['deriveBits']
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
const derivedKey = await crypto.subtle.deriveBits(
|
|
154
|
+
{
|
|
155
|
+
name: 'PBKDF2',
|
|
156
|
+
salt: saltBuffer,
|
|
157
|
+
iterations,
|
|
158
|
+
hash: digest.toUpperCase()
|
|
159
|
+
},
|
|
160
|
+
key,
|
|
161
|
+
keylen * 8
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
return Buffer.from(derivedKey);
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export default {
|
|
168
|
+
createHash,
|
|
169
|
+
createHmac,
|
|
170
|
+
randomBytes,
|
|
171
|
+
randomUUID,
|
|
172
|
+
scrypt,
|
|
173
|
+
pbkdf2,
|
|
174
|
+
Hash,
|
|
175
|
+
Hmac
|
|
176
|
+
};
|
package/commands/executor.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import ora from 'ora';
|
|
3
2
|
import Conf from 'conf';
|
|
4
3
|
import { listApps, appInfo, createApp, updateApp, deleteApp } from './apps.js';
|
|
5
4
|
import { listSites, createSite, deleteSite, infoSite } from './sites.js';
|
|
@@ -11,6 +10,7 @@ import { getUserInfo, getUsageInfo } from './auth.js';
|
|
|
11
10
|
import { PROJECT_NAME, API_BASE, getHeaders } from './commons.js';
|
|
12
11
|
import inquirer from 'inquirer';
|
|
13
12
|
import { exec } from 'node:child_process';
|
|
13
|
+
import { parseArgs } from './utils.js';
|
|
14
14
|
|
|
15
15
|
const config = new Conf({ projectName: PROJECT_NAME });
|
|
16
16
|
|
|
@@ -37,12 +37,28 @@ const commands = {
|
|
|
37
37
|
});
|
|
38
38
|
},
|
|
39
39
|
app: appInfo,
|
|
40
|
-
'app:create': async (
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
'app:create': async (rawArgs) => {
|
|
41
|
+
try {
|
|
42
|
+
const args = parseArgs(rawArgs.join(' '));
|
|
43
|
+
// Consider using explicit argument definition if necessary
|
|
44
|
+
// const args = parseArgs(rawArgs.join(' '), {string: ['description', 'url'],
|
|
45
|
+
// alias: { d: 'description', u: 'url', },
|
|
46
|
+
// });
|
|
47
|
+
|
|
48
|
+
if (!args.length < 1) {
|
|
49
|
+
console.log(chalk.red('Usage: app:create <name> [directory] [--description="My App Description"] [--url=app-url]'));
|
|
43
50
|
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
await createApp({
|
|
54
|
+
name: args._[0],
|
|
55
|
+
directory: args._[1] || '',
|
|
56
|
+
description: args.description || '',
|
|
57
|
+
url: args.url || 'https://dev-center.puter.com/coming-soon.html'
|
|
58
|
+
});
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error(chalk.red(error.message));
|
|
44
61
|
}
|
|
45
|
-
await createApp(args);
|
|
46
62
|
},
|
|
47
63
|
'app:update': async (args) => {
|
|
48
64
|
if (args.length < 1) {
|
|
@@ -51,13 +67,20 @@ const commands = {
|
|
|
51
67
|
}
|
|
52
68
|
await updateApp(args);
|
|
53
69
|
},
|
|
54
|
-
'app:delete': async (
|
|
70
|
+
'app:delete': async (rawArgs) => {
|
|
71
|
+
const args = parseArgs(rawArgs.join(' '), {
|
|
72
|
+
string: ['_'],
|
|
73
|
+
boolean: ['f'],
|
|
74
|
+
configuration: {
|
|
75
|
+
'populate--': true
|
|
76
|
+
}
|
|
77
|
+
});
|
|
55
78
|
if (args.length < 1) {
|
|
56
79
|
console.log(chalk.red('Usage: app:delete <name>'));
|
|
57
80
|
return;
|
|
58
81
|
}
|
|
59
|
-
const name = args.
|
|
60
|
-
const force = args.
|
|
82
|
+
const name = args._[0];
|
|
83
|
+
const force = !!args.f;
|
|
61
84
|
|
|
62
85
|
if (!force){
|
|
63
86
|
const { confirm } = await inquirer.prompt([
|
|
@@ -144,6 +167,7 @@ export async function execCommand(input) {
|
|
|
144
167
|
* @param {string} [command] - The command to display help for.
|
|
145
168
|
*/
|
|
146
169
|
function showHelp(command) {
|
|
170
|
+
// Consider using `program.helpInformation()` function for global "help" command...
|
|
147
171
|
const commandHelp = {
|
|
148
172
|
help: `
|
|
149
173
|
${chalk.cyan('help [command]')}
|
|
@@ -187,9 +211,9 @@ function showHelp(command) {
|
|
|
187
211
|
Example: app myapp
|
|
188
212
|
`,
|
|
189
213
|
'app:create': `
|
|
190
|
-
${chalk.cyan('app:create <name> [url]')}
|
|
214
|
+
${chalk.cyan('app:create <name> [<remote_dir>] [--description="<description>"] [--url=<url>]')}
|
|
191
215
|
Create a new app.
|
|
192
|
-
Example: app:create myapp https://
|
|
216
|
+
Example: app:create myapp https://myapp.puter.site
|
|
193
217
|
`,
|
|
194
218
|
'app:update': `
|
|
195
219
|
${chalk.cyan('app:update <name> [dir]')}
|
|
@@ -279,9 +303,9 @@ function showHelp(command) {
|
|
|
279
303
|
Example: site:delete sd-123456
|
|
280
304
|
`,
|
|
281
305
|
'site:create': `
|
|
282
|
-
${chalk.cyan('site:create <dir> [--subdomain=<name>]')}
|
|
306
|
+
${chalk.cyan('site:create <app_name> [<dir>] [--subdomain=<name>]')}
|
|
283
307
|
Create a static website from directory.
|
|
284
|
-
Example: site:create /path/to/dir --subdomain=
|
|
308
|
+
Example: site:create mywebsite /path/to/dir --subdomain=mywebsite
|
|
285
309
|
`,
|
|
286
310
|
'!': `
|
|
287
311
|
${chalk.cyan('!<command>')}
|
package/commands/files.js
CHANGED
|
@@ -11,6 +11,7 @@ import { formatDate, formatDateTime, formatSize } from './utils.js';
|
|
|
11
11
|
import inquirer from 'inquirer';
|
|
12
12
|
import { getAuthToken, getCurrentDirectory, getCurrentUserName } from './auth.js';
|
|
13
13
|
import { updatePrompt } from './shell.js';
|
|
14
|
+
import crypto from './crypto.js';
|
|
14
15
|
|
|
15
16
|
const config = new Conf({ projectName: PROJECT_NAME });
|
|
16
17
|
|
package/commands/sites.js
CHANGED
|
@@ -153,7 +153,7 @@ export async function infoSite(args = []) {
|
|
|
153
153
|
// Use the current directory as the root directory if none specified
|
|
154
154
|
const remoteDir = resolvePath(getCurrentDirectory(), (args[1] && !args[1].startsWith('--'))?args[1]:'.');
|
|
155
155
|
|
|
156
|
-
console.log(chalk.
|
|
156
|
+
console.log(chalk.dim(`Creating site ${chalk.green(appName)} from: ${chalk.green(remoteDir)}...\n`));
|
|
157
157
|
try {
|
|
158
158
|
// Step 1: Determine the subdomain
|
|
159
159
|
let subdomain;
|
|
@@ -182,7 +182,7 @@ export async function infoSite(args = []) {
|
|
|
182
182
|
} else {
|
|
183
183
|
console.log(chalk.yellow(`However, It's linked to different directory at: ${subdomainObj.root_dir?.path}`));
|
|
184
184
|
console.log(chalk.cyan(`We'll try to unlink this subdomain from that directory...`));
|
|
185
|
-
const result = await deleteSubdomain(subdomainObj
|
|
185
|
+
const result = await deleteSubdomain(subdomainObj?.uid);
|
|
186
186
|
if (result) {
|
|
187
187
|
console.log(chalk.green('Looks like this subdomain is free again, please try again.'));
|
|
188
188
|
return;
|
|
@@ -205,8 +205,8 @@ export async function infoSite(args = []) {
|
|
|
205
205
|
return;
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
console.log(chalk.green(`App
|
|
209
|
-
console.log(chalk.
|
|
208
|
+
console.log(chalk.green(`App ${chalk.dim(appName)} created successfully and accessible at:`));
|
|
209
|
+
console.log(chalk.cyan(`https://${site.subdomain}.puter.site`));
|
|
210
210
|
} catch (error) {
|
|
211
211
|
console.error(chalk.red('Failed to create site.'));
|
|
212
212
|
console.error(chalk.red(`Error: ${error.message}`));
|
package/commands/utils.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
+
import yargsParser from 'yargs-parser';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Convert "2024-10-07T15:03:53.000Z" to "10/7/2024, 15:03:53"
|
|
@@ -89,4 +90,14 @@ export function displayNonNullValues(data) {
|
|
|
89
90
|
});
|
|
90
91
|
console.log(chalk.cyan('-'.repeat(maxKeyLength*3)));
|
|
91
92
|
console.log(chalk.cyan(`You have ${chalk.green(tableData.length)} key/value pair(s).`));
|
|
92
|
-
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Parse command line arguments including quoted strings
|
|
97
|
+
* @param {string} input Raw command line input
|
|
98
|
+
* @returns {Object} Parsed arguments
|
|
99
|
+
*/
|
|
100
|
+
export function parseArgs(input, options = {}) {
|
|
101
|
+
const result = yargsParser(input, options);
|
|
102
|
+
return result;
|
|
103
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "puter-cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "Command line interface for Puter cloud platform",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -26,14 +26,16 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"chalk": "^5.3.0",
|
|
28
28
|
"cli-table3": "^0.6.5",
|
|
29
|
-
"commander": "^
|
|
29
|
+
"commander": "^13.0.0",
|
|
30
30
|
"conf": "^12.0.0",
|
|
31
31
|
"cross-spawn": "^7.0.3",
|
|
32
32
|
"glob": "^11.0.0",
|
|
33
33
|
"inquirer": "^9.2.12",
|
|
34
34
|
"minimatch": "^10.0.1",
|
|
35
35
|
"node-fetch": "^3.3.2",
|
|
36
|
-
"ora": "^8.0.1"
|
|
36
|
+
"ora": "^8.0.1",
|
|
37
|
+
"uuid": "^11.0.5",
|
|
38
|
+
"yargs-parser": "^21.1.1"
|
|
37
39
|
},
|
|
38
40
|
"devDependencies": {
|
|
39
41
|
"vitest": "^2.1.8"
|