blux-start 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/index.js +293 -0
- package/package.json +21 -0
package/bin/index.js
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import fs from 'fs-extra';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
|
|
8
|
+
const program = new Command();
|
|
9
|
+
|
|
10
|
+
program
|
|
11
|
+
.name('blux')
|
|
12
|
+
.description('A simple CLI to scaffold a TypeScript boilerplate project for blu projects')
|
|
13
|
+
.version('1.0.0');
|
|
14
|
+
|
|
15
|
+
program
|
|
16
|
+
.command('init')
|
|
17
|
+
.argument('<project-name>', 'Name of the project directory')
|
|
18
|
+
.description('Scaffold a new TypeScript project')
|
|
19
|
+
.action(async (projectName) => {
|
|
20
|
+
const targetDir = path.resolve(process.cwd(), projectName);
|
|
21
|
+
|
|
22
|
+
// 1. Check if directory already exists
|
|
23
|
+
if (await fs.pathExists(targetDir)) {
|
|
24
|
+
console.error(chalk.red(`\n❌ Error: Directory "${projectName}" already exists.`));
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
console.log(chalk.blue(`\n🚀 Creating a new TypeScript project in ${chalk.bold(targetDir)}...\n`));
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
// 2. Create directory structure
|
|
32
|
+
// await fs.ensureDir(path.join(targetDir, 'src'));
|
|
33
|
+
|
|
34
|
+
// 3. Define file contents
|
|
35
|
+
const packageJson = {
|
|
36
|
+
"name": projectName,
|
|
37
|
+
"version": "1.0.0",
|
|
38
|
+
"description": "Backend generated by xtech",
|
|
39
|
+
"main": "./bin/www",
|
|
40
|
+
"type": "module",
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsc",
|
|
43
|
+
"start": "node ./bin/www",
|
|
44
|
+
"dev": "tsc --watch"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"cookie-parser": "~1.4.4",
|
|
48
|
+
"cors": "^2.8.6",
|
|
49
|
+
"debug": "~2.6.9",
|
|
50
|
+
"dotenv": "^17.4.2",
|
|
51
|
+
"express": "~4.16.1",
|
|
52
|
+
"http-errors": "~1.6.3",
|
|
53
|
+
"morgan": "~1.9.1",
|
|
54
|
+
"nodemon": "^3.1.14",
|
|
55
|
+
"mssql": "^12.5.5",
|
|
56
|
+
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"typescript": '^6.0.3',
|
|
60
|
+
"@types/node": "^25.9.3",
|
|
61
|
+
"tsx": "^4.22.4",
|
|
62
|
+
"@types/cookie-parser": "^1.4.10",
|
|
63
|
+
"@types/cors": "^2.8.19",
|
|
64
|
+
"@types/express": "^5.0.6",
|
|
65
|
+
"@types/morgan": "^1.9.10",
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const tsConfig = {
|
|
70
|
+
"compilerOptions": {
|
|
71
|
+
// File Layout
|
|
72
|
+
// "rootDir": "./src",
|
|
73
|
+
// "outDir": "./dist",
|
|
74
|
+
|
|
75
|
+
// Environment Settings
|
|
76
|
+
// See also https://aka.ms/tsconfig/module
|
|
77
|
+
"module": "nodenext",
|
|
78
|
+
"target": "esnext",
|
|
79
|
+
"types": [],
|
|
80
|
+
// For nodejs:
|
|
81
|
+
// "lib": ["esnext"],
|
|
82
|
+
// "types": ["node"],
|
|
83
|
+
// and npm install -D @types/node
|
|
84
|
+
|
|
85
|
+
// Other Outputs
|
|
86
|
+
"sourceMap": true,
|
|
87
|
+
"declaration": true,
|
|
88
|
+
"declarationMap": true,
|
|
89
|
+
|
|
90
|
+
// Stricter Typechecking Options
|
|
91
|
+
"noUncheckedIndexedAccess": true,
|
|
92
|
+
"exactOptionalPropertyTypes": true,
|
|
93
|
+
|
|
94
|
+
// Style Options
|
|
95
|
+
// "noImplicitReturns": true,
|
|
96
|
+
// "noImplicitOverride": true,
|
|
97
|
+
// "noUnusedLocals": true,
|
|
98
|
+
// "noUnusedParameters": true,
|
|
99
|
+
// "noFallthroughCasesInSwitch": true,
|
|
100
|
+
// "noPropertyAccessFromIndexSignature": true,
|
|
101
|
+
|
|
102
|
+
// Recommended Options
|
|
103
|
+
"strict": true,
|
|
104
|
+
"jsx": "react-jsx",
|
|
105
|
+
"verbatimModuleSyntax": true,
|
|
106
|
+
"isolatedModules": true,
|
|
107
|
+
"noUncheckedSideEffectImports": true,
|
|
108
|
+
"moduleDetection": "force",
|
|
109
|
+
"skipLibCheck": true,
|
|
110
|
+
"rewriteRelativeImportExtensions": true,
|
|
111
|
+
"allowImportingTsExtensions": true
|
|
112
|
+
},
|
|
113
|
+
include: ['src/**/*']
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const wwwwJs = `
|
|
117
|
+
import app from '../app.ts';
|
|
118
|
+
import debugLib from 'debug';
|
|
119
|
+
import http from 'http';
|
|
120
|
+
|
|
121
|
+
const debug = debugLib('site:server');
|
|
122
|
+
|
|
123
|
+
const port = normalizePort(process.env.PORT || '3000');
|
|
124
|
+
app.set('port', port);
|
|
125
|
+
|
|
126
|
+
const server = http.createServer(app);
|
|
127
|
+
|
|
128
|
+
server.listen(port);
|
|
129
|
+
server.on('error', onError);
|
|
130
|
+
server.on('listening', onListening);
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
console.log('Listening on port: 3000');
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
function normalizePort(val) {
|
|
137
|
+
const port = parseInt(val, 10);
|
|
138
|
+
|
|
139
|
+
if (isNaN(port)) {
|
|
140
|
+
return val;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (port >= 0) {
|
|
144
|
+
return port;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function onError(error) {
|
|
151
|
+
if (error.syscall !== 'listen') {
|
|
152
|
+
throw error;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const bind = typeof port === 'string'
|
|
156
|
+
? 'Pipe ' + port
|
|
157
|
+
: 'Port ' + port;
|
|
158
|
+
|
|
159
|
+
switch (error.code) {
|
|
160
|
+
case 'EACCES':
|
|
161
|
+
console.error(bind + ' requires elevated privileges');
|
|
162
|
+
process.exit(1);
|
|
163
|
+
break;
|
|
164
|
+
case 'EADDRINUSE':
|
|
165
|
+
console.error(bind + ' is already in use');
|
|
166
|
+
process.exit(1);
|
|
167
|
+
break;
|
|
168
|
+
default:
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function onListening() {
|
|
174
|
+
const addr = server.address();
|
|
175
|
+
const bind = typeof addr === 'string'
|
|
176
|
+
? 'pipe ' + addr
|
|
177
|
+
: 'port ' + addr.port;
|
|
178
|
+
debug('Listening on ' + bind);
|
|
179
|
+
}
|
|
180
|
+
`
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
const appTs = `
|
|
184
|
+
import { DbConnect } from './db/db.ts'
|
|
185
|
+
import createError from 'http-errors';
|
|
186
|
+
import express from 'express';
|
|
187
|
+
import path from 'path';
|
|
188
|
+
import { fileURLToPath } from 'url';
|
|
189
|
+
import cookieParser from 'cookie-parser';
|
|
190
|
+
import logger from 'morgan';
|
|
191
|
+
import cors from 'cors'
|
|
192
|
+
|
|
193
|
+
import indexRouter from './routes/index.ts';
|
|
194
|
+
|
|
195
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
196
|
+
const app = express();
|
|
197
|
+
|
|
198
|
+
// view engine setup
|
|
199
|
+
// app.set('views', path.join(__dirname, 'views'));
|
|
200
|
+
// app.set('view engine', 'html');
|
|
201
|
+
|
|
202
|
+
app.use(cors({
|
|
203
|
+
origin:"localhost:5173" // local reactapp
|
|
204
|
+
}))
|
|
205
|
+
|
|
206
|
+
app.use(logger('dev'));
|
|
207
|
+
app.use(express.json());
|
|
208
|
+
app.use(express.urlencoded({ extended: false }));
|
|
209
|
+
app.use(cookieParser());
|
|
210
|
+
app.use(express.static(path.join(__dirname, 'public')));
|
|
211
|
+
|
|
212
|
+
app.use('/', indexRouter);
|
|
213
|
+
|
|
214
|
+
// catch 404 and forward to error handler
|
|
215
|
+
app.use(function(req, res, next) {
|
|
216
|
+
next(createError(404));
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// setup connection DbConnect()
|
|
220
|
+
|
|
221
|
+
// error handler
|
|
222
|
+
app.use((err: { message: string; status?: number }, req: express.Request, res: express.Response, _next: express.NextFunction) => {
|
|
223
|
+
res.locals.message = err.message;
|
|
224
|
+
res.locals.error = req.app.get('env') === 'development' ? err : {};
|
|
225
|
+
|
|
226
|
+
res.status(err.status || 500);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
export default app;
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
`;
|
|
233
|
+
|
|
234
|
+
const indexTs = `
|
|
235
|
+
import { Router } from 'express';
|
|
236
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
237
|
+
|
|
238
|
+
const router = Router();
|
|
239
|
+
|
|
240
|
+
router.get('/', (_req: Request, _res: Response, _next: NextFunction) => {
|
|
241
|
+
_res.json({
|
|
242
|
+
message:"HELLO FROM SERVER"
|
|
243
|
+
})
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
export default router;
|
|
247
|
+
`
|
|
248
|
+
|
|
249
|
+
const dbTs = `
|
|
250
|
+
import sql from 'mssql'
|
|
251
|
+
import dotenv from 'dotenv'
|
|
252
|
+
|
|
253
|
+
export async function DbConnect(){
|
|
254
|
+
try {
|
|
255
|
+
const conn = await sql.connect('Server=dbhost,port;Database=dbname;User Id=dbuser;Password=$dbpass;Encrypt=true')
|
|
256
|
+
console.log('DB Con Status: ',conn.healthy)
|
|
257
|
+
} catch (err) {
|
|
258
|
+
console.log(err)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
`
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
const gitignore = `node_modules/\ndist/\n.env`;
|
|
265
|
+
|
|
266
|
+
// 4. Write files to target directory
|
|
267
|
+
await fs.ensureDir(path.join(targetDir,'bin'))
|
|
268
|
+
await fs.ensureDir(path.join(targetDir,'routes'))
|
|
269
|
+
await fs.ensureDir(path.join(targetDir,'db'))
|
|
270
|
+
await fs.ensureDir(path.join(targetDir,'public'))
|
|
271
|
+
await fs.outputJson(path.join(targetDir, 'package.json'), packageJson, { spaces: 2 });
|
|
272
|
+
await fs.outputJson(path.join(targetDir, 'tsconfig.json'), tsConfig, { spaces: 2 });
|
|
273
|
+
await fs.outputFile(path.join(targetDir, 'app.ts'), appTs);
|
|
274
|
+
await fs.outputFile(path.join(targetDir, '.gitignore'), gitignore);
|
|
275
|
+
await fs.outputFile(path.join(targetDir+'/bin','www'),wwwwJs)
|
|
276
|
+
await fs.outputFile(path.join(targetDir+'/routes','index.ts'),indexTs)
|
|
277
|
+
await fs.outputFile(path.join(targetDir+'/db','db.ts'),dbTs)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
// 5. Success Message
|
|
282
|
+
console.log(chalk.green(`✨ Successfully scaffolded ${chalk.bold(projectName)}!`));
|
|
283
|
+
console.log('\nNext steps:');
|
|
284
|
+
console.log(chalk.cyan(` cd ${projectName}`));
|
|
285
|
+
console.log(chalk.cyan(' npm install'));
|
|
286
|
+
console.log(chalk.cyan(' npm run dev\n'));
|
|
287
|
+
|
|
288
|
+
} catch (err) {
|
|
289
|
+
console.error(chalk.red('❌ Something went wrong during generation:'), err);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
program.parse(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "blux-start",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"author": "Xavier",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "bin/index.js",
|
|
9
|
+
"bin": {
|
|
10
|
+
"blux": "./bin/index.js"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"chalk": "^5.6.2",
|
|
17
|
+
"commander": "^15.0.0",
|
|
18
|
+
"fs-extra": "^11.3.5",
|
|
19
|
+
"prompts": "^2.4.2"
|
|
20
|
+
}
|
|
21
|
+
}
|