create-gramstax 0.0.1 → 0.0.3

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.
Files changed (56) hide show
  1. package/dist/src/index.cjs +13 -0
  2. package/dist/src/index.cjs.map +1 -0
  3. package/dist/src/index.d.cts +1 -0
  4. package/dist/src/index.d.ts +0 -2
  5. package/dist/src/index.js +12 -25
  6. package/dist/src/index.js.map +1 -0
  7. package/dist/src/templates/README.md +1 -1
  8. package/dist/src/templates/package.json +4 -4
  9. package/dist/src/templates/tsconfig.json +1 -1
  10. package/package.json +5 -4
  11. package/dist/package.json +0 -57
  12. package/dist/src/create-OLD.d.ts +0 -83
  13. package/dist/src/create-OLD.d.ts.map +0 -1
  14. package/dist/src/create-OLD.js +0 -676
  15. package/dist/src/create.d.ts +0 -34
  16. package/dist/src/create.d.ts.map +0 -1
  17. package/dist/src/create.js +0 -367
  18. package/dist/src/index.d.ts.map +0 -1
  19. package/dist/src/templates/src/env.d.ts +0 -8
  20. package/dist/src/utils/logger.d.ts +0 -3
  21. package/dist/src/utils/logger.d.ts.map +0 -1
  22. package/dist/src/utils/logger.js +0 -2
  23. package/src/create-OLD.ts +0 -783
  24. package/src/create.ts +0 -415
  25. package/src/index.ts +0 -28
  26. package/src/templates/.env.example +0 -17
  27. package/src/templates/.prettierignore +0 -1
  28. package/src/templates/.prettierrc +0 -23
  29. package/src/templates/LICENSE +0 -0
  30. package/src/templates/README.md +0 -121
  31. package/src/templates/bunfig.toml +0 -2
  32. package/src/templates/ecosystem.config.cjs +0 -26
  33. package/src/templates/package.json +0 -55
  34. package/src/templates/src/base/general.ts +0 -3
  35. package/src/templates/src/base/guard.ts +0 -3
  36. package/src/templates/src/base/page.ts +0 -3
  37. package/src/templates/src/base/repository.ts +0 -1
  38. package/src/templates/src/base/service.ts +0 -1
  39. package/src/templates/src/core/bot.ts +0 -22
  40. package/src/templates/src/db/index.ts +0 -3
  41. package/src/templates/src/env.d.ts +0 -8
  42. package/src/templates/src/guards/user.ts +0 -19
  43. package/src/templates/src/index.ts +0 -17
  44. package/src/templates/src/pages/general-error-input-notfound.ts +0 -34
  45. package/src/templates/src/pages/general-error.ts +0 -51
  46. package/src/templates/src/pages/help.ts +0 -56
  47. package/src/templates/src/pages/start.ts +0 -63
  48. package/src/templates/src/pages/username-notfound.ts +0 -41
  49. package/src/templates/src/repositories/example.ts +0 -5
  50. package/src/templates/src/services/example.ts +0 -4
  51. package/src/templates/src/templates/example.html +0 -7
  52. package/src/templates/src/threads/main.ts +0 -9
  53. package/src/templates/src/utils/log.ts +0 -3
  54. package/src/templates/tsconfig.json +0 -38
  55. package/src/utils/logger.ts +0 -3
  56. /package/dist/src/templates/{ecosystem.config.cjs → ecosystem.config.js} +0 -0
