Skip to content

Commit 398c603

Browse files
authored
Implement setup_plugin command (#18)
1 parent 07567cb commit 398c603

File tree

3 files changed

+149
-1
lines changed

3 files changed

+149
-1
lines changed

commands/setup_plugin.js

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
import fetch from 'node-fetch';
4+
import AdmZip from 'adm-zip';
5+
import ProgressBar from 'progress';
6+
import ora from 'ora';
7+
import chalk from 'chalk';
8+
9+
// TODO: Extract into a util fn as it's reused for theme setup
10+
async function downloadFile(url, outputPath) {
11+
const response = await fetch(url);
12+
13+
if (!response.ok) {
14+
throw new Error(`Failed to download: ${response.statusText}`);
15+
}
16+
17+
const fileStream = fs.createWriteStream(outputPath);
18+
const contentLength = response.headers.get('content-length');
19+
let totalSize = parseInt(contentLength, 10);
20+
21+
if (isNaN(totalSize)) {
22+
console.warn(
23+
'Warning: Size of the file is unknown. Progress bar will not be shown.'
24+
);
25+
} else {
26+
const progressBar = new ProgressBar('Downloading [:bar] :percent :etas', {
27+
complete: '=',
28+
incomplete: ' ',
29+
width: 40,
30+
total: totalSize,
31+
});
32+
33+
response.body.on('data', (chunk) => {
34+
progressBar.tick(chunk.length);
35+
});
36+
}
37+
38+
await new Promise((resolve, reject) => {
39+
response.body.pipe(fileStream);
40+
response.body.on('error', reject);
41+
fileStream.on('finish', resolve);
42+
});
43+
}
44+
// ... [other imports and functions]
45+
46+
async function setup_plugin() {
47+
// TODO: Do this in setup_theme as well
48+
const zipName = 'trbs-framework.zip';
49+
50+
try {
51+
// Ensure the current working directory ends with plugins
52+
const pluginsEndPath = path.join('wp-content', 'plugins');
53+
const cwd = process.cwd();
54+
// TODO: Do this is setup_theme as well
55+
if (!cwd.endsWith(pluginsEndPath)) {
56+
console.log(
57+
chalk.red(
58+
'\nThis command needs to be run inside the wp-content/plugins folder.'
59+
)
60+
);
61+
return false;
62+
}
63+
64+
// Check if plugin directory already exists
65+
const newPluginPath = path.join('.', 'trbs-framework');
66+
if (fs.existsSync(newPluginPath)) {
67+
console.log(chalk.red('\nPlugin already exists.'));
68+
return false;
69+
}
70+
71+
// Fetch the latest release URL from GitHub API
72+
const apiUrl =
73+
'https://api.github.com/repos/webredone/trbs-framework-plugin/releases/latest';
74+
const apiResponse = await fetch(apiUrl);
75+
const apiData = await apiResponse.json();
76+
const zipUrl = apiData.zipball_url;
77+
78+
// Download the zip file
79+
await downloadFile(zipUrl, zipName);
80+
81+
// Unzip the file to a temporary directory
82+
const spinner = ora('Unzipping the file...').start();
83+
const zip = new AdmZip(zipName);
84+
const tempExtractPath = path.join('.', 'temp-extract');
85+
fs.mkdirSync(tempExtractPath, { recursive: true });
86+
zip.extractAllTo(tempExtractPath, true);
87+
spinner.succeed('Unzipping completed');
88+
89+
// Determine the top-level directory name and move its contents
90+
const extractedFolders = fs.readdirSync(tempExtractPath);
91+
if (extractedFolders.length !== 1) {
92+
console.error(chalk.red('Unexpected structure in the zip file.'));
93+
return false;
94+
}
95+
96+
const topLevelDir = path.join(tempExtractPath, extractedFolders[0]);
97+
fs.renameSync(topLevelDir, newPluginPath);
98+
99+
// Clean up temporary directory
100+
fs.rmSync(tempExtractPath, { recursive: true, force: true });
101+
102+
// Delete the .git directory from the new plugin folder
103+
const gitDirPath = path.join(newPluginPath, '.git');
104+
if (fs.existsSync(gitDirPath)) {
105+
fs.rmSync(gitDirPath, { recursive: true, force: true });
106+
}
107+
108+
// Delete the zip file
109+
fs.unlinkSync(zipName);
110+
111+
console.log(
112+
chalk.green(
113+
'Plugin has been set up. Please activate it from the WordPress admin panel.'
114+
)
115+
);
116+
117+
// Read package.json and extract Node version
118+
const packageJsonPath = path.join(newPluginPath, 'package.json');
119+
if (fs.existsSync(packageJsonPath)) {
120+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
121+
const nodeVersion = packageJson.engines.node;
122+
console.log(
123+
`Please ensure you have Node version ${nodeVersion} installed.`
124+
);
125+
console.log(
126+
'Then, run "npm i" and "composer i" from the plugin root directory.'
127+
);
128+
} else {
129+
console.log(
130+
chalk.yellow('Note: package.json not found in the plugin directory.')
131+
);
132+
}
133+
} catch (error) {
134+
console.error(chalk.red(`Error setting up plugin: ${error.message}`));
135+
return false;
136+
}
137+
}
138+
139+
export default setup_plugin;

index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { program } from 'commander';
44
import list_created_blocks from './commands/list_created_blocks.js';
55

66
import setup_theme from './commands/setup_theme.js';
7+
import setup_plugin from './commands/setup_plugin.js';
8+
79
import create_new_block from './commands/create_new_block.js';
810
import remove_existing_block from './commands/remove_existing_block.js';
911
import { help } from './CONFIG.js';
@@ -19,6 +21,13 @@ program
1921
)
2022
.action(setup_theme);
2123

24+
program
25+
.command('plugin')
26+
.description(
27+
'Download and set up a new plugin from the latest trbs=framework plugin release'
28+
)
29+
.action(setup_plugin);
30+
2231
program
2332
.command('add <block-name-kebab-case>')
2433
.description(help.add)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@webredone/trb-cli",
3-
"version": "3.0.8",
3+
"version": "3.1.0",
44
"description": "TRB-CLI is a handy Node.js CLI that automates the process of managing blocks in a Theme Redone WordPress theme",
55
"main": "index.js",
66
"type": "module",

0 commit comments

Comments
 (0)