nexforge-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 CHANGED
@@ -179,6 +179,12 @@ nexforge domains ls
179
179
 
180
180
  ### ℹ️ Utility Commands
181
181
 
182
+ **List all projects**
183
+ View all projects associated with your NexForge account.
184
+ ```bash
185
+ nexforge list
186
+ ```
187
+
182
188
  **View project info**
183
189
  View project status, framework, custom domains, live URL, and recent deployment status.
184
190
  ```bash
@@ -191,6 +197,18 @@ Change your project's subdomain instantly. Validates availability and updates yo
191
197
  nexforge rename
192
198
  ```
193
199
 
200
+ **Restart live server**
201
+ Instantly restart the live server for your deployed project without rebuilding.
202
+ ```bash
203
+ nexforge restart
204
+ ```
205
+
206
+ **Delete project**
207
+ Permanently delete your project, deployments, and domains from the NexForge platform.
208
+ ```bash
209
+ nexforge delete
210
+ ```
211
+
194
212
  **Open live project**
195
213
  Instantly opens your live project URL in your default web browser.
196
214
  ```bash
package/index.js CHANGED
@@ -23,6 +23,12 @@ import renameCmd from "./src/commands/rename.js";
23
23
  renameCmd(program);
24
24
  import createCmd from "./src/commands/create.js";
25
25
  createCmd(program);
26
+ import listCmd from "./src/commands/list.js";
27
+ listCmd(program);
28
+ import deleteCmd from "./src/commands/delete.js";
29
+ deleteCmd(program);
30
+ import restartCmd from "./src/commands/restart.js";
31
+ restartCmd(program);
26
32
  import infoCmd from "./src/commands/info.js";
27
33
  infoCmd(program);
28
34
  import domainsCmd from "./src/commands/domains.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexforge-cli",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "Custom Deployment CLI for NexForge",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -0,0 +1,51 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+ import chalk from 'chalk'
4
+ import ora from 'ora'
5
+ import { axios, API_BASE_URL, CONFIG_FILE } from '../config.js'
6
+
7
+ export default (program) => {
8
+ program
9
+ .command("delete [projectId]")
10
+ .description("Delete a project")
11
+ .action(async (projectId) => {
12
+ let targetProjectId = projectId;
13
+
14
+ if (!targetProjectId) {
15
+ const projectFilePath = path.join(process.cwd(), ".nexforge")
16
+ if (fs.existsSync(projectFilePath)) {
17
+ const config = JSON.parse(fs.readFileSync(projectFilePath, "utf8"))
18
+ targetProjectId = config.projectId
19
+ }
20
+ }
21
+
22
+ if (!targetProjectId) {
23
+ console.log(chalk.red("❌ No project specified. Run this inside a project folder or provide a projectId."))
24
+ return
25
+ }
26
+
27
+ const spinner = ora(`Deleting project ${targetProjectId}...`).start()
28
+
29
+ try {
30
+ await axios.delete(`${API_BASE_URL}/cli/project/${targetProjectId}`)
31
+ spinner.succeed(chalk.green(`Successfully deleted project ${targetProjectId}`))
32
+
33
+ // Remove .nexforge file if it exists and we deleted the current project
34
+ const projectFilePath = path.join(process.cwd(), ".nexforge")
35
+ if (fs.existsSync(projectFilePath)) {
36
+ const config = JSON.parse(fs.readFileSync(projectFilePath, "utf8"))
37
+ if (config.projectId === targetProjectId) {
38
+ fs.unlinkSync(projectFilePath)
39
+ console.log(chalk.gray("Removed local .nexforge link file."))
40
+ }
41
+ }
42
+ } catch (error) {
43
+ spinner.fail(chalk.red("Failed to delete project"))
44
+ if (error.response) {
45
+ console.error(chalk.red(`Error: ${error.response.data.error || error.response.statusText}`))
46
+ } else {
47
+ console.error(chalk.red(error.message))
48
+ }
49
+ }
50
+ })
51
+ }
@@ -0,0 +1,43 @@
1
+ import readlineModule from 'readline'
2
+ import fs from 'fs'
3
+ import chalk from 'chalk'
4
+ import ora from 'ora'
5
+ import { axios, API_BASE_URL, CONFIG_DIR, CONFIG_FILE } from '../config.js'
6
+
7
+ export default (program) => {
8
+ program
9
+ .command("list")
10
+ .description("List all projects")
11
+ .action(async () => {
12
+ const readline = readlineModule.createInterface({
13
+ input: process.stdin,
14
+ output: process.stdout,
15
+ })
16
+
17
+ console.log(chalk.cyan("✨ List of projects"))
18
+
19
+ try {
20
+ const response = await axios.get(`${API_BASE_URL}/cli/list`)
21
+
22
+ const { projects } = response.data
23
+
24
+ if (projects.length === 0) {
25
+ console.log(chalk.yellow("No projects found!"))
26
+ readline.close()
27
+ return
28
+ }
29
+
30
+ console.log(chalk.green("🎉 Projects found successfully!"))
31
+ console.log(chalk.cyan(`Project ID: ${projects.map((project) => project.projectId).join("\n")}`))
32
+ } catch (error) {
33
+ console.log(chalk.red("Failed to list projects!"))
34
+ if (error.response && error.response.data) {
35
+ console.log(chalk.red(`Server Error: ${JSON.stringify(error.response.data)}`))
36
+ } else {
37
+ console.error(error.message)
38
+ }
39
+ } finally {
40
+ readline.close()
41
+ }
42
+ })
43
+ }
@@ -0,0 +1,41 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+ import chalk from 'chalk'
4
+ import ora from 'ora'
5
+ import { axios, API_BASE_URL } from '../config.js'
6
+
7
+ export default (program) => {
8
+ program
9
+ .command("restart [projectId]")
10
+ .description("Restart the live server for a project")
11
+ .action(async (projectId) => {
12
+ let targetProjectId = projectId;
13
+
14
+ if (!targetProjectId) {
15
+ const projectFilePath = path.join(process.cwd(), ".nexforge")
16
+ if (fs.existsSync(projectFilePath)) {
17
+ const config = JSON.parse(fs.readFileSync(projectFilePath, "utf8"))
18
+ targetProjectId = config.projectId
19
+ }
20
+ }
21
+
22
+ if (!targetProjectId) {
23
+ console.log(chalk.red("❌ No project specified. Run this inside a project folder or provide a projectId."))
24
+ return
25
+ }
26
+
27
+ const spinner = ora(`Restarting server for project ${targetProjectId}...`).start()
28
+
29
+ try {
30
+ const res = await axios.post(`${API_BASE_URL}/cli/restart/${targetProjectId}`)
31
+ spinner.succeed(chalk.green(`Successfully restarted project ${targetProjectId}`))
32
+ } catch (error) {
33
+ spinner.fail(chalk.red("Failed to restart project"))
34
+ if (error.response) {
35
+ console.error(chalk.red(`Error: ${error.response.data.error || error.response.statusText}`))
36
+ } else {
37
+ console.error(chalk.red(error.message))
38
+ }
39
+ }
40
+ })
41
+ }
package/src/config.js CHANGED
@@ -2,11 +2,15 @@ import axios from 'axios'
2
2
  import fs from 'fs'
3
3
  import path from 'path'
4
4
  import os from 'os'
5
+ import dotenv from 'dotenv'
6
+
7
+ // Load environment variables from the .env file located at the root of the CLI project
8
+ dotenv.config({ path: path.join(path.dirname(new URL(import.meta.url).pathname), '..', '.env').substring(process.platform === 'win32' ? 1 : 0) })
5
9
 
6
10
  export const CONFIG_DIR = path.join(os.homedir(), ".nexforge")
7
11
  export const CONFIG_FILE = path.join(CONFIG_DIR, "config.json")
8
12
 
9
- export const API_BASE_URL = "https://nexforge-lbxg.onrender.com/api"
13
+ export const API_BASE_URL = process.env.API_BASE_URL || "https://nexforge-backend-x2j1.onrender.com/api"
10
14
 
11
15
  // Intercept axios requests to attach the CLI Token if it exists
12
16
  axios.interceptors.request.use((config) => {