puter-cli 1.1.4 → 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 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> [<remote_dir>] [--url=<url>]
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
 
package/bin/index.js CHANGED
@@ -34,10 +34,32 @@ async function main() {
34
34
  .description('Start interactive shell')
35
35
  .action(startShell);
36
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
+
37
59
  if (process.argv.length === 2) {
38
60
  startShell();
39
61
  } else {
40
- program.parse();
62
+ program.parse(process.argv);
41
63
  }
42
64
  }
43
65
 
package/commands/apps.js CHANGED
@@ -126,25 +126,28 @@ export async function appInfo(args = []) {
126
126
  /**
127
127
  * Create a new web application
128
128
  * @param {string} name The name of the App
129
+ * @param {string} directory Optional directory path
129
130
  * @param {string} description A description of the App
130
131
  * @param {string} url A default coming-soon URL
131
- * @returns Output JSON data
132
+ * @returns {Promise<Object>} Output JSON data
132
133
  */
133
- export async function createApp(args = []) {
134
- if (args.length < 1 || !isValidAppName(args[0])) {
135
- console.log(chalk.red('Usage: app:create <valid_name_app> [<remote_dir>] [--url=<url>]'));
136
- console.log(chalk.yellow('Example: app:create myapp'));
137
- console.log(chalk.yellow('Example: app:create myapp ./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 = (args[1] && !args[1].startsWith('--'))? resolvePath(getCurrentDirectory(), args[1]):'';
143
- // Optional description (disabled at the moment)
144
- const description = ''; // (args.find(arg => arg.toLocaleLowerCase().startsWith('--description='))?.split('=')[1]) || '';
145
- const url = (args.find(arg => arg.toLocaleLowerCase().startsWith('--url='))?.split('=')[1]) || 'https://dev-center.puter.com/coming-soon.html'; // Optional url
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}`));
146
150
 
147
- console.log(chalk.dim(`Creating app: ${chalk.green(name)}...\n`));
148
151
  try {
149
152
  // Step 1: Create the app
150
153
  const createAppResponse = await fetch(`${API_BASE}/drivers/call`, {
@@ -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 (args) => {
41
- if (args.length < 1) {
42
- console.log(chalk.red('Usage: app:create <name> [<remote_dir>] [--description=<description>] [--url=<url>]'));
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 (args) => {
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.find(arg => arg !=='-f')
60
- const force = args.some(arg => arg =='-f')? true: false;
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> [<remote_dir>] [--url=<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://example.com
216
+ Example: app:create myapp https://myapp.puter.site
193
217
  `,
194
218
  'app:update': `
195
219
  ${chalk.cyan('app:update <name> [dir]')}
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.4",
3
+ "version": "1.1.5",
4
4
  "description": "Command line interface for Puter cloud platform",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -26,7 +26,7 @@
26
26
  "dependencies": {
27
27
  "chalk": "^5.3.0",
28
28
  "cli-table3": "^0.6.5",
29
- "commander": "^11.1.0",
29
+ "commander": "^13.0.0",
30
30
  "conf": "^12.0.0",
31
31
  "cross-spawn": "^7.0.3",
32
32
  "glob": "^11.0.0",
@@ -34,7 +34,8 @@
34
34
  "minimatch": "^10.0.1",
35
35
  "node-fetch": "^3.3.2",
36
36
  "ora": "^8.0.1",
37
- "uuid": "^11.0.5"
37
+ "uuid": "^11.0.5",
38
+ "yargs-parser": "^21.1.1"
38
39
  },
39
40
  "devDependencies": {
40
41
  "vitest": "^2.1.8"