@docubook/create 1.14.0 → 1.14.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docubook/create",
3
- "version": "1.14.0",
3
+ "version": "1.14.1",
4
4
  "description": "CLI to create DocuBook projects",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -23,8 +23,8 @@
23
23
  "chalk": "^5.3.0",
24
24
  "cli-progress": "^3.12.0",
25
25
  "commander": "^12.1.0",
26
- "enquirer": "^2.4.1",
27
26
  "figlet": "^1.8.0",
28
- "ora": "^8.1.0"
27
+ "ora": "^8.1.0",
28
+ "prompts": "^2.4.2"
29
29
  }
30
30
  }
@@ -1,8 +1,8 @@
1
1
  import { program } from "commander";
2
- import chalk from "chalk";
3
- import { displayAsciiArt } from "../utils/display.js";
2
+ import { displayIntro } from "../utils/display.js";
4
3
  import { collectUserInput } from "./promptHandler.js";
5
4
  import { createProject } from "../installer/projectInstaller.js";
5
+ import log from "../utils/logger.js";
6
6
 
7
7
  /**
8
8
  * Initializes the CLI program
@@ -11,22 +11,21 @@ import { createProject } from "../installer/projectInstaller.js";
11
11
  export function initializeProgram(version) {
12
12
  program
13
13
  .version(version)
14
- .description("CLI to create a new Docubook project")
15
- .action(async () => {
14
+ .description("CLI to create a new DocuBook project")
15
+ // 1. Define optional argument here (handled below with .argument)
16
+ .argument("[directory]", "The name of the project directory")
17
+ .action(async (directory) => { // 2. Capture argument in action function
16
18
  try {
17
- await displayAsciiArt();
18
- console.log(chalk.white("DocuBook Installer\n"));
19
+ displayIntro();
20
+ // 3. Pass the argument to the prompt function
21
+ const options = await collectUserInput(directory);
19
22
 
20
- // Collect user input
21
- const options = await collectUserInput();
22
-
23
- // Create project with collected options
24
23
  await createProject(options);
25
24
  } catch (err) {
26
- // Error handling is done in the respective modules
25
+ log.error(err.message || "An unexpected error occurred.");
27
26
  process.exit(1);
28
27
  }
29
28
  });
30
29
 
31
30
  return program;
32
- }
31
+ }
@@ -1,73 +1,67 @@
1
- import enquirer from "enquirer";
1
+ import prompts from "prompts";
2
2
  import { detectDefaultPackageManager, getPackageManagerVersion } from "../utils/packageManager.js";
3
3
  import log from "../utils/logger.js";
4
-
5
- const { prompt } = enquirer;
6
-
7
- /**
8
- * Detects if the command was run with yarn or yarn dlx
9
- * @returns {boolean}
10
- */
11
- function isYarnCommand() {
12
- const userAgent = process.env.npm_config_user_agent || '';
13
- return userAgent.includes('yarn') || process.argv.some(arg => arg.includes('yarn'));
14
- }
4
+ import chalk from "chalk";
15
5
 
16
6
  /**
17
7
  * Collects user input for project creation
8
+ * @param {string} [cliProvidedDir] - The directory name provided via CLI argument.
18
9
  * @returns {Promise<Object>} User answers
19
10
  */
