create-rex-app 1.0.1 → 1.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.
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  import fs from 'fs';
4
4
  import path from 'path';
@@ -7,142 +7,162 @@ import { exec } from 'child_process';
7
7
  import util from 'util';
8
8
  import chalk from 'chalk';
9
9
  import ora from 'ora';
10
- import { confirm, select } from '@inquirer/prompts'; // <-- Imported select
10
+ import { confirm, select, input } from '@inquirer/prompts';
11
11
 
12
12
  const execPromise = util.promisify(exec);
13
-
14
13
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
- const projectName = process.argv[2] || 'react-express-app';
16
- const currentDir = process.cwd();
17
- const targetPath = path.join(currentDir, projectName);
18
-
19
- console.log();
20
- console.log(`Creating a new Rex app in ${chalk.green(targetPath)}.`);
21
- console.log();
22
-
23
- // 1. The Safe Empty Check
24
- if (fs.existsSync(targetPath)) {
25
- const files = fs.readdirSync(targetPath);
26
- if (files.length > 0) {
27
- console.error(chalk.red(`The directory ${chalk.green(projectName)} contains files that could conflict.`));
28
- console.error(chalk.red('Either try using a new directory name, or remove the existing files.'));
29
- process.exit(1);
30
- }
31
- } else {
32
- fs.mkdirSync(targetPath, { recursive: true });
33
- }
34
14
 
