@apexkrrish/create-node-app 1.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/bin/cli.js +218 -0
- package/package.json +34 -0
- package/readme.md +51 -0
- package/template/.env +0 -0
- package/template/app.js +36 -0
- package/template/bin/www +93 -0
- package/template/config/config.js +6 -0
- package/template/package.json +21 -0
- package/template/public/css/style.css +8 -0
- package/template/utils/helper.utils.js +33 -0
- package/template/utils/removeFile.utils.js +21 -0
package/bin/cli.js
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { program } from 'commander';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import { execSync } from 'child_process';
|
|
10
|
+
import ora from 'ora';
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
|
|
15
|
+
// ==========================================
|
|
16
|
+
// Helper Functions
|
|
17
|
+
// ==========================================
|
|
18
|
+
|
|
19
|
+
async function promptUser(projectDirectory) {
|
|
20
|
+
let targetDir = projectDirectory;
|
|
21
|
+
|
|
22
|
+
if (!targetDir) {
|
|
23
|
+
const answers = await inquirer.prompt([
|
|
24
|
+
{
|
|
25
|
+
type: 'input',
|
|
26
|
+
name: 'projectDirectory',
|
|
27
|
+
message: 'What is your project named?',
|
|
28
|
+
default: 'my-app'
|
|
29
|
+
}
|
|
30
|
+
]);
|
|
31
|
+
targetDir = answers.projectDirectory;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const { packageManager, database } = await inquirer.prompt([
|
|
35
|
+
{
|
|
36
|
+
type: 'list',
|
|
37
|
+
name: 'packageManager',
|
|
38
|
+
message: 'Which package manager would you like to use?',
|
|
39
|
+
choices: ['npm', 'yarn', 'pnpm'],
|
|
40
|
+
default: 'npm'
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: 'list',
|
|
44
|
+
name: 'database',
|
|
45
|
+
message: 'Which database would you like to use?',
|
|
46
|
+
choices: ['MongoDB (Mongoose)', 'PostgreSQL (Sequelize)', 'None'],
|
|
47
|
+
default: 'MongoDB (Mongoose)'
|
|
48
|
+
}
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
return { targetDir, packageManager, database };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function copyTemplateFiles(templateDir, targetPath) {
|
|
55
|
+
const spinner = ora('Copying template files...').start();
|
|
56
|
+
|
|
57
|
+
if (fs.existsSync(targetPath)) {
|
|
58
|
+
spinner.fail(`Directory ${path.basename(targetPath)} already exists.`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
fs.mkdirSync(targetPath, { recursive: true });
|
|
63
|
+
|
|
64
|
+
const copyRecursiveSync = (src, dest) => {
|
|
65
|
+
const exists = fs.existsSync(src);
|
|
66
|
+
const stats = exists && fs.statSync(src);
|
|
67
|
+
if (exists && stats.isDirectory()) {
|
|
68
|
+
if (!fs.existsSync(dest)) fs.mkdirSync(dest);
|
|
69
|
+
fs.readdirSync(src).forEach((child) => {
|
|
70
|
+
if (child === 'node_modules') return;
|
|
71
|
+
copyRecursiveSync(path.join(src, child), path.join(dest, child));
|
|
72
|
+
});
|
|
73
|
+
} else {
|
|
74
|
+
fs.copyFileSync(src, dest);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
copyRecursiveSync(templateDir, targetPath);
|
|
80
|
+
spinner.succeed('Template copied successfully.');
|
|
81
|
+
} catch (err) {
|
|
82
|
+
spinner.fail('Failed to copy template.');
|
|
83
|
+
console.error(err);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function configureDatabase(targetPath, database) {
|
|
89
|
+
const packageJsonPath = path.join(targetPath, 'package.json');
|
|
90
|
+
if (!fs.existsSync(packageJsonPath)) return;
|
|
91
|
+
|
|
92
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
93
|
+
pkg.name = path.basename(targetPath);
|
|
94
|
+
|
|
95
|
+
const dbConfigPath = path.join(targetPath, 'config', 'db.config.js');
|
|
96
|
+
const targetConfigDir = path.dirname(dbConfigPath);
|
|
97
|
+
if (!fs.existsSync(targetConfigDir)) {
|
|
98
|
+
fs.mkdirSync(targetConfigDir, { recursive: true });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (database === 'MongoDB (Mongoose)') {
|
|
102
|
+
pkg.dependencies = pkg.dependencies || {};
|
|
103
|
+
pkg.dependencies.mongoose = '^8.0.0';
|
|
104
|
+
|
|
105
|
+
const mongooseContent = `import mongoose from "mongoose"
|
|
106
|
+
|
|
107
|
+
const options = {
|
|
108
|
+
serverSelectionTimeoutMS: 10000,
|
|
109
|
+
dbName: '',
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const connectDB = async () => {
|
|
113
|
+
try {
|
|
114
|
+
await mongoose.connect('', options)
|
|
115
|
+
console.log(\`✅ MongoDB connected!\`)
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error(\`❌ MongoDB connection error: \${error.message}\`)
|
|
118
|
+
process.exit(1)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export default connectDB`;
|
|
123
|
+
fs.writeFileSync(dbConfigPath, mongooseContent);
|
|
124
|
+
|
|
125
|
+
} else if (database === 'PostgreSQL (Sequelize)') {
|
|
126
|
+
pkg.dependencies = pkg.dependencies || {};
|
|
127
|
+
pkg.dependencies.sequelize = '^6.35.0';
|
|
128
|
+
pkg.dependencies.pg = '^8.11.3';
|
|
129
|
+
pkg.dependencies.pg_hstore = '^2.3.4';
|
|
130
|
+
|
|
131
|
+
const sequelizeContent = `import { Sequelize } from "sequelize"
|
|
132
|
+
|
|
133
|
+
export const sequelize = new Sequelize(
|
|
134
|
+
'', // DB name
|
|
135
|
+
'', // User
|
|
136
|
+
'', // Password
|
|
137
|
+
{
|
|
138
|
+
host: '',
|
|
139
|
+
dialect: 'postgres',
|
|
140
|
+
logging: false,
|
|
141
|
+
port: ''
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
// Test connection
|
|
146
|
+
// (async () => {
|
|
147
|
+
// try {
|
|
148
|
+
// await sequelize.authenticate();
|
|
149
|
+
// console.log("PostgreSQL connected with Sequelize");
|
|
150
|
+
// } catch (err) {
|
|
151
|
+
// console.error("Error:", err.message);
|
|
152
|
+
// }
|
|
153
|
+
// })()
|
|
154
|
+
|
|
155
|
+
export default sequelize
|
|
156
|
+
`;
|
|
157
|
+
fs.writeFileSync(dbConfigPath, sequelizeContent);
|
|
158
|
+
|
|
159
|
+
} else {
|
|
160
|
+
fs.writeFileSync(dbConfigPath, '// No database configured\n');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Save updated package.json
|
|
164
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function installDependencies(targetPath, packageManager) {
|
|
168
|
+
const installSpinner = ora(`Installing dependencies using ${packageManager}...`).start();
|
|
169
|
+
try {
|
|
170
|
+
execSync(`${packageManager} install`, { cwd: targetPath, stdio: 'pipe' });
|
|
171
|
+
installSpinner.succeed('Dependencies installed successfully.');
|
|
172
|
+
} catch (err) {
|
|
173
|
+
installSpinner.fail('Failed to install dependencies.');
|
|
174
|
+
console.error(err);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function showSuccessMessage(targetDir, targetPath, packageManager) {
|
|
179
|
+
console.log(`\n${chalk.green('Success!')} Created ${path.basename(targetPath)} at ${targetPath}`);
|
|
180
|
+
console.log('\nInside that directory, you can run several commands:\n');
|
|
181
|
+
console.log(` ${chalk.cyan(`${packageManager} run dev`)}`);
|
|
182
|
+
console.log(' Starts the development server with nodemon.\n');
|
|
183
|
+
console.log('We suggest that you begin by typing:\n');
|
|
184
|
+
console.log(` ${chalk.cyan('cd')} ${targetDir}`);
|
|
185
|
+
console.log(` ${chalk.cyan(`${packageManager} run dev`)}\n`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ==========================================
|
|
189
|
+
// CLI Application
|
|
190
|
+
// ==========================================
|
|
191
|
+
|
|
192
|
+
program
|
|
193
|
+
.name('create-node-app')
|
|
194
|
+
.description('Scaffold a new Node.js application')
|
|
195
|
+
.argument('[project-directory]', 'Directory to create the project in')
|
|
196
|
+
.action(async (projectDirectory) => {
|
|
197
|
+
|
|
198
|
+
// 1. Prompt User
|
|
199
|
+
const { targetDir, packageManager, database } = await promptUser(projectDirectory);
|
|
200
|
+
const targetPath = path.resolve(process.cwd(), targetDir);
|
|
201
|
+
const templateDir = path.join(__dirname, '..', 'template');
|
|
202
|
+
|
|
203
|
+
console.log(`\nCreating a new Node.js app in ${chalk.green(targetPath)}\n`);
|
|
204
|
+
|
|
205
|
+
// 2. Copy Template Files
|
|
206
|
+
copyTemplateFiles(templateDir, targetPath);
|
|
207
|
+
|
|
208
|
+
// 3. Configure Database
|
|
209
|
+
configureDatabase(targetPath, database);
|
|
210
|
+
|
|
211
|
+
// 4. Install Dependencies
|
|
212
|
+
installDependencies(targetPath, packageManager);
|
|
213
|
+
|
|
214
|
+
// 5. Success Message
|
|
215
|
+
showSuccessMessage(targetDir, targetPath, packageManager);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
program.parse(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@apexkrrish/create-node-app",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A CLI tool to scaffold Node.js applications.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"private": false,
|
|
8
|
+
"bin": {
|
|
9
|
+
"create-node-app": "bin/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"start": "node ./bin/cli.js"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"chalk": "^5.3.0",
|
|
16
|
+
"commander": "^12.0.0",
|
|
17
|
+
"inquirer": "^9.2.14",
|
|
18
|
+
"ora": "^8.0.1"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/KrishDhimanOfficial/create_node_app.git"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"node",
|
|
26
|
+
"utility"
|
|
27
|
+
],
|
|
28
|
+
"author": "",
|
|
29
|
+
"license": "ISC",
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/KrishDhimanOfficial/create_node_app/issues"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/KrishDhimanOfficial/create_node_app#readme"
|
|
34
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# create-node-app
|
|
2
|
+
|
|
3
|
+
A fast and interactive CLI tool to scaffold Node.js applications.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Interactive Prompts**: Choose your project name, package manager, and database just by answering simple questions.
|
|
8
|
+
- **Multiple Package Managers**: Supports `npm`, `yarn`, and `pnpm`.
|
|
9
|
+
- **Database Configuration**: Automatically configures database connections with pre-written boilerplate for:
|
|
10
|
+
- MongoDB (using Mongoose)
|
|
11
|
+
- PostgreSQL (using Sequelize)
|
|
12
|
+
- None (no database setup out-of-the-box)
|
|
13
|
+
- **Ready to Go**: Automatically installs dependencies and sets up the basic folder structure based on the provided template.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
You can use the CLI directly:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx create-node-app [project-directory]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Or, if you clone locally and link:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm start -- my-new-project
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Interactive Prompts
|
|
30
|
+
|
|
31
|
+
If you do not provide a project directory, the CLI will ask you for one. It will then prompt you to answer the following:
|
|
32
|
+
|
|
33
|
+
1. **What is your project named?** (if no folder name was supplied)
|
|
34
|
+
2. **Which package manager would you like to use?**
|
|
35
|
+
- npm
|
|
36
|
+
- yarn
|
|
37
|
+
- pnpm
|
|
38
|
+
3. **Which database would you like to use?**
|
|
39
|
+
- MongoDB (Mongoose)
|
|
40
|
+
- PostgreSQL (Sequelize)
|
|
41
|
+
- None
|
|
42
|
+
|
|
43
|
+
### After Setup
|
|
44
|
+
|
|
45
|
+
Once the tool has finished scaffolding the project and installing dependencies, you can navigate into your new app and start the development server:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
cd <your-project-directory>
|
|
49
|
+
npm run dev
|
|
50
|
+
```
|
|
51
|
+
*(Replace `npm` with your chosen package manager!)*
|
package/template/.env
ADDED
|
File without changes
|
package/template/app.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import express from 'express'
|
|
2
|
+
import cookieParser from 'cookie-parser'
|
|
3
|
+
import logger from 'morgan'
|
|
4
|
+
import { globalErrorHandler } from './utils/helper.utils.js'
|
|
5
|
+
import compression from 'compression'
|
|
6
|
+
import cors from 'cors'
|
|
7
|
+
import { fileURLToPath } from 'node:url'
|
|
8
|
+
import path from 'node:path'
|
|
9
|
+
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
11
|
+
const __dirname = path.dirname(__filename)
|
|
12
|
+
const app = express()
|
|
13
|
+
|
|
14
|
+
app.use(cors())
|
|
15
|
+
app.use(logger('dev'))
|
|
16
|
+
app.use(express.json({ limit: '10kb' }))
|
|
17
|
+
app.use(express.urlencoded({ extended: true }))
|
|
18
|
+
app.use(compression(
|
|
19
|
+
{
|
|
20
|
+
level: 4, // compression level
|
|
21
|
+
threshold: 0, // Compress all
|
|
22
|
+
memLevel: 9, // memory usuage
|
|
23
|
+
filter: (req, res) => compression.filter(req, res)
|
|
24
|
+
}
|
|
25
|
+
))
|
|
26
|
+
app.use(cookieParser())
|
|
27
|
+
app.use(express.static(path.join(__dirname, 'public')))
|
|
28
|
+
|
|
29
|
+
app.get('/', (req, res) => {
|
|
30
|
+
return res.send('Hello World!')
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
// error handler
|
|
34
|
+
app.use(globalErrorHandler)
|
|
35
|
+
|
|
36
|
+
export default app
|
package/template/bin/www
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Module dependencies.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import app from '../app.js';
|
|
8
|
+
import Debug from 'debug';
|
|
9
|
+
const debug = Debug('create-node:server');
|
|
10
|
+
import http from 'http';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get port from environment and store in Express.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const port = normalizePort(process.env.PORT || '3000');
|
|
17
|
+
app.set('port', port);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Create HTTP server.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const server = http.createServer(app);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Listen on provided port, on all network interfaces.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
server.listen(port, () => {
|
|
30
|
+
console.log(`✅ Server is running on port ${port}`)
|
|
31
|
+
})
|
|
32
|
+
server.on('error', onError);
|
|
33
|
+
server.on('listening', onListening);
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Normalize a port into a number, string, or false.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
function normalizePort(val) {
|
|
40
|
+
const port = parseInt(val, 10);
|
|
41
|
+
|
|
42
|
+
if (isNaN(port)) {
|
|
43
|
+
// named pipe
|
|
44
|
+
return val;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (port >= 0) {
|
|
48
|
+
// port number
|
|
49
|
+
return port;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Event listener for HTTP server "error" event.
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
function onError(error) {
|
|
60
|
+
if (error.syscall !== 'listen') {
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const bind = typeof port === 'string'
|
|
65
|
+
? 'Pipe ' + port
|
|
66
|
+
: 'Port ' + port;
|
|
67
|
+
|
|
68
|
+
// handle specific listen errors with friendly messages
|
|
69
|
+
switch (error.code) {
|
|
70
|
+
case 'EACCES':
|
|
71
|
+
console.error(bind + ' requires elevated privileges');
|
|
72
|
+
process.exit(1);
|
|
73
|
+
break;
|
|
74
|
+
case 'EADDRINUSE':
|
|
75
|
+
console.error(bind + ' is already in use');
|
|
76
|
+
process.exit(1);
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Event listener for HTTP server "listening" event.
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
function onListening() {
|
|
88
|
+
const addr = server.address();
|
|
89
|
+
const bind = typeof addr === 'string'
|
|
90
|
+
? 'pipe ' + addr
|
|
91
|
+
: 'port ' + addr.port;
|
|
92
|
+
debug('Listening on ' + bind);
|
|
93
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "backend",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node ./bin/www",
|
|
8
|
+
"dev": "nodemon ./bin/www"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"compression": "^1.8.1",
|
|
12
|
+
"cookie-parser": "~1.4.4",
|
|
13
|
+
"cors": "^2.8.6",
|
|
14
|
+
"debug": "~2.6.9",
|
|
15
|
+
"express": "^4.22.1",
|
|
16
|
+
"morgan": "^1.10.1"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"nodemon": "^3.1.14"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { deleteFile } from './removeFile.utils.js'
|
|
2
|
+
|
|
3
|
+
export const ApiError = (message, statusCode) => {
|
|
4
|
+
const error = new Error(message)
|
|
5
|
+
error.statusCode = statusCode
|
|
6
|
+
error.success = false
|
|
7
|
+
return error
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const asyncHandler = (fn, name = 'UnknownController') => {
|
|
11
|
+
|
|
12
|
+
return (req, res, next) => {
|
|
13
|
+
Promise.resolve(fn(req, res, next)).catch((err) => {
|
|
14
|
+
console.error(`🔥 Error in ${name} : ${err.message}`)
|
|
15
|
+
if (req.file?.filename) deleteFile(req.file?.path)
|
|
16
|
+
if (req.files && req.files?.length > 0) req.files?.forEach(file => deleteFile(file.path))
|
|
17
|
+
next(err)
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const globalErrorHandler = (err, req, res, next) => {
|
|
23
|
+
const statusCode = err.statusCode || 500;
|
|
24
|
+
|
|
25
|
+
// For API requests (JSON response)
|
|
26
|
+
return res.status(statusCode).json(
|
|
27
|
+
{
|
|
28
|
+
success: false,
|
|
29
|
+
message: err.message || 'Something went wrong',
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import fs from 'node:fs'
|
|
4
|
+
import chalk from 'chalk'
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
7
|
+
const __dirname = path.dirname(__filename)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const deleteFile = async (folderPath) => {
|
|
11
|
+
try {
|
|
12
|
+
const imagePath = path.join(__dirname, '..', folderPath)
|
|
13
|
+
if (!fs.existsSync(imagePath)) return
|
|
14
|
+
|
|
15
|
+
await fs.promises.rm(imagePath, { force: true })
|
|
16
|
+
} catch (error) {
|
|
17
|
+
console.error(chalk.red('deleteFile error:', error.message))
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { deleteFile }
|