20
- export async function collectUserInput() {
21
- // Skip installation prompt if running with yarn/yarn dlx
22
- const isYarn = isYarnCommand();
11
+ export async function collectUserInput(cliProvidedDir) {
23
12
  const defaultPackageManager = detectDefaultPackageManager();
13
+ let answers = {
14
+ directoryName: cliProvidedDir
15
+ };
24
16
 
25
- // Get initial answers (directory name and package manager)
26
- const { directoryName, packageManager } = await prompt([
17
+ const questions = [
27
18
  {
28
- type: "input",
19
+ // Skip this question if directory name is provided
20
+ type: cliProvidedDir ? null : "text",
29
21
  name: "directoryName",
30
- message: "📁 Project name",
22
+ message: "What is your project named?",
31
23
  initial: "docubook",
24
+ validate: (name) => name.trim().length > 0 ? true : "Project name cannot be empty.",
32
25
  },
33
26
  {
34
27
  type: "select",
35
28
  name: "packageManager",
36
- message: "📦 Package manager",
37
- choices: ["npm", "pnpm", "yarn", "bun"],
38
- initial: defaultPackageManager,
39
- }
40
- ]);
41
-
42
- // Only ask about installation if not using yarn
43
- let installNow = false;
44
- if (packageManager !== 'yarn') {
45
- const { shouldInstall } = await prompt({
46
- type: "confirm",
47
- name: "shouldInstall",
48
- message: "Install dependencies now?",
29
+ message: "Select your package manager:",
30
+ choices: [
31
+ { title: "npm", value: "npm" },
32
+ { title: "pnpm", value: "pnpm" },
33
+ { title: "yarn", value: "yarn" },
34
+ { title: "bun", value: "bun" },
35
+ ],
36
+ initial: ["npm", "pnpm", "yarn", "bun"].indexOf(defaultPackageManager),
37
+ },
38
+ {
39
+ type: (prev) => (prev !== 'yarn' ? "confirm" : null),
40
+ name: "installNow",
41
+ message: "Would you like to install dependencies now?",
49
42
  initial: true,
50
- });
51
- installNow = shouldInstall;
52
- }
43
+ },
44
+ ];
53
45
 
54
- // Prepare the answers object
55
- const answers = {
56
- directoryName,
57
- packageManager,
58
- installNow
59
- };
46
+ const promptAnswers = await prompts(questions, {
47
+ onCancel: () => {
48
+ log.error("Scaffolding cancelled.");
49
+ process.exit(0);
50
+ },
51
+ });
60
52
 
61
- // Validate package manager is installed
62
- const version = getPackageManagerVersion(packageManager);
53
+ // Combine answers from CLI and from prompt
54
+ answers = { ...answers, ...promptAnswers };
63
55
 
56
+ // Validate the selected package manager
57
+ const version = getPackageManagerVersion(answers.packageManager);
64
58
  if (!version) {
65
- log.error(`${packageManager} is not installed on your system.`);
66
- process.exit(1);
59
+ throw new Error(`${chalk.bold(answers.packageManager)} is not installed on your system. Please install it to continue.`);
67
60
  }
68
61
 
69
62
  return {
70
63
  ...answers,
71
- version
64
+ directoryName: answers.directoryName.trim(),
65
+ version,
72
66
  };
73
- }
67
+ }
@@ -6,7 +6,7 @@ import { cn } from "@/lib/utils";
6
6
  import AnimatedShinyText from "@/components/ui/animated-shiny-text";
7
7
  import { getMetadata } from "@/app/layout";
8
8
  import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
9
- // v1.14.0
9
+
10
10
  export const metadata = getMetadata({
11
11
  title: "Home",
12
12
  });
@@ -25,7 +25,7 @@ export default function Home() {
25
25
  )}
26
26
  >
27
27
  <AnimatedShinyText className="inline-flex items-center justify-center px-4 py-1 transition ease-out hover:text-neutral-100 hover:duration-300 hover:dark:text-neutral-200">
28
- <span>🚀 New Version - Release v1.14.0</span>
28
+ <span>🚀 New Version - Release v1.14.1</span>
29
29
  <ArrowRightIcon className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" />
30
30
  </AnimatedShinyText>
31
31
  </div>
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docubook",
3
- "version": "1.14.0",
3
+ "version": "1.14.1",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "dev": "next dev",
@@ -9,117 +9,102 @@ import { configurePackageManager } from "../utils/packageManager.js";
9
9
  import { displayManualSteps, simulateInstallation, displayNextSteps } from "../utils/display.js";
10
10
 
11
11
  /**
12
- * Creates a new DocuBook project
13
- * @param {Object} options - Installation options
14
- * @param {string} options.directoryName - Project directory name
15
- * @param {string} options.packageManager - Package manager to use
16
- * @param {string} options.version - Package manager version
17
- * @param {boolean} options.installNow - Whether to install dependencies immediately
18
- * @returns {Promise<void>}
12
+ * Creates a new DocuBook project.
13
+ * @param {Object} options - Installation options.
19
14
  */
