@docubook/cli 0.2.1 → 0.2.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/package.json +1 -1
- package/src/cli/program.js +1 -1
- package/src/installer/projectInstaller.js +47 -39
- package/src/utils/display.js +0 -57
- package/src/utils/templateDetect.js +10 -10
package/package.json
CHANGED
package/src/cli/program.js
CHANGED
|
@@ -63,7 +63,7 @@ export function initializeProgram(version) {
|
|
|
63
63
|
|
|
64
64
|
// Show success message
|
|
65
65
|
const pmInfo = getPackageManagerInfo(detectedPM);
|
|
66
|
-
renderDone(userInput.directoryName, detectedPM, pmInfo.devCmd);
|
|
66
|
+
renderDone(userInput.directoryName, detectedPM, pmInfo.devCmd, userInput.autoInstall !== false);
|
|
67
67
|
} catch (err) {
|
|
68
68
|
renderError(err.message || "An unexpected error occurred.");
|
|
69
69
|
log.error(err.message || "An unexpected error occurred.");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import fs from "fs";
|
|
3
|
+
import { URL } from "url";
|
|
3
4
|
import ora from "ora";
|
|
4
5
|
import chalk from "chalk";
|
|
5
6
|
import { execSync } from "child_process";
|
|
@@ -36,9 +37,9 @@ export async function createProject(options) {
|
|
|
36
37
|
// 1. Create project directory and get/download template
|
|
37
38
|
state?.setCurrentStep("Creating directories...");
|
|
38
39
|
renderScaffolding(state || {});
|
|
39
|
-
|
|
40
|
+
|
|
40
41
|
const templatePath = await getOrDownloadTemplate(template, state);
|
|
41
|
-
|
|
42
|
+
|
|
42
43
|
if (!templatePath || !fs.existsSync(templatePath)) {
|
|
43
44
|
throw new Error(`Template "${template}" could not be found or downloaded.`);
|
|
44
45
|
}
|
|
@@ -93,46 +94,31 @@ async function getOrDownloadTemplate(templateId, state) {
|
|
|
93
94
|
// Download from GitHub
|
|
94
95
|
state?.setCurrentStep("Downloading template...");
|
|
95
96
|
renderScaffolding(state || {});
|
|
96
|
-
|
|
97
|
+
|
|
97
98
|
const templateInfo = getTemplate(templateId);
|
|
98
|
-
if (!templateInfo
|
|
99
|
-
throw new Error(`Template "${templateId}"
|
|
99
|
+
if (!templateInfo) {
|
|
100
|
+
throw new Error(`Template "${templateId}" not found.`);
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
return await downloadTemplateFromGitHub(templateId, templateInfo.url);
|
|
103
104
|
}
|
|
104
105
|
|
|
105
106
|
/**
|
|
106
|
-
* Gets local template path if it exists
|
|
107
|
+
* Gets local template path if it exists (for development)
|
|
107
108
|
* @param {string} templateId - Template ID
|
|
108
109
|
* @returns {string|null} Path to local template or null
|
|
109
110
|
*/
|
|
110
111
|
function getLocalTemplatePath(templateId) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
"..",
|
|
116
|
-
"..",
|
|
117
|
-
"dist",
|
|
118
|
-
templateId
|
|
119
|
-
);
|
|
120
|
-
|
|
112
|
+
const currentDir = new URL(".", import.meta.url).pathname;
|
|
113
|
+
|
|
114
|
+
// Check dist/ folder first (if built)
|
|
115
|
+
const distPath = path.join(currentDir, "..", "..", "dist", templateId);
|
|
121
116
|
if (fs.existsSync(distPath)) {
|
|
122
117
|
return distPath;
|
|
123
118
|
}
|
|
124
119
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
"..",
|
|
128
|
-
"..",
|
|
129
|
-
"..",
|
|
130
|
-
"..",
|
|
131
|
-
"packages",
|
|
132
|
-
"template",
|
|
133
|
-
templateId
|
|
134
|
-
);
|
|
135
|
-
|
|
120
|
+
// Check packages/template/ folder (dev environment)
|
|
121
|
+
const devPath = path.join(currentDir, "..", "..", "..", "..", "packages", "template", templateId);
|
|
136
122
|
if (fs.existsSync(devPath)) {
|
|
137
123
|
return devPath;
|
|
138
124
|
}
|
|
@@ -143,28 +129,50 @@ function getLocalTemplatePath(templateId) {
|
|
|
143
129
|
/**
|
|
144
130
|
* Downloads template from GitHub repository
|
|
145
131
|
* @param {string} templateId - Template ID
|
|
146
|
-
* @param {string}
|
|
132
|
+
* @param {string} templateUrl - Template URL from templates.json
|
|
147
133
|
* @returns {Promise<string>} Path to downloaded template
|
|
148
134
|
*/
|
|
149
|
-
async function downloadTemplateFromGitHub(templateId,
|
|
135
|
+
async function downloadTemplateFromGitHub(templateId, templateUrl) {
|
|
150
136
|
const tempDir = fs.mkdtempSync(path.join("/tmp", "docubook-"));
|
|
151
|
-
|
|
137
|
+
|
|
152
138
|
try {
|
|
153
|
-
//
|
|
139
|
+
// Build archive URL from template URL
|
|
154
140
|
// https://github.com/DocuBook/docubook/tree/main/packages/template/nextjs-vercel
|
|
155
141
|
// -> https://github.com/DocuBook/docubook/archive/refs/heads/main.tar.gz
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
142
|
+
const repoMatch = templateUrl.match(/https:\/\/github\.com\/([^/]+\/[^/]+)\//);
|
|
143
|
+
if (!repoMatch) {
|
|
144
|
+
throw new Error(`Invalid template URL: ${templateUrl}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const archiveUrl = `https://github.com/${repoMatch[1]}/archive/refs/heads/main.tar.gz`;
|
|
159
148
|
const archivePath = path.join(tempDir, "repo.tar.gz");
|
|
160
|
-
execSync(`curl -L -o "${archivePath}" "${archiveUrl}"`, { stdio: "pipe" });
|
|
161
149
|
|
|
162
|
-
//
|
|
163
|
-
|
|
150
|
+
// Show progress for download
|
|
151
|
+
const downloadSpinner = ora(`Downloading template...`).start();
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
execSync(`curl -L -o "${archivePath}" "${archiveUrl}"`, { stdio: "pipe" });
|
|
155
|
+
downloadSpinner.succeed("Template downloaded");
|
|
156
|
+
} catch (err) {
|
|
157
|
+
downloadSpinner.fail("Failed to download template");
|
|
158
|
+
throw err;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Show progress for extraction
|
|
162
|
+
const extractSpinner = ora(`Extracting template...`).start();
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
execSync(`tar -xzf "${archivePath}" -C "${tempDir}"`, { stdio: "pipe" });
|
|
166
|
+
extractSpinner.succeed("Template extracted");
|
|
167
|
+
} catch (err) {
|
|
168
|
+
extractSpinner.fail("Failed to extract template");
|
|
169
|
+
throw err;
|
|
170
|
+
}
|
|
164
171
|
|
|
165
172
|
// Find template in extracted repo
|
|
166
|
-
const
|
|
167
|
-
|
|
173
|
+
const repoName = repoMatch[1].split('/')[1];
|
|
174
|
+
const extractedDir = path.join(tempDir, `${repoName}-main`, "packages", "template", templateId);
|
|
175
|
+
|
|
168
176
|
if (!fs.existsSync(extractedDir)) {
|
|
169
177
|
throw new Error(`Template "${templateId}" not found in repository.`);
|
|
170
178
|
}
|
package/src/utils/display.js
CHANGED
|
@@ -1,37 +1,5 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import boxen from "boxen";
|
|
3
|
-
import cliProgress from "cli-progress";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Displays an introduction message for the CLI.
|
|
7
|
-
*/
|
|
8
|
-
export function displayIntro() {
|
|
9
|
-
console.log(`\n${chalk.bold.green("🚀 DocuBook Installer")}\n`);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Displays a progress bar to simulate final setup.
|
|
14
|
-
* @returns {Promise<void>} Promise that resolves when simulation completes.
|
|
15
|
-
*/
|
|
16
|
-
export async function simulateInstallation() {
|
|
17
|
-
const bar = new cliProgress.SingleBar(
|
|
18
|
-
{
|
|
19
|
-
format: `Finishing setup... ${chalk.greenBright("{bar}")} | {percentage}%`,
|
|
20
|
-
barCompleteChar: "\u2588",
|
|
21
|
-
barIncompleteChar: "\u2591",
|
|
22
|
-
hideCursor: true,
|
|
23
|
-
},
|
|
24
|
-
cliProgress.Presets.shades_classic
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
bar.start(100, 0);
|
|
28
|
-
for (let i = 0; i <= 100; i++) {
|
|
29
|
-
await new Promise((r) => setTimeout(r, 20)); // Faster simulation
|
|
30
|
-
bar.update(i);
|
|
31
|
-
}
|
|
32
|
-
bar.stop();
|
|
33
|
-
console.log("\n");
|
|
34
|
-
}
|
|
35
3
|
|
|
36
4
|
/**
|
|
37
5
|
* Displays manual installation steps if automatic installation fails.
|
|
@@ -56,29 +24,4 @@ export function displayManualSteps(projectDirectory, packageManager) {
|
|
|
56
24
|
titleAlignment: "center",
|
|
57
25
|
})
|
|
58
26
|
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Displays next steps after successful installation.
|
|
63
|
-
* @param {string} directoryName - Project directory name.
|
|
64
|
-
* @param {string} packageManager - Package manager being used.
|
|
65
|
-
*/
|
|
66
|
-
export function displayNextSteps(directoryName, packageManager) {
|
|
67
|
-
const steps = `
|
|
68
|
-
${chalk.bold("Next steps:")}
|
|
69
|
-
|
|
70
|
-
1. ${chalk.blueBright(`cd ${directoryName}`)}
|
|
71
|
-
2. ${chalk.blueBright(`${packageManager} run dev`)}
|
|
72
|
-
`;
|
|
73
|
-
|
|
74
|
-
console.log(
|
|
75
|
-
boxen(steps, {
|
|
76
|
-
padding: 1,
|
|
77
|
-
margin: 1,
|
|
78
|
-
borderStyle: "round",
|
|
79
|
-
borderColor: "green",
|
|
80
|
-
title: "Success!",
|
|
81
|
-
titleAlignment: "center",
|
|
82
|
-
})
|
|
83
|
-
);
|
|
84
27
|
}
|
|
@@ -15,30 +15,30 @@ export function getAvailableTemplates() {
|
|
|
15
15
|
const data = JSON.parse(content);
|
|
16
16
|
return data.templates || [];
|
|
17
17
|
}
|
|
18
|
-
} catch
|
|
18
|
+
} catch {
|
|
19
19
|
// Fallback to directory scanning
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
// Fallback: scan template directories
|
|
23
23
|
const distPath = path.join(__dirname, '..', '..', 'dist');
|
|
24
|
-
const templateDir = fs.existsSync(distPath)
|
|
25
|
-
? distPath
|
|
24
|
+
const templateDir = fs.existsSync(distPath)
|
|
25
|
+
? distPath
|
|
26
26
|
: path.join(__dirname, '..', '..', '..', '..', 'packages', 'template');
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
if (!fs.existsSync(templateDir)) {
|
|
29
29
|
return [];
|
|
30
30
|
}
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
const entries = fs.readdirSync(templateDir, { withFileTypes: true });
|
|
33
33
|
const templates = [];
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
for (const entry of entries) {
|
|
36
36
|
if (!entry.isDirectory()) continue;
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
const configPath = path.join(templateDir, entry.name, 'template.config.json');
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
if (!fs.existsSync(configPath)) continue;
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
try {
|
|
43
43
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
44
44
|
templates.push({
|
|
@@ -51,7 +51,7 @@ export function getAvailableTemplates() {
|
|
|
51
51
|
console.error(`Failed to read template config for ${entry.name}`);
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
return templates;
|
|
56
56
|
}
|
|
57
57
|
|