35
- // 2. Template Selection Prompt
36
- const templateChoice = await select({
37
- message: 'Which Rex template would you like to use?',
38
- choices: [
39
- {
40
- name: chalk.hex('#7C3AED')('Vanilla Rex (Standard)'), // Rex Purple
41
- value: 'template',
42
- description: 'The blazing fast, lightweight setup.',
43
- },
44
- {
45
- name: chalk.hex('#F97316')('Mongo Rex (Standard + MongoDB + JWT Auth)'), // Rex Orange
46
- value: 'template-mongo',
47
- description: 'Includes Mongoose, Auth flow, and protected routes.',
15
+ async function run() {
16
+ try {
17
+ let projectName = process.argv[2];
18
+
19
+ // 1. Get Project Name
20
+ if (!projectName) {
21
+ projectName = await input({
22
+ message: 'What is your project named?',
23
+ transformer: (input, { isFinal }) => {
24
+ if (isFinal) return chalk.cyan(input);
25
+ return chalk.dim(input);
26
+ }
27
+ });
48
28
  }
49
- ],
50
- theme: {
51
- prefix: chalk.hex('#F97316')('?'), // Changes the default green question mark
52
- style: {
53
- highlight: (text) => chalk.hex('#7C3AED')(text), // Changes the default cyan highlight pointer
29
+
30
+ const currentDir = process.cwd();
31
+ const targetPath = path.join(currentDir, projectName);
32
+
33
+ console.log();
34
+ console.log(`Creating a new Rex app in ${chalk.green(targetPath)}.`);
35
+ console.log();
36
+
37
+ // The Safe Empty Check
38
+ if (fs.existsSync(targetPath)) {
39
+ const files = fs.readdirSync(targetPath);
40
+ if (files.length > 0) {
41
+ console.error(chalk.red(`The directory ${chalk.green(projectName)} contains files that could conflict.`));
42
+ console.error(chalk.red('Either try using a new directory name, or remove the existing files.'));
43
+ process.exit(1);
44
+ }
45
+ } else {
46
+ fs.mkdirSync(targetPath, { recursive: true });
54
47
  }
55
- }
56
- });
57
-
58
- // Set the path dynamically based on the user's choice!
59
- const templatePath = path.join(__dirname, templateChoice);
60
-
61
- console.log();
62
-
63
- // 3. Copy files with a clean spinner
64
- const copySpinner = ora(`Initializing ${templateChoice} files...`).start();
65
- const copyRecursiveSync = (src, dest) => {
66
- const exists = fs.existsSync(src);
67
- const stats = exists && fs.statSync(src);
68
- const isDirectory = exists && stats.isDirectory();
69
-
70
- if (isDirectory) {
71
- fs.mkdirSync(dest, { recursive: true });
72
- fs.readdirSync(src).forEach((childItemName) => {
73
- if (childItemName === 'node_modules') return;
74
- copyRecursiveSync(path.join(src, childItemName), path.join(dest, childItemName));
48
+
49
+ // 2. Template Selection Prompt
50
+ const templateChoice = await select({
51
+ message: 'Which Rex template would you like to use?',
52
+ choices: [
53
+ {
54
+ name: chalk.hex('#7C3AED')('Vanilla Rex (Standard)'),
55
+ value: 'template',
56
+ description: 'The blazing fast, lightweight setup.',
57
+ },
58
+ {
59
+ name: chalk.hex('#F97316')('Mongo Rex (Standard + MongoDB + JWT Auth)'),
60
+ value: 'template-mongo',
61
+ description: 'Includes Mongoose, Auth flow, and protected routes.',
62
+ }
63
+ ],
64
+ theme: {
65
+ prefix: chalk.hex('#F97316')('?'),
66
+ style: {
67
+ highlight: (text) => chalk.hex('#7C3AED')(text),
68
+ }
69
+ }
75
70
  });
76
- } else {
77
- fs.copyFileSync(src, dest);
78
- }
79
- };
80
-
81
- try {
82
- copyRecursiveSync(templatePath, targetPath);
83
-
84
- const gitignorePath = path.join(targetPath, '_gitignore');
85
- if (fs.existsSync(gitignorePath)) {
86
- fs.renameSync(gitignorePath, path.join(targetPath, '.gitignore'));
87
- }
88
-
89
- const envPath = path.join(targetPath, '_env');
90
- if (fs.existsSync(envPath)) {
91
- fs.renameSync(envPath, path.join(targetPath, '.env'));
92
- }
93
-
94
- copySpinner.succeed(chalk.green('Initialized project files.'));
95
- } catch (error) {
96
- copySpinner.fail(chalk.red('Failed to extract template.'));
97
- console.error(error);
98
- process.exit(1);
99
- }
100
71
 
101
- // 4. Interactive Prompt
102
- console.log();
103
- const shouldInstall = await confirm({
104
- message: 'Would you like to install dependencies now?',
105
- default: true
106
- });
107
-
108
- // 5. The Real Worker (Auto-Install)
109
- console.log();
110
- if (shouldInstall) {
111
- const installSpinner = ora('Installing packages. This might take a couple of minutes...').start();
112
- try {
113
- await execPromise('npm install', { cwd: targetPath });
114
- installSpinner.succeed(chalk.green('Installed dependencies.'));
115
- } catch (error) {
116
- installSpinner.fail(chalk.yellow('Installation failed. You can run `npm install` manually later.'));
117
- }
118
- } else {
119
- console.log(chalk.dim('Skipped dependency installation.'));
120
- }
72
+ const templatePath = path.join(__dirname, templateChoice);
73
+ console.log();
74
+
75
+ // 3. Copy files
76
+ const copySpinner = ora(`Initializing ${templateChoice} files...`).start();
77
+ const copyRecursiveSync = (src, dest) => {
78
+ const exists = fs.existsSync(src);
79
+ const stats = exists && fs.statSync(src);
80
+ const isDirectory = exists && stats.isDirectory();
81
+
82
+ if (isDirectory) {
83
+ fs.mkdirSync(dest, { recursive: true });
84
+ fs.readdirSync(src).forEach((childItemName) => {
85
+ if (childItemName === 'node_modules') return;
86
+ copyRecursiveSync(path.join(src, childItemName), path.join(dest, childItemName));
87
+ });
88
+ } else {
89
+ fs.copyFileSync(src, dest);
90
+ }
91
+ };
92
+
93
+ copyRecursiveSync(templatePath, targetPath);
94
+
95
+ const gitignorePath = path.join(targetPath, '_gitignore');
96
+ if (fs.existsSync(gitignorePath)) {
97
+ fs.renameSync(gitignorePath, path.join(targetPath, '.gitignore'));
98
+ }
99
+
100
+ const envPath = path.join(targetPath, '_env');
101
+ if (fs.existsSync(envPath)) {
102
+ fs.renameSync(envPath, path.join(targetPath, '.env'));
103
+ }
104
+
105
+ copySpinner.succeed(chalk.green('Initialized project files.'));
106
+
107
+ // 4. Interactive Prompt for Dependencies
108
+ console.log();
109
+ const shouldInstall = await confirm({
110
+ message: 'Would you like to install dependencies now?',
111
+ default: true
112
+ });
121
113
 
122
- console.log();
123
- console.log(`${chalk.green('Success!')} Created ${chalk.cyan(projectName)} at ${chalk.cyan(targetPath)}`);
124
- console.log('Inside that directory, you can run several commands:');
125
- console.log();
126
- console.log(chalk.cyan(` npm run dev`));
127
- console.log(' Starts the development server.');
128
- console.log();
129
- console.log(chalk.cyan(` npm run build`));
130
- console.log(' Bundles the app into static files for production.');
131
- console.log();
132
- console.log('We suggest that you begin by typing:');
133
- console.log();
134
-
135
- if (projectName !== '.') {
136
- console.log(chalk.cyan(` cd ${projectName}`));
137
- }
138
- if (!shouldInstall) {
139
- console.log(chalk.cyan(` npm install`));
140
- }
114
+ // 5. Auto-Install
115
+ console.log();
116
+ if (shouldInstall) {
117
+ const installSpinner = ora('Installing packages. This might take a couple of minutes...').start();
118
+ try {
119
+ await execPromise('npm install', { cwd: targetPath });
120
+ installSpinner.succeed(chalk.green('Installed dependencies.'));
121
+ } catch (error) {
122
+ installSpinner.fail(chalk.yellow('Installation failed. You can run `npm install` manually later.'));
123
+ }
124
+ } else {
125
+ console.log(chalk.dim('Skipped dependency installation.'));
126
+ }
141
127
 
142
- // Add a helpful reminder for Mongo template users
143
- if (templateChoice === 'template-mongo') {
144
- console.log(chalk.yellow(`\n ⚠️ Don't forget to configure your .env file with your MONGO_URI and JWT_SECRET!`));
128
+ console.log();
129
+ console.log(`${chalk.green('Success!')} Created ${chalk.cyan(projectName)} at ${chalk.cyan(targetPath)}`);
130
+ console.log('Inside that directory, you can run several commands:');
131
+ console.log();
132
+ console.log(chalk.cyan(` npm run dev`));
133
+ console.log(' Starts the development server.');
134
+ console.log();
135
+ console.log(chalk.cyan(` npm run build`));
136
+ console.log(' Bundles the app into static files for production.');
137
+ console.log();
138
+ console.log('We suggest that you begin by typing:');
139
+ console.log();
140
+
141
+ if (projectName !== '.') {
142
+ console.log(chalk.cyan(` cd ${projectName}`));
143
+ }
144
+ if (!shouldInstall) {
145
+ console.log(chalk.cyan(` npm install`));
146
+ }
147
+
148
+ if (templateChoice === 'template-mongo') {
149
+ console.log(chalk.yellow(`\n ⚠️ Don't forget to configure your .env file with your MONGO_URI and JWT_SECRET!`));
150
+ }
151
+
152
+ console.log(chalk.cyan(` npm run dev`));
153
+ console.log();
154
+
155
+ } catch (error) {
156
+ if (error.name === 'ExitPromptError') {
157
+ console.log('\n');
158
+ console.log(chalk.yellow('Process interrupted, exiting the installation!'));
159
+ process.exit(0);
160
+ } else {
161
+ console.error(chalk.red('\nAn unexpected error occurred:'));
162
+ console.error(error);
163
+ process.exit(1);
164
+ }
165
+ }
145
166
  }
146
167
 
147
- console.log(chalk.cyan(` npm run dev`));
148
- console.log();
168
+ run();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-rex-app",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "homepage": "https://rex-docs.vercel.app/",
@@ -19,11 +19,11 @@
19
19
  "tailwindcss": "^4.2.0"
20
20
  },
21
21
  "devDependencies": {
22
- "@eslint/js": "^10.0.1",
22
+ "@eslint/js": "^9.15.0",
23
23
  "@types/react": "^19.2.14",
24
24
  "@types/react-dom": "^19.2.3",
25
25
  "@vitejs/plugin-react": "^5.1.4",
26
- "eslint": "^10.0.1",
26
+ "eslint": "^9.15.0",
27
27
  "eslint-plugin-react-hooks": "^7.0.1",
28
28
  "eslint-plugin-react-refresh": "^0.5.0",
29
29
  "globals": "^17.3.0",
@@ -24,11 +24,11 @@
24
24
  "tailwindcss": "^4.2.0"
25
25
  },
26
26
  "devDependencies": {
27
- "@eslint/js": "^10.0.1",
27
+ "@eslint/js": "^9.15.0",
28
28
  "@types/react": "^19.2.14",
29
29
  "@types/react-dom": "^19.2.3",
30
30
  "@vitejs/plugin-react": "^5.1.4",
31
- "eslint": "^10.0.1",
31
+ "eslint": "^9.15.0",
32
32
  "eslint-plugin-react-hooks": "^7.0.1",
33
33
  "eslint-plugin-react-refresh": "^0.5.0",
34
34
  "globals": "^17.3.0",