20
15
  export async function createProject({ directoryName, packageManager, version, installNow }) {
21
16
  const projectPath = path.resolve(process.cwd(), directoryName);
22
- const spinner = ora("Creating your DocuBook project...").start();
17
+
18
+ if (fs.existsSync(projectPath)) {
19
+ throw new Error(`Directory "${directoryName}" already exists.`);
20
+ }
21
+
22
+ log.info(`Creating a new DocuBook project in ${chalk.cyan(projectPath)}...`);
23
+
24
+ const spinner = ora("Setting up project files...").start();
23
25
 
24
26
  try {
25
- // Get the template directory path
27
+ // 1. Create project directory and copy template files
26
28
  const __filename = fileURLToPath(import.meta.url);
27
29
  const __dirname = path.dirname(__filename);
28
30
  const templatePath = path.join(__dirname, "../dist");
29
-
30
- // Create project directory if it doesn't exist
31
- if (!fs.existsSync(projectPath)) {
32
- fs.mkdirSync(projectPath, { recursive: true });
33
- }
34
-
35
- // Copy template files to project directory
36
31
  copyDirectoryRecursive(templatePath, projectPath);
32
+ spinner.succeed("Project files created.");
37
33
 
38
- // Configure package manager specific settings
34
+ // 2. Configure package manager specific settings
35
+ spinner.start("Configuring package manager...");
39
36
  configurePackageManager(packageManager, projectPath);
37
+ spinner.succeed("Package manager configured.");
40
38
 
41
- // Update package.json with package manager info
39
+ // 3. Update package.json
40
+ spinner.start("Updating package.json...");
42
41
  const pkgPath = path.join(projectPath, "package.json");
43
- let pkgVersion = "";
44
42
  if (fs.existsSync(pkgPath)) {
45
43
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
44
+ pkg.name = directoryName; // Set project name
46
45
  pkg.packageManager = `${packageManager}@${version}`;
47
- pkgVersion = pkg.version || "";
48
46
  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
49
47
  }
48
+ spinner.succeed("package.json updated.");
50
49
 
51
- spinner.succeed();
52
- log.success(`DocuBook v${pkgVersion} using "${packageManager}"`);
50
+ log.success(`DocuBook project ready to go!`);
53
51
 
54
- if (!installNow) {
52
+ if (installNow) {
53
+ await installDependencies(directoryName, packageManager, projectPath);
54
+ await simulateInstallation();
55
+ displayNextSteps(directoryName, packageManager);
56
+ } else {
55
57
  displayManualSteps(directoryName, packageManager);
56
- return;
57
58
  }
58
-
59
- await installDependencies(directoryName, packageManager, projectPath);
60
59
  } catch (err) {
61
60
  spinner.fail("Failed to create project.");
62
- log.error(err.message);
61
+ // Cleanup created directory on failure
62
+ if (fs.existsSync(projectPath)) {
63
+ fs.rmSync(projectPath, { recursive: true, force: true });
64
+ }
63
65
  throw err;
64
66
  }
65
67
  }
66
68
 
67
69
  /**
68
- * Recursively copies a directory
69
- * @param {string} source - Source directory path
70
- * @param {string} destination - Destination directory path
70
+ * Recursively copies a directory.
71
+ * @param {string} source - Source directory path.
72
+ * @param {string} destination - Destination directory path.
71
73
  */
72
74
  function copyDirectoryRecursive(source, destination) {
73
- // Create destination directory if it doesn't exist
74
75
  if (!fs.existsSync(destination)) {
75
76
  fs.mkdirSync(destination, { recursive: true });
76
77
  }
77
78
 
78
- // Read source directory contents
79
79
  const entries = fs.readdirSync(source, { withFileTypes: true });
80
-
81
- // Process each entry
82
80
  for (const entry of entries) {
83
81
  const srcPath = path.join(source, entry.name);
84
82
  const destPath = path.join(destination, entry.name);
85
83
 
86
- // If entry is a directory, recursively copy it
87
84
  if (entry.isDirectory()) {
88
85
  copyDirectoryRecursive(srcPath, destPath);
89
86
  } else {
90
- // Otherwise, copy the file
91
87
  fs.copyFileSync(srcPath, destPath);
92
88
  }
93
89
  }
94
90
  }
95
91
 
96
92
  /**
97
- * Installs project dependencies
98
- * @param {string} directoryName - Project directory name
99
- * @param {string} packageManager - Package manager to use
100
- * @param {string} projectPath - Path to the project directory
101
- * @returns {Promise<void>}
93
+ * Installs project dependencies.
94
+ * @param {string} directoryName - Project directory name.
95
+ * @param {string} packageManager - Package manager to use.
96
+ * @param {string} projectPath - Path to the project directory.
102
97
  */
103
98
  async function installDependencies(directoryName, packageManager, projectPath) {
104
99
  log.info("Installing dependencies...");
105
- console.log(chalk.yellow("This is a joke for you:"));
106
- console.log(
107
- chalk.white(
108
- "You don't need to worry about this process not running, you just need the latest device for a faster installation process."
109
- )
110
- );
111
-
112
- const installSpinner = ora(`Using ${packageManager}...`).start();
100
+ const installSpinner = ora(`Running ${chalk.cyan(`${packageManager} install`)}...`).start();
113
101
 
114
102
  try {
115
103
  execSync(`${packageManager} install`, { cwd: projectPath, stdio: "ignore" });
116
- installSpinner.succeed("Dependencies installed.");
117
-
118
- await simulateInstallation();
119
- displayNextSteps(directoryName, packageManager);
104
+ installSpinner.succeed("Dependencies installed successfully.");
120
105
  } catch (error) {
121
106
  installSpinner.fail("Failed to install dependencies.");
122
107
  displayManualSteps(directoryName, packageManager);
123
- throw new Error("Failed to install dependencies");
108
+ throw new Error("Dependency installation failed.");
124
109
  }
125
- }
110
+ }
@@ -1,83 +1,84 @@
1
1
  import chalk from "chalk";