package/src/create-OLD.ts DELETED
@@ -1,783 +0,0 @@
1
- import * as fs from "fs"
2
- import * as path from "path"
3
- import { log } from "./utils/logger"
4
- import { spawn } from "child_process"
5
- import enquirer from "enquirer"
6
-
7
- type CreateOptions = {
8
- yes?: boolean
9
- useBun?: boolean
10
- useNpm?: boolean
11
- usePnpm?: boolean
12
- useYarn?: boolean
13
- eslint?: boolean
14
- }
15
-
16
- type PackageManager = `bun` | `npm` | `pnpm` | `yarn`
17
- type Runtime = `bun` | `node`
18
-
19
- /**
20
- * Recursively copy directory structure
21
- */
22
- function copyDirectorySync(source: string, destination: string, variables: Record<string, string> = {}) {
23
- // Create destination directory if it doesn't exist
24
- if (!fs.existsSync(destination)) {
25
- fs.mkdirSync(destination, { recursive: true })
26
- }
27
-
28
- // Read all items in source directory
29
- const items = fs.readdirSync(source, { withFileTypes: true })
30
-
31
- for (const item of items) {
32
- const sourcePath = path.join(source, item.name)
33
- const destPath = path.join(destination, item.name)
34
-
35
- if (item.isDirectory()) {
36
- // Recursively copy subdirectories
37
- copyDirectorySync(sourcePath, destPath, variables)
38
- } else if (item.isFile()) {
39
- // Copy file and replace variables if needed
40
- let content = fs.readFileSync(sourcePath, `utf-8`)
41
-
42
- // Replace template variables in content
43
- content = replaceTemplateVariables(content, variables)
44
-
45
- fs.writeFileSync(destPath, content)
46
- }
47
- }
48
- }
49
-
50
- /**
51
- * Replace template variables in content
52
- */
53
- function replaceTemplateVariables(content: string, variables: Record<string, string>): string {
54
- let result = content
55
- for (const [key, value] of Object.entries(variables)) {
56
- result = result.replace(new RegExp(`{{${key}}}`, `g`), value)
57
- }
58
- return result
59
- }
60
-
61
- /**
62
- * Get package manager commands
63
- */
64
- function getPackageManagerCommands(packageManager: PackageManager) {
65
- const commands = {
66
- bun: {
67
- install: `bun install`,
68
- dev: `bun dev`,
69
- start: `bun start`,
70
- "pm2:start": `bun run pm2:start`,
71
- "pm2:stop": `bun run pm2:stop`,
72
- "pm2:restart": `bun run pm2:restart`,
73
- "pm2:delete": `bun run pm2:delete`,
74
- "pm2:logs": `bun run pm2:logs`,
75
- "pm2:monit": `bun run pm2:monit`
76
- },
77
- npm: {
78
- install: `npm install`,
79
- dev: `npm run dev`,
80
- start: `npm start`,
81
- "pm2:start": `npm run pm2:start`,
82
- "pm2:stop": `npm run pm2:stop`,
83
- "pm2:restart": `npm run pm2:restart`,
84
- "pm2:delete": `npm run pm2:delete`,
85
- "pm2:logs": `npm run pm2:logs`,
86
- "pm2:monit": `npm run pm2:monit`
87
- },
88
- pnpm: {
89
- install: `pnpm install`,
90
- dev: `pnpm dev`,
91
- start: `pnpm start`,
92
- "pm2:start": `pnpm pm2:start`,
93
- "pm2:stop": `pnpm pm2:stop`,
94
- "pm2:restart": `pnpm pm2:restart`,
95
- "pm2:delete": `pnpm pm2:delete`,
96
- "pm2:logs": `pnpm pm2:logs`,
97
- "pm2:monit": `pnpm pm2:monit`
98
- },
99
- yarn: {
100
- install: `yarn install`,
101
- dev: `yarn dev`,
102
- start: `yarn start`,
103
- "pm2:start": `yarn pm2:start`,
104
- "pm2:stop": `yarn pm2:stop`,
105
- "pm2:restart": `yarn pm2:restart`,
106
- "pm2:delete": `yarn pm2:delete`,
107
- "pm2:logs": `yarn pm2:logs`,
108
- "pm2:monit": `yarn pm2:monit`
109
- }
110
- }
111
- return commands[packageManager]
112
- }
113
-
114
- export async function createProject(projectDirectory?: string, options?: CreateOptions) {
115
- // Display ASCII art banner
116
- printBanner()
117
-
118
- // Get project name - if not provided, prompt or use current directory
119
- let projectName = projectDirectory
120
- let projectPath: string
121
-
122
- if (!projectName) {
123
- if (options?.yes) {
124
- // Use current directory name like npm init
125
- projectName = path.basename(process.cwd())
126
- projectPath = process.cwd()
127
-
128
- // Check if current directory is empty
129
- const files = fs.readdirSync(projectPath)
130
- if (files.length > 0) {
131
- log.error(`Current directory is not empty!`)
132
- process.exit(1)
133
- }
134
- } else {
135
- projectName = await promptForProjectName()
136
- projectPath = path.resolve(process.cwd(), projectName)
137
-
138
- // Check if directory already exists
139
- if (fs.existsSync(projectPath) && projectName != ``) {
140
- log.error(`Directory "${projectName}" already exists!`)
141
- process.exit(1)
142
- }
143
-
144
- if (projectName != ``) {
145
- // Create project directory
146
- fs.mkdirSync(projectPath, { recursive: true })
147
- }
148
- }
149
- } else {
150
- projectPath = path.resolve(process.cwd(), projectName)
151
-
152
- // Check if directory already exists
153
- if (fs.existsSync(projectPath)) {
154
- log.error(`Directory "${projectName}" already exists!`)
155
- process.exit(1)
156
- }
157
-
158
- // Create project directory
159
- fs.mkdirSync(projectPath, { recursive: true })
160
- }
161
-
162
- log.info(`Creating project: ${path.basename(projectPath)}`)
163
- log.info(`Location: ${projectPath}`)
164
-
165
- // Prompt for configuration if not in --yes mode
166
- let packageManager: PackageManager
167
- let runtime: Runtime
168
- let setupEslint: boolean
169
-
170
- if (options?.yes) {
171
- packageManager = detectPackageManager(options)
172
- runtime = packageManager === `bun` ? `bun` : `node`
173
- setupEslint = false
174
-
175
- log.info(`Using defaults - Package Manager: ${packageManager}, Runtime: ${runtime}, ESLint: No`)
176
- } else {
177
- const config = await promptForConfiguration(options)
178
- packageManager = config.packageManager
179
- runtime = config.runtime
180
- setupEslint = config.eslint
181
-
182
- log.info(`Configuration - Package Manager: ${packageManager}, Runtime: ${runtime}, ESLint: ${setupEslint ? `Yes` : `No`}`)
183
- }
184
-
185
- // Generate project structure
186
- log.info(`Generating project structure...`)
187
- await generateProjectStructure(projectPath, projectName, packageManager, runtime)
188
-
189
- // Setup ESLint if requested
190
- if (setupEslint) {
191
- log.info(`Setting up ESLint...`)
192
- await setupEslintConfig(projectPath, packageManager)
193
- }
194
-
195
- const commands = getPackageManagerCommands(packageManager)
196
-
197
- log.success(`Project created successfully!`)
198
- log.info(``)
199
- log.info(`Next steps:`)
200
- if (projectDirectory) {
201
- log.info(` cd ${projectName}`)
202
- }
203
- log.info(` ${commands.install}`)
204
- log.info(` ${commands.dev}`)
205
- log.info(``)
206
- log.info(`For production:`)
207
- log.info(` ${commands[`pm2:start`]}`)
208
- }
209
-
210
- function printBanner() {
211
- const banner = `
212
- $$$$$$\\ $$\\
213
- $$ __$$\\ $$ |
214
- $$ / \\__| $$$$$$\\ $$$$$$\\ $$$$$$\\$$$$\\ $$$$$$$\\ $$$$$$\\ $$$$$$\\ $$\\ $$\\
215
- $$ |$$$$\\ $$ __$$\\ \\____$$\\ $$ _$$ _$$\\ $$ _____|\\_$$ _| \\____$$\\ \\$$\\ $$ |
216
- $$ |\\_$$ |$$ | \\__|$$$$$$$ |$$ / $$ / $$ |\\$$$$$$\\ $$ | $$$$$$$ | \\$$$$ /
217
- $$ | $$ |$$ | $$ __$$ |$$ | $$ | $$ | \\____$$\\ $$ |$$\\ $$ __$$ | $$ $$<
218
- \\$$$$$$ |$$ | \\$$$$$$$ |$$ | $$ | $$ |$$$$$$$ | \\$$$$ |\\$$$$$$$ |$$ /\\$$\\
219
- \\______/ \\__| \\_______|\\__| \\__| \\__|\\_______/ \\____/ \\_______|\\__/ \\__|
220
-
221
- `
222
- console.log(banner)
223
- }
224
-
225
- async function promptForProjectName(): Promise<string> {
226
- const response = await enquirer.prompt<{ projectName: string }>({
227
- type: `input`,
228
- name: `projectName`,
229
- message: `What is your project named?`,
230
- initial: ``,
231
- validate: (value: string) => {
232
- if (value == ``) {
233
- return true
234
- }
235
-
236
- if (!/^[a-z0-9-_]+$/i.test(value)) {
237
- return `Project name can only contain letters, numbers, hyphens, and underscores`
238
- }
239
- return true
240
- }
241
- })
242
-
243
- return response.projectName
244
- }
245
-
246
- async function promptForConfiguration(options?: CreateOptions): Promise<{
247
- packageManager: PackageManager
248
- runtime: Runtime
249
- eslint: boolean
250
- }> {
251
- const questions: any[] = []
252
-
253
- // Package manager selection
254
- if (!options?.useBun && !options?.useNpm && !options?.usePnpm && !options?.useYarn) {
255
- questions.push({
256
- type: `select`,
257
- name: `packageManager`,
258
- message: `Which package manager would you like to use?`,
259
- choices: [
260
- { name: `bun`, message: `Bun (recommended)`, value: `bun` },
261
- { name: `npm`, message: `npm`, value: `npm` },
262
- { name: `pnpm`, message: `pnpm`, value: `pnpm` },
263
- { name: `yarn`, message: `Yarn`, value: `yarn` }
264
- ],
265
- initial: 0
266
- })
267
- }
268
-
269
- // Runtime selection
270
- questions.push({
271
- type: `select`,
272
- name: `runtime`,
273
- message: `Which runtime would you like to use?`,
274
- choices: [
275
- { name: `bun`, message: `Bun (recommended)`, value: `bun` },
276
- { name: `node`, message: `Node.js`, value: `node` }
277
- ],
278
- initial: 0
279
- })
280
-
281
- // ESLint
282
- if (options?.eslint === undefined) {
283
- questions.push({
284
- type: `confirm`,
285
- name: `eslint`,
286
- message: `Would you like to use ESLint?`,
287
- initial: true
288
- })
289
- }
290
-
291
- const answers = await enquirer.prompt<{
292
- packageManager?: PackageManager
293
- runtime: Runtime
294
- eslint?: boolean
295
- }>(questions)
296
-
297
- return {
298
- packageManager: answers.packageManager || detectPackageManager(options),
299
- runtime: answers.runtime,
300
- eslint: answers.eslint !== undefined ? answers.eslint : options?.eslint || false
301
- }
302
- }
303
-
304
- function detectPackageManager(options?: CreateOptions): PackageManager {
305
- if (options?.useBun) return `bun`
306
- if (options?.useNpm) return `npm`
307
- if (options?.usePnpm) return `pnpm`
308
- if (options?.useYarn) return `yarn`
309
-
310
- // Try to detect from environment
311
- const userAgent = process.env.npm_config_user_agent || ``
312
- if (userAgent.includes(`bun`)) return `bun`
313
- if (userAgent.includes(`pnpm`)) return `pnpm`
314
- if (userAgent.includes(`yarn`)) return `yarn`
315
-
316
- // Default to bun
317
- return `bun`
318
- }
319
-
320
- async function generateProjectStructure(projectPath: string, projectName: string, packageManager: PackageManager, runtime: Runtime) {
321
- log.info(`📁 Creating project structure...`)
322
-
323
- const templatesPath = path.join(__dirname, `templates`)
324
- const commands = getPackageManagerCommands(packageManager)
325
-
326
- // Prepare template variables
327
- const variables = {
328
- projectName,
329
- installCmd: commands.install,
330
- runDevCmd: commands.dev,
331
- runStartCmd: commands.start,
332
- runPm2StartCmd: commands[`pm2:start`],
333
- runPm2StopCmd: commands[`pm2:stop`],
334
- runPm2RestartCmd: commands[`pm2:restart`],
335
- runPm2DeleteCmd: commands[`pm2:delete`],
336
- runPm2LogsCmd: commands[`pm2:logs`],
337
- runPm2MonitCmd: commands[`pm2:monit`]
338
- }
339
-
340
- log.info(`📝 Copying template files...`)
341
-
342
- // Copy entire template structure recursively
343
- copyDirectorySync(templatesPath, projectPath, variables)
344
-
345
- // Create logs directory
346
- fs.mkdirSync(path.join(projectPath, `logs`), { recursive: true })
347
- fs.writeFileSync(path.join(projectPath, `logs/.gitkeep`), ``)
348
-
349
- // Create .env.example as copy of .env
350
- const envPath = path.join(projectPath, `.env`)
351
- const envExamplePath = path.join(projectPath, `.env.example`)
352
- if (fs.existsSync(envPath)) {
353
- fs.copyFileSync(envPath, envExamplePath)
354
- }
355
-
356
- // Remove bunfig.toml if runtime is NOT bun
357
- if (runtime !== `bun`) {
358
- const bunfigPath = path.join(projectPath, `bunfig.toml`)
359
- if (fs.existsSync(bunfigPath)) {
360
- fs.unlinkSync(bunfigPath)
361
- }
362
- }
363
-
364
- log.success(`✅ All files generated!`)
365
- }
366
-
367
- async function setupEslintConfig(projectPath: string, packageManager: PackageManager): Promise<void> {
368
- log.info(``)
369
- log.info(`🔍 Setting up ESLint...`)
370
-
371
- return new Promise((resolve, reject) => {
372
- // Use npm init @eslint/config with --yes flag for default configuration
373
- const initProcess = spawn(`npm`, [`init`, `@eslint/config@latest`, `--`, `--yes`], {
374
- cwd: projectPath,
375
- stdio: `inherit`,
376
- shell: true
377
- })
378
-
379
- initProcess.on(`close`, (code) => {
380
- if (code === 0) {
381
- log.success(`✅ ESLint configured successfully!`)
382
- resolve()
383
- } else {
384
- log.warn(`⚠️ ESLint setup failed. You can set it up later with: npm init @eslint/config`)
385
- resolve() // Don't fail the whole process
386
- }
387
- })
388
-
389
- initProcess.on(`error`, (error) => {
390
- log.warn(`⚠️ ESLint setup failed: ${error.message}`)
391
- log.info(`You can set it up later with: npm init @eslint/config`)
392
- resolve() // Don't fail the whole process
393
- })
394
- })
395
- }
396
-
397
- export default class {
398
- public runtime: Runtime | undefined
399
- public projectPath: string | undefined
400
- public projectName: string | undefined
401
- public packageManager: PackageManager | undefined
402
- public constructor() {
403
- //
404
- }
405
-
406
- public printBanner() {
407
- const banner = `
408
- $$$$$$\\ $$\\
409
- $$ __$$\\ $$ |
410
- $$ / \\__| $$$$$$\\ $$$$$$\\ $$$$$$\\$$$$\\ $$$$$$$\\ $$$$$$\\ $$$$$$\\ $$\\ $$\\
411
- $$ |$$$$\\ $$ __$$\\ \\____$$\\ $$ _$$ _$$\\ $$ _____|\\_$$ _| \\____$$\\ \\$$\\ $$ |
412
- $$ |\\_$$ |$$ | \\__|$$$$$$$ |$$ / $$ / $$ |\\$$$$$$\\ $$ | $$$$$$$ | \\$$$$ /
413
- $$ | $$ |$$ | $$ __$$ |$$ | $$ | $$ | \\____$$\\ $$ |$$\\ $$ __$$ | $$ $$<
414
- \\$$$$$$ |$$ | \\$$$$$$$ |$$ | $$ | $$ |$$$$$$$ | \\$$$$ |\\$$$$$$$ |$$ /\\$$\\
415
- \\______/ \\__| \\_______|\\__| \\__| \\__|\\_______/ \\____/ \\_______|\\__/ \\__|
416
-
417
- `
418
- console.log(banner)
419
- }
420
-
421
- public detectPackageManager(options?: CreateOptions): PackageManager {
422
- if (options?.useBun) return (this.packageManager = `bun`)
423
- if (options?.useNpm) return (this.packageManager = `npm`)
424
- if (options?.usePnpm) return (this.packageManager = `pnpm`)
425
- if (options?.useYarn) return (this.packageManager = `yarn`)
426
-
427
- // Try to detect from environment
428
- const userAgent = process.env.npm_config_user_agent || ``
429
- if (userAgent.includes(`bun`)) return (this.packageManager = `bun`)
430
- if (userAgent.includes(`pnpm`)) return (this.packageManager = `pnpm`)
431
- if (userAgent.includes(`yarn`)) return (this.packageManager = `yarn`)
432
-
433
- // Default to bun
434
- return (this.packageManager = `bun`)
435
- }
436
-
437
- /**
438
- * Recursively copy directory structure
439
- */
440
- public copyDirectorySync(source: string, destination: string, variables: Record<string, string> = {}) {
441
- // Create destination directory if it doesn't exist
442
- if (!fs.existsSync(destination)) {
443
- fs.mkdirSync(destination, { recursive: true })
444
- }
445
-
446
- // Read all items in source directory
447
- const items = fs.readdirSync(source, { withFileTypes: true })
448
-
449
- for (const item of items) {
450
- const sourcePath = path.join(source, item.name)
451
- const destPath = path.join(destination, item.name)
452
-
453
- if (item.isDirectory()) {
454
- // Recursively copy subdirectories
455
- copyDirectorySync(sourcePath, destPath, variables)
456
- } else if (item.isFile()) {
457
- // Copy file and replace variables if needed
458
- let content = fs.readFileSync(sourcePath, `utf-8`)
459
-
460
- // Replace template variables in content
461
- content = replaceTemplateVariables(content, variables)
462
-
463
- fs.writeFileSync(destPath, content)
464
- }
465
- }
466
- }
467
-
468
- /**
469
- * Replace template variables in content
470
- */
471
- public replaceTemplateVariables(content: string, variables: Record<string, string>): string {
472
- let result = content
473
- for (const [key, value] of Object.entries(variables)) {
474
- result = result.replace(new RegExp(`{{${key}}}`, `g`), value)
475
- }
476
- return result
477
- }
478
-
479
- /**
480
- * Get package manager commands
481
- */
482
- public getPackageManagerCommands(packageManager: PackageManager) {
483
- const commands = {
484
- bun: {
485
- install: `bun install`,
486
- dev: `bun dev`,
487
- start: `bun start`,
488
- "pm2:start": `bun run pm2:start`,
489
- "pm2:stop": `bun run pm2:stop`,
490
- "pm2:restart": `bun run pm2:restart`,
491
- "pm2:delete": `bun run pm2:delete`,
492
- "pm2:logs": `bun run pm2:logs`,
493
- "pm2:monit": `bun run pm2:monit`
494
- },
495
- npm: {
496
- install: `npm install`,
497
- dev: `npm run dev`,
498
- start: `npm start`,
499
- "pm2:start": `npm run pm2:start`,
500
- "pm2:stop": `npm run pm2:stop`,
501
- "pm2:restart": `npm run pm2:restart`,
502
- "pm2:delete": `npm run pm2:delete`,
503
- "pm2:logs": `npm run pm2:logs`,
504
- "pm2:monit": `npm run pm2:monit`
505
- },
506
- pnpm: {
507
- install: `pnpm install`,
508
- dev: `pnpm dev`,
509
- start: `pnpm start`,
510
- "pm2:start": `pnpm pm2:start`,
511
- "pm2:stop": `pnpm pm2:stop`,
512
- "pm2:restart": `pnpm pm2:restart`,
513
- "pm2:delete": `pnpm pm2:delete`,
514
- "pm2:logs": `pnpm pm2:logs`,
515
- "pm2:monit": `pnpm pm2:monit`
516
- },
517
- yarn: {
518
- install: `yarn install`,
519
- dev: `yarn dev`,
520
- start: `yarn start`,
521
- "pm2:start": `yarn pm2:start`,
522
- "pm2:stop": `yarn pm2:stop`,
523
- "pm2:restart": `yarn pm2:restart`,
524
- "pm2:delete": `yarn pm2:delete`,
525
- "pm2:logs": `yarn pm2:logs`,
526
- "pm2:monit": `yarn pm2:monit`
527
- }
528
- }
529
- return commands[packageManager]
530
- }
531
-
532
- public async promptForProjectName(): Promise<string> {
533
- const response = await enquirer.prompt<{ projectName: string }>({
534
- type: `input`,
535
- name: `projectName`,
536
- message: `What is your project named?`,
537
- initial: ``,
538
- validate: (value: string) => {
539
- if (value == ``) {
540
- return true
541
- }
542
-
543
- if (!/^[a-z0-9-_]+$/i.test(value)) {
544
- return `Project name can only contain letters, numbers, hyphens, and underscores`
545
- }
546
- return true
547
- }
548
- })
549
-
550
- return response.projectName
551
- }
552
-
553
- public async promptForConfiguration(options?: CreateOptions): Promise<{
554
- packageManager: PackageManager
555
- runtime: Runtime
556
- eslint: boolean
557
- }> {
558
- const questions: any[] = []
559
-
560
- // Package manager selection
561
- if (!options?.useBun && !options?.useNpm && !options?.usePnpm && !options?.useYarn) {
562
- questions.push({
563
- type: `select`,
564
- name: `packageManager`,
565
- message: `Which package manager would you like to use?`,
566
- choices: [
567
- { name: `bun`, message: `Bun (recommended)`, value: `bun` },
568
- { name: `npm`, message: `npm`, value: `npm` },
569
- { name: `pnpm`, message: `pnpm`, value: `pnpm` },
570
- { name: `yarn`, message: `Yarn`, value: `yarn` }
571
- ],
572
- initial: 0
573
- })
574
- }
575
-
576
- // Runtime selection
577
- questions.push({
578
- type: `select`,
579
- name: `runtime`,
580
- message: `Which runtime would you like to use?`,
581
- choices: [
582
- { name: `bun`, message: `Bun (recommended)`, value: `bun` },
583
- { name: `node`, message: `Node.js`, value: `node` }
584
- ],
585
- initial: 0
586
- })
587
-
588
- // ESLint
589
- if (options?.eslint === undefined) {
590
- questions.push({
591
- type: `confirm`,
592
- name: `eslint`,
593
- message: `Would you like to use ESLint?`,
594
- initial: true
595
- })
596
- }
597
-
598
- const answers = await enquirer.prompt<{
599
- packageManager?: PackageManager
600
- runtime: Runtime
601
- eslint?: boolean
602
- }>(questions)
603
-
604
- return {
605
- packageManager: answers.packageManager || detectPackageManager(options),
606
- runtime: answers.runtime,
607
- eslint: answers.eslint !== undefined ? answers.eslint : options?.eslint || false
608
- }
609
- }
610
-
611
- public async generateProjectStructure(projectPath: string, projectName: string, packageManager: PackageManager, runtime: Runtime) {
612
- log.info(`📁 Creating project structure...`)
613
-
614
- const templatesPath = path.join(__dirname, `templates`)
615
- const commands = getPackageManagerCommands(packageManager)
616
-
617
- // Prepare template variables
618
- const variables = {
619
- projectName,
620
- installCmd: commands.install,
621
- runDevCmd: commands.dev,
622
- runStartCmd: commands.start,
623
- runPm2StartCmd: commands[`pm2:start`],
624
- runPm2StopCmd: commands[`pm2:stop`],
625
- runPm2RestartCmd: commands[`pm2:restart`],
626
- runPm2DeleteCmd: commands[`pm2:delete`],
627
- runPm2LogsCmd: commands[`pm2:logs`],
628
- runPm2MonitCmd: commands[`pm2:monit`]
629
- }
630
-
631
- log.info(`📝 Copying template files...`)
632
-
633
- // Copy entire template structure recursively
634
- copyDirectorySync(templatesPath, projectPath, variables)
635
-
636
- // Create logs directory
637
- fs.mkdirSync(path.join(projectPath, `logs`), { recursive: true })
638
- fs.writeFileSync(path.join(projectPath, `logs/.gitkeep`), ``)
639
-
640
- // Create .env.example as copy of .env
641
- const envPath = path.join(projectPath, `.env`)
642
- const envExamplePath = path.join(projectPath, `.env.example`)
643
- if (fs.existsSync(envPath)) {
644
- fs.copyFileSync(envPath, envExamplePath)
645
- }
646
-
647
- // Remove bunfig.toml if runtime is NOT bun
648
- if (runtime !== `bun`) {
649
- const bunfigPath = path.join(projectPath, `bunfig.toml`)
650
- if (fs.existsSync(bunfigPath)) {
651
- fs.unlinkSync(bunfigPath)
652
- }
653
- }
654
-
655
- log.success(`✅ All files generated!`)
656
- }
657
-
658
- public async setupEslintConfig(projectPath: string, packageManager: PackageManager): Promise<void> {
659
- log.info(``)
660
- log.info(`🔍 Setting up ESLint...`)
661
-
662
- return new Promise((resolve, reject) => {
663
- // Use npm init @eslint/config with --yes flag for default configuration
664
- const initProcess = spawn(`npm`, [`init`, `@eslint/config@latest`, `--`, `--yes`], {
665
- cwd: projectPath,
666
- stdio: `inherit`,
667
- shell: true
668
- })
669
-
670
- initProcess.on(`close`, (code) => {
671
- if (code === 0) {
672
- log.success(`✅ ESLint configured successfully!`)
673
- resolve()
674
- } else {
675
- log.warn(`⚠️ ESLint setup failed. You can set it up later with: npm init @eslint/config`)
676
- resolve() // Don't fail the whole process
677
- }
678
- })
679
-
680
- initProcess.on(`error`, (error) => {
681
- log.warn(`⚠️ ESLint setup failed: ${error.message}`)
682
- log.info(`You can set it up later with: npm init @eslint/config`)
683
- resolve() // Don't fail the whole process
684
- })
685
- })
686
- }
687
-
688
- public async createProject(projectDirectory?: string, options?: CreateOptions) {
689
- // Display ASCII art banner
690
- printBanner()
691
-
692
- // Get project name - if not provided, prompt or use current directory
693
- let projectName = projectDirectory
694
- let projectPath: string
695
-
696
- if (!projectName) {
697
- if (options?.yes) {
698
- // Use current directory name like npm init
699
- projectName = path.basename(process.cwd())
700
- projectPath = process.cwd()
701
-
702
- // Check if current directory is empty
703
- const files = fs.readdirSync(projectPath)
704
- if (files.length > 0) {
705
- log.error(`Current directory is not empty!`)
706
- process.exit(1)
707
- }
708
- } else {
709
- projectName = await promptForProjectName()
710
- projectPath = path.resolve(process.cwd(), projectName)
711
-
712
- // Check if directory already exists
713
- if (fs.existsSync(projectPath) && projectName != ``) {
714
- log.error(`Directory "${projectName}" already exists!`)
715
- process.exit(1)
716
- }
717
-
718
- if (projectName != ``) {
719
- // Create project directory
720
- fs.mkdirSync(projectPath, { recursive: true })
721
- }
722
- }
723
- } else {
724
- projectPath = path.resolve(process.cwd(), projectName)
725
-
726
- // Check if directory already exists
727
- if (fs.existsSync(projectPath)) {
728
- log.error(`Directory "${projectName}" already exists!`)
729
- process.exit(1)
730
- }
731
-
732
- // Create project directory
733
- fs.mkdirSync(projectPath, { recursive: true })
734
- }
735
-
736
- log.info(`Creating project: ${path.basename(projectPath)}`)
737
- log.info(`Location: ${projectPath}`)
738
-
739
- // Prompt for configuration if not in --yes mode
740
- let packageManager: PackageManager
741
- let runtime: Runtime
742
- let setupEslint: boolean
743
-
744
- if (options?.yes) {
745
- packageManager = this.detectPackageManager(options)
746
- runtime = packageManager === `bun` ? `bun` : `node`
747
- setupEslint = false
748
-
749
- log.info(`Using defaults - Package Manager: ${packageManager}, Runtime: ${runtime}, ESLint: No`)
750
- } else {
751
- const config = await promptForConfiguration(options)
752
- packageManager = config.packageManager
753
- runtime = config.runtime
754
- setupEslint = config.eslint
755
-
756
- log.info(`Configuration - Package Manager: ${packageManager}, Runtime: ${runtime}, ESLint: ${setupEslint ? `Yes` : `No`}`)
757
- }
758
-
759
- // Generate project structure
760
- log.info(`Generating project structure...`)
761
- await generateProjectStructure(projectPath, projectName, packageManager, runtime)
762
-
763
- // Setup ESLint if requested
764
- if (setupEslint) {
765
- log.info(`Setting up ESLint...`)
766
- await setupEslintConfig(projectPath, packageManager)
767
- }
768
-
769
- const commands = getPackageManagerCommands(packageManager)
770
-
771
- log.success(`Project created successfully!`)
772
- log.info(``)
773
- log.info(`Next steps:`)
774
- if (projectDirectory) {
775
- log.info(` cd ${projectName}`)
776
- }
777
- log.info(` ${commands.install}`)
778
- log.info(` ${commands.dev}`)
779
- log.info(``)
780
- log.info(`For production:`)
781
- log.info(` ${commands[`pm2:start`]}`)
782
- }
783
- }