2
- import figlet from "figlet";
3
2
  import boxen from "boxen";
4
3
  import cliProgress from "cli-progress";
5
4
 
6
5
  /**
7
- * Displays ASCII art "DocuBook" when CLI is launched
8
- * @returns {Promise} Promise that resolves when ASCII art is displayed
6
+ * Displays an introduction message for the CLI.
9
7
  */
10
- export function displayAsciiArt() {
11
- return new Promise((resolve, reject) => {
12
- figlet.text("DocuBook", { horizontalLayout: "full" }, (err, data) => {
13
- if (err) return reject(err);
14
- console.log(chalk.green(data));
15
- resolve();
16
- });
17
- });
8
+ export function displayIntro() {
9
+ console.log(`\n${chalk.bold.green("🚀 DocuBook Installer")}\n`);
18
10
  }
19
11
 
20
12
  /**
21
- * Displays a progress bar to simulate final setup
22
- * @returns {Promise} Promise that resolves when simulation completes
13
+ * Displays a progress bar to simulate final setup.
14
+ * @returns {Promise<void>} Promise that resolves when simulation completes.
23
15
  */
24
16
  export async function simulateInstallation() {
25
17
  const bar = new cliProgress.SingleBar(
26
18
  {
27
- format: 'Finishing Setup |' + chalk.green('{bar}') + '| {percentage}% || {value}/{total}',
28
- barCompleteChar: '\u2588',
29
- barIncompleteChar: '\u2591',
19
+ format: `Finishing setup... ${chalk.cyan("{bar}")} | {percentage}%`,
20
+ barCompleteChar: "\u2588",
21
+ barIncompleteChar: "\u2591",
22
+ hideCursor: true,
30
23
  },
31
24
  cliProgress.Presets.shades_classic
32
25
  );
33
26
 
34
27
  bar.start(100, 0);
35
28
  for (let i = 0; i <= 100; i++) {
36
- await new Promise((r) => setTimeout(r, 50));
29
+ await new Promise((r) => setTimeout(r, 20)); // Faster simulation
37
30
  bar.update(i);
38
31
  }
39
32
  bar.stop();
33
+ console.log("\n");
40
34
  }
41
35
 
42
36
  /**
43
- * Displays manual installation steps if automatic installation fails
44
- * @param {string} projectDirectory - Project directory name
45
- * @param {string} packageManager - Package manager being used
37
+ * Displays manual installation steps if automatic installation fails.
38
+ * @param {string} projectDirectory - Project directory name.
39
+ * @param {string} packageManager - Package manager being used.
46
40
  */
47
41
  export function displayManualSteps(projectDirectory, packageManager) {
48
- const manualInstructions = `
49
- Please follow these steps manually to finish setting up your project:
42
+ const steps = `
43
+ ${chalk.yellow("Automatic installation failed.")} Please finish setup manually:
50
44
 
51
45
  1. ${chalk.cyan(`cd ${projectDirectory}`)}
52
46
  2. ${chalk.cyan(`${packageManager} install`)}
53
47
  3. ${chalk.cyan(`${packageManager} run dev`)}
54
48
  `;
55
-
56
49
  console.log(
57
- boxen(manualInstructions, {
58
- padding: 0.5,
50
+ boxen(steps, {
51
+ padding: 1,
52
+ margin: 1,
59
53
  borderStyle: "round",
60
- borderColor: "cyan",
54
+ borderColor: "yellow",
55
+ title: "Manual Setup Required",
56
+ titleAlignment: "center",
61
57
  })
62
58
  );
63
59
  }
64
60
 
65
61
  /**
66
- * Displays next steps after successful installation
67
- * @param {string} directoryName - Project directory name
68
- * @param {string} packageManager - Package manager being used
62
+ * Displays next steps after successful installation.
63
+ * @param {string} directoryName - Project directory name.
64
+ * @param {string} packageManager - Package manager being used.
69
65
  */
70
66
  export function displayNextSteps(directoryName, packageManager) {
67
+ const steps = `
68
+ ${chalk.bold("Next steps:")}
69
+
70
+ 1. ${chalk.cyan(`cd ${directoryName}`)}
71
+ 2. ${chalk.cyan(`${packageManager} run dev`)}
72
+ `;
73
+
71
74
  console.log(
72
- boxen(
73
- `Next Steps:\n\n` +
74
- `1. ${chalk.cyan(`cd ${directoryName}`)}\n` +
75
- `2. ${chalk.cyan(`${packageManager} run dev`)}`,
76
- {
77
- padding: 0.5,
78
- borderStyle: "round",
79
- borderColor: "cyan",
80
- }
81
- )
75
+ boxen(steps, {
76
+ padding: 1,
77
+ margin: 1,
78
+ borderStyle: "round",
79
+ borderColor: "green",
80
+ title: "Success!",
81
+ titleAlignment: "center",
82
+ })
82
83
  );
83
- }
84
+ }
@@ -1,11 +1,10 @@
1
1
  import chalk from "chalk";
2
2
 
3
- // Logging helper with styles
4
3
  const log = {
5
- info: (msg) => console.log(chalk.cyan("! " + msg)),
6
- success: (msg) => console.log(chalk.green("✔ " + msg)),
7
- warn: (msg) => console.log(chalk.yellow("⚠️ " + msg)),
8
- error: (msg) => console.log(chalk.red("x " + msg)),
4
+ info: (msg) => console.log(`${chalk.blue("")} ${msg}`),
5
+ success: (msg) => console.log(`${chalk.green("✔")} ${msg}`),
6
+ warn: (msg) => console.log(`${chalk.yellow("")} ${msg}`),
7
+ error: (msg) => console.log(`\n${chalk.red("")} ${chalk.bold(msg)}\n`),
9
8
  };
10
9
 
11
- export default log;
10
+ export default log;
@@ -51,4 +51,4 @@ export function configurePackageManager(packageManager, projectPath) {
51
51
  const yarnrcPath = path.join(projectPath, ".yarnrc.yml");
52
52
  fs.writeFileSync(yarnrcPath, "nodeLinker: node-modules\n");
53
53
  }
54
- }
54
+ }